From 213972e9faf8a16b27fee01ae7c7071de5080268 Mon Sep 17 00:00:00 2001 From: d binderman Date: Sat, 6 Feb 2010 02:13:29 +0000 Subject: powerpc/pmac/low_i2c.c: three minor problems Fix minor nits found by cppcheck [./arch/powerpc/platforms/powermac/low_i2c.c:594]: (style) The scope of the variable chans can be reduced [./arch/powerpc/platforms/powermac/low_i2c.c:594]: (style) The scope of the variable i can be reduced [./arch/powerpc/platforms/powermac/low_i2c.c:1260]: (style) Redundant condition. It is safe to deallocate a NULL pointer Signed-off-by: David Binderman Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/powermac/low_i2c.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c index f45331ab97cb..06a137c5b8bb 100644 --- a/arch/powerpc/platforms/powermac/low_i2c.c +++ b/arch/powerpc/platforms/powermac/low_i2c.c @@ -592,7 +592,7 @@ static void __init kw_i2c_probe(void) /* Probe keywest-i2c busses */ for_each_compatible_node(np, "i2c","keywest-i2c") { struct pmac_i2c_host_kw *host; - int multibus, chans, i; + int multibus; /* Found one, init a host structure */ host = kw_i2c_host_init(np); @@ -614,6 +614,8 @@ static void __init kw_i2c_probe(void) * parent type */ if (multibus) { + int chans, i; + parent = of_get_parent(np); if (parent == NULL) continue; @@ -1258,8 +1260,7 @@ static void pmac_i2c_do_end(struct pmf_function *func, void *instdata) if (inst == NULL) return; pmac_i2c_close(inst->bus); - if (inst) - kfree(inst); + kfree(inst); } static int pmac_i2c_do_read(PMF_STD_ARGS, u32 len) -- cgit v1.2.3 From a7df5c5e52a545774c4db1f2adf09ede018ab139 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 2 Apr 2010 02:47:13 +0000 Subject: powerpc/pseries/dlpar: Eliminate use after free dlpar_free_cc_nodes frees its argument, so dlpar_online_cpu should not be called on the same value. Skip over the call to dlpar_online_cpu by jumping directly to out. A simplified version of the semantic patch that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression E,E2; @@ dlpar_free_cc_nodes(E) ... ( E = E2 | * E ) // Signed-off-by: Julia Lawall Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/pseries/dlpar.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index e1682bc168a3..1540a41d1a85 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -433,6 +433,7 @@ static ssize_t dlpar_cpu_probe(const char *buf, size_t count) if (rc) { dlpar_release_drc(drc_index); dlpar_free_cc_nodes(dn); + goto out; } rc = dlpar_online_cpu(dn); -- cgit v1.2.3 From 43caa61f154da85a620965f3f61c2f45366d8dc7 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 10 Mar 2010 11:15:01 +0000 Subject: powerpc/pseries/dlpar: Use kasprintf kasprintf combines kmalloc and sprintf, and takes care of the size calculation itself. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ expression a,flag; expression list args; statement S; @@ a = - \(kmalloc\|kzalloc\)(...,flag) + kasprintf(flag,args) <... when != a if (a == NULL || ...) S ...> - sprintf(a,args); // Signed-off-by: Julia Lawall Acked-by: Nathan Fontenot Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/pseries/dlpar.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index 1540a41d1a85..d71e58584086 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -79,13 +79,12 @@ static struct device_node *dlpar_parse_cc_node(struct cc_workarea *ccwa) * prepend this to the full_name. */ name = (char *)ccwa + ccwa->name_offset; - dn->full_name = kmalloc(strlen(name) + 2, GFP_KERNEL); + dn->full_name = kasprintf(GFP_KERNEL, "/%s", name); if (!dn->full_name) { kfree(dn); return NULL; } - sprintf(dn->full_name, "/%s", name); return dn; } @@ -410,15 +409,13 @@ static ssize_t dlpar_cpu_probe(const char *buf, size_t count) * directory of the device tree. CPUs actually live in the * cpus directory so we need to fixup the full_name. */ - cpu_name = kzalloc(strlen(dn->full_name) + strlen("/cpus") + 1, - GFP_KERNEL); + cpu_name = kasprintf(GFP_KERNEL, "/cpus%s", dn->full_name); if (!cpu_name) { dlpar_free_cc_nodes(dn); rc = -ENOMEM; goto out; } - sprintf(cpu_name, "/cpus%s", dn->full_name); kfree(dn->full_name); dn->full_name = cpu_name; -- cgit v1.2.3 From 8260cf6f40014860cb857f5245194900dd6c9b94 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sun, 28 Feb 2010 00:58:16 +0000 Subject: powerpc/iseries/pci: Use __ratelimit Replace open-coded rate limiting logic with __ratelimit(). Signed-off-by: Akinobu Mita Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@ozlabs.org Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/iseries/pci.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index b841c9a9db87..3fc2e6494b8b 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -584,14 +585,9 @@ static inline struct device_node *xlate_iomm_address( orig_addr = (unsigned long __force)addr; if ((orig_addr < BASE_IO_MEMORY) || (orig_addr >= max_io_memory)) { - static unsigned long last_jiffies; - static int num_printed; + static DEFINE_RATELIMIT_STATE(ratelimit, 60 * HZ, 10); - if (time_after(jiffies, last_jiffies + 60 * HZ)) { - last_jiffies = jiffies; - num_printed = 0; - } - if (num_printed++ < 10) + if (__ratelimit(&ratelimit)) printk(KERN_ERR "iSeries_%s: invalid access at IO address %p\n", func, addr); -- cgit v1.2.3 From e0f278adc29e8986531a51e5ed33db42e34bf952 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Fri, 16 Apr 2010 23:07:24 +0400 Subject: powerpc/85xx/86xx: Fix build w/ CONFIG_PCI=n Currently some MPC85xx and MPC86xx boards fail to build without CONFIG_PCI: arch/powerpc/platforms/fsl_uli1575.c: In function 'quirk_final_uli5249': arch/powerpc/platforms/fsl_uli1575.c:234: error: implicit declaration of function 'pci_bus_for_each_resource' arch/powerpc/platforms/fsl_uli1575.c:234: error: expected ';' before '{' token cc1: warnings being treated as errors arch/powerpc/platforms/fsl_uli1575.c:223: warning: unused variable 'dummy' make[1]: *** [arch/powerpc/platforms/fsl_uli1575.o] Error 1 This patch fixes the issue by appending 'if PCI' condition when selecting FSL_ULI1575 Kconfig symbol. Signed-off-by: Anton Vorontsov Signed-off-by: Kumar Gala --- arch/powerpc/platforms/85xx/Kconfig | 4 ++-- arch/powerpc/platforms/86xx/Kconfig | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index d95121894eb7..3a2ade2e443f 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig @@ -51,7 +51,7 @@ config MPC85xx_DS bool "Freescale MPC85xx DS" select PPC_I8259 select DEFAULT_UIMAGE - select FSL_ULI1575 + select FSL_ULI1575 if PCI select SWIOTLB help This option enables support for the MPC85xx DS (MPC8544 DS) board @@ -60,7 +60,7 @@ config MPC85xx_RDB bool "Freescale MPC85xx RDB" select PPC_I8259 select DEFAULT_UIMAGE - select FSL_ULI1575 + select FSL_ULI1575 if PCI select SWIOTLB help This option enables support for the MPC85xx RDB (P2020 RDB) board diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig index fbe9f3621424..a0b5638c5dc8 100644 --- a/arch/powerpc/platforms/86xx/Kconfig +++ b/arch/powerpc/platforms/86xx/Kconfig @@ -13,7 +13,7 @@ config MPC8641_HPCN bool "Freescale MPC8641 HPCN" select PPC_I8259 select DEFAULT_UIMAGE - select FSL_ULI1575 + select FSL_ULI1575 if PCI select HAS_RAPIDIO select SWIOTLB help @@ -28,7 +28,7 @@ config SBC8641D config MPC8610_HPCD bool "Freescale MPC8610 HPCD" select DEFAULT_UIMAGE - select FSL_ULI1575 + select FSL_ULI1575 if PCI help This option enables support for the MPC8610 HPCD board. -- cgit v1.2.3 From c4b9f9a96eb93994ac42f4ea00bb94b44fa4d500 Mon Sep 17 00:00:00 2001 From: Thomas Weber Date: Sat, 24 Apr 2010 10:44:11 +0200 Subject: Powerpc: wii: Fix typo in comment discontiguous => discontinuous coealesce => coalesce Signed-off-by: Thomas Weber Signed-off-by: Jiri Kosina --- arch/powerpc/platforms/embedded6xx/wii.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/embedded6xx/wii.c b/arch/powerpc/platforms/embedded6xx/wii.c index 57e5b608fa1a..174a04ac4806 100644 --- a/arch/powerpc/platforms/embedded6xx/wii.c +++ b/arch/powerpc/platforms/embedded6xx/wii.c @@ -69,10 +69,10 @@ void __init wii_memory_fixups(void) /* * This is part of a workaround to allow the use of two - * discontiguous RAM ranges on the Wii, even if this is + * discontinuous RAM ranges on the Wii, even if this is * currently unsupported on 32-bit PowerPC Linux. * - * We coealesce the two memory ranges of the Wii into a + * We coalesce the two memory ranges of the Wii into a * single range, then create a reservation for the "hole" * between both ranges. */ -- cgit v1.2.3 From b4a26be9f6f8bb72998e445cc75fc6dc0c29513a Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 6 Apr 2010 15:03:40 +0000 Subject: powerpc/pseries: Flush lazy kernel mappings after unplug operations This ensures that the translations for unmapped IO mappings or unmapped memory are properly removed from the MMU hash table before such an unplug. Without this, the hypervisor refuses the unplug operations due to those resources still being mapped by the partition. Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/pseries/hotplug-memory.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index 9b21ee68ea50..01e7b5bb3c1d 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -54,6 +55,12 @@ static int pseries_remove_lmb(unsigned long base, unsigned int lmb_size) */ start = (unsigned long)__va(base); ret = remove_section_mapping(start, start + lmb_size); + + /* Ensure all vmalloc mappings are flushed in case they also + * hit that section of memory + */ + vm_unmap_aliases(); + return ret; } -- cgit v1.2.3 From e7f75ad01d590243904c2d95ab47e6b2e9ef6dad Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Fri, 5 Mar 2010 10:43:12 +0000 Subject: powerpc/47x: Base ppc476 support This patch adds the base support for the 476 processor. The code was primarily written by Ben Herrenschmidt and Torez Smith, but I've been maintaining it for a while. The goal is to have a single binary that will run on 44x and 47x, but we still have some details to work out. The biggest is that the L1 cache line size differs on the two platforms, but it's currently a compile-time option. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Torez Smith Signed-off-by: Dave Kleikamp Signed-off-by: Josh Boyer --- arch/powerpc/platforms/44x/Kconfig | 9 +++++++++ arch/powerpc/platforms/Kconfig.cputype | 5 +++-- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig index 7486bffd3ebb..9365e530ac5a 100644 --- a/arch/powerpc/platforms/44x/Kconfig +++ b/arch/powerpc/platforms/44x/Kconfig @@ -1,3 +1,12 @@ +config PPC_47x + bool "Support for 47x variant" + depends on 44x + default n + select MPIC + help + This option enables support for the 47x family of processors and is + not currently compatible with other 44x or 46x varients + config BAMBOO bool "Bamboo" depends on 44x diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index a8aae0b54579..d361f8119b1e 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype @@ -43,7 +43,7 @@ config 40x select PPC_PCI_CHOICE config 44x - bool "AMCC 44x" + bool "AMCC 44x, 46x or 47x" select PPC_DCR_NATIVE select PPC_UDBG_16550 select 4xx_SOC @@ -294,7 +294,7 @@ config PPC_PERF_CTRS This enables the powerpc-specific perf_event back-end. config SMP - depends on PPC_BOOK3S || PPC_BOOK3E || FSL_BOOKE + depends on PPC_BOOK3S || PPC_BOOK3E || FSL_BOOKE || PPC_47x bool "Symmetric multi-processing support" ---help--- This enables support for systems with more than one CPU. If you have @@ -322,6 +322,7 @@ config NR_CPUS config NOT_COHERENT_CACHE bool depends on 4xx || 8xx || E200 || PPC_MPC512x || GAMECUBE_COMMON + default n if PPC_47x default y config CHECK_CACHE_COHERENCY -- cgit v1.2.3 From b4e8c8dd8456c1d3685fb5b715c9795d250f500e Mon Sep 17 00:00:00 2001 From: Torez Smith Date: Fri, 5 Mar 2010 10:45:54 +0000 Subject: powerpc/4xx: Simple platform for the ISS 4xx simulator This is a trivial 4xx plaform that uses the new simple bsp from Josh and is handy to use in simulators such as ISS or even Mambo who don't properly implement most of the actual devices in the SoC but really only the core. Signed-off-by: Torez Smith Signed-off-by: Dave Kleikamp Signed-off-by: Josh Boyer --- arch/powerpc/platforms/44x/Kconfig | 11 +++ arch/powerpc/platforms/44x/Makefile | 1 + arch/powerpc/platforms/44x/iss4xx.c | 167 ++++++++++++++++++++++++++++++++++++ 3 files changed, 179 insertions(+) create mode 100644 arch/powerpc/platforms/44x/iss4xx.c (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig index 9365e530ac5a..eeba0a70e466 100644 --- a/arch/powerpc/platforms/44x/Kconfig +++ b/arch/powerpc/platforms/44x/Kconfig @@ -160,6 +160,17 @@ config YOSEMITE help This option enables support for the AMCC PPC440EP evaluation board. +config ISS4xx + bool "ISS 4xx Simulator" + depends on (44x || 40x) + default n + select 405GP if 40x + select 440GP if 44x && !PPC_47x + select PPC_FPU + select OF_RTC + help + This option enables support for the IBM ISS simulation environment + #config LUAN # bool "Luan" # depends on 44x diff --git a/arch/powerpc/platforms/44x/Makefile b/arch/powerpc/platforms/44x/Makefile index ee6185aeaa3b..82ff326e0795 100644 --- a/arch/powerpc/platforms/44x/Makefile +++ b/arch/powerpc/platforms/44x/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_SAM440EP) += sam440ep.o obj-$(CONFIG_WARP) += warp.o obj-$(CONFIG_XILINX_VIRTEX_5_FXT) += virtex.o obj-$(CONFIG_XILINX_ML510) += virtex_ml510.o +obj-$(CONFIG_ISS4xx) += iss4xx.o diff --git a/arch/powerpc/platforms/44x/iss4xx.c b/arch/powerpc/platforms/44x/iss4xx.c new file mode 100644 index 000000000000..aa46e9d1e771 --- /dev/null +++ b/arch/powerpc/platforms/44x/iss4xx.c @@ -0,0 +1,167 @@ +/* + * PPC476 board specific routines + * + * Copyright 2010 Torez Smith, IBM Corporation. + * + * Based on earlier code: + * Matt Porter + * Copyright 2002-2005 MontaVista Software Inc. + * + * Eugene Surovegin or + * Copyright (c) 2003-2005 Zultys Technologies + * + * Rewritten and ported to the merged powerpc tree: + * Copyright 2007 David Gibson , 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static __initdata struct of_device_id iss4xx_of_bus[] = { + { .compatible = "ibm,plb4", }, + { .compatible = "ibm,plb6", }, + { .compatible = "ibm,opb", }, + { .compatible = "ibm,ebc", }, + {}, +}; + +static int __init iss4xx_device_probe(void) +{ + of_platform_bus_probe(NULL, iss4xx_of_bus, NULL); + of_instantiate_rtc(); + + return 0; +} +machine_device_initcall(iss4xx, iss4xx_device_probe); + +/* We can have either UICs or MPICs */ +static void __init iss4xx_init_irq(void) +{ + struct device_node *np; + + /* Find top level interrupt controller */ + for_each_node_with_property(np, "interrupt-controller") { + if (of_get_property(np, "interrupts", NULL) == NULL) + break; + } + if (np == NULL) + panic("Can't find top level interrupt controller"); + + /* Check type and do appropriate initialization */ + if (of_device_is_compatible(np, "ibm,uic")) { + uic_init_tree(); + ppc_md.get_irq = uic_get_irq; +#ifdef CONFIG_MPIC + } else if (of_device_is_compatible(np, "chrp,open-pic")) { + /* The MPIC driver will get everything it needs from the + * device-tree, just pass 0 to all arguments + */ + struct mpic *mpic = mpic_alloc(np, 0, MPIC_PRIMARY, 0, 0, + " MPIC "); + BUG_ON(mpic == NULL); + mpic_init(mpic); + ppc_md.get_irq = mpic_get_irq; +#endif + } else + panic("Unrecognized top level interrupt controller"); +} + +#ifdef CONFIG_SMP +static void __cpuinit smp_iss4xx_setup_cpu(int cpu) +{ + mpic_setup_this_cpu(); +} + +static void __cpuinit smp_iss4xx_kick_cpu(int cpu) +{ + struct device_node *cpunode = of_get_cpu_node(cpu, NULL); + const u64 *spin_table_addr_prop; + u32 *spin_table; + extern void start_secondary_47x(void); + + BUG_ON(cpunode == NULL); + + /* Assume spin table. We could test for the enable-method in + * the device-tree but currently there's little point as it's + * our only supported method + */ + spin_table_addr_prop = of_get_property(cpunode, "cpu-release-addr", + NULL); + if (spin_table_addr_prop == NULL) { + pr_err("CPU%d: Can't start, missing cpu-release-addr !\n", cpu); + return; + } + + /* Assume it's mapped as part of the linear mapping. This is a bit + * fishy but will work fine for now + */ + spin_table = (u32 *)__va(*spin_table_addr_prop); + pr_debug("CPU%d: Spin table mapped at %p\n", cpu, spin_table); + + spin_table[3] = cpu; + smp_wmb(); + spin_table[1] = __pa(start_secondary_47x); + mb(); +} + +static struct smp_ops_t iss_smp_ops = { + .probe = smp_mpic_probe, + .message_pass = smp_mpic_message_pass, + .setup_cpu = smp_iss4xx_setup_cpu, + .kick_cpu = smp_iss4xx_kick_cpu, + .give_timebase = smp_generic_give_timebase, + .take_timebase = smp_generic_take_timebase, +}; + +static void __init iss4xx_smp_init(void) +{ + if (mmu_has_feature(MMU_FTR_TYPE_47x)) + smp_ops = &iss_smp_ops; +} + +#else /* CONFIG_SMP */ +static void __init iss4xx_smp_init(void) { } +#endif /* CONFIG_SMP */ + +static void __init iss4xx_setup_arch(void) +{ + iss4xx_smp_init(); +} + +/* + * Called very early, MMU is off, device-tree isn't unflattened + */ +static int __init iss4xx_probe(void) +{ + unsigned long root = of_get_flat_dt_root(); + + if (!of_flat_dt_is_compatible(root, "ibm,iss-4xx")) + return 0; + + return 1; +} + +define_machine(iss4xx) { + .name = "ISS-4xx", + .probe = iss4xx_probe, + .progress = udbg_progress, + .init_IRQ = iss4xx_init_irq, + .setup_arch = iss4xx_setup_arch, + .restart = ppc4xx_reset_system, + .calibrate_decr = generic_calibrate_decr, +}; -- cgit v1.2.3 From f8b67691828321f5c85bb853283aa101ae673130 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Wed, 28 Apr 2010 13:39:41 +0000 Subject: powerpc/pseries: Make query_cpu_stopped callable outside hotplug cpu This moves query_cpu_stopped() out of the hotplug cpu code and into smp.c so it can called in other places and renames it to smp_query_cpu_stopped(). It also cleans up the return values by adding some #defines Cc: Signed-off-by: Michael Neuling Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/pseries/hotplug-cpu.c | 30 ++++--------------------- arch/powerpc/platforms/pseries/plpar_wrappers.h | 8 +++++++ arch/powerpc/platforms/pseries/smp.c | 22 ++++++++++++++++++ 3 files changed, 34 insertions(+), 26 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 a8e1d5d17a28..b0760d7701b4 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c @@ -154,30 +154,6 @@ static void pseries_mach_cpu_die(void) for(;;); } -static int qcss_tok; /* query-cpu-stopped-state token */ - -/* Get state of physical CPU. - * Return codes: - * 0 - The processor is in the RTAS stopped state - * 1 - stop-self is in progress - * 2 - The processor is not in the RTAS stopped state - * -1 - Hardware Error - * -2 - Hardware Busy, Try again later. - */ -static int query_cpu_stopped(unsigned int pcpu) -{ - int cpu_status, status; - - status = rtas_call(qcss_tok, 1, 2, &cpu_status, pcpu); - if (status != 0) { - printk(KERN_ERR - "RTAS query-cpu-stopped-state failed: %i\n", status); - return status; - } - - return cpu_status; -} - static int pseries_cpu_disable(void) { int cpu = smp_processor_id(); @@ -224,8 +200,9 @@ static void pseries_cpu_die(unsigned int cpu) } else if (get_preferred_offline_state(cpu) == CPU_STATE_OFFLINE) { for (tries = 0; tries < 25; tries++) { - cpu_status = query_cpu_stopped(pcpu); - if (cpu_status == 0 || cpu_status == -1) + cpu_status = smp_query_cpu_stopped(pcpu); + if (cpu_status == QCSS_STOPPED || + cpu_status == QCSS_HARDWARE_ERROR) break; cpu_relax(); } @@ -388,6 +365,7 @@ static int __init pseries_cpu_hotplug_init(void) struct device_node *np; const char *typep; int cpu; + int qcss_tok; for_each_node_by_name(np, "interrupt-controller") { typep = of_get_property(np, "compatible", NULL); diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h index a05f8d427856..6c4fd2c3f385 100644 --- a/arch/powerpc/platforms/pseries/plpar_wrappers.h +++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h @@ -4,6 +4,14 @@ #include #include +/* Get state of physical CPU from query_cpu_stopped */ +int smp_query_cpu_stopped(unsigned int pcpu); +#define QCSS_STOPPED 0 +#define QCSS_STOPPING 1 +#define QCSS_NOT_STOPPED 2 +#define QCSS_HARDWARE_ERROR -1 +#define QCSS_HARDWARE_BUSY -2 + static inline long poll_pending(void) { return plpar_hcall_norets(H_POLL_PENDING); diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index 4e7f89a84561..20b694280a66 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c @@ -57,6 +57,28 @@ */ static cpumask_t of_spin_map; +/* Query where a cpu is now. Return codes #defined in plpar_wrappers.h */ +int smp_query_cpu_stopped(unsigned int pcpu) +{ + int cpu_status, status; + int qcss_tok = rtas_token("query-cpu-stopped-state"); + + if (qcss_tok == RTAS_UNKNOWN_SERVICE) { + printk(KERN_INFO "Firmware doesn't support " + "query-cpu-stopped-state\n"); + return QCSS_HARDWARE_ERROR; + } + + status = rtas_call(qcss_tok, 1, 2, &cpu_status, pcpu); + if (status != 0) { + printk(KERN_ERR + "RTAS query-cpu-stopped-state failed: %i\n", status); + return status; + } + + return cpu_status; +} + /** * smp_startup_cpu() - start the given cpu * -- cgit v1.2.3 From aef40e87d866355ffd279ab21021de733242d0d5 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Wed, 28 Apr 2010 13:39:41 +0000 Subject: powerpc/pseries: Only call start-cpu when a CPU is stopped Currently we always call start-cpu irrespective of if the CPU is stopped or not. Unfortunatley on POWER7, firmware seems to not like start-cpu being called when a cpu already been started. This was not the case on POWER6 and earlier. This patch checks to see if the CPU is stopped or not via an query-cpu-stopped-state call, and only calls start-cpu on CPUs which are stopped. This fixes a bug with kexec on POWER7 on PHYP where only the primary thread would make it to the second kernel. Reported-by: Ankita Garg Cc: Signed-off-by: Michael Neuling Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/pseries/smp.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index 20b694280a66..8979982eb2ee 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c @@ -104,6 +104,12 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu) pcpu = get_hard_smp_processor_id(lcpu); + /* Check to see if the CPU out of FW already for kexec */ + if (smp_query_cpu_stopped(pcpu) == QCSS_NOT_STOPPED){ + cpu_set(lcpu, of_spin_map); + return 1; + } + /* Fixup atomic count: it exited inside IRQ handler. */ task_thread_info(paca[lcpu].__current)->preempt_count = 0; -- cgit v1.2.3 From 1b095cf4029f43db363981c0e5f02216e495ac9f Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 26 Apr 2010 15:32:32 +0000 Subject: powerpc/cpumask: Use cpu_online_mask Change &cpu_online_map to cpu_online_mask. Signed-off-by: Anton Blanchard Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/pasemi/cpufreq.c | 2 +- arch/powerpc/platforms/powermac/cpufreq_64.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pasemi/cpufreq.c b/arch/powerpc/platforms/pasemi/cpufreq.c index d35e0520abf0..c16537bc0c6e 100644 --- a/arch/powerpc/platforms/pasemi/cpufreq.c +++ b/arch/powerpc/platforms/pasemi/cpufreq.c @@ -213,7 +213,7 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy) pr_debug("current astate is at %d\n",cur_astate); policy->cur = pas_freqs[cur_astate].frequency; - cpumask_copy(policy->cpus, &cpu_online_map); + cpumask_copy(policy->cpus, cpu_online_mask); ppc_proc_freq = policy->cur * 1000ul; diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c index 3ca09d3ccce3..9650c6029c82 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_64.c +++ b/arch/powerpc/platforms/powermac/cpufreq_64.c @@ -362,7 +362,7 @@ static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy) /* secondary CPUs are tied to the primary one by the * cpufreq core if in the secondary policy we tell it that * it actually must be one policy together with all others. */ - cpumask_copy(policy->cpus, &cpu_online_map); + cpumask_copy(policy->cpus, cpu_online_mask); cpufreq_frequency_table_get_attr(g5_cpu_freqs, policy->cpu); return cpufreq_frequency_table_cpuinfo(policy, -- cgit v1.2.3 From 115731312fb3207705023e3ff247d1b9d039838d Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 26 Apr 2010 15:32:36 +0000 Subject: powerpc/cpumask: Convert iseries SMP code to new cpumask API Use new cpumask functions in iseries SMP startup code. Signed-off-by: Anton Blanchard Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/iseries/smp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/smp.c b/arch/powerpc/platforms/iseries/smp.c index 722335e32fd4..6590850045af 100644 --- a/arch/powerpc/platforms/iseries/smp.c +++ b/arch/powerpc/platforms/iseries/smp.c @@ -83,7 +83,7 @@ static void smp_iSeries_message_pass(int target, int msg) static int smp_iSeries_probe(void) { - return cpus_weight(cpu_possible_map); + return cpumask_weight(cpu_possible_mask); } static void smp_iSeries_kick_cpu(int nr) -- cgit v1.2.3 From af831e1e44619a7429eba8ece4eba8f977ee7c4f Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 26 Apr 2010 15:32:37 +0000 Subject: powerpc/cpumask: Convert pseries SMP code to new cpumask API Use new cpumask functions in pseries SMP startup code. Signed-off-by: Anton Blanchard Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/pseries/smp.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index 8979982eb2ee..3b1bf61c45be 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c @@ -55,7 +55,7 @@ * The Primary thread of each non-boot processor was started from the OF client * interface by prom_hold_cpus and is spinning on secondary_hold_spinloop. */ -static cpumask_t of_spin_map; +static cpumask_var_t of_spin_mask; /* Query where a cpu is now. Return codes #defined in plpar_wrappers.h */ int smp_query_cpu_stopped(unsigned int pcpu) @@ -98,7 +98,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu) unsigned int pcpu; int start_cpu; - if (cpu_isset(lcpu, of_spin_map)) + if (cpumask_test_cpu(lcpu, of_spin_mask)) /* Already started by OF and sitting in spin loop */ return 1; @@ -106,7 +106,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu) /* Check to see if the CPU out of FW already for kexec */ if (smp_query_cpu_stopped(pcpu) == QCSS_NOT_STOPPED){ - cpu_set(lcpu, of_spin_map); + cpumask_set_cpu(lcpu, of_spin_mask); return 1; } @@ -143,7 +143,7 @@ static void __devinit smp_xics_setup_cpu(int cpu) if (firmware_has_feature(FW_FEATURE_SPLPAR)) vpa_init(cpu); - cpu_clear(cpu, of_spin_map); + cpumask_clear_cpu(cpu, of_spin_mask); set_cpu_current_state(cpu, CPU_STATE_ONLINE); set_default_offline_state(cpu); @@ -214,17 +214,19 @@ static void __init smp_init_pseries(void) pr_debug(" -> smp_init_pSeries()\n"); + alloc_bootmem_cpumask_var(&of_spin_mask); + /* Mark threads which are still spinning in hold loops. */ if (cpu_has_feature(CPU_FTR_SMT)) { for_each_present_cpu(i) { if (cpu_thread_in_core(i) == 0) - cpu_set(i, of_spin_map); + cpumask_set_cpu(i, of_spin_mask); } } else { - of_spin_map = cpu_present_map; + cpumask_copy(of_spin_mask, cpu_present_mask); } - cpu_clear(boot_cpuid, of_spin_map); + cpumask_clear_cpu(boot_cpuid, of_spin_mask); /* Non-lpar has additional take/give timebase */ if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) { -- cgit v1.2.3 From 64fe220c13440a12d0bd8e32ebdf679e869e3ce3 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 26 Apr 2010 15:32:38 +0000 Subject: powerpc/cpumask: Convert xics driver to new cpumask API Use the new cpumask API and add some comments to clarify how get_irq_server works. Signed-off-by: Anton Blanchard Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/pseries/xics.c | 38 +++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 17 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 1bcedd8b4616..f19d19468393 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -163,29 +163,37 @@ static inline void lpar_qirr_info(int n_cpu , u8 value) /* Interface to generic irq subsystem */ #ifdef CONFIG_SMP -static int get_irq_server(unsigned int virq, cpumask_t cpumask, +/* + * For the moment we only implement delivery to all cpus or one cpu. + * + * If the requested affinity is cpu_all_mask, we set global affinity. + * If not we set it to the first cpu in the mask, even if multiple cpus + * are set. This is so things like irqbalance (which set core and package + * wide affinities) do the right thing. + */ +static int get_irq_server(unsigned int virq, const struct cpumask *cpumask, unsigned int strict_check) { - int server; - /* For the moment only implement delivery to all cpus or one cpu */ - cpumask_t tmp = CPU_MASK_NONE; if (!distribute_irqs) return default_server; - if (!cpus_equal(cpumask, CPU_MASK_ALL)) { - cpus_and(tmp, cpu_online_map, cpumask); - - server = first_cpu(tmp); + if (!cpumask_equal(cpumask, cpu_all_mask)) { + int server = cpumask_first_and(cpu_online_mask, cpumask); - if (server < NR_CPUS) + if (server < nr_cpu_ids) return get_hard_smp_processor_id(server); if (strict_check) return -1; } - if (cpus_equal(cpu_online_map, cpu_present_map)) + /* + * Workaround issue with some versions of JS20 firmware that + * deliver interrupts to cpus which haven't been started. This + * happens when using the maxcpus= boot option. + */ + if (cpumask_equal(cpu_online_mask, cpu_present_mask)) return default_distrib_server; return default_server; @@ -207,7 +215,7 @@ static void xics_unmask_irq(unsigned int virq) if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) return; - server = get_irq_server(virq, *(irq_to_desc(virq)->affinity), 0); + server = get_irq_server(virq, irq_to_desc(virq)->affinity, 0); call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, DEFAULT_PRIORITY); @@ -398,11 +406,7 @@ static int xics_set_affinity(unsigned int virq, const struct cpumask *cpumask) return -1; } - /* - * For the moment only implement delivery to all cpus or one cpu. - * Get current irq_server for the given irq - */ - irq_server = get_irq_server(virq, *cpumask, 1); + irq_server = get_irq_server(virq, cpumask, 1); if (irq_server == -1) { char cpulist[128]; cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask); @@ -611,7 +615,7 @@ int __init smp_xics_probe(void) { xics_request_ipi(); - return cpus_weight(cpu_possible_map); + return cpumask_weight(cpu_possible_mask); } #endif /* CONFIG_SMP */ -- cgit v1.2.3 From cc1ba8ea6dde3f049b2b365d8fdc13976aee25cb Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 26 Apr 2010 15:32:41 +0000 Subject: powerpc/cpumask: Dynamically allocate cpu_sibling_map and cpu_core_map cpumasks Dynamically allocate cpu_sibling_map and cpu_core_map cpumasks. We don't need to set_cpu_online() the boot cpu in smp_prepare_boot_cpu, init/main.c does it for us. We also postpone setting of the boot cpu in cpu_sibling_map and cpu_core_map until when the memory allocator is available (smp_prepare_cpus), similar to x86. Signed-off-by: Anton Blanchard Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/cell/cbe_cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c index e6506cd0ff94..bfa2c0cb3d1e 100644 --- a/arch/powerpc/platforms/cell/cbe_cpufreq.c +++ b/arch/powerpc/platforms/cell/cbe_cpufreq.c @@ -118,7 +118,7 @@ static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy) policy->cur = cbe_freqs[cur_pmode].frequency; #ifdef CONFIG_SMP - cpumask_copy(policy->cpus, &per_cpu(cpu_sibling_map, policy->cpu)); + cpumask_copy(policy->cpus, cpu_sibling_mask(policy->cpu)); #endif cpufreq_frequency_table_get_attr(cbe_freqs, policy->cpu); -- cgit v1.2.3 From 8729faaa5e87557876c02f1665d517e2b41299f1 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 26 Apr 2010 15:32:42 +0000 Subject: powerpc/cpumask: Convert hotplug-cpu code to new cpumask API Convert hotplug-cpu code to new cpumask API. Signed-off-by: Anton Blanchard Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/pseries/hotplug-cpu.c | 33 ++++++++++++++++------------ 1 file changed, 19 insertions(+), 14 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 b0760d7701b4..235f363f732d 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c @@ -163,7 +163,7 @@ static int pseries_cpu_disable(void) /*fix boot_cpuid here*/ if (cpu == boot_cpuid) - boot_cpuid = any_online_cpu(cpu_online_map); + boot_cpuid = cpumask_any(cpu_online_mask); /* FIXME: abstract this to not be platform specific later on */ xics_migrate_irqs_away(); @@ -231,7 +231,7 @@ static void pseries_cpu_die(unsigned int cpu) static int pseries_add_processor(struct device_node *np) { unsigned int cpu; - cpumask_t candidate_map, tmp = CPU_MASK_NONE; + cpumask_var_t candidate_mask, tmp; int err = -ENOSPC, len, nthreads, i; const u32 *intserv; @@ -239,48 +239,53 @@ static int pseries_add_processor(struct device_node *np) if (!intserv) return 0; + zalloc_cpumask_var(&candidate_mask, GFP_KERNEL); + zalloc_cpumask_var(&tmp, GFP_KERNEL); + nthreads = len / sizeof(u32); for (i = 0; i < nthreads; i++) - cpu_set(i, tmp); + cpumask_set_cpu(i, tmp); cpu_maps_update_begin(); - BUG_ON(!cpus_subset(cpu_present_map, cpu_possible_map)); + BUG_ON(!cpumask_subset(cpu_present_mask, cpu_possible_mask)); /* Get a bitmap of unoccupied slots. */ - cpus_xor(candidate_map, cpu_possible_map, cpu_present_map); - if (cpus_empty(candidate_map)) { + cpumask_xor(candidate_mask, cpu_possible_mask, cpu_present_mask); + if (cpumask_empty(candidate_mask)) { /* If we get here, it most likely means that NR_CPUS is * less than the partition's max processors setting. */ printk(KERN_ERR "Cannot add cpu %s; this system configuration" " supports %d logical cpus.\n", np->full_name, - cpus_weight(cpu_possible_map)); + cpumask_weight(cpu_possible_mask)); goto out_unlock; } - while (!cpus_empty(tmp)) - if (cpus_subset(tmp, candidate_map)) + while (!cpumask_empty(tmp)) + if (cpumask_subset(tmp, candidate_mask)) /* Found a range where we can insert the new cpu(s) */ break; else - cpus_shift_left(tmp, tmp, nthreads); + cpumask_shift_left(tmp, tmp, nthreads); - if (cpus_empty(tmp)) { + if (cpumask_empty(tmp)) { printk(KERN_ERR "Unable to find space in cpu_present_map for" " processor %s with %d thread(s)\n", np->name, nthreads); goto out_unlock; } - for_each_cpu_mask(cpu, tmp) { - BUG_ON(cpu_isset(cpu, cpu_present_map)); + for_each_cpu(cpu, tmp) { + BUG_ON(cpumask_test_cpu(cpu, cpu_present_mask)); set_cpu_present(cpu, true); set_hard_smp_processor_id(cpu, *intserv++); } err = 0; out_unlock: cpu_maps_update_done(); + free_cpumask_var(candidate_mask); + free_cpumask_var(tmp); return err; } @@ -311,7 +316,7 @@ static void pseries_remove_processor(struct device_node *np) set_hard_smp_processor_id(cpu, -1); break; } - if (cpu == NR_CPUS) + if (cpu >= nr_cpu_ids) printk(KERN_WARNING "Could not find cpu to remove " "with physical id 0x%x\n", intserv[i]); } -- cgit v1.2.3 From 828a69869ba266cabb486a6b59ea8643d56b33ce Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 26 Apr 2010 15:32:44 +0000 Subject: powerpc/cpumask: Update some comments Since the *_map cpumask variants are deprecated, change the comments to instead refer to *_mask. Signed-off-by: Anton Blanchard Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/powermac/setup.c | 2 +- arch/powerpc/platforms/powermac/smp.c | 4 ++-- arch/powerpc/platforms/pseries/hotplug-cpu.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 15c2241f9c72..47a2b4488557 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -480,7 +480,7 @@ static void __init pmac_init_early(void) #endif /* SMP Init has to be done early as we need to patch up - * cpu_possible_map before interrupt stacks are allocated + * cpu_possible_mask before interrupt stacks are allocated * or kaboom... */ #ifdef CONFIG_SMP diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index 6898e8241cd0..02d0b8e5b13c 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c @@ -315,7 +315,7 @@ static int __init smp_psurge_probe(void) /* This is necessary because OF doesn't know about the * secondary cpu(s), and thus there aren't nodes in the * device tree for them, and smp_setup_cpu_maps hasn't - * set their bits in cpu_present_map. + * set their bits in cpu_present_mask. */ if (ncpus > NR_CPUS) ncpus = NR_CPUS; @@ -944,7 +944,7 @@ void __init pmac_setup_smp(void) } #ifdef CONFIG_PPC32 else { - /* We have to set bits in cpu_possible_map here since the + /* We have to set bits in cpu_possible_mask here since the * secondary CPU(s) aren't in the device tree. Various * things won't be initialized for CPUs not in the possible * map, so we really need to fix it up here. diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c index 235f363f732d..8f85f399ab9f 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c @@ -222,7 +222,7 @@ static void pseries_cpu_die(unsigned int cpu) } /* - * Update cpu_present_map and paca(s) for a new cpu node. The wrinkle + * Update cpu_present_mask and paca(s) for a new cpu node. The wrinkle * here is that a cpu device node may represent up to two logical cpus * in the SMT case. We must honor the assumption in other code that * the logical ids for sibling SMT threads x and y are adjacent, such @@ -270,7 +270,7 @@ static int pseries_add_processor(struct device_node *np) cpumask_shift_left(tmp, tmp, nthreads); if (cpumask_empty(tmp)) { - printk(KERN_ERR "Unable to find space in cpu_present_map for" + printk(KERN_ERR "Unable to find space in cpu_present_mask for" " processor %s with %d thread(s)\n", np->name, nthreads); goto out_unlock; -- cgit v1.2.3 From 6971df4f5b0e5b6955c03e8d51bad5d50463f98f Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Sun, 2 May 2010 21:27:05 +0400 Subject: powerpc/83xx: Add MCU LEDs support for MPC837xRDB and MPC8315RDB boards There are two front-panel LEDs on MPC837xRDB and MPC8315RDB boards: PWR and HDD. After adding appropriate nodes we can program these LEDs from kernel and user space. Signed-off-by: Anton Vorontsov Signed-off-by: Kumar Gala --- arch/powerpc/platforms/83xx/mpc831x_rdb.c | 1 + arch/powerpc/platforms/83xx/mpc837x_rdb.c | 1 + 2 files changed, 2 insertions(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/83xx/mpc831x_rdb.c b/arch/powerpc/platforms/83xx/mpc831x_rdb.c index 0b4f883b20eb..ae525e4745d2 100644 --- a/arch/powerpc/platforms/83xx/mpc831x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc831x_rdb.c @@ -74,6 +74,7 @@ static int __init mpc831x_rdb_probe(void) static struct of_device_id __initdata of_bus_ids[] = { { .compatible = "simple-bus" }, { .compatible = "gianfar" }, + { .compatible = "gpio-leds", }, {}, }; diff --git a/arch/powerpc/platforms/83xx/mpc837x_rdb.c b/arch/powerpc/platforms/83xx/mpc837x_rdb.c index a1908d261240..e00801c42540 100644 --- a/arch/powerpc/platforms/83xx/mpc837x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc837x_rdb.c @@ -72,6 +72,7 @@ static struct of_device_id mpc837x_ids[] = { { .compatible = "soc", }, { .compatible = "simple-bus", }, { .compatible = "gianfar", }, + { .compatible = "gpio-leds", }, {}, }; -- cgit v1.2.3 From 4c5ddd52695f7bac6362ad13fd3dc878212d1368 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Mon, 3 May 2010 16:54:15 -0500 Subject: powerpc/8610: add probing for individual DMA channels, not just DMA controllers A future version of the MPC8610 HPCD's ASoC DMA driver will probe on individual DMA channel nodes, so the DMA controller nodes' compatible string must be listed in mpc8610_ids[] for the probe to work. Also remove the "gianfar" compatible from mpc8610_ids[], since there is no gianfar (or any other networking device) on the 8610. Signed-off-by: Timur Tabi Signed-off-by: Kumar Gala --- arch/powerpc/platforms/86xx/mpc8610_hpcd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c index 5abe137f6309..018cc67be426 100644 --- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c +++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c @@ -83,7 +83,8 @@ static struct of_device_id __initdata mpc8610_ids[] = { { .compatible = "fsl,mpc8610-immr", }, { .compatible = "fsl,mpc8610-guts", }, { .compatible = "simple-bus", }, - { .compatible = "gianfar", }, + /* So that the DMA channel nodes can be probed individually: */ + { .compatible = "fsl,eloplus-dma", }, {} }; -- cgit v1.2.3 From abb17f9c3a92c5acf30e749efdf0419b7f50a5b8 Mon Sep 17 00:00:00 2001 From: Milton Miller Date: Wed, 19 May 2010 02:56:29 +0000 Subject: powerpc: Use common cpu_die (fixes SMP+SUSPEND build) Configuring a powerpc 32 bit kernel for both SMP and SUSPEND turns on CPU_HOTPLUG to enable disable_nonboot_cpus to be called by the common suspend code. Previously the definition of cpu_die for ppc32 was in the powermac platform code, causing it to be undefined if that platform as not selected. arch/powerpc/kernel/built-in.o: In function 'cpu_idle': arch/powerpc/kernel/idle.c:98: undefined reference to 'cpu_die' Move the code from setup_64 to smp.c and rename the power mac versions to their specific names. Note that this does not setup the cpu_die pointers in either smp_ops (request a given cpu die) or ppc_md (make this cpu die), for other platforms but there are generic versions in smp.c. Reported-by: Matt Sealey Reported-by: Kumar Gala Signed-off-by: Milton Miller Signed-off-by: Anton Vorontsov Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/powermac/pmac.h | 2 ++ arch/powerpc/platforms/powermac/setup.c | 11 ++++++++--- arch/powerpc/platforms/powermac/smp.c | 5 +++-- 3 files changed, 13 insertions(+), 5 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powermac/pmac.h b/arch/powerpc/platforms/powermac/pmac.h index 3362e781b6a7..f0bc08f6c1f0 100644 --- a/arch/powerpc/platforms/powermac/pmac.h +++ b/arch/powerpc/platforms/powermac/pmac.h @@ -33,6 +33,8 @@ extern void pmac_setup_pci_dma(void); extern void pmac_check_ht_link(void); extern void pmac_setup_smp(void); +extern void pmac32_cpu_die(void); +extern void low_cpu_die(void) __attribute__((noreturn)); extern int pmac_nvram_init(void); extern void pmac_pic_init(void); diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 47a2b4488557..f1d0132ebcc7 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -646,7 +646,7 @@ static int pmac_pci_probe_mode(struct pci_bus *bus) /* access per cpu vars from generic smp.c */ DECLARE_PER_CPU(int, cpu_state); -static void pmac_cpu_die(void) +static void pmac64_cpu_die(void) { /* * turn off as much as possible, we'll be @@ -717,8 +717,13 @@ define_machine(powermac) { .pcibios_after_init = pmac_pcibios_after_init, .phys_mem_access_prot = pci_phys_mem_access_prot, #endif -#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC64) - .cpu_die = pmac_cpu_die, +#ifdef CONFIG_HOTPLUG_CPU +#ifdef CONFIG_PPC64 + .cpu_die = pmac64_cpu_die, +#endif +#ifdef CONFIG_PPC32 + .cpu_die = pmac32_cpu_die, +#endif #endif #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32) .cpu_die = generic_mach_cpu_die, diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index 02d0b8e5b13c..c95215f4f8b6 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c @@ -53,6 +53,8 @@ #include #include +#include "pmac.h" + #undef DEBUG #ifdef DEBUG @@ -878,10 +880,9 @@ int smp_core99_cpu_disable(void) return 0; } -extern void low_cpu_die(void) __attribute__((noreturn)); /* in sleep.S */ static int cpu_dead[NR_CPUS]; -void cpu_die(void) +void pmac32_cpu_die(void) { local_irq_disable(); cpu_dead[smp_processor_id()] = 1; -- cgit v1.2.3 From e62cee42e66dcca83aae02748535f62e0f564a0c Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 6 May 2010 19:46:50 +0000 Subject: powerpc: Avoid bad relocations in iSeries code Subrata Modak reported that building a CONFIG_RELOCATABLE kernel with CONFIG_ISERIES enabled gives the following warnings: WARNING: 4 bad relocations c00000000007216e R_PPC64_ADDR16_HIGHEST __ksymtab+0x00000000009dcec8 c000000000072172 R_PPC64_ADDR16_HIGHER __ksymtab+0x00000000009dcec8 c00000000007217a R_PPC64_ADDR16_HI __ksymtab+0x00000000009dcec8 c00000000007217e R_PPC64_ADDR16_LO __ksymtab+0x00000000009dcec8 The reason is that decrementer_iSeries_masked is using LOAD_REG_IMMEDIATE to get the address of a kernel symbol, which creates relocations that aren't handled by the kernel relocator code. Instead of reading the tb_ticks_per_jiffy variable, we can just set the decrementer to its maximum value (0x7fffffff) and that will work just as well. In fact timer_interrupt sets the decrementer to that value initially anyway, and we are sure to get into timer_interrupt once interrupts are reenabled because we store 1 to the decrementer interrupt flag in the lppaca (LPPACADECRINT(r12) here). Reported-by: Subrata Modak Signed-off-by: Paul Mackerras Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/iseries/exception.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/exception.S b/arch/powerpc/platforms/iseries/exception.S index fba5bf915073..32a56c6dfa72 100644 --- a/arch/powerpc/platforms/iseries/exception.S +++ b/arch/powerpc/platforms/iseries/exception.S @@ -252,8 +252,8 @@ decrementer_iSeries_masked: li r11,1 ld r12,PACALPPACAPTR(r13) stb r11,LPPACADECRINT(r12) - LOAD_REG_IMMEDIATE(r12, tb_ticks_per_jiffy) - lwz r12,0(r12) + li r12,-1 + clrldi r12,r12,33 /* set DEC to 0x7fffffff */ mtspr SPRN_DEC,r12 /* fall through */ -- cgit v1.2.3 From ce47c1c45b2b17ad07af82c775f27cc5196080f8 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 10 May 2010 15:38:56 +0000 Subject: powerpc/eeh: Fix oops when probing in early boot If we take an EEH error early enough, we oops: Call Trace: [c000000010483770] [c000000000013ee4] .show_stack+0xd8/0x218 (unreliable) [c000000010483850] [c000000000658940] .dump_stack+0x28/0x3c [c0000000104838d0] [c000000000057a68] .eeh_dn_check_failure+0x2b8/0x304 [c000000010483990] [c0000000000259c8] .rtas_read_config+0x120/0x168 [c000000010483a40] [c000000000025af4] .rtas_pci_read_config+0xe4/0x124 [c000000010483af0] [c00000000037af18] .pci_bus_read_config_word+0xac/0x104 [c000000010483bc0] [c0000000008fec98] .pcibios_allocate_resources+0x7c/0x220 [c000000010483c90] [c0000000008feed8] .pcibios_resource_survey+0x9c/0x418 [c000000010483d80] [c0000000008fea10] .pcibios_init+0xbc/0xf4 [c000000010483e20] [c000000000009844] .do_one_initcall+0x98/0x1d8 [c000000010483ed0] [c0000000008f0560] .kernel_init+0x228/0x2e8 [c000000010483f90] [c000000000031a08] .kernel_thread+0x54/0x70 EEH: Detected PCI bus error on device EEH: This PCI device has failed 1 times in the last hour: EEH: location=U78A5.001.WIH8464-P1 driver= pci addr=0001:00:01.0 EEH: of node=/pci@800000020000209/usb@1 EEH: PCI device/vendor: 00351033 EEH: PCI cmd/status register: 12100146 Unable to handle kernel paging request for data at address 0x00000468 Oops: Kernel access of bad area, sig: 11 [#1] .... NIP [c000000000057610] .rtas_set_slot_reset+0x38/0x10c LR [c000000000058724] .eeh_reset_device+0x5c/0x124 Call Trace: [c00000000bc6bd00] [c00000000005a0e0] .pcibios_remove_pci_devices+0x7c/0xb0 (unreliable) [c00000000bc6bd90] [c000000000058724] .eeh_reset_device+0x5c/0x124 [c00000000bc6be40] [c0000000000589c0] .handle_eeh_events+0x1d4/0x39c [c00000000bc6bf00] [c000000000059124] .eeh_event_handler+0xf0/0x188 [c00000000bc6bf90] [c000000000031a08] .kernel_thread+0x54/0x70 We called rtas_set_slot_reset while scanning the bus and before the pci_dn to pcidev mapping has been created. Since we only need the pcidev to work out the type of reset and that only gets set after the module for the device loads, lets just do a hot reset if the pcidev is NULL. Signed-off-by: Anton Blanchard Acked-by: Linas Vepstas Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/pseries/eeh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 7df7fbb7cacb..34b7dc12e731 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c @@ -749,7 +749,7 @@ static void __rtas_set_slot_reset(struct pci_dn *pdn) /* Determine type of EEH reset required by device, * default hot reset or fundamental reset */ - if (dev->needs_freset) + if (dev && dev->needs_freset) rtas_pci_slot_reset(pdn, 3); else rtas_pci_slot_reset(pdn, 1); -- cgit v1.2.3 From f90ece28c1f5b3ec13fe481406857fe92f4bc7d1 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Mon, 10 May 2010 20:28:26 +0000 Subject: powerpc/pseries: Add hcall to read 4 ptes at a time in real mode This adds plpar_pte_read_4_raw() which can be used read 4 PTEs from PHYP at a time, while in real mode. It also creates a new hcall9 which can be used in real mode. It's the same as plpar_hcall9 but minus the tracing hcall statistics which may require variables outside the RMO. Signed-off-by: Michael Neuling Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/pseries/hvCall.S | 38 +++++++++++++++++++++++++ arch/powerpc/platforms/pseries/plpar_wrappers.h | 18 ++++++++++++ 2 files changed, 56 insertions(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/hvCall.S b/arch/powerpc/platforms/pseries/hvCall.S index 383a5d0e9818..48d20573e4de 100644 --- a/arch/powerpc/platforms/pseries/hvCall.S +++ b/arch/powerpc/platforms/pseries/hvCall.S @@ -228,3 +228,41 @@ _GLOBAL(plpar_hcall9) mtcrf 0xff,r0 blr /* return r3 = status */ + +/* See plpar_hcall_raw to see why this is needed */ +_GLOBAL(plpar_hcall9_raw) + HMT_MEDIUM + + mfcr r0 + stw r0,8(r1) + + std r4,STK_PARM(r4)(r1) /* Save ret buffer */ + + mr r4,r5 + mr r5,r6 + mr r6,r7 + mr r7,r8 + mr r8,r9 + mr r9,r10 + ld r10,STK_PARM(r11)(r1) /* put arg7 in R10 */ + ld r11,STK_PARM(r12)(r1) /* put arg8 in R11 */ + ld r12,STK_PARM(r13)(r1) /* put arg9 in R12 */ + + HVSC /* invoke the hypervisor */ + + mr r0,r12 + ld r12,STK_PARM(r4)(r1) + std r4, 0(r12) + std r5, 8(r12) + std r6, 16(r12) + std r7, 24(r12) + std r8, 32(r12) + std r9, 40(r12) + std r10,48(r12) + std r11,56(r12) + std r0, 64(r12) + + lwz r0,8(r1) + mtcrf 0xff,r0 + + blr /* return r3 = status */ diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h index 6c4fd2c3f385..d9801117124b 100644 --- a/arch/powerpc/platforms/pseries/plpar_wrappers.h +++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h @@ -191,6 +191,24 @@ static inline long plpar_pte_read_raw(unsigned long flags, unsigned long ptex, return rc; } +/* + * plpar_pte_read_4_raw can be called in real mode. + * ptes must be 8*sizeof(unsigned long) + */ +static inline long plpar_pte_read_4_raw(unsigned long flags, unsigned long ptex, + unsigned long *ptes) + +{ + long rc; + unsigned long retbuf[PLPAR_HCALL9_BUFSIZE]; + + rc = plpar_hcall9_raw(H_READ, retbuf, flags | H_READ_4, ptex); + + memcpy(ptes, retbuf, 8*sizeof(unsigned long)); + + return rc; +} + static inline long plpar_pte_protect(unsigned long flags, unsigned long ptex, unsigned long avpn) { -- cgit v1.2.3 From d504bed676caad29a3dba3d3727298c560628f5c Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Mon, 10 May 2010 20:28:26 +0000 Subject: powerpc/kexec: Speedup kexec hash PTE tear down Currently for kexec the PTE tear down on 1TB segment systems normally requires 3 hcalls for each PTE removal. On a machine with 32GB of memory it can take around a minute to remove all the PTEs. This optimises the path so that we only remove PTEs that are valid. It also uses the read 4 PTEs at once HCALL. For the common case where a PTEs is invalid in a 1TB segment, this turns the 3 HCALLs per PTE down to 1 HCALL per 4 PTEs. This gives an > 10x speedup in kexec times on PHYP, taking a 32GB machine from around 1 minute down to a few seconds. Signed-off-by: Michael Neuling Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/pseries/lpar.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 0707653612ba..cf79b46d8f88 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -367,21 +367,28 @@ static void pSeries_lpar_hptab_clear(void) { unsigned long size_bytes = 1UL << ppc64_pft_size; unsigned long hpte_count = size_bytes >> 4; - unsigned long dummy1, dummy2, dword0; + struct { + unsigned long pteh; + unsigned long ptel; + } ptes[4]; long lpar_rc; - int i; + int i, j; - /* TODO: Use bulk call */ - for (i = 0; i < hpte_count; i++) { - /* dont remove HPTEs with VRMA mappings */ - lpar_rc = plpar_pte_remove_raw(H_ANDCOND, i, HPTE_V_1TB_SEG, - &dummy1, &dummy2); - if (lpar_rc == H_NOT_FOUND) { - lpar_rc = plpar_pte_read_raw(0, i, &dword0, &dummy1); - if (!lpar_rc && ((dword0 & HPTE_V_VRMA_MASK) - != HPTE_V_VRMA_MASK)) - /* Can be hpte for 1TB Seg. So remove it */ - plpar_pte_remove_raw(0, i, 0, &dummy1, &dummy2); + /* Read in batches of 4, + * invalidate only valid entries not in the VRMA + * hpte_count will be a multiple of 4 + */ + for (i = 0; i < hpte_count; i += 4) { + lpar_rc = plpar_pte_read_4_raw(0, i, (void *)ptes); + if (lpar_rc != H_SUCCESS) + continue; + for (j = 0; j < 4; j++){ + if ((ptes[j].pteh & HPTE_V_VRMA_MASK) == + HPTE_V_VRMA_MASK) + continue; + if (ptes[j].pteh & HPTE_V_VALID) + plpar_pte_remove_raw(0, i + j, 0, + &(ptes[j].pteh), &(ptes[j].ptel)); } } } -- cgit v1.2.3 From b878dc00595440586874952dd85ce9b803360b87 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Sun, 16 May 2010 20:02:39 +0000 Subject: powerpc: Use smt_snooze_delay=-1 to always busy loop Right now if we want to busy loop and not give up any time to the hypervisor we put a very large value into smt_snooze_delay. This is sometimes useful when running a single partition and you want to avoid any latencies due to the hypervisor or CPU power state transitions. While this works, it's a bit ugly - how big a number is enough now we have NO_HZ and can be idle for a very long time. The patch below makes smt_snooze_delay signed, and a negative value means loop forever: echo -1 > /sys/devices/system/cpu/cpu0/smt_snooze_delay This change shouldn't affect the existing userspace tools (eg ppc64_cpu), but I'm cc-ing Nathan just to be sure. Signed-off-by: Anton Blanchard Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/pseries/setup.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 6710761bf60f..a6d19e3a505e 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -496,13 +496,14 @@ static int __init pSeries_probe(void) } -DECLARE_PER_CPU(unsigned long, smt_snooze_delay); +DECLARE_PER_CPU(long, smt_snooze_delay); static void pseries_dedicated_idle_sleep(void) { unsigned int cpu = smp_processor_id(); unsigned long start_snooze; unsigned long in_purr, out_purr; + long snooze = __get_cpu_var(smt_snooze_delay); /* * Indicate to the HV that we are idle. Now would be @@ -517,13 +518,12 @@ static void pseries_dedicated_idle_sleep(void) * has been checked recently. If we should poll for a little * while, do so. */ - if (__get_cpu_var(smt_snooze_delay)) { - start_snooze = get_tb() + - __get_cpu_var(smt_snooze_delay) * tb_ticks_per_usec; + if (snooze) { + start_snooze = get_tb() + snooze * tb_ticks_per_usec; local_irq_enable(); set_thread_flag(TIF_POLLING_NRFLAG); - while (get_tb() < start_snooze) { + while ((snooze < 0) || (get_tb() < start_snooze)) { if (need_resched() || cpu_is_offline(cpu)) goto out; ppc64_runlatch_off(); -- cgit v1.2.3 From 32c96f7765b881ab1f6ab8ff04b733e4cf157239 Mon Sep 17 00:00:00 2001 From: Mark Nelson Date: Tue, 18 May 2010 22:51:00 +0000 Subject: powerpc/pseries: Make request_ras_irqs() available to other pseries code At the moment only the RAS code uses event-sources interrupts (for EPOW events and internal errors) so request_ras_irqs() (which actually requests the event-sources interrupts) is found in ras.c and is static. We want to be able to use event-sources interrupts in other pseries code, so let's rename request_ras_irqs() to request_event_sources_irqs() and move it to event_sources.c. This will be used in an upcoming patch that adds support for IO Event interrupts that come through as event sources. Signed-off-by: Mark Nelson Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/pseries/Makefile | 2 +- arch/powerpc/platforms/pseries/event_sources.c | 79 ++++++++++++++++++++++++++ arch/powerpc/platforms/pseries/pseries.h | 7 +++ arch/powerpc/platforms/pseries/ras.c | 62 +------------------- 4 files changed, 90 insertions(+), 60 deletions(-) create mode 100644 arch/powerpc/platforms/pseries/event_sources.c (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 0ff5174ae4f5..3dbef309bc8d 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile @@ -7,7 +7,7 @@ EXTRA_CFLAGS += -DDEBUG endif obj-y := lpar.o hvCall.o nvram.o reconfig.o \ - setup.o iommu.o ras.o \ + setup.o iommu.o event_sources.o ras.o \ firmware.o power.o dlpar.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_XICS) += xics.o diff --git a/arch/powerpc/platforms/pseries/event_sources.c b/arch/powerpc/platforms/pseries/event_sources.c new file mode 100644 index 000000000000..e889c9d9586a --- /dev/null +++ b/arch/powerpc/platforms/pseries/event_sources.c @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2001 Dave Engebretsen 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "pseries.h" + +void request_event_sources_irqs(struct device_node *np, + irq_handler_t handler, + const char *name) +{ + int i, index, count = 0; + struct of_irq 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) + printk(KERN_ERR "Unable to allocate interrupt " + "number for %s\n", np->full_name); + else + count++; + + } + } + /* Else use normal interrupt tree parsing */ + else { + /* First try to do a proper OF tree parsing */ + for (index = 0; of_irq_map_one(np, index, &oirq) == 0; + index++) { + if (count > 15) + break; + virqs[count] = irq_create_of_mapping(oirq.controller, + oirq.specifier, + oirq.size); + if (virqs[count] == NO_IRQ) + printk(KERN_ERR "Unable to allocate interrupt " + "number for %s\n", np->full_name); + else + count++; + } + } + + /* Now request them */ + for (i = 0; i < count; i++) { + if (request_irq(virqs[i], handler, 0, name, NULL)) { + printk(KERN_ERR "Unable to request interrupt %d for " + "%s\n", virqs[i], np->full_name); + return; + } + } +} + diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h index 9e17c0d2a0c8..40c93cad91d2 100644 --- a/arch/powerpc/platforms/pseries/pseries.h +++ b/arch/powerpc/platforms/pseries/pseries.h @@ -10,6 +10,13 @@ #ifndef _PSERIES_PSERIES_H #define _PSERIES_PSERIES_H +#include + +struct device_node; + +extern void request_event_sources_irqs(struct device_node *np, + irq_handler_t handler, const char *name); + extern void __init fw_feature_init(const char *hypertas, unsigned long len); struct pt_regs; diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c index db940d2c39a0..41a3e9a039ed 100644 --- a/arch/powerpc/platforms/pseries/ras.c +++ b/arch/powerpc/platforms/pseries/ras.c @@ -67,63 +67,6 @@ static irqreturn_t ras_epow_interrupt(int irq, void *dev_id); static irqreturn_t ras_error_interrupt(int irq, void *dev_id); -static void request_ras_irqs(struct device_node *np, - irq_handler_t handler, - const char *name) -{ - int i, index, count = 0; - struct of_irq 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) - printk(KERN_ERR "Unable to allocate interrupt " - "number for %s\n", np->full_name); - else - count++; - - } - } - /* Else use normal interrupt tree parsing */ - else { - /* First try to do a proper OF tree parsing */ - for (index = 0; of_irq_map_one(np, index, &oirq) == 0; - index++) { - if (count > 15) - break; - virqs[count] = irq_create_of_mapping(oirq.controller, - oirq.specifier, - oirq.size); - if (virqs[count] == NO_IRQ) - printk(KERN_ERR "Unable to allocate interrupt " - "number for %s\n", np->full_name); - else - count++; - } - } - - /* Now request them */ - for (i = 0; i < count; i++) { - if (request_irq(virqs[i], handler, 0, name, NULL)) { - printk(KERN_ERR "Unable to request interrupt %d for " - "%s\n", virqs[i], np->full_name); - return; - } - } -} - /* * Initialize handlers for the set of interrupts caused by hardware errors * and power system events. @@ -138,14 +81,15 @@ static int __init init_ras_IRQ(void) /* Internal Errors */ np = of_find_node_by_path("/event-sources/internal-errors"); if (np != NULL) { - request_ras_irqs(np, ras_error_interrupt, "RAS_ERROR"); + request_event_sources_irqs(np, ras_error_interrupt, + "RAS_ERROR"); of_node_put(np); } /* EPOW Events */ np = of_find_node_by_path("/event-sources/epow-events"); if (np != NULL) { - request_ras_irqs(np, ras_epow_interrupt, "RAS_EPOW"); + request_event_sources_irqs(np, ras_epow_interrupt, "RAS_EPOW"); of_node_put(np); } -- cgit v1.2.3