From 027dfac694fc27ef0273afb810d9b1f9da57d6e1 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 1 Jun 2016 16:34:37 +1000 Subject: powerpc: Various typo fixes Signed-off-by: Andrea Gelmini Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/512x/clock-commonclk.c | 2 +- arch/powerpc/platforms/cell/iommu.c | 4 ++-- arch/powerpc/platforms/cell/spider-pic.c | 2 +- arch/powerpc/platforms/cell/spu_base.c | 4 ++-- arch/powerpc/platforms/cell/spufs/file.c | 2 +- arch/powerpc/platforms/cell/spufs/run.c | 2 +- arch/powerpc/platforms/cell/spufs/sched.c | 2 +- arch/powerpc/platforms/powermac/low_i2c.c | 2 +- arch/powerpc/platforms/powernv/pci-ioda.c | 2 +- arch/powerpc/platforms/pseries/eeh_pseries.c | 2 +- arch/powerpc/platforms/pseries/io_event_irq.c | 2 +- arch/powerpc/platforms/pseries/setup.c | 2 +- 12 files changed, 14 insertions(+), 14 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c index 6081fbd75330..add5a5374fa0 100644 --- a/arch/powerpc/platforms/512x/clock-commonclk.c +++ b/arch/powerpc/platforms/512x/clock-commonclk.c @@ -719,7 +719,7 @@ static void mpc512x_clk_setup_clock_tree(struct device_node *np, int busfreq) * most one of a mux, div, and gate each into one 'struct clk' * item * - PSC/MSCAN/SPDIF clock generation OTOH already is very - * specific and cannot get mapped to componsites (at least not + * specific and cannot get mapped to composites (at least not * a single one, maybe two of them, but then some of these * intermediate clock signals get referenced elsewhere (e.g. * in the clock frequency measurement, CFM) and thus need diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index 14a582b21274..9027d7c48507 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c @@ -178,7 +178,7 @@ static int tce_build_cell(struct iommu_table *tbl, long index, long npages, * default for now.*/ #ifdef CELL_IOMMU_STRICT_PROTECTION /* to avoid referencing a global, we use a trick here to setup the - * protection bit. "prot" is setup to be 3 fields of 4 bits apprended + * protection bit. "prot" is setup to be 3 fields of 4 bits appended * together for each of the 3 supported direction values. It is then * shifted left so that the fields matching the desired direction * lands on the appropriate bits, and other bits are masked out. @@ -338,7 +338,7 @@ static unsigned long *cell_iommu_alloc_ptab(struct cbe_iommu *iommu, start_seg = base >> IO_SEGMENT_SHIFT; segments = size >> IO_SEGMENT_SHIFT; pages_per_segment = 1ull << IO_PAGENO_BITS(page_shift); - /* PTEs for each segment must start on a 4K bounday */ + /* PTEs for each segment must start on a 4K boundary */ pages_per_segment = max(pages_per_segment, (1 << 12) / sizeof(unsigned long)); diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c index 54ee5743cb72..d06dcac66fcb 100644 --- a/arch/powerpc/platforms/cell/spider-pic.c +++ b/arch/powerpc/platforms/cell/spider-pic.c @@ -217,7 +217,7 @@ static void spider_irq_cascade(struct irq_desc *desc) chip->irq_eoi(&desc->irq_data); } -/* For hooking up the cascace we have a problem. Our device-tree is +/* For hooking up the cascade we have a problem. Our device-tree is * crap and we don't know on which BE iic interrupt we are hooked on at * least not the "standard" way. We can reconstitute it based on two * informations though: which BE node we are connected to and whether diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 3cbe38fad609..bb4a8e07c229 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -69,7 +69,7 @@ static DEFINE_SPINLOCK(spu_lock); * spu_full_list_lock and spu_full_list_mutex held, while iterating * through it requires either of these locks. * - * In addition spu_full_list_lock protects all assignmens to + * In addition spu_full_list_lock protects all assignments to * spu->mm. */ static LIST_HEAD(spu_full_list); @@ -253,7 +253,7 @@ static inline int __slb_present(struct copro_slb *slbs, int nr_slbs, * Setup the SPU kernel SLBs, in preparation for a context save/restore. We * need to map both the context save area, and the save/restore code. * - * Because the lscsa and code may cross segment boundaires, we check to see + * Because the lscsa and code may cross segment boundaries, we check to see * if mappings are required for the start and end of each range. We currently * assume that the mappings are smaller that one segment - if not, something * is seriously wrong. diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 2936a0044c04..06254467e4dd 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c @@ -866,7 +866,7 @@ void spufs_wbox_callback(struct spu *spu) * - end of the mapped area * * If the file is opened without O_NONBLOCK, we wait here until - * space is availabyl, but return when we have been able to + * space is available, but return when we have been able to * write something. */ static ssize_t spufs_wbox_write(struct file *file, const char __user *buf, diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index 9f79004e6d6f..cfacbee24d7b 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c @@ -435,7 +435,7 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event) /* Note: we don't need to force_sig SIGTRAP on single-step * since we have TIF_SINGLESTEP set, thus the kernel will do - * it upon return from the syscall anyawy + * it upon return from the syscall anyway. */ if (unlikely(status & SPU_STATUS_SINGLE_STEP)) ret = -ERESTARTSYS; diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 998f632e7cce..460f5f31d5cb 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c @@ -622,7 +622,7 @@ static struct spu *spu_get_idle(struct spu_context *ctx) /** * find_victim - find a lower priority context to preempt - * @ctx: canidate context for running + * @ctx: candidate context for running * * Returns the freed physical spu to run the new context on. */ diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c index 7553b6a77c64..6d6f277477aa 100644 --- a/arch/powerpc/platforms/powermac/low_i2c.c +++ b/arch/powerpc/platforms/powermac/low_i2c.c @@ -15,7 +15,7 @@ * This file thus provides a simple low level unified i2c interface for * powermac that covers the various types of i2c busses used in Apple machines. * For now, keywest, PMU and SMU, though we could add Cuda, or other bit - * banging busses found on older chipstes in earlier machines if we ever need + * banging busses found on older chipsets in earlier machines if we ever need * one of them. * * The drivers in this file are synchronous/blocking. In addition, the diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 3a5ea8236db8..1fc53e015d29 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -197,7 +197,7 @@ static int pnv_ioda2_init_m64(struct pnv_phb *phb) /* * Strip off the segment used by the reserved PE, which is - * expected to be 0 or last one of PE capabicity. + * expected to be 0 or last one of PE capability. */ r = &phb->hose->mem_resources[1]; if (phb->ioda.reserved_pe_idx == 0) diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c index 3998e0f9a03b..1c428f06b14c 100644 --- a/arch/powerpc/platforms/pseries/eeh_pseries.c +++ b/arch/powerpc/platforms/pseries/eeh_pseries.c @@ -2,7 +2,7 @@ * The file intends to implement the platform dependent EEH operations on pseries. * Actually, the pseries platform is built based on RTAS heavily. That means the * pseries platform dependent EEH operations will be built on RTAS calls. The functions - * are devired from arch/powerpc/platforms/pseries/eeh.c and necessary cleanup has + * are derived from arch/powerpc/platforms/pseries/eeh.c and necessary cleanup has * been done. * * Copyright Benjamin Herrenschmidt & Gavin Shan, IBM Corporation 2011. diff --git a/arch/powerpc/platforms/pseries/io_event_irq.c b/arch/powerpc/platforms/pseries/io_event_irq.c index 0240c4ff878a..f053bda64ee7 100644 --- a/arch/powerpc/platforms/pseries/io_event_irq.c +++ b/arch/powerpc/platforms/pseries/io_event_irq.c @@ -113,7 +113,7 @@ static struct pseries_io_event * ioei_find_event(struct rtas_error_log *elog) * - The owner of an event is determined by combinations of scope, * event type, and sub-type. There is no easy way to pre-sort clients * by scope or event type alone. For example, Torrent ISR route change - * event is reported with scope 0x00 (Not Applicatable) rather than + * event is reported with scope 0x00 (Not Applicable) rather than * 0x3B (Torrent-hub). It is better to let the clients to identify * who owns the event. */ diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 9883bc7ea007..9a79c2753a22 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -367,7 +367,7 @@ static void pseries_lpar_idle(void) { /* * Default handler to go into low thread priority and possibly - * low power mode by cedeing processor to hypervisor + * low power mode by ceding processor to hypervisor */ /* Indicate to hypervisor that we are idle. */ -- cgit v1.2.3 From e7da5dac4e9067a526136db2f23cc8696a5d4649 Mon Sep 17 00:00:00 2001 From: Rashmica Gupta Date: Mon, 30 May 2016 16:18:11 +1000 Subject: powerpc/pseries: Drop support for MPIC in pseries MPIC was only used by Power3 which is now unsupported, so drop support for MPIC. XICS is now the only supported interrupt controller for pSeries so make the XICS functions generic. Signed-off-by: Rashmica Gupta Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/pseries/setup.c | 77 +++------------------------------- 1 file changed, 5 insertions(+), 72 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 9a79c2753a22..39f21fb3c609 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -57,7 +57,6 @@ #include #include #include -#include #include #include #include @@ -77,8 +76,6 @@ EXPORT_SYMBOL(CMO_PageSize); int fwnmi_active; /* TRUE if an FWNMI handler is present */ -static struct device_node *pSeries_mpic_node; - static void pSeries_show_cpuinfo(struct seq_file *m) { struct device_node *root; @@ -172,48 +169,7 @@ static void __init pseries_setup_i8259_cascade(void) irq_set_chained_handler(cascade, pseries_8259_cascade); } -static void __init pseries_mpic_init_IRQ(void) -{ - struct device_node *np; - const unsigned int *opprop; - unsigned long openpic_addr = 0; - int naddr, n, i, opplen; - struct mpic *mpic; - - np = of_find_node_by_path("/"); - naddr = of_n_addr_cells(np); - opprop = of_get_property(np, "platform-open-pic", &opplen); - if (opprop != NULL) { - openpic_addr = of_read_number(opprop, naddr); - printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr); - } - of_node_put(np); - - BUG_ON(openpic_addr == 0); - - /* Setup the openpic driver */ - mpic = mpic_alloc(pSeries_mpic_node, openpic_addr, - MPIC_NO_RESET, 16, 0, " MPIC "); - BUG_ON(mpic == NULL); - - /* Add ISUs */ - opplen /= sizeof(u32); - for (n = 0, i = naddr; i < opplen; i += naddr, n++) { - unsigned long isuaddr = of_read_number(opprop + i, naddr); - mpic_assign_isu(mpic, n, isuaddr); - } - - /* Setup top-level get_irq */ - ppc_md.get_irq = mpic_get_irq; - - /* All ISUs are setup, complete initialization */ - mpic_init(mpic); - - /* Look for cascade */ - pseries_setup_i8259_cascade(); -} - -static void __init pseries_xics_init_IRQ(void) +static void __init pseries_init_irq(void) { xics_init(); pseries_setup_i8259_cascade(); @@ -228,32 +184,6 @@ static void pseries_lpar_enable_pmcs(void) plpar_hcall_norets(H_PERFMON, set, reset); } -static void __init pseries_discover_pic(void) -{ - struct device_node *np; - const char *typep; - - for_each_node_by_name(np, "interrupt-controller") { - typep = of_get_property(np, "compatible", NULL); - if (!typep) - continue; - if (strstr(typep, "open-pic")) { - pSeries_mpic_node = of_node_get(np); - ppc_md.init_IRQ = pseries_mpic_init_IRQ; - setup_kexec_cpu_down_mpic(); - smp_init_pseries_mpic(); - return; - } else if (strstr(typep, "ppc-xicp")) { - ppc_md.init_IRQ = pseries_xics_init_IRQ; - setup_kexec_cpu_down_xics(); - smp_init_pseries_xics(); - return; - } - } - printk(KERN_ERR "pSeries_discover_pic: failed to recognize" - " interrupt-controller\n"); -} - static int pci_dn_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *data) { struct of_reconfig_data *rd = data; @@ -506,7 +436,9 @@ static void __init pSeries_setup_arch(void) set_arch_panic_timeout(10, ARCH_PANIC_TIMEOUT); /* Discover PIC type and setup ppc_md accordingly */ - pseries_discover_pic(); + setup_kexec_cpu_down_xics(); + smp_init_pseries_xics(); + /* openpic global configuration register (64-bit format). */ /* openpic Interrupt Source Unit pointer (64-bit format). */ @@ -838,6 +770,7 @@ define_machine(pseries) { .probe = pSeries_probe, .setup_arch = pSeries_setup_arch, .init_early = pSeries_init_early, + .init_IRQ = pseries_init_irq, .show_cpuinfo = pSeries_show_cpuinfo, .log_error = pSeries_log_error, .pcibios_fixup = pSeries_final_fixup, -- cgit v1.2.3 From 86425bedd5b69ea5969ff11bb07c8e5ff7117976 Mon Sep 17 00:00:00 2001 From: Rashmica Gupta Date: Mon, 30 May 2016 16:18:12 +1000 Subject: powerpc/pseries: Remove MPIC from pseries smp MPIC was only used by Power3 which is now unsupported, so remove MPIC code. XICS is now the only supported interrupt controller for pSeries so do some cleanups too. Signed-off-by: Rashmica Gupta Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/pseries/pseries.h | 6 ++---- arch/powerpc/platforms/pseries/setup.c | 2 +- arch/powerpc/platforms/pseries/smp.c | 31 +++++-------------------------- 3 files changed, 8 insertions(+), 31 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h index 7aa83f00ac62..edeaec74b656 100644 --- a/arch/powerpc/platforms/pseries/pseries.h +++ b/arch/powerpc/platforms/pseries/pseries.h @@ -31,11 +31,9 @@ extern int pSeries_system_reset_exception(struct pt_regs *regs); extern int pSeries_machine_check_exception(struct pt_regs *regs); #ifdef CONFIG_SMP -extern void smp_init_pseries_mpic(void); -extern void smp_init_pseries_xics(void); +extern void smp_init_pseries(void); #else -static inline void smp_init_pseries_mpic(void) { }; -static inline void smp_init_pseries_xics(void) { }; +static inline void smp_init_pseries(void) { }; #endif #ifdef CONFIG_KEXEC diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 39f21fb3c609..4b94a1e75bcf 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -437,7 +437,7 @@ static void __init pSeries_setup_arch(void) /* Discover PIC type and setup ppc_md accordingly */ setup_kexec_cpu_down_xics(); - smp_init_pseries_xics(); + smp_init_pseries(); /* openpic global configuration register (64-bit format). */ diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index 6932ea803e33..f6f83aeccaaa 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -140,7 +139,7 @@ out: return 1; } -static void smp_xics_setup_cpu(int cpu) +static void smp_setup_cpu(int cpu) { if (cpu != boot_cpuid) xics_setup_cpu(); @@ -207,28 +206,22 @@ static __init void pSeries_smp_probe(void) } } -static struct smp_ops_t pSeries_mpic_smp_ops = { - .message_pass = smp_mpic_message_pass, - .probe = smp_mpic_probe, - .kick_cpu = smp_pSeries_kick_cpu, - .setup_cpu = smp_mpic_setup_cpu, -}; - -static struct smp_ops_t pSeries_xics_smp_ops = { +static struct smp_ops_t pseries_smp_ops = { .message_pass = NULL, /* Use smp_muxed_ipi_message_pass */ .cause_ipi = NULL, /* Filled at runtime by pSeries_smp_probe() */ .probe = pSeries_smp_probe, .kick_cpu = smp_pSeries_kick_cpu, - .setup_cpu = smp_xics_setup_cpu, + .setup_cpu = smp_setup_cpu, .cpu_bootable = smp_generic_cpu_bootable, }; /* This is called very early */ -static void __init smp_init_pseries(void) +void __init smp_init_pseries(void) { int i; pr_debug(" -> smp_init_pSeries()\n"); + smp_ops = &pseries_smp_ops; alloc_bootmem_cpumask_var(&of_spin_mask); @@ -258,17 +251,3 @@ static void __init smp_init_pseries(void) pr_debug(" <- smp_init_pSeries()\n"); } - -void __init smp_init_pseries_mpic(void) -{ - smp_ops = &pSeries_mpic_smp_ops; - - smp_init_pseries(); -} - -void __init smp_init_pseries_xics(void) -{ - smp_ops = &pSeries_xics_smp_ops; - - smp_init_pseries(); -} -- cgit v1.2.3 From d739d2caa3d3e283ca4d41716cd317684e066ef9 Mon Sep 17 00:00:00 2001 From: Rashmica Gupta Date: Mon, 30 May 2016 16:18:13 +1000 Subject: powerpc/pseries: Remove MPIC from pseries kexec MPIC was only used by Power3 which is now unsupported, so remove MPIC code. XICS is now the only supported interrupt controller for pSeries so do some cleanups too. Signed-off-by: Rashmica Gupta Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/pseries/kexec.c | 23 +---------------------- arch/powerpc/platforms/pseries/pseries.h | 8 +------- arch/powerpc/platforms/pseries/setup.c | 2 +- 3 files changed, 3 insertions(+), 30 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/kexec.c b/arch/powerpc/platforms/pseries/kexec.c index 13fa95b3aa8b..6681ac97fb18 100644 --- a/arch/powerpc/platforms/pseries/kexec.c +++ b/arch/powerpc/platforms/pseries/kexec.c @@ -14,14 +14,13 @@ #include #include #include -#include #include #include #include #include "pseries.h" -static void pseries_kexec_cpu_down(int crash_shutdown, int secondary) +void pseries_kexec_cpu_down(int crash_shutdown, int secondary) { /* Don't risk a hypervisor call if we're crashing */ if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) { @@ -51,26 +50,6 @@ static void pseries_kexec_cpu_down(int crash_shutdown, int secondary) "(hw %d) failed with %d\n", cpu, hwcpu, ret); } } -} - -static void pseries_kexec_cpu_down_mpic(int crash_shutdown, int secondary) -{ - pseries_kexec_cpu_down(crash_shutdown, secondary); - mpic_teardown_this_cpu(secondary); -} -void __init setup_kexec_cpu_down_mpic(void) -{ - ppc_md.kexec_cpu_down = pseries_kexec_cpu_down_mpic; -} - -static void pseries_kexec_cpu_down_xics(int crash_shutdown, int secondary) -{ - pseries_kexec_cpu_down(crash_shutdown, secondary); xics_kexec_teardown_cpu(secondary); } - -void __init setup_kexec_cpu_down_xics(void) -{ - ppc_md.kexec_cpu_down = pseries_kexec_cpu_down_xics; -} diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h index edeaec74b656..ddb9aa51aad6 100644 --- a/arch/powerpc/platforms/pseries/pseries.h +++ b/arch/powerpc/platforms/pseries/pseries.h @@ -36,13 +36,7 @@ extern void smp_init_pseries(void); static inline void smp_init_pseries(void) { }; #endif -#ifdef CONFIG_KEXEC -extern void setup_kexec_cpu_down_xics(void); -extern void setup_kexec_cpu_down_mpic(void); -#else -static inline void setup_kexec_cpu_down_xics(void) { } -static inline void setup_kexec_cpu_down_mpic(void) { } -#endif +extern void pseries_kexec_cpu_down(int crash_shutdown, int secondary); extern void pSeries_final_fixup(void); diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 4b94a1e75bcf..34668f9bc57b 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -436,7 +436,6 @@ static void __init pSeries_setup_arch(void) set_arch_panic_timeout(10, ARCH_PANIC_TIMEOUT); /* Discover PIC type and setup ppc_md accordingly */ - setup_kexec_cpu_down_xics(); smp_init_pseries(); @@ -786,6 +785,7 @@ define_machine(pseries) { .machine_check_exception = pSeries_machine_check_exception, #ifdef CONFIG_KEXEC .machine_kexec = pSeries_machine_kexec, + .kexec_cpu_down = pseries_kexec_cpu_down, #endif #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE .memory_block_size = pseries_memory_block_size, -- cgit v1.2.3 From 8324947d6d318fbcf558d50ae348a85aacd68930 Mon Sep 17 00:00:00 2001 From: Rashmica Gupta Date: Mon, 30 May 2016 16:18:14 +1000 Subject: powerpc/pseries: Remove MPIC from pseries cpu hotplug MPIC was only used by Power3 which is now unsupported, so remove MPIC code. Signed-off-by: Rashmica Gupta Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/pseries/hotplug-cpu.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c index 282837a1d74b..a1b63e00b2f7 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c @@ -903,8 +903,6 @@ static int parse_cede_parameters(void) static int __init pseries_cpu_hotplug_init(void) { - struct device_node *np; - const char *typep; int cpu; int qcss_tok; @@ -913,17 +911,6 @@ static int __init pseries_cpu_hotplug_init(void) ppc_md.cpu_release = dlpar_cpu_release; #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ - for_each_node_by_name(np, "interrupt-controller") { - typep = of_get_property(np, "compatible", NULL); - if (strstr(typep, "open-pic")) { - of_node_put(np); - - printk(KERN_INFO "CPU Hotplug not supported on " - "systems using MPIC\n"); - return 0; - } - } - rtas_stop_self_token = rtas_token("stop-self"); qcss_tok = rtas_token("query-cpu-stopped-state"); -- cgit v1.2.3 From ac9cd1709c0be4334fbad4ab610ecb7acceac884 Mon Sep 17 00:00:00 2001 From: Rashmica Gupta Date: Mon, 30 May 2016 16:18:15 +1000 Subject: powerpc/pseries: Remove MPIC from pseries event sources MPIC was only used by Power3 which is now unsupported, so remove MPIC code. XICS is now the only supported interrupt controller for pSeries so do some cleanups too. Signed-off-by: Rashmica Gupta Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/pseries/event_sources.c | 53 +++++++------------------- 1 file changed, 13 insertions(+), 40 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/event_sources.c b/arch/powerpc/platforms/pseries/event_sources.c index 18380e8f6dfe..a6ddca833119 100644 --- a/arch/powerpc/platforms/pseries/event_sources.c +++ b/arch/powerpc/platforms/pseries/event_sources.c @@ -26,48 +26,21 @@ void request_event_sources_irqs(struct device_node *np, { int i, index, count = 0; struct of_phandle_args oirq; - const u32 *opicprop; - unsigned int opicplen; unsigned int virqs[16]; - /* Check for obsolete "open-pic-interrupt" property. If present, then - * map those interrupts using the default interrupt host and default - * trigger - */ - opicprop = of_get_property(np, "open-pic-interrupt", &opicplen); - if (opicprop) { - opicplen /= sizeof(u32); - for (i = 0; i < opicplen; i++) { - if (count > 15) - break; - virqs[count] = irq_create_mapping(NULL, *(opicprop++)); - if (virqs[count] == NO_IRQ) { - pr_err("event-sources: Unable to allocate " - "interrupt number for %s\n", - np->full_name); - WARN_ON(1); - } - else - count++; - - } - } - /* Else use normal interrupt tree parsing */ - else { - /* First try to do a proper OF tree parsing */ - for (index = 0; of_irq_parse_one(np, index, &oirq) == 0; - index++) { - if (count > 15) - break; - virqs[count] = irq_create_of_mapping(&oirq); - if (virqs[count] == NO_IRQ) { - pr_err("event-sources: Unable to allocate " - "interrupt number for %s\n", - np->full_name); - WARN_ON(1); - } - else - count++; + /* First try to do a proper OF tree parsing */ + for (index = 0; of_irq_parse_one(np, index, &oirq) == 0; + index++) { + if (count > 15) + break; + virqs[count] = irq_create_of_mapping(&oirq); + if (virqs[count] == NO_IRQ) { + pr_err("event-sources: Unable to allocate " + "interrupt number for %s\n", + np->full_name); + WARN_ON(1); + } else { + count++; } } -- cgit v1.2.3 From 1e61423fb1b6a814e50ed7845c6c5f2bd5b4c6dc Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Wed, 8 Jun 2016 18:02:37 +0800 Subject: powerpc/pseries: Remove unused pstore headers in nvram.c Since the pstore code has moved away from nvram.c, remove unused pstore headers pstore.h and kmsg_dump.h. Signed-off-by: Geliang Tang Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/pseries/nvram.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c index 9f8184175c86..79aef8c1c5b3 100644 --- a/arch/powerpc/platforms/pseries/nvram.c +++ b/arch/powerpc/platforms/pseries/nvram.c @@ -17,8 +17,6 @@ #include #include #include -#include -#include #include #include #include -- cgit v1.2.3 From 34852ed5511ec5d07897f22d5607061a248fc82f Mon Sep 17 00:00:00 2001 From: Daniel Axtens Date: Wed, 18 May 2016 11:16:49 +1000 Subject: powerpc/sparse: make some things static This is just a smattering of things picked up by sparse that should be made static. Signed-off-by: Daniel Axtens Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/crash.c | 2 +- arch/powerpc/kernel/sysfs.c | 2 +- arch/powerpc/platforms/powernv/idle.c | 2 +- arch/powerpc/platforms/pseries/pseries_energy.c | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index 3dc1fade0b28..888bdf198c3e 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c @@ -65,7 +65,7 @@ static int handle_fault(struct pt_regs *regs) #ifdef CONFIG_SMP static atomic_t cpus_in_crash; -void crash_ipi_callback(struct pt_regs *regs) +static void crash_ipi_callback(struct pt_regs *regs) { static cpumask_t cpus_state_saved = CPU_MASK_NONE; diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 692873bff334..c4f1d1f7bae0 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -35,7 +35,7 @@ static DEFINE_PER_CPU(struct cpu, cpu_devices); #ifdef CONFIG_PPC64 /* Time in microseconds we delay before sleeping in the idle loop */ -DEFINE_PER_CPU(long, smt_snooze_delay) = { 100 }; +static DEFINE_PER_CPU(long, smt_snooze_delay) = { 100 }; static ssize_t store_smt_snooze_delay(struct device *dev, struct device_attribute *attr, diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c index fcc8b6861b63..92a8020f3502 100644 --- a/arch/powerpc/platforms/powernv/idle.c +++ b/arch/powerpc/platforms/powernv/idle.c @@ -29,7 +29,7 @@ static u32 supported_cpuidle_states; -int pnv_save_sprs_for_winkle(void) +static int pnv_save_sprs_for_winkle(void) { int cpu; int rc; diff --git a/arch/powerpc/platforms/pseries/pseries_energy.c b/arch/powerpc/platforms/pseries/pseries_energy.c index 92767791f93b..164a13d3998a 100644 --- a/arch/powerpc/platforms/pseries/pseries_energy.c +++ b/arch/powerpc/platforms/pseries/pseries_energy.c @@ -208,19 +208,19 @@ static ssize_t percpu_deactivate_hint_show(struct device *dev, * Per-cpu value of the hint */ -struct device_attribute attr_cpu_activate_hint_list = +static struct device_attribute attr_cpu_activate_hint_list = __ATTR(pseries_activate_hint_list, 0444, cpu_activate_hint_list_show, NULL); -struct device_attribute attr_cpu_deactivate_hint_list = +static struct device_attribute attr_cpu_deactivate_hint_list = __ATTR(pseries_deactivate_hint_list, 0444, cpu_deactivate_hint_list_show, NULL); -struct device_attribute attr_percpu_activate_hint = +static struct device_attribute attr_percpu_activate_hint = __ATTR(pseries_activate_hint, 0444, percpu_activate_hint_show, NULL); -struct device_attribute attr_percpu_deactivate_hint = +static struct device_attribute attr_percpu_deactivate_hint = __ATTR(pseries_deactivate_hint, 0444, percpu_deactivate_hint_show, NULL); -- cgit v1.2.3 From 42f5b4cacd783faf05e3ff8bf85e8be31f3dfa9d Mon Sep 17 00:00:00 2001 From: Daniel Axtens Date: Wed, 18 May 2016 11:16:50 +1000 Subject: powerpc: Introduce asm-prototypes.h Sparse picked up a number of functions that are implemented in C and then only referred to in asm code. This introduces asm-prototypes.h, which provides a place for prototypes of these functions. This silences some sparse warnings. Signed-off-by: Daniel Axtens [mpe: Add include guards, clean up copyright & GPL text] Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/asm-prototypes.h | 75 +++++++++++++++++++++++ arch/powerpc/kernel/machine_kexec_64.c | 1 + arch/powerpc/kernel/smp.c | 1 + arch/powerpc/kernel/traps.c | 1 + arch/powerpc/lib/vmx-helper.c | 1 + arch/powerpc/platforms/powernv/opal-tracepoints.c | 1 + arch/powerpc/platforms/pseries/lpar.c | 1 + 7 files changed, 81 insertions(+) create mode 100644 arch/powerpc/include/asm/asm-prototypes.h (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/include/asm/asm-prototypes.h b/arch/powerpc/include/asm/asm-prototypes.h new file mode 100644 index 000000000000..e71b9097594c --- /dev/null +++ b/arch/powerpc/include/asm/asm-prototypes.h @@ -0,0 +1,75 @@ +#ifndef _ASM_POWERPC_ASM_PROTOTYPES_H +#define _ASM_POWERPC_ASM_PROTOTYPES_H +/* + * This file is for prototypes of C functions that are only called + * from asm, and any associated variables. + * + * Copyright 2016, Daniel Axtens, IBM Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + */ + +#include +#include + +/* SMP */ +extern struct thread_info *current_set[NR_CPUS]; +extern struct thread_info *secondary_ti; +void start_secondary(void *unused); + +/* kexec */ +struct paca_struct; +struct kimage; +extern struct paca_struct kexec_paca; +void kexec_copy_flush(struct kimage *image); + +/* pseries hcall tracing */ +extern struct static_key hcall_tracepoint_key; +void __trace_hcall_entry(unsigned long opcode, unsigned long *args); +void __trace_hcall_exit(long opcode, unsigned long retval, + unsigned long *retbuf); +/* OPAL tracing */ +#ifdef HAVE_JUMP_LABEL +extern struct static_key opal_tracepoint_key; +#endif + +void __trace_opal_entry(unsigned long opcode, unsigned long *args); +void __trace_opal_exit(long opcode, unsigned long retval); + +/* VMX copying */ +int enter_vmx_usercopy(void); +int exit_vmx_usercopy(void); +int enter_vmx_copy(void); +void * exit_vmx_copy(void *dest); + +/* Traps */ +long machine_check_early(struct pt_regs *regs); +long hmi_exception_realmode(struct pt_regs *regs); +void SMIException(struct pt_regs *regs); +void handle_hmi_exception(struct pt_regs *regs); +void instruction_breakpoint_exception(struct pt_regs *regs); +void RunModeException(struct pt_regs *regs); +void __kprobes single_step_exception(struct pt_regs *regs); +void __kprobes program_check_exception(struct pt_regs *regs); +void alignment_exception(struct pt_regs *regs); +void StackOverflow(struct pt_regs *regs); +void nonrecoverable_exception(struct pt_regs *regs); +void kernel_fp_unavailable_exception(struct pt_regs *regs); +void altivec_unavailable_exception(struct pt_regs *regs); +void vsx_unavailable_exception(struct pt_regs *regs); +void fp_unavailable_tm(struct pt_regs *regs); +void altivec_unavailable_tm(struct pt_regs *regs); +void vsx_unavailable_tm(struct pt_regs *regs); +void facility_unavailable_exception(struct pt_regs *regs); +void TAUException(struct pt_regs *regs); +void altivec_assist_exception(struct pt_regs *regs); +void unrecoverable_exception(struct pt_regs *regs); +void kernel_bad_stack(struct pt_regs *regs); +void system_reset_exception(struct pt_regs *regs); +void machine_check_exception(struct pt_regs *regs); +void __kprobes emulation_assist_interrupt(struct pt_regs *regs); + +#endif /* _ASM_POWERPC_ASM_PROTOTYPES_H */ diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index b8c202d63ecb..50bf55135ef8 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c @@ -29,6 +29,7 @@ #include #include #include +#include #ifdef CONFIG_PPC_BOOK3E int default_machine_kexec_prepare(struct kimage *image) diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 55c924b65f71..f1adc3c4f4ca 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -53,6 +53,7 @@ #include #include #include +#include #ifdef DEBUG #include diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 9229ba63c370..11d15e7270e0 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -60,6 +60,7 @@ #include #include #include +#include #include #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC) diff --git a/arch/powerpc/lib/vmx-helper.c b/arch/powerpc/lib/vmx-helper.c index b27e030fc9f8..bf925cdcaca9 100644 --- a/arch/powerpc/lib/vmx-helper.c +++ b/arch/powerpc/lib/vmx-helper.c @@ -21,6 +21,7 @@ #include #include #include +#include int enter_vmx_usercopy(void) { diff --git a/arch/powerpc/platforms/powernv/opal-tracepoints.c b/arch/powerpc/platforms/powernv/opal-tracepoints.c index e11273b2386d..1e496b780efd 100644 --- a/arch/powerpc/platforms/powernv/opal-tracepoints.c +++ b/arch/powerpc/platforms/powernv/opal-tracepoints.c @@ -1,6 +1,7 @@ #include #include #include +#include #ifdef HAVE_JUMP_LABEL struct static_key opal_tracepoint_key = STATIC_KEY_INIT; diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 7f6100d91b4b..03ff9867a610 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -45,6 +45,7 @@ #include #include #include +#include #include "pseries.h" -- cgit v1.2.3 From 665e87ffe1c400c525c3a4cd6fcb5db75972fadd Mon Sep 17 00:00:00 2001 From: Daniel Axtens Date: Wed, 18 May 2016 11:16:51 +1000 Subject: powerpc/sparse: Include headers containing prototypes Sometimes headers that provide prototypes for functions are accidentally omitted from the files that define the functions. Fix a couple of times that occurs. Signed-off-by: Daniel Axtens Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/smp.c | 1 + arch/powerpc/platforms/pseries/power.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index f1adc3c4f4ca..1b55c7864291 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include diff --git a/arch/powerpc/platforms/pseries/power.c b/arch/powerpc/platforms/pseries/power.c index c26eadde434c..a4a0b57d1d81 100644 --- a/arch/powerpc/platforms/pseries/power.c +++ b/arch/powerpc/platforms/pseries/power.c @@ -27,6 +27,8 @@ #include #include +#include "pseries.h" + unsigned long rtas_poweron_auto; /* default and normal state is 0 */ static ssize_t auto_poweron_show(struct kobject *kobj, -- cgit v1.2.3 From b385c9e971468eb8816b26742449d6d1e49f55f1 Mon Sep 17 00:00:00 2001 From: Ian Munsie Date: Wed, 8 Jun 2016 15:09:54 +1000 Subject: cxl: Add support for CAPP DMA mode This adds support for using CAPP DMA mode, which is required for XSL based cards such as the Mellanox CX4 to function. This is currently an RFC as it depends on the corresponding support to be merged into skiboot first, which was submitted here: http://patchwork.ozlabs.org/patch/625582/ In the event that the skiboot on the system does not have the above support, it will indicate as such in the kernel log and abort the init process. Signed-off-by: Ian Munsie Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/opal-api.h | 1 + arch/powerpc/platforms/powernv/pci-ioda.c | 4 +++- drivers/misc/cxl/cxl.h | 1 + drivers/misc/cxl/pci.c | 4 +++- 4 files changed, 8 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h index 70b5cbc0a49c..cd9371b33f1a 100644 --- a/arch/powerpc/include/asm/opal-api.h +++ b/arch/powerpc/include/asm/opal-api.h @@ -825,6 +825,7 @@ enum { OPAL_PHB_CAPI_MODE_CAPI = 1, OPAL_PHB_CAPI_MODE_SNOOP_OFF = 2, OPAL_PHB_CAPI_MODE_SNOOP_ON = 3, + OPAL_PHB_CAPI_MODE_DMA = 4, }; /* OPAL I2C request */ diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 1fc53e015d29..2c0e09f2fc50 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -2793,7 +2793,9 @@ int pnv_phb_to_cxl_mode(struct pci_dev *dev, uint64_t mode) pe_info(pe, "Switching PHB to CXL\n"); rc = opal_pci_set_phb_cxl_mode(phb->opal_id, mode, pe->pe_number); - if (rc) + if (rc == OPAL_UNSUPPORTED) + dev_err(&dev->dev, "Required cxl mode not supported by firmware - update skiboot\n"); + else if (rc) dev_err(&dev->dev, "opal_pci_set_phb_cxl_mode failed: %i\n", rc); return rc; diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h index 790faebf44dc..ce2b9d513069 100644 --- a/drivers/misc/cxl/cxl.h +++ b/drivers/misc/cxl/cxl.h @@ -543,6 +543,7 @@ struct cxl_service_layer_ops { void (*debugfs_stop_trace)(struct cxl *adapter); void (*write_timebase_ctrl)(struct cxl *adapter); u64 (*timebase_read)(struct cxl *adapter); + int capi_mode; }; struct cxl_native { diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c index 556718d7915f..648817a2e219 100644 --- a/drivers/misc/cxl/pci.c +++ b/drivers/misc/cxl/pci.c @@ -1249,7 +1249,7 @@ static int cxl_configure_adapter(struct cxl *adapter, struct pci_dev *dev) if ((rc = adapter->native->sl_ops->adapter_regs_init(adapter, dev))) goto err; - if ((rc = pnv_phb_to_cxl_mode(dev, OPAL_PHB_CAPI_MODE_CAPI))) + if ((rc = pnv_phb_to_cxl_mode(dev, adapter->native->sl_ops->capi_mode))) goto err; /* If recovery happened, the last step is to turn on snooping. @@ -1293,6 +1293,7 @@ static const struct cxl_service_layer_ops psl_ops = { .debugfs_stop_trace = cxl_stop_trace, .write_timebase_ctrl = write_timebase_ctrl_psl, .timebase_read = timebase_read_psl, + .capi_mode = OPAL_PHB_CAPI_MODE_CAPI, }; static const struct cxl_service_layer_ops xsl_ops = { @@ -1300,6 +1301,7 @@ static const struct cxl_service_layer_ops xsl_ops = { .debugfs_add_adapter_sl_regs = cxl_debugfs_add_adapter_xsl_regs, .write_timebase_ctrl = write_timebase_ctrl_xsl, .timebase_read = timebase_read_xsl, + .capi_mode = OPAL_PHB_CAPI_MODE_DMA, }; static void set_sl_ops(struct cxl *adapter, struct pci_dev *dev) -- cgit v1.2.3 From e368e4ca9c0686514febd3f1767d465caf208db0 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Fri, 20 May 2016 16:41:27 +1000 Subject: powerpc/powernv: Remove PCI_RESET_DELAY_US The macro defined in arch/powerpc/platforms/powernv/pci.c isn't used by anyone. Just remove it. Signed-off-by: Gavin Shan Reviewed-by: Andrew Donnellan Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/pci.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index 1d92bd93bcd9..b1ee6314f946 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c @@ -36,9 +36,6 @@ #include "powernv.h" #include "pci.h" -/* Delay in usec */ -#define PCI_RESET_DELAY_US 3000000 - #ifdef CONFIG_PCI_MSI int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) { -- cgit v1.2.3 From 577c8c886823ea81fae92ff54ae4225a3f1f6c75 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Fri, 20 May 2016 16:41:28 +1000 Subject: powerpc/powernv: Move pnv_pci_ioda_setup_opal_tce_kill() around pnv_pci_ioda_setup_opal_tce_kill() called by pnv_ioda_setup_dma() to remap the TCE kill regiter. What's done in pnv_ioda_setup_dma() will be covered in pcibios_setup_bridge() which is invoked on each PCI bridge. It means we will possibly remap the TCE kill register for multiple times and it's unnecessary. This moves pnv_pci_ioda_setup_opal_tce_kill() to where the PHB is initialized (pnv_pci_init_ioda_phb()) to avoid above issue. Signed-off-by: Gavin Shan Reviewed-by: Alexey Kardashevskiy Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/pci-ioda.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 2c0e09f2fc50..5bbee8249584 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -2702,8 +2702,6 @@ static void pnv_ioda_setup_dma(struct pnv_phb *phb) pr_info("PCI: Domain %04x has %d available 32-bit DMA segments\n", hose->global_number, phb->ioda.dma32_count); - pnv_pci_ioda_setup_opal_tce_kill(phb); - /* Walk our PE list and configure their DMA segments */ list_for_each_entry(pe, &phb->ioda.pe_list, list) { weight = pnv_pci_ioda_pe_dma_weight(pe); @@ -3482,6 +3480,9 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, if (phb->regs == NULL) pr_err(" Failed to map registers !\n"); + /* Initialize TCE kill register */ + pnv_pci_ioda_setup_opal_tce_kill(phb); + /* Initialize more IODA stuff */ phb->ioda.total_pe_num = 1; prop32 = of_get_property(np, "ibm,opal-num-pes", NULL); -- cgit v1.2.3 From c127562ae1d85c7f79192ace0431f97add8f83ea Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Fri, 20 May 2016 16:41:29 +1000 Subject: powerpc/powernv: Increase PE# capacity Each PHB maintains an array helping to translate 2-bytes Request ID (RID) to PE# with the assumption that PE# takes one byte, meaning that we can't have more than 256 PEs. However, pci_dn->pe_number already had 4-bytes for the PE#. This extends the PE# capacity for every PHB. After that, the PE number is represented by 4-bytes value. Then we can reuse IODA_INVALID_PE to check the PE# in phb->pe_rmap[] is valid or not. Signed-off-by: Gavin Shan Reviewed-by: Daniel Axtens Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/pci-ioda.c | 6 +++++- arch/powerpc/platforms/powernv/pci.h | 7 ++----- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 5bbee8249584..393d32401f4f 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -761,7 +761,7 @@ static int pnv_ioda_deconfigure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe) /* Clear the reverse map */ for (rid = pe->rid; rid < rid_end; rid++) - phb->ioda.pe_rmap[rid] = 0; + phb->ioda.pe_rmap[rid] = IODA_INVALID_PE; /* Release from all parents PELT-V */ while (parent) { @@ -3492,6 +3492,10 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, if (prop32) phb->ioda.reserved_pe_idx = be32_to_cpup(prop32); + /* Invalidate RID to PE# mapping */ + for (segno = 0; segno < ARRAY_SIZE(phb->ioda.pe_rmap); segno++) + phb->ioda.pe_rmap[segno] = IODA_INVALID_PE; + /* Parse 64-bit MMIO range */ pnv_ioda_parse_m64_window(phb); diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index 7dee25e304db..de56ed2046b4 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h @@ -152,11 +152,8 @@ struct pnv_phb { struct list_head pe_list; struct mutex pe_list_mutex; - /* Reverse map of PEs, will have to extend if - * we are to support more than 256 PEs, indexed - * bus { bus, devfn } - */ - unsigned char pe_rmap[0x10000]; + /* Reverse map of PEs, indexed by {bus, devfn} */ + unsigned int pe_rmap[0x10000]; /* TCE cache invalidate registers (physical and * remapped) -- cgit v1.2.3 From 9fcd6f4a2b264f15071ab5e2d61ac2d9125ebc1d Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Fri, 20 May 2016 16:41:30 +1000 Subject: powerpc/powernv: Allocate PE# in reverse order PE number for one particular PE can be allocated dynamically or reserved according to the consumed M64 (64-bits prefetchable) segments of the PE. The M64 segment can't be remapped to arbitrary PE, meaning the PE number is determined according to the index of the consumed M64 segment. As below figure shows, M64 resource grows from low to high end, meaning the PE (number) reserved according to M64 segment grows from low to high end as well, so does the dynamically allocated PE number. It will lead to conflict: PE number (M64 segment) reserved by dynamic allocation is required by hot added PCI adapter at later point. It fails the PCI hotplug because of the PE number can't be reserved based on the index of the consumed M64 segment. +---+---+---+---+---+--------------------------------+-----+ | 0 | 1 | 2 | 3 | 4 | ....... | 255 | +---+---+---+---+---+--------------------------------+-----+ PE number for dynamic allocation -----------------> PE number reserved for M64 segment -----------------> To resolve above conflicts, this forces the PE number to be allocated dynamically in reverse order. With this patch applied, the PE numbers are reserved in ascending order, but allocated dynamically in reverse order. Signed-off-by: Gavin Shan Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/pci-ioda.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 393d32401f4f..e82097316602 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -141,16 +141,14 @@ static void pnv_ioda_reserve_pe(struct pnv_phb *phb, int pe_no) static struct pnv_ioda_pe *pnv_ioda_alloc_pe(struct pnv_phb *phb) { - unsigned long pe; + unsigned long pe = phb->ioda.total_pe_num - 1; - do { - pe = find_next_zero_bit(phb->ioda.pe_alloc, - phb->ioda.total_pe_num, 0); - if (pe >= phb->ioda.total_pe_num) - return NULL; - } while(test_and_set_bit(pe, phb->ioda.pe_alloc)); + for (pe = phb->ioda.total_pe_num - 1; pe >= 0; pe--) { + if (!test_and_set_bit(pe, phb->ioda.pe_alloc)) + return pnv_ioda_init_pe(phb, pe); + } - return pnv_ioda_init_pe(phb, pe); + return NULL; } static void pnv_ioda_free_pe(struct pnv_ioda_pe *pe) -- cgit v1.2.3 From ccd1c1911a70298cc0473de89ff0f95cd8d16ffe Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Fri, 20 May 2016 16:41:31 +1000 Subject: powerpc/powernv: Create PEs in pcibios_setup_bridge() Currently, the PEs and their associated resources are assigned in ppc_md.pcibios_fixup() except those used by SRIOV VFs. The function is called for once after PCI probing and resources assignment is completed. So it's obviously not hotplug friendly. This creates PEs dynamically in pcibios_setup_bridge() that is called for the event during system bootup and PCI hotplug: updating PCI bridge's windows after resource assignment/reassignment are done. In partial hotplug case, not all PCI devices included to one particular PE are unplugged and plugged again, we just need unbinding/binding the hot added PCI devices with the corresponding PE without creating new one. The change is applied to IODA1 and IODA2 PHBs only. The behaviour on NPU PHBs aren't changed. There are no PCI bridges on NPU PHBs, meaning pcibios_setup_bridge() won't be invoked there. We have to use old path (pnv_pci_ioda_fixup()) to setup PEs on NPU PHBs. Signed-off-by: Gavin Shan Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/pci-ioda.c | 184 +++++++++++------------------- 1 file changed, 69 insertions(+), 115 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index e82097316602..062f7fbddccc 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -1022,6 +1022,15 @@ static void pnv_ioda_setup_same_PE(struct pci_bus *bus, struct pnv_ioda_pe *pe) pci_name(dev)); continue; } + + /* + * In partial hotplug case, the PCI device might be still + * associated with the PE and needn't attach it to the PE + * again. + */ + if (pdn->pe_number != IODA_INVALID_PE) + continue; + pdn->pcidev = dev; pdn->pe_number = pe->pe_number; if ((pe->flags & PNV_IODA_PE_BUS_ALL) && dev->subordinate) @@ -1040,6 +1049,18 @@ static struct pnv_ioda_pe *pnv_ioda_setup_bus_PE(struct pci_bus *bus, bool all) struct pci_controller *hose = pci_bus_to_host(bus); struct pnv_phb *phb = hose->private_data; struct pnv_ioda_pe *pe = NULL; + unsigned int pe_num; + + /* + * In partial hotplug case, the PE instance might be still alive. + * We should reuse it instead of allocating a new one. + */ + pe_num = phb->ioda.pe_rmap[bus->number << 8]; + if (pe_num != IODA_INVALID_PE) { + pe = &phb->ioda.pe_array[pe_num]; + pnv_ioda_setup_same_PE(bus, pe); + return NULL; + } /* Check if PE is determined by M64 */ if (phb->pick_m64_pe) @@ -1154,30 +1175,6 @@ static void pnv_ioda_setup_npu_PEs(struct pci_bus *bus) pnv_ioda_setup_npu_PE(pdev); } -static void pnv_ioda_setup_PEs(struct pci_bus *bus) -{ - struct pci_dev *dev; - - pnv_ioda_setup_bus_PE(bus, false); - - list_for_each_entry(dev, &bus->devices, bus_list) { - if (dev->subordinate) { - if (pci_pcie_type(dev) == PCI_EXP_TYPE_PCI_BRIDGE) - pnv_ioda_setup_bus_PE(dev->subordinate, true); - else - pnv_ioda_setup_PEs(dev->subordinate); - } - } -} - -/* - * Configure PEs so that the downstream PCI buses and devices - * could have their associated PE#. Unfortunately, we didn't - * figure out the way to identify the PLX bridge yet. So we - * simply put the PCI bus and the subordinate behind the root - * port to PE# here. The game rule here is expected to be changed - * as soon as we can detected PLX bridge correctly. - */ static void pnv_pci_ioda_setup_PEs(void) { struct pci_controller *hose, *tmp; @@ -1185,22 +1182,11 @@ static void pnv_pci_ioda_setup_PEs(void) list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { phb = hose->private_data; - - /* M64 layout might affect PE allocation */ - if (phb->reserve_m64_pe) - phb->reserve_m64_pe(hose->bus, NULL, true); - - /* - * On NPU PHB, we expect separate PEs for individual PCI - * functions. PCI bus dependent PEs are required for the - * remaining types of PHBs. - */ if (phb->type == PNV_PHB_NPU) { /* PE#0 is needed for error reporting */ pnv_ioda_reserve_pe(phb, 0); pnv_ioda_setup_npu_PEs(hose->bus); - } else - pnv_ioda_setup_PEs(hose->bus); + } } } @@ -2655,6 +2641,9 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb, { int64_t rc; + if (!pnv_pci_ioda_pe_dma_weight(pe)) + return; + /* TVE #1 is selected by PCI address bit 59 */ pe->tce_bypass_base = 1ull << 59; @@ -2686,47 +2675,6 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb, pnv_ioda_setup_bus_dma(pe, pe->pbus); } -static void pnv_ioda_setup_dma(struct pnv_phb *phb) -{ - struct pci_controller *hose = phb->hose; - struct pnv_ioda_pe *pe; - unsigned int weight; - - /* If we have more PE# than segments available, hand out one - * per PE until we run out and let the rest fail. If not, - * then we assign at least one segment per PE, plus more based - * on the amount of devices under that PE - */ - pr_info("PCI: Domain %04x has %d available 32-bit DMA segments\n", - hose->global_number, phb->ioda.dma32_count); - - /* Walk our PE list and configure their DMA segments */ - list_for_each_entry(pe, &phb->ioda.pe_list, list) { - weight = pnv_pci_ioda_pe_dma_weight(pe); - if (!weight) - continue; - - /* - * For IODA2 compliant PHB3, we needn't care about the weight. - * The all available 32-bits DMA space will be assigned to - * the specific PE. - */ - if (phb->type == PNV_PHB_IODA1) { - pnv_pci_ioda1_setup_dma_pe(phb, pe); - } else if (phb->type == PNV_PHB_IODA2) { - pe_info(pe, "Assign DMA32 space\n"); - pnv_pci_ioda2_setup_dma_pe(phb, pe); - } else if (phb->type == PNV_PHB_NPU) { - /* - * We initialise the DMA space for an NPU PHB - * after setup of the PHB is complete as we - * point the NPU TVT to the the same location - * as the PHB3 TVT. - */ - } - } -} - #ifdef CONFIG_PCI_MSI static void pnv_ioda2_msi_eoi(struct irq_data *d) { @@ -3195,41 +3143,6 @@ static void pnv_ioda_setup_pe_seg(struct pnv_ioda_pe *pe) } } -static void pnv_pci_ioda_setup_seg(void) -{ - struct pci_controller *tmp, *hose; - struct pnv_phb *phb; - struct pnv_ioda_pe *pe; - - list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { - phb = hose->private_data; - - /* NPU PHB does not support IO or MMIO segmentation */ - if (phb->type == PNV_PHB_NPU) - continue; - - list_for_each_entry(pe, &phb->ioda.pe_list, list) { - pnv_ioda_setup_pe_seg(pe); - } - } -} - -static void pnv_pci_ioda_setup_DMA(void) -{ - struct pci_controller *hose, *tmp; - struct pnv_phb *phb; - - list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { - pnv_ioda_setup_dma(hose->private_data); - - /* Mark the PHB initialization done */ - phb = hose->private_data; - phb->initialized = 1; - } - - pnv_pci_ioda_setup_iommu_api(); -} - static void pnv_pci_ioda_create_dbgfs(void) { #ifdef CONFIG_DEBUG_FS @@ -3240,6 +3153,9 @@ static void pnv_pci_ioda_create_dbgfs(void) list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { phb = hose->private_data; + /* Notify initialization of PHB done */ + phb->initialized = 1; + sprintf(name, "PCI%04x", hose->global_number); phb->dbgfs = debugfs_create_dir(name, powerpc_debugfs_root); if (!phb->dbgfs) @@ -3252,9 +3168,7 @@ static void pnv_pci_ioda_create_dbgfs(void) static void pnv_pci_ioda_fixup(void) { pnv_pci_ioda_setup_PEs(); - pnv_pci_ioda_setup_seg(); - pnv_pci_ioda_setup_DMA(); - + pnv_pci_ioda_setup_iommu_api(); pnv_pci_ioda_create_dbgfs(); #ifdef CONFIG_EEH @@ -3304,6 +3218,45 @@ static resource_size_t pnv_pci_window_alignment(struct pci_bus *bus, return phb->ioda.io_segsize; } +static void pnv_pci_setup_bridge(struct pci_bus *bus, unsigned long type) +{ + struct pci_controller *hose = pci_bus_to_host(bus); + struct pnv_phb *phb = hose->private_data; + struct pci_dev *bridge = bus->self; + struct pnv_ioda_pe *pe; + bool all = (pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE); + + /* Don't assign PE to PCI bus, which doesn't have subordinate devices */ + if (list_empty(&bus->devices)) + return; + + /* Reserve PEs according to used M64 resources */ + if (phb->reserve_m64_pe) + phb->reserve_m64_pe(bus, NULL, all); + + /* + * Assign PE. We might run here because of partial hotplug. + * For the case, we just pick up the existing PE and should + * not allocate resources again. + */ + pe = pnv_ioda_setup_bus_PE(bus, all); + if (!pe) + return; + + pnv_ioda_setup_pe_seg(pe); + switch (phb->type) { + case PNV_PHB_IODA1: + pnv_pci_ioda1_setup_dma_pe(phb, pe); + break; + case PNV_PHB_IODA2: + pnv_pci_ioda2_setup_dma_pe(phb, pe); + break; + default: + pr_warn("%s: No DMA for PHB#%d (type %d)\n", + __func__, phb->hose->global_number, phb->type); + } +} + #ifdef CONFIG_PCI_IOV static resource_size_t pnv_pci_iov_resource_alignment(struct pci_dev *pdev, int resno) @@ -3381,6 +3334,7 @@ static const struct pci_controller_ops pnv_pci_ioda_controller_ops = { #endif .enable_device_hook = pnv_pci_enable_device_hook, .window_alignment = pnv_pci_window_alignment, + .setup_bridge = pnv_pci_setup_bridge, .reset_secondary_bus = pnv_pci_reset_secondary_bus, .dma_set_mask = pnv_pci_ioda_dma_set_mask, .dma_get_required_mask = pnv_pci_ioda_dma_get_required_mask, -- cgit v1.2.3 From 63803c39c858e4c9156601c332b7a9ddffdbd37f Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Fri, 20 May 2016 16:41:32 +1000 Subject: powerpc/powernv: Setup PE for root bus There is no parent bridge for root bus, meaning pcibios_setup_bridge() isn't invoked for root bus. The PE for root bus is the ancestor of other PEs in PELTV. It means we need PE for root bus populated before all others. This populates the PE for root bus in pcibios_setup_bridge() path if it's not populated yet. The PE number next to the reserved one is used as the PE# to avoid holes in continuous M64 space. Signed-off-by: Gavin Shan Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/pci-ioda.c | 49 ++++++++++++++++++++++++------- arch/powerpc/platforms/powernv/pci.h | 2 ++ 2 files changed, 41 insertions(+), 10 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 062f7fbddccc..74183ff95228 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -194,14 +194,14 @@ static int pnv_ioda2_init_m64(struct pnv_phb *phb) set_bit(phb->ioda.m64_bar_idx, &phb->ioda.m64_bar_alloc); /* - * Strip off the segment used by the reserved PE, which is - * expected to be 0 or last one of PE capability. + * Exclude the segments for reserved and root bus PE, which + * are first or last two PEs. */ r = &phb->hose->mem_resources[1]; if (phb->ioda.reserved_pe_idx == 0) - r->start += phb->ioda.m64_segsize; + r->start += (2 * phb->ioda.m64_segsize); else if (phb->ioda.reserved_pe_idx == (phb->ioda.total_pe_num - 1)) - r->end -= phb->ioda.m64_segsize; + r->end -= (2 * phb->ioda.m64_segsize); else pr_warn(" Cannot strip M64 segment for reserved PE#%d\n", phb->ioda.reserved_pe_idx); @@ -281,14 +281,14 @@ static int pnv_ioda1_init_m64(struct pnv_phb *phb) } /* - * Exclude the segment used by the reserved PE, which - * is expected to be 0 or last supported PE#. + * Exclude the segments for reserved and root bus PE, which + * are first or last two PEs. */ r = &phb->hose->mem_resources[1]; if (phb->ioda.reserved_pe_idx == 0) - r->start += phb->ioda.m64_segsize; + r->start += (2 * phb->ioda.m64_segsize); else if (phb->ioda.reserved_pe_idx == (phb->ioda.total_pe_num - 1)) - r->end -= phb->ioda.m64_segsize; + r->end -= (2 * phb->ioda.m64_segsize); else WARN(1, "Wrong reserved PE#%d on PHB#%d\n", phb->ioda.reserved_pe_idx, phb->hose->global_number); @@ -1062,8 +1062,13 @@ static struct pnv_ioda_pe *pnv_ioda_setup_bus_PE(struct pci_bus *bus, bool all) return NULL; } + /* PE number for root bus should have been reserved */ + if (pci_is_root_bus(bus) && + phb->ioda.root_pe_idx != IODA_INVALID_PE) + pe = &phb->ioda.pe_array[phb->ioda.root_pe_idx]; + /* Check if PE is determined by M64 */ - if (phb->pick_m64_pe) + if (!pe && phb->pick_m64_pe) pe = phb->pick_m64_pe(bus, all); /* The PE number isn't pinned by M64 */ @@ -3226,6 +3231,15 @@ static void pnv_pci_setup_bridge(struct pci_bus *bus, unsigned long type) struct pnv_ioda_pe *pe; bool all = (pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE); + /* The PE for root bus should be realized before any one else */ + if (!phb->ioda.root_pe_populated) { + pe = pnv_ioda_setup_bus_PE(phb->hose->bus, false); + if (pe) { + phb->ioda.root_pe_idx = pe->pe_number; + phb->ioda.root_pe_populated = true; + } + } + /* Don't assign PE to PCI bus, which doesn't have subordinate devices */ if (list_empty(&bus->devices)) return; @@ -3499,7 +3513,22 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, phb->ioda.dma32_segmap[segno] = IODA_INVALID_PE; } phb->ioda.pe_array = aux + pemap_off; - set_bit(phb->ioda.reserved_pe_idx, phb->ioda.pe_alloc); + + /* + * Choose PE number for root bus, which shouldn't have + * M64 resources consumed by its child devices. To pick + * the PE number adjacent to the reserved one if possible. + */ + pnv_ioda_reserve_pe(phb, phb->ioda.reserved_pe_idx); + if (phb->ioda.reserved_pe_idx == 0) { + phb->ioda.root_pe_idx = 1; + pnv_ioda_reserve_pe(phb, phb->ioda.root_pe_idx); + } else if (phb->ioda.reserved_pe_idx == (phb->ioda.total_pe_num - 1)) { + phb->ioda.root_pe_idx = phb->ioda.reserved_pe_idx - 1; + pnv_ioda_reserve_pe(phb, phb->ioda.root_pe_idx); + } else { + phb->ioda.root_pe_idx = IODA_INVALID_PE; + } INIT_LIST_HEAD(&phb->ioda.pe_list); mutex_init(&phb->ioda.pe_list_mutex); diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index de56ed2046b4..8927e5d1c09e 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h @@ -110,6 +110,8 @@ struct pnv_phb { /* Global bridge info */ unsigned int total_pe_num; unsigned int reserved_pe_idx; + unsigned int root_pe_idx; + bool root_pe_populated; /* 32-bit MMIO window */ unsigned int m32_size; -- cgit v1.2.3 From 40e2a47e62dabad64f0d2955ec17064225305a52 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Fri, 20 May 2016 16:41:33 +1000 Subject: powerpc/powernv: Extend PCI bridge resources The PCI slots are associated with root port or downstream ports of the PCIe switch connected to root port. When adapter is hot added to the PCI slot, it usually requests more IO or memory resource from the directly connected parent bridge (port) and update the bridge's windows accordingly. The resource windows of upstream bridges can't be updated automatically. It possibly leads to unbalanced resource across the bridges: The window of downstream bridge is overruning that of upstream bridge. The IO or MMIO path won't work. This resolves the above issue by extending bridge windows of root port and upstream port of the PCIe switch connected to the root port to PHB's windows. The windows of root port and bridge behind that are extended to the PHB's windows to accomodate the PCI hotplug happening in future. The PHB's 64KB 32-bits MSI region is included in bridge's M32 windows (in hardware) though it's excluded in the corresponding resource, as the bridge's M32 windows have 1MB as their minimal alignment. We observed EEH error during system boot when the MSI region is included in bridge's M32 window. This excludes top 1MB (including 64KB 32-bits MSI region) region from bridge's M32 windows when extending them. Signed-off-by: Gavin Shan Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/pci-ioda.c | 61 +++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 74183ff95228..f647c8d083a8 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -3223,6 +3223,64 @@ static resource_size_t pnv_pci_window_alignment(struct pci_bus *bus, return phb->ioda.io_segsize; } +/* + * We are updating root port or the upstream port of the + * bridge behind the root port with PHB's windows in order + * to accommodate the changes on required resources during + * PCI (slot) hotplug, which is connected to either root + * port or the downstream ports of PCIe switch behind the + * root port. + */ +static void pnv_pci_fixup_bridge_resources(struct pci_bus *bus, + unsigned long type) +{ + struct pci_controller *hose = pci_bus_to_host(bus); + struct pnv_phb *phb = hose->private_data; + struct pci_dev *bridge = bus->self; + struct resource *r, *w; + bool msi_region = false; + int i; + + /* Check if we need apply fixup to the bridge's windows */ + if (!pci_is_root_bus(bridge->bus) && + !pci_is_root_bus(bridge->bus->self->bus)) + return; + + /* Fixup the resources */ + for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) { + r = &bridge->resource[PCI_BRIDGE_RESOURCES + i]; + if (!r->flags || !r->parent) + continue; + + w = NULL; + if (r->flags & type & IORESOURCE_IO) + w = &hose->io_resource; + else if (pnv_pci_is_mem_pref_64(r->flags) && + (type & IORESOURCE_PREFETCH) && + phb->ioda.m64_segsize) + w = &hose->mem_resources[1]; + else if (r->flags & type & IORESOURCE_MEM) { + w = &hose->mem_resources[0]; + msi_region = true; + } + + r->start = w->start; + r->end = w->end; + + /* The 64KB 32-bits MSI region shouldn't be included in + * the 32-bits bridge window. Otherwise, we can see strange + * issues. One of them is EEH error observed on Garrison. + * + * Exclude top 1MB region which is the minimal alignment of + * 32-bits bridge window. + */ + if (msi_region) { + r->end += 0x10000; + r->end -= 0x100000; + } + } +} + static void pnv_pci_setup_bridge(struct pci_bus *bus, unsigned long type) { struct pci_controller *hose = pci_bus_to_host(bus); @@ -3231,6 +3289,9 @@ static void pnv_pci_setup_bridge(struct pci_bus *bus, unsigned long type) struct pnv_ioda_pe *pe; bool all = (pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE); + /* Extend bridge's windows if necessary */ + pnv_pci_fixup_bridge_resources(bus, type); + /* The PE for root bus should be realized before any one else */ if (!phb->ioda.root_pe_populated) { pe = pnv_ioda_setup_bus_PE(phb->hose->bus, false); -- cgit v1.2.3 From 93e01a5039915048e6b0be559ca4bfba1cce6f71 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Fri, 20 May 2016 16:41:34 +1000 Subject: powerpc/powernv: Make pnv_ioda_deconfigure_pe() visible pnv_ioda_deconfigure_pe() is visible only when CONFIG_PCI_IOV is enabled. The function will be used to tear down PE's associated mapping in PCI hotplug path that doesn't depend on CONFIG_PCI_IOV. This makes pnv_ioda_deconfigure_pe() visible and not depend on CONFIG_PCI_IOV. Signed-off-by: Gavin Shan Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/pci-ioda.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index f647c8d083a8..58ca7df068eb 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -712,7 +712,6 @@ static int pnv_ioda_set_peltv(struct pnv_phb *phb, return 0; } -#ifdef CONFIG_PCI_IOV static int pnv_ioda_deconfigure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe) { struct pci_dev *parent; @@ -747,9 +746,11 @@ static int pnv_ioda_deconfigure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe) } rid_end = pe->rid + (count << 8); } else { +#ifdef CONFIG_PCI_IOV if (pe->flags & PNV_IODA_PE_VF) parent = pe->parent_dev; else +#endif parent = pe->pdev->bus->self; bcomp = OpalPciBusAll; dcomp = OPAL_COMPARE_RID_DEVICE_NUMBER; @@ -787,11 +788,12 @@ static int pnv_ioda_deconfigure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe) pe->pbus = NULL; pe->pdev = NULL; +#ifdef CONFIG_PCI_IOV pe->parent_dev = NULL; +#endif return 0; } -#endif /* CONFIG_PCI_IOV */ static int pnv_ioda_configure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe) { -- cgit v1.2.3 From c5f7700bbd2e6b598738d85a6c46887b8c8fb6c5 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Fri, 20 May 2016 16:41:35 +1000 Subject: powerpc/powernv: Dynamically release PE This supports releasing PEs dynamically. A reference count is introduced to PE representing number of PCI devices associated with the PE. The reference count is increased when PCI device joins the PE and decreased when PCI device leaves the PE in pnv_pci_release_device(). When the count becomes zero, the PE and its consumed resources are released. Note that the count is accessed concurrently. So a counter with "int" type is enough here. In order to release the sources consumed by the PE, couple of helper functions are introduced as below: * pnv_pci_ioda1_unset_window() - Unset IODA1 DMA32 window * pnv_pci_ioda1_release_dma_pe() - Release IODA1 DMA32 segments * pnv_pci_ioda2_release_dma_pe() - Release IODA2 DMA resource * pnv_ioda_release_pe_seg() - Unmap IO/M32/M64 segments Signed-off-by: Gavin Shan Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/pci-ioda.c | 174 ++++++++++++++++++++++++++++++ arch/powerpc/platforms/powernv/pci.h | 1 + 2 files changed, 175 insertions(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 58ca7df068eb..4e0b2fc06694 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -1033,6 +1033,7 @@ static void pnv_ioda_setup_same_PE(struct pci_bus *bus, struct pnv_ioda_pe *pe) if (pdn->pe_number != IODA_INVALID_PE) continue; + pe->device_count++; pdn->pcidev = dev; pdn->pe_number = pe->pe_number; if ((pe->flags & PNV_IODA_PE_BUS_ALL) && dev->subordinate) @@ -3394,6 +3395,178 @@ static bool pnv_pci_enable_device_hook(struct pci_dev *dev) return true; } +static long pnv_pci_ioda1_unset_window(struct iommu_table_group *table_group, + int num) +{ + struct pnv_ioda_pe *pe = container_of(table_group, + struct pnv_ioda_pe, table_group); + struct pnv_phb *phb = pe->phb; + unsigned int idx; + long rc; + + pe_info(pe, "Removing DMA window #%d\n", num); + for (idx = 0; idx < phb->ioda.dma32_count; idx++) { + if (phb->ioda.dma32_segmap[idx] != pe->pe_number) + continue; + + rc = opal_pci_map_pe_dma_window(phb->opal_id, pe->pe_number, + idx, 0, 0ul, 0ul, 0ul); + if (rc != OPAL_SUCCESS) { + pe_warn(pe, "Failure %ld unmapping DMA32 segment#%d\n", + rc, idx); + return rc; + } + + phb->ioda.dma32_segmap[idx] = IODA_INVALID_PE; + } + + pnv_pci_unlink_table_and_group(table_group->tables[num], table_group); + return OPAL_SUCCESS; +} + +static void pnv_pci_ioda1_release_pe_dma(struct pnv_ioda_pe *pe) +{ + unsigned int weight = pnv_pci_ioda_pe_dma_weight(pe); + struct iommu_table *tbl = pe->table_group.tables[0]; + int64_t rc; + + if (!weight) + return; + + rc = pnv_pci_ioda1_unset_window(&pe->table_group, 0); + if (rc != OPAL_SUCCESS) + return; + + pnv_pci_ioda1_tce_invalidate(tbl, tbl->it_offset, tbl->it_size, false); + if (pe->table_group.group) { + iommu_group_put(pe->table_group.group); + WARN_ON(pe->table_group.group); + } + + free_pages(tbl->it_base, get_order(tbl->it_size << 3)); + iommu_free_table(tbl, "pnv"); +} + +static void pnv_pci_ioda2_release_pe_dma(struct pnv_ioda_pe *pe) +{ + struct iommu_table *tbl = pe->table_group.tables[0]; + unsigned int weight = pnv_pci_ioda_pe_dma_weight(pe); +#ifdef CONFIG_IOMMU_API + int64_t rc; +#endif + + if (!weight) + return; + +#ifdef CONFIG_IOMMU_API + rc = pnv_pci_ioda2_unset_window(&pe->table_group, 0); + if (rc) + pe_warn(pe, "OPAL error %ld release DMA window\n", rc); +#endif + + pnv_pci_ioda2_set_bypass(pe, false); + if (pe->table_group.group) { + iommu_group_put(pe->table_group.group); + WARN_ON(pe->table_group.group); + } + + pnv_pci_ioda2_table_free_pages(tbl); + iommu_free_table(tbl, "pnv"); +} + +static void pnv_ioda_free_pe_seg(struct pnv_ioda_pe *pe, + unsigned short win, + unsigned int *map) +{ + struct pnv_phb *phb = pe->phb; + int idx; + int64_t rc; + + for (idx = 0; idx < phb->ioda.total_pe_num; idx++) { + if (map[idx] != pe->pe_number) + continue; + + if (win == OPAL_M64_WINDOW_TYPE) + rc = opal_pci_map_pe_mmio_window(phb->opal_id, + phb->ioda.reserved_pe_idx, win, + idx / PNV_IODA1_M64_SEGS, + idx % PNV_IODA1_M64_SEGS); + else + rc = opal_pci_map_pe_mmio_window(phb->opal_id, + phb->ioda.reserved_pe_idx, win, 0, idx); + + if (rc != OPAL_SUCCESS) + pe_warn(pe, "Error %ld unmapping (%d) segment#%d\n", + rc, win, idx); + + map[idx] = IODA_INVALID_PE; + } +} + +static void pnv_ioda_release_pe_seg(struct pnv_ioda_pe *pe) +{ + struct pnv_phb *phb = pe->phb; + + if (phb->type == PNV_PHB_IODA1) { + pnv_ioda_free_pe_seg(pe, OPAL_IO_WINDOW_TYPE, + phb->ioda.io_segmap); + pnv_ioda_free_pe_seg(pe, OPAL_M32_WINDOW_TYPE, + phb->ioda.m32_segmap); + pnv_ioda_free_pe_seg(pe, OPAL_M64_WINDOW_TYPE, + phb->ioda.m64_segmap); + } else if (phb->type == PNV_PHB_IODA2) { + pnv_ioda_free_pe_seg(pe, OPAL_M32_WINDOW_TYPE, + phb->ioda.m32_segmap); + } +} + +static void pnv_ioda_release_pe(struct pnv_ioda_pe *pe) +{ + struct pnv_phb *phb = pe->phb; + struct pnv_ioda_pe *slave, *tmp; + + /* Release slave PEs in compound PE */ + if (pe->flags & PNV_IODA_PE_MASTER) { + list_for_each_entry_safe(slave, tmp, &pe->slaves, list) + pnv_ioda_release_pe(slave); + } + + list_del(&pe->list); + switch (phb->type) { + case PNV_PHB_IODA1: + pnv_pci_ioda1_release_pe_dma(pe); + break; + case PNV_PHB_IODA2: + pnv_pci_ioda2_release_pe_dma(pe); + break; + default: + WARN_ON(1); + } + + pnv_ioda_release_pe_seg(pe); + pnv_ioda_deconfigure_pe(pe->phb, pe); + pnv_ioda_free_pe(pe); +} + +static void pnv_pci_release_device(struct pci_dev *pdev) +{ + struct pci_controller *hose = pci_bus_to_host(pdev->bus); + struct pnv_phb *phb = hose->private_data; + struct pci_dn *pdn = pci_get_pdn(pdev); + struct pnv_ioda_pe *pe; + + if (pdev->is_virtfn) + return; + + if (!pdn || pdn->pe_number == IODA_INVALID_PE) + return; + + pe = &phb->ioda.pe_array[pdn->pe_number]; + WARN_ON(--pe->device_count < 0); + if (pe->device_count == 0) + pnv_ioda_release_pe(pe); +} + static void pnv_pci_ioda_shutdown(struct pci_controller *hose) { struct pnv_phb *phb = hose->private_data; @@ -3410,6 +3583,7 @@ static const struct pci_controller_ops pnv_pci_ioda_controller_ops = { .teardown_msi_irqs = pnv_teardown_msi_irqs, #endif .enable_device_hook = pnv_pci_enable_device_hook, + .release_device = pnv_pci_release_device, .window_alignment = pnv_pci_window_alignment, .setup_bridge = pnv_pci_setup_bridge, .reset_secondary_bus = pnv_pci_reset_secondary_bus, diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index 8927e5d1c09e..3a97990a4dad 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h @@ -30,6 +30,7 @@ struct pnv_phb; struct pnv_ioda_pe { unsigned long flags; struct pnv_phb *phb; + int device_count; /* A PE can be associated with a single device or an * entire bus (& children). In the former case, pdev -- cgit v1.2.3 From 8cc7581cdb84a232468c41bc417183a423dfbb07 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Fri, 20 May 2016 16:41:37 +1000 Subject: powerpc/pci: Delay populating pdn The pdn (struct pci_dn) instances are allocated from memblock or bootmem when creating PCI controller (hoses) in setup_arch(). PCI hotplug, which will be supported by proceeding patches, releases PCI device nodes and their corresponding pdn on unplugging event. The memory chunks for pdn instances allocated from memblock or bootmem are hard to reused after being released. This delays creating pdn by pci_devs_phb_init() from setup_arch() to core_initcall() so that they are allocated from slab. The memory consumed by pdn can be released to system without problem during PCI unplugging time. It indicates that pci_dn is unavailable in setup_arch() and the the fixup on pdn (like AGP's) can't be carried out that time. We have to do that in pcibios_root_bridge_prepare() on maple/pasemi/powermac platforms where/when the pdn is available. pcibios_root_bridge_prepare is called from subsys_initcall() which is executed after core_initcall() so the code flow does not change. At the mean while, the EEH device is created when pdn is populated, meaning pdn and EEH device have same life cycle. In turn, we needn't call eeh_dev_init() to create EEH device explicitly. Signed-off-by: Gavin Shan Reviewed-by: Alexey Kardashevskiy Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/eeh.h | 2 +- arch/powerpc/include/asm/ppc-pci.h | 2 -- arch/powerpc/kernel/eeh_dev.c | 17 +++------------ arch/powerpc/kernel/pci_dn.c | 23 ++++++++++++++++---- arch/powerpc/platforms/maple/pci.c | 34 ++++++++++++++++++------------ arch/powerpc/platforms/pasemi/pci.c | 3 --- arch/powerpc/platforms/powermac/pci.c | 38 +++++++++++++++++++++------------- arch/powerpc/platforms/powernv/pci.c | 3 --- arch/powerpc/platforms/pseries/setup.c | 6 +----- 9 files changed, 69 insertions(+), 59 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index 7d34f3d3ca0e..8e37b71674f4 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h @@ -274,7 +274,7 @@ void eeh_pe_restore_bars(struct eeh_pe *pe); const char *eeh_pe_loc_get(struct eeh_pe *pe); struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe); -void *eeh_dev_init(struct pci_dn *pdn, void *data); +struct eeh_dev *eeh_dev_init(struct pci_dn *pdn); void eeh_dev_phb_init_dynamic(struct pci_controller *phb); int eeh_init(void); int __init eeh_ops_register(struct eeh_ops *ops); diff --git a/arch/powerpc/include/asm/ppc-pci.h b/arch/powerpc/include/asm/ppc-pci.h index 8753e4eb9ab5..0f73de069f19 100644 --- a/arch/powerpc/include/asm/ppc-pci.h +++ b/arch/powerpc/include/asm/ppc-pci.h @@ -39,8 +39,6 @@ void *pci_traverse_device_nodes(struct device_node *start, void *traverse_pci_dn(struct pci_dn *root, void *(*fn)(struct pci_dn *, void *), void *data); - -extern void pci_devs_phb_init(void); extern void pci_devs_phb_init_dynamic(struct pci_controller *phb); /* From rtas_pci.h */ diff --git a/arch/powerpc/kernel/eeh_dev.c b/arch/powerpc/kernel/eeh_dev.c index 7815095fe3d8..d6b2ca70d14d 100644 --- a/arch/powerpc/kernel/eeh_dev.c +++ b/arch/powerpc/kernel/eeh_dev.c @@ -44,14 +44,13 @@ /** * eeh_dev_init - Create EEH device according to OF node * @pdn: PCI device node - * @data: PHB * * It will create EEH device according to the given OF node. The function * might be called by PCI emunation, DR, PHB hotplug. */ -void *eeh_dev_init(struct pci_dn *pdn, void *data) +struct eeh_dev *eeh_dev_init(struct pci_dn *pdn) { - struct pci_controller *phb = data; + struct pci_controller *phb = pdn->phb; struct eeh_dev *edev; /* Allocate EEH device */ @@ -69,7 +68,7 @@ void *eeh_dev_init(struct pci_dn *pdn, void *data) INIT_LIST_HEAD(&edev->list); INIT_LIST_HEAD(&edev->rmv_list); - return NULL; + return edev; } /** @@ -81,16 +80,8 @@ void *eeh_dev_init(struct pci_dn *pdn, void *data) */ void eeh_dev_phb_init_dynamic(struct pci_controller *phb) { - struct pci_dn *root = phb->pci_data; - /* EEH PE for PHB */ eeh_phb_pe_create(phb); - - /* EEH device for PHB */ - eeh_dev_init(root, phb); - - /* EEH devices for children OF nodes */ - traverse_pci_dn(root, eeh_dev_init, phb); } /** @@ -106,8 +97,6 @@ static int __init eeh_dev_phb_init(void) list_for_each_entry_safe(phb, tmp, &hose_list, list_node) eeh_dev_phb_init_dynamic(phb); - pr_info("EEH: devices created\n"); - return 0; } diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c index afeda26c2ebc..bfe60a1e70d9 100644 --- a/arch/powerpc/kernel/pci_dn.c +++ b/arch/powerpc/kernel/pci_dn.c @@ -212,8 +212,7 @@ struct pci_dn *add_dev_pci_data(struct pci_dev *pdev) #ifdef CONFIG_EEH /* Create the EEH device for the VF */ - eeh_dev_init(pdn, pci_bus_to_host(pdev->bus)); - edev = pdn_to_eeh_dev(pdn); + edev = eeh_dev_init(pdn); BUG_ON(!edev); edev->physfn = pdev; #endif /* CONFIG_EEH */ @@ -295,8 +294,11 @@ struct pci_dn *pci_add_device_node_info(struct pci_controller *hose, const __be32 *regs; struct device_node *parent; struct pci_dn *pdn; +#ifdef CONFIG_EEH + struct eeh_dev *edev; +#endif - pdn = zalloc_maybe_bootmem(sizeof(*pdn), GFP_KERNEL); + pdn = kzalloc(sizeof(*pdn), GFP_KERNEL); if (pdn == NULL) return NULL; dn->data = pdn; @@ -325,6 +327,15 @@ struct pci_dn *pci_add_device_node_info(struct pci_controller *hose, /* Extended config space */ pdn->pci_ext_config_space = (type && of_read_number(type, 1) == 1); + /* Create EEH device */ +#ifdef CONFIG_EEH + edev = eeh_dev_init(pdn); + if (!edev) { + kfree(pdn); + return NULL; + } +#endif + /* Attach to parent node */ INIT_LIST_HEAD(&pdn->child_list); INIT_LIST_HEAD(&pdn->list); @@ -510,15 +521,19 @@ void pci_devs_phb_init_dynamic(struct pci_controller *phb) * pci device found underneath. This routine runs once, * early in the boot sequence. */ -void __init pci_devs_phb_init(void) +static int __init pci_devs_phb_init(void) { struct pci_controller *phb, *tmp; /* This must be done first so the device nodes have valid pci info! */ list_for_each_entry_safe(phb, tmp, &hose_list, list_node) pci_devs_phb_init_dynamic(phb); + + return 0; } +core_initcall(pci_devs_phb_init); + static void pci_dev_pdn_setup(struct pci_dev *pdev) { struct pci_dn *pdn; diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c index a923230e575b..a2f89e6326ce 100644 --- a/arch/powerpc/platforms/maple/pci.c +++ b/arch/powerpc/platforms/maple/pci.c @@ -568,6 +568,26 @@ void maple_pci_irq_fixup(struct pci_dev *dev) DBG(" <- maple_pci_irq_fixup\n"); } +static int maple_pci_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + struct pci_controller *hose = pci_bus_to_host(bridge->bus); + struct device_node *np, *child; + + if (hose != u3_agp) + return 0; + + /* Fixup the PCI<->OF mapping for U3 AGP due to bus renumbering. We + * assume there is no P2P bridge on the AGP bus, which should be a + * safe assumptions hopefully. + */ + np = hose->dn; + PCI_DN(np)->busno = 0xf0; + for_each_child_of_node(np, child) + PCI_DN(child)->busno = 0xf0; + + return 0; +} + void __init maple_pci_init(void) { struct device_node *np, *root; @@ -605,19 +625,7 @@ void __init maple_pci_init(void) if (ht && maple_add_bridge(ht) != 0) of_node_put(ht); - /* Setup the linkage between OF nodes and PHBs */ - pci_devs_phb_init(); - - /* Fixup the PCI<->OF mapping for U3 AGP due to bus renumbering. We - * assume there is no P2P bridge on the AGP bus, which should be a - * safe assumptions hopefully. - */ - if (u3_agp) { - struct device_node *np = u3_agp->dn; - PCI_DN(np)->busno = 0xf0; - for (np = np->child; np; np = np->sibling) - PCI_DN(np)->busno = 0xf0; - } + ppc_md.pcibios_root_bridge_prepare = maple_pci_root_bridge_prepare; /* Tell pci.c to not change any resource allocations. */ pci_add_flags(PCI_PROBE_ONLY); diff --git a/arch/powerpc/platforms/pasemi/pci.c b/arch/powerpc/platforms/pasemi/pci.c index f3a68a0fef23..10c4e8fc6ea9 100644 --- a/arch/powerpc/platforms/pasemi/pci.c +++ b/arch/powerpc/platforms/pasemi/pci.c @@ -229,9 +229,6 @@ void __init pas_pci_init(void) of_node_get(np); of_node_put(root); - - /* Setup the linkage between OF nodes and PHBs */ - pci_devs_phb_init(); } void __iomem *pasemi_pci_getcfgaddr(struct pci_dev *dev, int offset) diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index 59ab16fa600f..6e06c3be2e9a 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c @@ -878,6 +878,29 @@ void pmac_pci_irq_fixup(struct pci_dev *dev) #endif /* CONFIG_PPC32 */ } +#ifdef CONFIG_PPC64 +static int pmac_pci_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + struct pci_controller *hose = pci_bus_to_host(bridge->bus); + struct device_node *np, *child; + + if (hose != u3_agp) + return 0; + + /* Fixup the PCI<->OF mapping for U3 AGP due to bus renumbering. We + * assume there is no P2P bridge on the AGP bus, which should be a + * safe assumptions for now. We should do something better in the + * future though + */ + np = hose->dn; + PCI_DN(np)->busno = 0xf0; + for_each_child_of_node(np, child) + PCI_DN(child)->busno = 0xf0; + + return 0; +} +#endif /* CONFIG_PPC64 */ + void __init pmac_pci_init(void) { struct device_node *np, *root; @@ -914,20 +937,7 @@ void __init pmac_pci_init(void) if (ht && pmac_add_bridge(ht) != 0) of_node_put(ht); - /* Setup the linkage between OF nodes and PHBs */ - pci_devs_phb_init(); - - /* Fixup the PCI<->OF mapping for U3 AGP due to bus renumbering. We - * assume there is no P2P bridge on the AGP bus, which should be a - * safe assumptions for now. We should do something better in the - * future though - */ - if (u3_agp) { - struct device_node *np = u3_agp->dn; - PCI_DN(np)->busno = 0xf0; - for (np = np->child; np; np = np->sibling) - PCI_DN(np)->busno = 0xf0; - } + ppc_md.pcibios_root_bridge_prepare = pmac_pci_root_bridge_prepare; /* pmac_check_ht_link(); */ #else /* CONFIG_PPC64 */ diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index b1ee6314f946..0f1b8bf953e1 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c @@ -816,9 +816,6 @@ void __init pnv_pci_init(void) for_each_compatible_node(np, NULL, "ibm,ioda2-npu-phb") pnv_pci_init_npu_phb(np); - /* Setup the linkage between OF nodes and PHBs */ - pci_devs_phb_init(); - /* Configure IOMMU DMA hooks */ set_pci_dma_ops(&dma_iommu_ops); } diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 34668f9bc57b..e61e9b986e21 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -195,11 +195,8 @@ static int pci_dn_reconfig_notifier(struct notifier_block *nb, unsigned long act case OF_RECONFIG_ATTACH_NODE: parent = of_get_parent(np); pdn = parent ? PCI_DN(parent) : NULL; - if (pdn) { - /* Create pdn and EEH device */ + if (pdn) pci_add_device_node_info(pdn->phb, np); - eeh_dev_init(PCI_DN(np), pdn->phb); - } of_node_put(parent); break; @@ -422,7 +419,6 @@ static void __init find_and_init_phbs(void) } of_node_put(root); - pci_devs_phb_init(); /* * PCI_PROBE_ONLY and PCI_REASSIGN_ALL_BUS can be set via properties -- cgit v1.2.3 From ebe2253127395b884e1ace5fb48598e1eb4de689 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Fri, 20 May 2016 16:41:38 +1000 Subject: powerpc/powernv: Support PCI slot ID The reset and poll functionality from (OPAL) firmware supports PHB and PCI slot at same time. They are identified by ID. This supports PCI slot ID by: * Rename the argument name for opal_pci_reset() and opal_pci_poll() accordingly * Rename pnv_eeh_phb_poll() to pnv_eeh_poll() and adjust its argument name. * One macro is added to produce PCI slot ID. Signed-off-by: Gavin Shan Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/opal.h | 4 ++-- arch/powerpc/include/asm/pnv-pci.h | 4 ++++ arch/powerpc/platforms/powernv/eeh-powernv.c | 8 ++++---- 3 files changed, 10 insertions(+), 6 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index 9d86c6651716..348132c00601 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h @@ -131,7 +131,7 @@ int64_t opal_pci_map_pe_dma_window(uint64_t phb_id, uint16_t pe_number, uint16_t int64_t opal_pci_map_pe_dma_window_real(uint64_t phb_id, uint16_t pe_number, uint16_t dma_window_number, uint64_t pci_start_addr, uint64_t pci_mem_size); -int64_t opal_pci_reset(uint64_t phb_id, uint8_t reset_scope, uint8_t assert_state); +int64_t opal_pci_reset(uint64_t id, uint8_t reset_scope, uint8_t assert_state); int64_t opal_pci_get_hub_diag_data(uint64_t hub_id, void *diag_buffer, uint64_t diag_buffer_len); @@ -148,7 +148,7 @@ int64_t opal_get_dpo_status(__be64 *dpo_timeout); int64_t opal_set_system_attention_led(uint8_t led_action); int64_t opal_pci_next_error(uint64_t phb_id, __be64 *first_frozen_pe, __be16 *pci_error_type, __be16 *severity); -int64_t opal_pci_poll(uint64_t phb_id); +int64_t opal_pci_poll(uint64_t id); int64_t opal_return_cpu(void); int64_t opal_check_token(uint64_t token); int64_t opal_reinit_cpus(uint64_t flags); diff --git a/arch/powerpc/include/asm/pnv-pci.h b/arch/powerpc/include/asm/pnv-pci.h index 6f77f71ee964..c607902c5477 100644 --- a/arch/powerpc/include/asm/pnv-pci.h +++ b/arch/powerpc/include/asm/pnv-pci.h @@ -13,6 +13,10 @@ #include #include +#define PCI_SLOT_ID_PREFIX 0x8000000000000000 +#define PCI_SLOT_ID(phb_id, bdfn) \ + (PCI_SLOT_ID_PREFIX | ((uint64_t)(bdfn) << 16) | (phb_id)) + int pnv_phb_to_cxl_mode(struct pci_dev *dev, uint64_t mode); int pnv_cxl_ioda_msi_setup(struct pci_dev *dev, unsigned int hwirq, unsigned int virq); diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index 9226df11bf39..26bb60b1d66c 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c @@ -717,12 +717,12 @@ static int pnv_eeh_get_state(struct eeh_pe *pe, int *delay) return ret; } -static s64 pnv_eeh_phb_poll(struct pnv_phb *phb) +static s64 pnv_eeh_poll(unsigned long id) { s64 rc = OPAL_HARDWARE; while (1) { - rc = opal_pci_poll(phb->opal_id); + rc = opal_pci_poll(id); if (rc <= 0) break; @@ -762,7 +762,7 @@ int pnv_eeh_phb_reset(struct pci_controller *hose, int option) * reset followed by hot reset on root bus. So we also * need the PCI bus settlement delay. */ - rc = pnv_eeh_phb_poll(phb); + rc = pnv_eeh_poll(phb->opal_id); if (option == EEH_RESET_DEACTIVATE) { if (system_state < SYSTEM_RUNNING) udelay(1000 * EEH_PE_RST_SETTLE_TIME); @@ -805,7 +805,7 @@ static int pnv_eeh_root_reset(struct pci_controller *hose, int option) goto out; /* Poll state of the PHB until the request is done */ - rc = pnv_eeh_phb_poll(phb); + rc = pnv_eeh_poll(phb->opal_id); if (option == EEH_RESET_DEACTIVATE) msleep(EEH_PE_RST_SETTLE_TIME); out: -- cgit v1.2.3 From 9c0e1ecbe19540c23f941c1fdb59e79b16c17d55 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Fri, 20 May 2016 16:41:39 +1000 Subject: powerpc/powernv: Use PCI slot reset infrastructure The (OPAL) firmware might provide the PCI slot reset capability which is identified by property "ibm,reset-by-firmware" on the PCI slot associated device node. This routes the reset request to firmware if "ibm,reset-by-firmware" exists in the PCI slot device node. Otherwise, the reset is done inside kernel as before. Signed-off-by: Gavin Shan Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/eeh-powernv.c | 41 +++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index 26bb60b1d66c..86544ea85dc3 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "powernv.h" #include "pci.h" @@ -815,7 +816,7 @@ out: return 0; } -static int pnv_eeh_bridge_reset(struct pci_dev *dev, int option) +static int __pnv_eeh_bridge_reset(struct pci_dev *dev, int option) { struct pci_dn *pdn = pci_get_pdn_by_devfn(dev->bus, dev->devfn); struct eeh_dev *edev = pdn_to_eeh_dev(pdn); @@ -866,6 +867,44 @@ static int pnv_eeh_bridge_reset(struct pci_dev *dev, int option) return 0; } +static int pnv_eeh_bridge_reset(struct pci_dev *pdev, int option) +{ + struct pci_controller *hose = pci_bus_to_host(pdev->bus); + struct pnv_phb *phb = hose->private_data; + struct device_node *dn = pci_device_to_OF_node(pdev); + uint64_t id = PCI_SLOT_ID(phb->opal_id, + (pdev->bus->number << 8) | pdev->devfn); + uint8_t scope; + int64_t rc; + + /* Hot reset to the bus if firmware cannot handle */ + if (!dn || !of_get_property(dn, "ibm,reset-by-firmware", NULL)) + return __pnv_eeh_bridge_reset(pdev, option); + + switch (option) { + case EEH_RESET_FUNDAMENTAL: + scope = OPAL_RESET_PCI_FUNDAMENTAL; + break; + case EEH_RESET_HOT: + scope = OPAL_RESET_PCI_HOT; + break; + case EEH_RESET_DEACTIVATE: + return 0; + default: + dev_dbg(&pdev->dev, "%s: Unsupported reset %d\n", + __func__, option); + return -EINVAL; + } + + rc = opal_pci_reset(id, scope, OPAL_ASSERT_RESET); + if (rc <= OPAL_SUCCESS) + goto out; + + rc = pnv_eeh_poll(id); +out: + return (rc == OPAL_SUCCESS) ? 0 : -EIO; +} + void pnv_pci_reset_secondary_bus(struct pci_dev *dev) { struct pci_controller *hose; -- cgit v1.2.3 From 7e19bf32c8ac977e7702a67d7392a3e0a9644bc8 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Fri, 20 May 2016 16:41:40 +1000 Subject: powerpc/powernv: Introduce pnv_pci_get_slot_id() This introduces pnv_pci_get_slot_id() to get the hotpluggable PCI slot ID from the corresponding device node. It will be used by hotplug driver. Requested-by: Andrew Donnellan Signed-off-by: Gavin Shan Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/pnv-pci.h | 2 ++ arch/powerpc/platforms/powernv/pci.c | 38 ++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/include/asm/pnv-pci.h b/arch/powerpc/include/asm/pnv-pci.h index c607902c5477..810cc9a8169f 100644 --- a/arch/powerpc/include/asm/pnv-pci.h +++ b/arch/powerpc/include/asm/pnv-pci.h @@ -17,6 +17,8 @@ #define PCI_SLOT_ID(phb_id, bdfn) \ (PCI_SLOT_ID_PREFIX | ((uint64_t)(bdfn) << 16) | (phb_id)) +extern int pnv_pci_get_slot_id(struct device_node *np, uint64_t *id); + int pnv_phb_to_cxl_mode(struct pci_dev *dev, uint64_t mode); int pnv_cxl_ioda_msi_setup(struct pci_dev *dev, unsigned int hwirq, unsigned int virq); diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index 0f1b8bf953e1..2607d2923b80 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,43 @@ #include "powernv.h" #include "pci.h" +int pnv_pci_get_slot_id(struct device_node *np, uint64_t *id) +{ + struct device_node *parent = np; + u32 bdfn; + u64 phbid; + int ret; + + ret = of_property_read_u32(np, "reg", &bdfn); + if (ret) + return -ENXIO; + + bdfn = ((bdfn & 0x00ffff00) >> 8); + while ((parent = of_get_parent(parent))) { + if (!PCI_DN(parent)) { + of_node_put(parent); + break; + } + + if (!of_device_is_compatible(parent, "ibm,ioda2-phb")) { + of_node_put(parent); + continue; + } + + ret = of_property_read_u64(parent, "ibm,opal-phbid", &phbid); + if (ret) { + of_node_put(parent); + return -ENXIO; + } + + *id = PCI_SLOT_ID(phbid, bdfn); + return 0; + } + + return -ENODEV; +} +EXPORT_SYMBOL_GPL(pnv_pci_get_slot_id); + #ifdef CONFIG_PCI_MSI int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) { -- cgit v1.2.3 From ea0d856cb26d4d78b9529de49a0f89379224e2f9 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Fri, 20 May 2016 16:41:41 +1000 Subject: powerpc/powernv: Functions to get/set PCI slot state This exports 4 functions, which base on the corresponding OPAL APIs to get/set PCI slot status. Those functions are going to be used by PowerNV PCI hotplug driver: pnv_pci_get_device_tree() opal_get_device_tree() pnv_pci_get_presence_state() opal_pci_get_presence_state() pnv_pci_get_power_state() opal_pci_get_power_state() pnv_pci_set_power_state() opal_pci_set_power_state() Signed-off-by: Gavin Shan Reviewed-by: Alexey Kardashevskiy Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/opal-api.h | 18 +++++- arch/powerpc/include/asm/opal.h | 6 ++ arch/powerpc/include/asm/pnv-pci.h | 6 ++ arch/powerpc/platforms/powernv/opal-wrappers.S | 4 ++ arch/powerpc/platforms/powernv/pci.c | 82 ++++++++++++++++++++++++++ 5 files changed, 115 insertions(+), 1 deletion(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h index cd9371b33f1a..72b5f27cd0b8 100644 --- a/arch/powerpc/include/asm/opal-api.h +++ b/arch/powerpc/include/asm/opal-api.h @@ -158,7 +158,11 @@ #define OPAL_LEDS_SET_INDICATOR 115 #define OPAL_CEC_REBOOT2 116 #define OPAL_CONSOLE_FLUSH 117 -#define OPAL_LAST 117 +#define OPAL_GET_DEVICE_TREE 118 +#define OPAL_PCI_GET_PRESENCE_STATE 119 +#define OPAL_PCI_GET_POWER_STATE 120 +#define OPAL_PCI_SET_POWER_STATE 121 +#define OPAL_LAST 121 /* Device tree flags */ @@ -344,6 +348,18 @@ enum OpalPciResetState { OPAL_ASSERT_RESET = 1 }; +enum OpalPciSlotPresence { + OPAL_PCI_SLOT_EMPTY = 0, + OPAL_PCI_SLOT_PRESENT = 1 +}; + +enum OpalPciSlotPower { + OPAL_PCI_SLOT_POWER_OFF = 0, + OPAL_PCI_SLOT_POWER_ON = 1, + OPAL_PCI_SLOT_OFFLINE = 2, + OPAL_PCI_SLOT_ONLINE = 3 +}; + enum OpalSlotLedType { OPAL_SLOT_LED_TYPE_ID = 0, /* IDENTIFY LED */ OPAL_SLOT_LED_TYPE_FAULT = 1, /* FAULT LED */ diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index 348132c00601..fa71fea3b6ee 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h @@ -209,6 +209,12 @@ int64_t opal_flash_write(uint64_t id, uint64_t offset, uint64_t buf, uint64_t size, uint64_t token); int64_t opal_flash_erase(uint64_t id, uint64_t offset, uint64_t size, uint64_t token); +int64_t opal_get_device_tree(uint32_t phandle, uint64_t buf, uint64_t len); +int64_t opal_pci_get_presence_state(uint64_t id, uint64_t data); +int64_t opal_pci_get_power_state(uint64_t id, uint64_t data); +int64_t opal_pci_set_power_state(uint64_t async_token, uint64_t id, + uint64_t data); +int64_t opal_pci_poll2(uint64_t id, uint64_t data); /* Internal functions */ extern int early_init_dt_scan_opal(unsigned long node, const char *uname, diff --git a/arch/powerpc/include/asm/pnv-pci.h b/arch/powerpc/include/asm/pnv-pci.h index 810cc9a8169f..791db1bbd4b9 100644 --- a/arch/powerpc/include/asm/pnv-pci.h +++ b/arch/powerpc/include/asm/pnv-pci.h @@ -12,12 +12,18 @@ #include #include +#include #define PCI_SLOT_ID_PREFIX 0x8000000000000000 #define PCI_SLOT_ID(phb_id, bdfn) \ (PCI_SLOT_ID_PREFIX | ((uint64_t)(bdfn) << 16) | (phb_id)) extern int pnv_pci_get_slot_id(struct device_node *np, uint64_t *id); +extern int pnv_pci_get_device_tree(uint32_t phandle, void *buf, uint64_t len); +extern int pnv_pci_get_presence_state(uint64_t id, uint8_t *state); +extern int pnv_pci_get_power_state(uint64_t id, uint8_t *state); +extern int pnv_pci_set_power_state(uint64_t id, uint8_t state, + struct opal_msg *msg); int pnv_phb_to_cxl_mode(struct pci_dev *dev, uint64_t mode); int pnv_cxl_ioda_msi_setup(struct pci_dev *dev, unsigned int hwirq, diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S index e45b88a5d7e0..3ea1a8559035 100644 --- a/arch/powerpc/platforms/powernv/opal-wrappers.S +++ b/arch/powerpc/platforms/powernv/opal-wrappers.S @@ -302,3 +302,7 @@ OPAL_CALL(opal_prd_msg, OPAL_PRD_MSG); OPAL_CALL(opal_leds_get_ind, OPAL_LEDS_GET_INDICATOR); OPAL_CALL(opal_leds_set_ind, OPAL_LEDS_SET_INDICATOR); OPAL_CALL(opal_console_flush, OPAL_CONSOLE_FLUSH); +OPAL_CALL(opal_get_device_tree, OPAL_GET_DEVICE_TREE); +OPAL_CALL(opal_pci_get_presence_state, OPAL_PCI_GET_PRESENCE_STATE); +OPAL_CALL(opal_pci_get_power_state, OPAL_PCI_GET_POWER_STATE); +OPAL_CALL(opal_pci_set_power_state, OPAL_PCI_SET_POWER_STATE); diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index 2607d2923b80..62c7637d4831 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c @@ -74,6 +74,88 @@ int pnv_pci_get_slot_id(struct device_node *np, uint64_t *id) } EXPORT_SYMBOL_GPL(pnv_pci_get_slot_id); +int pnv_pci_get_device_tree(uint32_t phandle, void *buf, uint64_t len) +{ + int64_t rc; + + if (!opal_check_token(OPAL_GET_DEVICE_TREE)) + return -ENXIO; + + rc = opal_get_device_tree(phandle, (uint64_t)buf, len); + if (rc < OPAL_SUCCESS) + return -EIO; + + return rc; +} +EXPORT_SYMBOL_GPL(pnv_pci_get_device_tree); + +int pnv_pci_get_presence_state(uint64_t id, uint8_t *state) +{ + int64_t rc; + + if (!opal_check_token(OPAL_PCI_GET_PRESENCE_STATE)) + return -ENXIO; + + rc = opal_pci_get_presence_state(id, (uint64_t)state); + if (rc != OPAL_SUCCESS) + return -EIO; + + return 0; +} +EXPORT_SYMBOL_GPL(pnv_pci_get_presence_state); + +int pnv_pci_get_power_state(uint64_t id, uint8_t *state) +{ + int64_t rc; + + if (!opal_check_token(OPAL_PCI_GET_POWER_STATE)) + return -ENXIO; + + rc = opal_pci_get_power_state(id, (uint64_t)state); + if (rc != OPAL_SUCCESS) + return -EIO; + + return 0; +} +EXPORT_SYMBOL_GPL(pnv_pci_get_power_state); + +int pnv_pci_set_power_state(uint64_t id, uint8_t state, struct opal_msg *msg) +{ + struct opal_msg m; + int token, ret; + int64_t rc; + + if (!opal_check_token(OPAL_PCI_SET_POWER_STATE)) + return -ENXIO; + + token = opal_async_get_token_interruptible(); + if (unlikely(token < 0)) + return token; + + rc = opal_pci_set_power_state(token, id, (uint64_t)&state); + if (rc == OPAL_SUCCESS) { + ret = 0; + goto exit; + } else if (rc != OPAL_ASYNC_COMPLETION) { + ret = -EIO; + goto exit; + } + + ret = opal_async_wait_response(token, &m); + if (ret < 0) + goto exit; + + if (msg) { + ret = 1; + memcpy(msg, &m, sizeof(m)); + } + +exit: + opal_async_release_token(token); + return ret; +} +EXPORT_SYMBOL_GPL(pnv_pci_set_power_state); + #ifdef CONFIG_PCI_MSI int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) { -- cgit v1.2.3 From 9497a1c1c5b4de2a359b6d8648b4000679363473 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Tue, 21 Jun 2016 12:35:56 +1000 Subject: powerpc/powernv: Print correct PHB type names We're initializing "IODA1" and "IODA2" PHBs though they are IODA2 and NPU PHBs as below kernel log indicates. Initializing IODA1 OPAL PHB /pciex@3fffe40700000 Initializing IODA2 OPAL PHB /pciex@3fff000400000 This fixes the PHB names. After it's applied, we get: Initializing IODA2 PHB (/pciex@3fffe40700000) Initializing NPU PHB (/pciex@3fff000400000) Signed-off-by: Gavin Shan Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/pci-ioda.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 4e0b2fc06694..2115ed70440e 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -55,6 +55,7 @@ #define POWERNV_IOMMU_DEFAULT_LEVELS 1 #define POWERNV_IOMMU_MAX_LEVELS 5 +static const char * const pnv_phb_names[] = { "IODA1", "IODA2", "NPU" }; static void pnv_pci_ioda2_table_free_pages(struct iommu_table *tbl); void pe_level_printk(const struct pnv_ioda_pe *pe, const char *level, @@ -3628,7 +3629,8 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, void *aux; long rc; - pr_info("Initializing IODA%d OPAL PHB %s\n", ioda_type, np->full_name); + pr_info("Initializing %s PHB (%s)\n", + pnv_phb_names[ioda_type], of_node_full_name(np)); prop64 = of_get_property(np, "ibm,opal-phbid", NULL); if (!prop64) { -- cgit v1.2.3 From 5593e3032736ccba30d28bd27ebf9e8671980ca9 Mon Sep 17 00:00:00 2001 From: "Shreyas B. Prabhu" Date: Wed, 8 Jun 2016 11:54:27 -0500 Subject: powerpc/powernv: set power_save func after the idle states are initialized pnv_init_idle_states() discovers supported idle states from the device tree and does the required initialization. Set power_save function pointer only after this initialization is done Otherwise on machines which don't support nap, eg. Power9, the kernel will crash when it tries to nap. Reviewed-by: Gautham R. Shenoy Signed-off-by: Shreyas B. Prabhu Acked-by: Benjamin Herrenschmidt Acked-by: Michael Neuling Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/idle.c | 3 +++ arch/powerpc/platforms/powernv/setup.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c index 92a8020f3502..8a77f5c4159e 100644 --- a/arch/powerpc/platforms/powernv/idle.c +++ b/arch/powerpc/platforms/powernv/idle.c @@ -285,6 +285,9 @@ static int __init pnv_init_idle_states(void) } pnv_alloc_idle_core_states(); + + if (supported_cpuidle_states & OPAL_PM_NAP_ENABLED) + ppc_md.power_save = power7_idle; out_free: kfree(flags); out: diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c index ee6430bedcc3..8492bbbcfc08 100644 --- a/arch/powerpc/platforms/powernv/setup.c +++ b/arch/powerpc/platforms/powernv/setup.c @@ -315,7 +315,7 @@ define_machine(powernv) { .get_proc_freq = pnv_get_proc_freq, .progress = pnv_progress, .machine_shutdown = pnv_shutdown, - .power_save = power7_idle, + .power_save = NULL, .calibrate_decr = generic_calibrate_decr, #ifdef CONFIG_KEXEC .kexec_cpu_down = pnv_kexec_cpu_down, -- cgit v1.2.3 From 6e8a9279a85abd07d05e9322844b0f254e8437ac Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 23 Jun 2016 18:05:56 +0100 Subject: powerpc/powernv: Fix spelling mistake "Retrived" -> "Retrieved" Trivial fix to spelling mistake in pr_debug() message. Signed-off-by: Colin Ian King Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/opal-memory-errors.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powernv/opal-memory-errors.c b/arch/powerpc/platforms/powernv/opal-memory-errors.c index 00a29432be39..4495f428b500 100644 --- a/arch/powerpc/platforms/powernv/opal-memory-errors.c +++ b/arch/powerpc/platforms/powernv/opal-memory-errors.c @@ -44,7 +44,7 @@ static void handle_memory_error_event(struct OpalMemoryErrorData *merr_evt) { uint64_t paddr_start, paddr_end; - pr_debug("%s: Retrived memory error event, type: 0x%x\n", + pr_debug("%s: Retrieved memory error event, type: 0x%x\n", __func__, merr_evt->type); switch (merr_evt->type) { case OPAL_MEM_ERR_TYPE_RESILIENCE: -- cgit v1.2.3 From d0226d315dba5e401a124b394a1af5e35e082b08 Mon Sep 17 00:00:00 2001 From: Suraj Jitindar Singh Date: Wed, 29 Jun 2016 13:38:38 +1000 Subject: powerpc/opal: Add inline function to get rc from an ASYNC_COMP opal_msg An opal_msg of type OPAL_MSG_ASYNC_COMP contains the return code in the params[1] struct member. However this isn't intuitive or obvious when reading the code and requires that a user look at the skiboot documentation or opal-api.h to verify this. Add an inline function to get the return code from an opal_msg and update call sites accordingly. Signed-off-by: Suraj Jitindar Singh Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/opal.h | 8 ++++++++ arch/powerpc/platforms/powernv/opal-sensor.c | 2 +- arch/powerpc/platforms/powernv/opal-sysparam.c | 4 ++-- drivers/i2c/busses/i2c-opal.c | 2 +- drivers/leds/leds-powernv.c | 2 +- drivers/mtd/devices/powernv_flash.c | 2 +- drivers/rtc/rtc-opal.c | 4 ++-- 7 files changed, 16 insertions(+), 8 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index fa71fea3b6ee..9ab52e27cf71 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h @@ -282,6 +282,14 @@ extern int opal_error_code(int rc); ssize_t opal_msglog_copy(char *to, loff_t pos, size_t count); +static inline int opal_get_async_rc(struct opal_msg msg) +{ + if (msg.msg_type != OPAL_MSG_ASYNC_COMP) + return OPAL_PARAMETER; + else + return be64_to_cpu(msg.params[1]); +} + #endif /* __ASSEMBLY__ */ #endif /* _ASM_POWERPC_OPAL_H */ diff --git a/arch/powerpc/platforms/powernv/opal-sensor.c b/arch/powerpc/platforms/powernv/opal-sensor.c index a06059df9239..308efd170c27 100644 --- a/arch/powerpc/platforms/powernv/opal-sensor.c +++ b/arch/powerpc/platforms/powernv/opal-sensor.c @@ -55,7 +55,7 @@ int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data) goto out_token; } - ret = opal_error_code(be64_to_cpu(msg.params[1])); + ret = opal_error_code(opal_get_async_rc(msg)); *sensor_data = be32_to_cpu(data); break; diff --git a/arch/powerpc/platforms/powernv/opal-sysparam.c b/arch/powerpc/platforms/powernv/opal-sysparam.c index afe66c576a38..23fb6647dced 100644 --- a/arch/powerpc/platforms/powernv/opal-sysparam.c +++ b/arch/powerpc/platforms/powernv/opal-sysparam.c @@ -67,7 +67,7 @@ static ssize_t opal_get_sys_param(u32 param_id, u32 length, void *buffer) goto out_token; } - ret = opal_error_code(be64_to_cpu(msg.params[1])); + ret = opal_error_code(opal_get_async_rc(msg)); out_token: opal_async_release_token(token); @@ -103,7 +103,7 @@ static int opal_set_sys_param(u32 param_id, u32 length, void *buffer) goto out_token; } - ret = opal_error_code(be64_to_cpu(msg.params[1])); + ret = opal_error_code(opal_get_async_rc(msg)); out_token: opal_async_release_token(token); diff --git a/drivers/i2c/busses/i2c-opal.c b/drivers/i2c/busses/i2c-opal.c index 75dd6d041241..11e2a1fc10e9 100644 --- a/drivers/i2c/busses/i2c-opal.c +++ b/drivers/i2c/busses/i2c-opal.c @@ -71,7 +71,7 @@ static int i2c_opal_send_request(u32 bus_id, struct opal_i2c_request *req) if (rc) goto exit; - rc = be64_to_cpu(msg.params[1]); + rc = opal_get_async_rc(msg); if (rc != OPAL_SUCCESS) { rc = i2c_opal_translate_error(rc); goto exit; diff --git a/drivers/leds/leds-powernv.c b/drivers/leds/leds-powernv.c index dfb8bd390125..b2a98c7b521b 100644 --- a/drivers/leds/leds-powernv.c +++ b/drivers/leds/leds-powernv.c @@ -118,7 +118,7 @@ static int powernv_led_set(struct powernv_led_data *powernv_led, goto out_token; } - rc = be64_to_cpu(msg.params[1]); + rc = opal_get_async_rc(msg); if (rc != OPAL_SUCCESS) dev_err(dev, "%s : OAPL async call returned failed [rc=%d]\n", __func__, rc); diff --git a/drivers/mtd/devices/powernv_flash.c b/drivers/mtd/devices/powernv_flash.c index d5b870b3fd4e..f5396f26ddb4 100644 --- a/drivers/mtd/devices/powernv_flash.c +++ b/drivers/mtd/devices/powernv_flash.c @@ -95,7 +95,7 @@ static int powernv_flash_async_op(struct mtd_info *mtd, enum flash_op op, return -EIO; } - rc = be64_to_cpu(msg.params[1]); + rc = opal_get_async_rc(msg); if (rc == OPAL_SUCCESS) { rc = 0; if (retlen) diff --git a/drivers/rtc/rtc-opal.c b/drivers/rtc/rtc-opal.c index 9c18d6fd8107..ea20f627dabe 100644 --- a/drivers/rtc/rtc-opal.c +++ b/drivers/rtc/rtc-opal.c @@ -134,7 +134,7 @@ static int opal_get_tpo_time(struct device *dev, struct rtc_wkalrm *alarm) goto exit; } - rc = be64_to_cpu(msg.params[1]); + rc = opal_get_async_rc(msg); if (rc != OPAL_SUCCESS) { rc = -EIO; goto exit; @@ -181,7 +181,7 @@ static int opal_set_tpo_time(struct device *dev, struct rtc_wkalrm *alarm) goto exit; } - rc = be64_to_cpu(msg.params[1]); + rc = opal_get_async_rc(msg); if (rc != OPAL_SUCCESS) rc = -EIO; -- cgit v1.2.3 From 43a1dd9b5fc64184e578ac1570d016d2862e00b2 Mon Sep 17 00:00:00 2001 From: Suraj Jitindar Singh Date: Wed, 29 Jun 2016 13:38:39 +1000 Subject: powerpc/powernv: Add driver for operator panel on FSP machines Implement new character device driver to allow access from user space to the operator panel display present on IBM Power Systems machines with FSPs. This will allow status information to be presented on the display which is visible to a user. The driver implements a character buffer which a user can read/write by accessing the device (/dev/op_panel). This buffer is then displayed on the operator panel display. Any attempt to write past the last character position will have no effect and attempts to write more characters than the size of the display will be truncated. The device may only be accessed by a single process at a time. Signed-off-by: Suraj Jitindar Singh Reviewed-by: Andrew Donnellan Signed-off-by: Michael Ellerman --- MAINTAINERS | 6 + arch/powerpc/configs/powernv_defconfig | 1 + arch/powerpc/include/asm/opal.h | 2 + arch/powerpc/platforms/powernv/opal-wrappers.S | 1 + arch/powerpc/platforms/powernv/opal.c | 5 + drivers/char/Kconfig | 14 ++ drivers/char/Makefile | 1 + drivers/char/powernv-op-panel.c | 223 +++++++++++++++++++++++++ 8 files changed, 253 insertions(+) create mode 100644 drivers/char/powernv-op-panel.c (limited to 'arch/powerpc/platforms') diff --git a/MAINTAINERS b/MAINTAINERS index ea80d71fffaa..3318633732d0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9081,6 +9081,12 @@ F: drivers/firmware/psci.c F: include/linux/psci.h F: include/uapi/linux/psci.h +POWERNV OPERATOR PANEL LCD DISPLAY DRIVER +M: Suraj Jitindar Singh +L: linuxppc-dev@lists.ozlabs.org +S: Maintained +F: drivers/char/powernv-op-panel.c + PNP SUPPORT M: "Rafael J. Wysocki" S: Maintained diff --git a/arch/powerpc/configs/powernv_defconfig b/arch/powerpc/configs/powernv_defconfig index 045031048f8d..959d32bc7337 100644 --- a/arch/powerpc/configs/powernv_defconfig +++ b/arch/powerpc/configs/powernv_defconfig @@ -181,6 +181,7 @@ CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_JSM=m CONFIG_VIRTIO_CONSOLE=m +CONFIG_POWERNV_OP_PANEL=m CONFIG_IPMI_HANDLER=y CONFIG_IPMI_DEVICE_INTERFACE=y CONFIG_IPMI_POWERNV=y diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index 9ab52e27cf71..3b369e9cb6e1 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h @@ -178,6 +178,8 @@ int64_t opal_dump_ack(uint32_t dump_id); int64_t opal_dump_resend_notification(void); int64_t opal_get_msg(uint64_t buffer, uint64_t size); +int64_t opal_write_oppanel_async(uint64_t token, oppanel_line_t *lines, + uint64_t num_lines); int64_t opal_check_completion(uint64_t buffer, uint64_t size, uint64_t token); int64_t opal_sync_host_reboot(void); int64_t opal_get_param(uint64_t token, uint32_t param_id, uint64_t buffer, diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S index 3ea1a8559035..7979d6d43bff 100644 --- a/arch/powerpc/platforms/powernv/opal-wrappers.S +++ b/arch/powerpc/platforms/powernv/opal-wrappers.S @@ -278,6 +278,7 @@ OPAL_CALL(opal_dump_info2, OPAL_DUMP_INFO2); OPAL_CALL(opal_dump_read, OPAL_DUMP_READ); OPAL_CALL(opal_dump_ack, OPAL_DUMP_ACK); OPAL_CALL(opal_get_msg, OPAL_GET_MSG); +OPAL_CALL(opal_write_oppanel_async, OPAL_WRITE_OPPANEL_ASYNC); OPAL_CALL(opal_check_completion, OPAL_CHECK_ASYNC_COMPLETION); OPAL_CALL(opal_dump_resend_notification, OPAL_DUMP_RESEND); OPAL_CALL(opal_sync_host_reboot, OPAL_SYNC_HOST_REBOOT); diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index 0256d0729252..228751a0d8c6 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c @@ -751,6 +751,9 @@ static int __init opal_init(void) opal_pdev_init(opal_node, "ibm,opal-flash"); opal_pdev_init(opal_node, "ibm,opal-prd"); + /* Initialise platform device: oppanel interface */ + opal_pdev_init(opal_node, "ibm,opal-oppanel"); + /* Initialise OPAL kmsg dumper for flushing console on panic */ opal_kmsg_init(); @@ -885,3 +888,5 @@ EXPORT_SYMBOL_GPL(opal_i2c_request); /* Export these symbols for PowerNV LED class driver */ EXPORT_SYMBOL_GPL(opal_leds_get_ind); EXPORT_SYMBOL_GPL(opal_leds_set_ind); +/* Export this symbol for PowerNV Operator Panel class driver */ +EXPORT_SYMBOL_GPL(opal_write_oppanel_async); diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 601f64fcc890..fdb8f3e10b6f 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -178,6 +178,20 @@ config IBM_BSR of threads across a large system which avoids bouncing a cacheline between several cores on a system +config POWERNV_OP_PANEL + tristate "IBM POWERNV Operator Panel Display support" + depends on PPC_POWERNV + default m + help + If you say Y here, a special character device node, /dev/op_panel, + will be created which exposes the operator panel display on IBM + Power Systems machines with FSPs. + + If you don't require access to the operator panel display from user + space, say N. + + If unsure, say M here to build it as a module called powernv-op-panel. + source "drivers/char/ipmi/Kconfig" config DS1620 diff --git a/drivers/char/Makefile b/drivers/char/Makefile index d8a7579300d2..55d16bf3ccc5 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -60,3 +60,4 @@ js-rtc-y = rtc.o obj-$(CONFIG_TILE_SROM) += tile-srom.o obj-$(CONFIG_XILLYBUS) += xillybus/ +obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o diff --git a/drivers/char/powernv-op-panel.c b/drivers/char/powernv-op-panel.c new file mode 100644 index 000000000000..a45dabcc8e10 --- /dev/null +++ b/drivers/char/powernv-op-panel.c @@ -0,0 +1,223 @@ +/* + * OPAL Operator Panel Display Driver + * + * Copyright 2016, Suraj Jitindar Singh, IBM Corporation. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * This driver creates a character device (/dev/op_panel) which exposes the + * operator panel (character LCD display) on IBM Power Systems machines + * with FSPs. + * A character buffer written to the device will be displayed on the + * operator panel. + */ + +static DEFINE_MUTEX(oppanel_mutex); + +static u32 num_lines, oppanel_size; +static oppanel_line_t *oppanel_lines; +static char *oppanel_data; + +static loff_t oppanel_llseek(struct file *filp, loff_t offset, int whence) +{ + return fixed_size_llseek(filp, offset, whence, oppanel_size); +} + +static ssize_t oppanel_read(struct file *filp, char __user *userbuf, size_t len, + loff_t *f_pos) +{ + return simple_read_from_buffer(userbuf, len, f_pos, oppanel_data, + oppanel_size); +} + +static int __op_panel_update_display(void) +{ + struct opal_msg msg; + int rc, token; + + token = opal_async_get_token_interruptible(); + if (token < 0) { + if (token != -ERESTARTSYS) + pr_debug("Couldn't get OPAL async token [token=%d]\n", + token); + return token; + } + + rc = opal_write_oppanel_async(token, oppanel_lines, num_lines); + switch (rc) { + case OPAL_ASYNC_COMPLETION: + rc = opal_async_wait_response(token, &msg); + if (rc) { + pr_debug("Failed to wait for async response [rc=%d]\n", + rc); + break; + } + rc = opal_get_async_rc(msg); + if (rc != OPAL_SUCCESS) { + pr_debug("OPAL async call returned failed [rc=%d]\n", + rc); + break; + } + case OPAL_SUCCESS: + break; + default: + pr_debug("OPAL write op-panel call failed [rc=%d]\n", rc); + } + + opal_async_release_token(token); + return rc; +} + +static ssize_t oppanel_write(struct file *filp, const char __user *userbuf, + size_t len, loff_t *f_pos) +{ + loff_t f_pos_prev = *f_pos; + ssize_t ret; + int rc; + + if (!*f_pos) + memset(oppanel_data, ' ', oppanel_size); + else if (*f_pos >= oppanel_size) + return -EFBIG; + + ret = simple_write_to_buffer(oppanel_data, oppanel_size, f_pos, userbuf, + len); + if (ret > 0) { + rc = __op_panel_update_display(); + if (rc != OPAL_SUCCESS) { + pr_err_ratelimited("OPAL call failed to write to op panel display [rc=%d]\n", + rc); + *f_pos = f_pos_prev; + return -EIO; + } + } + return ret; +} + +static int oppanel_open(struct inode *inode, struct file *filp) +{ + if (!mutex_trylock(&oppanel_mutex)) { + pr_debug("Device Busy\n"); + return -EBUSY; + } + return 0; +} + +static int oppanel_release(struct inode *inode, struct file *filp) +{ + mutex_unlock(&oppanel_mutex); + return 0; +} + +static const struct file_operations oppanel_fops = { + .owner = THIS_MODULE, + .llseek = oppanel_llseek, + .read = oppanel_read, + .write = oppanel_write, + .open = oppanel_open, + .release = oppanel_release +}; + +static struct miscdevice oppanel_dev = { + .minor = MISC_DYNAMIC_MINOR, + .name = "op_panel", + .fops = &oppanel_fops +}; + +static int oppanel_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + u32 line_len; + int rc, i; + + rc = of_property_read_u32(np, "#length", &line_len); + if (rc) { + pr_err_ratelimited("Operator panel length property not found\n"); + return rc; + } + rc = of_property_read_u32(np, "#lines", &num_lines); + if (rc) { + pr_err_ratelimited("Operator panel lines property not found\n"); + return rc; + } + oppanel_size = line_len * num_lines; + + pr_devel("Operator panel of size %u found with %u lines of length %u\n", + oppanel_size, num_lines, line_len); + + oppanel_data = kcalloc(oppanel_size, sizeof(*oppanel_data), GFP_KERNEL); + if (!oppanel_data) + return -ENOMEM; + + oppanel_lines = kcalloc(num_lines, sizeof(oppanel_line_t), GFP_KERNEL); + if (!oppanel_lines) { + rc = -ENOMEM; + goto free_oppanel_data; + } + + memset(oppanel_data, ' ', oppanel_size); + for (i = 0; i < num_lines; i++) { + oppanel_lines[i].line_len = cpu_to_be64(line_len); + oppanel_lines[i].line = cpu_to_be64(__pa(&oppanel_data[i * + line_len])); + } + + rc = misc_register(&oppanel_dev); + if (rc) { + pr_err_ratelimited("Failed to register as misc device\n"); + goto free_oppanel; + } + + return 0; + +free_oppanel: + kfree(oppanel_lines); +free_oppanel_data: + kfree(oppanel_data); + return rc; +} + +static int oppanel_remove(struct platform_device *pdev) +{ + misc_deregister(&oppanel_dev); + kfree(oppanel_lines); + kfree(oppanel_data); + return 0; +} + +static const struct of_device_id oppanel_match[] = { + { .compatible = "ibm,opal-oppanel" }, + { }, +}; + +static struct platform_driver oppanel_driver = { + .driver = { + .name = "powernv-op-panel", + .of_match_table = oppanel_match, + }, + .probe = oppanel_probe, + .remove = oppanel_remove, +}; + +module_platform_driver(oppanel_driver); + +MODULE_DEVICE_TABLE(of, oppanel_match); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("PowerNV Operator Panel LCD Display Driver"); +MODULE_AUTHOR("Suraj Jitindar Singh "); -- cgit v1.2.3 From e2be23712a9c8e3710c9e2684a3204bd20c685d6 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Tue, 8 Mar 2016 22:26:17 +0100 Subject: powerpc/pseries: Fix error return value in cmm_mem_going_offline() cmm_mem_going_offline() is (only) called from cmm_memory_cb(), which sends the return value through notifier_from_errno(). The latter expects 0 or -errno (notifier_to_errno(notifier_from_errno(x)) is 0 for any x >= 0, so passing a positive value cannot make sense). Hence negate ENOMEM. Signed-off-by: Rasmus Villemoes Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/pseries/cmm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/cmm.c b/arch/powerpc/platforms/pseries/cmm.c index fc44ad0475f8..66e7227469b8 100644 --- a/arch/powerpc/platforms/pseries/cmm.c +++ b/arch/powerpc/platforms/pseries/cmm.c @@ -574,7 +574,7 @@ static int cmm_mem_going_offline(void *arg) cmm_dbg("Failed to allocate memory for list " "management. Memory hotplug " "failed.\n"); - return ENOMEM; + return -ENOMEM; } memcpy(npa, pa_curr, PAGE_SIZE); if (pa_curr == cmm_page_list) -- cgit v1.2.3 From a203658b5ed37c11e5016d3fbbbab9ce018c1b78 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 4 Jul 2016 14:51:44 +1000 Subject: powerpc/opal: Wake up kopald polling thread before waiting for events On some environments (prototype machines, some simulators, etc...) there is no functional interrupt source to signal completion, so we rely on the fairly slow OPAL heartbeat. In a number of cases, the calls complete very quickly or even immediately. We've observed that it helps a lot to wakeup the OPAL heartbeat thread before waiting for event in those cases, it will call OPAL immediately to collect completions for anything that finished fast enough. Signed-off-by: Benjamin Herrenschmidt Acked-By: Michael Neuling Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/opal.h | 2 ++ arch/powerpc/platforms/powernv/opal-async.c | 5 +++++ arch/powerpc/platforms/powernv/opal.c | 12 ++++++++++-- 3 files changed, 17 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index 3b369e9cb6e1..52b9f4a80aed 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h @@ -292,6 +292,8 @@ static inline int opal_get_async_rc(struct opal_msg msg) return be64_to_cpu(msg.params[1]); } +void opal_wake_poller(void); + #endif /* __ASSEMBLY__ */ #endif /* _ASM_POWERPC_OPAL_H */ diff --git a/arch/powerpc/platforms/powernv/opal-async.c b/arch/powerpc/platforms/powernv/opal-async.c index bdc8c0c71d15..83bebeec0fea 100644 --- a/arch/powerpc/platforms/powernv/opal-async.c +++ b/arch/powerpc/platforms/powernv/opal-async.c @@ -117,6 +117,11 @@ int opal_async_wait_response(uint64_t token, struct opal_msg *msg) return -EINVAL; } + /* Wakeup the poller before we wait for events to speed things + * up on platforms or simulators where the interrupts aren't + * functional. + */ + opal_wake_poller(); wait_event(opal_async_wait, test_bit(token, opal_async_complete_map)); memcpy(msg, &opal_async_responses[token], sizeof(*msg)); diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index 228751a0d8c6..da40d6bdb0e6 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c @@ -55,6 +55,7 @@ struct device_node *opal_node; static DEFINE_SPINLOCK(opal_write_lock); static struct atomic_notifier_head opal_msg_notifier_head[OPAL_MSG_TYPE_MAX]; static uint32_t opal_heartbeat; +static struct task_struct *kopald_tsk; static void opal_reinit_cores(void) { @@ -653,6 +654,7 @@ static void opal_i2c_create_devs(void) static int kopald(void *unused) { + unsigned long timeout = msecs_to_jiffies(opal_heartbeat) + 1; __be64 events; set_freezable(); @@ -660,12 +662,18 @@ static int kopald(void *unused) try_to_freeze(); opal_poll_events(&events); opal_handle_events(be64_to_cpu(events)); - msleep_interruptible(opal_heartbeat); + schedule_timeout_interruptible(timeout); } while (!kthread_should_stop()); return 0; } +void opal_wake_poller(void) +{ + if (kopald_tsk) + wake_up_process(kopald_tsk); +} + static void opal_init_heartbeat(void) { /* Old firwmware, we assume the HVC heartbeat is sufficient */ @@ -674,7 +682,7 @@ static void opal_init_heartbeat(void) opal_heartbeat = 0; if (opal_heartbeat) - kthread_run(kopald, NULL, "kopald"); + kopald_tsk = kthread_run(kopald, NULL, "kopald"); } static int __init opal_init(void) -- cgit v1.2.3 From 53775c43feae462e145b4bb88aa2115123c3c565 Mon Sep 17 00:00:00 2001 From: Andrew Donnellan Date: Tue, 5 Jul 2016 16:12:33 +1000 Subject: powerpc/ps3: Fix typo in comment reference to CONFIG_PS3_REPOSITORY_WRITE Signed-off-by: Andrew Donnellan Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/ps3/repository.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/ps3/repository.c b/arch/powerpc/platforms/ps3/repository.c index bfccdc7cb85f..814a7eaa7769 100644 --- a/arch/powerpc/platforms/ps3/repository.c +++ b/arch/powerpc/platforms/ps3/repository.c @@ -1198,7 +1198,7 @@ int ps3_repository_delete_highmem_info(unsigned int region_index) return result ? -1 : 0; } -#endif /* defined(CONFIG_PS3_WRITE_REPOSITORY) */ +#endif /* defined(CONFIG_PS3_REPOSITORY_WRITE) */ #if defined(DEBUG) -- cgit v1.2.3 From 97493e2e9eeddfecaca741454f97a689d8141dcf Mon Sep 17 00:00:00 2001 From: Alessio Igor Bogani Date: Mon, 30 May 2016 11:47:16 +0200 Subject: powerpc/86xx: Add support for Emerson/Artesyn MVME7100 Add support for the Artesyn MVME7100 Single Board Computer. The MVME7100 is a 6U form factor VME64 computer with: - A two e600 cores Freescale MPC8641D CPU - 2 GB of DDR2 onboard memory - Four Gigabit Ethernets - Five 16550 compatible UARTs - One USB 2.0 port - Two PCI/PCI eXpress Mezzanine Card (PMC/XMC) Slots - A DS1375 Real Time Clock (RTC) - 512 KB of Non-Volatile Memory (NVRAM) - Two 64 KB EEPROMs - 128 MB NOR and 4/8 GB NAND Flash This patch is based on linux-4.7-rc1 and has been only boot tested. Limitations: This patch covers only models 171 and 173 No plans to support CPLD timers Know issues: All four PHYs work in polling mode Configuration is missing for: PCI IDSEL and PCI Interrupt definition Support is missing for: Cache and memory controllers (which are very similar to the 85xx ones but right now I don't know if we can re-use their support) Watchdog, USB, NVRAM, NOR, NAND, EEPROMs, VME, PMC/XMC and RTC Signed-off-by: Alessio Igor Bogani Signed-off-by: Scott Wood --- arch/powerpc/boot/Makefile | 4 + arch/powerpc/boot/dts/fsl/mvme7100.dts | 153 +++++++++++++++++++++++++++ arch/powerpc/boot/motload-head.S | 11 ++ arch/powerpc/boot/mvme7100.c | 59 +++++++++++ arch/powerpc/boot/ppcboot.h | 2 +- arch/powerpc/boot/wrapper | 5 + arch/powerpc/configs/86xx-hw.config | 4 +- arch/powerpc/configs/mpc86xx_basic_defconfig | 1 + arch/powerpc/platforms/86xx/Kconfig | 8 +- arch/powerpc/platforms/86xx/Makefile | 1 + arch/powerpc/platforms/86xx/mvme7100.c | 121 +++++++++++++++++++++ 11 files changed, 365 insertions(+), 4 deletions(-) create mode 100644 arch/powerpc/boot/dts/fsl/mvme7100.dts create mode 100644 arch/powerpc/boot/motload-head.S create mode 100644 arch/powerpc/boot/mvme7100.c create mode 100644 arch/powerpc/platforms/86xx/mvme7100.c (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 00cf88aa9a23..4cd612a6e272 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -113,6 +113,7 @@ src-plat-$(CONFIG_EPAPR_BOOT) += epapr.c epapr-wrapper.c src-plat-$(CONFIG_PPC_PSERIES) += pseries-head.S src-plat-$(CONFIG_PPC_POWERNV) += pseries-head.S src-plat-$(CONFIG_PPC_IBM_CELL_BLADE) += pseries-head.S +src-plat-$(CONFIG_MVME7100) += motload-head.S mvme7100.c src-wlib := $(sort $(src-wlib-y)) src-plat := $(sort $(src-plat-y)) @@ -296,6 +297,9 @@ image-$(CONFIG_TQM8560) += cuImage.tqm8560 image-$(CONFIG_SBC8548) += cuImage.sbc8548 image-$(CONFIG_KSI8560) += cuImage.ksi8560 +# Board ports in arch/powerpc/platform/86xx/Kconfig +image-$(CONFIG_MVME7100) += dtbImage.mvme7100 + # Board ports in arch/powerpc/platform/embedded6xx/Kconfig image-$(CONFIG_STORCENTER) += cuImage.storcenter image-$(CONFIG_MPC7448HPC2) += cuImage.mpc7448hpc2 diff --git a/arch/powerpc/boot/dts/fsl/mvme7100.dts b/arch/powerpc/boot/dts/fsl/mvme7100.dts new file mode 100644 index 000000000000..e2d306ad37a6 --- /dev/null +++ b/arch/powerpc/boot/dts/fsl/mvme7100.dts @@ -0,0 +1,153 @@ +/* + * Device tree source for the Emerson/Artesyn MVME7100 + * + * Copyright 2016 Elettra-Sincrotrone Trieste S.C.p.A. + * + * Author: Alessio Igor Bogani + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +/include/ "mpc8641si-pre.dtsi" + +/ { + model = "MVME7100"; + compatible = "artesyn,MVME7100"; + + memory { + device_type = "memory"; + reg = <0x00000000 0x80000000>; + }; + + soc: soc@f1000000 { + ranges = <0x00000000 0xf1000000 0x00100000>; + + i2c@3000 { + hwmon@4c { + compatible = "dallas,max6649"; + reg = <0x4c>; + }; + + rtc@68 { + status = "disabled"; + }; + }; + + + enet0: ethernet@24000 { + phy-handle = <&phy0>; + phy-connection-type = "rgmii-id"; + }; + + mdio@24520 { + phy0: ethernet-phy@1 { + reg = <1>; + }; + phy1: ethernet-phy@2 { + reg = <2>; + }; + phy2: ethernet-phy@3 { + reg = <3>; + }; + phy3: ethernet-phy@4 { + reg = <4>; + }; + }; + + enet1: ethernet@25000 { + phy-handle = <&phy1>; + phy-connection-type = "rgmii-id"; + }; + + mdio@25520 { + status = "disabled"; + }; + + enet2: ethernet@26000 { + phy-handle = <&phy2>; + phy-connection-type = "rgmii-id"; + }; + + mdio@26520 { + status = "disabled"; + }; + + enet3: ethernet@27000 { + phy-handle = <&phy3>; + phy-connection-type = "rgmii-id"; + }; + + mdio@27520 { + status = "disabled"; + }; + + serial1: serial@4600 { + status = "disabled"; + }; + }; + + lbc: localbus@f1005000 { + reg = <0xf1005000 0x1000>; + + ranges = <0 0 0xf8000000 0x08000000 // NOR Flash (128MB) + 2 0 0xf2030000 0x00010000 // NAND Flash (8GB) + 3 0 0xf2400000 0x00080000 // MRAM (512KB) + 4 0 0xf2000000 0x00010000 // BCSR + 5 0 0xf2010000 0x00010000>; // QUART + + bcsr@4,0 { + compatible = "artesyn,mvme7100-bcsr"; + reg = <4 0 0x10000>; + }; + + serial@5,1000 { + device_type = "serial"; + compatible = "ns16550"; + reg = <5 0x1000 0x100>; + clock-frequency = <1843200>; + interrupts = <11 1 0 0>; + }; + + serial@5,2000 { + device_type = "serial"; + compatible = "ns16550"; + reg = <5 0x2000 0x100>; + clock-frequency = <1843200>; + interrupts = <11 1 0 0>; + }; + + serial@5,3000 { + device_type = "serial"; + compatible = "ns16550"; + reg = <5 0x3000 0x100>; + clock-frequency = <1843200>; + interrupts = <11 1 0 0>; + }; + + serial@5,4000 { + device_type = "serial"; + compatible = "ns16550"; + reg = <5 0x4000 0x100>; + clock-frequency = <1843200>; + interrupts = <11 1 0 0>; + }; + }; + + pci0: pcie@f1008000 { + status = "disabled"; + }; + + pci1: pcie@f1009000 { + status = "disabled"; + }; + + chosen { + linux,stdout-path = &serial0; + }; +}; + +/include/ "mpc8641si-post.dtsi" diff --git a/arch/powerpc/boot/motload-head.S b/arch/powerpc/boot/motload-head.S new file mode 100644 index 000000000000..41cabb4b63fa --- /dev/null +++ b/arch/powerpc/boot/motload-head.S @@ -0,0 +1,11 @@ +#include "ppc_asm.h" + + .text + .globl _zimage_start +_zimage_start: + mfmsr r10 + rlwinm r10,r10,0,~(1<<15) /* Clear MSR_EE */ + sync + mtmsr r10 + isync + b _zimage_start_lib diff --git a/arch/powerpc/boot/mvme7100.c b/arch/powerpc/boot/mvme7100.c new file mode 100644 index 000000000000..8b0a932311af --- /dev/null +++ b/arch/powerpc/boot/mvme7100.c @@ -0,0 +1,59 @@ +/* + * Motload compatibility for the Emerson/Artesyn MVME7100 + * + * Copyright 2016 Elettra-Sincrotrone Trieste S.C.p.A. + * + * Author: Alessio Igor Bogani + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include "ops.h" +#include "stdio.h" +#include "cuboot.h" + +#define TARGET_86xx +#define TARGET_HAS_ETH1 +#define TARGET_HAS_ETH2 +#define TARGET_HAS_ETH3 +#include "ppcboot.h" + +static bd_t bd; + +BSS_STACK(16384); + +static void mvme7100_fixups(void) +{ + void *devp; + unsigned long busfreq = bd.bi_busfreq * 1000000; + + dt_fixup_cpu_clocks(bd.bi_intfreq * 1000000, busfreq / 4, busfreq); + + devp = finddevice("/soc@f1000000"); + if (devp) + setprop(devp, "bus-frequency", &busfreq, sizeof(busfreq)); + + devp = finddevice("/soc/serial@4500"); + if (devp) + setprop(devp, "clock-frequency", &busfreq, sizeof(busfreq)); + + dt_fixup_memory(bd.bi_memstart, bd.bi_memsize); + + dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr); + dt_fixup_mac_address_by_alias("ethernet1", bd.bi_enet1addr); + dt_fixup_mac_address_by_alias("ethernet2", bd.bi_enet2addr); + dt_fixup_mac_address_by_alias("ethernet3", bd.bi_enet3addr); +} + +void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) +{ + CUBOOT_INIT(); + fdt_init(_dtb_start); + serial_console_init(); + platform_ops.fixups = mvme7100_fixups; +} diff --git a/arch/powerpc/boot/ppcboot.h b/arch/powerpc/boot/ppcboot.h index 6ae6f9063952..453df429d5d0 100644 --- a/arch/powerpc/boot/ppcboot.h +++ b/arch/powerpc/boot/ppcboot.h @@ -43,7 +43,7 @@ typedef struct bd_info { unsigned long bi_sramstart; /* start of SRAM memory */ unsigned long bi_sramsize; /* size of SRAM memory */ #if defined(TARGET_8xx) || defined(TARGET_CPM2) || defined(TARGET_85xx) ||\ - defined(TARGET_83xx) + defined(TARGET_83xx) || defined(TARGET_86xx) unsigned long bi_immr_base; /* base of IMMR register */ #endif #if defined(TARGET_PPC_MPC52xx) diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper index 6a19fcef5596..6681ec3625c9 100755 --- a/arch/powerpc/boot/wrapper +++ b/arch/powerpc/boot/wrapper @@ -302,6 +302,11 @@ mvme5100) platformo="$object/fixed-head.o $object/mvme5100.o" binary=y ;; +mvme7100) + platformo="$object/motload-head.o $object/mvme7100.o" + link_address='0x4000000' + binary=y + ;; esac vmz="$tmpdir/`basename \"$kernel\"`.$ext" diff --git a/arch/powerpc/configs/86xx-hw.config b/arch/powerpc/configs/86xx-hw.config index f91f8895fc93..d3dd6b8865c0 100644 --- a/arch/powerpc/configs/86xx-hw.config +++ b/arch/powerpc/configs/86xx-hw.config @@ -74,9 +74,9 @@ CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_DETECT_IRQ=y CONFIG_SERIAL_8250_EXTENDED=y CONFIG_SERIAL_8250_MANY_PORTS=y -CONFIG_SERIAL_8250_NR_UARTS=2 +CONFIG_SERIAL_8250_NR_UARTS=5 CONFIG_SERIAL_8250_RSA=y -CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +CONFIG_SERIAL_8250_RUNTIME_UARTS=5 CONFIG_SERIAL_8250_SHARE_IRQ=y CONFIG_SERIAL_8250=y CONFIG_SERIO_LIBPS2=y diff --git a/arch/powerpc/configs/mpc86xx_basic_defconfig b/arch/powerpc/configs/mpc86xx_basic_defconfig index 33af5c5de105..3283f0586e11 100644 --- a/arch/powerpc/configs/mpc86xx_basic_defconfig +++ b/arch/powerpc/configs/mpc86xx_basic_defconfig @@ -8,3 +8,4 @@ CONFIG_GEF_SBC610=y CONFIG_MPC8610_HPCD=y CONFIG_MPC8641_HPCN=y CONFIG_SBC8641D=y +CONFIG_MVME7100=y diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig index 1afd1e4a2dd2..37b166ebc729 100644 --- a/arch/powerpc/platforms/86xx/Kconfig +++ b/arch/powerpc/platforms/86xx/Kconfig @@ -61,6 +61,11 @@ config GEF_SBC610 help This option enables support for the GE SBC610. +config MVME7100 + bool "Artesyn MVME7100" + help + This option enables support for the Emerson/Artesyn MVME7100 board. + endif config MPC8641 @@ -69,7 +74,8 @@ config MPC8641 select FSL_PCI if PCI select PPC_UDBG_16550 select MPIC - default y if MPC8641_HPCN || SBC8641D || GEF_SBC610 || GEF_SBC310 || GEF_PPC9A + default y if MPC8641_HPCN || SBC8641D || GEF_SBC610 || GEF_SBC310 || GEF_PPC9A \ + || MVME7100 config MPC8610 bool diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile index 2d889ad7dc89..01958fedc3f2 100644 --- a/arch/powerpc/platforms/86xx/Makefile +++ b/arch/powerpc/platforms/86xx/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_MPC8610_HPCD) += mpc8610_hpcd.o obj-$(CONFIG_GEF_SBC610) += gef_sbc610.o obj-$(CONFIG_GEF_SBC310) += gef_sbc310.o obj-$(CONFIG_GEF_PPC9A) += gef_ppc9a.o +obj-$(CONFIG_MVME7100) += mvme7100.o diff --git a/arch/powerpc/platforms/86xx/mvme7100.c b/arch/powerpc/platforms/86xx/mvme7100.c new file mode 100644 index 000000000000..addb41e7cd14 --- /dev/null +++ b/arch/powerpc/platforms/86xx/mvme7100.c @@ -0,0 +1,121 @@ +/* + * Board setup routines for the Emerson/Artesyn MVME7100 + * + * Copyright 2016 Elettra-Sincrotrone Trieste S.C.p.A. + * + * Author: Alessio Igor Bogani + * + * Based on earlier code by: + * + * Ajit Prem + * Copyright 2008 Emerson + * + * USB host fixup is borrowed by: + * + * Martyn Welch + * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mpc86xx.h" + +#define MVME7100_INTERRUPT_REG_2_OFFSET 0x05 +#define MVME7100_DS1375_MASK 0x40 +#define MVME7100_MAX6649_MASK 0x20 +#define MVME7100_ABORT_MASK 0x10 + +/* + * Setup the architecture + */ +static void __init mvme7100_setup_arch(void) +{ + struct device_node *bcsr_node; + void __iomem *mvme7100_regs = NULL; + u8 reg; + + if (ppc_md.progress) + ppc_md.progress("mvme7100_setup_arch()", 0); + +#ifdef CONFIG_SMP + mpc86xx_smp_init(); +#endif + + fsl_pci_assign_primary(); + + /* Remap BCSR registers */ + bcsr_node = of_find_compatible_node(NULL, NULL, + "artesyn,mvme7100-bcsr"); + if (bcsr_node) { + mvme7100_regs = of_iomap(bcsr_node, 0); + of_node_put(bcsr_node); + } + + if (mvme7100_regs) { + /* Disable ds1375, max6649, and abort interrupts */ + reg = readb(mvme7100_regs + MVME7100_INTERRUPT_REG_2_OFFSET); + reg |= MVME7100_DS1375_MASK | MVME7100_MAX6649_MASK + | MVME7100_ABORT_MASK; + writeb(reg, mvme7100_regs + MVME7100_INTERRUPT_REG_2_OFFSET); + } else + pr_warn("Unable to map board registers\n"); + + pr_info("MVME7100 board from Artesyn\n"); +} + +/* + * Called very early, device-tree isn't unflattened + */ +static int __init mvme7100_probe(void) +{ + unsigned long root = of_get_flat_dt_root(); + + return of_flat_dt_is_compatible(root, "artesyn,MVME7100"); +} + +static void mvme7100_usb_host_fixup(struct pci_dev *pdev) +{ + unsigned int val; + + if (!machine_is(mvme7100)) + return; + + /* Ensure only ports 1 & 2 are enabled */ + pci_read_config_dword(pdev, 0xe0, &val); + pci_write_config_dword(pdev, 0xe0, (val & ~7) | 0x2); + + /* System clock is 48-MHz Oscillator and EHCI Enabled. */ + pci_write_config_dword(pdev, 0xe4, 1 << 5); +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB, + mvme7100_usb_host_fixup); + +machine_arch_initcall(mvme7100, mpc86xx_common_publish_devices); + +define_machine(mvme7100) { + .name = "MVME7100", + .probe = mvme7100_probe, + .setup_arch = mvme7100_setup_arch, + .init_IRQ = mpc86xx_init_irq, + .get_irq = mpic_get_irq, + .restart = fsl_rstcr_restart, + .time_init = mpc86xx_time_init, + .calibrate_decr = generic_calibrate_decr, + .progress = udbg_progress, +#ifdef CONFIG_PCI + .pcibios_fixup_bus = fsl_pcibios_fixup_bus, +#endif +}; -- cgit v1.2.3 From c223c90386bc2306510e0ceacd768a0123ff2a2f Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Tue, 17 May 2016 08:33:46 +0200 Subject: powerpc32: provide VIRT_CPU_ACCOUNTING This patch provides VIRT_CPU_ACCOUTING to PPC32 architecture. PPC32 doesn't have the PACA structure, so we use the task_info structure to store the accounting data. In order to reuse on PPC32 the PPC64 functions, all u64 data has been replaced by 'unsigned long' so that it is u32 on PPC32 and u64 on PPC64 Signed-off-by: Christophe Leroy Signed-off-by: Scott Wood --- arch/powerpc/Kconfig | 1 + arch/powerpc/include/asm/accounting.h | 24 ++++++++++ arch/powerpc/include/asm/cputime.h | 14 ++++-- arch/powerpc/include/asm/exception-64s.h | 2 +- arch/powerpc/include/asm/paca.h | 9 +--- arch/powerpc/include/asm/ppc_asm.h | 24 +++++----- arch/powerpc/include/asm/reg.h | 1 + arch/powerpc/include/asm/thread_info.h | 4 ++ arch/powerpc/kernel/asm-offsets.c | 23 +++++++-- arch/powerpc/kernel/entry_32.S | 17 +++++++ arch/powerpc/kernel/entry_64.S | 6 +-- arch/powerpc/kernel/exceptions-64e.S | 4 +- arch/powerpc/kernel/time.c | 81 +++++++++++++++++++++----------- arch/powerpc/platforms/Kconfig.cputype | 1 - arch/powerpc/xmon/xmon.c | 14 +++--- 15 files changed, 158 insertions(+), 67 deletions(-) create mode 100644 arch/powerpc/include/asm/accounting.h (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index ee82f9a09a85..394f9dc7be08 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -165,6 +165,7 @@ config PPC select ARCH_HAS_UBSAN_SANITIZE_ALL select ARCH_SUPPORTS_DEFERRED_STRUCT_PAGE_INIT select HAVE_LIVEPATCH if HAVE_DYNAMIC_FTRACE_WITH_REGS + select HAVE_VIRT_CPU_ACCOUNTING config GENERIC_CSUM def_bool CPU_LITTLE_ENDIAN diff --git a/arch/powerpc/include/asm/accounting.h b/arch/powerpc/include/asm/accounting.h new file mode 100644 index 000000000000..c133246df467 --- /dev/null +++ b/arch/powerpc/include/asm/accounting.h @@ -0,0 +1,24 @@ +/* + * Common time accounting prototypes and such for all ppc machines. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef __POWERPC_ACCOUNTING_H +#define __POWERPC_ACCOUNTING_H + +/* Stuff for accurate time accounting */ +struct cpu_accounting_data { + unsigned long user_time; /* accumulated usermode TB ticks */ + unsigned long system_time; /* accumulated system TB ticks */ + unsigned long user_time_scaled; /* accumulated usermode SPURR ticks */ + unsigned long starttime; /* TB value snapshot */ + unsigned long starttime_user; /* TB value on exit to usermode */ + unsigned long startspurr; /* SPURR value snapshot */ + unsigned long utime_sspurr; /* ->user_time when ->startspurr set */ +}; + +#endif diff --git a/arch/powerpc/include/asm/cputime.h b/arch/powerpc/include/asm/cputime.h index e2452550bcb1..2dfd4fc41f3e 100644 --- a/arch/powerpc/include/asm/cputime.h +++ b/arch/powerpc/include/asm/cputime.h @@ -90,11 +90,10 @@ static inline void setup_cputime_one_jiffy(void) static inline cputime64_t jiffies64_to_cputime64(const u64 jif) { u64 ct; - u64 sec; + u64 sec = jif; /* have to be a little careful about overflow */ - ct = jif % HZ; - sec = jif / HZ; + ct = do_div(sec, HZ); if (ct) { ct *= tb_ticks_per_sec; do_div(ct, HZ); @@ -230,7 +229,16 @@ static inline cputime_t clock_t_to_cputime(const unsigned long clk) #define cputime64_to_clock_t(ct) cputime_to_clock_t((cputime_t)(ct)) +/* + * PPC64 uses PACA which is task independent for storing accounting data while + * PPC32 uses struct thread_info, therefore at task switch the accounting data + * has to be populated in the new task + */ +#ifdef CONFIG_PPC64 static inline void arch_vtime_task_switch(struct task_struct *tsk) { } +#else +void arch_vtime_task_switch(struct task_struct *tsk); +#endif #endif /* __KERNEL__ */ #endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index 93ae809fe5ea..8bc38d179c36 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h @@ -287,7 +287,7 @@ do_kvm_##n: \ std r0,GPR0(r1); /* save r0 in stackframe */ \ std r10,GPR1(r1); /* save r1 in stackframe */ \ beq 4f; /* if from kernel mode */ \ - ACCOUNT_CPU_USER_ENTRY(r9, r10); \ + ACCOUNT_CPU_USER_ENTRY(r13, r9, r10); \ SAVE_PPR(area, r9, r10); \ 4: EXCEPTION_PROLOG_COMMON_2(area) \ EXCEPTION_PROLOG_COMMON_3(n) \ diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index 546540b91095..ad171e979ab0 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h @@ -25,6 +25,7 @@ #ifdef CONFIG_KVM_BOOK3S_64_HANDLER #include #endif +#include register struct paca_struct *local_paca asm("r13"); @@ -184,13 +185,7 @@ struct paca_struct { #endif /* Stuff for accurate time accounting */ - u64 user_time; /* accumulated usermode TB ticks */ - u64 system_time; /* accumulated system TB ticks */ - u64 user_time_scaled; /* accumulated usermode SPURR ticks */ - u64 starttime; /* TB value snapshot */ - u64 starttime_user; /* TB value on exit to usermode */ - u64 startspurr; /* SPURR value snapshot */ - u64 utime_sspurr; /* ->user_time when ->startspurr set */ + struct cpu_accounting_data accounting; u64 stolen_time; /* TB ticks taken by hypervisor */ u64 dtl_ridx; /* read index in dispatch log */ struct dtl_entry *dtl_curr; /* pointer corresponding to dtl_ridx */ diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h index 7b591f98edcc..96b06dc93b4c 100644 --- a/arch/powerpc/include/asm/ppc_asm.h +++ b/arch/powerpc/include/asm/ppc_asm.h @@ -24,27 +24,27 @@ */ #ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE -#define ACCOUNT_CPU_USER_ENTRY(ra, rb) -#define ACCOUNT_CPU_USER_EXIT(ra, rb) +#define ACCOUNT_CPU_USER_ENTRY(ptr, ra, rb) +#define ACCOUNT_CPU_USER_EXIT(ptr, ra, rb) #define ACCOUNT_STOLEN_TIME #else -#define ACCOUNT_CPU_USER_ENTRY(ra, rb) \ +#define ACCOUNT_CPU_USER_ENTRY(ptr, ra, rb) \ MFTB(ra); /* get timebase */ \ - ld rb,PACA_STARTTIME_USER(r13); \ - std ra,PACA_STARTTIME(r13); \ + PPC_LL rb, ACCOUNT_STARTTIME_USER(ptr); \ + PPC_STL ra, ACCOUNT_STARTTIME(ptr); \ subf rb,rb,ra; /* subtract start value */ \ - ld ra,PACA_USER_TIME(r13); \ + PPC_LL ra, ACCOUNT_USER_TIME(ptr); \ add ra,ra,rb; /* add on to user time */ \ - std ra,PACA_USER_TIME(r13); \ + PPC_STL ra, ACCOUNT_USER_TIME(ptr); \ -#define ACCOUNT_CPU_USER_EXIT(ra, rb) \ +#define ACCOUNT_CPU_USER_EXIT(ptr, ra, rb) \ MFTB(ra); /* get timebase */ \ - ld rb,PACA_STARTTIME(r13); \ - std ra,PACA_STARTTIME_USER(r13); \ + PPC_LL rb, ACCOUNT_STARTTIME(ptr); \ + PPC_STL ra, ACCOUNT_STARTTIME_USER(ptr); \ subf rb,rb,ra; /* subtract start value */ \ - ld ra,PACA_SYSTEM_TIME(r13); \ + PPC_LL ra, ACCOUNT_SYSTEM_TIME(ptr); \ add ra,ra,rb; /* add on to system time */ \ - std ra,PACA_SYSTEM_TIME(r13) + PPC_STL ra, ACCOUNT_SYSTEM_TIME(ptr) #ifdef CONFIG_PPC_SPLPAR #define ACCOUNT_STOLEN_TIME \ diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index 320136f5fe28..d383f13b9fac 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -1294,6 +1294,7 @@ static inline unsigned long mfvtb (void) asm volatile("mfspr %0, %1" : "=r" (rval) : \ "i" (SPRN_TBRU)); rval;}) #endif +#define mftb() mftbl() #endif /* !__powerpc64__ */ #define mttbl(v) asm volatile("mttbl %0":: "r"(v)) diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h index 8febc3f66d53..b21bb1f72314 100644 --- a/arch/powerpc/include/asm/thread_info.h +++ b/arch/powerpc/include/asm/thread_info.h @@ -33,6 +33,7 @@ #include #include #include +#include /* * low level task data. @@ -45,6 +46,9 @@ struct thread_info { unsigned long local_flags; /* private flags for thread */ #ifdef CONFIG_LIVEPATCH unsigned long *livepatch_sp; +#endif +#if defined(CONFIG_VIRT_CPU_ACCOUNTING_NATIVE) && defined(CONFIG_PPC32) + struct cpu_accounting_data accounting; #endif /* low level flags - has atomic operations done on it */ unsigned long flags ____cacheline_aligned_in_smp; diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 5b99f956e32f..047892869257 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -240,13 +240,28 @@ int main(void) DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); DEFINE(PACAKEXECSTATE, offsetof(struct paca_struct, kexec_state)); DEFINE(PACA_DSCR_DEFAULT, offsetof(struct paca_struct, dscr_default)); - DEFINE(PACA_STARTTIME, offsetof(struct paca_struct, starttime)); - DEFINE(PACA_STARTTIME_USER, offsetof(struct paca_struct, starttime_user)); - DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time)); - DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time)); + DEFINE(ACCOUNT_STARTTIME, + offsetof(struct paca_struct, accounting.starttime)); + DEFINE(ACCOUNT_STARTTIME_USER, + offsetof(struct paca_struct, accounting.starttime_user)); + DEFINE(ACCOUNT_USER_TIME, + offsetof(struct paca_struct, accounting.user_time)); + DEFINE(ACCOUNT_SYSTEM_TIME, + offsetof(struct paca_struct, accounting.system_time)); DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save)); DEFINE(PACA_NAPSTATELOST, offsetof(struct paca_struct, nap_state_lost)); DEFINE(PACA_SPRG_VDSO, offsetof(struct paca_struct, sprg_vdso)); +#else /* CONFIG_PPC64 */ +#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE + DEFINE(ACCOUNT_STARTTIME, + offsetof(struct thread_info, accounting.starttime)); + DEFINE(ACCOUNT_STARTTIME_USER, + offsetof(struct thread_info, accounting.starttime_user)); + DEFINE(ACCOUNT_USER_TIME, + offsetof(struct thread_info, accounting.user_time)); + DEFINE(ACCOUNT_SYSTEM_TIME, + offsetof(struct thread_info, accounting.system_time)); +#endif #endif /* CONFIG_PPC64 */ /* RTAS */ diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 2405631e91a2..9899032230b4 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -175,6 +175,12 @@ transfer_to_handler: addi r12,r12,-1 stw r12,4(r11) #endif +#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE + CURRENT_THREAD_INFO(r9, r1) + tophys(r9, r9) + ACCOUNT_CPU_USER_ENTRY(r9, r11, r12) +#endif + b 3f 2: /* if from kernel, check interrupted DOZE/NAP mode and @@ -398,6 +404,13 @@ BEGIN_FTR_SECTION lwarx r7,0,r1 END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX) stwcx. r0,0,r1 /* to clear the reservation */ +#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE + andi. r4,r8,MSR_PR + beq 3f + CURRENT_THREAD_INFO(r4, r1) + ACCOUNT_CPU_USER_EXIT(r4, r5, r7) +3: +#endif lwz r4,_LINK(r1) lwz r5,_CCR(r1) mtlr r4 @@ -769,6 +782,10 @@ restore_user: andis. r10,r0,DBCR0_IDM@h bnel- load_dbcr0 #endif +#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE + CURRENT_THREAD_INFO(r9, r1) + ACCOUNT_CPU_USER_EXIT(r9, r10, r11) +#endif b restore diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 2e0c565754aa..fcb2887f5a33 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -72,7 +72,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_TM) std r0,GPR0(r1) std r10,GPR1(r1) beq 2f /* if from kernel mode */ - ACCOUNT_CPU_USER_ENTRY(r10, r11) + ACCOUNT_CPU_USER_ENTRY(r13, r10, r11) 2: std r2,GPR2(r1) std r3,GPR3(r1) mfcr r2 @@ -246,7 +246,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS) ld r4,_LINK(r1) beq- 1f - ACCOUNT_CPU_USER_EXIT(r11, r12) + ACCOUNT_CPU_USER_EXIT(r13, r11, r12) BEGIN_FTR_SECTION HMT_MEDIUM_LOW @@ -859,7 +859,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) BEGIN_FTR_SECTION mtspr SPRN_PPR,r2 /* Restore PPR */ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) - ACCOUNT_CPU_USER_EXIT(r2, r4) + ACCOUNT_CPU_USER_EXIT(r13, r2, r4) REST_GPR(13, r1) 1: mtspr SPRN_SRR1,r3 diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S index 2d3b40fd9bac..38a1f96430e1 100644 --- a/arch/powerpc/kernel/exceptions-64e.S +++ b/arch/powerpc/kernel/exceptions-64e.S @@ -386,7 +386,7 @@ exc_##n##_common: \ std r10,_NIP(r1); /* save SRR0 to stackframe */ \ std r11,_MSR(r1); /* save SRR1 to stackframe */ \ beq 2f; /* if from kernel mode */ \ - ACCOUNT_CPU_USER_ENTRY(r10,r11);/* accounting (uses cr0+eq) */ \ + ACCOUNT_CPU_USER_ENTRY(r13,r10,r11);/* accounting (uses cr0+eq) */ \ 2: ld r3,excf+EX_R10(r13); /* get back r10 */ \ ld r4,excf+EX_R11(r13); /* get back r11 */ \ mfspr r5,scratch; /* get back r13 */ \ @@ -1059,7 +1059,7 @@ fast_exception_return: andi. r6,r10,MSR_PR REST_2GPRS(6, r1) beq 1f - ACCOUNT_CPU_USER_EXIT(r10, r11) + ACCOUNT_CPU_USER_EXIT(r13, r10, r11) ld r0,GPR13(r1) 1: stdcx. r0,0,r1 /* to clear the reservation */ diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 6b4d01d1ccf0..4e7759c8ca30 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -167,7 +167,15 @@ DEFINE_PER_CPU(unsigned long, cputime_scaled_last_delta); cputime_t cputime_one_jiffy; +#ifdef CONFIG_PPC_SPLPAR void (*dtl_consumer)(struct dtl_entry *, u64); +#endif + +#ifdef CONFIG_PPC64 +#define get_accounting(tsk) (&get_paca()->accounting) +#else +#define get_accounting(tsk) (&task_thread_info(tsk)->accounting) +#endif static void calc_cputime_factors(void) { @@ -187,7 +195,7 @@ static void calc_cputime_factors(void) * Read the SPURR on systems that have it, otherwise the PURR, * or if that doesn't exist return the timebase value passed in. */ -static u64 read_spurr(u64 tb) +static unsigned long read_spurr(unsigned long tb) { if (cpu_has_feature(CPU_FTR_SPURR)) return mfspr(SPRN_SPURR); @@ -250,8 +258,8 @@ static u64 scan_dispatch_log(u64 stop_tb) void accumulate_stolen_time(void) { u64 sst, ust; - u8 save_soft_enabled = local_paca->soft_enabled; + struct cpu_accounting_data *acct = &local_paca->accounting; /* We are called early in the exception entry, before * soft/hard_enabled are sync'ed to the expected state @@ -261,10 +269,10 @@ void accumulate_stolen_time(void) */ local_paca->soft_enabled = 0; - sst = scan_dispatch_log(local_paca->starttime_user); - ust = scan_dispatch_log(local_paca->starttime); - local_paca->system_time -= sst; - local_paca->user_time -= ust; + sst = scan_dispatch_log(acct->starttime_user); + ust = scan_dispatch_log(acct->starttime); + acct->system_time -= sst; + acct->user_time -= ust; local_paca->stolen_time += ust + sst; local_paca->soft_enabled = save_soft_enabled; @@ -276,7 +284,7 @@ static inline u64 calculate_stolen_time(u64 stop_tb) if (get_paca()->dtl_ridx != be64_to_cpu(get_lppaca()->dtl_idx)) { stolen = scan_dispatch_log(stop_tb); - get_paca()->system_time -= stolen; + get_paca()->accounting.system_time -= stolen; } stolen += get_paca()->stolen_time; @@ -296,27 +304,29 @@ static inline u64 calculate_stolen_time(u64 stop_tb) * Account time for a transition between system, hard irq * or soft irq state. */ -static u64 vtime_delta(struct task_struct *tsk, - u64 *sys_scaled, u64 *stolen) +static unsigned long vtime_delta(struct task_struct *tsk, + unsigned long *sys_scaled, + unsigned long *stolen) { - u64 now, nowscaled, deltascaled; - u64 udelta, delta, user_scaled; + unsigned long now, nowscaled, deltascaled; + unsigned long udelta, delta, user_scaled; + struct cpu_accounting_data *acct = get_accounting(tsk); WARN_ON_ONCE(!irqs_disabled()); now = mftb(); nowscaled = read_spurr(now); - get_paca()->system_time += now - get_paca()->starttime; - get_paca()->starttime = now; - deltascaled = nowscaled - get_paca()->startspurr; - get_paca()->startspurr = nowscaled; + acct->system_time += now - acct->starttime; + acct->starttime = now; + deltascaled = nowscaled - acct->startspurr; + acct->startspurr = nowscaled; *stolen = calculate_stolen_time(now); - delta = get_paca()->system_time; - get_paca()->system_time = 0; - udelta = get_paca()->user_time - get_paca()->utime_sspurr; - get_paca()->utime_sspurr = get_paca()->user_time; + delta = acct->system_time; + acct->system_time = 0; + udelta = acct->user_time - acct->utime_sspurr; + acct->utime_sspurr = acct->user_time; /* * Because we don't read the SPURR on every kernel entry/exit, @@ -338,14 +348,14 @@ static u64 vtime_delta(struct task_struct *tsk, *sys_scaled = deltascaled; } } - get_paca()->user_time_scaled += user_scaled; + acct->user_time_scaled += user_scaled; return delta; } void vtime_account_system(struct task_struct *tsk) { - u64 delta, sys_scaled, stolen; + unsigned long delta, sys_scaled, stolen; delta = vtime_delta(tsk, &sys_scaled, &stolen); account_system_time(tsk, 0, delta, sys_scaled); @@ -356,7 +366,7 @@ EXPORT_SYMBOL_GPL(vtime_account_system); void vtime_account_idle(struct task_struct *tsk) { - u64 delta, sys_scaled, stolen; + unsigned long delta, sys_scaled, stolen; delta = vtime_delta(tsk, &sys_scaled, &stolen); account_idle_time(delta + stolen); @@ -374,15 +384,32 @@ void vtime_account_idle(struct task_struct *tsk) void vtime_account_user(struct task_struct *tsk) { cputime_t utime, utimescaled; + struct cpu_accounting_data *acct = get_accounting(tsk); - utime = get_paca()->user_time; - utimescaled = get_paca()->user_time_scaled; - get_paca()->user_time = 0; - get_paca()->user_time_scaled = 0; - get_paca()->utime_sspurr = 0; + utime = acct->user_time; + utimescaled = acct->user_time_scaled; + acct->user_time = 0; + acct->user_time_scaled = 0; + acct->utime_sspurr = 0; account_user_time(tsk, utime, utimescaled); } +#ifdef CONFIG_PPC32 +/* + * Called from the context switch with interrupts disabled, to charge all + * accumulated times to the current process, and to prepare accounting on + * the next process. + */ +void arch_vtime_task_switch(struct task_struct *prev) +{ + struct cpu_accounting_data *acct = get_accounting(current); + + acct->starttime = get_accounting(prev)->starttime; + acct->system_time = 0; + acct->user_time = 0; +} +#endif /* CONFIG_PPC32 */ + #else /* ! CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ #define calc_cputime_factors() #endif diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index 77e9b8d591fb..f32edec13fd1 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype @@ -1,7 +1,6 @@ config PPC64 bool "64-bit kernel" default n - select HAVE_VIRT_CPU_ACCOUNTING select ZLIB_DEFLATE help This option selects whether a 32-bit or a 64-bit kernel diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index c5e155108be5..4f7c29d87ec3 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -2213,13 +2213,13 @@ static void dump_one_paca(int cpu) DUMP(p, subcore_sibling_mask, "x"); #endif - DUMP(p, user_time, "llx"); - DUMP(p, system_time, "llx"); - DUMP(p, user_time_scaled, "llx"); - DUMP(p, starttime, "llx"); - DUMP(p, starttime_user, "llx"); - DUMP(p, startspurr, "llx"); - DUMP(p, utime_sspurr, "llx"); + DUMP(p, accounting.user_time, "llx"); + DUMP(p, accounting.system_time, "llx"); + DUMP(p, accounting.user_time_scaled, "llx"); + DUMP(p, accounting.starttime, "llx"); + DUMP(p, accounting.starttime_user, "llx"); + DUMP(p, accounting.startspurr, "llx"); + DUMP(p, accounting.utime_sspurr, "llx"); DUMP(p, stolen_time, "llx"); #undef DUMP -- cgit v1.2.3 From 69a94d84c7efc7bc146b5a8d6f05f6ed6f2d4e8f Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 5 Jul 2016 15:04:01 +1000 Subject: powerpc/cell: Don't use flat device-tree after boot Some bit of SPU code was using the FDT rather than the expanded device-tree. Fix it. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/cell/spu_manage.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/spu_manage.c b/arch/powerpc/platforms/cell/spu_manage.c index c3327f3d8cf7..21b4bfb97200 100644 --- a/arch/powerpc/platforms/cell/spu_manage.c +++ b/arch/powerpc/platforms/cell/spu_manage.c @@ -535,8 +535,7 @@ static int __init init_affinity(void) if (of_has_vicinity()) { init_affinity_fw(); } else { - long root = of_get_flat_dt_root(); - if (of_flat_dt_is_compatible(root, "IBM,CPBW-1.0")) + if (of_machine_is_compatible("IBM,CPBW-1.0")) init_affinity_qs20_harcoded(); else printk("No affinity configuration found\n"); -- cgit v1.2.3 From b282788341933c4dcd462f3c93cb39b90334ed76 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 5 Jul 2016 15:04:02 +1000 Subject: powerpc/85xx/ge_imp3a: Don't use the flat device-tree after boot ge_imp3a_pic_init() is called way beyond the unflattening of the tree, it shouldn't be using of_flat_dt_* Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/85xx/ge_imp3a.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/85xx/ge_imp3a.c b/arch/powerpc/platforms/85xx/ge_imp3a.c index 11790e074c8a..55eefef0c0c7 100644 --- a/arch/powerpc/platforms/85xx/ge_imp3a.c +++ b/arch/powerpc/platforms/85xx/ge_imp3a.c @@ -47,9 +47,8 @@ void __init ge_imp3a_pic_init(void) struct mpic *mpic; struct device_node *np; struct device_node *cascade_node = NULL; - unsigned long root = of_get_flat_dt_root(); - if (of_flat_dt_is_compatible(root, "fsl,MPC8572DS-CAMP")) { + if (of_machine_is_compatible("fsl,MPC8572DS-CAMP")) { mpic = mpic_alloc(NULL, 0, MPIC_NO_RESET | MPIC_BIG_ENDIAN | -- cgit v1.2.3 From 5b0f9f83684dff40014ce1d3c09a6cad749d351f Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 5 Jul 2016 15:04:03 +1000 Subject: powerpc/85xx/mpc85xx_ds: Don't use the flat device-tree after boot Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/85xx/mpc85xx_ds.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c index f858306dba6a..64a7e8c16839 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c @@ -66,9 +66,7 @@ void __init mpc85xx_ds_pic_init(void) struct device_node *cascade_node = NULL; int cascade_irq; #endif - unsigned long root = of_get_flat_dt_root(); - - if (of_flat_dt_is_compatible(root, "fsl,MPC8572DS-CAMP")) { + if (of_machine_is_compatible("fsl,MPC8572DS-CAMP")) { mpic = mpic_alloc(NULL, 0, MPIC_NO_RESET | MPIC_BIG_ENDIAN | -- cgit v1.2.3 From acd3578ed9100565ef1b39685ec0e75e5124a0d6 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 5 Jul 2016 15:04:04 +1000 Subject: powerpc/85xx/mpc85xx_rdb: Don't use the flat device-tree after boot Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/85xx/mpc85xx_rdb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c index 3f4dad133338..761e504d22ef 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c @@ -47,13 +47,12 @@ void __init mpc85xx_rdb_pic_init(void) { struct mpic *mpic; - unsigned long root = of_get_flat_dt_root(); #ifdef CONFIG_QUICC_ENGINE struct device_node *np; #endif - if (of_flat_dt_is_compatible(root, "fsl,MPC85XXRDB-CAMP")) { + if (of_machine_is_compatible("fsl,MPC85XXRDB-CAMP")) { mpic = mpic_alloc(NULL, 0, MPIC_NO_RESET | MPIC_BIG_ENDIAN | MPIC_SINGLE_DEST_CPU, -- cgit v1.2.3 From f456834a6c1db36c290fdfe8ab53107adaf334e7 Mon Sep 17 00:00:00 2001 From: Ian Munsie Date: Thu, 14 Jul 2016 07:17:00 +1000 Subject: powerpc/powernv: Split cxl code out into a separate file The support for using the Mellanox CX4 in cxl mode will require additions to the PHB code. In preparation for this, move the existing cxl code out of pci-ioda.c into a separate pci-cxl.c file to keep things more organised. Signed-off-by: Ian Munsie Reviewed-by: Andrew Donnellan Reviewed-by: Frederic Barrat Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/Makefile | 1 + arch/powerpc/platforms/powernv/pci-cxl.c | 163 ++++++++++++++++++++++++++++++ arch/powerpc/platforms/powernv/pci-ioda.c | 159 +---------------------------- arch/powerpc/platforms/powernv/pci.h | 6 ++ 4 files changed, 173 insertions(+), 156 deletions(-) create mode 100644 arch/powerpc/platforms/powernv/pci-cxl.c (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile index cd9711e72df6..b5d98cb3f482 100644 --- a/arch/powerpc/platforms/powernv/Makefile +++ b/arch/powerpc/platforms/powernv/Makefile @@ -6,6 +6,7 @@ obj-y += opal-kmsg.o obj-$(CONFIG_SMP) += smp.o subcore.o subcore-asm.o obj-$(CONFIG_PCI) += pci.o pci-ioda.o npu-dma.o +obj-$(CONFIG_CXL_BASE) += pci-cxl.o obj-$(CONFIG_EEH) += eeh-powernv.o obj-$(CONFIG_PPC_SCOM) += opal-xscom.o obj-$(CONFIG_MEMORY_FAILURE) += opal-memory-errors.o diff --git a/arch/powerpc/platforms/powernv/pci-cxl.c b/arch/powerpc/platforms/powernv/pci-cxl.c new file mode 100644 index 000000000000..e0eeb00e00eb --- /dev/null +++ b/arch/powerpc/platforms/powernv/pci-cxl.c @@ -0,0 +1,163 @@ +/* + * Copyright 2014-2016 IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include + +#include "pci.h" + +struct device_node *pnv_pci_get_phb_node(struct pci_dev *dev) +{ + struct pci_controller *hose = pci_bus_to_host(dev->bus); + + return of_node_get(hose->dn); +} +EXPORT_SYMBOL(pnv_pci_get_phb_node); + +int pnv_phb_to_cxl_mode(struct pci_dev *dev, uint64_t mode) +{ + struct pci_controller *hose = pci_bus_to_host(dev->bus); + struct pnv_phb *phb = hose->private_data; + struct pnv_ioda_pe *pe; + int rc; + + pe = pnv_ioda_get_pe(dev); + if (!pe) + return -ENODEV; + + pe_info(pe, "Switching PHB to CXL\n"); + + rc = opal_pci_set_phb_cxl_mode(phb->opal_id, mode, pe->pe_number); + if (rc == OPAL_UNSUPPORTED) + dev_err(&dev->dev, "Required cxl mode not supported by firmware - update skiboot\n"); + else if (rc) + dev_err(&dev->dev, "opal_pci_set_phb_cxl_mode failed: %i\n", rc); + + return rc; +} +EXPORT_SYMBOL(pnv_phb_to_cxl_mode); + +/* Find PHB for cxl dev and allocate MSI hwirqs? + * Returns the absolute hardware IRQ number + */ +int pnv_cxl_alloc_hwirqs(struct pci_dev *dev, int num) +{ + struct pci_controller *hose = pci_bus_to_host(dev->bus); + struct pnv_phb *phb = hose->private_data; + int hwirq = msi_bitmap_alloc_hwirqs(&phb->msi_bmp, num); + + if (hwirq < 0) { + dev_warn(&dev->dev, "Failed to find a free MSI\n"); + return -ENOSPC; + } + + return phb->msi_base + hwirq; +} +EXPORT_SYMBOL(pnv_cxl_alloc_hwirqs); + +void pnv_cxl_release_hwirqs(struct pci_dev *dev, int hwirq, int num) +{ + struct pci_controller *hose = pci_bus_to_host(dev->bus); + struct pnv_phb *phb = hose->private_data; + + msi_bitmap_free_hwirqs(&phb->msi_bmp, hwirq - phb->msi_base, num); +} +EXPORT_SYMBOL(pnv_cxl_release_hwirqs); + +void pnv_cxl_release_hwirq_ranges(struct cxl_irq_ranges *irqs, + struct pci_dev *dev) +{ + struct pci_controller *hose = pci_bus_to_host(dev->bus); + struct pnv_phb *phb = hose->private_data; + int i, hwirq; + + for (i = 1; i < CXL_IRQ_RANGES; i++) { + if (!irqs->range[i]) + continue; + pr_devel("cxl release irq range 0x%x: offset: 0x%lx limit: %ld\n", + i, irqs->offset[i], + irqs->range[i]); + hwirq = irqs->offset[i] - phb->msi_base; + msi_bitmap_free_hwirqs(&phb->msi_bmp, hwirq, + irqs->range[i]); + } +} +EXPORT_SYMBOL(pnv_cxl_release_hwirq_ranges); + +int pnv_cxl_alloc_hwirq_ranges(struct cxl_irq_ranges *irqs, + struct pci_dev *dev, int num) +{ + struct pci_controller *hose = pci_bus_to_host(dev->bus); + struct pnv_phb *phb = hose->private_data; + int i, hwirq, try; + + memset(irqs, 0, sizeof(struct cxl_irq_ranges)); + + /* 0 is reserved for the multiplexed PSL DSI interrupt */ + for (i = 1; i < CXL_IRQ_RANGES && num; i++) { + try = num; + while (try) { + hwirq = msi_bitmap_alloc_hwirqs(&phb->msi_bmp, try); + if (hwirq >= 0) + break; + try /= 2; + } + if (!try) + goto fail; + + irqs->offset[i] = phb->msi_base + hwirq; + irqs->range[i] = try; + pr_devel("cxl alloc irq range 0x%x: offset: 0x%lx limit: %li\n", + i, irqs->offset[i], irqs->range[i]); + num -= try; + } + if (num) + goto fail; + + return 0; +fail: + pnv_cxl_release_hwirq_ranges(irqs, dev); + return -ENOSPC; +} +EXPORT_SYMBOL(pnv_cxl_alloc_hwirq_ranges); + +int pnv_cxl_get_irq_count(struct pci_dev *dev) +{ + struct pci_controller *hose = pci_bus_to_host(dev->bus); + struct pnv_phb *phb = hose->private_data; + + return phb->msi_bmp.irq_count; +} +EXPORT_SYMBOL(pnv_cxl_get_irq_count); + +int pnv_cxl_ioda_msi_setup(struct pci_dev *dev, unsigned int hwirq, + unsigned int virq) +{ + struct pci_controller *hose = pci_bus_to_host(dev->bus); + struct pnv_phb *phb = hose->private_data; + unsigned int xive_num = hwirq - phb->msi_base; + struct pnv_ioda_pe *pe; + int rc; + + if (!(pe = pnv_ioda_get_pe(dev))) + return -ENODEV; + + /* Assign XIVE to PE */ + rc = opal_pci_set_xive_pe(phb->opal_id, pe->pe_number, xive_num); + if (rc) { + pe_warn(pe, "%s: OPAL error %d setting msi_base 0x%x " + "hwirq 0x%x XIVE 0x%x PE\n", + pci_name(dev), rc, phb->msi_base, hwirq, xive_num); + return -EIO; + } + pnv_set_msi_irq_chip(phb, virq); + + return 0; +} +EXPORT_SYMBOL(pnv_cxl_ioda_msi_setup); diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 2115ed70440e..e0d810349d96 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -595,7 +595,7 @@ static int pnv_ioda_get_pe_state(struct pnv_phb *phb, int pe_no) * but in the meantime, we need to protect them to avoid warnings */ #ifdef CONFIG_PCI_MSI -static struct pnv_ioda_pe *pnv_ioda_get_pe(struct pci_dev *dev) +struct pnv_ioda_pe *pnv_ioda_get_pe(struct pci_dev *dev) { struct pci_controller *hose = pci_bus_to_host(dev->bus); struct pnv_phb *phb = hose->private_data; @@ -2700,7 +2700,7 @@ static void pnv_ioda2_msi_eoi(struct irq_data *d) } -static void set_msi_irq_chip(struct pnv_phb *phb, unsigned int virq) +void pnv_set_msi_irq_chip(struct pnv_phb *phb, unsigned int virq) { struct irq_data *idata; struct irq_chip *ichip; @@ -2722,159 +2722,6 @@ static void set_msi_irq_chip(struct pnv_phb *phb, unsigned int virq) irq_set_chip(virq, &phb->ioda.irq_chip); } -#ifdef CONFIG_CXL_BASE - -struct device_node *pnv_pci_get_phb_node(struct pci_dev *dev) -{ - struct pci_controller *hose = pci_bus_to_host(dev->bus); - - return of_node_get(hose->dn); -} -EXPORT_SYMBOL(pnv_pci_get_phb_node); - -int pnv_phb_to_cxl_mode(struct pci_dev *dev, uint64_t mode) -{ - struct pci_controller *hose = pci_bus_to_host(dev->bus); - struct pnv_phb *phb = hose->private_data; - struct pnv_ioda_pe *pe; - int rc; - - pe = pnv_ioda_get_pe(dev); - if (!pe) - return -ENODEV; - - pe_info(pe, "Switching PHB to CXL\n"); - - rc = opal_pci_set_phb_cxl_mode(phb->opal_id, mode, pe->pe_number); - if (rc == OPAL_UNSUPPORTED) - dev_err(&dev->dev, "Required cxl mode not supported by firmware - update skiboot\n"); - else if (rc) - dev_err(&dev->dev, "opal_pci_set_phb_cxl_mode failed: %i\n", rc); - - return rc; -} -EXPORT_SYMBOL(pnv_phb_to_cxl_mode); - -/* Find PHB for cxl dev and allocate MSI hwirqs? - * Returns the absolute hardware IRQ number - */ -int pnv_cxl_alloc_hwirqs(struct pci_dev *dev, int num) -{ - struct pci_controller *hose = pci_bus_to_host(dev->bus); - struct pnv_phb *phb = hose->private_data; - int hwirq = msi_bitmap_alloc_hwirqs(&phb->msi_bmp, num); - - if (hwirq < 0) { - dev_warn(&dev->dev, "Failed to find a free MSI\n"); - return -ENOSPC; - } - - return phb->msi_base + hwirq; -} -EXPORT_SYMBOL(pnv_cxl_alloc_hwirqs); - -void pnv_cxl_release_hwirqs(struct pci_dev *dev, int hwirq, int num) -{ - struct pci_controller *hose = pci_bus_to_host(dev->bus); - struct pnv_phb *phb = hose->private_data; - - msi_bitmap_free_hwirqs(&phb->msi_bmp, hwirq - phb->msi_base, num); -} -EXPORT_SYMBOL(pnv_cxl_release_hwirqs); - -void pnv_cxl_release_hwirq_ranges(struct cxl_irq_ranges *irqs, - struct pci_dev *dev) -{ - struct pci_controller *hose = pci_bus_to_host(dev->bus); - struct pnv_phb *phb = hose->private_data; - int i, hwirq; - - for (i = 1; i < CXL_IRQ_RANGES; i++) { - if (!irqs->range[i]) - continue; - pr_devel("cxl release irq range 0x%x: offset: 0x%lx limit: %ld\n", - i, irqs->offset[i], - irqs->range[i]); - hwirq = irqs->offset[i] - phb->msi_base; - msi_bitmap_free_hwirqs(&phb->msi_bmp, hwirq, - irqs->range[i]); - } -} -EXPORT_SYMBOL(pnv_cxl_release_hwirq_ranges); - -int pnv_cxl_alloc_hwirq_ranges(struct cxl_irq_ranges *irqs, - struct pci_dev *dev, int num) -{ - struct pci_controller *hose = pci_bus_to_host(dev->bus); - struct pnv_phb *phb = hose->private_data; - int i, hwirq, try; - - memset(irqs, 0, sizeof(struct cxl_irq_ranges)); - - /* 0 is reserved for the multiplexed PSL DSI interrupt */ - for (i = 1; i < CXL_IRQ_RANGES && num; i++) { - try = num; - while (try) { - hwirq = msi_bitmap_alloc_hwirqs(&phb->msi_bmp, try); - if (hwirq >= 0) - break; - try /= 2; - } - if (!try) - goto fail; - - irqs->offset[i] = phb->msi_base + hwirq; - irqs->range[i] = try; - pr_devel("cxl alloc irq range 0x%x: offset: 0x%lx limit: %li\n", - i, irqs->offset[i], irqs->range[i]); - num -= try; - } - if (num) - goto fail; - - return 0; -fail: - pnv_cxl_release_hwirq_ranges(irqs, dev); - return -ENOSPC; -} -EXPORT_SYMBOL(pnv_cxl_alloc_hwirq_ranges); - -int pnv_cxl_get_irq_count(struct pci_dev *dev) -{ - struct pci_controller *hose = pci_bus_to_host(dev->bus); - struct pnv_phb *phb = hose->private_data; - - return phb->msi_bmp.irq_count; -} -EXPORT_SYMBOL(pnv_cxl_get_irq_count); - -int pnv_cxl_ioda_msi_setup(struct pci_dev *dev, unsigned int hwirq, - unsigned int virq) -{ - struct pci_controller *hose = pci_bus_to_host(dev->bus); - struct pnv_phb *phb = hose->private_data; - unsigned int xive_num = hwirq - phb->msi_base; - struct pnv_ioda_pe *pe; - int rc; - - if (!(pe = pnv_ioda_get_pe(dev))) - return -ENODEV; - - /* Assign XIVE to PE */ - rc = opal_pci_set_xive_pe(phb->opal_id, pe->pe_number, xive_num); - if (rc) { - pe_warn(pe, "%s: OPAL error %d setting msi_base 0x%x " - "hwirq 0x%x XIVE 0x%x PE\n", - pci_name(dev), rc, phb->msi_base, hwirq, xive_num); - return -EIO; - } - set_msi_irq_chip(phb, virq); - - return 0; -} -EXPORT_SYMBOL(pnv_cxl_ioda_msi_setup); -#endif - static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev, unsigned int hwirq, unsigned int virq, unsigned int is_64, struct msi_msg *msg) @@ -2931,7 +2778,7 @@ static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev, } msg->data = be32_to_cpu(data); - set_msi_irq_chip(phb, virq); + pnv_set_msi_irq_chip(phb, virq); pr_devel("%s: %s-bit MSI on hwirq %x (xive #%d)," " address=%x_%08x data=%x PE# %d\n", diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index 3a97990a4dad..49c29973d717 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h @@ -1,6 +1,10 @@ #ifndef __POWERNV_PCI_H #define __POWERNV_PCI_H +#include +#include +#include + struct pci_dn; enum pnv_phb_type { @@ -212,6 +216,8 @@ extern void pnv_pci_dma_dev_setup(struct pci_dev *pdev); extern void pnv_pci_dma_bus_setup(struct pci_bus *bus); extern int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type); extern void pnv_teardown_msi_irqs(struct pci_dev *pdev); +extern struct pnv_ioda_pe *pnv_ioda_get_pe(struct pci_dev *dev); +extern void pnv_set_msi_irq_chip(struct pnv_phb *phb, unsigned int virq); extern void pe_level_printk(const struct pnv_ioda_pe *pe, const char *level, const char *fmt, ...); -- cgit v1.2.3 From 4361b03430d685610e5feea3ec7846e8b9ae795f Mon Sep 17 00:00:00 2001 From: Ian Munsie Date: Thu, 14 Jul 2016 07:17:06 +1000 Subject: powerpc/powernv: Add support for the cxl kernel api on the real phb This adds support for the peer model of the cxl kernel api to the PowerNV PHB, in which physical function 0 represents the cxl function on the card (an XSL in the case of the CX4), which other physical functions will use for memory access and interrupt services. It is referred to as the peer model as these functions are peers of one another, as opposed to the Virtual PHB model which forms a hierarchy. This patch exports APIs to enable the peer mode, check if a PCI device is attached to a PHB in this mode, and to set and get the peer AFU for this mode. The cxl driver will enable this mode for supported cards by calling pnv_cxl_enable_phb_kernel_api(). This will set a flag in the PHB to note that this mode is enabled, and switch out it's controller_ops for the cxl version. The cxl version of the controller_ops struct implements it's own versions of the enable_device_hook and release_device to handle refcounting on the peer AFU and to allocate a default context for the device. Once enabled, the cxl kernel API may not be disabled on a PHB. Currently there is no safe way to disable cxl mode short of a reboot, so until that changes there is no reason to support the disable path. Signed-off-by: Ian Munsie Reviewed-by: Andrew Donnellan Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/pnv-pci.h | 7 ++ arch/powerpc/platforms/powernv/pci-cxl.c | 120 ++++++++++++++++++++++++++++++ arch/powerpc/platforms/powernv/pci-ioda.c | 18 ++++- arch/powerpc/platforms/powernv/pci.h | 14 ++++ 4 files changed, 158 insertions(+), 1 deletion(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/include/asm/pnv-pci.h b/arch/powerpc/include/asm/pnv-pci.h index 791db1bbd4b9..c47097f7f6ab 100644 --- a/arch/powerpc/include/asm/pnv-pci.h +++ b/arch/powerpc/include/asm/pnv-pci.h @@ -38,6 +38,13 @@ int pnv_cxl_alloc_hwirq_ranges(struct cxl_irq_ranges *irqs, struct pci_dev *dev, int num); void pnv_cxl_release_hwirq_ranges(struct cxl_irq_ranges *irqs, struct pci_dev *dev); + +/* Support for the cxl kernel api on the real PHB (instead of vPHB) */ +int pnv_cxl_enable_phb_kernel_api(struct pci_controller *hose, bool enable); +bool pnv_pci_on_cxl_phb(struct pci_dev *dev); +struct cxl_afu *pnv_cxl_phb_to_afu(struct pci_controller *hose); +void pnv_cxl_phb_set_peer_afu(struct pci_dev *dev, struct cxl_afu *afu); + #endif #endif diff --git a/arch/powerpc/platforms/powernv/pci-cxl.c b/arch/powerpc/platforms/powernv/pci-cxl.c index e0eeb00e00eb..831bbfb4e278 100644 --- a/arch/powerpc/platforms/powernv/pci-cxl.c +++ b/arch/powerpc/platforms/powernv/pci-cxl.c @@ -7,8 +7,11 @@ * 2 of the License, or (at your option) any later version. */ +#include +#include #include #include +#include #include "pci.h" @@ -161,3 +164,120 @@ int pnv_cxl_ioda_msi_setup(struct pci_dev *dev, unsigned int hwirq, return 0; } EXPORT_SYMBOL(pnv_cxl_ioda_msi_setup); + +/* + * Sets flags and switches the controller ops to enable the cxl kernel api. + * Originally the cxl kernel API operated on a virtual PHB, but certain cards + * such as the Mellanox CX4 use a peer model instead and for these cards the + * cxl kernel api will operate on the real PHB. + */ +int pnv_cxl_enable_phb_kernel_api(struct pci_controller *hose, bool enable) +{ + struct pnv_phb *phb = hose->private_data; + struct module *cxl_module; + + if (!enable) { + /* + * Once cxl mode is enabled on the PHB, there is currently no + * known safe method to disable it again, and trying risks a + * checkstop. If we can find a way to safely disable cxl mode + * in the future we can revisit this, but for now the only sane + * thing to do is to refuse to disable cxl mode: + */ + return -EPERM; + } + + /* + * Hold a reference to the cxl module since several PHB operations now + * depend on it, and it would be insane to allow it to be removed so + * long as we are in this mode (and since we can't safely disable this + * mode once enabled...). + */ + mutex_lock(&module_mutex); + cxl_module = find_module("cxl"); + if (cxl_module) + __module_get(cxl_module); + mutex_unlock(&module_mutex); + if (!cxl_module) + return -ENODEV; + + phb->flags |= PNV_PHB_FLAG_CXL; + hose->controller_ops = pnv_cxl_cx4_ioda_controller_ops; + + return 0; +} +EXPORT_SYMBOL_GPL(pnv_cxl_enable_phb_kernel_api); + +bool pnv_pci_on_cxl_phb(struct pci_dev *dev) +{ + struct pci_controller *hose = pci_bus_to_host(dev->bus); + struct pnv_phb *phb = hose->private_data; + + return !!(phb->flags & PNV_PHB_FLAG_CXL); +} +EXPORT_SYMBOL_GPL(pnv_pci_on_cxl_phb); + +struct cxl_afu *pnv_cxl_phb_to_afu(struct pci_controller *hose) +{ + struct pnv_phb *phb = hose->private_data; + + return (struct cxl_afu *)phb->cxl_afu; +} +EXPORT_SYMBOL_GPL(pnv_cxl_phb_to_afu); + +void pnv_cxl_phb_set_peer_afu(struct pci_dev *dev, struct cxl_afu *afu) +{ + struct pci_controller *hose = pci_bus_to_host(dev->bus); + struct pnv_phb *phb = hose->private_data; + + phb->cxl_afu = afu; +} +EXPORT_SYMBOL_GPL(pnv_cxl_phb_set_peer_afu); + +/* + * In the peer cxl model, the XSL/PSL is physical function 0, and will be used + * by other functions on the device for memory access and interrupts. When the + * other functions are enabled we explicitly take a reference on the cxl + * function since they will use it, and allocate a default context associated + * with that function just like the vPHB model of the cxl kernel API. + */ +bool pnv_cxl_enable_device_hook(struct pci_dev *dev) +{ + struct pci_controller *hose = pci_bus_to_host(dev->bus); + struct pnv_phb *phb = hose->private_data; + struct cxl_afu *afu = phb->cxl_afu; + + if (!pnv_pci_enable_device_hook(dev)) + return false; + + + /* No special handling for the cxl function, which is always PF 0 */ + if (PCI_FUNC(dev->devfn) == 0) + return true; + + if (!afu) { + dev_WARN(&dev->dev, "Attempted to enable function > 0 on CXL PHB without a peer AFU\n"); + return false; + } + + dev_info(&dev->dev, "Enabling function on CXL enabled PHB with peer AFU\n"); + + /* Make sure the peer AFU can't go away while this device is active */ + cxl_afu_get(afu); + + return cxl_pci_associate_default_context(dev, afu); +} + +void pnv_cxl_disable_device(struct pci_dev *dev) +{ + struct pci_controller *hose = pci_bus_to_host(dev->bus); + struct pnv_phb *phb = hose->private_data; + struct cxl_afu *afu = phb->cxl_afu; + + /* No special handling for cxl function: */ + if (PCI_FUNC(dev->devfn) == 0) + return; + + cxl_pci_disable_device(dev); + cxl_afu_put(afu); +} diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index e0d810349d96..104c0405f47c 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -3222,7 +3222,7 @@ static resource_size_t pnv_pci_iov_resource_alignment(struct pci_dev *pdev, /* Prevent enabling devices for which we couldn't properly * assign a PE */ -static bool pnv_pci_enable_device_hook(struct pci_dev *dev) +bool pnv_pci_enable_device_hook(struct pci_dev *dev) { struct pci_controller *hose = pci_bus_to_host(dev->bus); struct pnv_phb *phb = hose->private_data; @@ -3461,6 +3461,22 @@ static const struct pci_controller_ops pnv_npu_ioda_controller_ops = { .shutdown = pnv_pci_ioda_shutdown, }; +#ifdef CONFIG_CXL_BASE +const struct pci_controller_ops pnv_cxl_cx4_ioda_controller_ops = { + .dma_dev_setup = pnv_pci_dma_dev_setup, + .dma_bus_setup = pnv_pci_dma_bus_setup, + .enable_device_hook = pnv_cxl_enable_device_hook, + .disable_device = pnv_cxl_disable_device, + .release_device = pnv_pci_release_device, + .window_alignment = pnv_pci_window_alignment, + .setup_bridge = pnv_pci_setup_bridge, + .reset_secondary_bus = pnv_pci_reset_secondary_bus, + .dma_set_mask = pnv_pci_ioda_dma_set_mask, + .dma_get_required_mask = pnv_pci_ioda_dma_get_required_mask, + .shutdown = pnv_pci_ioda_shutdown, +}; +#endif + static void __init pnv_pci_init_ioda_phb(struct device_node *np, u64 hub_id, int ioda_type) { diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index 49c29973d717..20c9a6b1c64d 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h @@ -76,6 +76,7 @@ struct pnv_ioda_pe { }; #define PNV_PHB_FLAG_EEH (1 << 0) +#define PNV_PHB_FLAG_CXL (1 << 1) /* Real PHB supporting the cxl kernel API */ struct pnv_phb { struct pci_controller *hose; @@ -177,6 +178,9 @@ struct pnv_phb { struct OpalIoP7IOCErrorData hub_diag; } diag; +#ifdef CONFIG_CXL_BASE + struct cxl_afu *cxl_afu; +#endif }; extern struct pci_ops pnv_pci_ops; @@ -218,6 +222,7 @@ extern int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type); extern void pnv_teardown_msi_irqs(struct pci_dev *pdev); extern struct pnv_ioda_pe *pnv_ioda_get_pe(struct pci_dev *dev); extern void pnv_set_msi_irq_chip(struct pnv_phb *phb, unsigned int virq); +extern bool pnv_pci_enable_device_hook(struct pci_dev *dev); extern void pe_level_printk(const struct pnv_ioda_pe *pe, const char *level, const char *fmt, ...); @@ -238,4 +243,13 @@ extern long pnv_npu_unset_window(struct pnv_ioda_pe *npe, int num); extern void pnv_npu_take_ownership(struct pnv_ioda_pe *npe); extern void pnv_npu_release_ownership(struct pnv_ioda_pe *npe); + +/* cxl functions */ +extern bool pnv_cxl_enable_device_hook(struct pci_dev *dev); +extern void pnv_cxl_disable_device(struct pci_dev *dev); + + +/* phb ops (cxl switches these when enabling the kernel api on the phb) */ +extern const struct pci_controller_ops pnv_cxl_cx4_ioda_controller_ops; + #endif /* __POWERNV_PCI_H */ -- cgit v1.2.3 From a2f67d5ee8d950caaa7a6144cf0bfb256500b73e Mon Sep 17 00:00:00 2001 From: Ian Munsie Date: Thu, 14 Jul 2016 07:17:10 +1000 Subject: cxl: Add support for interrupts on the Mellanox CX4 The Mellanox CX4 in cxl mode uses a hybrid interrupt model, where interrupts are routed from the networking hardware to the XSL using the MSIX table, and from there will be transformed back into an MSIX interrupt using the cxl style interrupts (i.e. using IVTE entries and ranges to map a PE and AFU interrupt number to an MSIX address). We want to hide the implementation details of cxl interrupts as much as possible. To this end, we use a special version of the MSI setup & teardown routines in the PHB while in cxl mode to allocate the cxl interrupts and configure the IVTE entries in the process element. This function does not configure the MSIX table - the CX4 card uses a custom format in that table and it would not be appropriate to fill that out in generic code. The rest of the functionality is similar to the "Full MSI-X mode" described in the CAIA, and this could be easily extended to support other adapters that use that mode in the future. The interrupts will be associated with the default context. If the maximum number of interrupts per context has been limited (e.g. by the mlx5 driver), it will automatically allocate additional kernel contexts to associate extra interrupts as required. These contexts will be started using the same WED that was used to start the default context. Signed-off-by: Ian Munsie Reviewed-by: Andrew Donnellan Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/pci-cxl.c | 84 +++++++++++++++++++++++++++++++ arch/powerpc/platforms/powernv/pci-ioda.c | 4 ++ arch/powerpc/platforms/powernv/pci.h | 2 + drivers/misc/cxl/api.c | 71 ++++++++++++++++++++++++++ drivers/misc/cxl/base.c | 31 ++++++++++++ drivers/misc/cxl/cxl.h | 4 ++ drivers/misc/cxl/main.c | 2 + include/misc/cxl-base.h | 4 ++ 8 files changed, 202 insertions(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powernv/pci-cxl.c b/arch/powerpc/platforms/powernv/pci-cxl.c index 831bbfb4e278..3f342077628b 100644 --- a/arch/powerpc/platforms/powernv/pci-cxl.c +++ b/arch/powerpc/platforms/powernv/pci-cxl.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -281,3 +282,86 @@ void pnv_cxl_disable_device(struct pci_dev *dev) cxl_pci_disable_device(dev); cxl_afu_put(afu); } + +/* + * This is a special version of pnv_setup_msi_irqs for cards in cxl mode. This + * function handles setting up the IVTE entries for the XSL to use. + * + * We are currently not filling out the MSIX table, since the only currently + * supported adapter (CX4) uses a custom MSIX table format in cxl mode and it + * is up to their driver to fill that out. In the future we may fill out the + * MSIX table (and change the IVTE entries to be an index to the MSIX table) + * for adapters implementing the Full MSI-X mode described in the CAIA. + */ +int pnv_cxl_cx4_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) +{ + struct pci_controller *hose = pci_bus_to_host(pdev->bus); + struct pnv_phb *phb = hose->private_data; + struct msi_desc *entry; + struct cxl_context *ctx = NULL; + unsigned int virq; + int hwirq; + int afu_irq = 0; + int rc; + + if (WARN_ON(!phb) || !phb->msi_bmp.bitmap) + return -ENODEV; + + if (pdev->no_64bit_msi && !phb->msi32_support) + return -ENODEV; + + rc = cxl_cx4_setup_msi_irqs(pdev, nvec, type); + if (rc) + return rc; + + for_each_pci_msi_entry(entry, pdev) { + if (!entry->msi_attrib.is_64 && !phb->msi32_support) { + pr_warn("%s: Supports only 64-bit MSIs\n", + pci_name(pdev)); + return -ENXIO; + } + + hwirq = cxl_next_msi_hwirq(pdev, &ctx, &afu_irq); + if (WARN_ON(hwirq <= 0)) + return (hwirq ? hwirq : -ENOMEM); + + virq = irq_create_mapping(NULL, hwirq); + if (virq == NO_IRQ) { + pr_warn("%s: Failed to map cxl mode MSI to linux irq\n", + pci_name(pdev)); + return -ENOMEM; + } + + rc = pnv_cxl_ioda_msi_setup(pdev, hwirq, virq); + if (rc) { + pr_warn("%s: Failed to setup cxl mode MSI\n", pci_name(pdev)); + irq_dispose_mapping(virq); + return rc; + } + + irq_set_msi_desc(virq, entry); + } + + return 0; +} + +void pnv_cxl_cx4_teardown_msi_irqs(struct pci_dev *pdev) +{ + struct pci_controller *hose = pci_bus_to_host(pdev->bus); + struct pnv_phb *phb = hose->private_data; + struct msi_desc *entry; + irq_hw_number_t hwirq; + + if (WARN_ON(!phb)) + return; + + for_each_pci_msi_entry(entry, pdev) { + if (entry->irq == NO_IRQ) + continue; + hwirq = virq_to_hw(entry->irq); + irq_set_msi_desc(entry->irq, NULL); + irq_dispose_mapping(entry->irq); + } + + cxl_cx4_teardown_msi_irqs(pdev); +} diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 104c0405f47c..530d4afbe2fd 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -3465,6 +3465,10 @@ static const struct pci_controller_ops pnv_npu_ioda_controller_ops = { const struct pci_controller_ops pnv_cxl_cx4_ioda_controller_ops = { .dma_dev_setup = pnv_pci_dma_dev_setup, .dma_bus_setup = pnv_pci_dma_bus_setup, +#ifdef CONFIG_PCI_MSI + .setup_msi_irqs = pnv_cxl_cx4_setup_msi_irqs, + .teardown_msi_irqs = pnv_cxl_cx4_teardown_msi_irqs, +#endif .enable_device_hook = pnv_cxl_enable_device_hook, .disable_device = pnv_cxl_disable_device, .release_device = pnv_pci_release_device, diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index 20c9a6b1c64d..f0c276c05f50 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h @@ -247,6 +247,8 @@ extern void pnv_npu_release_ownership(struct pnv_ioda_pe *npe); /* cxl functions */ extern bool pnv_cxl_enable_device_hook(struct pci_dev *dev); extern void pnv_cxl_disable_device(struct pci_dev *dev); +extern int pnv_cxl_cx4_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type); +extern void pnv_cxl_cx4_teardown_msi_irqs(struct pci_dev *pdev); /* phb ops (cxl switches these when enabling the kernel api on the phb) */ diff --git a/drivers/misc/cxl/api.c b/drivers/misc/cxl/api.c index f02a85974e49..f3d34b941f85 100644 --- a/drivers/misc/cxl/api.c +++ b/drivers/misc/cxl/api.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "cxl.h" @@ -489,3 +490,73 @@ int cxl_get_max_irqs_per_process(struct pci_dev *dev) return afu->irqs_max; } EXPORT_SYMBOL_GPL(cxl_get_max_irqs_per_process); + +/* + * This is a special interrupt allocation routine called from the PHB's MSI + * setup function. When capi interrupts are allocated in this manner they must + * still be associated with a running context, but since the MSI APIs have no + * way to specify this we use the default context associated with the device. + * + * The Mellanox CX4 has a hardware limitation that restricts the maximum AFU + * interrupt number, so in order to overcome this their driver informs us of + * the restriction by setting the maximum interrupts per context, and we + * allocate additional contexts as necessary so that we can keep the AFU + * interrupt number within the supported range. + */ +int _cxl_cx4_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) +{ + struct cxl_context *ctx, *new_ctx, *default_ctx; + int remaining; + int rc; + + ctx = default_ctx = cxl_get_context(pdev); + if (WARN_ON(!default_ctx)) + return -ENODEV; + + remaining = nvec; + while (remaining > 0) { + rc = cxl_allocate_afu_irqs(ctx, min(remaining, ctx->afu->irqs_max)); + if (rc) { + pr_warn("%s: Failed to find enough free MSIs\n", pci_name(pdev)); + return rc; + } + remaining -= ctx->afu->irqs_max; + + if (ctx != default_ctx && default_ctx->status == STARTED) { + WARN_ON(cxl_start_context(ctx, + be64_to_cpu(default_ctx->elem->common.wed), + NULL)); + } + + if (remaining > 0) { + new_ctx = cxl_dev_context_init(pdev); + if (!new_ctx) { + pr_warn("%s: Failed to allocate enough contexts for MSIs\n", pci_name(pdev)); + return -ENOSPC; + } + list_add(&new_ctx->extra_irq_contexts, &ctx->extra_irq_contexts); + ctx = new_ctx; + } + } + + return 0; +} +/* Exported via cxl_base */ + +void _cxl_cx4_teardown_msi_irqs(struct pci_dev *pdev) +{ + struct cxl_context *ctx, *pos, *tmp; + + ctx = cxl_get_context(pdev); + if (WARN_ON(!ctx)) + return; + + cxl_free_afu_irqs(ctx); + list_for_each_entry_safe(pos, tmp, &ctx->extra_irq_contexts, extra_irq_contexts) { + cxl_stop_context(pos); + cxl_free_afu_irqs(pos); + list_del(&pos->extra_irq_contexts); + cxl_release_context(pos); + } +} +/* Exported via cxl_base */ diff --git a/drivers/misc/cxl/base.c b/drivers/misc/cxl/base.c index fe90f895bb10..cd54ce6f6230 100644 --- a/drivers/misc/cxl/base.c +++ b/drivers/misc/cxl/base.c @@ -158,6 +158,37 @@ int cxl_next_msi_hwirq(struct pci_dev *pdev, struct cxl_context **ctx, int *afu_ } EXPORT_SYMBOL_GPL(cxl_next_msi_hwirq); +int cxl_cx4_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) +{ + int ret; + struct cxl_calls *calls; + + calls = cxl_calls_get(); + if (!calls) + return false; + + ret = calls->cxl_cx4_setup_msi_irqs(pdev, nvec, type); + + cxl_calls_put(calls); + + return ret; +} +EXPORT_SYMBOL_GPL(cxl_cx4_setup_msi_irqs); + +void cxl_cx4_teardown_msi_irqs(struct pci_dev *pdev) +{ + struct cxl_calls *calls; + + calls = cxl_calls_get(); + if (!calls) + return; + + calls->cxl_cx4_teardown_msi_irqs(pdev); + + cxl_calls_put(calls); +} +EXPORT_SYMBOL_GPL(cxl_cx4_teardown_msi_irqs); + static int __init cxl_base_init(void) { struct device_node *np; diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h index 73b9a55aa35b..d50cdb137c43 100644 --- a/drivers/misc/cxl/cxl.h +++ b/drivers/misc/cxl/cxl.h @@ -731,12 +731,16 @@ ssize_t cxl_pci_afu_read_err_buffer(struct cxl_afu *afu, char *buf, bool _cxl_pci_associate_default_context(struct pci_dev *dev, struct cxl_afu *afu); void _cxl_pci_disable_device(struct pci_dev *dev); int _cxl_next_msi_hwirq(struct pci_dev *pdev, struct cxl_context **ctx, int *afu_irq); +int _cxl_cx4_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type); +void _cxl_cx4_teardown_msi_irqs(struct pci_dev *pdev); struct cxl_calls { void (*cxl_slbia)(struct mm_struct *mm); bool (*cxl_pci_associate_default_context)(struct pci_dev *dev, struct cxl_afu *afu); void (*cxl_pci_disable_device)(struct pci_dev *dev); int (*cxl_next_msi_hwirq)(struct pci_dev *pdev, struct cxl_context **ctx, int *afu_irq); + int (*cxl_cx4_setup_msi_irqs)(struct pci_dev *pdev, int nvec, int type); + void (*cxl_cx4_teardown_msi_irqs)(struct pci_dev *pdev); struct module *owner; }; diff --git a/drivers/misc/cxl/main.c b/drivers/misc/cxl/main.c index 66fac713e7ad..d9be23b24aa3 100644 --- a/drivers/misc/cxl/main.c +++ b/drivers/misc/cxl/main.c @@ -113,6 +113,8 @@ static struct cxl_calls cxl_calls = { .cxl_pci_associate_default_context = _cxl_pci_associate_default_context, .cxl_pci_disable_device = _cxl_pci_disable_device, .cxl_next_msi_hwirq = _cxl_next_msi_hwirq, + .cxl_cx4_setup_msi_irqs = _cxl_cx4_setup_msi_irqs, + .cxl_cx4_teardown_msi_irqs = _cxl_cx4_teardown_msi_irqs, .owner = THIS_MODULE, }; diff --git a/include/misc/cxl-base.h b/include/misc/cxl-base.h index bb7e629ae492..b2ebc91fe09a 100644 --- a/include/misc/cxl-base.h +++ b/include/misc/cxl-base.h @@ -43,6 +43,8 @@ void cxl_afu_put(struct cxl_afu *afu); void cxl_slbia(struct mm_struct *mm); bool cxl_pci_associate_default_context(struct pci_dev *dev, struct cxl_afu *afu); void cxl_pci_disable_device(struct pci_dev *dev); +int cxl_cx4_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type); +void cxl_cx4_teardown_msi_irqs(struct pci_dev *pdev); #else /* CONFIG_CXL_BASE */ @@ -52,6 +54,8 @@ static inline void cxl_afu_put(struct cxl_afu *afu) {} static inline void cxl_slbia(struct mm_struct *mm) {} static inline bool cxl_pci_associate_default_context(struct pci_dev *dev, struct cxl_afu *afu) { return false; } static inline void cxl_pci_disable_device(struct pci_dev *dev) {} +static inline int cxl_cx4_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) { return -ENODEV; } +static inline void cxl_cx4_teardown_msi_irqs(struct pci_dev *pdev) {} #endif /* CONFIG_CXL_BASE */ -- cgit v1.2.3 From c011926fcbeb9565599f278148b91e536a07b68a Mon Sep 17 00:00:00 2001 From: Anna-Maria Gleixner Date: Mon, 4 Apr 2016 11:30:01 +0200 Subject: powerpc/pmac/smp: Add missing FROZEN hotplug notifier transitions The FROZEN transitions are used when a CPU suspends/resumes. In case of a suspend/resume, only the up prepare (CPU_UP_PREPARE_FROZEN) is handled. The error handling transition CPU_UP_CANCELED_FROZEN as well as the CPU_ONLINE_FROZEN transition are not handled. Masking the switch case action argument with ~CPU_TASKS_FROZEN, to handle all FROZEN tasks the same way than the corresponding non frozen tasks. Cc: Benjamin Herrenschmidt Cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Anna-Maria Gleixner Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powermac/smp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index 28a147ca32ba..834868b9fdc9 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c @@ -857,9 +857,8 @@ static int smp_core99_cpu_notify(struct notifier_block *self, { int rc; - switch(action) { + switch(action & ~CPU_TASKS_FROZEN) { case CPU_UP_PREPARE: - case CPU_UP_PREPARE_FROZEN: /* Open i2c bus if it was used for tb sync */ if (pmac_tb_clock_chip_host) { rc = pmac_i2c_open(pmac_tb_clock_chip_host, 1); -- cgit v1.2.3 From 95ec77c06e8e63fff50c497eca0668bf6da39813 Mon Sep 17 00:00:00 2001 From: Daniel Axtens Date: Tue, 12 Jul 2016 10:54:52 +1000 Subject: powerpc: Make ppc_md.{halt, restart} __noreturn powernv marks it's halt and restart calls as __noreturn. However, ppc_md does not have this annotation. Add the annotation to ppc_md, and then to every halt/restart function that is missing it. Additionally, I have verified that all of these functions do not return. Occasionally I have added a spin loop to be sure. Signed-off-by: Daniel Axtens Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/machdep.h | 4 ++-- arch/powerpc/include/asm/mpc52xx.h | 2 +- arch/powerpc/include/asm/ppc4xx.h | 2 +- arch/powerpc/include/asm/rtas.h | 4 ++-- arch/powerpc/kernel/rtas.c | 4 ++-- arch/powerpc/platforms/44x/ppc476.c | 4 ++-- arch/powerpc/platforms/512x/mpc512x.h | 2 +- arch/powerpc/platforms/512x/mpc512x_shared.c | 2 +- arch/powerpc/platforms/52xx/mpc52xx_common.c | 3 +-- arch/powerpc/platforms/82xx/pq2.c | 2 +- arch/powerpc/platforms/82xx/pq2.h | 2 +- arch/powerpc/platforms/83xx/misc.c | 2 +- arch/powerpc/platforms/83xx/mpc83xx.h | 2 +- arch/powerpc/platforms/85xx/ksi8560.c | 2 +- arch/powerpc/platforms/85xx/mpc85xx_cds.c | 2 +- arch/powerpc/platforms/8xx/m8xx_setup.c | 2 +- arch/powerpc/platforms/8xx/mpc8xx.h | 2 +- arch/powerpc/platforms/amigaone/setup.c | 2 +- arch/powerpc/platforms/chrp/setup.c | 2 +- arch/powerpc/platforms/embedded6xx/c2k.c | 2 +- arch/powerpc/platforms/embedded6xx/gamecube.c | 6 +++--- arch/powerpc/platforms/embedded6xx/holly.c | 2 +- arch/powerpc/platforms/embedded6xx/linkstation.c | 6 +++--- arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c | 2 +- arch/powerpc/platforms/embedded6xx/mvme5100.c | 2 +- arch/powerpc/platforms/embedded6xx/storcenter.c | 2 +- arch/powerpc/platforms/embedded6xx/wii.c | 6 +++--- arch/powerpc/platforms/maple/setup.c | 8 +++++--- arch/powerpc/platforms/pasemi/setup.c | 2 +- arch/powerpc/platforms/powermac/setup.c | 12 +++++++----- arch/powerpc/platforms/ps3/setup.c | 4 ++-- arch/powerpc/sysdev/fsl_soc.c | 8 +++++--- arch/powerpc/sysdev/fsl_soc.h | 6 +++--- 33 files changed, 60 insertions(+), 55 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index 6bdcd0da9e21..a9af1bd6a51e 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h @@ -111,8 +111,8 @@ struct machdep_calls { /* To setup PHBs when using automatic OF platform driver for PCI */ int (*pci_setup_phb)(struct pci_controller *host); - void (*restart)(char *cmd); - void (*halt)(void); + void __noreturn (*restart)(char *cmd); + void __noreturn (*halt)(void); void (*panic)(char *str); void (*cpu_die)(void); diff --git a/arch/powerpc/include/asm/mpc52xx.h b/arch/powerpc/include/asm/mpc52xx.h index 0acc7c7c28d1..e94cede14522 100644 --- a/arch/powerpc/include/asm/mpc52xx.h +++ b/arch/powerpc/include/asm/mpc52xx.h @@ -275,7 +275,7 @@ extern int mpc5200_psc_ac97_gpio_reset(int psc_number); extern void mpc52xx_map_common_devices(void); extern int mpc52xx_set_psc_clkdiv(int psc_id, int clkdiv); extern unsigned int mpc52xx_get_xtal_freq(struct device_node *node); -extern void mpc52xx_restart(char *cmd); +extern void __noreturn mpc52xx_restart(char *cmd); /* mpc52xx_gpt.c */ struct mpc52xx_gpt_priv; diff --git a/arch/powerpc/include/asm/ppc4xx.h b/arch/powerpc/include/asm/ppc4xx.h index 033039a80c42..610a5119ad8c 100644 --- a/arch/powerpc/include/asm/ppc4xx.h +++ b/arch/powerpc/include/asm/ppc4xx.h @@ -13,6 +13,6 @@ #ifndef __ASM_POWERPC_PPC4xx_H__ #define __ASM_POWERPC_PPC4xx_H__ -extern void ppc4xx_reset_system(char *cmd); +extern void __noreturn ppc4xx_reset_system(char *cmd); #endif /* __ASM_POWERPC_PPC4xx_H__ */ diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h index 51400baa8d48..fa3e3c4367bd 100644 --- a/arch/powerpc/include/asm/rtas.h +++ b/arch/powerpc/include/asm/rtas.h @@ -339,9 +339,9 @@ extern int rtas_service_present(const char *service); extern int rtas_call(int token, int, int, int *, ...); void rtas_call_unlocked(struct rtas_args *args, int token, int nargs, int nret, ...); -extern void rtas_restart(char *cmd); +extern void __noreturn rtas_restart(char *cmd); extern void rtas_power_off(void); -extern void rtas_halt(void); +extern void __noreturn rtas_halt(void); extern void rtas_os_term(char *str); extern int rtas_get_sensor(int sensor, int index, int *state); extern int rtas_get_sensor_fast(int sensor, int index, int *state); diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 286354f00ff6..6a3e5de544ce 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -685,7 +685,7 @@ int rtas_set_indicator_fast(int indicator, int index, int new_value) return rc; } -void rtas_restart(char *cmd) +void __noreturn rtas_restart(char *cmd) { if (rtas_flash_term_hook) rtas_flash_term_hook(SYS_RESTART); @@ -704,7 +704,7 @@ void rtas_power_off(void) for (;;); } -void rtas_halt(void) +void __noreturn rtas_halt(void) { if (rtas_flash_term_hook) rtas_flash_term_hook(SYS_HALT); diff --git a/arch/powerpc/platforms/44x/ppc476.c b/arch/powerpc/platforms/44x/ppc476.c index c11ce6516c8f..003973f65297 100644 --- a/arch/powerpc/platforms/44x/ppc476.c +++ b/arch/powerpc/platforms/44x/ppc476.c @@ -68,7 +68,7 @@ DECLARE_PCI_FIXUP_HEADER(0x1033, 0x0035, quirk_ppc_currituck_usb_fixup); #define AVR_PWRCTL_RESET (0x02) static struct i2c_client *avr_i2c_client; -static void avr_halt_system(int pwrctl_flags) +static void __noreturn avr_halt_system(int pwrctl_flags) { /* Request the AVR to reset the system */ i2c_smbus_write_byte_data(avr_i2c_client, @@ -84,7 +84,7 @@ static void avr_power_off_system(void) avr_halt_system(AVR_PWRCTL_PWROFF); } -static void avr_reset_system(char *cmd) +static void __noreturn avr_reset_system(char *cmd) { avr_halt_system(AVR_PWRCTL_RESET); } diff --git a/arch/powerpc/platforms/512x/mpc512x.h b/arch/powerpc/platforms/512x/mpc512x.h index cc97f022d028..14ba49fd7938 100644 --- a/arch/powerpc/platforms/512x/mpc512x.h +++ b/arch/powerpc/platforms/512x/mpc512x.h @@ -18,6 +18,6 @@ extern void __init mpc512x_setup_arch(void); extern int __init mpc5121_clk_init(void); extern const char *mpc512x_select_psc_compat(void); extern const char *mpc512x_select_reset_compat(void); -extern void mpc512x_restart(char *cmd); +extern void __noreturn mpc512x_restart(char *cmd); #endif /* __MPC512X_H__ */ diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c index 452da2391153..6b4f4cb7009a 100644 --- a/arch/powerpc/platforms/512x/mpc512x_shared.c +++ b/arch/powerpc/platforms/512x/mpc512x_shared.c @@ -47,7 +47,7 @@ static void __init mpc512x_restart_init(void) of_node_put(np); } -void mpc512x_restart(char *cmd) +void __noreturn mpc512x_restart(char *cmd) { if (reset_module_base) { /* Enable software reset "RSTE" */ diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c index 26993826a797..565e3a83dc9e 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_common.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c @@ -243,8 +243,7 @@ EXPORT_SYMBOL(mpc52xx_get_xtal_freq); /** * mpc52xx_restart: ppc_md->restart hook for mpc5200 using the watchdog timer */ -void -mpc52xx_restart(char *cmd) +void __noreturn mpc52xx_restart(char *cmd) { local_irq_disable(); diff --git a/arch/powerpc/platforms/82xx/pq2.c b/arch/powerpc/platforms/82xx/pq2.c index fc8b2d6a7d8d..c4f7029fc9ae 100644 --- a/arch/powerpc/platforms/82xx/pq2.c +++ b/arch/powerpc/platforms/82xx/pq2.c @@ -22,7 +22,7 @@ #define RMR_CSRE 0x00000001 -void pq2_restart(char *cmd) +void __noreturn pq2_restart(char *cmd) { local_irq_disable(); setbits32(&cpm2_immr->im_clkrst.car_rmr, RMR_CSRE); diff --git a/arch/powerpc/platforms/82xx/pq2.h b/arch/powerpc/platforms/82xx/pq2.h index a41f84ae2325..3080ce3441c1 100644 --- a/arch/powerpc/platforms/82xx/pq2.h +++ b/arch/powerpc/platforms/82xx/pq2.h @@ -1,7 +1,7 @@ #ifndef _PQ2_H #define _PQ2_H -void pq2_restart(char *cmd); +void __noreturn pq2_restart(char *cmd); #ifdef CONFIG_PCI int pq2ads_pci_init_irq(void); diff --git a/arch/powerpc/platforms/83xx/misc.c b/arch/powerpc/platforms/83xx/misc.c index 7e923cad56cf..8899aa9d11f5 100644 --- a/arch/powerpc/platforms/83xx/misc.c +++ b/arch/powerpc/platforms/83xx/misc.c @@ -35,7 +35,7 @@ static int __init mpc83xx_restart_init(void) arch_initcall(mpc83xx_restart_init); -void mpc83xx_restart(char *cmd) +void __noreturn mpc83xx_restart(char *cmd) { #define RST_OFFSET 0x00000900 #define RST_PROT_REG 0x00000018 diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h index 0cf74d7ea1c5..ad484199eff7 100644 --- a/arch/powerpc/platforms/83xx/mpc83xx.h +++ b/arch/powerpc/platforms/83xx/mpc83xx.h @@ -65,7 +65,7 @@ * mpc83xx_* files. Mostly for use by mpc83xx_setup */ -extern void mpc83xx_restart(char *cmd); +extern void __noreturn mpc83xx_restart(char *cmd); extern long mpc83xx_time_init(void); extern int mpc837x_usb_cfg(void); extern int mpc834x_usb_cfg(void); diff --git a/arch/powerpc/platforms/85xx/ksi8560.c b/arch/powerpc/platforms/85xx/ksi8560.c index 3dc1bda3ddc3..867a1078b488 100644 --- a/arch/powerpc/platforms/85xx/ksi8560.c +++ b/arch/powerpc/platforms/85xx/ksi8560.c @@ -44,7 +44,7 @@ static void __iomem *cpld_base = NULL; -static void machine_restart(char *cmd) +static void __noreturn machine_restart(char *cmd) { if (cpld_base) out_8(cpld_base + KSI8560_CPLD_RCR1, KSI8560_CPLD_RCR1_CPUHR); diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c index d7e87ff912d7..5e0a0a24d5ce 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c @@ -83,7 +83,7 @@ static int mpc85xx_exclude_device(struct pci_controller *hose, return PCIBIOS_SUCCESSFUL; } -static void mpc85xx_cds_restart(char *cmd) +static void __noreturn mpc85xx_cds_restart(char *cmd) { struct pci_dev *dev; u_char tmp; diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c index c289fc77b4ba..b1ab6e96cb31 100644 --- a/arch/powerpc/platforms/8xx/m8xx_setup.c +++ b/arch/powerpc/platforms/8xx/m8xx_setup.c @@ -198,7 +198,7 @@ void mpc8xx_get_rtc_time(struct rtc_time *tm) return; } -void mpc8xx_restart(char *cmd) +void __noreturn mpc8xx_restart(char *cmd) { car8xx_t __iomem *clk_r = immr_map(im_clkrst); diff --git a/arch/powerpc/platforms/8xx/mpc8xx.h b/arch/powerpc/platforms/8xx/mpc8xx.h index 239a243a6161..31cc2ecace42 100644 --- a/arch/powerpc/platforms/8xx/mpc8xx.h +++ b/arch/powerpc/platforms/8xx/mpc8xx.h @@ -11,7 +11,7 @@ #ifndef __MPC8xx_H #define __MPC8xx_H -extern void mpc8xx_restart(char *cmd); +extern void __noreturn mpc8xx_restart(char *cmd); extern void mpc8xx_calibrate_decr(void); extern int mpc8xx_set_rtc_time(struct rtc_time *tm); extern void mpc8xx_get_rtc_time(struct rtc_time *tm); diff --git a/arch/powerpc/platforms/amigaone/setup.c b/arch/powerpc/platforms/amigaone/setup.c index 2fe12046279e..3e12d8789252 100644 --- a/arch/powerpc/platforms/amigaone/setup.c +++ b/arch/powerpc/platforms/amigaone/setup.c @@ -123,7 +123,7 @@ static int __init request_isa_regions(void) } machine_device_initcall(amigaone, request_isa_regions); -void amigaone_restart(char *cmd) +void __noreturn amigaone_restart(char *cmd) { local_irq_disable(); diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 987d1b8d68e3..c55002f01dc1 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -239,7 +239,7 @@ out: of_node_put(np); } -static void briq_restart(char *cmd) +static void __noreturn briq_restart(char *cmd) { local_irq_disable(); if (briq_SPOR) diff --git a/arch/powerpc/platforms/embedded6xx/c2k.c b/arch/powerpc/platforms/embedded6xx/c2k.c index ebd3963fdf91..782066245bb5 100644 --- a/arch/powerpc/platforms/embedded6xx/c2k.c +++ b/arch/powerpc/platforms/embedded6xx/c2k.c @@ -99,7 +99,7 @@ static void c2k_reset_board(void) out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_VALUE_SET, 0x00080004); } -static void c2k_restart(char *cmd) +static void __noreturn c2k_restart(char *cmd) { c2k_reset_board(); msleep(100); diff --git a/arch/powerpc/platforms/embedded6xx/gamecube.c b/arch/powerpc/platforms/embedded6xx/gamecube.c index fe0ed6ee285e..b17705c3f7a4 100644 --- a/arch/powerpc/platforms/embedded6xx/gamecube.c +++ b/arch/powerpc/platforms/embedded6xx/gamecube.c @@ -29,14 +29,14 @@ #include "usbgecko_udbg.h" -static void gamecube_spin(void) +static void __noreturn gamecube_spin(void) { /* spin until power button pressed */ for (;;) cpu_relax(); } -static void gamecube_restart(char *cmd) +static void __noreturn gamecube_restart(char *cmd) { local_irq_disable(); flipper_platform_reset(); @@ -49,7 +49,7 @@ static void gamecube_power_off(void) gamecube_spin(); } -static void gamecube_halt(void) +static void __noreturn gamecube_halt(void) { gamecube_restart(NULL); } diff --git a/arch/powerpc/platforms/embedded6xx/holly.c b/arch/powerpc/platforms/embedded6xx/holly.c index 8c305c7c8977..8b6e76100895 100644 --- a/arch/powerpc/platforms/embedded6xx/holly.c +++ b/arch/powerpc/platforms/embedded6xx/holly.c @@ -193,7 +193,7 @@ void holly_show_cpuinfo(struct seq_file *m) seq_printf(m, "machine\t\t: PPC750 GX/CL\n"); } -void holly_restart(char *cmd) +void __noreturn holly_restart(char *cmd) { __be32 __iomem *ocn_bar1 = NULL; unsigned long bar; diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c index 540eeb58d3f0..4c5089f05c7f 100644 --- a/arch/powerpc/platforms/embedded6xx/linkstation.c +++ b/arch/powerpc/platforms/embedded6xx/linkstation.c @@ -100,7 +100,7 @@ static void __init linkstation_init_IRQ(void) extern void avr_uart_configure(void); extern void avr_uart_send(const char); -static void linkstation_restart(char *cmd) +static void __noreturn linkstation_restart(char *cmd) { local_irq_disable(); @@ -113,7 +113,7 @@ static void linkstation_restart(char *cmd) avr_uart_send('G'); /* "kick" */ } -static void linkstation_power_off(void) +static void __noreturn linkstation_power_off(void) { local_irq_disable(); @@ -127,7 +127,7 @@ static void linkstation_power_off(void) /* NOTREACHED */ } -static void linkstation_halt(void) +static void __noreturn linkstation_halt(void) { linkstation_power_off(); /* NOTREACHED */ diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c index df4ad95f183e..3eda5df6281a 100644 --- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c +++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c @@ -146,7 +146,7 @@ void mpc7448_hpc2_show_cpuinfo(struct seq_file *m) seq_printf(m, "vendor\t\t: Freescale Semiconductor\n"); } -void mpc7448_hpc2_restart(char *cmd) +static void __noreturn mpc7448_hpc2_restart(char *cmd) { local_irq_disable(); diff --git a/arch/powerpc/platforms/embedded6xx/mvme5100.c b/arch/powerpc/platforms/embedded6xx/mvme5100.c index 8f65aa3747f5..1382e1f27518 100644 --- a/arch/powerpc/platforms/embedded6xx/mvme5100.c +++ b/arch/powerpc/platforms/embedded6xx/mvme5100.c @@ -177,7 +177,7 @@ static void mvme5100_show_cpuinfo(struct seq_file *m) seq_puts(m, "Machine\t\t: MVME5100\n"); } -static void mvme5100_restart(char *cmd) +static void __noreturn mvme5100_restart(char *cmd) { local_irq_disable(); diff --git a/arch/powerpc/platforms/embedded6xx/storcenter.c b/arch/powerpc/platforms/embedded6xx/storcenter.c index d572833ebd00..4596cba8c827 100644 --- a/arch/powerpc/platforms/embedded6xx/storcenter.c +++ b/arch/powerpc/platforms/embedded6xx/storcenter.c @@ -96,7 +96,7 @@ static void __init storcenter_init_IRQ(void) mpic_init(mpic); } -static void storcenter_restart(char *cmd) +static void __noreturn storcenter_restart(char *cmd) { local_irq_disable(); diff --git a/arch/powerpc/platforms/embedded6xx/wii.c b/arch/powerpc/platforms/embedded6xx/wii.c index 352592d3e44e..ebaecb88df26 100644 --- a/arch/powerpc/platforms/embedded6xx/wii.c +++ b/arch/powerpc/platforms/embedded6xx/wii.c @@ -112,7 +112,7 @@ unsigned long __init wii_mmu_mapin_mem2(unsigned long top) return delta + bl; } -static void wii_spin(void) +static void __noreturn wii_spin(void) { local_irq_disable(); for (;;) @@ -160,7 +160,7 @@ static void __init wii_setup_arch(void) } } -static void wii_restart(char *cmd) +static void __noreturn wii_restart(char *cmd) { local_irq_disable(); @@ -185,7 +185,7 @@ static void wii_power_off(void) wii_spin(); } -static void wii_halt(void) +static void __noreturn wii_halt(void) { if (ppc_md.restart) ppc_md.restart(NULL); diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index a837188544c8..5f8f6f966608 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c @@ -94,7 +94,7 @@ static unsigned long maple_find_nvram_base(void) return result; } -static void maple_restart(char *cmd) +static void __noreturn maple_restart(char *cmd) { unsigned int maple_nvram_base; const unsigned int *maple_nvram_offset, *maple_nvram_command; @@ -119,9 +119,10 @@ static void maple_restart(char *cmd) for (;;) ; fail: printk(KERN_EMERG "Maple: Manual Restart Required\n"); + for (;;) ; } -static void maple_power_off(void) +static void __noreturn maple_power_off(void) { unsigned int maple_nvram_base; const unsigned int *maple_nvram_offset, *maple_nvram_command; @@ -146,9 +147,10 @@ static void maple_power_off(void) for (;;) ; fail: printk(KERN_EMERG "Maple: Manual Power-Down Required\n"); + for (;;) ; } -static void maple_halt(void) +static void __noreturn maple_halt(void) { maple_power_off(); } diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index d71b2c7e8403..7349644c9828 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c @@ -62,7 +62,7 @@ static int num_mce_regs; static int nmi_virq = NO_IRQ; -static void pas_restart(char *cmd) +static void __noreturn pas_restart(char *cmd) { /* Need to put others cpu in hold loop so they're not sleeping */ smp_send_stop(); diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 8dd78f4e1af4..bd83b52c9830 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -383,7 +383,7 @@ void __init_refok note_bootable_part(dev_t dev, int part, int goodness) } #ifdef CONFIG_ADB_CUDA -static void cuda_restart(void) +static void __noreturn cuda_restart(void) { struct adb_request req; @@ -392,7 +392,7 @@ static void cuda_restart(void) cuda_poll(); } -static void cuda_shutdown(void) +static void __noreturn cuda_shutdown(void) { struct adb_request req; @@ -416,7 +416,7 @@ static void cuda_shutdown(void) #define smu_shutdown() #endif -static void pmac_restart(char *cmd) +static void __noreturn pmac_restart(char *cmd) { switch (sys_ctrler) { case SYS_CTRLER_CUDA: @@ -430,9 +430,10 @@ static void pmac_restart(char *cmd) break; default: ; } + while (1) ; } -static void pmac_power_off(void) +static void __noreturn pmac_power_off(void) { switch (sys_ctrler) { case SYS_CTRLER_CUDA: @@ -446,9 +447,10 @@ static void pmac_power_off(void) break; default: ; } + while (1) ; } -static void +static void __noreturn pmac_halt(void) { pmac_power_off(); diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c index 799c8580ab09..486ecd017535 100644 --- a/arch/powerpc/platforms/ps3/setup.c +++ b/arch/powerpc/platforms/ps3/setup.c @@ -80,7 +80,7 @@ static void ps3_power_save(void) lv1_pause(0); } -static void ps3_restart(char *cmd) +static void __noreturn ps3_restart(char *cmd) { DBG("%s:%d cmd '%s'\n", __func__, __LINE__, cmd); @@ -96,7 +96,7 @@ static void ps3_power_off(void) ps3_sys_manager_power_off(); /* never returns */ } -static void ps3_halt(void) +static void __noreturn ps3_halt(void) { DBG("%s:%d\n", __func__, __LINE__); diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index 99269c041615..a09ca704de58 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c @@ -204,7 +204,7 @@ static int __init setup_rstcr(void) arch_initcall(setup_rstcr); -void fsl_rstcr_restart(char *cmd) +void __noreturn fsl_rstcr_restart(char *cmd) { local_irq_disable(); if (rstcr) @@ -228,10 +228,11 @@ EXPORT_SYMBOL(diu_ops); * to initiate a partition restart when we're running under the Freescale * hypervisor. */ -void fsl_hv_restart(char *cmd) +void __noreturn fsl_hv_restart(char *cmd) { pr_info("hv restart\n"); fh_partition_restart(-1); + while (1) ; } /* @@ -241,9 +242,10 @@ void fsl_hv_restart(char *cmd) * function pointers, to shut down the partition when we're running under * the Freescale hypervisor. */ -void fsl_hv_halt(void) +void __noreturn fsl_hv_halt(void) { pr_info("hv exit\n"); fh_partition_stop(-1); + while (1) ; } #endif diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h index 4c5a19ef4f0b..433566a5ef19 100644 --- a/arch/powerpc/sysdev/fsl_soc.h +++ b/arch/powerpc/sysdev/fsl_soc.h @@ -19,7 +19,7 @@ extern u32 fsl_get_sys_freq(void); struct spi_board_info; struct device_node; -extern void fsl_rstcr_restart(char *cmd); +extern void __noreturn fsl_rstcr_restart(char *cmd); /* The different ports that the DIU can be connected to */ enum fsl_diu_monitor_port { @@ -42,8 +42,8 @@ struct platform_diu_data_ops { extern struct platform_diu_data_ops diu_ops; -void fsl_hv_restart(char *cmd); -void fsl_hv_halt(void); +void __noreturn fsl_hv_restart(char *cmd); +void __noreturn fsl_hv_halt(void); #endif #endif -- cgit v1.2.3 From c2101c9039fe2a005f7b4138e028ed9a8468a48a Mon Sep 17 00:00:00 2001 From: Nathan Fontenot Date: Mon, 20 Jun 2016 09:00:39 -0500 Subject: powerpc/pseries: Move property cloning into its own routine Move property cloning code into its own routine Split the pieces of dlpar_clone_drconf_property() that create a copy of the property struct into its own routine. This allows for creating clones of more than just the ibm,dynamic-memory property used in memory hotplug. Signed-off-by: Nathan Fontenot Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/pseries/hotplug-memory.c | 38 +++++++++++++++++-------- 1 file changed, 26 insertions(+), 12 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index 2ce138542083..3dbc82b7e374 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c @@ -69,13 +69,36 @@ unsigned long pseries_memory_block_size(void) return memblock_size; } -static void dlpar_free_drconf_property(struct property *prop) +static void dlpar_free_property(struct property *prop) { kfree(prop->name); kfree(prop->value); kfree(prop); } +static struct property *dlpar_clone_property(struct property *prop, + u32 prop_size) +{ + struct property *new_prop; + + new_prop = kzalloc(sizeof(*new_prop), GFP_KERNEL); + if (!new_prop) + return NULL; + + new_prop->name = kstrdup(prop->name, GFP_KERNEL); + new_prop->value = kzalloc(prop_size, GFP_KERNEL); + if (!new_prop->name || !new_prop->value) { + dlpar_free_property(new_prop); + return NULL; + } + + memcpy(new_prop->value, prop->value, prop->length); + new_prop->length = prop_size; + + of_property_set_flag(new_prop, OF_DYNAMIC); + return new_prop; +} + static struct property *dlpar_clone_drconf_property(struct device_node *dn) { struct property *prop, *new_prop; @@ -87,19 +110,10 @@ static struct property *dlpar_clone_drconf_property(struct device_node *dn) if (!prop) return NULL; - new_prop = kzalloc(sizeof(*new_prop), GFP_KERNEL); + new_prop = dlpar_clone_property(prop, prop->length); if (!new_prop) return NULL; - new_prop->name = kstrdup(prop->name, GFP_KERNEL); - new_prop->value = kmemdup(prop->value, prop->length, GFP_KERNEL); - if (!new_prop->name || !new_prop->value) { - dlpar_free_drconf_property(new_prop); - return NULL; - } - - new_prop->length = prop->length; - /* Convert the property to cpu endian-ness */ p = new_prop->value; *p = be32_to_cpu(*p); @@ -748,7 +762,7 @@ int dlpar_memory(struct pseries_hp_errorlog *hp_elog) break; } - dlpar_free_drconf_property(prop); + dlpar_free_property(prop); dlpar_memory_out: of_node_put(dn); -- cgit v1.2.3 From c05a5a40969e63d3490901acf60989979b0fcd27 Mon Sep 17 00:00:00 2001 From: Nathan Fontenot Date: Mon, 20 Jun 2016 09:01:38 -0500 Subject: powerpc/pseries: Dynamic add entires to associativity lookup array Dynamically add entries to the associativity lookup array The ibm,associativity-lookup-arrays property may only contain associativity arrays for LMBs present at boot time. When hotplug adding a LMB its associativity array may not be in the associativity lookup array, this patch adds the ability to add new entries to the associativity lookup array. Signed-off-by: Nathan Fontenot Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/pseries/hotplug-memory.c | 95 ++++++++++++++++++------- 1 file changed, 68 insertions(+), 27 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index 3dbc82b7e374..08e51f6ef71f 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c @@ -191,14 +191,74 @@ static int dlpar_update_device_tree_lmb(struct of_drconf_cell *lmb) return 0; } +static u32 find_aa_index(struct device_node *dr_node, + struct property *ala_prop, const u32 *lmb_assoc) +{ + u32 *assoc_arrays; + u32 aa_index; + int aa_arrays, aa_array_entries, aa_array_sz; + int i, index; + + /* + * The ibm,associativity-lookup-arrays property is defined to be + * a 32-bit value specifying the number of associativity arrays + * followed by a 32-bitvalue specifying the number of entries per + * array, followed by the associativity arrays. + */ + assoc_arrays = ala_prop->value; + + aa_arrays = be32_to_cpu(assoc_arrays[0]); + aa_array_entries = be32_to_cpu(assoc_arrays[1]); + aa_array_sz = aa_array_entries * sizeof(u32); + + aa_index = -1; + for (i = 0; i < aa_arrays; i++) { + index = (i * aa_array_entries) + 2; + + if (memcmp(&assoc_arrays[index], &lmb_assoc[1], aa_array_sz)) + continue; + + aa_index = i; + break; + } + + if (aa_index == -1) { + struct property *new_prop; + u32 new_prop_size; + + new_prop_size = ala_prop->length + aa_array_sz; + new_prop = dlpar_clone_property(ala_prop, new_prop_size); + if (!new_prop) + return -1; + + assoc_arrays = new_prop->value; + + /* increment the number of entries in the lookup array */ + assoc_arrays[0] = cpu_to_be32(aa_arrays + 1); + + /* copy the new associativity into the lookup array */ + index = aa_arrays * aa_array_entries + 2; + memcpy(&assoc_arrays[index], &lmb_assoc[1], aa_array_sz); + + of_update_property(dr_node, new_prop); + + /* + * The associativity lookup array index for this lmb is + * number of entries - 1 since we added its associativity + * to the end of the lookup array. + */ + aa_index = be32_to_cpu(assoc_arrays[0]) - 1; + } + + return aa_index; +} + static u32 lookup_lmb_associativity_index(struct of_drconf_cell *lmb) { struct device_node *parent, *lmb_node, *dr_node; + struct property *ala_prop; const u32 *lmb_assoc; - const u32 *assoc_arrays; u32 aa_index; - int aa_arrays, aa_array_entries, aa_array_sz; - int i; parent = of_find_node_by_path("/"); if (!parent) @@ -222,34 +282,15 @@ static u32 lookup_lmb_associativity_index(struct of_drconf_cell *lmb) return -ENODEV; } - assoc_arrays = of_get_property(dr_node, - "ibm,associativity-lookup-arrays", - NULL); - of_node_put(dr_node); - if (!assoc_arrays) { + ala_prop = of_find_property(dr_node, "ibm,associativity-lookup-arrays", + NULL); + if (!ala_prop) { + of_node_put(dr_node); dlpar_free_cc_nodes(lmb_node); return -ENODEV; } - /* The ibm,associativity-lookup-arrays property is defined to be - * a 32-bit value specifying the number of associativity arrays - * followed by a 32-bitvalue specifying the number of entries per - * array, followed by the associativity arrays. - */ - aa_arrays = be32_to_cpu(assoc_arrays[0]); - aa_array_entries = be32_to_cpu(assoc_arrays[1]); - aa_array_sz = aa_array_entries * sizeof(u32); - - aa_index = -1; - for (i = 0; i < aa_arrays; i++) { - int indx = (i * aa_array_entries) + 2; - - if (memcmp(&assoc_arrays[indx], &lmb_assoc[1], aa_array_sz)) - continue; - - aa_index = i; - break; - } + aa_index = find_aa_index(dr_node, ala_prop, lmb_assoc); dlpar_free_cc_nodes(lmb_node); return aa_index; -- cgit v1.2.3 From ec999072442ad531cccbecbd6d5a569b0af6c8e3 Mon Sep 17 00:00:00 2001 From: Nathan Fontenot Date: Wed, 29 Jun 2016 12:19:14 -0500 Subject: powerpc/pseries: Auto-online hotplugged memory A recent update (commit id 31bc3858ea3) allows for automatically onlining memory that is added. This patch sets the config option CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE=y for pseries and updates the pseries memory hotplug code so that DLPAR added memory can be automatically onlined instead of explicitly onlining the memory. Signed-off-by: Nathan Fontenot Signed-off-by: Michael Ellerman --- arch/powerpc/configs/pseries_defconfig | 1 + arch/powerpc/platforms/pseries/hotplug-memory.c | 14 -------------- 2 files changed, 1 insertion(+), 14 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig index 99dec9d5f85c..654aeffc57ef 100644 --- a/arch/powerpc/configs/pseries_defconfig +++ b/arch/powerpc/configs/pseries_defconfig @@ -53,6 +53,7 @@ CONFIG_KEXEC=y CONFIG_IRQ_ALL_CPUS=y CONFIG_MEMORY_HOTPLUG=y CONFIG_MEMORY_HOTREMOVE=y +CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE=y CONFIG_KSM=y CONFIG_TRANSPARENT_HUGEPAGE=y CONFIG_PPC_64K_PAGES=y diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index 08e51f6ef71f..8baad183583f 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c @@ -590,7 +590,6 @@ static int dlpar_memory_remove_by_index(u32 drc_index, struct property *prop) static int dlpar_add_lmb_memory(struct of_drconf_cell *lmb) { - struct memory_block *mem_block; unsigned long block_sz; int nid, rc; @@ -611,19 +610,6 @@ static int dlpar_add_lmb_memory(struct of_drconf_cell *lmb) return rc; } - mem_block = lmb_to_memblock(lmb); - if (!mem_block) { - remove_memory(nid, lmb->base_addr, block_sz); - return -EINVAL; - } - - rc = device_online(&mem_block->dev); - put_device(&mem_block->dev); - if (rc) { - remove_memory(nid, lmb->base_addr, block_sz); - return rc; - } - lmb->flags |= DRCONF_MEM_ASSIGNED; return 0; } -- cgit v1.2.3 From fdb4f6e99ffacfa643ab2d2da99171b3084d4446 Mon Sep 17 00:00:00 2001 From: Nathan Fontenot Date: Wed, 29 Jun 2016 12:20:30 -0500 Subject: powerpc/pseries: Remove call to memblock_add() The call to memblock_add is not needed, this is already done by memory_add(). This patch removes this call which shrinks dlpar_add_lmb_memory() enough that it can be merged into dlpar_add_lmb(). Signed-off-by: Nathan Fontenot Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/pseries/hotplug-memory.c | 37 +++++++------------------ 1 file changed, 10 insertions(+), 27 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index 8baad183583f..43f7beb2902d 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c @@ -588,36 +588,11 @@ static int dlpar_memory_remove_by_index(u32 drc_index, struct property *prop) #endif /* CONFIG_MEMORY_HOTREMOVE */ -static int dlpar_add_lmb_memory(struct of_drconf_cell *lmb) +static int dlpar_add_lmb(struct of_drconf_cell *lmb) { unsigned long block_sz; int nid, rc; - block_sz = memory_block_size_bytes(); - - /* Find the node id for this address */ - nid = memory_add_physaddr_to_nid(lmb->base_addr); - - /* Add the memory */ - rc = add_memory(nid, lmb->base_addr, block_sz); - if (rc) - return rc; - - /* Register this block of memory */ - rc = memblock_add(lmb->base_addr, block_sz); - if (rc) { - remove_memory(nid, lmb->base_addr, block_sz); - return rc; - } - - lmb->flags |= DRCONF_MEM_ASSIGNED; - return 0; -} - -static int dlpar_add_lmb(struct of_drconf_cell *lmb) -{ - int rc; - if (lmb->flags & DRCONF_MEM_ASSIGNED) return -EINVAL; @@ -633,10 +608,18 @@ static int dlpar_add_lmb(struct of_drconf_cell *lmb) return rc; } - rc = dlpar_add_lmb_memory(lmb); + block_sz = memory_block_size_bytes(); + + /* Find the node id for this address */ + nid = memory_add_physaddr_to_nid(lmb->base_addr); + + /* Add the memory */ + rc = add_memory(nid, lmb->base_addr, block_sz); if (rc) { dlpar_remove_device_tree_lmb(lmb); dlpar_release_drc(lmb->drc_index); + } else { + lmb->flags |= DRCONF_MEM_ASSIGNED; } return rc; -- cgit v1.2.3 From bcef83a00dc44ee25ff4d6e078cf6432ddf74dec Mon Sep 17 00:00:00 2001 From: "Shreyas B. Prabhu" Date: Fri, 8 Jul 2016 11:50:49 +0530 Subject: powerpc/powernv: Add platform support for stop instruction POWER ISA v3 defines a new idle processor core mechanism. In summary, a) new instruction named stop is added. This instruction replaces instructions like nap, sleep, rvwinkle. b) new per thread SPR named Processor Stop Status and Control Register (PSSCR) is added which controls the behavior of stop instruction. PSSCR layout: ---------------------------------------------------------- | PLS | /// | SD | ESL | EC | PSLL | /// | TR | MTL | RL | ---------------------------------------------------------- 0 4 41 42 43 44 48 54 56 60 PSSCR key fields: Bits 0:3 - Power-Saving Level Status. This field indicates the lowest power-saving state the thread entered since stop instruction was last executed. Bit 42 - Enable State Loss 0 - No state is lost irrespective of other fields 1 - Allows state loss Bits 44:47 - Power-Saving Level Limit This limits the power-saving level that can be entered into. Bits 60:63 - Requested Level Used to specify which power-saving level must be entered on executing stop instruction This patch adds support for stop instruction and PSSCR handling. Reviewed-by: Gautham R. Shenoy Signed-off-by: Shreyas B. Prabhu Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/cpuidle.h | 2 + arch/powerpc/include/asm/kvm_book3s_asm.h | 2 +- arch/powerpc/include/asm/opal-api.h | 11 +- arch/powerpc/include/asm/ppc-opcode.h | 4 + arch/powerpc/include/asm/processor.h | 2 + arch/powerpc/include/asm/reg.h | 10 ++ arch/powerpc/kernel/idle_book3s.S | 193 ++++++++++++++++++++++++------ arch/powerpc/platforms/powernv/idle.c | 174 ++++++++++++++++++++++----- 8 files changed, 332 insertions(+), 66 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/include/asm/cpuidle.h b/arch/powerpc/include/asm/cpuidle.h index d2f99ca1e3a6..3d7fc06532a1 100644 --- a/arch/powerpc/include/asm/cpuidle.h +++ b/arch/powerpc/include/asm/cpuidle.h @@ -13,6 +13,8 @@ #ifndef __ASSEMBLY__ extern u32 pnv_fastsleep_workaround_at_entry[]; extern u32 pnv_fastsleep_workaround_at_exit[]; + +extern u64 pnv_first_deep_stop_state; #endif #endif diff --git a/arch/powerpc/include/asm/kvm_book3s_asm.h b/arch/powerpc/include/asm/kvm_book3s_asm.h index 72b6225aca73..d318d432caa9 100644 --- a/arch/powerpc/include/asm/kvm_book3s_asm.h +++ b/arch/powerpc/include/asm/kvm_book3s_asm.h @@ -162,7 +162,7 @@ struct kvmppc_book3s_shadow_vcpu { /* Values for kvm_state */ #define KVM_HWTHREAD_IN_KERNEL 0 -#define KVM_HWTHREAD_IN_NAP 1 +#define KVM_HWTHREAD_IN_IDLE 1 #define KVM_HWTHREAD_IN_KVM 2 #endif /* __ASM_KVM_BOOK3S_ASM_H__ */ diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h index 72b5f27cd0b8..6de1e4e272f9 100644 --- a/arch/powerpc/include/asm/opal-api.h +++ b/arch/powerpc/include/asm/opal-api.h @@ -166,13 +166,20 @@ /* Device tree flags */ -/* Flags set in power-mgmt nodes in device tree if - * respective idle states are supported in the platform. +/* + * Flags set in power-mgmt nodes in device tree describing + * idle states that are supported in the platform. */ + +#define OPAL_PM_TIMEBASE_STOP 0x00000002 +#define OPAL_PM_LOSE_HYP_CONTEXT 0x00002000 +#define OPAL_PM_LOSE_FULL_CONTEXT 0x00004000 #define OPAL_PM_NAP_ENABLED 0x00010000 #define OPAL_PM_SLEEP_ENABLED 0x00020000 #define OPAL_PM_WINKLE_ENABLED 0x00040000 #define OPAL_PM_SLEEP_ENABLED_ER1 0x00080000 /* with workaround */ +#define OPAL_PM_STOP_INST_FAST 0x00100000 +#define OPAL_PM_STOP_INST_DEEP 0x00200000 /* * OPAL_CONFIG_CPU_IDLE_STATE parameters diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index 9de9df14a8d9..81657a1e03fe 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h @@ -205,6 +205,8 @@ #define PPC_INST_SLEEP 0x4c0003a4 #define PPC_INST_WINKLE 0x4c0003e4 +#define PPC_INST_STOP 0x4c0002e4 + /* A2 specific instructions */ #define PPC_INST_ERATWE 0x7c0001a6 #define PPC_INST_ERATRE 0x7c000166 @@ -394,6 +396,8 @@ #define PPC_SLEEP stringify_in_c(.long PPC_INST_SLEEP) #define PPC_WINKLE stringify_in_c(.long PPC_INST_WINKLE) +#define PPC_STOP stringify_in_c(.long PPC_INST_STOP) + /* BHRB instructions */ #define PPC_CLRBHRB stringify_in_c(.long PPC_INST_CLRBHRB) #define PPC_MFBHRBE(r, n) stringify_in_c(.long PPC_INST_BHRBE | \ diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index b5925d5d4985..68e3bf57b027 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h @@ -460,6 +460,8 @@ extern int powersave_nap; /* set if nap mode can be used in idle loop */ extern unsigned long power7_nap(int check_irq); extern unsigned long power7_sleep(void); extern unsigned long power7_winkle(void); +extern unsigned long power9_idle_stop(unsigned long stop_level); + extern void flush_instruction_cache(void); extern void hard_reset_now(void); extern void poweroff_now(void); diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index ac4be83f8fdc..c0263a2d1008 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -145,6 +145,15 @@ #define MSR_64BIT 0 #endif +/* Power Management - Processor Stop Status and Control Register Fields */ +#define PSSCR_RL_MASK 0x0000000F /* Requested Level */ +#define PSSCR_MTL_MASK 0x000000F0 /* Maximum Transition Level */ +#define PSSCR_TR_MASK 0x00000300 /* Transition State */ +#define PSSCR_PSLL_MASK 0x000F0000 /* Power-Saving Level Limit */ +#define PSSCR_EC 0x00100000 /* Exit Criterion */ +#define PSSCR_ESL 0x00200000 /* Enable State Loss */ +#define PSSCR_SD 0x00400000 /* Status Disable */ + /* Floating Point Status and Control Register (FPSCR) Fields */ #define FPSCR_FX 0x80000000 /* FPU exception summary */ #define FPSCR_FEX 0x40000000 /* FPU enabled exception summary */ @@ -291,6 +300,7 @@ #define SPRN_PMICR 0x354 /* Power Management Idle Control Reg */ #define SPRN_PMSR 0x355 /* Power Management Status Reg */ #define SPRN_PMMAR 0x356 /* Power Management Memory Activity Register */ +#define SPRN_PSSCR 0x357 /* Processor Stop Status and Control Register (ISA 3.0) */ #define SPRN_PMCR 0x374 /* Power Management Control Register */ /* HFSCR and FSCR bit numbers are the same */ diff --git a/arch/powerpc/kernel/idle_book3s.S b/arch/powerpc/kernel/idle_book3s.S index 2f909a12c76c..1f564eb409c3 100644 --- a/arch/powerpc/kernel/idle_book3s.S +++ b/arch/powerpc/kernel/idle_book3s.S @@ -1,6 +1,6 @@ /* - * This file contains idle entry/exit functions for POWER7 and - * POWER8 CPUs. + * This file contains idle entry/exit functions for POWER7, + * POWER8 and POWER9 CPUs. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -21,6 +21,7 @@ #include #include #include +#include #undef DEBUG @@ -37,6 +38,11 @@ #define _AMOR GPR9 #define _WORT GPR10 #define _WORC GPR11 +#define _PTCR GPR12 + +#define PSSCR_HV_TEMPLATE PSSCR_ESL | PSSCR_EC | \ + PSSCR_PSLL_MASK | PSSCR_TR_MASK | \ + PSSCR_MTL_MASK /* Idle state entry routines */ @@ -61,8 +67,17 @@ save_sprs_to_stack: * Note all register i.e per-core, per-subcore or per-thread is saved * here since any thread in the core might wake up first */ +BEGIN_FTR_SECTION + mfspr r3,SPRN_PTCR + std r3,_PTCR(r1) + /* + * Note - SDR1 is dropped in Power ISA v3. Hence not restoring + * SDR1 here + */ +FTR_SECTION_ELSE mfspr r3,SPRN_SDR1 std r3,_SDR1(r1) +ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_300) mfspr r3,SPRN_RPR std r3,_RPR(r1) mfspr r3,SPRN_SPURR @@ -100,7 +115,8 @@ core_idle_lock_held: /* * Pass requested state in r3: - * r3 - PNV_THREAD_NAP/SLEEP/WINKLE + * r3 - PNV_THREAD_NAP/SLEEP/WINKLE in POWER8 + * - Requested STOP state in POWER9 * * To check IRQ_HAPPENED in r4 * 0 - don't check @@ -161,7 +177,7 @@ _GLOBAL(pnv_powersave_common) #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE /* Tell KVM we're entering idle */ - li r4,KVM_HWTHREAD_IN_NAP + li r4,KVM_HWTHREAD_IN_IDLE stb r4,HSTATE_HWTHREAD_STATE(r13) #endif @@ -243,6 +259,41 @@ enter_winkle: IDLE_STATE_ENTER_SEQ(PPC_WINKLE) +/* + * r3 - requested stop state + */ +power_enter_stop: +/* + * Check if the requested state is a deep idle state. + */ + LOAD_REG_ADDRBASE(r5,pnv_first_deep_stop_state) + ld r4,ADDROFF(pnv_first_deep_stop_state)(r5) + cmpd r3,r4 + bge 2f + IDLE_STATE_ENTER_SEQ(PPC_STOP) +2: +/* + * Entering deep idle state. + * Clear thread bit in PACA_CORE_IDLE_STATE, save SPRs to + * stack and enter stop + */ + lbz r7,PACA_THREAD_MASK(r13) + ld r14,PACA_CORE_IDLE_STATE_PTR(r13) + +lwarx_loop_stop: + lwarx r15,0,r14 + andi. r9,r15,PNV_CORE_IDLE_LOCK_BIT + bnel core_idle_lock_held + andc r15,r15,r7 /* Clear thread bit */ + + stwcx. r15,0,r14 + bne- lwarx_loop_stop + isync + + bl save_sprs_to_stack + + IDLE_STATE_ENTER_SEQ(PPC_STOP) + _GLOBAL(power7_idle) /* Now check if user or arch enabled NAP mode */ LOAD_REG_ADDRBASE(r3,powersave_nap) @@ -292,6 +343,17 @@ ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66); \ 20: nop; +/* + * r3 - requested stop state + */ +_GLOBAL(power9_idle_stop) + LOAD_REG_IMMEDIATE(r4, PSSCR_HV_TEMPLATE) + or r4,r4,r3 + mtspr SPRN_PSSCR, r4 + li r4, 1 + LOAD_REG_ADDR(r5,power_enter_stop) + b pnv_powersave_common + /* No return */ /* * Called from reset vector. Check whether we have woken up with * hypervisor state loss. If yes, restore hypervisor state and return @@ -301,7 +363,33 @@ ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66); \ * cr3 - set to gt if waking up with partial/complete hypervisor state loss */ _GLOBAL(pnv_restore_hyp_resource) + ld r2,PACATOC(r13); +BEGIN_FTR_SECTION + /* + * POWER ISA 3. Use PSSCR to determine if we + * are waking up from deep idle state + */ + LOAD_REG_ADDRBASE(r5,pnv_first_deep_stop_state) + ld r4,ADDROFF(pnv_first_deep_stop_state)(r5) + + mfspr r5,SPRN_PSSCR /* + * 0-3 bits correspond to Power-Saving Level Status + * which indicates the idle state we are waking up from + */ + rldicl r5,r5,4,60 + cmpd cr4,r5,r4 + bge cr4,pnv_wakeup_tb_loss + /* + * Waking up without hypervisor state loss. Return to + * reset vector + */ + blr + +END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300) + + /* + * POWER ISA 2.07 or less. * Check if last bit of HSPGR0 is set. This indicates whether we are * waking up from winkle. */ @@ -324,9 +412,17 @@ _GLOBAL(pnv_restore_hyp_resource) blr /* Return back to System Reset vector from where pnv_restore_hyp_resource was invoked */ - +/* + * Called if waking up from idle state which can cause either partial or + * complete hyp state loss. + * In POWER8, called if waking up from fastsleep or winkle + * In POWER9, called if waking up from stop state >= pnv_first_deep_stop_state + * + * r13 - PACA + * cr3 - gt if waking up with partial/complete hypervisor state loss + * cr4 - eq if waking up from complete hypervisor state loss. + */ _GLOBAL(pnv_wakeup_tb_loss) - ld r2,PACATOC(r13); ld r1,PACAR1(r13) /* * Before entering any idle state, the NVGPRs are saved in the stack @@ -361,35 +457,35 @@ lwarx_loop2: bnel core_idle_lock_held cmpwi cr2,r15,0 - lbz r4,PACA_SUBCORE_SIBLING_MASK(r13) - and r4,r4,r15 - cmpwi cr1,r4,0 /* Check if first in subcore */ /* * At this stage - * cr1 - 0b0100 if first thread to wakeup in subcore - * cr2 - 0b0100 if first thread to wakeup in core - * cr3- 0b0010 if waking up from sleep or winkle - * cr4 - 0b0100 if waking up from winkle + * cr2 - eq if first thread to wakeup in core + * cr3- gt if waking up with partial/complete hypervisor state loss + * cr4 - eq if waking up from complete hypervisor state loss. */ - or r15,r15,r7 /* Set thread bit */ - - beq cr1,first_thread_in_subcore - - /* Not first thread in subcore to wake up */ - stwcx. r15,0,r14 - bne- lwarx_loop2 - isync - b common_exit - -first_thread_in_subcore: - /* First thread in subcore to wakeup */ ori r15,r15,PNV_CORE_IDLE_LOCK_BIT stwcx. r15,0,r14 bne- lwarx_loop2 isync +BEGIN_FTR_SECTION + lbz r4,PACA_SUBCORE_SIBLING_MASK(r13) + and r4,r4,r15 + cmpwi r4,0 /* Check if first in subcore */ + + or r15,r15,r7 /* Set thread bit */ + beq first_thread_in_subcore +END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300) + + or r15,r15,r7 /* Set thread bit */ + beq cr2,first_thread_in_core + + /* Not first thread in core or subcore to wake up */ + b clear_lock + +first_thread_in_subcore: /* * If waking up from sleep, subcore state is not lost. Hence * skip subcore state restore @@ -399,6 +495,7 @@ first_thread_in_subcore: /* Restore per-subcore state */ ld r4,_SDR1(r1) mtspr SPRN_SDR1,r4 + ld r4,_RPR(r1) mtspr SPRN_RPR,r4 ld r4,_AMOR(r1) @@ -414,19 +511,23 @@ subcore_state_restored: first_thread_in_core: /* - * First thread in the core waking up from fastsleep. It needs to + * First thread in the core waking up from any state which can cause + * partial or complete hypervisor state loss. It needs to * call the fastsleep workaround code if the platform requires it. * Call it unconditionally here. The below branch instruction will - * be patched out when the idle states are discovered if platform - * does not require workaround. + * be patched out if the platform does not have fastsleep or does not + * require the workaround. Patching will be performed during the + * discovery of idle-states. */ .global pnv_fastsleep_workaround_at_exit pnv_fastsleep_workaround_at_exit: b fastsleep_workaround_at_exit timebase_resync: - /* Do timebase resync if we are waking up from sleep. Use cr3 value - * set in exceptions-64s.S */ + /* + * Use cr3 which indicates that we are waking up with atleast partial + * hypervisor state loss to determine if TIMEBASE RESYNC is needed. + */ ble cr3,clear_lock /* Time base re-sync */ li r0,OPAL_RESYNC_TIMEBASE @@ -439,7 +540,18 @@ timebase_resync: */ bne cr4,clear_lock - /* Restore per core state */ + /* + * First thread in the core to wake up and its waking up with + * complete hypervisor state loss. Restore per core hypervisor + * state. + */ +BEGIN_FTR_SECTION + ld r4,_PTCR(r1) + mtspr SPRN_PTCR,r4 + ld r4,_RPR(r1) + mtspr SPRN_RPR,r4 +END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300) + ld r4,_TSCR(r1) mtspr SPRN_TSCR,r4 ld r4,_WORC(r1) @@ -461,9 +573,9 @@ common_exit: /* Waking up from winkle */ - /* Restore per thread state */ - bl __restore_cpu_power8 - +BEGIN_MMU_FTR_SECTION + b no_segments +END_MMU_FTR_SECTION_IFSET(MMU_FTR_RADIX) /* Restore SLB from PACA */ ld r8,PACA_SLBSHADOWPTR(r13) @@ -477,6 +589,9 @@ common_exit: slbmte r6,r5 1: addi r8,r8,16 .endr +no_segments: + + /* Restore per thread state */ ld r4,_SPURR(r1) mtspr SPRN_SPURR,r4 @@ -487,6 +602,16 @@ common_exit: ld r4,_WORT(r1) mtspr SPRN_WORT,r4 + /* Call cur_cpu_spec->cpu_restore() */ + LOAD_REG_ADDR(r4, cur_cpu_spec) + ld r4,0(r4) + ld r12,CPU_SPEC_RESTORE(r4) +#ifdef PPC64_ELF_ABI_v1 + ld r12,0(r12) +#endif + mtctr r12 + bctrl + hypervisor_state_restored: mtspr SPRN_SRR1,r16 diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c index 8a77f5c4159e..8219e22c2b91 100644 --- a/arch/powerpc/platforms/powernv/idle.c +++ b/arch/powerpc/platforms/powernv/idle.c @@ -27,9 +27,12 @@ #include "powernv.h" #include "subcore.h" +/* Power ISA 3.0 allows for stop states 0x0 - 0xF */ +#define MAX_STOP_STATE 0xF + static u32 supported_cpuidle_states; -static int pnv_save_sprs_for_winkle(void) +static int pnv_save_sprs_for_deep_states(void) { int cpu; int rc; @@ -50,15 +53,19 @@ static int pnv_save_sprs_for_winkle(void) uint64_t pir = get_hard_smp_processor_id(cpu); uint64_t hsprg0_val = (uint64_t)&paca[cpu]; - /* - * HSPRG0 is used to store the cpu's pointer to paca. Hence last - * 3 bits are guaranteed to be 0. Program slw to restore HSPRG0 - * with 63rd bit set, so that when a thread wakes up at 0x100 we - * can use this bit to distinguish between fastsleep and - * deep winkle. - */ - hsprg0_val |= 1; - + if (!cpu_has_feature(CPU_FTR_ARCH_300)) { + /* + * HSPRG0 is used to store the cpu's pointer to paca. + * Hence last 3 bits are guaranteed to be 0. Program + * slw to restore HSPRG0 with 63rd bit set, so that + * when a thread wakes up at 0x100 we can use this bit + * to distinguish between fastsleep and deep winkle. + * This is not necessary with stop/psscr since PLS + * field of psscr indicates which state we are waking + * up from. + */ + hsprg0_val |= 1; + } rc = opal_slw_set_reg(pir, SPRN_HSPRG0, hsprg0_val); if (rc != 0) return rc; @@ -130,8 +137,8 @@ static void pnv_alloc_idle_core_states(void) update_subcore_sibling_mask(); - if (supported_cpuidle_states & OPAL_PM_WINKLE_ENABLED) - pnv_save_sprs_for_winkle(); + if (supported_cpuidle_states & OPAL_PM_LOSE_FULL_CONTEXT) + pnv_save_sprs_for_deep_states(); } u32 pnv_get_supported_cpuidle_states(void) @@ -230,43 +237,151 @@ static DEVICE_ATTR(fastsleep_workaround_applyonce, 0600, show_fastsleep_workaround_applyonce, store_fastsleep_workaround_applyonce); -static int __init pnv_init_idle_states(void) + +/* + * Used for ppc_md.power_save which needs a function with no parameters + */ +static void power9_idle(void) { - struct device_node *power_mgt; - int dt_idle_states; - u32 *flags; - int i; + /* Requesting stop state 0 */ + power9_idle_stop(0); +} +/* + * First deep stop state. Used to figure out when to save/restore + * hypervisor context. + */ +u64 pnv_first_deep_stop_state = MAX_STOP_STATE; - supported_cpuidle_states = 0; +/* + * Power ISA 3.0 idle initialization. + * + * POWER ISA 3.0 defines a new SPR Processor stop Status and Control + * Register (PSSCR) to control idle behavior. + * + * PSSCR layout: + * ---------------------------------------------------------- + * | PLS | /// | SD | ESL | EC | PSLL | /// | TR | MTL | RL | + * ---------------------------------------------------------- + * 0 4 41 42 43 44 48 54 56 60 + * + * PSSCR key fields: + * Bits 0:3 - Power-Saving Level Status (PLS). This field indicates the + * lowest power-saving state the thread entered since stop instruction was + * last executed. + * + * Bit 41 - Status Disable(SD) + * 0 - Shows PLS entries + * 1 - PLS entries are all 0 + * + * Bit 42 - Enable State Loss + * 0 - No state is lost irrespective of other fields + * 1 - Allows state loss + * + * Bit 43 - Exit Criterion + * 0 - Exit from power-save mode on any interrupt + * 1 - Exit from power-save mode controlled by LPCR's PECE bits + * + * Bits 44:47 - Power-Saving Level Limit + * This limits the power-saving level that can be entered into. + * + * Bits 60:63 - Requested Level + * Used to specify which power-saving level must be entered on executing + * stop instruction + * + * @np: /ibm,opal/power-mgt device node + * @flags: cpu-idle-state-flags array + * @dt_idle_states: Number of idle state entries + * Returns 0 on success + */ +static int __init pnv_arch300_idle_init(struct device_node *np, u32 *flags, + int dt_idle_states) +{ + u64 *psscr_val = NULL; + int rc = 0, i; - if (cpuidle_disable != IDLE_NO_OVERRIDE) + psscr_val = kcalloc(dt_idle_states, sizeof(*psscr_val), + GFP_KERNEL); + if (!psscr_val) { + rc = -1; goto out; - - if (!firmware_has_feature(FW_FEATURE_OPAL)) + } + if (of_property_read_u64_array(np, + "ibm,cpu-idle-state-psscr", + psscr_val, dt_idle_states)) { + pr_warn("cpuidle-powernv: missing ibm,cpu-idle-states-psscr in DT\n"); + rc = -1; goto out; + } - power_mgt = of_find_node_by_path("/ibm,opal/power-mgt"); - if (!power_mgt) { + /* + * Set pnv_first_deep_stop_state to the first stop level + * to cause hypervisor state loss + */ + pnv_first_deep_stop_state = MAX_STOP_STATE; + for (i = 0; i < dt_idle_states; i++) { + u64 psscr_rl = psscr_val[i] & PSSCR_RL_MASK; + + if ((flags[i] & OPAL_PM_LOSE_FULL_CONTEXT) && + (pnv_first_deep_stop_state > psscr_rl)) + pnv_first_deep_stop_state = psscr_rl; + } + +out: + kfree(psscr_val); + return rc; +} + +/* + * Probe device tree for supported idle states + */ +static void __init pnv_probe_idle_states(void) +{ + struct device_node *np; + int dt_idle_states; + u32 *flags = NULL; + int i; + + np = of_find_node_by_path("/ibm,opal/power-mgt"); + if (!np) { pr_warn("opal: PowerMgmt Node not found\n"); goto out; } - dt_idle_states = of_property_count_u32_elems(power_mgt, + dt_idle_states = of_property_count_u32_elems(np, "ibm,cpu-idle-state-flags"); if (dt_idle_states < 0) { pr_warn("cpuidle-powernv: no idle states found in the DT\n"); goto out; } - flags = kzalloc(sizeof(*flags) * dt_idle_states, GFP_KERNEL); - if (of_property_read_u32_array(power_mgt, + flags = kcalloc(dt_idle_states, sizeof(*flags), GFP_KERNEL); + + if (of_property_read_u32_array(np, "ibm,cpu-idle-state-flags", flags, dt_idle_states)) { pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-flags in DT\n"); - goto out_free; + goto out; + } + + if (cpu_has_feature(CPU_FTR_ARCH_300)) { + if (pnv_arch300_idle_init(np, flags, dt_idle_states)) + goto out; } for (i = 0; i < dt_idle_states; i++) supported_cpuidle_states |= flags[i]; +out: + kfree(flags); +} +static int __init pnv_init_idle_states(void) +{ + + supported_cpuidle_states = 0; + + if (cpuidle_disable != IDLE_NO_OVERRIDE) + goto out; + + pnv_probe_idle_states(); + if (!(supported_cpuidle_states & OPAL_PM_SLEEP_ENABLED_ER1)) { patch_instruction( (unsigned int *)pnv_fastsleep_workaround_at_entry, @@ -288,8 +403,9 @@ static int __init pnv_init_idle_states(void) if (supported_cpuidle_states & OPAL_PM_NAP_ENABLED) ppc_md.power_save = power7_idle; -out_free: - kfree(flags); + else if (supported_cpuidle_states & OPAL_PM_STOP_INST_FAST) + ppc_md.power_save = power9_idle; + out: return 0; } -- cgit v1.2.3 From c0691f9dd2066087524d2b4498c0c9331f26dcd5 Mon Sep 17 00:00:00 2001 From: "Shreyas B. Prabhu" Date: Fri, 8 Jul 2016 11:50:53 +0530 Subject: powerpc/powernv: Use deepest stop state when cpu is offlined If hardware supports stop state, use the deepest stop state when the cpu is offlined. Reviewed-by: Gautham R. Shenoy Signed-off-by: Shreyas B. Prabhu Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/idle.c | 15 +++++++++++++-- arch/powerpc/platforms/powernv/powernv.h | 1 + arch/powerpc/platforms/powernv/smp.c | 4 +++- 3 files changed, 17 insertions(+), 3 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c index 8219e22c2b91..479c25601612 100644 --- a/arch/powerpc/platforms/powernv/idle.c +++ b/arch/powerpc/platforms/powernv/idle.c @@ -252,6 +252,11 @@ static void power9_idle(void) */ u64 pnv_first_deep_stop_state = MAX_STOP_STATE; +/* + * Deepest stop idle state. Used when a cpu is offlined + */ +u64 pnv_deepest_stop_state; + /* * Power ISA 3.0 idle initialization. * @@ -314,8 +319,11 @@ static int __init pnv_arch300_idle_init(struct device_node *np, u32 *flags, } /* - * Set pnv_first_deep_stop_state to the first stop level - * to cause hypervisor state loss + * Set pnv_first_deep_stop_state and pnv_deepest_stop_state. + * pnv_first_deep_stop_state should be set to the first stop + * level to cause hypervisor state loss. + * pnv_deepest_stop_state should be set to the deepest stop + * stop state. */ pnv_first_deep_stop_state = MAX_STOP_STATE; for (i = 0; i < dt_idle_states; i++) { @@ -324,6 +332,9 @@ static int __init pnv_arch300_idle_init(struct device_node *np, u32 *flags, if ((flags[i] & OPAL_PM_LOSE_FULL_CONTEXT) && (pnv_first_deep_stop_state > psscr_rl)) pnv_first_deep_stop_state = psscr_rl; + + if (pnv_deepest_stop_state < psscr_rl) + pnv_deepest_stop_state = psscr_rl; } out: diff --git a/arch/powerpc/platforms/powernv/powernv.h b/arch/powerpc/platforms/powernv/powernv.h index 6dbc0a1da1f6..da7c843ac7f1 100644 --- a/arch/powerpc/platforms/powernv/powernv.h +++ b/arch/powerpc/platforms/powernv/powernv.h @@ -18,6 +18,7 @@ static inline void pnv_pci_shutdown(void) { } #endif extern u32 pnv_get_supported_cpuidle_states(void); +extern u64 pnv_deepest_stop_state; extern void pnv_lpc_init(void); diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c index ad7b1a3dbed0..c789258ae1e1 100644 --- a/arch/powerpc/platforms/powernv/smp.c +++ b/arch/powerpc/platforms/powernv/smp.c @@ -182,7 +182,9 @@ static void pnv_smp_cpu_kill_self(void) ppc64_runlatch_off(); - if (idle_states & OPAL_PM_WINKLE_ENABLED) + if (cpu_has_feature(CPU_FTR_ARCH_300)) + srr1 = power9_idle_stop(pnv_deepest_stop_state); + else if (idle_states & OPAL_PM_WINKLE_ENABLED) srr1 = power7_winkle(); else if ((idle_states & OPAL_PM_SLEEP_ENABLED) || (idle_states & OPAL_PM_SLEEP_ENABLED_ER1)) -- cgit v1.2.3 From 9fedd3f8804af87be608310aac707a64f831b344 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 8 Jul 2016 16:37:05 +1000 Subject: powerpc/powernv: Add XICS emulation APIs OPAL provides an emulated XICS interrupt controller to use as a fallback on newer processors that don't have a XICS. It's meant as a way to provide backward compatibility with future processors. Add the corresponding interfaces. Signed-off-by: Benjamin Herrenschmidt Acked-by: Stewart Smith Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/opal-api.h | 6 +++++- arch/powerpc/include/asm/opal.h | 5 +++++ arch/powerpc/platforms/powernv/opal-wrappers.S | 4 ++++ 3 files changed, 14 insertions(+), 1 deletion(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h index 6de1e4e272f9..b349621da6ce 100644 --- a/arch/powerpc/include/asm/opal-api.h +++ b/arch/powerpc/include/asm/opal-api.h @@ -162,7 +162,11 @@ #define OPAL_PCI_GET_PRESENCE_STATE 119 #define OPAL_PCI_GET_POWER_STATE 120 #define OPAL_PCI_SET_POWER_STATE 121 -#define OPAL_LAST 121 +#define OPAL_INT_GET_XIRR 122 +#define OPAL_INT_SET_CPPR 123 +#define OPAL_INT_EOI 124 +#define OPAL_INT_SET_MFRR 125 +#define OPAL_LAST 125 /* Device tree flags */ diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index 52b9f4a80aed..162ebe6f2de6 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h @@ -218,6 +218,11 @@ int64_t opal_pci_set_power_state(uint64_t async_token, uint64_t id, uint64_t data); int64_t opal_pci_poll2(uint64_t id, uint64_t data); +int64_t opal_int_get_xirr(uint32_t *out_xirr, bool just_poll); +int64_t opal_int_set_cppr(uint8_t cppr); +int64_t opal_int_eoi(uint32_t xirr); +int64_t opal_int_set_mfrr(uint32_t cpu, uint8_t mfrr); + /* Internal functions */ extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data); diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S index 7979d6d43bff..c7764f9f661d 100644 --- a/arch/powerpc/platforms/powernv/opal-wrappers.S +++ b/arch/powerpc/platforms/powernv/opal-wrappers.S @@ -307,3 +307,7 @@ OPAL_CALL(opal_get_device_tree, OPAL_GET_DEVICE_TREE); OPAL_CALL(opal_pci_get_presence_state, OPAL_PCI_GET_PRESENCE_STATE); OPAL_CALL(opal_pci_get_power_state, OPAL_PCI_GET_POWER_STATE); OPAL_CALL(opal_pci_set_power_state, OPAL_PCI_SET_POWER_STATE); +OPAL_CALL(opal_int_get_xirr, OPAL_INT_GET_XIRR); +OPAL_CALL(opal_int_set_cppr, OPAL_INT_SET_CPPR); +OPAL_CALL(opal_int_eoi, OPAL_INT_EOI); +OPAL_CALL(opal_int_set_mfrr, OPAL_INT_SET_MFRR); -- cgit v1.2.3 From fb111334e4d9b0365f76d30254fcea9032854867 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 8 Jul 2016 16:37:09 +1000 Subject: powerpc/powernv: Discover IODA3 PHBs We instanciate them as IODA2. We also change the MSI EOI hack to only kick on PHB3 since it will not be needed on any new implementation. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/pci-ioda.c | 3 ++- arch/powerpc/platforms/powernv/pci.c | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 530d4afbe2fd..49de0816cf2b 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -2705,7 +2705,8 @@ void pnv_set_msi_irq_chip(struct pnv_phb *phb, unsigned int virq) struct irq_data *idata; struct irq_chip *ichip; - if (phb->type != PNV_PHB_IODA2) + /* The MSI EOI OPAL call is only needed on PHB3 */ + if (phb->model != PNV_PHB_MODEL_PHB3) return; if (!phb->ioda.irq_chip_init) { diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index 62c7637d4831..4617ea221881 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c @@ -932,6 +932,10 @@ void __init pnv_pci_init(void) for_each_compatible_node(np, NULL, "ibm,ioda2-phb") pnv_pci_init_ioda2_phb(np); + /* Look for ioda3 built-in PHB4's, we treat them as IODA2 */ + for_each_compatible_node(np, NULL, "ibm,ioda3-phb") + pnv_pci_init_ioda2_phb(np); + /* Look for NPU PHBs */ for_each_compatible_node(np, NULL, "ibm,ioda2-npu-phb") pnv_pci_init_npu_phb(np); -- cgit v1.2.3 From b7d6bf4fdd47b7a067e6caecb606e27fd09d1ae9 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 8 Jul 2016 16:37:10 +1000 Subject: powerpc/pseries/pci: Remove obsolete SW invalidate That was used by some old IBM internal bringup tools and is no longer relevant. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/pseries/iommu.c | 53 +--------------------------------- 1 file changed, 1 insertion(+), 52 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 3e8865b187de..770a753b52c9 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -120,35 +120,6 @@ static void iommu_pseries_free_group(struct iommu_table_group *table_group, kfree(table_group); } -static void tce_invalidate_pSeries_sw(struct iommu_table *tbl, - __be64 *startp, __be64 *endp) -{ - u64 __iomem *invalidate = (u64 __iomem *)tbl->it_index; - unsigned long start, end, inc; - - start = __pa(startp); - end = __pa(endp); - inc = L1_CACHE_BYTES; /* invalidate a cacheline of TCEs at a time */ - - /* If this is non-zero, change the format. We shift the - * address and or in the magic from the device tree. */ - if (tbl->it_busno) { - start <<= 12; - end <<= 12; - inc <<= 12; - start |= tbl->it_busno; - end |= tbl->it_busno; - } - - end |= inc - 1; /* round up end to be different than start */ - - mb(); /* Make sure TCEs in memory are written */ - while (start <= end) { - out_be64(invalidate, start); - start += inc; - } -} - static int tce_build_pSeries(struct iommu_table *tbl, long index, long npages, unsigned long uaddr, enum dma_data_direction direction, @@ -173,9 +144,6 @@ static int tce_build_pSeries(struct iommu_table *tbl, long index, uaddr += TCE_PAGE_SIZE; tcep++; } - - if (tbl->it_type & TCE_PCI_SWINV_CREATE) - tce_invalidate_pSeries_sw(tbl, tces, tcep - 1); return 0; } @@ -188,9 +156,6 @@ static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages) while (npages--) *(tcep++) = 0; - - if (tbl->it_type & TCE_PCI_SWINV_FREE) - tce_invalidate_pSeries_sw(tbl, tces, tcep - 1); } static unsigned long tce_get_pseries(struct iommu_table *tbl, long index) @@ -537,7 +502,7 @@ static void iommu_table_setparms(struct pci_controller *phb, struct iommu_table *tbl) { struct device_node *node; - const unsigned long *basep, *sw_inval; + const unsigned long *basep; const u32 *sizep; node = phb->dn; @@ -575,22 +540,6 @@ static void iommu_table_setparms(struct pci_controller *phb, tbl->it_index = 0; tbl->it_blocksize = 16; tbl->it_type = TCE_PCI; - - sw_inval = of_get_property(node, "linux,tce-sw-invalidate-info", NULL); - if (sw_inval) { - /* - * This property contains information on how to - * invalidate the TCE entry. The first property is - * the base MMIO address used to invalidate entries. - * The second property tells us the format of the TCE - * invalidate (whether it needs to be shifted) and - * some magic routing info to add to our invalidate - * command. - */ - tbl->it_index = (unsigned long) ioremap(sw_inval[0], 8); - tbl->it_busno = sw_inval[1]; /* overload this with magic */ - tbl->it_type = TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE; - } } /* -- cgit v1.2.3 From 69c592ed40d32b4b680fd46c1b059cfe8abeb755 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 8 Jul 2016 16:37:11 +1000 Subject: powerpc/opal: Add real mode call wrappers Replace the old generic opal_call_realmode() with proper per-call wrappers similar to the normal ones and convert callers. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/opal-api.h | 10 +++- arch/powerpc/include/asm/opal.h | 6 +++ arch/powerpc/kernel/idle_book3s.S | 16 ++----- arch/powerpc/platforms/powernv/opal-wrappers.S | 63 +++++++++++++------------- 4 files changed, 51 insertions(+), 44 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h index b349621da6ce..0e2e57bcab50 100644 --- a/arch/powerpc/include/asm/opal-api.h +++ b/arch/powerpc/include/asm/opal-api.h @@ -166,7 +166,8 @@ #define OPAL_INT_SET_CPPR 123 #define OPAL_INT_EOI 124 #define OPAL_INT_SET_MFRR 125 -#define OPAL_LAST 125 +#define OPAL_PCI_TCE_KILL 126 +#define OPAL_LAST 126 /* Device tree flags */ @@ -919,6 +920,13 @@ enum { OPAL_REBOOT_PLATFORM_ERROR = 1, }; +/* Argument to OPAL_PCI_TCE_KILL */ +enum { + OPAL_PCI_TCE_KILL_PAGES, + OPAL_PCI_TCE_KILL_PE, + OPAL_PCI_TCE_KILL_ALL, +}; + #endif /* __ASSEMBLY__ */ #endif /* __OPAL_API_H */ diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index 162ebe6f2de6..b656bb192b63 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h @@ -222,6 +222,12 @@ int64_t opal_int_get_xirr(uint32_t *out_xirr, bool just_poll); int64_t opal_int_set_cppr(uint8_t cppr); int64_t opal_int_eoi(uint32_t xirr); int64_t opal_int_set_mfrr(uint32_t cpu, uint8_t mfrr); +int64_t opal_pci_tce_kill(uint64_t phb_id, uint32_t kill_type, + uint32_t pe_num, uint32_t tce_size, + uint64_t dma_addr, uint32_t npages); +int64_t opal_rm_pci_tce_kill(uint64_t phb_id, uint32_t kill_type, + uint32_t pe_num, uint32_t tce_size, + uint64_t dma_addr, uint32_t npages); /* Internal functions */ extern int early_init_dt_scan_opal(unsigned long node, const char *uname, diff --git a/arch/powerpc/kernel/idle_book3s.S b/arch/powerpc/kernel/idle_book3s.S index 1f564eb409c3..335eb6cedae5 100644 --- a/arch/powerpc/kernel/idle_book3s.S +++ b/arch/powerpc/kernel/idle_book3s.S @@ -245,8 +245,7 @@ fastsleep_workaround_at_entry: /* Fast sleep workaround */ li r3,1 li r4,1 - li r0,OPAL_CONFIG_CPU_IDLE_STATE - bl opal_call_realmode + bl opal_rm_config_cpu_idle_state /* Clear Lock bit */ li r0,0 @@ -337,8 +336,7 @@ ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66); \ ld r2,PACATOC(r13); \ ld r1,PACAR1(r13); \ std r3,ORIG_GPR3(r1); /* Save original r3 */ \ - li r0,OPAL_HANDLE_HMI; /* Pass opal token argument*/ \ - bl opal_call_realmode; \ + bl opal_rm_handle_hmi; \ ld r3,ORIG_GPR3(r1); /* Restore original r3 */ \ 20: nop; @@ -430,7 +428,7 @@ _GLOBAL(pnv_wakeup_tb_loss) * until they are restored, they are free to be used. * * Save SRR1 and LR in NVGPRs as they might be clobbered in - * opal_call_realmode (called in CHECK_HMI_INTERRUPT). SRR1 is required + * opal_call() (called in CHECK_HMI_INTERRUPT). SRR1 is required * to determine the wakeup reason if we branch to kvm_start_guest. LR * is required to return back to reset vector after hypervisor state * restore is complete. @@ -530,10 +528,7 @@ timebase_resync: */ ble cr3,clear_lock /* Time base re-sync */ - li r0,OPAL_RESYNC_TIMEBASE - bl opal_call_realmode; - /* TODO: Check r3 for failure */ - + bl opal_rm_resync_timebase; /* * If waking up from sleep, per core state is not lost, skip to * clear_lock. @@ -622,8 +617,7 @@ hypervisor_state_restored: fastsleep_workaround_at_exit: li r3,1 li r4,0 - li r0,OPAL_CONFIG_CPU_IDLE_STATE - bl opal_call_realmode + bl opal_rm_config_cpu_idle_state b timebase_resync /* diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S index c7764f9f661d..cf928bba4d9a 100644 --- a/arch/powerpc/platforms/powernv/opal-wrappers.S +++ b/arch/powerpc/platforms/powernv/opal-wrappers.S @@ -59,7 +59,7 @@ END_FTR_SECTION(0, 1); \ #define OPAL_CALL(name, token) \ _GLOBAL_TOC(name); \ mflr r0; \ - std r0,16(r1); \ + std r0,PPC_LR_STKOFF(r1); \ li r0,token; \ OPAL_BRANCH(opal_tracepoint_entry) \ mfcr r12; \ @@ -92,7 +92,7 @@ opal_return: FIXUP_ENDIAN ld r2,PACATOC(r13); lwz r4,8(r1); - ld r5,16(r1); + ld r5,PPC_LR_STKOFF(r1); ld r6,PACASAVEDMSR(r13); mtspr SPRN_SRR0,r5; mtspr SPRN_SRR1,r6; @@ -157,43 +157,37 @@ opal_tracepoint_return: blr #endif -/* - * Make opal call in realmode. This is a generic function to be called - * from realmode. It handles endianness. - * - * r13 - paca pointer - * r1 - stack pointer - * r0 - opal token - */ -_GLOBAL(opal_call_realmode) - mflr r12 - std r12,PPC_LR_STKOFF(r1) - ld r2,PACATOC(r13) - /* Set opal return address */ - LOAD_REG_ADDR(r12,return_from_opal_call) - mtlr r12 - - mfmsr r12 -#ifdef __LITTLE_ENDIAN__ - /* Handle endian-ness */ - li r11,MSR_LE - andc r12,r12,r11 -#endif - mtspr SPRN_HSRR1,r12 - LOAD_REG_ADDR(r11,opal) - ld r12,8(r11) - ld r2,0(r11) - mtspr SPRN_HSRR0,r12 +#define OPAL_CALL_REAL(name, token) \ + _GLOBAL_TOC(name); \ + mflr r0; \ + std r0,PPC_LR_STKOFF(r1); \ + li r0,token; \ + mfcr r12; \ + stw r12,8(r1); \ + \ + /* Set opal return address */ \ + LOAD_REG_ADDR(r11, opal_return_realmode); \ + mtlr r11; \ + mfmsr r12; \ + li r11,MSR_LE; \ + andc r12,r12,r11; \ + mtspr SPRN_HSRR1,r12; \ + LOAD_REG_ADDR(r11,opal); \ + ld r12,8(r11); \ + ld r2,0(r11); \ + mtspr SPRN_HSRR0,r12; \ hrfid -return_from_opal_call: -#ifdef __LITTLE_ENDIAN__ +opal_return_realmode: FIXUP_ENDIAN -#endif + ld r2,PACATOC(r13); + lwz r11,8(r1); ld r12,PPC_LR_STKOFF(r1) + mtcr r11; mtlr r12 blr + OPAL_CALL(opal_invalid_call, OPAL_INVALID_CALL); OPAL_CALL(opal_console_write, OPAL_CONSOLE_WRITE); OPAL_CALL(opal_console_read, OPAL_CONSOLE_READ); @@ -271,6 +265,7 @@ OPAL_CALL(opal_validate_flash, OPAL_FLASH_VALIDATE); OPAL_CALL(opal_manage_flash, OPAL_FLASH_MANAGE); OPAL_CALL(opal_update_flash, OPAL_FLASH_UPDATE); OPAL_CALL(opal_resync_timebase, OPAL_RESYNC_TIMEBASE); +OPAL_CALL_REAL(opal_rm_resync_timebase, OPAL_RESYNC_TIMEBASE); OPAL_CALL(opal_check_token, OPAL_CHECK_TOKEN); OPAL_CALL(opal_dump_init, OPAL_DUMP_INIT); OPAL_CALL(opal_dump_info, OPAL_DUMP_INFO); @@ -286,7 +281,9 @@ OPAL_CALL(opal_sensor_read, OPAL_SENSOR_READ); OPAL_CALL(opal_get_param, OPAL_GET_PARAM); OPAL_CALL(opal_set_param, OPAL_SET_PARAM); OPAL_CALL(opal_handle_hmi, OPAL_HANDLE_HMI); +OPAL_CALL_REAL(opal_rm_handle_hmi, OPAL_HANDLE_HMI); OPAL_CALL(opal_config_cpu_idle_state, OPAL_CONFIG_CPU_IDLE_STATE); +OPAL_CALL_REAL(opal_rm_config_cpu_idle_state, OPAL_CONFIG_CPU_IDLE_STATE); OPAL_CALL(opal_slw_set_reg, OPAL_SLW_SET_REG); OPAL_CALL(opal_register_dump_region, OPAL_REGISTER_DUMP_REGION); OPAL_CALL(opal_unregister_dump_region, OPAL_UNREGISTER_DUMP_REGION); @@ -311,3 +308,5 @@ OPAL_CALL(opal_int_get_xirr, OPAL_INT_GET_XIRR); OPAL_CALL(opal_int_set_cppr, OPAL_INT_SET_CPPR); OPAL_CALL(opal_int_eoi, OPAL_INT_EOI); OPAL_CALL(opal_int_set_mfrr, OPAL_INT_SET_MFRR); +OPAL_CALL(opal_pci_tce_kill, OPAL_PCI_TCE_KILL); +OPAL_CALL_REAL(opal_rm_pci_tce_kill, OPAL_PCI_TCE_KILL); -- cgit v1.2.3 From a34ab7c328b969d9f841e7887f6be3cc45b5202e Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 8 Jul 2016 16:37:12 +1000 Subject: powerpc/powernv/pci: Rename TCE invalidation calls The TCE invalidation functions are fairly implementation specific, and while the IODA specs more/less describe the register, in practice various implementation workarounds may be required. So name the functions after the target PHB. Note today and for the foreseeable future, there's a 1:1 relationship between an IODA version and a PHB implementation. There exist another variant of IODA1 (Torrent) but we never supported in with OPAL and never will. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/npu-dma.c | 8 +++---- arch/powerpc/platforms/powernv/pci-ioda.c | 36 +++++++++++++++---------------- arch/powerpc/platforms/powernv/pci.h | 4 +--- 3 files changed, 23 insertions(+), 25 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powernv/npu-dma.c b/arch/powerpc/platforms/powernv/npu-dma.c index 0459e100b4e7..4383a5ff82ba 100644 --- a/arch/powerpc/platforms/powernv/npu-dma.c +++ b/arch/powerpc/platforms/powernv/npu-dma.c @@ -180,7 +180,7 @@ long pnv_npu_set_window(struct pnv_ioda_pe *npe, int num, pe_err(npe, "Failed to configure TCE table, err %lld\n", rc); return rc; } - pnv_pci_ioda2_tce_invalidate_entire(phb, false); + pnv_pci_phb3_tce_invalidate_entire(phb, false); /* Add the table to the list so its TCE cache will get invalidated */ pnv_pci_link_table_and_group(phb->hose->node, num, @@ -204,7 +204,7 @@ long pnv_npu_unset_window(struct pnv_ioda_pe *npe, int num) pe_err(npe, "Unmapping failed, ret = %lld\n", rc); return rc; } - pnv_pci_ioda2_tce_invalidate_entire(phb, false); + pnv_pci_phb3_tce_invalidate_entire(phb, false); pnv_pci_unlink_table_and_group(npe->table_group.tables[num], &npe->table_group); @@ -270,7 +270,7 @@ static int pnv_npu_dma_set_bypass(struct pnv_ioda_pe *npe) 0 /* bypass base */, top); if (rc == OPAL_SUCCESS) - pnv_pci_ioda2_tce_invalidate_entire(phb, false); + pnv_pci_phb3_tce_invalidate_entire(phb, false); return rc; } @@ -334,7 +334,7 @@ void pnv_npu_take_ownership(struct pnv_ioda_pe *npe) pe_err(npe, "Failed to disable bypass, err %lld\n", rc); return; } - pnv_pci_ioda2_tce_invalidate_entire(npe->phb, false); + pnv_pci_phb3_tce_invalidate_entire(npe->phb, false); } struct pnv_ioda_pe *pnv_pci_npu_setup_iommu(struct pnv_ioda_pe *npe) diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 49de0816cf2b..4817bd1d1187 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -1721,7 +1721,7 @@ static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, } } -static void pnv_pci_ioda1_tce_invalidate(struct iommu_table *tbl, +static void pnv_pci_p7ioc_tce_invalidate(struct iommu_table *tbl, unsigned long index, unsigned long npages, bool rm) { struct iommu_table_group_link *tgl = list_first_entry_or_null( @@ -1782,7 +1782,7 @@ static int pnv_ioda1_tce_build(struct iommu_table *tbl, long index, attrs); if (!ret && (tbl->it_type & TCE_PCI_SWINV_CREATE)) - pnv_pci_ioda1_tce_invalidate(tbl, index, npages, false); + pnv_pci_p7ioc_tce_invalidate(tbl, index, npages, false); return ret; } @@ -1795,7 +1795,7 @@ static int pnv_ioda1_tce_xchg(struct iommu_table *tbl, long index, if (!ret && (tbl->it_type & (TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE))) - pnv_pci_ioda1_tce_invalidate(tbl, index, 1, false); + pnv_pci_p7ioc_tce_invalidate(tbl, index, 1, false); return ret; } @@ -1807,7 +1807,7 @@ static void pnv_ioda1_tce_free(struct iommu_table *tbl, long index, pnv_tce_free(tbl, index, npages); if (tbl->it_type & TCE_PCI_SWINV_FREE) - pnv_pci_ioda1_tce_invalidate(tbl, index, npages, false); + pnv_pci_p7ioc_tce_invalidate(tbl, index, npages, false); } static struct iommu_table_ops pnv_ioda1_iommu_ops = { @@ -1819,13 +1819,13 @@ static struct iommu_table_ops pnv_ioda1_iommu_ops = { .get = pnv_tce_get, }; -#define TCE_KILL_INVAL_ALL PPC_BIT(0) -#define TCE_KILL_INVAL_PE PPC_BIT(1) -#define TCE_KILL_INVAL_TCE PPC_BIT(2) +#define PHB3_TCE_KILL_INVAL_ALL PPC_BIT(0) +#define PHB3_TCE_KILL_INVAL_PE PPC_BIT(1) +#define PHB3_TCE_KILL_INVAL_ONE PPC_BIT(2) -void pnv_pci_ioda2_tce_invalidate_entire(struct pnv_phb *phb, bool rm) +void pnv_pci_phb3_tce_invalidate_entire(struct pnv_phb *phb, bool rm) { - const unsigned long val = TCE_KILL_INVAL_ALL; + const unsigned long val = PHB3_TCE_KILL_INVAL_ALL; mb(); /* Ensure previous TCE table stores are visible */ if (rm) @@ -1836,10 +1836,10 @@ void pnv_pci_ioda2_tce_invalidate_entire(struct pnv_phb *phb, bool rm) __raw_writeq(cpu_to_be64(val), phb->ioda.tce_inval_reg); } -static inline void pnv_pci_ioda2_tce_invalidate_pe(struct pnv_ioda_pe *pe) +static inline void pnv_pci_phb3_tce_invalidate_pe(struct pnv_ioda_pe *pe) { /* 01xb - invalidate TCEs that match the specified PE# */ - unsigned long val = TCE_KILL_INVAL_PE | (pe->pe_number & 0xFF); + unsigned long val = PHB3_TCE_KILL_INVAL_PE | (pe->pe_number & 0xFF); struct pnv_phb *phb = pe->phb; if (!phb->ioda.tce_inval_reg) @@ -1849,14 +1849,14 @@ static inline void pnv_pci_ioda2_tce_invalidate_pe(struct pnv_ioda_pe *pe) __raw_writeq(cpu_to_be64(val), phb->ioda.tce_inval_reg); } -static void pnv_pci_ioda2_do_tce_invalidate(unsigned pe_number, bool rm, +static void pnv_pci_phb3_tce_invalidate(unsigned pe_number, bool rm, __be64 __iomem *invalidate, unsigned shift, unsigned long index, unsigned long npages) { unsigned long start, end, inc; /* We'll invalidate DMA address in PE scope */ - start = TCE_KILL_INVAL_TCE; + start = PHB3_TCE_KILL_INVAL_ONE; start |= (pe_number & 0xFF); end = start; @@ -1893,10 +1893,10 @@ static void pnv_pci_ioda2_tce_invalidate(struct iommu_table *tbl, * per TCE entry so we have to invalidate * the entire cache for it. */ - pnv_pci_ioda2_tce_invalidate_entire(pe->phb, rm); + pnv_pci_phb3_tce_invalidate_entire(pe->phb, rm); continue; } - pnv_pci_ioda2_do_tce_invalidate(pe->pe_number, rm, + pnv_pci_phb3_tce_invalidate(pe->pe_number, rm, invalidate, tbl->it_page_shift, index, npages); } @@ -2172,7 +2172,7 @@ static long pnv_pci_ioda2_set_window(struct iommu_table_group *table_group, pnv_pci_link_table_and_group(phb->hose->node, num, tbl, &pe->table_group); - pnv_pci_ioda2_tce_invalidate_pe(pe); + pnv_pci_phb3_tce_invalidate_pe(pe); return 0; } @@ -2316,7 +2316,7 @@ static long pnv_pci_ioda2_unset_window(struct iommu_table_group *table_group, if (ret) pe_warn(pe, "Unmapping failed, ret = %ld\n", ret); else - pnv_pci_ioda2_tce_invalidate_pe(pe); + pnv_pci_phb3_tce_invalidate_pe(pe); pnv_pci_unlink_table_and_group(table_group->tables[num], table_group); @@ -3286,7 +3286,7 @@ static void pnv_pci_ioda1_release_pe_dma(struct pnv_ioda_pe *pe) if (rc != OPAL_SUCCESS) return; - pnv_pci_ioda1_tce_invalidate(tbl, tbl->it_offset, tbl->it_size, false); + pnv_pci_p7ioc_tce_invalidate(tbl, tbl->it_offset, tbl->it_size, false); if (pe->table_group.group) { iommu_group_put(pe->table_group.group); WARN_ON(pe->table_group.group); diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index f0c276c05f50..1336fe2fce51 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h @@ -211,8 +211,6 @@ extern void pnv_pci_setup_iommu_table(struct iommu_table *tbl, extern void pnv_pci_init_ioda_hub(struct device_node *np); extern void pnv_pci_init_ioda2_phb(struct device_node *np); extern void pnv_pci_init_npu_phb(struct device_node *np); -extern void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl, - __be64 *startp, __be64 *endp, bool rm); extern void pnv_pci_reset_secondary_bus(struct pci_dev *dev); extern int pnv_eeh_phb_reset(struct pci_controller *hose, int option); @@ -235,7 +233,7 @@ extern void pe_level_printk(const struct pnv_ioda_pe *pe, const char *level, /* Nvlink functions */ extern void pnv_npu_try_dma_set_bypass(struct pci_dev *gpdev, bool bypass); -extern void pnv_pci_ioda2_tce_invalidate_entire(struct pnv_phb *phb, bool rm); +extern void pnv_pci_phb3_tce_invalidate_entire(struct pnv_phb *phb, bool rm); extern struct pnv_ioda_pe *pnv_pci_npu_setup_iommu(struct pnv_ioda_pe *npe); extern long pnv_npu_set_window(struct pnv_ioda_pe *npe, int num, struct iommu_table *tbl); -- cgit v1.2.3 From 08acce1cab7c80f38169435c0a122369f07f12e8 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 8 Jul 2016 16:37:13 +1000 Subject: powerpc/powernv/pci: Remove SWINV constants and obsolete TCE code We have some obsolete code in pnv_pci_p7ioc_tce_invalidate() to handle some internal lab tools that have stopped being useful a long time ago. Remove that along with the definition and test for the TCE_PCI_SWINV_* flags whose value is basically always the same. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/tce.h | 3 -- arch/powerpc/platforms/powernv/pci-ioda.c | 50 +++++++------------------------ 2 files changed, 10 insertions(+), 43 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/include/asm/tce.h b/arch/powerpc/include/asm/tce.h index 743f36b38e5d..12e362935160 100644 --- a/arch/powerpc/include/asm/tce.h +++ b/arch/powerpc/include/asm/tce.h @@ -31,9 +31,6 @@ */ #define TCE_VB 0 #define TCE_PCI 1 -#define TCE_PCI_SWINV_CREATE 2 -#define TCE_PCI_SWINV_FREE 4 -#define TCE_PCI_SWINV_PAIR 8 /* TCE page size is 4096 bytes (1 << 12) */ diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 4817bd1d1187..c9494eacef51 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -1733,29 +1733,15 @@ static void pnv_pci_p7ioc_tce_invalidate(struct iommu_table *tbl, (__be64 __iomem *)pe->phb->ioda.tce_inval_reg_phys : pe->phb->ioda.tce_inval_reg; unsigned long start, end, inc; - const unsigned shift = tbl->it_page_shift; start = __pa(((__be64 *)tbl->it_base) + index - tbl->it_offset); end = __pa(((__be64 *)tbl->it_base) + index - tbl->it_offset + npages - 1); - /* BML uses this case for p6/p7/galaxy2: Shift addr and put in node */ - if (tbl->it_busno) { - start <<= shift; - end <<= shift; - inc = 128ull << shift; - start |= tbl->it_busno; - end |= tbl->it_busno; - } else if (tbl->it_type & TCE_PCI_SWINV_PAIR) { - /* p7ioc-style invalidation, 2 TCEs per write */ - start |= (1ull << 63); - end |= (1ull << 63); - inc = 16; - } else { - /* Default (older HW) */ - inc = 128; - } - + /* p7ioc-style invalidation, 2 TCEs per write */ + start |= (1ull << 63); + end |= (1ull << 63); + inc = 16; end |= inc - 1; /* round up end to be different than start */ mb(); /* Ensure above stores are visible */ @@ -1781,7 +1767,7 @@ static int pnv_ioda1_tce_build(struct iommu_table *tbl, long index, int ret = pnv_tce_build(tbl, index, npages, uaddr, direction, attrs); - if (!ret && (tbl->it_type & TCE_PCI_SWINV_CREATE)) + if (!ret) pnv_pci_p7ioc_tce_invalidate(tbl, index, npages, false); return ret; @@ -1793,8 +1779,7 @@ static int pnv_ioda1_tce_xchg(struct iommu_table *tbl, long index, { long ret = pnv_tce_xchg(tbl, index, hpa, direction); - if (!ret && (tbl->it_type & - (TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE))) + if (!ret) pnv_pci_p7ioc_tce_invalidate(tbl, index, 1, false); return ret; @@ -1806,8 +1791,7 @@ static void pnv_ioda1_tce_free(struct iommu_table *tbl, long index, { pnv_tce_free(tbl, index, npages); - if (tbl->it_type & TCE_PCI_SWINV_FREE) - pnv_pci_p7ioc_tce_invalidate(tbl, index, npages, false); + pnv_pci_p7ioc_tce_invalidate(tbl, index, npages, false); } static struct iommu_table_ops pnv_ioda1_iommu_ops = { @@ -1910,7 +1894,7 @@ static int pnv_ioda2_tce_build(struct iommu_table *tbl, long index, int ret = pnv_tce_build(tbl, index, npages, uaddr, direction, attrs); - if (!ret && (tbl->it_type & TCE_PCI_SWINV_CREATE)) + if (!ret) pnv_pci_ioda2_tce_invalidate(tbl, index, npages, false); return ret; @@ -1922,8 +1906,7 @@ static int pnv_ioda2_tce_xchg(struct iommu_table *tbl, long index, { long ret = pnv_tce_xchg(tbl, index, hpa, direction); - if (!ret && (tbl->it_type & - (TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE))) + if (!ret) pnv_pci_ioda2_tce_invalidate(tbl, index, 1, false); return ret; @@ -1935,8 +1918,7 @@ static void pnv_ioda2_tce_free(struct iommu_table *tbl, long index, { pnv_tce_free(tbl, index, npages); - if (tbl->it_type & TCE_PCI_SWINV_FREE) - pnv_pci_ioda2_tce_invalidate(tbl, index, npages, false); + pnv_pci_ioda2_tce_invalidate(tbl, index, npages, false); } static void pnv_ioda2_table_free(struct iommu_table *tbl) @@ -2105,12 +2087,6 @@ found: base * PNV_IODA1_DMA32_SEGSIZE, IOMMU_PAGE_SHIFT_4K); - /* OPAL variant of P7IOC SW invalidated TCEs */ - if (phb->ioda.tce_inval_reg) - tbl->it_type |= (TCE_PCI_SWINV_CREATE | - TCE_PCI_SWINV_FREE | - TCE_PCI_SWINV_PAIR); - tbl->it_ops = &pnv_ioda1_iommu_ops; pe->table_group.tce32_start = tbl->it_offset << tbl->it_page_shift; pe->table_group.tce32_size = tbl->it_size << tbl->it_page_shift; @@ -2233,8 +2209,6 @@ static long pnv_pci_ioda2_create_table(struct iommu_table_group *table_group, } tbl->it_ops = &pnv_ioda2_iommu_ops; - if (pe->phb->ioda.tce_inval_reg) - tbl->it_type |= (TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE); *ptbl = tbl; @@ -2283,10 +2257,6 @@ static long pnv_pci_ioda2_setup_default_config(struct pnv_ioda_pe *pe) if (!pnv_iommu_bypass_disabled) pnv_pci_ioda2_set_bypass(pe, true); - /* OPAL variant of PHB3 invalidated TCEs */ - if (pe->phb->ioda.tce_inval_reg) - tbl->it_type |= (TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE); - /* * Setting table base here only for carrying iommu_group * further down to let iommu_add_device() do the job. -- cgit v1.2.3 From fd141d1a99a300944dc42a7820afb8c1bafd4035 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 8 Jul 2016 16:37:14 +1000 Subject: powerpc/powernv/pci: Rework accessing the TCE invalidate register It's architected, always in a known place, so there is no need to keep a separate pointer to it, we use the existing "regs", and we complement it with a real mode variant. Signed-off-by: Benjamin Herrenschmidt # Conflicts: # arch/powerpc/platforms/powernv/pci-ioda.c # arch/powerpc/platforms/powernv/pci.h Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/pci-ioda.c | 69 ++++++++++++------------------- arch/powerpc/platforms/powernv/pci.h | 7 +--- 2 files changed, 28 insertions(+), 48 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index c9494eacef51..6203b2f3db40 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -1721,6 +1721,13 @@ static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, } } +static inline __be64 __iomem *pnv_ioda_get_inval_reg(struct pnv_phb *phb, + bool real_mode) +{ + return real_mode ? (__be64 __iomem *)(phb->regs_phys + 0x210) : + (phb->regs + 0x210); +} + static void pnv_pci_p7ioc_tce_invalidate(struct iommu_table *tbl, unsigned long index, unsigned long npages, bool rm) { @@ -1729,9 +1736,7 @@ static void pnv_pci_p7ioc_tce_invalidate(struct iommu_table *tbl, next); struct pnv_ioda_pe *pe = container_of(tgl->table_group, struct pnv_ioda_pe, table_group); - __be64 __iomem *invalidate = rm ? - (__be64 __iomem *)pe->phb->ioda.tce_inval_reg_phys : - pe->phb->ioda.tce_inval_reg; + __be64 __iomem *invalidate = pnv_ioda_get_inval_reg(pe->phb, rm); unsigned long start, end, inc; start = __pa(((__be64 *)tbl->it_base) + index - tbl->it_offset); @@ -1809,39 +1814,36 @@ static struct iommu_table_ops pnv_ioda1_iommu_ops = { void pnv_pci_phb3_tce_invalidate_entire(struct pnv_phb *phb, bool rm) { + __be64 __iomem *invalidate = pnv_ioda_get_inval_reg(phb, rm); const unsigned long val = PHB3_TCE_KILL_INVAL_ALL; mb(); /* Ensure previous TCE table stores are visible */ if (rm) - __raw_rm_writeq(cpu_to_be64(val), - (__be64 __iomem *) - phb->ioda.tce_inval_reg_phys); + __raw_rm_writeq(cpu_to_be64(val), invalidate); else - __raw_writeq(cpu_to_be64(val), phb->ioda.tce_inval_reg); + __raw_writeq(cpu_to_be64(val), invalidate); } static inline void pnv_pci_phb3_tce_invalidate_pe(struct pnv_ioda_pe *pe) { /* 01xb - invalidate TCEs that match the specified PE# */ + __be64 __iomem *invalidate = pnv_ioda_get_inval_reg(pe->phb, false); unsigned long val = PHB3_TCE_KILL_INVAL_PE | (pe->pe_number & 0xFF); - struct pnv_phb *phb = pe->phb; - - if (!phb->ioda.tce_inval_reg) - return; mb(); /* Ensure above stores are visible */ - __raw_writeq(cpu_to_be64(val), phb->ioda.tce_inval_reg); + __raw_writeq(cpu_to_be64(val), invalidate); } -static void pnv_pci_phb3_tce_invalidate(unsigned pe_number, bool rm, - __be64 __iomem *invalidate, unsigned shift, - unsigned long index, unsigned long npages) +static void pnv_pci_phb3_tce_invalidate(struct pnv_ioda_pe *pe, bool rm, + unsigned shift, unsigned long index, + unsigned long npages) { + __be64 __iomem *invalidate = pnv_ioda_get_inval_reg(pe->phb, false); unsigned long start, end, inc; /* We'll invalidate DMA address in PE scope */ start = PHB3_TCE_KILL_INVAL_ONE; - start |= (pe_number & 0xFF); + start |= (pe->pe_number & 0xFF); end = start; /* Figure out the start, end and step */ @@ -1867,10 +1869,6 @@ static void pnv_pci_ioda2_tce_invalidate(struct iommu_table *tbl, list_for_each_entry_rcu(tgl, &tbl->it_group_list, next) { struct pnv_ioda_pe *pe = container_of(tgl->table_group, struct pnv_ioda_pe, table_group); - __be64 __iomem *invalidate = rm ? - (__be64 __iomem *)pe->phb->ioda.tce_inval_reg_phys : - pe->phb->ioda.tce_inval_reg; - if (pe->phb->type == PNV_PHB_NPU) { /* * The NVLink hardware does not support TCE kill @@ -1880,9 +1878,8 @@ static void pnv_pci_ioda2_tce_invalidate(struct iommu_table *tbl, pnv_pci_phb3_tce_invalidate_entire(pe->phb, rm); continue; } - pnv_pci_phb3_tce_invalidate(pe->pe_number, rm, - invalidate, tbl->it_page_shift, - index, npages); + pnv_pci_phb3_tce_invalidate(pe, rm, tbl->it_page_shift, + index, npages); } } @@ -2467,19 +2464,6 @@ static void pnv_pci_ioda_setup_iommu_api(void) static void pnv_pci_ioda_setup_iommu_api(void) { }; #endif -static void pnv_pci_ioda_setup_opal_tce_kill(struct pnv_phb *phb) -{ - const __be64 *swinvp; - - /* OPAL variant of PHB3 invalidated TCEs */ - swinvp = of_get_property(phb->hose->dn, "ibm,opal-tce-kill", NULL); - if (!swinvp) - return; - - phb->ioda.tce_inval_reg_phys = be64_to_cpup(swinvp); - phb->ioda.tce_inval_reg = ioremap(phb->ioda.tce_inval_reg_phys, 8); -} - static __be64 *pnv_pci_ioda2_table_do_alloc_pages(int nid, unsigned shift, unsigned levels, unsigned long limit, unsigned long *current_offset, unsigned long *total_allocated) @@ -3459,6 +3443,7 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, struct pnv_phb *phb; unsigned long size, m64map_off, m32map_off, pemap_off; unsigned long iomap_off = 0, dma32map_off = 0; + struct resource r; const __be64 *prop64; const __be32 *prop32; int len; @@ -3519,12 +3504,12 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, pci_process_bridge_OF_ranges(hose, np, !hose->global_number); /* Get registers */ - phb->regs = of_iomap(np, 0); - if (phb->regs == NULL) - pr_err(" Failed to map registers !\n"); - - /* Initialize TCE kill register */ - pnv_pci_ioda_setup_opal_tce_kill(phb); + if (!of_address_to_resource(np, 0, &r)) { + phb->regs_phys = r.start; + phb->regs = ioremap(r.start, resource_size(&r)); + if (phb->regs == NULL) + pr_err(" Failed to map registers !\n"); + } /* Initialize more IODA stuff */ phb->ioda.total_pe_num = 1; diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index 1336fe2fce51..d088d4f06116 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h @@ -86,6 +86,7 @@ struct pnv_phb { u64 opal_id; int flags; void __iomem *regs; + u64 regs_phys; int initialized; spinlock_t lock; @@ -162,12 +163,6 @@ struct pnv_phb { /* Reverse map of PEs, indexed by {bus, devfn} */ unsigned int pe_rmap[0x10000]; - - /* TCE cache invalidate registers (physical and - * remapped) - */ - phys_addr_t tce_inval_reg_phys; - __be64 __iomem *tce_inval_reg; } ioda; /* PHB and hub status structure */ -- cgit v1.2.3 From f0228c413011b7e20de9198c4a7244f498dcda2a Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 8 Jul 2016 16:37:15 +1000 Subject: powerpc/powernv/pci: Fallback to OPAL for TCE invalidations If we don't find registers for the PHB or don't know the model specific invalidation method, use OPAL calls instead. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/pci-ioda.c | 33 +++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 6203b2f3db40..d7502f2265bc 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -1861,6 +1861,17 @@ static void pnv_pci_phb3_tce_invalidate(struct pnv_ioda_pe *pe, bool rm, } } +static inline void pnv_pci_ioda2_tce_invalidate_pe(struct pnv_ioda_pe *pe) +{ + struct pnv_phb *phb = pe->phb; + + if (phb->model == PNV_PHB_MODEL_PHB3 && phb->regs) + pnv_pci_phb3_tce_invalidate_pe(pe); + else + opal_pci_tce_kill(phb->opal_id, OPAL_PCI_TCE_KILL_PE, + pe->pe_number, 0, 0, 0); +} + static void pnv_pci_ioda2_tce_invalidate(struct iommu_table *tbl, unsigned long index, unsigned long npages, bool rm) { @@ -1869,17 +1880,31 @@ static void pnv_pci_ioda2_tce_invalidate(struct iommu_table *tbl, list_for_each_entry_rcu(tgl, &tbl->it_group_list, next) { struct pnv_ioda_pe *pe = container_of(tgl->table_group, struct pnv_ioda_pe, table_group); - if (pe->phb->type == PNV_PHB_NPU) { + struct pnv_phb *phb = pe->phb; + unsigned int shift = tbl->it_page_shift; + + if (phb->type == PNV_PHB_NPU) { /* * The NVLink hardware does not support TCE kill * per TCE entry so we have to invalidate * the entire cache for it. */ - pnv_pci_phb3_tce_invalidate_entire(pe->phb, rm); + pnv_pci_phb3_tce_invalidate_entire(phb, rm); continue; } - pnv_pci_phb3_tce_invalidate(pe, rm, tbl->it_page_shift, - index, npages); + if (phb->model == PNV_PHB_MODEL_PHB3 && phb->regs) + pnv_pci_phb3_tce_invalidate(pe, rm, shift, + index, npages); + else if (rm) + opal_rm_pci_tce_kill(phb->opal_id, + OPAL_PCI_TCE_KILL_PAGES, + pe->pe_number, 1u << shift, + index << shift, npages); + else + opal_pci_tce_kill(phb->opal_id, + OPAL_PCI_TCE_KILL_PAGES, + pe->pe_number, 1u << shift, + index << shift, npages); } } -- cgit v1.2.3 From a1339faf72ac0d90797516ad0996cec18fe534b5 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 8 Jul 2016 16:37:16 +1000 Subject: powerpc/powernv/pci: Use the device-tree to get available range of M64's M64's are the configurable 64-bit windows that cover the 64-bit MMIO space. We used to hard code 16 windows. Newer chips might have a variable number and might need to reserve some as well (for example on PHB4/POWER9, M32 and M64 are actually unified and we use M64#0 to map the 32-bit space). So newer OPALs will provide a property we can use to know what range of windows is available. The property is named so that it can eventually support multiple ranges but we only use the first one for now. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/pci-ioda.c | 51 +++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 6 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index d7502f2265bc..ed27f4cb28ca 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -191,9 +191,6 @@ static int pnv_ioda2_init_m64(struct pnv_phb *phb) goto fail; } - /* Mark the M64 BAR assigned */ - set_bit(phb->ioda.m64_bar_idx, &phb->ioda.m64_bar_alloc); - /* * Exclude the segments for reserved and root bus PE, which * are first or last two PEs. @@ -404,6 +401,7 @@ static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb) struct pci_controller *hose = phb->hose; struct device_node *dn = hose->dn; struct resource *res; + u32 m64_range[2], i; const u32 *r; u64 pci_addr; @@ -424,6 +422,30 @@ static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb) return; } + /* + * Find the available M64 BAR range and pickup the last one for + * covering the whole 64-bits space. We support only one range. + */ + if (of_property_read_u32_array(dn, "ibm,opal-available-m64-ranges", + m64_range, 2)) { + /* In absence of the property, assume 0..15 */ + m64_range[0] = 0; + m64_range[1] = 16; + } + /* We only support 64 bits in our allocator */ + if (m64_range[1] > 63) { + pr_warn("%s: Limiting M64 range to 63 (from %d) on PHB#%x\n", + __func__, m64_range[1], phb->hose->global_number); + m64_range[1] = 63; + } + /* Empty range, no m64 */ + if (m64_range[1] <= m64_range[0]) { + pr_warn("%s: M64 empty, disabling M64 usage on PHB#%x\n", + __func__, phb->hose->global_number); + return; + } + + /* Configure M64 informations */ res = &hose->mem_resources[1]; res->name = dn->full_name; res->start = of_translate_address(dn, r + 2); @@ -436,11 +458,28 @@ static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb) phb->ioda.m64_segsize = phb->ioda.m64_size / phb->ioda.total_pe_num; phb->ioda.m64_base = pci_addr; - pr_info(" MEM64 0x%016llx..0x%016llx -> 0x%016llx\n", - res->start, res->end, pci_addr); + /* This lines up nicely with the display from processing OF ranges */ + pr_info(" MEM 0x%016llx..0x%016llx -> 0x%016llx (M64 #%d..%d)\n", + res->start, res->end, pci_addr, m64_range[0], + m64_range[0] + m64_range[1] - 1); + + /* Mark all M64 used up by default */ + phb->ioda.m64_bar_alloc = (unsigned long)-1; /* Use last M64 BAR to cover M64 window */ - phb->ioda.m64_bar_idx = 15; + m64_range[1]--; + phb->ioda.m64_bar_idx = m64_range[0] + m64_range[1]; + + pr_info(" Using M64 #%d as default window\n", phb->ioda.m64_bar_idx); + + /* Mark remaining ones free */ + for (i = m64_range[0]; i < m64_range[1]; i++) + clear_bit(i, &phb->ioda.m64_bar_alloc); + + /* + * Setup init functions for M64 based on IODA version, IODA3 uses + * the IODA2 code. + */ if (phb->type == PNV_PHB_IODA1) phb->init_m64 = pnv_ioda1_init_m64; else -- cgit v1.2.3 From 08a45b320a0ec76866acca7db2fe2647387e5c21 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 8 Jul 2016 16:37:17 +1000 Subject: powerpc/powernv/pci: Check status of a PHB before using it If the firmware encounters an error (internal or HW) during initialization of a PHB, it might leave the device-node in the tree but mark it disabled using the "status" property. We should check it. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/pci-ioda.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index ed27f4cb28ca..891fc4a453df 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -3516,6 +3516,9 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, void *aux; long rc; + if (!of_device_is_available(np)) + return; + pr_info("Initializing %s PHB (%s)\n", pnv_phb_names[ioda_type], of_node_full_name(np)); -- cgit v1.2.3 From c2ca9f6b4cc4c45eb598b24b8b06beee668052d5 Mon Sep 17 00:00:00 2001 From: Ian Munsie Date: Tue, 19 Jul 2016 12:33:35 +1000 Subject: powerpc/powernv: Fix pci-cxl.c build when CONFIG_MODULES=n pnv_cxl_enable_phb_kernel_api() grabs a reference to the cxl module to prevent it from being unloaded after the PHB has been switched to CX4 mode. This breaks the build when CONFIG_MODULES=n as module_mutex doesn't exist. However, if we don't have modules, we don't need to protect against the case of the cxl module being unloaded. As such, split the relevant code out into a function surrounded with #if IS_MODULE(CXL) so we don't try to compile it if cxl isn't being compiled as a module. Fixes: 5918dbc9b4ec ("powerpc/powernv: Add support for the cxl kernel api on the real phb") Reported-by: Michael Ellerman Signed-off-by: Ian Munsie Signed-off-by: Andrew Donnellan Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/pci-cxl.c | 34 ++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powernv/pci-cxl.c b/arch/powerpc/platforms/powernv/pci-cxl.c index 3f342077628b..1349a099c74c 100644 --- a/arch/powerpc/platforms/powernv/pci-cxl.c +++ b/arch/powerpc/platforms/powernv/pci-cxl.c @@ -166,6 +166,28 @@ int pnv_cxl_ioda_msi_setup(struct pci_dev *dev, unsigned int hwirq, } EXPORT_SYMBOL(pnv_cxl_ioda_msi_setup); +#if IS_MODULE(CONFIG_CXL) +static inline int get_cxl_module(void) +{ + struct module *cxl_module; + + mutex_lock(&module_mutex); + + cxl_module = find_module("cxl"); + if (cxl_module) + __module_get(cxl_module); + + mutex_unlock(&module_mutex); + + if (!cxl_module) + return -ENODEV; + + return 0; +} +#else +static inline int get_cxl_module(void) { return 0; } +#endif + /* * Sets flags and switches the controller ops to enable the cxl kernel api. * Originally the cxl kernel API operated on a virtual PHB, but certain cards @@ -175,7 +197,7 @@ EXPORT_SYMBOL(pnv_cxl_ioda_msi_setup); int pnv_cxl_enable_phb_kernel_api(struct pci_controller *hose, bool enable) { struct pnv_phb *phb = hose->private_data; - struct module *cxl_module; + int rc; if (!enable) { /* @@ -194,13 +216,9 @@ int pnv_cxl_enable_phb_kernel_api(struct pci_controller *hose, bool enable) * long as we are in this mode (and since we can't safely disable this * mode once enabled...). */ - mutex_lock(&module_mutex); - cxl_module = find_module("cxl"); - if (cxl_module) - __module_get(cxl_module); - mutex_unlock(&module_mutex); - if (!cxl_module) - return -ENODEV; + rc = get_cxl_module(); + if (rc) + return rc; phb->flags |= PNV_PHB_FLAG_CXL; hose->controller_ops = pnv_cxl_cx4_ioda_controller_ops; -- cgit v1.2.3 From 9054619ef54a3a832863ae25d15ac410ae3df146 Mon Sep 17 00:00:00 2001 From: John Allen Date: Thu, 7 Jul 2016 10:00:34 -0500 Subject: powerpc/pseries: Add pseries hotplug workqueue In support of PAPR changes to add a new hotplug interrupt, introduce a hotplug workqueue to avoid processing hotplug events in interrupt context. We will also take advantage of the queue on PowerVM to ensure hotplug events initiated from different sources (HMC and PRRN events) are handled and serialized properly. Signed-off-by: John Allen Reviewed-by: Nathan Fontenot Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/pseries/dlpar.c | 52 ++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index 2b93ae8d557a..66a77d7a7e4c 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -27,6 +27,15 @@ #include #include +struct workqueue_struct *pseries_hp_wq; + +struct pseries_hp_work { + struct work_struct work; + struct pseries_hp_errorlog *errlog; + struct completion *hp_completion; + int *rc; +}; + struct cc_workarea { __be32 drc_index; __be32 zero; @@ -368,10 +377,51 @@ static int handle_dlpar_errorlog(struct pseries_hp_errorlog *hp_elog) return rc; } +void pseries_hp_work_fn(struct work_struct *work) +{ + struct pseries_hp_work *hp_work = + container_of(work, struct pseries_hp_work, work); + + if (hp_work->rc) + *(hp_work->rc) = handle_dlpar_errorlog(hp_work->errlog); + else + handle_dlpar_errorlog(hp_work->errlog); + + if (hp_work->hp_completion) + complete(hp_work->hp_completion); + + kfree(hp_work->errlog); + kfree((void *)work); +} + +void queue_hotplug_event(struct pseries_hp_errorlog *hp_errlog, + struct completion *hotplug_done, int *rc) +{ + struct pseries_hp_work *work; + struct pseries_hp_errorlog *hp_errlog_copy; + + hp_errlog_copy = kmalloc(sizeof(struct pseries_hp_errorlog), + GFP_KERNEL); + memcpy(hp_errlog_copy, hp_errlog, sizeof(struct pseries_hp_errorlog)); + + work = kmalloc(sizeof(struct pseries_hp_work), GFP_KERNEL); + if (work) { + INIT_WORK((struct work_struct *)work, pseries_hp_work_fn); + work->errlog = hp_errlog_copy; + work->hp_completion = hotplug_done; + work->rc = rc; + queue_work(pseries_hp_wq, (struct work_struct *)work); + } else { + *rc = -ENOMEM; + complete(hotplug_done); + } +} + static ssize_t dlpar_store(struct class *class, struct class_attribute *attr, const char *buf, size_t count) { struct pseries_hp_errorlog *hp_elog; + struct completion hotplug_done; const char *arg; int rc; @@ -450,6 +500,8 @@ static CLASS_ATTR(dlpar, S_IWUSR, NULL, dlpar_store); static int __init pseries_dlpar_init(void) { + pseries_hp_wq = alloc_workqueue("pseries hotplug workqueue", + WQ_UNBOUND, 1); return sysfs_create_file(kernel_kobj, &class_attr_dlpar.attr); } machine_device_initcall(pseries, pseries_dlpar_init); -- cgit v1.2.3 From b7d9eb397b8764c1f1c53d504aa70f85ce0e212f Mon Sep 17 00:00:00 2001 From: John Allen Date: Thu, 7 Jul 2016 10:03:44 -0500 Subject: powerpc/pseries: Add support for hotplug interrupt source Add handler for new hotplug interrupt. For memory and CPU hotplug events, we will add the hotplug errorlog to the hotplug workqueue. Since PCI hotplug is not currently supported in the kernel, PCI hotplug events are written to the rtas_log_bug and are handled by rtas_errd. Signed-off-by: John Allen Reviewed-by: Nathan Fontenot Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/pseries/pseries.h | 2 ++ arch/powerpc/platforms/pseries/ras.c | 39 ++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h index ddb9aa51aad6..bba32853c468 100644 --- a/arch/powerpc/platforms/pseries/pseries.h +++ b/arch/powerpc/platforms/pseries/pseries.h @@ -56,6 +56,8 @@ extern int dlpar_detach_node(struct device_node *); extern int dlpar_acquire_drc(u32 drc_index); extern int dlpar_release_drc(u32 drc_index); +void queue_hotplug_event(struct pseries_hp_errorlog *hp_errlog, + struct completion *hotplug_done, int *rc); #ifdef CONFIG_MEMORY_HOTPLUG int dlpar_memory(struct pseries_hp_errorlog *hp_elog); #else diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c index 9a3e27b863ce..904a677208d1 100644 --- a/arch/powerpc/platforms/pseries/ras.c +++ b/arch/powerpc/platforms/pseries/ras.c @@ -43,6 +43,7 @@ static int ras_check_exception_token; /* EPOW events counter variable */ static int num_epow_events; +static irqreturn_t ras_hotplug_interrupt(int irq, void *dev_id); static irqreturn_t ras_epow_interrupt(int irq, void *dev_id); static irqreturn_t ras_error_interrupt(int irq, void *dev_id); @@ -65,6 +66,14 @@ static int __init init_ras_IRQ(void) of_node_put(np); } + /* Hotplug Events */ + np = of_find_node_by_path("/event-sources/hot-plug-events"); + if (np != NULL) { + request_event_sources_irqs(np, ras_hotplug_interrupt, + "RAS_HOTPLUG"); + of_node_put(np); + } + /* EPOW Events */ np = of_find_node_by_path("/event-sources/epow-events"); if (np != NULL) { @@ -190,6 +199,36 @@ static void rtas_parse_epow_errlog(struct rtas_error_log *log) num_epow_events++; } +static irqreturn_t ras_hotplug_interrupt(int irq, void *dev_id) +{ + struct pseries_errorlog *pseries_log; + struct pseries_hp_errorlog *hp_elog; + + spin_lock(&ras_log_buf_lock); + + rtas_call(ras_check_exception_token, 6, 1, NULL, + RTAS_VECTOR_EXTERNAL_INTERRUPT, virq_to_hw(irq), + RTAS_HOTPLUG_EVENTS, 0, __pa(&ras_log_buf), + rtas_get_error_log_max()); + + pseries_log = get_pseries_errorlog((struct rtas_error_log *)ras_log_buf, + PSERIES_ELOG_SECT_ID_HOTPLUG); + hp_elog = (struct pseries_hp_errorlog *)pseries_log->data; + + /* + * Since PCI hotplug is not currently supported on pseries, put PCI + * hotplug events on the ras_log_buf to be handled by rtas_errd. + */ + if (hp_elog->resource == PSERIES_HP_ELOG_RESOURCE_MEM || + hp_elog->resource == PSERIES_HP_ELOG_RESOURCE_CPU) + queue_hotplug_event(hp_elog, NULL, NULL); + else + log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, 0); + + spin_unlock(&ras_log_buf_lock); + return IRQ_HANDLED; +} + /* Handle environmental and power warning (EPOW) interrupts. */ static irqreturn_t ras_epow_interrupt(int irq, void *dev_id) { -- cgit v1.2.3 From 1dc75956663661e6bfee7836ddd2def2f66745b9 Mon Sep 17 00:00:00 2001 From: John Allen Date: Thu, 7 Jul 2016 10:05:52 -0500 Subject: powerpc/pseries: Use kernel hotplug queue for PowerVM hotplug events The sysfs interface used to handle PowerVM hotplug events should use the hotplug queue as well. PRRN events will soon be placing many hotplug events on the queue at once and we will need ordinary hotplug events to use the queue as well in order to ensure these events will still be handled and that proper serialization is maintained during the PRRN event. Signed-off-by: John Allen Reviewed-by: Nathan Fontenot Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/pseries/dlpar.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index 66a77d7a7e4c..4748124faa10 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -489,7 +489,9 @@ static ssize_t dlpar_store(struct class *class, struct class_attribute *attr, goto dlpar_store_out; } - rc = handle_dlpar_errorlog(hp_elog); + init_completion(&hotplug_done); + queue_hotplug_event(hp_elog, &hotplug_done, &rc); + wait_for_completion(&hotplug_done); dlpar_store_out: kfree(hp_elog); -- cgit v1.2.3 From c40785ad305b32e9b0b5fbc888f1f5d57f29bf44 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 5 Jul 2016 15:03:47 +1000 Subject: powerpc/dart: Use a cachable DART Instead of punching a hole in the linear mapping, just use normal cachable memory, and apply the flush sequence documented in the CPC625 (aka U3) user manual. This allows us to remove quite a bit of code related to the early allocation of the DART and the hole in the linear mapping. We can also get rid of the copy of the DART for suspend/resume as the original memory can just be saved/restored now, as long as we properly sync the caches. Signed-off-by: Benjamin Herrenschmidt [mpe: Integrate dart_init() fix to return ENODEV when DART disabled] Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/iommu.h | 1 - arch/powerpc/mm/hash_utils_64.c | 32 ------ arch/powerpc/platforms/maple/setup.c | 7 -- arch/powerpc/platforms/powermac/setup.c | 8 -- arch/powerpc/sysdev/dart_iommu.c | 184 +++++++++++++++----------------- 5 files changed, 88 insertions(+), 144 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h index 7b87bab09564..f49a72a9062d 100644 --- a/arch/powerpc/include/asm/iommu.h +++ b/arch/powerpc/include/asm/iommu.h @@ -273,7 +273,6 @@ extern void iommu_init_early_pSeries(void); extern void iommu_init_early_dart(struct pci_controller_ops *controller_ops); extern void iommu_init_early_pasemi(void); -extern void alloc_dart_table(void); #if defined(CONFIG_PPC64) && defined(CONFIG_PM) static inline void iommu_save(void) { diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 7d0955e04f08..859ecaa928e9 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -87,10 +87,6 @@ * */ -#ifdef CONFIG_U3_DART -extern unsigned long dart_tablebase; -#endif /* CONFIG_U3_DART */ - static unsigned long _SDR1; struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; EXPORT_SYMBOL_GPL(mmu_psize_defs); @@ -846,34 +842,6 @@ static void __init htab_initialize(void) DBG("creating mapping for region: %lx..%lx (prot: %lx)\n", base, size, prot); -#ifdef CONFIG_U3_DART - /* Do not map the DART space. Fortunately, it will be aligned - * in such a way that it will not cross two memblock regions and - * will fit within a single 16Mb page. - * The DART space is assumed to be a full 16Mb region even if - * we only use 2Mb of that space. We will use more of it later - * for AGP GART. We have to use a full 16Mb large page. - */ - DBG("DART base: %lx\n", dart_tablebase); - - if (dart_tablebase != 0 && dart_tablebase >= base - && dart_tablebase < (base + size)) { - unsigned long dart_table_end = dart_tablebase + 16 * MB; - if (base != dart_tablebase) - BUG_ON(htab_bolt_mapping(base, dart_tablebase, - __pa(base), prot, - mmu_linear_psize, - mmu_kernel_ssize)); - if ((base + size) > dart_table_end) - BUG_ON(htab_bolt_mapping(dart_tablebase+16*MB, - base + size, - __pa(dart_table_end), - prot, - mmu_linear_psize, - mmu_kernel_ssize)); - continue; - } -#endif /* CONFIG_U3_DART */ BUG_ON(htab_bolt_mapping(base, base + size, __pa(base), prot, mmu_linear_psize, mmu_kernel_ssize)); } diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index 5f8f6f966608..99b9b96ab059 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c @@ -305,13 +305,6 @@ static int __init maple_probe(void) if (!of_flat_dt_is_compatible(root, "Momentum,Maple") && !of_flat_dt_is_compatible(root, "Momentum,Apache")) return 0; - /* - * On U3, the DART (iommu) must be allocated now since it - * has an impact on htab_initialize (due to the large page it - * occupies having to be broken up so the DART itself is not - * part of the cacheable linar mapping - */ - alloc_dart_table(); hpte_init_native(); pm_power_off = maple_power_off; diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index bd83b52c9830..fc0b69f6e3d4 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -607,14 +607,6 @@ static int __init pmac_probe(void) return 0; #ifdef CONFIG_PPC64 - /* - * On U3, the DART (iommu) must be allocated now since it - * has an impact on htab_initialize (due to the large page it - * occupies having to be broken up so the DART itself is not - * part of the cacheable linar mapping - */ - alloc_dart_table(); - hpte_init_native(); #endif diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index b7348637eae0..26904f4879ec 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c @@ -48,16 +48,10 @@ #include "dart.h" -/* Physical base address and size of the DART table */ -unsigned long dart_tablebase; /* exported to htab_initialize */ +/* DART table address and size */ +static u32 *dart_tablebase; static unsigned long dart_tablesize; -/* Virtual base address of the DART table */ -static u32 *dart_vbase; -#ifdef CONFIG_PM -static u32 *dart_copy; -#endif - /* Mapped base address for the dart */ static unsigned int __iomem *dart; @@ -151,6 +145,34 @@ wait_more: spin_unlock_irqrestore(&invalidate_lock, flags); } +static void dart_cache_sync(unsigned int *base, unsigned int count) +{ + /* + * We add 1 to the number of entries to flush, following a + * comment in Darwin indicating that the memory controller + * can prefetch unmapped memory under some circumstances. + */ + unsigned long start = (unsigned long)base; + unsigned long end = start + (count + 1) * sizeof(unsigned int); + unsigned int tmp; + + /* Perform a standard cache flush */ + flush_inval_dcache_range(start, end); + + /* + * Perform the sequence described in the CPC925 manual to + * ensure all the data gets to a point the cache incoherent + * DART hardware will see. + */ + asm volatile(" sync;" + " isync;" + " dcbf 0,%1;" + " sync;" + " isync;" + " lwz %0,0(%1);" + " isync" : "=r" (tmp) : "r" (end) : "memory"); +} + static void dart_flush(struct iommu_table *tbl) { mb(); @@ -165,13 +187,13 @@ static int dart_build(struct iommu_table *tbl, long index, enum dma_data_direction direction, struct dma_attrs *attrs) { - unsigned int *dp; + unsigned int *dp, *orig_dp; unsigned int rpn; long l; DBG("dart: build at: %lx, %lx, addr: %x\n", index, npages, uaddr); - dp = ((unsigned int*)tbl->it_base) + index; + orig_dp = dp = ((unsigned int*)tbl->it_base) + index; /* On U3, all memory is contiguous, so we can move this * out of the loop. @@ -184,11 +206,7 @@ static int dart_build(struct iommu_table *tbl, long index, uaddr += DART_PAGE_SIZE; } - - /* make sure all updates have reached memory */ - mb(); - in_be32((unsigned __iomem *)dp); - mb(); + dart_cache_sync(orig_dp, npages); if (dart_is_u4) { rpn = index; @@ -203,7 +221,8 @@ static int dart_build(struct iommu_table *tbl, long index, static void dart_free(struct iommu_table *tbl, long index, long npages) { - unsigned int *dp; + unsigned int *dp, *orig_dp; + long orig_npages = npages; /* We don't worry about flushing the TLB cache. The only drawback of * not doing it is that we won't catch buggy device drivers doing @@ -212,34 +231,30 @@ static void dart_free(struct iommu_table *tbl, long index, long npages) DBG("dart: free at: %lx, %lx\n", index, npages); - dp = ((unsigned int *)tbl->it_base) + index; + orig_dp = dp = ((unsigned int *)tbl->it_base) + index; while (npages--) *(dp++) = dart_emptyval; -} + dart_cache_sync(orig_dp, orig_npages); +} -static int __init dart_init(struct device_node *dart_node) +static void allocate_dart(void) { - unsigned int i; - unsigned long tmp, base, size; - struct resource r; - - if (dart_tablebase == 0 || dart_tablesize == 0) { - printk(KERN_INFO "DART: table not allocated, using " - "direct DMA\n"); - return -ENODEV; - } + unsigned long tmp; - if (of_address_to_resource(dart_node, 0, &r)) - panic("DART: can't get register base ! "); + /* 512 pages (2MB) is max DART tablesize. */ + dart_tablesize = 1UL << 21; - /* Make sure nothing from the DART range remains in the CPU cache - * from a previous mapping that existed before the kernel took - * over + /* + * 16MB (1 << 24) alignment. We allocate a full 16Mb chuck since we + * will blow up an entire large page anyway in the kernel mapping. */ - flush_dcache_phys_range(dart_tablebase, - dart_tablebase + dart_tablesize); + dart_tablebase = __va(memblock_alloc_base(1UL<<24, + 1UL<<24, 0x80000000L)); + + /* There is no point scanning the DART space for leaks*/ + kmemleak_no_scan((void *)dart_tablebase); /* Allocate a spare page to map all invalid DART pages. We need to do * that to work around what looks like a problem with the HT bridge @@ -249,20 +264,51 @@ static int __init dart_init(struct device_node *dart_node) dart_emptyval = DARTMAP_VALID | ((tmp >> DART_PAGE_SHIFT) & DARTMAP_RPNMASK); + printk(KERN_INFO "DART table allocated at: %p\n", dart_tablebase); +} + +static int __init dart_init(struct device_node *dart_node) +{ + unsigned int i; + unsigned long base, size; + struct resource r; + + /* IOMMU disabled by the user ? bail out */ + if (iommu_is_off) + return -ENODEV; + + /* + * Only use the DART if the machine has more than 1GB of RAM + * or if requested with iommu=on on cmdline. + * + * 1GB of RAM is picked as limit because some default devices + * (i.e. Airport Extreme) have 30 bit address range limits. + */ + + if (!iommu_force_on && memblock_end_of_DRAM() <= 0x40000000ull) + return -ENODEV; + + /* Get DART registers */ + if (of_address_to_resource(dart_node, 0, &r)) + panic("DART: can't get register base ! "); + /* Map in DART registers */ dart = ioremap(r.start, resource_size(&r)); if (dart == NULL) panic("DART: Cannot map registers!"); - /* Map in DART table */ - dart_vbase = ioremap(__pa(dart_tablebase), dart_tablesize); + /* Allocate the DART and dummy page */ + allocate_dart(); /* Fill initial table */ for (i = 0; i < dart_tablesize/4; i++) - dart_vbase[i] = dart_emptyval; + dart_tablebase[i] = dart_emptyval; + + /* Push to memory */ + dart_cache_sync(dart_tablebase, dart_tablesize / sizeof(u32)); /* Initialize DART with table base and enable it. */ - base = dart_tablebase >> DART_PAGE_SHIFT; + base = ((unsigned long)dart_tablebase) >> DART_PAGE_SHIFT; size = dart_tablesize >> DART_PAGE_SHIFT; if (dart_is_u4) { size &= DART_SIZE_U4_SIZE_MASK; @@ -301,7 +347,7 @@ static void iommu_table_dart_setup(void) iommu_table_dart.it_page_shift = IOMMU_PAGE_SHIFT_4K; /* Initialize the common IOMMU code */ - iommu_table_dart.it_base = (unsigned long)dart_vbase; + iommu_table_dart.it_base = (unsigned long)dart_tablebase; iommu_table_dart.it_index = 0; iommu_table_dart.it_blocksize = 1; iommu_table_dart.it_ops = &iommu_dart_ops; @@ -404,75 +450,21 @@ void __init iommu_init_early_dart(struct pci_controller_ops *controller_ops) } #ifdef CONFIG_PM -static void iommu_dart_save(void) -{ - memcpy(dart_copy, dart_vbase, 2*1024*1024); -} - static void iommu_dart_restore(void) { - memcpy(dart_vbase, dart_copy, 2*1024*1024); + dart_cache_sync(dart_tablebase, dart_tablesize / sizeof(u32)); dart_tlb_invalidate_all(); } static int __init iommu_init_late_dart(void) { - unsigned long tbasepfn; - struct page *p; - - /* if no dart table exists then we won't need to save it - * and the area has also not been reserved */ if (!dart_tablebase) return 0; - tbasepfn = __pa(dart_tablebase) >> PAGE_SHIFT; - register_nosave_region_late(tbasepfn, - tbasepfn + ((1<<24) >> PAGE_SHIFT)); - - /* For suspend we need to copy the dart contents because - * it is not part of the regular mapping (see above) and - * thus not saved automatically. The memory for this copy - * must be allocated early because we need 2 MB. */ - p = alloc_pages(GFP_KERNEL, 21 - PAGE_SHIFT); - BUG_ON(!p); - dart_copy = page_address(p); - - ppc_md.iommu_save = iommu_dart_save; ppc_md.iommu_restore = iommu_dart_restore; return 0; } late_initcall(iommu_init_late_dart); -#endif - -void __init alloc_dart_table(void) -{ - /* Only reserve DART space if machine has more than 1GB of RAM - * or if requested with iommu=on on cmdline. - * - * 1GB of RAM is picked as limit because some default devices - * (i.e. Airport Extreme) have 30 bit address range limits. - */ - - if (iommu_is_off) - return; - - if (!iommu_force_on && memblock_end_of_DRAM() <= 0x40000000ull) - return; - - /* 512 pages (2MB) is max DART tablesize. */ - dart_tablesize = 1UL << 21; - /* 16MB (1 << 24) alignment. We allocate a full 16Mb chuck since we - * will blow up an entire large page anyway in the kernel mapping - */ - dart_tablebase = (unsigned long) - __va(memblock_alloc_base(1UL<<24, 1UL<<24, 0x80000000L)); - /* - * The DART space is later unmapped from the kernel linear mapping and - * accessing dart_tablebase during kmemleak scanning will fault. - */ - kmemleak_no_scan((void *)dart_tablebase); - - printk(KERN_INFO "DART table allocated at: %lx\n", dart_tablebase); -} +#endif /* CONFIG_PM */ -- cgit v1.2.3 From 3808a88985b4f5f5e947c364debce4441a380fb8 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 5 Jul 2016 15:03:48 +1000 Subject: powerpc: Move FW feature probing out of pseries probe() We move the function itself to pseries/firmware.c and call it along with almost all other flat device-tree parsers from early_init_devtree() Signed-off-by: Benjamin Herrenschmidt [mpe: Move #ifdefs into the header by providing pseries_probe_fw_features()] Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/firmware.h | 6 ++++ arch/powerpc/kernel/prom.c | 4 +++ arch/powerpc/platforms/pseries/firmware.c | 48 +++++++++++++++++++++++++++++-- arch/powerpc/platforms/pseries/pseries.h | 5 ---- arch/powerpc/platforms/pseries/setup.c | 41 -------------------------- 5 files changed, 56 insertions(+), 48 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/include/asm/firmware.h b/arch/powerpc/include/asm/firmware.h index b0629249778b..1e0b5a5d660a 100644 --- a/arch/powerpc/include/asm/firmware.h +++ b/arch/powerpc/include/asm/firmware.h @@ -126,6 +126,12 @@ extern int fwnmi_active; extern unsigned int __start___fw_ftr_fixup, __stop___fw_ftr_fixup; +#ifdef CONFIG_PPC_PSERIES +void pseries_probe_fw_features(void); +#else +static inline void pseries_probe_fw_features(void) { }; +#endif + #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ #endif /* __ASM_POWERPC_FIRMWARE_H */ diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 7a01113d525c..2bd1784e65b3 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -57,6 +57,7 @@ #include #include #include +#include #include @@ -755,6 +756,9 @@ void __init early_init_devtree(void *params) #endif epapr_paravirt_early_init(); + /* Now try to figure out if we are running on LPAR and so on */ + pseries_probe_fw_features(); + DBG(" <- early_init_devtree()\n"); } diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c index 8c80588abacc..ea7f09bd73b1 100644 --- a/arch/powerpc/platforms/pseries/firmware.c +++ b/arch/powerpc/platforms/pseries/firmware.c @@ -22,6 +22,7 @@ */ +#include #include #include #include @@ -69,7 +70,8 @@ hypertas_fw_features_table[] = { * device-tree/ibm,hypertas-functions. Ultimately this functionality may * be moved into prom.c prom_init(). */ -void __init fw_hypertas_feature_init(const char *hypertas, unsigned long len) +static void __init fw_hypertas_feature_init(const char *hypertas, + unsigned long len) { const char *s; int i; @@ -113,7 +115,7 @@ vec5_fw_features_table[] = { {FW_FEATURE_PRRN, OV5_PRRN}, }; -void __init fw_vec5_feature_init(const char *vec5, unsigned long len) +static void __init fw_vec5_feature_init(const char *vec5, unsigned long len) { unsigned int index, feat; int i; @@ -131,3 +133,45 @@ void __init fw_vec5_feature_init(const char *vec5, unsigned long len) pr_debug(" <- fw_vec5_feature_init()\n"); } + +/* + * Called very early, MMU is off, device-tree isn't unflattened + */ +static int __init probe_fw_features(unsigned long node, const char *uname, int + depth, void *data) +{ + const char *prop; + int len; + static int hypertas_found; + static int vec5_found; + + if (depth != 1) + return 0; + + if (!strcmp(uname, "rtas") || !strcmp(uname, "rtas@0")) { + prop = of_get_flat_dt_prop(node, "ibm,hypertas-functions", + &len); + if (prop) { + powerpc_firmware_features |= FW_FEATURE_LPAR; + fw_hypertas_feature_init(prop, len); + } + + hypertas_found = 1; + } + + if (!strcmp(uname, "chosen")) { + prop = of_get_flat_dt_prop(node, "ibm,architecture-vec-5", + &len); + if (prop) + fw_vec5_feature_init(prop, len); + + vec5_found = 1; + } + + return hypertas_found && vec5_found; +} + +void __init pseries_probe_fw_features(void) +{ + of_scan_flat_dt(probe_fw_features, NULL); +} diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h index bba32853c468..b1be7b713fe6 100644 --- a/arch/powerpc/platforms/pseries/pseries.h +++ b/arch/powerpc/platforms/pseries/pseries.h @@ -20,11 +20,6 @@ extern void request_event_sources_irqs(struct device_node *np, #include -extern void __init fw_hypertas_feature_init(const char *hypertas, - unsigned long len); -extern void __init fw_vec5_feature_init(const char *hypertas, - unsigned long len); - struct pt_regs; extern int pSeries_system_reset_exception(struct pt_regs *regs); diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index e61e9b986e21..9cc9b88fce79 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -659,45 +659,6 @@ static void pseries_power_off(void) for (;;); } -/* - * Called very early, MMU is off, device-tree isn't unflattened - */ - -static int __init pseries_probe_fw_features(unsigned long node, - const char *uname, int depth, - void *data) -{ - const char *prop; - int len; - static int hypertas_found; - static int vec5_found; - - if (depth != 1) - return 0; - - if (!strcmp(uname, "rtas") || !strcmp(uname, "rtas@0")) { - prop = of_get_flat_dt_prop(node, "ibm,hypertas-functions", - &len); - if (prop) { - powerpc_firmware_features |= FW_FEATURE_LPAR; - fw_hypertas_feature_init(prop, len); - } - - hypertas_found = 1; - } - - if (!strcmp(uname, "chosen")) { - prop = of_get_flat_dt_prop(node, "ibm,architecture-vec-5", - &len); - if (prop) - fw_vec5_feature_init(prop, len); - - vec5_found = 1; - } - - return hypertas_found && vec5_found; -} - static int __init pSeries_probe(void) { unsigned long root = of_get_flat_dt_root(); @@ -717,8 +678,6 @@ static int __init pSeries_probe(void) pr_debug("pSeries detected, looking for LPAR capability...\n"); - /* Now try to figure out if we are running on LPAR */ - of_scan_flat_dt(pseries_probe_fw_features, NULL); #ifdef __LITTLE_ENDIAN__ if (firmware_has_feature(FW_FEATURE_SET_MODE)) { -- cgit v1.2.3 From d3cbff1b5a90afe6cb201aa2187c9609e21f92ad Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 5 Jul 2016 15:03:49 +1000 Subject: powerpc: Put exception configuration in a common place The various calls to establish exception endianness and AIL are now done from a single point using already established CPU and FW feature bits to decide what to do. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/hvcall.h | 11 ---- arch/powerpc/include/asm/opal.h | 1 + arch/powerpc/include/asm/setup.h | 12 +++++ arch/powerpc/kernel/setup_64.c | 56 +++++++++++++++------ arch/powerpc/kvm/book3s_pr.c | 6 +-- arch/powerpc/platforms/powernv/opal.c | 13 ++--- arch/powerpc/platforms/pseries/lpar.c | 20 +------- arch/powerpc/platforms/pseries/setup.c | 92 ++++++++++++++++------------------ 8 files changed, 108 insertions(+), 103 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h index 0bc9c284aa10..708edebcf147 100644 --- a/arch/powerpc/include/asm/hvcall.h +++ b/arch/powerpc/include/asm/hvcall.h @@ -431,17 +431,6 @@ static inline unsigned long cmo_get_page_size(void) { return CMO_PageSize; } - -extern long pSeries_enable_reloc_on_exc(void); -extern long pSeries_disable_reloc_on_exc(void); - -extern long pseries_big_endian_exceptions(void); - -#else - -#define pSeries_enable_reloc_on_exc() do {} while (0) -#define pSeries_disable_reloc_on_exc() do {} while (0) - #endif /* CONFIG_PPC_PSERIES */ #endif /* __ASSEMBLY__ */ diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index b656bb192b63..ee05bd203630 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h @@ -234,6 +234,7 @@ extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data); extern int early_init_dt_scan_recoverable_ranges(unsigned long node, const char *uname, int depth, void *data); +extern void opal_configure_cores(void); extern int opal_get_chars(uint32_t vtermno, char *buf, int count); extern int opal_put_chars(uint32_t vtermno, const char *buf, int total_len); diff --git a/arch/powerpc/include/asm/setup.h b/arch/powerpc/include/asm/setup.h index e9d384cbd021..654d64c9f3ac 100644 --- a/arch/powerpc/include/asm/setup.h +++ b/arch/powerpc/include/asm/setup.h @@ -26,6 +26,18 @@ void initmem_init(void); void setup_panic(void); #define ARCH_PANIC_TIMEOUT 180 +#ifdef CONFIG_PPC_PSERIES +extern void pseries_enable_reloc_on_exc(void); +extern void pseries_disable_reloc_on_exc(void); +extern void pseries_big_endian_exceptions(void); +extern void pseries_little_endian_exceptions(void); +#else +static inline void pseries_enable_reloc_on_exc(void) {} +static inline void pseries_disable_reloc_on_exc(void) {} +static inline void pseries_big_endian_exceptions(void) {} +static inline void pseries_little_endian_exceptions(void) {} +#endif /* CONFIG_PPC_PSERIES */ + #endif /* !__ASSEMBLY__ */ #endif /* _ASM_POWERPC_SETUP_H */ diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 155dbcce8ef8..4ffd090633de 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -69,6 +69,7 @@ #include #include #include +#include #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) @@ -205,23 +206,50 @@ static void fixup_boot_paca(void) get_paca()->data_offset = 0; } -static void cpu_ready_for_interrupts(void) +static void configure_exceptions(void) { - /* Set IR and DR in PACA MSR */ - get_paca()->kernel_msr = MSR_KERNEL; - /* - * Enable AIL if supported, and we are in hypervisor mode. If we are - * not in hypervisor mode, we enable relocation-on interrupts later - * in pSeries_setup_arch() using the H_SET_MODE hcall. + * Setup the trampolines from the lowmem exception vectors + * to the kdump kernel when not using a relocatable kernel. */ - if (cpu_has_feature(CPU_FTR_HVMODE) && - cpu_has_feature(CPU_FTR_ARCH_207S)) { - unsigned long lpcr = mfspr(SPRN_LPCR); - mtspr(SPRN_LPCR, lpcr | LPCR_AIL_3); + setup_kdump_trampoline(); + + /* Under a PAPR hypervisor, we need hypercalls */ + if (firmware_has_feature(FW_FEATURE_SET_MODE)) { + /* Enable AIL if possible */ + pseries_enable_reloc_on_exc(); + + /* + * Tell the hypervisor that we want our exceptions to + * be taken in little endian mode. + * + * We don't call this for big endian as our calling convention + * makes us always enter in BE, and the call may fail under + * some circumstances with kdump. + */ +#ifdef __LITTLE_ENDIAN__ + pseries_little_endian_exceptions(); +#endif + } else { + /* Set endian mode using OPAL */ + if (firmware_has_feature(FW_FEATURE_OPAL)) + opal_configure_cores(); + + /* Enable AIL if supported, and we are in hypervisor mode */ + if (cpu_has_feature(CPU_FTR_HVMODE) && + cpu_has_feature(CPU_FTR_ARCH_207S)) { + unsigned long lpcr = mfspr(SPRN_LPCR); + mtspr(SPRN_LPCR, lpcr | LPCR_AIL_3); + } } } +static void cpu_ready_for_interrupts(void) +{ + /* Set IR and DR in PACA MSR */ + get_paca()->kernel_msr = MSR_KERNEL; +} + /* * Early initialization entry point. This is called by head.S * with MMU translation disabled. We rely on the "feature" of @@ -277,10 +305,10 @@ void __init early_setup(unsigned long dt_ptr) probe_machine(); /* - * Setup the trampolines from the lowmem exception vectors - * to the kdump kernel when not using a relocatable kernel. + * Configure exception handlers. This include setting up trampolines + * if needed, setting exception endian mode, etc... */ - setup_kdump_trampoline(); + configure_exceptions(); /* Initialize the hash table or TLB handling */ early_init_mmu(); diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index 8e4f64f0b774..c4f7d6b86b9e 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include #include @@ -1690,7 +1690,7 @@ static int kvmppc_core_init_vm_pr(struct kvm *kvm) if (firmware_has_feature(FW_FEATURE_SET_MODE)) { spin_lock(&kvm_global_user_count_lock); if (++kvm_global_user_count == 1) - pSeries_disable_reloc_on_exc(); + pseries_disable_reloc_on_exc(); spin_unlock(&kvm_global_user_count_lock); } return 0; @@ -1706,7 +1706,7 @@ static void kvmppc_core_destroy_vm_pr(struct kvm *kvm) spin_lock(&kvm_global_user_count_lock); BUG_ON(kvm_global_user_count == 0); if (--kvm_global_user_count == 0) - pSeries_enable_reloc_on_exc(); + pseries_enable_reloc_on_exc(); spin_unlock(&kvm_global_user_count_lock); } } diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index da40d6bdb0e6..8b4fc68cebcb 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c @@ -57,7 +57,7 @@ static struct atomic_notifier_head opal_msg_notifier_head[OPAL_MSG_TYPE_MAX]; static uint32_t opal_heartbeat; static struct task_struct *kopald_tsk; -static void opal_reinit_cores(void) +void opal_configure_cores(void) { /* Do the actual re-init, This will clobber all FPRs, VRs, etc... * @@ -70,6 +70,10 @@ static void opal_reinit_cores(void) #else opal_reinit_cpus(OPAL_REINIT_CPUS_HILE_LE); #endif + + /* Restore some bits */ + if (cur_cpu_spec->cpu_restore) + cur_cpu_spec->cpu_restore(); } int __init early_init_dt_scan_opal(unsigned long node, @@ -106,13 +110,6 @@ int __init early_init_dt_scan_opal(unsigned long node, panic("OPAL != V3 detected, no longer supported.\n"); } - /* Reinit all cores with the right endian */ - opal_reinit_cores(); - - /* Restore some bits */ - if (cur_cpu_spec->cpu_restore) - cur_cpu_spec->cpu_restore(); - return 1; } diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 03ff9867a610..03c732afef34 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -261,24 +261,8 @@ static void pSeries_lpar_hptab_clear(void) * This is also called on boot when a fadump happens. In that case we * must not change the exception endian mode. */ - if (firmware_has_feature(FW_FEATURE_SET_MODE) && !is_fadump_active()) { - long rc; - - rc = pseries_big_endian_exceptions(); - /* - * At this point it is unlikely panic() will get anything - * out to the user, but at least this will stop us from - * continuing on further and creating an even more - * difficult to debug situation. - * - * There is a known problem when kdump'ing, if cpus are offline - * the above call will fail. Rather than panicking again, keep - * going and hope the kdump kernel is also little endian, which - * it usually is. - */ - if (rc && !kdump_in_progress()) - panic("Could not enable big endian exceptions"); - } + if (firmware_has_feature(FW_FEATURE_SET_MODE) && !is_fadump_active()) + pseries_big_endian_exceptions(); #endif } diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 9cc9b88fce79..ba7dc126b5e5 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -319,15 +319,23 @@ static void pseries_lpar_idle(void) * to ever be a problem in practice we can move this into a kernel thread to * finish off the process later in boot. */ -long pSeries_enable_reloc_on_exc(void) +void pseries_enable_reloc_on_exc(void) { long rc; unsigned int delay, total_delay = 0; while (1) { rc = enable_reloc_on_exceptions(); - if (!H_IS_LONG_BUSY(rc)) - return rc; + if (!H_IS_LONG_BUSY(rc)) { + if (rc == H_P2) { + pr_info("Relocation on exceptions not" + " supported\n"); + } else if (rc != H_SUCCESS) { + pr_warn("Unable to enable relocation" + " on exceptions: %ld\n", rc); + } + break; + } delay = get_longbusy_msecs(rc); total_delay += delay; @@ -335,66 +343,81 @@ long pSeries_enable_reloc_on_exc(void) pr_warn("Warning: Giving up waiting to enable " "relocation on exceptions (%u msec)!\n", total_delay); - return rc; + return; } mdelay(delay); } } -EXPORT_SYMBOL(pSeries_enable_reloc_on_exc); +EXPORT_SYMBOL(pseries_enable_reloc_on_exc); -long pSeries_disable_reloc_on_exc(void) +void pseries_disable_reloc_on_exc(void) { long rc; while (1) { rc = disable_reloc_on_exceptions(); if (!H_IS_LONG_BUSY(rc)) - return rc; + break; mdelay(get_longbusy_msecs(rc)); } + if (rc != H_SUCCESS) + pr_warning("Warning: Failed to disable relocation on " + "exceptions: %ld\n", rc); } -EXPORT_SYMBOL(pSeries_disable_reloc_on_exc); +EXPORT_SYMBOL(pseries_disable_reloc_on_exc); #ifdef CONFIG_KEXEC static void pSeries_machine_kexec(struct kimage *image) { - long rc; - - if (firmware_has_feature(FW_FEATURE_SET_MODE)) { - rc = pSeries_disable_reloc_on_exc(); - if (rc != H_SUCCESS) - pr_warning("Warning: Failed to disable relocation on " - "exceptions: %ld\n", rc); - } + if (firmware_has_feature(FW_FEATURE_SET_MODE)) + pseries_disable_reloc_on_exc(); default_machine_kexec(image); } #endif #ifdef __LITTLE_ENDIAN__ -long pseries_big_endian_exceptions(void) +void pseries_big_endian_exceptions(void) { long rc; while (1) { rc = enable_big_endian_exceptions(); if (!H_IS_LONG_BUSY(rc)) - return rc; + break; mdelay(get_longbusy_msecs(rc)); } + + /* + * At this point it is unlikely panic() will get anything + * out to the user, since this is called very late in kexec + * but at least this will stop us from continuing on further + * and creating an even more difficult to debug situation. + * + * There is a known problem when kdump'ing, if cpus are offline + * the above call will fail. Rather than panicking again, keep + * going and hope the kdump kernel is also little endian, which + * it usually is. + */ + if (rc && !kdump_in_progress()) + panic("Could not enable big endian exceptions"); } -static long pseries_little_endian_exceptions(void) +void pseries_little_endian_exceptions(void) { long rc; while (1) { rc = enable_little_endian_exceptions(); if (!H_IS_LONG_BUSY(rc)) - return rc; + break; mdelay(get_longbusy_msecs(rc)); } + if (rc) { + ppc_md.progress("H_SET_MODE LE exception fail", 0); + panic("Could not enable little endian exceptions"); + } } #endif @@ -464,18 +487,6 @@ static void __init pSeries_setup_arch(void) } ppc_md.pcibios_root_bridge_prepare = pseries_root_bridge_prepare; - - if (firmware_has_feature(FW_FEATURE_SET_MODE)) { - long rc; - - rc = pSeries_enable_reloc_on_exc(); - if (rc == H_P2) { - pr_info("Relocation on exceptions not supported\n"); - } else if (rc != H_SUCCESS) { - pr_warn("Unable to enable relocation on exceptions: " - "%ld\n", rc); - } - } } static int __init pSeries_init_panel(void) @@ -678,23 +689,6 @@ static int __init pSeries_probe(void) pr_debug("pSeries detected, looking for LPAR capability...\n"); - -#ifdef __LITTLE_ENDIAN__ - if (firmware_has_feature(FW_FEATURE_SET_MODE)) { - long rc; - /* - * Tell the hypervisor that we want our exceptions to - * be taken in little endian mode. If this fails we don't - * want to use BUG() because it will trigger an exception. - */ - rc = pseries_little_endian_exceptions(); - if (rc) { - ppc_md.progress("H_SET_MODE LE exception fail", 0); - panic("Could not enable little endian exceptions"); - } - } -#endif - if (firmware_has_feature(FW_FEATURE_LPAR)) hpte_init_lpar(); else -- cgit v1.2.3 From 91b6fad5cf16c5fcf0ab2a08fcdbd1483d871d43 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 5 Jul 2016 15:03:50 +1000 Subject: powerpc/pmac: Remove early allocation of the SMU command buffer The SMU command buffer needs to be allocated below 2G using memblock. In the past, this had to be done very early from the arch code as memblock wasn't available past that point. That is no longer the case though, smu_init() is called from setup_arch() when memblock is still functional these days. So move the allocation to the SMU driver itself. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/smu.h | 7 ------- arch/powerpc/platforms/powermac/setup.c | 16 ---------------- drivers/macintosh/smu.c | 9 ++++++++- 3 files changed, 8 insertions(+), 24 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/include/asm/smu.h b/arch/powerpc/include/asm/smu.h index 9dc2de5da35a..09f98e861869 100644 --- a/arch/powerpc/include/asm/smu.h +++ b/arch/powerpc/include/asm/smu.h @@ -470,13 +470,6 @@ struct rtc_time; extern int smu_get_rtc_time(struct rtc_time *time, int spinwait); extern int smu_set_rtc_time(struct rtc_time *time, int spinwait); -/* - * SMU command buffer absolute address, exported by pmac_setup, - * this is allocated very early during boot. - */ -extern unsigned long smu_cmdbuf_abs; - - /* * Kernel asynchronous i2c interface */ diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index fc0b69f6e3d4..4ad61687c670 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -52,7 +52,6 @@ #include #include #include -#include #include #include @@ -97,11 +96,6 @@ int sccdbg; sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN; EXPORT_SYMBOL(sys_ctrler); -#ifdef CONFIG_PMAC_SMU -unsigned long smu_cmdbuf_abs; -EXPORT_SYMBOL(smu_cmdbuf_abs); -#endif - static void pmac_show_cpuinfo(struct seq_file *m) { struct device_node *np; @@ -325,7 +319,6 @@ static void __init pmac_setup_arch(void) defined(CONFIG_PPC64) pmac_nvram_init(); #endif - #ifdef CONFIG_PPC32 #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start) @@ -617,15 +610,6 @@ static int __init pmac_probe(void) DMA_MODE_WRITE = 2; #endif /* CONFIG_PPC32 */ -#ifdef CONFIG_PMAC_SMU - /* - * SMU based G5s need some memory below 2Gb, at least the current - * driver needs that. We have to allocate it now. We allocate 4k - * (1 small page) for now. - */ - smu_cmdbuf_abs = memblock_alloc_base(4096, 4096, 0x80000000UL); -#endif /* CONFIG_PMAC_SMU */ - pm_power_off = pmac_power_off; return 1; diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index d531f804455d..d6f72c826c1c 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -99,6 +100,7 @@ static DEFINE_MUTEX(smu_mutex); static struct smu_device *smu; static DEFINE_MUTEX(smu_part_access); static int smu_irq_inited; +static unsigned long smu_cmdbuf_abs; static void smu_i2c_retry(unsigned long data); @@ -479,8 +481,13 @@ int __init smu_init (void) printk(KERN_INFO "SMU: Driver %s %s\n", VERSION, AUTHOR); + /* + * SMU based G5s need some memory below 2Gb. Thankfully this is + * called at a time where memblock is still available. + */ + smu_cmdbuf_abs = memblock_alloc_base(4096, 4096, 0x80000000UL); if (smu_cmdbuf_abs == 0) { - printk(KERN_ERR "SMU: Command buffer not allocated !\n"); + printk(KERN_ERR "SMU: Command buffer allocation failed !\n"); ret = -EINVAL; goto fail_np; } -- cgit v1.2.3 From 166dd7d3fbf2df183926f0e4b4855f6cbd8da945 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 5 Jul 2016 15:03:51 +1000 Subject: powerpc/64: Move MMU backend selection out of platform code We move it into early_mmu_init() based on firmware features. For PS3, we have to move the setting of these into early_init_devtree(). Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/ps3.h | 2 ++ arch/powerpc/kernel/prom.c | 6 ++++++ arch/powerpc/mm/hash_utils_64.c | 14 ++++++++++++++ arch/powerpc/mm/pgtable-radix.c | 1 + arch/powerpc/platforms/cell/setup.c | 1 - arch/powerpc/platforms/maple/setup.c | 1 - arch/powerpc/platforms/pasemi/setup.c | 2 -- arch/powerpc/platforms/powermac/setup.c | 4 ---- arch/powerpc/platforms/powernv/setup.c | 5 ----- arch/powerpc/platforms/ps3/setup.c | 15 +++++++++------ arch/powerpc/platforms/pseries/setup.c | 7 ------- 11 files changed, 32 insertions(+), 26 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/include/asm/ps3.h b/arch/powerpc/include/asm/ps3.h index a1bc7e758422..a19f831a4cc9 100644 --- a/arch/powerpc/include/asm/ps3.h +++ b/arch/powerpc/include/asm/ps3.h @@ -526,4 +526,6 @@ void ps3_sync_irq(int node); u32 ps3_get_hw_thread_id(int cpu); u64 ps3_get_spe_id(void *arg); +void ps3_early_mm_init(void); + #endif diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 2bd1784e65b3..bae3db791150 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -759,6 +759,12 @@ void __init early_init_devtree(void *params) /* Now try to figure out if we are running on LPAR and so on */ pseries_probe_fw_features(); +#ifdef CONFIG_PPC_PS3 + /* Identify PS3 firmware */ + if (of_flat_dt_is_compatible(of_get_flat_dt_root(), "sony,ps3")) + powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE; +#endif + DBG(" <- early_init_devtree()\n"); } diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 859ecaa928e9..336fad6524df 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -58,6 +58,7 @@ #include #include #include +#include #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) @@ -872,6 +873,11 @@ static void __init htab_initialize(void) #undef KB #undef MB +void __init __weak hpte_init_lpar(void) +{ + panic("FW_FEATURE_LPAR set but no LPAR support compiled\n"); +} + void __init hash__early_init_mmu(void) { /* @@ -908,6 +914,14 @@ void __init hash__early_init_mmu(void) pci_io_base = ISA_IO_BASE; #endif + /* Select appropriate backend */ + if (firmware_has_feature(FW_FEATURE_PS3_LV1)) + ps3_early_mm_init(); + else if (firmware_has_feature(FW_FEATURE_LPAR)) + hpte_init_lpar(); + else + hpte_init_native(); + /* Initialize the MMU Hash table and create the linear mapping * of memory. Has to be done before SLB initialization as this is * currently where the page size encoding is obtained. diff --git a/arch/powerpc/mm/pgtable-radix.c b/arch/powerpc/mm/pgtable-radix.c index 4ea1094c9fc4..003ff48a11b6 100644 --- a/arch/powerpc/mm/pgtable-radix.c +++ b/arch/powerpc/mm/pgtable-radix.c @@ -345,6 +345,7 @@ void __init radix__early_init_mmu(void) radix_init_page_sizes(); if (!firmware_has_feature(FW_FEATURE_LPAR)) { + radix_init_native(); lpcr = mfspr(SPRN_LPCR); mtspr(SPRN_LPCR, lpcr | LPCR_UPRT | LPCR_HR); radix_init_partition_table(); diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index 36cff28d0293..e342f7833db5 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -261,7 +261,6 @@ static int __init cell_probe(void) !of_flat_dt_is_compatible(root, "IBM,CPBW-1.0")) return 0; - hpte_init_native(); pm_power_off = rtas_power_off; return 1; diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index 99b9b96ab059..b1ecd991a0fb 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c @@ -306,7 +306,6 @@ static int __init maple_probe(void) !of_flat_dt_is_compatible(root, "Momentum,Apache")) return 0; - hpte_init_native(); pm_power_off = maple_power_off; return 1; diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index 7349644c9828..924d01d9b375 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c @@ -426,8 +426,6 @@ static int __init pas_probe(void) !of_flat_dt_is_compatible(root, "pasemi,pwrficient")) return 0; - hpte_init_native(); - alloc_iobmap_l2(); return 1; diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 4ad61687c670..795bf8cfddd9 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -599,10 +599,6 @@ static int __init pmac_probe(void) !of_flat_dt_is_compatible(root, "MacRISC")) return 0; -#ifdef CONFIG_PPC64 - hpte_init_native(); -#endif - #ifdef CONFIG_PPC32 /* isa_io_base gets set in pmac_pci_init */ ISA_DMA_THRESHOLD = ~0L; diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c index 8492bbbcfc08..f70ea83502b2 100644 --- a/arch/powerpc/platforms/powernv/setup.c +++ b/arch/powerpc/platforms/powernv/setup.c @@ -273,11 +273,6 @@ static int __init pnv_probe(void) if (!of_flat_dt_is_compatible(root, "ibm,powernv")) return 0; - if (IS_ENABLED(CONFIG_PPC_RADIX_MMU) && radix_enabled()) - radix_init_native(); - else if (IS_ENABLED(CONFIG_PPC_STD_MMU_64)) - hpte_init_native(); - if (firmware_has_feature(FW_FEATURE_OPAL)) pnv_setup_machdep_opal(); diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c index 486ecd017535..b7fdf88474e8 100644 --- a/arch/powerpc/platforms/ps3/setup.c +++ b/arch/powerpc/platforms/ps3/setup.c @@ -226,9 +226,17 @@ static void __init ps3_progress(char *s, unsigned short hex) printk("*** %04x : %s\n", hex, s ? s : ""); } -static int __init ps3_probe(void) +void __init ps3_early_mm_init(void) { unsigned long htab_size; + + ps3_mm_init(); + ps3_mm_vas_create(&htab_size); + ps3_hpte_init(htab_size); +} + +static int __init ps3_probe(void) +{ unsigned long dt_root; DBG(" -> %s:%d\n", __func__, __LINE__); @@ -237,12 +245,7 @@ static int __init ps3_probe(void) if (!of_flat_dt_is_compatible(dt_root, "sony,ps3")) return 0; - powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE; - ps3_os_area_save_params(); - ps3_mm_init(); - ps3_mm_vas_create(&htab_size); - ps3_hpte_init(htab_size); pm_power_off = ps3_power_off; DBG(" <- %s:%d\n", __func__, __LINE__); diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index ba7dc126b5e5..240721348ebc 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -687,13 +687,6 @@ static int __init pSeries_probe(void) of_flat_dt_is_compatible(root, "IBM,CBEA")) return 0; - pr_debug("pSeries detected, looking for LPAR capability...\n"); - - if (firmware_has_feature(FW_FEATURE_LPAR)) - hpte_init_lpar(); - else - hpte_init_native(); - pm_power_off = pseries_power_off; pr_debug("Machine is%s LPAR !\n", -- cgit v1.2.3 From 388dc1c3f003539c82e0f1436019955df78aa9f9 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 5 Jul 2016 15:03:52 +1000 Subject: powerpc/pasemi: Remove IOBMAP allocation from platform probe() These days, memblocks is available later, so we can just allocate it as part of iob_init. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/pasemi/iommu.c | 15 +++++---------- arch/powerpc/platforms/pasemi/pasemi.h | 1 - arch/powerpc/platforms/pasemi/setup.c | 2 -- 3 files changed, 5 insertions(+), 13 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pasemi/iommu.c b/arch/powerpc/platforms/pasemi/iommu.c index c929644e74a6..43dd3fb514e0 100644 --- a/arch/powerpc/platforms/pasemi/iommu.c +++ b/arch/powerpc/platforms/pasemi/iommu.c @@ -202,6 +202,11 @@ int __init iob_init(struct device_node *dn) pr_debug(" -> %s\n", __func__); + /* For 2G space, 8x64 pages (2^21 bytes) is max total l2 size */ + iob_l2_base = (u32 *)__va(memblock_alloc_base(1UL<<21, 1UL<<21, 0x80000000)); + + printk(KERN_INFO "IOBMAP L2 allocated at: %p\n", iob_l2_base); + /* Allocate a spare page to map all invalid IOTLB pages. */ tmp = memblock_alloc(IOBMAP_PAGE_SIZE, IOBMAP_PAGE_SIZE); if (!tmp) @@ -260,13 +265,3 @@ void __init iommu_init_early_pasemi(void) set_pci_dma_ops(&dma_iommu_ops); } -void __init alloc_iobmap_l2(void) -{ -#ifndef CONFIG_PPC_PASEMI_IOMMU - return; -#endif - /* For 2G space, 8x64 pages (2^21 bytes) is max total l2 size */ - iob_l2_base = (u32 *)__va(memblock_alloc_base(1UL<<21, 1UL<<21, 0x80000000)); - - printk(KERN_INFO "IOBMAP L2 allocated at: %p\n", iob_l2_base); -} diff --git a/arch/powerpc/platforms/pasemi/pasemi.h b/arch/powerpc/platforms/pasemi/pasemi.h index 11f230a48227..74cbcb357612 100644 --- a/arch/powerpc/platforms/pasemi/pasemi.h +++ b/arch/powerpc/platforms/pasemi/pasemi.h @@ -8,7 +8,6 @@ extern void pas_pci_dma_dev_setup(struct pci_dev *dev); extern void __iomem *pasemi_pci_getcfgaddr(struct pci_dev *dev, int offset); -extern void __init alloc_iobmap_l2(void); extern void __init pasemi_map_registers(void); /* Power savings modes, implemented in asm */ diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index 924d01d9b375..d120f7a9e4ad 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c @@ -426,8 +426,6 @@ static int __init pas_probe(void) !of_flat_dt_is_compatible(root, "pasemi,pwrficient")) return 0; - alloc_iobmap_l2(); - return 1; } -- cgit v1.2.3 From b521f576df6c49fcc06fbc06a349f7590f223a38 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 5 Jul 2016 15:03:57 +1000 Subject: powerpc/pmac: Remove spurrious machine type test pmac_declare_of_platform_devices() is already a machine initcall, thus it won't be called on a non-powermac machine. Testing for chrp there is pointless. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powermac/setup.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 795bf8cfddd9..8fffe1c4b6f5 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -484,9 +484,6 @@ static int __init pmac_declare_of_platform_devices(void) { struct device_node *np; - if (machine_is(chrp)) - return -1; - np = of_find_node_by_name(NULL, "valkyrie"); if (np) { of_platform_device_create(np, "valkyrie", NULL); -- cgit v1.2.3 From 7025776ed1ebdfa1959932e7a4662c2f88607df0 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 5 Jul 2016 15:03:58 +1000 Subject: powerpc/mm: Move hash table ops to a separate structure Moving probe_machine() to after mmu init will cause the ppc_md fields relative to the hash table management to be overwritten. Since we have essentially disconnected the machine type from the hash backend ops, finish the job by moving them to a different structure. The only callback that didn't quite fix is update_partition_table since this is not specific to hash, so I moved it to a standalone variable for now. We can revisit later if needed. Signed-off-by: Benjamin Herrenschmidt [mpe: Fix ppc64e build failure in kexec] Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/book3s/64/mmu-hash.h | 39 ++++++++++++++++++++ arch/powerpc/include/asm/machdep.h | 36 ------------------- arch/powerpc/kernel/machine_kexec_64.c | 9 +++-- arch/powerpc/kernel/misc_64.S | 2 +- arch/powerpc/kvm/book3s_64_mmu_host.c | 18 +++++----- arch/powerpc/mm/hash64_4k.c | 18 +++++----- arch/powerpc/mm/hash64_64k.c | 39 +++++++++++--------- arch/powerpc/mm/hash_native_64.c | 16 ++++----- arch/powerpc/mm/hash_utils_64.c | 51 +++++++++++++++------------ arch/powerpc/mm/hugepage-hash64.c | 17 ++++----- arch/powerpc/mm/hugetlbpage-hash64.c | 4 +-- arch/powerpc/platforms/ps3/htab.c | 12 +++---- arch/powerpc/platforms/pseries/lpar.c | 18 +++++----- 13 files changed, 151 insertions(+), 128 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/include/asm/book3s/64/mmu-hash.h b/arch/powerpc/include/asm/book3s/64/mmu-hash.h index 2c2d55580ae2..b0f4dffe12ae 100644 --- a/arch/powerpc/include/asm/book3s/64/mmu-hash.h +++ b/arch/powerpc/include/asm/book3s/64/mmu-hash.h @@ -124,6 +124,45 @@ #ifndef __ASSEMBLY__ +struct mmu_hash_ops { + void (*hpte_invalidate)(unsigned long slot, + unsigned long vpn, + int bpsize, int apsize, + int ssize, int local); + long (*hpte_updatepp)(unsigned long slot, + unsigned long newpp, + unsigned long vpn, + int bpsize, int apsize, + int ssize, unsigned long flags); + void (*hpte_updateboltedpp)(unsigned long newpp, + unsigned long ea, + int psize, int ssize); + long (*hpte_insert)(unsigned long hpte_group, + unsigned long vpn, + unsigned long prpn, + unsigned long rflags, + unsigned long vflags, + int psize, int apsize, + int ssize); + long (*hpte_remove)(unsigned long hpte_group); + int (*hpte_removebolted)(unsigned long ea, + int psize, int ssize); + void (*flush_hash_range)(unsigned long number, int local); + void (*hugepage_invalidate)(unsigned long vsid, + unsigned long addr, + unsigned char *hpte_slot_array, + int psize, int ssize, int local); + /* + * Special for kexec. + * To be called in real mode with interrupts disabled. No locks are + * taken as such, concurrent access on pre POWER5 hardware could result + * in a deadlock. + * The linear mapping is destroyed as well. + */ + void (*hpte_clear_all)(void); +}; +extern struct mmu_hash_ops mmu_hash_ops; + struct hash_pte { __be64 v; __be64 r; diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index e62e7d33bda0..5b2edf5ba114 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h @@ -34,42 +34,6 @@ struct pci_host_bridge; struct machdep_calls { char *name; #ifdef CONFIG_PPC64 - void (*hpte_invalidate)(unsigned long slot, - unsigned long vpn, - int bpsize, int apsize, - int ssize, int local); - long (*hpte_updatepp)(unsigned long slot, - unsigned long newpp, - unsigned long vpn, - int bpsize, int apsize, - int ssize, unsigned long flags); - void (*hpte_updateboltedpp)(unsigned long newpp, - unsigned long ea, - int psize, int ssize); - long (*hpte_insert)(unsigned long hpte_group, - unsigned long vpn, - unsigned long prpn, - unsigned long rflags, - unsigned long vflags, - int psize, int apsize, - int ssize); - long (*hpte_remove)(unsigned long hpte_group); - int (*hpte_removebolted)(unsigned long ea, - int psize, int ssize); - void (*flush_hash_range)(unsigned long number, int local); - void (*hugepage_invalidate)(unsigned long vsid, - unsigned long addr, - unsigned char *hpte_slot_array, - int psize, int ssize, int local); - /* - * Special for kexec. - * To be called in real mode with interrupts disabled. No locks are - * taken as such, concurrent access on pre POWER5 hardware could result - * in a deadlock. - * The linear mapping is destroyed as well. - */ - void (*hpte_clear_all)(void); - void __iomem * (*ioremap)(phys_addr_t addr, unsigned long size, unsigned long flags, void *caller); void (*iounmap)(volatile void __iomem *token); diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index 50bf55135ef8..4c780a342282 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c @@ -55,7 +55,7 @@ int default_machine_kexec_prepare(struct kimage *image) const unsigned long *basep; const unsigned int *sizep; - if (!ppc_md.hpte_clear_all) + if (!mmu_hash_ops.hpte_clear_all) return -ENOENT; /* @@ -380,7 +380,12 @@ void default_machine_kexec(struct kimage *image) */ kexec_sequence(&kexec_stack, image->start, image, page_address(image->control_code_page), - ppc_md.hpte_clear_all); +#ifdef CONFIG_PPC_STD_MMU + mmu_hash_ops.hpte_clear_all +#else + NULL +#endif + ); /* NOTREACHED */ } diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index 7a8519052b14..cb195157b318 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S @@ -667,7 +667,7 @@ _GLOBAL(kexec_sequence) mr r12,r27 #endif mtctr r12 - bctrl /* ppc_md.hpte_clear_all(void); */ + bctrl /* mmu_hash_ops.hpte_clear_all(void); */ #endif /* !CONFIG_PPC_BOOK3E */ /* diff --git a/arch/powerpc/kvm/book3s_64_mmu_host.c b/arch/powerpc/kvm/book3s_64_mmu_host.c index 114edace6cdd..a587e8f4fd26 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_host.c +++ b/arch/powerpc/kvm/book3s_64_mmu_host.c @@ -34,9 +34,9 @@ void kvmppc_mmu_invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte) { - ppc_md.hpte_invalidate(pte->slot, pte->host_vpn, - pte->pagesize, pte->pagesize, MMU_SEGSIZE_256M, - false); + mmu_hash_ops.hpte_invalidate(pte->slot, pte->host_vpn, + pte->pagesize, pte->pagesize, + MMU_SEGSIZE_256M, false); } /* We keep 512 gvsid->hvsid entries, mapping the guest ones to the array using @@ -169,13 +169,13 @@ map_again: /* In case we tried normal mapping already, let's nuke old entries */ if (attempt > 1) - if (ppc_md.hpte_remove(hpteg) < 0) { + if (mmu_hash_ops.hpte_remove(hpteg) < 0) { r = -1; goto out_unlock; } - ret = ppc_md.hpte_insert(hpteg, vpn, hpaddr, rflags, vflags, - hpsize, hpsize, MMU_SEGSIZE_256M); + ret = mmu_hash_ops.hpte_insert(hpteg, vpn, hpaddr, rflags, vflags, + hpsize, hpsize, MMU_SEGSIZE_256M); if (ret < 0) { /* If we couldn't map a primary PTE, try a secondary */ @@ -187,8 +187,10 @@ map_again: trace_kvm_book3s_64_mmu_map(rflags, hpteg, vpn, hpaddr, orig_pte); - /* The ppc_md code may give us a secondary entry even though we - asked for a primary. Fix up. */ + /* + * The mmu_hash_ops code may give us a secondary entry even + * though we asked for a primary. Fix up. + */ if ((ret & _PTEIDX_SECONDARY) && !(vflags & HPTE_V_SECONDARY)) { hash = ~hash; hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP); diff --git a/arch/powerpc/mm/hash64_4k.c b/arch/powerpc/mm/hash64_4k.c index 6333b273d2d5..42c702b3be1f 100644 --- a/arch/powerpc/mm/hash64_4k.c +++ b/arch/powerpc/mm/hash64_4k.c @@ -70,8 +70,8 @@ int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid, slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; slot += (old_pte & H_PAGE_F_GIX) >> H_PAGE_F_GIX_SHIFT; - if (ppc_md.hpte_updatepp(slot, rflags, vpn, MMU_PAGE_4K, - MMU_PAGE_4K, ssize, flags) == -1) + if (mmu_hash_ops.hpte_updatepp(slot, rflags, vpn, MMU_PAGE_4K, + MMU_PAGE_4K, ssize, flags) == -1) old_pte &= ~_PAGE_HPTEFLAGS; } @@ -84,21 +84,23 @@ repeat: hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; /* Insert into the hash table, primary slot */ - slot = ppc_md.hpte_insert(hpte_group, vpn, pa, rflags, 0, - MMU_PAGE_4K, MMU_PAGE_4K, ssize); + slot = mmu_hash_ops.hpte_insert(hpte_group, vpn, pa, rflags, 0, + MMU_PAGE_4K, MMU_PAGE_4K, ssize); /* * Primary is full, try the secondary */ if (unlikely(slot == -1)) { hpte_group = ((~hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; - slot = ppc_md.hpte_insert(hpte_group, vpn, pa, - rflags, HPTE_V_SECONDARY, - MMU_PAGE_4K, MMU_PAGE_4K, ssize); + slot = mmu_hash_ops.hpte_insert(hpte_group, vpn, pa, + rflags, + HPTE_V_SECONDARY, + MMU_PAGE_4K, + MMU_PAGE_4K, ssize); if (slot == -1) { if (mftb() & 0x1) hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; - ppc_md.hpte_remove(hpte_group); + mmu_hash_ops.hpte_remove(hpte_group); /* * FIXME!! Should be try the group from which we removed ? */ diff --git a/arch/powerpc/mm/hash64_64k.c b/arch/powerpc/mm/hash64_64k.c index 16644e1f4e6b..3bbbea07378c 100644 --- a/arch/powerpc/mm/hash64_64k.c +++ b/arch/powerpc/mm/hash64_64k.c @@ -133,9 +133,9 @@ int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid, slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; slot += hidx & _PTEIDX_GROUP_IX; - ret = ppc_md.hpte_updatepp(slot, rflags, vpn, - MMU_PAGE_4K, MMU_PAGE_4K, - ssize, flags); + ret = mmu_hash_ops.hpte_updatepp(slot, rflags, vpn, + MMU_PAGE_4K, MMU_PAGE_4K, + ssize, flags); /* *if we failed because typically the HPTE wasn't really here * we try an insertion. @@ -166,21 +166,22 @@ repeat: hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; /* Insert into the hash table, primary slot */ - slot = ppc_md.hpte_insert(hpte_group, vpn, pa, rflags, 0, - MMU_PAGE_4K, MMU_PAGE_4K, ssize); + slot = mmu_hash_ops.hpte_insert(hpte_group, vpn, pa, rflags, 0, + MMU_PAGE_4K, MMU_PAGE_4K, ssize); /* * Primary is full, try the secondary */ if (unlikely(slot == -1)) { hpte_group = ((~hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; - slot = ppc_md.hpte_insert(hpte_group, vpn, pa, - rflags, HPTE_V_SECONDARY, - MMU_PAGE_4K, MMU_PAGE_4K, ssize); + slot = mmu_hash_ops.hpte_insert(hpte_group, vpn, pa, + rflags, HPTE_V_SECONDARY, + MMU_PAGE_4K, MMU_PAGE_4K, + ssize); if (slot == -1) { if (mftb() & 0x1) hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; - ppc_md.hpte_remove(hpte_group); + mmu_hash_ops.hpte_remove(hpte_group); /* * FIXME!! Should be try the group from which we removed ? */ @@ -272,8 +273,9 @@ int __hash_page_64K(unsigned long ea, unsigned long access, slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; slot += (old_pte & H_PAGE_F_GIX) >> H_PAGE_F_GIX_SHIFT; - if (ppc_md.hpte_updatepp(slot, rflags, vpn, MMU_PAGE_64K, - MMU_PAGE_64K, ssize, flags) == -1) + if (mmu_hash_ops.hpte_updatepp(slot, rflags, vpn, MMU_PAGE_64K, + MMU_PAGE_64K, ssize, + flags) == -1) old_pte &= ~_PAGE_HPTEFLAGS; } @@ -286,21 +288,24 @@ repeat: hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; /* Insert into the hash table, primary slot */ - slot = ppc_md.hpte_insert(hpte_group, vpn, pa, rflags, 0, - MMU_PAGE_64K, MMU_PAGE_64K, ssize); + slot = mmu_hash_ops.hpte_insert(hpte_group, vpn, pa, rflags, 0, + MMU_PAGE_64K, MMU_PAGE_64K, + ssize); /* * Primary is full, try the secondary */ if (unlikely(slot == -1)) { hpte_group = ((~hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; - slot = ppc_md.hpte_insert(hpte_group, vpn, pa, - rflags, HPTE_V_SECONDARY, - MMU_PAGE_64K, MMU_PAGE_64K, ssize); + slot = mmu_hash_ops.hpte_insert(hpte_group, vpn, pa, + rflags, + HPTE_V_SECONDARY, + MMU_PAGE_64K, + MMU_PAGE_64K, ssize); if (slot == -1) { if (mftb() & 0x1) hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; - ppc_md.hpte_remove(hpte_group); + mmu_hash_ops.hpte_remove(hpte_group); /* * FIXME!! Should be try the group from which we removed ? */ diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index cb3b4c98b637..88ce7d212320 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c @@ -739,14 +739,14 @@ static int native_register_proc_table(unsigned long base, unsigned long page_siz void __init hpte_init_native(void) { - ppc_md.hpte_invalidate = native_hpte_invalidate; - ppc_md.hpte_updatepp = native_hpte_updatepp; - ppc_md.hpte_updateboltedpp = native_hpte_updateboltedpp; - ppc_md.hpte_insert = native_hpte_insert; - ppc_md.hpte_remove = native_hpte_remove; - ppc_md.hpte_clear_all = native_hpte_clear; - ppc_md.flush_hash_range = native_flush_hash_range; - ppc_md.hugepage_invalidate = native_hugepage_invalidate; + mmu_hash_ops.hpte_invalidate = native_hpte_invalidate; + mmu_hash_ops.hpte_updatepp = native_hpte_updatepp; + mmu_hash_ops.hpte_updateboltedpp = native_hpte_updateboltedpp; + mmu_hash_ops.hpte_insert = native_hpte_insert; + mmu_hash_ops.hpte_remove = native_hpte_remove; + mmu_hash_ops.hpte_clear_all = native_hpte_clear; + mmu_hash_ops.flush_hash_range = native_flush_hash_range; + mmu_hash_ops.hugepage_invalidate = native_hugepage_invalidate; if (cpu_has_feature(CPU_FTR_ARCH_300)) ppc_md.register_process_table = native_register_proc_table; diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index eab3074a6a37..341632471b9d 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -118,6 +118,8 @@ static u8 *linear_map_hash_slots; static unsigned long linear_map_hash_count; static DEFINE_SPINLOCK(linear_map_hash_lock); #endif /* CONFIG_DEBUG_PAGEALLOC */ +struct mmu_hash_ops mmu_hash_ops; +EXPORT_SYMBOL(mmu_hash_ops); /* There are definitions of page sizes arrays to be used when none * is provided by the firmware. @@ -276,9 +278,10 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, hash = hpt_hash(vpn, shift, ssize); hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP); - BUG_ON(!ppc_md.hpte_insert); - ret = ppc_md.hpte_insert(hpteg, vpn, paddr, tprot, - HPTE_V_BOLTED, psize, psize, ssize); + BUG_ON(!mmu_hash_ops.hpte_insert); + ret = mmu_hash_ops.hpte_insert(hpteg, vpn, paddr, tprot, + HPTE_V_BOLTED, psize, psize, + ssize); if (ret < 0) break; @@ -303,11 +306,11 @@ int htab_remove_mapping(unsigned long vstart, unsigned long vend, shift = mmu_psize_defs[psize].shift; step = 1 << shift; - if (!ppc_md.hpte_removebolted) + if (!mmu_hash_ops.hpte_removebolted) return -ENODEV; for (vaddr = vstart; vaddr < vend; vaddr += step) { - rc = ppc_md.hpte_removebolted(vaddr, psize, ssize); + rc = mmu_hash_ops.hpte_removebolted(vaddr, psize, ssize); if (rc == -ENOENT) { ret = -ENOENT; continue; @@ -789,8 +792,8 @@ static void __init htab_initialize(void) * Clear the htab if firmware assisted dump is active so * that we dont end up using old mappings. */ - if (is_fadump_active() && ppc_md.hpte_clear_all) - ppc_md.hpte_clear_all(); + if (is_fadump_active() && mmu_hash_ops.hpte_clear_all) + mmu_hash_ops.hpte_clear_all(); #endif } else { unsigned long limit = MEMBLOCK_ALLOC_ANYWHERE; @@ -1480,7 +1483,8 @@ void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, int ssize, * We use same base page size and actual psize, because we don't * use these functions for hugepage */ - ppc_md.hpte_invalidate(slot, vpn, psize, psize, ssize, local); + mmu_hash_ops.hpte_invalidate(slot, vpn, psize, psize, + ssize, local); } pte_iterate_hashed_end(); #ifdef CONFIG_PPC_TRANSACTIONAL_MEM @@ -1521,9 +1525,9 @@ void flush_hash_hugepage(unsigned long vsid, unsigned long addr, if (!hpte_slot_array) return; - if (ppc_md.hugepage_invalidate) { - ppc_md.hugepage_invalidate(vsid, s_addr, hpte_slot_array, - psize, ssize, local); + if (mmu_hash_ops.hugepage_invalidate) { + mmu_hash_ops.hugepage_invalidate(vsid, s_addr, hpte_slot_array, + psize, ssize, local); goto tm_abort; } /* @@ -1550,8 +1554,8 @@ void flush_hash_hugepage(unsigned long vsid, unsigned long addr, slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; slot += hidx & _PTEIDX_GROUP_IX; - ppc_md.hpte_invalidate(slot, vpn, psize, - MMU_PAGE_16M, ssize, local); + mmu_hash_ops.hpte_invalidate(slot, vpn, psize, + MMU_PAGE_16M, ssize, local); } tm_abort: #ifdef CONFIG_PPC_TRANSACTIONAL_MEM @@ -1575,8 +1579,8 @@ tm_abort: void flush_hash_range(unsigned long number, int local) { - if (ppc_md.flush_hash_range) - ppc_md.flush_hash_range(number, local); + if (mmu_hash_ops.flush_hash_range) + mmu_hash_ops.flush_hash_range(number, local); else { int i; struct ppc64_tlb_batch *batch = @@ -1621,22 +1625,22 @@ repeat: HPTES_PER_GROUP) & ~0x7UL; /* Insert into the hash table, primary slot */ - slot = ppc_md.hpte_insert(hpte_group, vpn, pa, rflags, vflags, - psize, psize, ssize); + slot = mmu_hash_ops.hpte_insert(hpte_group, vpn, pa, rflags, vflags, + psize, psize, ssize); /* Primary is full, try the secondary */ if (unlikely(slot == -1)) { hpte_group = ((~hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; - slot = ppc_md.hpte_insert(hpte_group, vpn, pa, rflags, - vflags | HPTE_V_SECONDARY, - psize, psize, ssize); + slot = mmu_hash_ops.hpte_insert(hpte_group, vpn, pa, rflags, + vflags | HPTE_V_SECONDARY, + psize, psize, ssize); if (slot == -1) { if (mftb() & 0x1) hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP)&~0x7UL; - ppc_md.hpte_remove(hpte_group); + mmu_hash_ops.hpte_remove(hpte_group); goto repeat; } } @@ -1686,8 +1690,9 @@ static void kernel_unmap_linear_page(unsigned long vaddr, unsigned long lmi) hash = ~hash; slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; slot += hidx & _PTEIDX_GROUP_IX; - ppc_md.hpte_invalidate(slot, vpn, mmu_linear_psize, mmu_linear_psize, - mmu_kernel_ssize, 0); + mmu_hash_ops.hpte_invalidate(slot, vpn, mmu_linear_psize, + mmu_linear_psize, + mmu_kernel_ssize, 0); } void __kernel_map_pages(struct page *page, int numpages, int enable) diff --git a/arch/powerpc/mm/hugepage-hash64.c b/arch/powerpc/mm/hugepage-hash64.c index ba3fc229468a..f20d16f849c5 100644 --- a/arch/powerpc/mm/hugepage-hash64.c +++ b/arch/powerpc/mm/hugepage-hash64.c @@ -103,8 +103,8 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; slot += hidx & _PTEIDX_GROUP_IX; - ret = ppc_md.hpte_updatepp(slot, rflags, vpn, - psize, lpsize, ssize, flags); + ret = mmu_hash_ops.hpte_updatepp(slot, rflags, vpn, + psize, lpsize, ssize, flags); /* * We failed to update, try to insert a new entry. */ @@ -131,23 +131,24 @@ repeat: hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; /* Insert into the hash table, primary slot */ - slot = ppc_md.hpte_insert(hpte_group, vpn, pa, rflags, 0, - psize, lpsize, ssize); + slot = mmu_hash_ops.hpte_insert(hpte_group, vpn, pa, rflags, 0, + psize, lpsize, ssize); /* * Primary is full, try the secondary */ if (unlikely(slot == -1)) { hpte_group = ((~hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; - slot = ppc_md.hpte_insert(hpte_group, vpn, pa, - rflags, HPTE_V_SECONDARY, - psize, lpsize, ssize); + slot = mmu_hash_ops.hpte_insert(hpte_group, vpn, pa, + rflags, + HPTE_V_SECONDARY, + psize, lpsize, ssize); if (slot == -1) { if (mftb() & 0x1) hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; - ppc_md.hpte_remove(hpte_group); + mmu_hash_ops.hpte_remove(hpte_group); goto repeat; } } diff --git a/arch/powerpc/mm/hugetlbpage-hash64.c b/arch/powerpc/mm/hugetlbpage-hash64.c index 3058560b6121..d5026f3800b6 100644 --- a/arch/powerpc/mm/hugetlbpage-hash64.c +++ b/arch/powerpc/mm/hugetlbpage-hash64.c @@ -79,8 +79,8 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid, slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; slot += (old_pte & H_PAGE_F_GIX) >> H_PAGE_F_GIX_SHIFT; - if (ppc_md.hpte_updatepp(slot, rflags, vpn, mmu_psize, - mmu_psize, ssize, flags) == -1) + if (mmu_hash_ops.hpte_updatepp(slot, rflags, vpn, mmu_psize, + mmu_psize, ssize, flags) == -1) old_pte &= ~_PAGE_HPTEFLAGS; } diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c index c9a3e677192a..cb3c50328de8 100644 --- a/arch/powerpc/platforms/ps3/htab.c +++ b/arch/powerpc/platforms/ps3/htab.c @@ -195,12 +195,12 @@ static void ps3_hpte_clear(void) void __init ps3_hpte_init(unsigned long htab_size) { - ppc_md.hpte_invalidate = ps3_hpte_invalidate; - ppc_md.hpte_updatepp = ps3_hpte_updatepp; - ppc_md.hpte_updateboltedpp = ps3_hpte_updateboltedpp; - ppc_md.hpte_insert = ps3_hpte_insert; - ppc_md.hpte_remove = ps3_hpte_remove; - ppc_md.hpte_clear_all = ps3_hpte_clear; + mmu_hash_ops.hpte_invalidate = ps3_hpte_invalidate; + mmu_hash_ops.hpte_updatepp = ps3_hpte_updatepp; + mmu_hash_ops.hpte_updateboltedpp = ps3_hpte_updateboltedpp; + mmu_hash_ops.hpte_insert = ps3_hpte_insert; + mmu_hash_ops.hpte_remove = ps3_hpte_remove; + mmu_hash_ops.hpte_clear_all = ps3_hpte_clear; ppc64_pft_size = __ilog2(htab_size); } diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 03c732afef34..0e91388d0af9 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -591,15 +591,15 @@ __setup("bulk_remove=", disable_bulk_remove); void __init hpte_init_lpar(void) { - ppc_md.hpte_invalidate = pSeries_lpar_hpte_invalidate; - ppc_md.hpte_updatepp = pSeries_lpar_hpte_updatepp; - ppc_md.hpte_updateboltedpp = pSeries_lpar_hpte_updateboltedpp; - ppc_md.hpte_insert = pSeries_lpar_hpte_insert; - ppc_md.hpte_remove = pSeries_lpar_hpte_remove; - ppc_md.hpte_removebolted = pSeries_lpar_hpte_removebolted; - ppc_md.flush_hash_range = pSeries_lpar_flush_hash_range; - ppc_md.hpte_clear_all = pSeries_lpar_hptab_clear; - ppc_md.hugepage_invalidate = pSeries_lpar_hugepage_invalidate; + mmu_hash_ops.hpte_invalidate = pSeries_lpar_hpte_invalidate; + mmu_hash_ops.hpte_updatepp = pSeries_lpar_hpte_updatepp; + mmu_hash_ops.hpte_updateboltedpp = pSeries_lpar_hpte_updateboltedpp; + mmu_hash_ops.hpte_insert = pSeries_lpar_hpte_insert; + mmu_hash_ops.hpte_remove = pSeries_lpar_hpte_remove; + mmu_hash_ops.hpte_removebolted = pSeries_lpar_hpte_removebolted; + mmu_hash_ops.flush_hash_range = pSeries_lpar_flush_hash_range; + mmu_hash_ops.hpte_clear_all = pSeries_lpar_hptab_clear; + mmu_hash_ops.hugepage_invalidate = pSeries_lpar_hugepage_invalidate; } #ifdef CONFIG_PPC_SMLPAR -- cgit v1.2.3 From 406b0b6ae3fcd5c7946a68a9e43b470c79d292a2 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 5 Jul 2016 15:04:00 +1000 Subject: powerpc/64: Move 64-bit probe_machine() to later in the boot process We no long need the machine type that early, so we can move probe_machine() to after the device-tree has been expanded. This will allow further consolidation. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/setup_64.c | 6 +++--- arch/powerpc/platforms/cell/setup.c | 6 ++---- arch/powerpc/platforms/maple/setup.c | 6 ++---- arch/powerpc/platforms/pasemi/setup.c | 6 ++---- arch/powerpc/platforms/powermac/setup.c | 6 ++++++ arch/powerpc/platforms/powernv/setup.c | 4 +--- arch/powerpc/platforms/ps3/setup.c | 6 ++---- arch/powerpc/platforms/pseries/setup.c | 7 +++---- 8 files changed, 21 insertions(+), 26 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 4ffd090633de..883d527899a7 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -301,9 +301,6 @@ void __init early_setup(unsigned long dt_ptr) setup_paca(&paca[boot_cpuid]); fixup_boot_paca(); - /* Probe the machine type */ - probe_machine(); - /* * Configure exception handlers. This include setting up trampolines * if needed, setting exception endian mode, etc... @@ -511,6 +508,9 @@ void __init setup_system(void) */ check_for_initrd(); + /* Probe the machine type */ + probe_machine(); + /* * Do some platform specific early initializations, that includes * setting up the hash table pointers. It also sets up some interrupt-mapping diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index e342f7833db5..d3543e68efe8 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -255,10 +255,8 @@ static void __init cell_setup_arch(void) static int __init cell_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (!of_flat_dt_is_compatible(root, "IBM,CBEA") && - !of_flat_dt_is_compatible(root, "IBM,CPBW-1.0")) + if (!of_machine_is_compatible("IBM,CBEA") && + !of_machine_is_compatible("IBM,CPBW-1.0")) return 0; pm_power_off = rtas_power_off; diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index b1ecd991a0fb..d3d44cba661b 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c @@ -300,10 +300,8 @@ static void __init maple_progress(char *s, unsigned short hex) */ static int __init maple_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (!of_flat_dt_is_compatible(root, "Momentum,Maple") && - !of_flat_dt_is_compatible(root, "Momentum,Apache")) + if (!of_machine_is_compatible("Momentum,Maple") && + !of_machine_is_compatible("Momentum,Apache")) return 0; pm_power_off = maple_power_off; diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index d120f7a9e4ad..ec810ddb10ee 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c @@ -420,10 +420,8 @@ machine_device_initcall(pasemi, pasemi_publish_devices); */ static int __init pas_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (!of_flat_dt_is_compatible(root, "PA6T-1682M") && - !of_flat_dt_is_compatible(root, "pasemi,pwrficient")) + if (!of_machine_is_compatible("PA6T-1682M") && + !of_machine_is_compatible("pasemi,pwrficient")) return 0; return 1; diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 8fffe1c4b6f5..0872f9837cf5 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -590,11 +590,17 @@ console_initcall(check_pmac_serial_console); */ static int __init pmac_probe(void) { +#ifdef CONFIG_PPC32 unsigned long root = of_get_flat_dt_root(); if (!of_flat_dt_is_compatible(root, "Power Macintosh") && !of_flat_dt_is_compatible(root, "MacRISC")) return 0; +#else + if (!of_machine_is_compatible("Power Macintosh") && + !of_machine_is_compatible("MacRISC")) + return 0; +#endif #ifdef CONFIG_PPC32 /* isa_io_base gets set in pmac_pci_init */ diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c index f70ea83502b2..8865efa54e51 100644 --- a/arch/powerpc/platforms/powernv/setup.c +++ b/arch/powerpc/platforms/powernv/setup.c @@ -268,9 +268,7 @@ static void __init pnv_setup_machdep_opal(void) static int __init pnv_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (!of_flat_dt_is_compatible(root, "ibm,powernv")) + if (!of_machine_is_compatible("ibm,powernv")) return 0; if (firmware_has_feature(FW_FEATURE_OPAL)) diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c index b7fdf88474e8..3a487e7f4a5e 100644 --- a/arch/powerpc/platforms/ps3/setup.c +++ b/arch/powerpc/platforms/ps3/setup.c @@ -237,15 +237,13 @@ void __init ps3_early_mm_init(void) static int __init ps3_probe(void) { - unsigned long dt_root; - DBG(" -> %s:%d\n", __func__, __LINE__); - dt_root = of_get_flat_dt_root(); - if (!of_flat_dt_is_compatible(dt_root, "sony,ps3")) + if (!of_machine_is_compatible("sony,ps3")) return 0; ps3_os_area_save_params(); + pm_power_off = ps3_power_off; DBG(" <- %s:%d\n", __func__, __LINE__); diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 240721348ebc..6988b9dc3d3b 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -672,8 +672,7 @@ static void pseries_power_off(void) static int __init pSeries_probe(void) { - unsigned long root = of_get_flat_dt_root(); - const char *dtype = of_get_flat_dt_prop(root, "device_type", NULL); + const char *dtype = of_get_property(of_root, "device_type", NULL); if (dtype == NULL) return 0; @@ -683,8 +682,8 @@ static int __init pSeries_probe(void) /* Cell blades firmware claims to be chrp while it's not. Until this * is fixed, we need to avoid those here. */ - if (of_flat_dt_is_compatible(root, "IBM,CPBW-1.0") || - of_flat_dt_is_compatible(root, "IBM,CBEA")) + if (of_machine_is_compatible("IBM,CPBW-1.0") || + of_machine_is_compatible("IBM,CBEA")) return 0; pm_power_off = pseries_power_off; -- cgit v1.2.3 From 565713840445b7ccafb28dc1230d57d40bcb42a5 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 5 Jul 2016 15:04:05 +1000 Subject: powerpc: Move 32-bit probe() machine to later in the boot process This converts all the 32-bit platforms to use the expanded device-tree which is a pretty mechanical change. Unlike 64-bit, the 32-bit kernel didn't rely on platform initializations to setup the MMU since it sets it up entirely before probe_machine() so the move has comparatively less consequences though it's a bigger patch. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/setup_32.c | 35 +++++++++++--------- arch/powerpc/platforms/40x/ep405.c | 4 +-- arch/powerpc/platforms/40x/ppc40x_simple.c | 2 +- arch/powerpc/platforms/40x/virtex.c | 4 +-- arch/powerpc/platforms/40x/walnut.c | 4 +-- arch/powerpc/platforms/44x/canyonlands.c | 5 ++- arch/powerpc/platforms/44x/ebony.c | 4 +-- arch/powerpc/platforms/44x/iss4xx.c | 4 +-- arch/powerpc/platforms/44x/ppc44x_simple.c | 3 +- arch/powerpc/platforms/44x/ppc476.c | 6 ++-- arch/powerpc/platforms/44x/sam440ep.c | 4 +-- arch/powerpc/platforms/44x/virtex.c | 4 +-- arch/powerpc/platforms/44x/warp.c | 4 +-- arch/powerpc/platforms/512x/mpc5121_ads.c | 4 +-- arch/powerpc/platforms/512x/mpc512x_generic.c | 2 +- arch/powerpc/platforms/512x/pdm360ng.c | 4 +-- arch/powerpc/platforms/52xx/efika.c | 3 +- arch/powerpc/platforms/52xx/lite5200.c | 2 +- arch/powerpc/platforms/52xx/media5200.c | 2 +- arch/powerpc/platforms/52xx/mpc5200_simple.c | 2 +- arch/powerpc/platforms/82xx/ep8248e.c | 3 +- arch/powerpc/platforms/82xx/km82xx.c | 3 +- arch/powerpc/platforms/82xx/mpc8272_ads.c | 3 +- arch/powerpc/platforms/82xx/pq2fads.c | 3 +- arch/powerpc/platforms/83xx/asp834x.c | 3 +- arch/powerpc/platforms/83xx/km83xx.c | 3 +- arch/powerpc/platforms/83xx/mpc830x_rdb.c | 2 +- arch/powerpc/platforms/83xx/mpc831x_rdb.c | 2 +- arch/powerpc/platforms/83xx/mpc832x_mds.c | 4 +-- arch/powerpc/platforms/83xx/mpc832x_rdb.c | 4 +-- arch/powerpc/platforms/83xx/mpc834x_itx.c | 4 +-- arch/powerpc/platforms/83xx/mpc834x_mds.c | 4 +-- arch/powerpc/platforms/83xx/mpc836x_mds.c | 4 +-- arch/powerpc/platforms/83xx/mpc836x_rdk.c | 4 +-- arch/powerpc/platforms/83xx/mpc837x_mds.c | 4 +-- arch/powerpc/platforms/83xx/mpc837x_rdb.c | 2 +- arch/powerpc/platforms/83xx/sbc834x.c | 4 +-- arch/powerpc/platforms/85xx/bsc913x_qds.c | 4 +-- arch/powerpc/platforms/85xx/bsc913x_rdb.c | 4 +-- arch/powerpc/platforms/85xx/c293pcie.c | 4 +-- arch/powerpc/platforms/85xx/corenet_generic.c | 5 ++- arch/powerpc/platforms/85xx/ge_imp3a.c | 4 +-- arch/powerpc/platforms/85xx/ksi8560.c | 4 +-- arch/powerpc/platforms/85xx/mpc8536_ds.c | 4 +-- arch/powerpc/platforms/85xx/mpc85xx_ads.c | 4 +-- arch/powerpc/platforms/85xx/mpc85xx_cds.c | 4 +-- arch/powerpc/platforms/85xx/mpc85xx_ds.c | 12 ++----- arch/powerpc/platforms/85xx/mpc85xx_mds.c | 12 ++----- arch/powerpc/platforms/85xx/mpc85xx_rdb.c | 40 ++++++----------------- arch/powerpc/platforms/85xx/mvme2500.c | 4 +-- arch/powerpc/platforms/85xx/p1010rdb.c | 6 ++-- arch/powerpc/platforms/85xx/p1022_ds.c | 4 +-- arch/powerpc/platforms/85xx/p1022_rdk.c | 4 +-- arch/powerpc/platforms/85xx/p1023_rdb.c | 4 +-- arch/powerpc/platforms/85xx/ppa8548.c | 4 +-- arch/powerpc/platforms/85xx/qemu_e500.c | 4 +-- arch/powerpc/platforms/85xx/sbc8548.c | 4 +-- arch/powerpc/platforms/85xx/socrates.c | 4 +-- arch/powerpc/platforms/85xx/stx_gp3.c | 4 +-- arch/powerpc/platforms/85xx/tqm85xx.c | 2 +- arch/powerpc/platforms/85xx/twr_p102x.c | 4 +-- arch/powerpc/platforms/85xx/xes_mpc85xx.c | 12 ++----- arch/powerpc/platforms/86xx/gef_ppc9a.c | 4 +-- arch/powerpc/platforms/86xx/gef_sbc310.c | 4 +-- arch/powerpc/platforms/86xx/gef_sbc610.c | 4 +-- arch/powerpc/platforms/86xx/mpc8610_hpcd.c | 4 +-- arch/powerpc/platforms/86xx/mpc86xx_hpcn.c | 6 ++-- arch/powerpc/platforms/86xx/sbc8641d.c | 4 +-- arch/powerpc/platforms/8xx/adder875.c | 3 +- arch/powerpc/platforms/8xx/ep88xc.c | 3 +- arch/powerpc/platforms/8xx/mpc86xads_setup.c | 3 +- arch/powerpc/platforms/8xx/mpc885ads_setup.c | 3 +- arch/powerpc/platforms/8xx/tqm8xx_setup.c | 4 +-- arch/powerpc/platforms/amigaone/setup.c | 4 +-- arch/powerpc/platforms/embedded6xx/c2k.c | 4 +-- arch/powerpc/platforms/embedded6xx/gamecube.c | 5 +-- arch/powerpc/platforms/embedded6xx/holly.c | 4 +-- arch/powerpc/platforms/embedded6xx/linkstation.c | 6 +--- arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c | 4 +-- arch/powerpc/platforms/embedded6xx/mvme5100.c | 4 +-- arch/powerpc/platforms/embedded6xx/storcenter.c | 4 +-- arch/powerpc/platforms/embedded6xx/wii.c | 5 +-- arch/powerpc/platforms/powermac/setup.c | 8 ----- 83 files changed, 120 insertions(+), 289 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 3f0aca2b7f63..e7bb4e76896a 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -113,23 +113,7 @@ notrace void __init machine_init(u64 dt_ptr) early_init_mmu(); - probe_machine(); - setup_kdump_trampoline(); - -#ifdef CONFIG_6xx - if (cpu_has_feature(CPU_FTR_CAN_DOZE) || - cpu_has_feature(CPU_FTR_CAN_NAP)) - ppc_md.power_save = ppc6xx_idle; -#endif - -#ifdef CONFIG_E500 - if (cpu_has_feature(CPU_FTR_CAN_DOZE) || - cpu_has_feature(CPU_FTR_CAN_NAP)) - ppc_md.power_save = e500_idle; -#endif - if (ppc_md.progress) - ppc_md.progress("id mach(): done", 0x200); } /* Checks "l2cr=xxxx" command-line option */ @@ -249,6 +233,21 @@ static void __init exc_lvl_early_init(void) #define exc_lvl_early_init() #endif +static void setup_power_save(void) +{ +#ifdef CONFIG_6xx + if (cpu_has_feature(CPU_FTR_CAN_DOZE) || + cpu_has_feature(CPU_FTR_CAN_NAP)) + ppc_md.power_save = ppc6xx_idle; +#endif + +#ifdef CONFIG_E500 + if (cpu_has_feature(CPU_FTR_CAN_DOZE) || + cpu_has_feature(CPU_FTR_CAN_NAP)) + ppc_md.power_save = e500_idle; +#endif +} + /* Warning, IO base is not yet inited */ void __init setup_arch(char **cmdline_p) { @@ -260,6 +259,10 @@ void __init setup_arch(char **cmdline_p) unflatten_device_tree(); check_for_initrd(); + probe_machine(); + + setup_power_save(); + if (ppc_md.init_early) ppc_md.init_early(); diff --git a/arch/powerpc/platforms/40x/ep405.c b/arch/powerpc/platforms/40x/ep405.c index ddc12a1926ef..1c8aec6e9bb7 100644 --- a/arch/powerpc/platforms/40x/ep405.c +++ b/arch/powerpc/platforms/40x/ep405.c @@ -105,9 +105,7 @@ static void __init ep405_setup_arch(void) static int __init ep405_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (!of_flat_dt_is_compatible(root, "ep405")) + if (!of_machine_is_compatible("ep405")) return 0; return 1; diff --git a/arch/powerpc/platforms/40x/ppc40x_simple.c b/arch/powerpc/platforms/40x/ppc40x_simple.c index b0c46375dd95..2a050007bbae 100644 --- a/arch/powerpc/platforms/40x/ppc40x_simple.c +++ b/arch/powerpc/platforms/40x/ppc40x_simple.c @@ -63,7 +63,7 @@ static const char * const board[] __initconst = { static int __init ppc40x_probe(void) { - if (of_flat_dt_match(of_get_flat_dt_root(), board)) { + if (of_device_compatible_match(of_root, board)) { pci_set_flags(PCI_REASSIGN_ALL_RSRC); return 1; } diff --git a/arch/powerpc/platforms/40x/virtex.c b/arch/powerpc/platforms/40x/virtex.c index 9aa7ae2f4164..91a08ea758a8 100644 --- a/arch/powerpc/platforms/40x/virtex.c +++ b/arch/powerpc/platforms/40x/virtex.c @@ -37,9 +37,7 @@ machine_device_initcall(virtex, virtex_device_probe); static int __init virtex_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (!of_flat_dt_is_compatible(root, "xlnx,virtex")) + if (!of_machine_is_compatible("xlnx,virtex")) return 0; return 1; diff --git a/arch/powerpc/platforms/40x/walnut.c b/arch/powerpc/platforms/40x/walnut.c index f7ac2d0fcb44..e5797815e2f1 100644 --- a/arch/powerpc/platforms/40x/walnut.c +++ b/arch/powerpc/platforms/40x/walnut.c @@ -46,9 +46,7 @@ machine_device_initcall(walnut, walnut_device_probe); static int __init walnut_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (!of_flat_dt_is_compatible(root, "ibm,walnut")) + if (!of_machine_is_compatible("ibm,walnut")) return 0; pci_set_flags(PCI_REASSIGN_ALL_RSRC); diff --git a/arch/powerpc/platforms/44x/canyonlands.c b/arch/powerpc/platforms/44x/canyonlands.c index 22ca5430c9cb..157f4ce46386 100644 --- a/arch/powerpc/platforms/44x/canyonlands.c +++ b/arch/powerpc/platforms/44x/canyonlands.c @@ -53,11 +53,10 @@ machine_device_initcall(canyonlands, ppc460ex_device_probe); static int __init ppc460ex_probe(void) { - unsigned long root = of_get_flat_dt_root(); - if (of_flat_dt_is_compatible(root, "amcc,canyonlands")) { + if (of_machine_is_compatible("amcc,canyonlands")) { pci_set_flags(PCI_REASSIGN_ALL_RSRC); return 1; - } + } return 0; } diff --git a/arch/powerpc/platforms/44x/ebony.c b/arch/powerpc/platforms/44x/ebony.c index ae893226392d..1070225f5f9b 100644 --- a/arch/powerpc/platforms/44x/ebony.c +++ b/arch/powerpc/platforms/44x/ebony.c @@ -49,9 +49,7 @@ machine_device_initcall(ebony, ebony_device_probe); */ static int __init ebony_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (!of_flat_dt_is_compatible(root, "ibm,ebony")) + if (!of_machine_is_compatible("ibm,ebony")) return 0; pci_set_flags(PCI_REASSIGN_ALL_RSRC); diff --git a/arch/powerpc/platforms/44x/iss4xx.c b/arch/powerpc/platforms/44x/iss4xx.c index c7c6758b3cfe..5f296dd6b1c0 100644 --- a/arch/powerpc/platforms/44x/iss4xx.c +++ b/arch/powerpc/platforms/44x/iss4xx.c @@ -149,9 +149,7 @@ static void __init iss4xx_setup_arch(void) */ static int __init iss4xx_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (!of_flat_dt_is_compatible(root, "ibm,iss-4xx")) + if (!of_machine_is_compatible("ibm,iss-4xx")) return 0; return 1; diff --git a/arch/powerpc/platforms/44x/ppc44x_simple.c b/arch/powerpc/platforms/44x/ppc44x_simple.c index 573c3d2689c6..8d6e4da9dfbe 100644 --- a/arch/powerpc/platforms/44x/ppc44x_simple.c +++ b/arch/powerpc/platforms/44x/ppc44x_simple.c @@ -67,11 +67,10 @@ static char *board[] __initdata = { static int __init ppc44x_probe(void) { - unsigned long root = of_get_flat_dt_root(); int i = 0; for (i = 0; i < ARRAY_SIZE(board); i++) { - if (of_flat_dt_is_compatible(root, board[i])) { + if (of_machine_is_compatible(board[i])) { pci_set_flags(PCI_REASSIGN_ALL_RSRC); return 1; } diff --git a/arch/powerpc/platforms/44x/ppc476.c b/arch/powerpc/platforms/44x/ppc476.c index 003973f65297..e55933f9cd55 100644 --- a/arch/powerpc/platforms/44x/ppc476.c +++ b/arch/powerpc/platforms/44x/ppc476.c @@ -275,12 +275,10 @@ static void ppc47x_pci_irq_fixup(struct pci_dev *dev) */ static int __init ppc47x_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (of_flat_dt_is_compatible(root, "ibm,akebono")) + if (of_machine_is_compatible("ibm,akebono")) return 1; - if (of_flat_dt_is_compatible(root, "ibm,currituck")) { + if (of_machine_is_compatible("ibm,currituck")) { ppc_md.pci_irq_fixup = ppc47x_pci_irq_fixup; return 1; } diff --git a/arch/powerpc/platforms/44x/sam440ep.c b/arch/powerpc/platforms/44x/sam440ep.c index 3ee4a03c1496..688ffeab0699 100644 --- a/arch/powerpc/platforms/44x/sam440ep.c +++ b/arch/powerpc/platforms/44x/sam440ep.c @@ -46,9 +46,7 @@ machine_device_initcall(sam440ep, sam440ep_device_probe); static int __init sam440ep_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (!of_flat_dt_is_compatible(root, "acube,sam440ep")) + if (!of_machine_is_compatible("acube,sam440ep")) return 0; pci_set_flags(PCI_REASSIGN_ALL_RSRC); diff --git a/arch/powerpc/platforms/44x/virtex.c b/arch/powerpc/platforms/44x/virtex.c index ad272c17c640..a7e08026097a 100644 --- a/arch/powerpc/platforms/44x/virtex.c +++ b/arch/powerpc/platforms/44x/virtex.c @@ -43,9 +43,7 @@ machine_device_initcall(virtex, virtex_device_probe); static int __init virtex_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (!of_flat_dt_is_compatible(root, "xlnx,virtex440")) + if (!of_machine_is_compatible("xlnx,virtex440")) return 0; return 1; diff --git a/arch/powerpc/platforms/44x/warp.c b/arch/powerpc/platforms/44x/warp.c index 501333cf42cf..5ecce543103e 100644 --- a/arch/powerpc/platforms/44x/warp.c +++ b/arch/powerpc/platforms/44x/warp.c @@ -44,9 +44,7 @@ machine_device_initcall(warp, warp_device_probe); static int __init warp_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (!of_flat_dt_is_compatible(root, "pika,warp")) + if (!of_machine_is_compatible("pika,warp")) return 0; /* For __dma_alloc_coherent */ diff --git a/arch/powerpc/platforms/512x/mpc5121_ads.c b/arch/powerpc/platforms/512x/mpc5121_ads.c index 3e90ece10ae9..4e03f04e3a1f 100644 --- a/arch/powerpc/platforms/512x/mpc5121_ads.c +++ b/arch/powerpc/platforms/512x/mpc5121_ads.c @@ -57,9 +57,7 @@ static void __init mpc5121_ads_init_IRQ(void) */ static int __init mpc5121_ads_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "fsl,mpc5121ads"); + return of_machine_is_compatible("fsl,mpc5121ads"); } define_machine(mpc5121_ads) { diff --git a/arch/powerpc/platforms/512x/mpc512x_generic.c b/arch/powerpc/platforms/512x/mpc512x_generic.c index ce71408781a0..87eba1753088 100644 --- a/arch/powerpc/platforms/512x/mpc512x_generic.c +++ b/arch/powerpc/platforms/512x/mpc512x_generic.c @@ -38,7 +38,7 @@ static const char * const board[] __initconst = { */ static int __init mpc512x_generic_probe(void) { - return of_flat_dt_match(of_get_flat_dt_root(), board); + return of_device_compatible_match(of_root, board); } define_machine(mpc512x_generic) { diff --git a/arch/powerpc/platforms/512x/pdm360ng.c b/arch/powerpc/platforms/512x/pdm360ng.c index 116f2325b20b..f9cad19a33ab 100644 --- a/arch/powerpc/platforms/512x/pdm360ng.c +++ b/arch/powerpc/platforms/512x/pdm360ng.c @@ -113,9 +113,7 @@ void __init pdm360ng_init(void) static int __init pdm360ng_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "ifm,pdm360ng"); + return of_machine_is_compatible("ifm,pdm360ng"); } define_machine(pdm360ng) { diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c index 6af651e69129..39b49822ace1 100644 --- a/arch/powerpc/platforms/52xx/efika.c +++ b/arch/powerpc/platforms/52xx/efika.c @@ -200,8 +200,7 @@ static void __init efika_setup_arch(void) static int __init efika_probe(void) { - const char *model = of_get_flat_dt_prop(of_get_flat_dt_root(), - "model", NULL); + const char *model = of_get_property(of_root, "model", NULL); if (model == NULL) return 0; diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c index 7492de3cf6d0..c94c385cc919 100644 --- a/arch/powerpc/platforms/52xx/lite5200.c +++ b/arch/powerpc/platforms/52xx/lite5200.c @@ -183,7 +183,7 @@ static const char * const board[] __initconst = { */ static int __init lite5200_probe(void) { - return of_flat_dt_match(of_get_flat_dt_root(), board); + return of_device_compatible_match(of_root, board); } define_machine(lite5200) { diff --git a/arch/powerpc/platforms/52xx/media5200.c b/arch/powerpc/platforms/52xx/media5200.c index 8fb95480fd73..a3227040cc86 100644 --- a/arch/powerpc/platforms/52xx/media5200.c +++ b/arch/powerpc/platforms/52xx/media5200.c @@ -242,7 +242,7 @@ static const char * const board[] __initconst = { */ static int __init media5200_probe(void) { - return of_flat_dt_match(of_get_flat_dt_root(), board); + return of_device_compatible_match(of_root, board); } define_machine(media5200_platform) { diff --git a/arch/powerpc/platforms/52xx/mpc5200_simple.c b/arch/powerpc/platforms/52xx/mpc5200_simple.c index 792a301a0bf0..a80c6278d515 100644 --- a/arch/powerpc/platforms/52xx/mpc5200_simple.c +++ b/arch/powerpc/platforms/52xx/mpc5200_simple.c @@ -70,7 +70,7 @@ static const char *board[] __initdata = { */ static int __init mpc5200_simple_probe(void) { - return of_flat_dt_match(of_get_flat_dt_root(), board); + return of_device_compatible_match(of_root, board); } define_machine(mpc5200_simple_platform) { diff --git a/arch/powerpc/platforms/82xx/ep8248e.c b/arch/powerpc/platforms/82xx/ep8248e.c index 6781bda117be..cdab847749e6 100644 --- a/arch/powerpc/platforms/82xx/ep8248e.c +++ b/arch/powerpc/platforms/82xx/ep8248e.c @@ -309,8 +309,7 @@ machine_device_initcall(ep8248e, declare_of_platform_devices); */ static int __init ep8248e_probe(void) { - unsigned long root = of_get_flat_dt_root(); - return of_flat_dt_is_compatible(root, "fsl,ep8248e"); + return of_machine_is_compatible("fsl,ep8248e"); } define_machine(ep8248e) diff --git a/arch/powerpc/platforms/82xx/km82xx.c b/arch/powerpc/platforms/82xx/km82xx.c index 387b446f4161..28860e40b5db 100644 --- a/arch/powerpc/platforms/82xx/km82xx.c +++ b/arch/powerpc/platforms/82xx/km82xx.c @@ -198,8 +198,7 @@ machine_device_initcall(km82xx, declare_of_platform_devices); */ static int __init km82xx_probe(void) { - unsigned long root = of_get_flat_dt_root(); - return of_flat_dt_is_compatible(root, "keymile,km82xx"); + return of_machine_is_compatible("keymile,km82xx"); } define_machine(km82xx) diff --git a/arch/powerpc/platforms/82xx/mpc8272_ads.c b/arch/powerpc/platforms/82xx/mpc8272_ads.c index d24deacf07d0..d23c10a96bde 100644 --- a/arch/powerpc/platforms/82xx/mpc8272_ads.c +++ b/arch/powerpc/platforms/82xx/mpc8272_ads.c @@ -201,8 +201,7 @@ machine_device_initcall(mpc8272_ads, declare_of_platform_devices); */ static int __init mpc8272_ads_probe(void) { - unsigned long root = of_get_flat_dt_root(); - return of_flat_dt_is_compatible(root, "fsl,mpc8272ads"); + return of_machine_is_compatible("fsl,mpc8272ads"); } define_machine(mpc8272_ads) diff --git a/arch/powerpc/platforms/82xx/pq2fads.c b/arch/powerpc/platforms/82xx/pq2fads.c index 3a5164ad10ad..6c654dc74a4b 100644 --- a/arch/powerpc/platforms/82xx/pq2fads.c +++ b/arch/powerpc/platforms/82xx/pq2fads.c @@ -164,8 +164,7 @@ static void __init pq2fads_setup_arch(void) */ static int __init pq2fads_probe(void) { - unsigned long root = of_get_flat_dt_root(); - return of_flat_dt_is_compatible(root, "fsl,pq2fads"); + return of_machine_is_compatible("fsl,pq2fads"); } static const struct of_device_id of_bus_ids[] __initconst = { diff --git a/arch/powerpc/platforms/83xx/asp834x.c b/arch/powerpc/platforms/83xx/asp834x.c index 464ea8e0292d..17e54339f8d9 100644 --- a/arch/powerpc/platforms/83xx/asp834x.c +++ b/arch/powerpc/platforms/83xx/asp834x.c @@ -43,8 +43,7 @@ machine_device_initcall(asp834x, mpc83xx_declare_of_platform_devices); */ static int __init asp834x_probe(void) { - unsigned long root = of_get_flat_dt_root(); - return of_flat_dt_is_compatible(root, "analogue-and-micro,asp8347e"); + return of_machine_is_compatible("analogue-and-micro,asp8347e"); } define_machine(asp834x) { diff --git a/arch/powerpc/platforms/83xx/km83xx.c b/arch/powerpc/platforms/83xx/km83xx.c index 4bc6bbbe9ada..e7fbd6366abb 100644 --- a/arch/powerpc/platforms/83xx/km83xx.c +++ b/arch/powerpc/platforms/83xx/km83xx.c @@ -171,11 +171,10 @@ static char *board[] __initdata = { */ static int __init mpc83xx_km_probe(void) { - unsigned long node = of_get_flat_dt_root(); int i = 0; while (board[i]) { - if (of_flat_dt_is_compatible(node, board[i])) + if (of_machine_is_compatible(board[i])) break; i++; } diff --git a/arch/powerpc/platforms/83xx/mpc830x_rdb.c b/arch/powerpc/platforms/83xx/mpc830x_rdb.c index 4f2d9fea77b7..040d5d085467 100644 --- a/arch/powerpc/platforms/83xx/mpc830x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc830x_rdb.c @@ -46,7 +46,7 @@ static const char *board[] __initdata = { */ static int __init mpc830x_rdb_probe(void) { - return of_flat_dt_match(of_get_flat_dt_root(), board); + return of_device_compatible_match(of_root, board); } machine_device_initcall(mpc830x_rdb, mpc83xx_declare_of_platform_devices); diff --git a/arch/powerpc/platforms/83xx/mpc831x_rdb.c b/arch/powerpc/platforms/83xx/mpc831x_rdb.c index fa25977c52de..40e0d8307b59 100644 --- a/arch/powerpc/platforms/83xx/mpc831x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc831x_rdb.c @@ -46,7 +46,7 @@ static const char *board[] __initdata = { */ static int __init mpc831x_rdb_probe(void) { - return of_flat_dt_match(of_get_flat_dt_root(), board); + return of_device_compatible_match(of_root, board); } machine_device_initcall(mpc831x_rdb, mpc83xx_declare_of_platform_devices); diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c index a973b2ae5df6..cdfa47c4d394 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c @@ -102,9 +102,7 @@ machine_device_initcall(mpc832x_mds, mpc83xx_declare_of_platform_devices); */ static int __init mpc832x_sys_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "MPC832xMDS"); + return of_machine_is_compatible("MPC832xMDS"); } define_machine(mpc832x_mds) { diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c index ea2b87d202ca..2ef03e7d248c 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c @@ -220,9 +220,7 @@ machine_device_initcall(mpc832x_rdb, mpc83xx_declare_of_platform_devices); */ static int __init mpc832x_rdb_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "MPC832xRDB"); + return of_machine_is_compatible("MPC832xRDB"); } define_machine(mpc832x_rdb) { diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c index 80aea8c4b5a3..8fd0c1e8b182 100644 --- a/arch/powerpc/platforms/83xx/mpc834x_itx.c +++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c @@ -70,9 +70,7 @@ static void __init mpc834x_itx_setup_arch(void) */ static int __init mpc834x_itx_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "MPC834xMITX"); + return of_machine_is_compatible("MPC834xMITX"); } define_machine(mpc834x_itx) { diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c index 553e793a4a93..eeaee6123bb3 100644 --- a/arch/powerpc/platforms/83xx/mpc834x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c @@ -91,9 +91,7 @@ machine_device_initcall(mpc834x_mds, mpc83xx_declare_of_platform_devices); */ static int __init mpc834x_mds_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "MPC834xMDS"); + return of_machine_is_compatible("MPC834xMDS"); } define_machine(mpc834x_mds) { diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c index dd70b85f56d4..dacf4c2df069 100644 --- a/arch/powerpc/platforms/83xx/mpc836x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c @@ -209,9 +209,7 @@ machine_arch_initcall(mpc836x_mds, mpc836x_usb_cfg); */ static int __init mpc836x_mds_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "MPC836xMDS"); + return of_machine_is_compatible("MPC836xMDS"); } define_machine(mpc836x_mds) { diff --git a/arch/powerpc/platforms/83xx/mpc836x_rdk.c b/arch/powerpc/platforms/83xx/mpc836x_rdk.c index 4cd7153a6c88..cf67ac93ddcb 100644 --- a/arch/powerpc/platforms/83xx/mpc836x_rdk.c +++ b/arch/powerpc/platforms/83xx/mpc836x_rdk.c @@ -42,9 +42,7 @@ static void __init mpc836x_rdk_setup_arch(void) */ static int __init mpc836x_rdk_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "fsl,mpc8360rdk"); + return of_machine_is_compatible("fsl,mpc8360rdk"); } define_machine(mpc836x_rdk) { diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c b/arch/powerpc/platforms/83xx/mpc837x_mds.c index e53a60b6c863..652b97d699c9 100644 --- a/arch/powerpc/platforms/83xx/mpc837x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c @@ -93,9 +93,7 @@ machine_device_initcall(mpc837x_mds, mpc83xx_declare_of_platform_devices); */ static int __init mpc837x_mds_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "fsl,mpc837xmds"); + return of_machine_is_compatible("fsl,mpc837xmds"); } define_machine(mpc837x_mds) { diff --git a/arch/powerpc/platforms/83xx/mpc837x_rdb.c b/arch/powerpc/platforms/83xx/mpc837x_rdb.c index 9813c81e8e5b..667731d81676 100644 --- a/arch/powerpc/platforms/83xx/mpc837x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc837x_rdb.c @@ -73,7 +73,7 @@ static const char * const board[] __initconst = { */ static int __init mpc837x_rdb_probe(void) { - return of_flat_dt_match(of_get_flat_dt_root(), board); + return of_device_compatible_match(of_root, board); } define_machine(mpc837x_rdb) { diff --git a/arch/powerpc/platforms/83xx/sbc834x.c b/arch/powerpc/platforms/83xx/sbc834x.c index 26cb3e934722..b867e88dfb0d 100644 --- a/arch/powerpc/platforms/83xx/sbc834x.c +++ b/arch/powerpc/platforms/83xx/sbc834x.c @@ -60,9 +60,7 @@ machine_device_initcall(sbc834x, mpc83xx_declare_of_platform_devices); */ static int __init sbc834x_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "SBC834xE"); + return of_machine_is_compatible("SBC834xE"); } define_machine(sbc834x) { diff --git a/arch/powerpc/platforms/85xx/bsc913x_qds.c b/arch/powerpc/platforms/85xx/bsc913x_qds.c index dcfafd6b91ee..07dd6ae3ec52 100644 --- a/arch/powerpc/platforms/85xx/bsc913x_qds.c +++ b/arch/powerpc/platforms/85xx/bsc913x_qds.c @@ -60,9 +60,7 @@ machine_arch_initcall(bsc9132_qds, mpc85xx_common_publish_devices); static int __init bsc9132_qds_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "fsl,bsc9132qds"); + return of_machine_is_compatible("fsl,bsc9132qds"); } define_machine(bsc9132_qds) { diff --git a/arch/powerpc/platforms/85xx/bsc913x_rdb.c b/arch/powerpc/platforms/85xx/bsc913x_rdb.c index 9d57bedb940c..e48f6710e6d5 100644 --- a/arch/powerpc/platforms/85xx/bsc913x_rdb.c +++ b/arch/powerpc/platforms/85xx/bsc913x_rdb.c @@ -50,9 +50,7 @@ machine_device_initcall(bsc9131_rdb, mpc85xx_common_publish_devices); static int __init bsc9131_rdb_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "fsl,bsc9131rdb"); + return of_machine_is_compatible("fsl,bsc9131rdb"); } define_machine(bsc9131_rdb) { diff --git a/arch/powerpc/platforms/85xx/c293pcie.c b/arch/powerpc/platforms/85xx/c293pcie.c index 61bc851e9a8e..3b9e3f0f9aec 100644 --- a/arch/powerpc/platforms/85xx/c293pcie.c +++ b/arch/powerpc/platforms/85xx/c293pcie.c @@ -54,9 +54,7 @@ machine_arch_initcall(c293_pcie, mpc85xx_common_publish_devices); */ static int __init c293_pcie_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (of_flat_dt_is_compatible(root, "fsl,C293PCIE")) + if (of_machine_is_compatible("fsl,C293PCIE")) return 1; return 0; } diff --git a/arch/powerpc/platforms/85xx/corenet_generic.c b/arch/powerpc/platforms/85xx/corenet_generic.c index a2b0bc859de0..3a6a84f07f43 100644 --- a/arch/powerpc/platforms/85xx/corenet_generic.c +++ b/arch/powerpc/platforms/85xx/corenet_generic.c @@ -170,20 +170,19 @@ static const char * const boards[] __initconst = { */ static int __init corenet_generic_probe(void) { - unsigned long root = of_get_flat_dt_root(); char hv_compat[24]; int i; #ifdef CONFIG_SMP extern struct smp_ops_t smp_85xx_ops; #endif - if (of_flat_dt_match(root, boards)) + if (of_device_compatible_match(of_root, boards)) return 1; /* Check if we're running under the Freescale hypervisor */ for (i = 0; boards[i]; i++) { snprintf(hv_compat, sizeof(hv_compat), "%s-hv", boards[i]); - if (of_flat_dt_is_compatible(root, hv_compat)) { + if (of_machine_is_compatible(hv_compat)) { ppc_md.init_IRQ = ehv_pic_init; ppc_md.get_irq = ehv_pic_get_irq; diff --git a/arch/powerpc/platforms/85xx/ge_imp3a.c b/arch/powerpc/platforms/85xx/ge_imp3a.c index 55eefef0c0c7..14af36a7fa9c 100644 --- a/arch/powerpc/platforms/85xx/ge_imp3a.c +++ b/arch/powerpc/platforms/85xx/ge_imp3a.c @@ -197,9 +197,7 @@ static void ge_imp3a_show_cpuinfo(struct seq_file *m) */ static int __init ge_imp3a_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "ge,IMP3A"); + return of_machine_is_compatible("ge,IMP3A"); } machine_arch_initcall(ge_imp3a, mpc85xx_common_publish_devices); diff --git a/arch/powerpc/platforms/85xx/ksi8560.c b/arch/powerpc/platforms/85xx/ksi8560.c index 867a1078b488..6ef8580fdc0e 100644 --- a/arch/powerpc/platforms/85xx/ksi8560.c +++ b/arch/powerpc/platforms/85xx/ksi8560.c @@ -176,9 +176,7 @@ machine_device_initcall(ksi8560, mpc85xx_common_publish_devices); */ static int __init ksi8560_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "emerson,KSI8560"); + return of_machine_is_compatible("emerson,KSI8560"); } define_machine(ksi8560) { diff --git a/arch/powerpc/platforms/85xx/mpc8536_ds.c b/arch/powerpc/platforms/85xx/mpc8536_ds.c index a378ba3519e9..6ba687f19e45 100644 --- a/arch/powerpc/platforms/85xx/mpc8536_ds.c +++ b/arch/powerpc/platforms/85xx/mpc8536_ds.c @@ -64,9 +64,7 @@ machine_arch_initcall(mpc8536_ds, swiotlb_setup_bus_notifier); */ static int __init mpc8536_ds_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "fsl,mpc8536ds"); + return of_machine_is_compatible("fsl,mpc8536ds"); } define_machine(mpc8536_ds) { diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c index de72a5f464b1..8756715c7a47 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c @@ -160,9 +160,7 @@ machine_arch_initcall(mpc85xx_ads, mpc85xx_common_publish_devices); */ static int __init mpc85xx_ads_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "MPC85xxADS"); + return of_machine_is_compatible("MPC85xxADS"); } define_machine(mpc85xx_ads) { diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c index 5e0a0a24d5ce..62f171c71c4c 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c @@ -367,9 +367,7 @@ static void mpc85xx_cds_show_cpuinfo(struct seq_file *m) */ static int __init mpc85xx_cds_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "MPC85xxCDS"); + return of_machine_is_compatible("MPC85xxCDS"); } machine_arch_initcall(mpc85xx_cds, mpc85xx_common_publish_devices); diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c index 64a7e8c16839..6bc07d837b1c 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c @@ -167,9 +167,7 @@ static void __init mpc85xx_ds_setup_arch(void) */ static int __init mpc8544_ds_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return !!of_flat_dt_is_compatible(root, "MPC8544DS"); + return !!of_machine_is_compatible("MPC8544DS"); } machine_arch_initcall(mpc8544_ds, mpc85xx_common_publish_devices); @@ -185,9 +183,7 @@ machine_arch_initcall(p2020_ds, swiotlb_setup_bus_notifier); */ static int __init mpc8572_ds_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return !!of_flat_dt_is_compatible(root, "fsl,MPC8572DS"); + return !!of_machine_is_compatible("fsl,MPC8572DS"); } /* @@ -195,9 +191,7 @@ static int __init mpc8572_ds_probe(void) */ static int __init p2020_ds_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return !!of_flat_dt_is_compatible(root, "fsl,P2020DS"); + return !!of_machine_is_compatible("fsl,P2020DS"); } define_machine(mpc8544_ds) { diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index f61cbe235581..fa9cd710d2ae 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c @@ -376,9 +376,7 @@ static void __init mpc85xx_mds_pic_init(void) static int __init mpc85xx_mds_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "MPC85xxMDS"); + return of_machine_is_compatible("MPC85xxMDS"); } define_machine(mpc8568_mds) { @@ -398,9 +396,7 @@ define_machine(mpc8568_mds) { static int __init mpc8569_mds_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "fsl,MPC8569EMDS"); + return of_machine_is_compatible("fsl,MPC8569EMDS"); } define_machine(mpc8569_mds) { @@ -420,9 +416,7 @@ define_machine(mpc8569_mds) { static int __init p1021_mds_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "fsl,P1021MDS"); + return of_machine_is_compatible("fsl,P1021MDS"); } diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c index 761e504d22ef..c1499cbf3786 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c @@ -147,80 +147,60 @@ machine_arch_initcall(p1024_rdb, mpc85xx_common_publish_devices); */ static int __init p2020_rdb_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (of_flat_dt_is_compatible(root, "fsl,P2020RDB")) + if (of_machine_is_compatible("fsl,P2020RDB")) return 1; return 0; } static int __init p1020_rdb_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (of_flat_dt_is_compatible(root, "fsl,P1020RDB")) + if (of_machine_is_compatible("fsl,P1020RDB")) return 1; return 0; } static int __init p1020_rdb_pc_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "fsl,P1020RDB-PC"); + return of_machine_is_compatible("fsl,P1020RDB-PC"); } static int __init p1020_rdb_pd_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "fsl,P1020RDB-PD"); + return of_machine_is_compatible("fsl,P1020RDB-PD"); } static int __init p1021_rdb_pc_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (of_flat_dt_is_compatible(root, "fsl,P1021RDB-PC")) + if (of_machine_is_compatible("fsl,P1021RDB-PC")) return 1; return 0; } static int __init p2020_rdb_pc_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (of_flat_dt_is_compatible(root, "fsl,P2020RDB-PC")) + if (of_machine_is_compatible("fsl,P2020RDB-PC")) return 1; return 0; } static int __init p1025_rdb_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "fsl,P1025RDB"); + return of_machine_is_compatible("fsl,P1025RDB"); } static int __init p1020_mbg_pc_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "fsl,P1020MBG-PC"); + return of_machine_is_compatible("fsl,P1020MBG-PC"); } static int __init p1020_utm_pc_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "fsl,P1020UTM-PC"); + return of_machine_is_compatible("fsl,P1020UTM-PC"); } static int __init p1024_rdb_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "fsl,P1024RDB"); + return of_machine_is_compatible("fsl,P1024RDB"); } define_machine(p2020_rdb) { diff --git a/arch/powerpc/platforms/85xx/mvme2500.c b/arch/powerpc/platforms/85xx/mvme2500.c index 1233050560ae..acc3d0d6049d 100644 --- a/arch/powerpc/platforms/85xx/mvme2500.c +++ b/arch/powerpc/platforms/85xx/mvme2500.c @@ -53,9 +53,7 @@ machine_arch_initcall(mvme2500, mpc85xx_common_publish_devices); */ static int __init mvme2500_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "artesyn,MVME2500"); + return of_machine_is_compatible("artesyn,MVME2500"); } define_machine(mvme2500) { diff --git a/arch/powerpc/platforms/85xx/p1010rdb.c b/arch/powerpc/platforms/85xx/p1010rdb.c index ad1a3d438a9e..661d7b59e413 100644 --- a/arch/powerpc/platforms/85xx/p1010rdb.c +++ b/arch/powerpc/platforms/85xx/p1010rdb.c @@ -62,11 +62,9 @@ machine_arch_initcall(p1010_rdb, swiotlb_setup_bus_notifier); */ static int __init p1010_rdb_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (of_flat_dt_is_compatible(root, "fsl,P1010RDB")) + if (of_machine_is_compatible("fsl,P1010RDB")) return 1; - if (of_flat_dt_is_compatible(root, "fsl,P1010RDB-PB")) + if (of_machine_is_compatible("fsl,P1010RDB-PB")) return 1; return 0; } diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c index 371df822e88e..63568d68c76f 100644 --- a/arch/powerpc/platforms/85xx/p1022_ds.c +++ b/arch/powerpc/platforms/85xx/p1022_ds.c @@ -555,9 +555,7 @@ machine_arch_initcall(p1022_ds, swiotlb_setup_bus_notifier); */ static int __init p1022_ds_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "fsl,p1022ds"); + return of_machine_is_compatible("fsl,p1022ds"); } define_machine(p1022_ds) { diff --git a/arch/powerpc/platforms/85xx/p1022_rdk.c b/arch/powerpc/platforms/85xx/p1022_rdk.c index 5087becaa8bc..2f2943600301 100644 --- a/arch/powerpc/platforms/85xx/p1022_rdk.c +++ b/arch/powerpc/platforms/85xx/p1022_rdk.c @@ -135,9 +135,7 @@ machine_arch_initcall(p1022_rdk, swiotlb_setup_bus_notifier); */ static int __init p1022_rdk_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "fsl,p1022rdk"); + return of_machine_is_compatible("fsl,p1022rdk"); } define_machine(p1022_rdk) { diff --git a/arch/powerpc/platforms/85xx/p1023_rdb.c b/arch/powerpc/platforms/85xx/p1023_rdb.c index d5b7509825de..40d8de57c341 100644 --- a/arch/powerpc/platforms/85xx/p1023_rdb.c +++ b/arch/powerpc/platforms/85xx/p1023_rdb.c @@ -100,9 +100,7 @@ static void __init mpc85xx_rdb_pic_init(void) static int __init p1023_rdb_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "fsl,P1023RDB"); + return of_machine_is_compatible("fsl,P1023RDB"); } diff --git a/arch/powerpc/platforms/85xx/ppa8548.c b/arch/powerpc/platforms/85xx/ppa8548.c index 12019f17f297..2410167b290a 100644 --- a/arch/powerpc/platforms/85xx/ppa8548.c +++ b/arch/powerpc/platforms/85xx/ppa8548.c @@ -81,9 +81,7 @@ machine_device_initcall(ppa8548, declare_of_platform_devices); */ static int __init ppa8548_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "ppa8548"); + return of_machine_is_compatible("ppa8548"); } define_machine(ppa8548) { diff --git a/arch/powerpc/platforms/85xx/qemu_e500.c b/arch/powerpc/platforms/85xx/qemu_e500.c index 8ad2fe6f200a..50d745809809 100644 --- a/arch/powerpc/platforms/85xx/qemu_e500.c +++ b/arch/powerpc/platforms/85xx/qemu_e500.c @@ -62,9 +62,7 @@ static void __init qemu_e500_setup_arch(void) */ static int __init qemu_e500_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return !!of_flat_dt_is_compatible(root, "fsl,qemu-e500"); + return !!of_machine_is_compatible("fsl,qemu-e500"); } machine_arch_initcall(qemu_e500, mpc85xx_common_publish_devices); diff --git a/arch/powerpc/platforms/85xx/sbc8548.c b/arch/powerpc/platforms/85xx/sbc8548.c index b07214666d65..62b6c45a5a9b 100644 --- a/arch/powerpc/platforms/85xx/sbc8548.c +++ b/arch/powerpc/platforms/85xx/sbc8548.c @@ -120,9 +120,7 @@ machine_arch_initcall(sbc8548, mpc85xx_common_publish_devices); */ static int __init sbc8548_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "SBC8548"); + return of_machine_is_compatible("SBC8548"); } define_machine(sbc8548) { diff --git a/arch/powerpc/platforms/85xx/socrates.c b/arch/powerpc/platforms/85xx/socrates.c index ae368e0e1076..cd255acde2e2 100644 --- a/arch/powerpc/platforms/85xx/socrates.c +++ b/arch/powerpc/platforms/85xx/socrates.c @@ -79,9 +79,7 @@ machine_arch_initcall(socrates, mpc85xx_common_publish_devices); */ static int __init socrates_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (of_flat_dt_is_compatible(root, "abb,socrates")) + if (of_machine_is_compatible("abb,socrates")) return 1; return 0; diff --git a/arch/powerpc/platforms/85xx/stx_gp3.c b/arch/powerpc/platforms/85xx/stx_gp3.c index 6f4939b6309e..91b824c4dc08 100644 --- a/arch/powerpc/platforms/85xx/stx_gp3.c +++ b/arch/powerpc/platforms/85xx/stx_gp3.c @@ -93,9 +93,7 @@ machine_arch_initcall(stx_gp3, mpc85xx_common_publish_devices); */ static int __init stx_gp3_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "stx,gp3-8560"); + return of_machine_is_compatible("stx,gp3-8560"); } define_machine(stx_gp3) { diff --git a/arch/powerpc/platforms/85xx/tqm85xx.c b/arch/powerpc/platforms/85xx/tqm85xx.c index ec0b7272fae2..b7c54454d611 100644 --- a/arch/powerpc/platforms/85xx/tqm85xx.c +++ b/arch/powerpc/platforms/85xx/tqm85xx.c @@ -122,7 +122,7 @@ static const char * const board[] __initconst = { */ static int __init tqm85xx_probe(void) { - return of_flat_dt_match(of_get_flat_dt_root(), board); + return of_device_compatible_match(of_root, board); } define_machine(tqm85xx) { diff --git a/arch/powerpc/platforms/85xx/twr_p102x.c b/arch/powerpc/platforms/85xx/twr_p102x.c index 71bc255b4324..1bc02a87f597 100644 --- a/arch/powerpc/platforms/85xx/twr_p102x.c +++ b/arch/powerpc/platforms/85xx/twr_p102x.c @@ -128,9 +128,7 @@ machine_arch_initcall(twr_p1025, mpc85xx_common_publish_devices); static int __init twr_p1025_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "fsl,TWR-P1025"); + return of_machine_is_compatible("fsl,TWR-P1025"); } define_machine(twr_p1025) { diff --git a/arch/powerpc/platforms/85xx/xes_mpc85xx.c b/arch/powerpc/platforms/85xx/xes_mpc85xx.c index 1a9c1085855f..cf0c70ff026e 100644 --- a/arch/powerpc/platforms/85xx/xes_mpc85xx.c +++ b/arch/powerpc/platforms/85xx/xes_mpc85xx.c @@ -144,23 +144,17 @@ machine_arch_initcall(xes_mpc8540, mpc85xx_common_publish_devices); */ static int __init xes_mpc8572_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "xes,MPC8572"); + return of_machine_is_compatible("xes,MPC8572"); } static int __init xes_mpc8548_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "xes,MPC8548"); + return of_machine_is_compatible("xes,MPC8548"); } static int __init xes_mpc8540_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "xes,MPC8540"); + return of_machine_is_compatible("xes,MPC8540"); } define_machine(xes_mpc8572) { diff --git a/arch/powerpc/platforms/86xx/gef_ppc9a.c b/arch/powerpc/platforms/86xx/gef_ppc9a.c index 8e63b752712c..ef684afb63c6 100644 --- a/arch/powerpc/platforms/86xx/gef_ppc9a.c +++ b/arch/powerpc/platforms/86xx/gef_ppc9a.c @@ -189,9 +189,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB, */ static int __init gef_ppc9a_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (of_flat_dt_is_compatible(root, "gef,ppc9a")) + if (of_machine_is_compatible("gef,ppc9a")) return 1; return 0; diff --git a/arch/powerpc/platforms/86xx/gef_sbc310.c b/arch/powerpc/platforms/86xx/gef_sbc310.c index 0e0be94f551f..67dd0c231646 100644 --- a/arch/powerpc/platforms/86xx/gef_sbc310.c +++ b/arch/powerpc/platforms/86xx/gef_sbc310.c @@ -176,9 +176,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB, */ static int __init gef_sbc310_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (of_flat_dt_is_compatible(root, "gef,sbc310")) + if (of_machine_is_compatible("gef,sbc310")) return 1; return 0; diff --git a/arch/powerpc/platforms/86xx/gef_sbc610.c b/arch/powerpc/platforms/86xx/gef_sbc610.c index e8292b492d7e..805026976cac 100644 --- a/arch/powerpc/platforms/86xx/gef_sbc610.c +++ b/arch/powerpc/platforms/86xx/gef_sbc610.c @@ -166,9 +166,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB, */ static int __init gef_sbc610_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (of_flat_dt_is_compatible(root, "gef,sbc610")) + if (of_machine_is_compatible("gef,sbc610")) return 1; return 0; diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c index 957473e5c8e5..fef0582eddf1 100644 --- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c +++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c @@ -319,9 +319,7 @@ static void __init mpc86xx_hpcd_setup_arch(void) */ static int __init mpc86xx_hpcd_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (of_flat_dt_is_compatible(root, "fsl,MPC8610HPCD")) + if (of_machine_is_compatible("fsl,MPC8610HPCD")) return 1; /* Looks good */ return 0; diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c index e5084811b9c6..5ae42a037065 100644 --- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c +++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c @@ -96,13 +96,11 @@ mpc86xx_hpcn_show_cpuinfo(struct seq_file *m) */ static int __init mpc86xx_hpcn_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (of_flat_dt_is_compatible(root, "fsl,mpc8641hpcn")) + if (of_machine_is_compatible("fsl,mpc8641hpcn")) return 1; /* Looks good */ /* Be nice and don't give silent boot death. Delete this in 2.6.27 */ - if (of_flat_dt_is_compatible(root, "mpc86xx")) { + if (of_machine_is_compatible("mpc86xx")) { pr_warning("WARNING: your dts/dtb is old. You must update before the next kernel release\n"); return 1; } diff --git a/arch/powerpc/platforms/86xx/sbc8641d.c b/arch/powerpc/platforms/86xx/sbc8641d.c index 2a9cf278c12a..52af5735742e 100644 --- a/arch/powerpc/platforms/86xx/sbc8641d.c +++ b/arch/powerpc/platforms/86xx/sbc8641d.c @@ -67,9 +67,7 @@ sbc8641_show_cpuinfo(struct seq_file *m) */ static int __init sbc8641_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (of_flat_dt_is_compatible(root, "wind,sbc8641")) + if (of_machine_is_compatible("wind,sbc8641")) return 1; /* Looks good */ return 0; diff --git a/arch/powerpc/platforms/8xx/adder875.c b/arch/powerpc/platforms/8xx/adder875.c index 61cae4c1edb8..333dece79394 100644 --- a/arch/powerpc/platforms/8xx/adder875.c +++ b/arch/powerpc/platforms/8xx/adder875.c @@ -88,8 +88,7 @@ static void __init adder875_setup(void) static int __init adder875_probe(void) { - unsigned long root = of_get_flat_dt_root(); - return of_flat_dt_is_compatible(root, "analogue-and-micro,adder875"); + return of_machine_is_compatible("analogue-and-micro,adder875"); } static const struct of_device_id of_bus_ids[] __initconst = { diff --git a/arch/powerpc/platforms/8xx/ep88xc.c b/arch/powerpc/platforms/8xx/ep88xc.c index 2bedeb7d5f8f..cd0d90f1fb1c 100644 --- a/arch/powerpc/platforms/8xx/ep88xc.c +++ b/arch/powerpc/platforms/8xx/ep88xc.c @@ -143,8 +143,7 @@ static void __init ep88xc_setup_arch(void) static int __init ep88xc_probe(void) { - unsigned long root = of_get_flat_dt_root(); - return of_flat_dt_is_compatible(root, "fsl,ep88xc"); + return of_machine_is_compatible("fsl,ep88xc"); } static const struct of_device_id of_bus_ids[] __initconst = { diff --git a/arch/powerpc/platforms/8xx/mpc86xads_setup.c b/arch/powerpc/platforms/8xx/mpc86xads_setup.c index 78180c5e73ff..8d02f5ff4481 100644 --- a/arch/powerpc/platforms/8xx/mpc86xads_setup.c +++ b/arch/powerpc/platforms/8xx/mpc86xads_setup.c @@ -118,8 +118,7 @@ static void __init mpc86xads_setup_arch(void) static int __init mpc86xads_probe(void) { - unsigned long root = of_get_flat_dt_root(); - return of_flat_dt_is_compatible(root, "fsl,mpc866ads"); + return of_machine_is_compatible("fsl,mpc866ads"); } static const struct of_device_id of_bus_ids[] __initconst = { diff --git a/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/arch/powerpc/platforms/8xx/mpc885ads_setup.c index 4d62bf9dc789..e821a42d5816 100644 --- a/arch/powerpc/platforms/8xx/mpc885ads_setup.c +++ b/arch/powerpc/platforms/8xx/mpc885ads_setup.c @@ -193,8 +193,7 @@ static void __init mpc885ads_setup_arch(void) static int __init mpc885ads_probe(void) { - unsigned long root = of_get_flat_dt_root(); - return of_flat_dt_is_compatible(root, "fsl,mpc885ads"); + return of_machine_is_compatible("fsl,mpc885ads"); } static const struct of_device_id of_bus_ids[] __initconst = { diff --git a/arch/powerpc/platforms/8xx/tqm8xx_setup.c b/arch/powerpc/platforms/8xx/tqm8xx_setup.c index bee47a2b23e6..4cea8b1afa44 100644 --- a/arch/powerpc/platforms/8xx/tqm8xx_setup.c +++ b/arch/powerpc/platforms/8xx/tqm8xx_setup.c @@ -119,9 +119,7 @@ static void __init tqm8xx_setup_arch(void) static int __init tqm8xx_probe(void) { - unsigned long node = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(node, "tqc,tqm8xx"); + return of_machine_is_compatible("tqc,tqm8xx"); } static const struct of_device_id of_bus_ids[] __initconst = { diff --git a/arch/powerpc/platforms/amigaone/setup.c b/arch/powerpc/platforms/amigaone/setup.c index 3e12d8789252..45cb9821173c 100644 --- a/arch/powerpc/platforms/amigaone/setup.c +++ b/arch/powerpc/platforms/amigaone/setup.c @@ -143,9 +143,7 @@ void __noreturn amigaone_restart(char *cmd) static int __init amigaone_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (of_flat_dt_is_compatible(root, "eyetech,amigaone")) { + if (of_machine_is_compatible("eyetech,amigaone")) { /* * Coherent memory access cause complete system lockup! Thus * disable this CPU feature, even if the CPU needs it. diff --git a/arch/powerpc/platforms/embedded6xx/c2k.c b/arch/powerpc/platforms/embedded6xx/c2k.c index 782066245bb5..7fef40edf044 100644 --- a/arch/powerpc/platforms/embedded6xx/c2k.c +++ b/arch/powerpc/platforms/embedded6xx/c2k.c @@ -123,9 +123,7 @@ void c2k_show_cpuinfo(struct seq_file *m) */ static int __init c2k_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (!of_flat_dt_is_compatible(root, "GEFanuc,C2K")) + if (!of_machine_is_compatible("GEFanuc,C2K")) return 0; printk(KERN_INFO "Detected a GEFanuc C2K board\n"); diff --git a/arch/powerpc/platforms/embedded6xx/gamecube.c b/arch/powerpc/platforms/embedded6xx/gamecube.c index b17705c3f7a4..f5a837fa8951 100644 --- a/arch/powerpc/platforms/embedded6xx/gamecube.c +++ b/arch/powerpc/platforms/embedded6xx/gamecube.c @@ -61,10 +61,7 @@ static void __init gamecube_init_early(void) static int __init gamecube_probe(void) { - unsigned long dt_root; - - dt_root = of_get_flat_dt_root(); - if (!of_flat_dt_is_compatible(dt_root, "nintendo,gamecube")) + if (!of_machine_is_compatible("nintendo,gamecube")) return 0; pm_power_off = gamecube_power_off; diff --git a/arch/powerpc/platforms/embedded6xx/holly.c b/arch/powerpc/platforms/embedded6xx/holly.c index 8b6e76100895..dafba1057a47 100644 --- a/arch/powerpc/platforms/embedded6xx/holly.c +++ b/arch/powerpc/platforms/embedded6xx/holly.c @@ -250,9 +250,7 @@ void holly_halt(void) */ static int __init holly_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (!of_flat_dt_is_compatible(root, "ibm,holly")) + if (!of_machine_is_compatible("ibm,holly")) return 0; return 1; } diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c index 4c5089f05c7f..f29cf29b11f8 100644 --- a/arch/powerpc/platforms/embedded6xx/linkstation.c +++ b/arch/powerpc/platforms/embedded6xx/linkstation.c @@ -141,11 +141,7 @@ static void linkstation_show_cpuinfo(struct seq_file *m) static int __init linkstation_probe(void) { - unsigned long root; - - root = of_get_flat_dt_root(); - - if (!of_flat_dt_is_compatible(root, "linkstation")) + if (!of_machine_is_compatible("linkstation")) return 0; pm_power_off = linkstation_power_off; diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c index 3eda5df6281a..80804f9916ee 100644 --- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c +++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c @@ -161,9 +161,7 @@ static void __noreturn mpc7448_hpc2_restart(char *cmd) */ static int __init mpc7448_hpc2_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - if (!of_flat_dt_is_compatible(root, "mpc74xx")) + if (!of_machine_is_compatible("mpc74xx")) return 0; return 1; } diff --git a/arch/powerpc/platforms/embedded6xx/mvme5100.c b/arch/powerpc/platforms/embedded6xx/mvme5100.c index 1382e1f27518..ed7321d6772e 100644 --- a/arch/powerpc/platforms/embedded6xx/mvme5100.c +++ b/arch/powerpc/platforms/embedded6xx/mvme5100.c @@ -194,9 +194,7 @@ static void __noreturn mvme5100_restart(char *cmd) */ static int __init mvme5100_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "MVME5100"); + return of_machine_is_compatible("MVME5100"); } static int __init probe_of_platform_devices(void) diff --git a/arch/powerpc/platforms/embedded6xx/storcenter.c b/arch/powerpc/platforms/embedded6xx/storcenter.c index 4596cba8c827..471a50bcd074 100644 --- a/arch/powerpc/platforms/embedded6xx/storcenter.c +++ b/arch/powerpc/platforms/embedded6xx/storcenter.c @@ -109,9 +109,7 @@ static void __noreturn storcenter_restart(char *cmd) static int __init storcenter_probe(void) { - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "iomega,storcenter"); + return of_machine_is_compatible("iomega,storcenter"); } define_machine(storcenter){ diff --git a/arch/powerpc/platforms/embedded6xx/wii.c b/arch/powerpc/platforms/embedded6xx/wii.c index ebaecb88df26..fe3e769db263 100644 --- a/arch/powerpc/platforms/embedded6xx/wii.c +++ b/arch/powerpc/platforms/embedded6xx/wii.c @@ -205,10 +205,7 @@ static void __init wii_pic_probe(void) static int __init wii_probe(void) { - unsigned long dt_root; - - dt_root = of_get_flat_dt_root(); - if (!of_flat_dt_is_compatible(dt_root, "nintendo,wii")) + if (!of_machine_is_compatible("nintendo,wii")) return 0; pm_power_off = wii_power_off; diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 0872f9837cf5..60ca40ac3519 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -590,17 +590,9 @@ console_initcall(check_pmac_serial_console); */ static int __init pmac_probe(void) { -#ifdef CONFIG_PPC32 - unsigned long root = of_get_flat_dt_root(); - - if (!of_flat_dt_is_compatible(root, "Power Macintosh") && - !of_flat_dt_is_compatible(root, "MacRISC")) - return 0; -#else if (!of_machine_is_compatible("Power Macintosh") && !of_machine_is_compatible("MacRISC")) return 0; -#endif #ifdef CONFIG_PPC32 /* isa_io_base gets set in pmac_pci_init */ -- cgit v1.2.3 From f2d576948d6cec16e4aae201d738c4f22039a551 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 5 Jul 2016 15:04:06 +1000 Subject: powerpc: Get rid of ppc_md.init_early() It is now called right after platform probe, so the probe function can just do the job. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/machdep.h | 1 - arch/powerpc/kernel/setup_32.c | 3 --- arch/powerpc/kernel/setup_64.c | 8 -------- arch/powerpc/platforms/512x/mpc5121_ads.c | 8 ++++++-- arch/powerpc/platforms/512x/mpc512x_generic.c | 8 ++++++-- arch/powerpc/platforms/512x/pdm360ng.c | 8 ++++++-- arch/powerpc/platforms/chrp/setup.c | 5 +++-- arch/powerpc/platforms/embedded6xx/c2k.c | 4 +++- arch/powerpc/platforms/embedded6xx/gamecube.c | 8 ++------ arch/powerpc/platforms/embedded6xx/wii.c | 8 ++------ arch/powerpc/platforms/maple/setup.c | 15 ++------------- arch/powerpc/platforms/pasemi/setup.c | 8 ++------ arch/powerpc/platforms/powermac/setup.c | 5 +++-- arch/powerpc/platforms/powernv/setup.c | 5 +++-- arch/powerpc/platforms/pseries/setup.c | 9 +++++---- 15 files changed, 43 insertions(+), 60 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index 5b2edf5ba114..76f5398e7152 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h @@ -53,7 +53,6 @@ struct machdep_calls { int (*probe)(void); void (*setup_arch)(void); /* Optional, may be NULL */ - void (*init_early)(void); /* Optional, may be NULL. */ void (*show_cpuinfo)(struct seq_file *m); void (*show_percpuinfo)(struct seq_file *m, int i); diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index e7bb4e76896a..22347e87c354 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -263,9 +263,6 @@ void __init setup_arch(char **cmdline_p) setup_power_save(); - if (ppc_md.init_early) - ppc_md.init_early(); - find_legacy_serial_ports(); smp_setup_cpu_maps(); diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 883d527899a7..8b9768a97387 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -511,14 +511,6 @@ void __init setup_system(void) /* Probe the machine type */ probe_machine(); - /* - * Do some platform specific early initializations, that includes - * setting up the hash table pointers. It also sets up some interrupt-mapping - * related options that will be used by finish_device_tree() - */ - if (ppc_md.init_early) - ppc_md.init_early(); - /* * We can discover serial ports now since the above did setup the * hash table management for us, thus ioremap works. We do that early diff --git a/arch/powerpc/platforms/512x/mpc5121_ads.c b/arch/powerpc/platforms/512x/mpc5121_ads.c index 4e03f04e3a1f..f65d5033cdb0 100644 --- a/arch/powerpc/platforms/512x/mpc5121_ads.c +++ b/arch/powerpc/platforms/512x/mpc5121_ads.c @@ -57,7 +57,12 @@ static void __init mpc5121_ads_init_IRQ(void) */ static int __init mpc5121_ads_probe(void) { - return of_machine_is_compatible("fsl,mpc5121ads"); + if (!of_machine_is_compatible("fsl,mpc5121ads")) + return 0; + + mpc512x_init_early(); + + return 1; } define_machine(mpc5121_ads) { @@ -65,7 +70,6 @@ define_machine(mpc5121_ads) { .probe = mpc5121_ads_probe, .setup_arch = mpc5121_ads_setup_arch, .init = mpc512x_init, - .init_early = mpc512x_init_early, .init_IRQ = mpc5121_ads_init_IRQ, .get_irq = ipic_get_irq, .calibrate_decr = generic_calibrate_decr, diff --git a/arch/powerpc/platforms/512x/mpc512x_generic.c b/arch/powerpc/platforms/512x/mpc512x_generic.c index 87eba1753088..bf884d3075e4 100644 --- a/arch/powerpc/platforms/512x/mpc512x_generic.c +++ b/arch/powerpc/platforms/512x/mpc512x_generic.c @@ -38,14 +38,18 @@ static const char * const board[] __initconst = { */ static int __init mpc512x_generic_probe(void) { - return of_device_compatible_match(of_root, board); + if (!of_device_compatible_match(of_root, board)) + return 0; + + mpc512x_init_early(); + + return 1; } define_machine(mpc512x_generic) { .name = "MPC512x generic", .probe = mpc512x_generic_probe, .init = mpc512x_init, - .init_early = mpc512x_init_early, .setup_arch = mpc512x_setup_arch, .init_IRQ = mpc512x_init_IRQ, .get_irq = ipic_get_irq, diff --git a/arch/powerpc/platforms/512x/pdm360ng.c b/arch/powerpc/platforms/512x/pdm360ng.c index f9cad19a33ab..dc81f05e0bce 100644 --- a/arch/powerpc/platforms/512x/pdm360ng.c +++ b/arch/powerpc/platforms/512x/pdm360ng.c @@ -113,7 +113,12 @@ void __init pdm360ng_init(void) static int __init pdm360ng_probe(void) { - return of_machine_is_compatible("ifm,pdm360ng"); + if (!of_machine_is_compatible("ifm,pdm360ng")) + return 0; + + mpc512x_init_early(); + + return 1; } define_machine(pdm360ng) { @@ -121,7 +126,6 @@ define_machine(pdm360ng) { .probe = pdm360ng_probe, .setup_arch = mpc512x_setup_arch, .init = pdm360ng_init, - .init_early = mpc512x_init_early, .init_IRQ = mpc512x_init_IRQ, .get_irq = ipic_get_irq, .calibrate_decr = generic_calibrate_decr, diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index c55002f01dc1..bfb300633dfe 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -253,7 +253,7 @@ static void __noreturn briq_restart(char *cmd) * But unfortunately, the firmware does not connect /chosen/{stdin,stdout} * the the built-in serial node. Instead, a /failsafe node is created. */ -static __init void chrp_init_early(void) +static __init void chrp_init(void) { struct device_node *node; const char *property; @@ -587,6 +587,8 @@ static int __init chrp_probe(void) pm_power_off = rtas_power_off; + chrp_init(); + return 1; } @@ -595,7 +597,6 @@ define_machine(chrp) { .probe = chrp_probe, .setup_arch = chrp_setup_arch, .init = chrp_init2, - .init_early = chrp_init_early, .show_cpuinfo = chrp_show_cpuinfo, .init_IRQ = chrp_init_IRQ, .restart = rtas_restart, diff --git a/arch/powerpc/platforms/embedded6xx/c2k.c b/arch/powerpc/platforms/embedded6xx/c2k.c index 7fef40edf044..d19e4e759597 100644 --- a/arch/powerpc/platforms/embedded6xx/c2k.c +++ b/arch/powerpc/platforms/embedded6xx/c2k.c @@ -130,6 +130,9 @@ static int __init c2k_probe(void) _set_L2CR(0); _set_L2CR(L2CR_L2E | L2CR_L2PE | L2CR_L2I); + + mv64x60_init_early(); + return 1; } @@ -137,7 +140,6 @@ define_machine(c2k) { .name = "C2K", .probe = c2k_probe, .setup_arch = c2k_setup_arch, - .init_early = mv64x60_init_early, .show_cpuinfo = c2k_show_cpuinfo, .init_IRQ = mv64x60_init_irq, .get_irq = mv64x60_get_irq, diff --git a/arch/powerpc/platforms/embedded6xx/gamecube.c b/arch/powerpc/platforms/embedded6xx/gamecube.c index f5a837fa8951..36789cec957c 100644 --- a/arch/powerpc/platforms/embedded6xx/gamecube.c +++ b/arch/powerpc/platforms/embedded6xx/gamecube.c @@ -54,11 +54,6 @@ static void __noreturn gamecube_halt(void) gamecube_restart(NULL); } -static void __init gamecube_init_early(void) -{ - ug_udbg_init(); -} - static int __init gamecube_probe(void) { if (!of_machine_is_compatible("nintendo,gamecube")) @@ -66,6 +61,8 @@ static int __init gamecube_probe(void) pm_power_off = gamecube_power_off; + ug_udbg_init(); + return 1; } @@ -77,7 +74,6 @@ static void gamecube_shutdown(void) define_machine(gamecube) { .name = "gamecube", .probe = gamecube_probe, - .init_early = gamecube_init_early, .restart = gamecube_restart, .halt = gamecube_halt, .init_IRQ = flipper_pic_probe, diff --git a/arch/powerpc/platforms/embedded6xx/wii.c b/arch/powerpc/platforms/embedded6xx/wii.c index fe3e769db263..3fd683e40bc9 100644 --- a/arch/powerpc/platforms/embedded6xx/wii.c +++ b/arch/powerpc/platforms/embedded6xx/wii.c @@ -192,11 +192,6 @@ static void __noreturn wii_halt(void) wii_spin(); } -static void __init wii_init_early(void) -{ - ug_udbg_init(); -} - static void __init wii_pic_probe(void) { flipper_pic_probe(); @@ -210,6 +205,8 @@ static int __init wii_probe(void) pm_power_off = wii_power_off; + ug_udbg_init(); + return 1; } @@ -222,7 +219,6 @@ static void wii_shutdown(void) define_machine(wii) { .name = "wii", .probe = wii_probe, - .init_early = wii_init_early, .setup_arch = wii_setup_arch, .restart = wii_restart, .halt = wii_halt, diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index d3d44cba661b..3c30c7a4534d 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c @@ -198,18 +198,6 @@ void __init maple_setup_arch(void) mmio_nvram_init(); } -/* - * Early initialization. - */ -static void __init maple_init_early(void) -{ - DBG(" -> maple_init_early\n"); - - iommu_init_early_dart(&maple_pci_controller_ops); - - DBG(" <- maple_init_early\n"); -} - /* * This is almost identical to pSeries and CHRP. We need to make that * code generic at one point, with appropriate bits in the device-tree to @@ -306,6 +294,8 @@ static int __init maple_probe(void) pm_power_off = maple_power_off; + iommu_init_early_dart(&maple_pci_controller_ops); + return 1; } @@ -313,7 +303,6 @@ define_machine(maple) { .name = "Maple", .probe = maple_probe, .setup_arch = maple_setup_arch, - .init_early = maple_init_early, .init_IRQ = maple_init_IRQ, .pci_irq_fixup = maple_pci_irq_fixup, .pci_get_legacy_ide_irq = maple_pci_get_legacy_ide_irq, diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index ec810ddb10ee..e86c1bd08f1f 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c @@ -339,11 +339,6 @@ out: return !!(srr1 & 0x2); } -static void __init pas_init_early(void) -{ - iommu_init_early_pasemi(); -} - #ifdef CONFIG_PCMCIA static int pcmcia_notify(struct notifier_block *nb, unsigned long action, void *data) @@ -424,6 +419,8 @@ static int __init pas_probe(void) !of_machine_is_compatible("pasemi,pwrficient")) return 0; + iommu_init_early_pasemi(); + return 1; } @@ -431,7 +428,6 @@ define_machine(pasemi) { .name = "PA Semi PWRficient", .probe = pas_probe, .setup_arch = pas_setup_arch, - .init_early = pas_init_early, .init_IRQ = pas_init_IRQ, .get_irq = mpic_get_irq, .restart = pas_restart, diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 60ca40ac3519..3de4a7c85140 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -452,7 +452,7 @@ pmac_halt(void) /* * Early initialization. */ -static void __init pmac_init_early(void) +static void __init pmac_init(void) { /* Enable early btext debug if requested */ if (strstr(boot_command_line, "btextdbg")) { @@ -603,6 +603,8 @@ static int __init pmac_probe(void) pm_power_off = pmac_power_off; + pmac_init(); + return 1; } @@ -610,7 +612,6 @@ define_machine(powermac) { .name = "PowerMac", .probe = pmac_probe, .setup_arch = pmac_setup_arch, - .init_early = pmac_init_early, .show_cpuinfo = pmac_show_cpuinfo, .init_IRQ = pmac_pic_init, .get_irq = NULL, /* changed later */ diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c index 8865efa54e51..efe8b6bb168b 100644 --- a/arch/powerpc/platforms/powernv/setup.c +++ b/arch/powerpc/platforms/powernv/setup.c @@ -58,7 +58,7 @@ static void __init pnv_setup_arch(void) /* XXX PMCS */ } -static void __init pnv_init_early(void) +static void __init pnv_init(void) { /* * Initialize the LPC bus now so that legacy serial @@ -276,6 +276,8 @@ static int __init pnv_probe(void) pr_debug("PowerNV detected !\n"); + pnv_init(); + return 1; } @@ -301,7 +303,6 @@ static unsigned long pnv_get_proc_freq(unsigned int cpu) define_machine(powernv) { .name = "PowerNV", .probe = pnv_probe, - .init_early = pnv_init_early, .setup_arch = pnv_setup_arch, .init_IRQ = pnv_init_IRQ, .show_cpuinfo = pnv_show_cpuinfo, diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 6988b9dc3d3b..4ffcaa6f8670 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -620,9 +620,9 @@ static void pSeries_cmo_feature_init(void) /* * Early initialization. Relocation is on but do not reference unbolted pages */ -static void __init pSeries_init_early(void) +static void __init pseries_init(void) { - pr_debug(" -> pSeries_init_early()\n"); + pr_debug(" -> pseries_init()\n"); #ifdef CONFIG_HVC_CONSOLE if (firmware_has_feature(FW_FEATURE_LPAR)) @@ -639,7 +639,7 @@ static void __init pSeries_init_early(void) pSeries_cmo_feature_init(); iommu_init_early_pSeries(); - pr_debug(" <- pSeries_init_early()\n"); + pr_debug(" <- pseries_init()\n"); } /** @@ -691,6 +691,8 @@ static int __init pSeries_probe(void) pr_debug("Machine is%s LPAR !\n", (powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not"); + pseries_init(); + return 1; } @@ -709,7 +711,6 @@ define_machine(pseries) { .name = "pSeries", .probe = pSeries_probe, .setup_arch = pSeries_setup_arch, - .init_early = pSeries_init_early, .init_IRQ = pseries_init_irq, .show_cpuinfo = pSeries_show_cpuinfo, .log_error = pSeries_log_error, -- cgit v1.2.3 From 802a345183c0308aa64969cca62c23961bf86a44 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Wed, 20 Jul 2016 14:26:51 +1000 Subject: powerpc/powernv/ioda: Fix endianness when reading TCEs The iommu_table_ops::exchange() callback writes new TCE to the table and returns old value and permission mask. The old TCE value is correctly converted from BE to CPU endian; however permission mask was calculated from BE value and therefore always returned DMA_NONE which could cause memory leak on LE systems using VFIO SPAPR TCE IOMMU v1 driver. This fixes pnv_tce_xchg() to have @oldtce a CPU endian. Fixes: 05c6cfb9dce0 ("powerpc/iommu/powernv: Release replaced TCE") Signed-off-by: Alexey Kardashevskiy Reviewed-by: David Gibson Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index 4617ea221881..6701dd5ded20 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c @@ -737,8 +737,8 @@ int pnv_tce_xchg(struct iommu_table *tbl, long index, if (newtce & TCE_PCI_WRITE) newtce |= TCE_PCI_READ; - oldtce = xchg(pnv_tce(tbl, idx), cpu_to_be64(newtce)); - *hpa = be64_to_cpu(oldtce) & ~(TCE_PCI_READ | TCE_PCI_WRITE); + oldtce = be64_to_cpu(xchg(pnv_tce(tbl, idx), cpu_to_be64(newtce))); + *hpa = oldtce & ~(TCE_PCI_READ | TCE_PCI_WRITE); *direction = iommu_tce_direction(oldtce); return 0; -- cgit v1.2.3 From 6364e84e855ae9a0558ac873e3ff50ecb75bb40a Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 26 Jul 2016 10:33:03 +1000 Subject: powerpc/mm: Rename hpte_init_lpar() and move the fallback to a header hpte_init_lpar() is part of the pseries platform, so name it as such. Move the fallback implementation for when PSERIES=n into the header, dropping the weak implementation. The panic() is now handled by the calling code. Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/book3s/64/mmu-hash.h | 7 ++++++- arch/powerpc/mm/hash_utils_64.c | 7 +------ arch/powerpc/platforms/pseries/lpar.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/include/asm/book3s/64/mmu-hash.h b/arch/powerpc/include/asm/book3s/64/mmu-hash.h index b0f4dffe12ae..450b017fdc19 100644 --- a/arch/powerpc/include/asm/book3s/64/mmu-hash.h +++ b/arch/powerpc/include/asm/book3s/64/mmu-hash.h @@ -391,8 +391,13 @@ int htab_remove_mapping(unsigned long vstart, unsigned long vend, extern void add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages); extern void demote_segment_4k(struct mm_struct *mm, unsigned long addr); +#ifdef CONFIG_PPC_PSERIES +void hpte_init_pseries(void); +#else +static inline void hpte_init_pseries(void) { } +#endif + extern void hpte_init_native(void); -extern void hpte_init_lpar(void); extern void hpte_init_beat(void); extern void hpte_init_beat_v3(void); diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 381b5894cc99..1ff11c1bb182 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -885,11 +885,6 @@ static void __init htab_initialize(void) #undef KB #undef MB -void __init __weak hpte_init_lpar(void) -{ - panic("FW_FEATURE_LPAR set but no LPAR support compiled\n"); -} - void __init hash__early_init_mmu(void) { /* @@ -930,7 +925,7 @@ void __init hash__early_init_mmu(void) if (firmware_has_feature(FW_FEATURE_PS3_LV1)) ps3_early_mm_init(); else if (firmware_has_feature(FW_FEATURE_LPAR)) - hpte_init_lpar(); + hpte_init_pseries(); else if IS_ENABLED(CONFIG_PPC_NATIVE) hpte_init_native(); diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 0e91388d0af9..86707e67843f 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -589,7 +589,7 @@ static int __init disable_bulk_remove(char *str) __setup("bulk_remove=", disable_bulk_remove); -void __init hpte_init_lpar(void) +void __init hpte_init_pseries(void) { mmu_hash_ops.hpte_invalidate = pSeries_lpar_hpte_invalidate; mmu_hash_ops.hpte_updatepp = pSeries_lpar_hpte_updatepp; -- cgit v1.2.3