diff options
Diffstat (limited to 'arch/powerpc/platforms')
28 files changed, 921 insertions, 101 deletions
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig index 69d668c072a..0f979c5c756 100644 --- a/arch/powerpc/platforms/44x/Kconfig +++ b/arch/powerpc/platforms/44x/Kconfig | |||
| @@ -17,6 +17,16 @@ config BAMBOO | |||
| 17 | help | 17 | help |
| 18 | This option enables support for the IBM PPC440EP evaluation board. | 18 | This option enables support for the IBM PPC440EP evaluation board. |
| 19 | 19 | ||
| 20 | config BLUESTONE | ||
| 21 | bool "Bluestone" | ||
| 22 | depends on 44x | ||
| 23 | default n | ||
| 24 | select PPC44x_SIMPLE | ||
| 25 | select APM821xx | ||
| 26 | select IBM_NEW_EMAC_RGMII | ||
| 27 | help | ||
| 28 | This option enables support for the APM APM821xx Evaluation board. | ||
| 29 | |||
| 20 | config EBONY | 30 | config EBONY |
| 21 | bool "Ebony" | 31 | bool "Ebony" |
| 22 | depends on 44x | 32 | depends on 44x |
| @@ -293,6 +303,12 @@ config 460SX | |||
| 293 | select IBM_NEW_EMAC_ZMII | 303 | select IBM_NEW_EMAC_ZMII |
| 294 | select IBM_NEW_EMAC_TAH | 304 | select IBM_NEW_EMAC_TAH |
| 295 | 305 | ||
| 306 | config APM821xx | ||
| 307 | bool | ||
| 308 | select PPC_FPU | ||
| 309 | select IBM_NEW_EMAC_EMAC4 | ||
| 310 | select IBM_NEW_EMAC_TAH | ||
| 311 | |||
| 296 | # 44x errata/workaround config symbols, selected by the CPU models above | 312 | # 44x errata/workaround config symbols, selected by the CPU models above |
| 297 | config IBM440EP_ERR42 | 313 | config IBM440EP_ERR42 |
| 298 | bool | 314 | bool |
diff --git a/arch/powerpc/platforms/44x/ppc44x_simple.c b/arch/powerpc/platforms/44x/ppc44x_simple.c index 5f7a29d7f59..7ddcba3b939 100644 --- a/arch/powerpc/platforms/44x/ppc44x_simple.c +++ b/arch/powerpc/platforms/44x/ppc44x_simple.c | |||
| @@ -52,6 +52,7 @@ machine_device_initcall(ppc44x_simple, ppc44x_device_probe); | |||
| 52 | static char *board[] __initdata = { | 52 | static char *board[] __initdata = { |
| 53 | "amcc,arches", | 53 | "amcc,arches", |
| 54 | "amcc,bamboo", | 54 | "amcc,bamboo", |
| 55 | "amcc,bluestone", | ||
| 55 | "amcc,canyonlands", | 56 | "amcc,canyonlands", |
| 56 | "amcc,glacier", | 57 | "amcc,glacier", |
| 57 | "ibm,ebony", | 58 | "ibm,ebony", |
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig index 021763a32c2..73f4135f3a1 100644 --- a/arch/powerpc/platforms/83xx/Kconfig +++ b/arch/powerpc/platforms/83xx/Kconfig | |||
| @@ -10,12 +10,12 @@ menuconfig PPC_83xx | |||
| 10 | if PPC_83xx | 10 | if PPC_83xx |
| 11 | 11 | ||
| 12 | config MPC830x_RDB | 12 | config MPC830x_RDB |
| 13 | bool "Freescale MPC830x RDB" | 13 | bool "Freescale MPC830x RDB and derivatives" |
| 14 | select DEFAULT_UIMAGE | 14 | select DEFAULT_UIMAGE |
| 15 | select PPC_MPC831x | 15 | select PPC_MPC831x |
| 16 | select FSL_GTM | 16 | select FSL_GTM |
| 17 | help | 17 | help |
| 18 | This option enables support for the MPC8308 RDB board. | 18 | This option enables support for the MPC8308 RDB and MPC8308 P1M boards. |
| 19 | 19 | ||
| 20 | config MPC831x_RDB | 20 | config MPC831x_RDB |
| 21 | bool "Freescale MPC831x RDB" | 21 | bool "Freescale MPC831x RDB" |
diff --git a/arch/powerpc/platforms/83xx/mpc830x_rdb.c b/arch/powerpc/platforms/83xx/mpc830x_rdb.c index ac102ee9abe..846831d495b 100644 --- a/arch/powerpc/platforms/83xx/mpc830x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc830x_rdb.c | |||
| @@ -65,7 +65,8 @@ static int __init mpc830x_rdb_probe(void) | |||
| 65 | unsigned long root = of_get_flat_dt_root(); | 65 | unsigned long root = of_get_flat_dt_root(); |
| 66 | 66 | ||
| 67 | return of_flat_dt_is_compatible(root, "MPC8308RDB") || | 67 | return of_flat_dt_is_compatible(root, "MPC8308RDB") || |
| 68 | of_flat_dt_is_compatible(root, "fsl,mpc8308rdb"); | 68 | of_flat_dt_is_compatible(root, "fsl,mpc8308rdb") || |
| 69 | of_flat_dt_is_compatible(root, "denx,mpc8308_p1m"); | ||
| 69 | } | 70 | } |
| 70 | 71 | ||
| 71 | static struct of_device_id __initdata of_bus_ids[] = { | 72 | static struct of_device_id __initdata of_bus_ids[] = { |
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index bea1f5905ad..b6976e1726e 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig | |||
| @@ -11,6 +11,8 @@ menuconfig FSL_SOC_BOOKE | |||
| 11 | 11 | ||
| 12 | if FSL_SOC_BOOKE | 12 | if FSL_SOC_BOOKE |
| 13 | 13 | ||
| 14 | if PPC32 | ||
| 15 | |||
| 14 | config MPC8540_ADS | 16 | config MPC8540_ADS |
| 15 | bool "Freescale MPC8540 ADS" | 17 | bool "Freescale MPC8540 ADS" |
| 16 | select DEFAULT_UIMAGE | 18 | select DEFAULT_UIMAGE |
| @@ -153,10 +155,20 @@ config SBC8560 | |||
| 153 | help | 155 | help |
| 154 | This option enables support for the Wind River SBC8560 board | 156 | This option enables support for the Wind River SBC8560 board |
| 155 | 157 | ||
| 158 | config P3041_DS | ||
| 159 | bool "Freescale P3041 DS" | ||
| 160 | select DEFAULT_UIMAGE | ||
| 161 | select PPC_E500MC | ||
| 162 | select PHYS_64BIT | ||
| 163 | select SWIOTLB | ||
| 164 | select MPC8xxx_GPIO | ||
| 165 | select HAS_RAPIDIO | ||
| 166 | help | ||
| 167 | This option enables support for the P3041 DS board | ||
| 168 | |||
| 156 | config P4080_DS | 169 | config P4080_DS |
| 157 | bool "Freescale P4080 DS" | 170 | bool "Freescale P4080 DS" |
| 158 | select DEFAULT_UIMAGE | 171 | select DEFAULT_UIMAGE |
| 159 | select PPC_FSL_BOOK3E | ||
| 160 | select PPC_E500MC | 172 | select PPC_E500MC |
| 161 | select PHYS_64BIT | 173 | select PHYS_64BIT |
| 162 | select SWIOTLB | 174 | select SWIOTLB |
| @@ -165,6 +177,20 @@ config P4080_DS | |||
| 165 | help | 177 | help |
| 166 | This option enables support for the P4080 DS board | 178 | This option enables support for the P4080 DS board |
| 167 | 179 | ||
| 180 | endif # PPC32 | ||
| 181 | |||
| 182 | config P5020_DS | ||
| 183 | bool "Freescale P5020 DS" | ||
| 184 | select DEFAULT_UIMAGE | ||
| 185 | select E500 | ||
| 186 | select PPC_E500MC | ||
| 187 | select PHYS_64BIT | ||
| 188 | select SWIOTLB | ||
| 189 | select MPC8xxx_GPIO | ||
| 190 | select HAS_RAPIDIO | ||
| 191 | help | ||
| 192 | This option enables support for the P5020 DS board | ||
| 193 | |||
| 168 | endif # FSL_SOC_BOOKE | 194 | endif # FSL_SOC_BOOKE |
| 169 | 195 | ||
| 170 | config TQM85xx | 196 | config TQM85xx |
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index a2ec3f8f4d0..dd70db77d63 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile | |||
| @@ -11,7 +11,9 @@ obj-$(CONFIG_MPC85xx_DS) += mpc85xx_ds.o | |||
| 11 | obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o | 11 | obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o |
| 12 | obj-$(CONFIG_MPC85xx_RDB) += mpc85xx_rdb.o | 12 | obj-$(CONFIG_MPC85xx_RDB) += mpc85xx_rdb.o |
| 13 | obj-$(CONFIG_P1022_DS) += p1022_ds.o | 13 | obj-$(CONFIG_P1022_DS) += p1022_ds.o |
| 14 | obj-$(CONFIG_P3041_DS) += p3041_ds.o corenet_ds.o | ||
| 14 | obj-$(CONFIG_P4080_DS) += p4080_ds.o corenet_ds.o | 15 | obj-$(CONFIG_P4080_DS) += p4080_ds.o corenet_ds.o |
| 16 | obj-$(CONFIG_P5020_DS) += p5020_ds.o corenet_ds.o | ||
| 15 | obj-$(CONFIG_STX_GP3) += stx_gp3.o | 17 | obj-$(CONFIG_STX_GP3) += stx_gp3.o |
| 16 | obj-$(CONFIG_TQM85xx) += tqm85xx.o | 18 | obj-$(CONFIG_TQM85xx) += tqm85xx.o |
| 17 | obj-$(CONFIG_SBC8560) += sbc8560.o | 19 | obj-$(CONFIG_SBC8560) += sbc8560.o |
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c index 34e00902ce8..2b390d19a1d 100644 --- a/arch/powerpc/platforms/85xx/p1022_ds.c +++ b/arch/powerpc/platforms/85xx/p1022_ds.c | |||
| @@ -112,6 +112,8 @@ static struct of_device_id __initdata p1022_ds_ids[] = { | |||
| 112 | { .compatible = "soc", }, | 112 | { .compatible = "soc", }, |
| 113 | { .compatible = "simple-bus", }, | 113 | { .compatible = "simple-bus", }, |
| 114 | { .compatible = "gianfar", }, | 114 | { .compatible = "gianfar", }, |
| 115 | /* So that the DMA channel nodes can be probed individually: */ | ||
| 116 | { .compatible = "fsl,eloplus-dma", }, | ||
| 115 | {}, | 117 | {}, |
| 116 | }; | 118 | }; |
| 117 | 119 | ||
diff --git a/arch/powerpc/platforms/85xx/p3041_ds.c b/arch/powerpc/platforms/85xx/p3041_ds.c new file mode 100644 index 00000000000..0ed52e18298 --- /dev/null +++ b/arch/powerpc/platforms/85xx/p3041_ds.c | |||
| @@ -0,0 +1,64 @@ | |||
| 1 | /* | ||
| 2 | * P3041 DS Setup | ||
| 3 | * | ||
| 4 | * Maintained by Kumar Gala (see MAINTAINERS for contact information) | ||
| 5 | * | ||
| 6 | * Copyright 2009-2010 Freescale Semiconductor Inc. | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the | ||
| 10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 11 | * option) any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include <linux/pci.h> | ||
| 16 | #include <linux/kdev_t.h> | ||
| 17 | #include <linux/delay.h> | ||
| 18 | #include <linux/interrupt.h> | ||
| 19 | #include <linux/phy.h> | ||
| 20 | |||
| 21 | #include <asm/system.h> | ||
| 22 | #include <asm/time.h> | ||
| 23 | #include <asm/machdep.h> | ||
| 24 | #include <asm/pci-bridge.h> | ||
| 25 | #include <mm/mmu_decl.h> | ||
| 26 | #include <asm/prom.h> | ||
| 27 | #include <asm/udbg.h> | ||
| 28 | #include <asm/mpic.h> | ||
| 29 | |||
| 30 | #include <linux/of_platform.h> | ||
| 31 | #include <sysdev/fsl_soc.h> | ||
| 32 | #include <sysdev/fsl_pci.h> | ||
| 33 | |||
| 34 | #include "corenet_ds.h" | ||
| 35 | |||
| 36 | /* | ||
| 37 | * Called very early, device-tree isn't unflattened | ||
| 38 | */ | ||
| 39 | static int __init p3041_ds_probe(void) | ||
| 40 | { | ||
| 41 | unsigned long root = of_get_flat_dt_root(); | ||
| 42 | |||
| 43 | return of_flat_dt_is_compatible(root, "fsl,P3041DS"); | ||
| 44 | } | ||
| 45 | |||
| 46 | define_machine(p3041_ds) { | ||
| 47 | .name = "P3041 DS", | ||
| 48 | .probe = p3041_ds_probe, | ||
| 49 | .setup_arch = corenet_ds_setup_arch, | ||
| 50 | .init_IRQ = corenet_ds_pic_init, | ||
| 51 | #ifdef CONFIG_PCI | ||
| 52 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | ||
| 53 | #endif | ||
| 54 | .get_irq = mpic_get_coreint_irq, | ||
| 55 | .restart = fsl_rstcr_restart, | ||
| 56 | .calibrate_decr = generic_calibrate_decr, | ||
| 57 | .progress = udbg_progress, | ||
| 58 | }; | ||
| 59 | |||
| 60 | machine_device_initcall(p3041_ds, corenet_ds_publish_devices); | ||
| 61 | |||
| 62 | #ifdef CONFIG_SWIOTLB | ||
| 63 | machine_arch_initcall(p3041_ds, swiotlb_setup_bus_notifier); | ||
| 64 | #endif | ||
diff --git a/arch/powerpc/platforms/85xx/p5020_ds.c b/arch/powerpc/platforms/85xx/p5020_ds.c new file mode 100644 index 00000000000..7467b712ee0 --- /dev/null +++ b/arch/powerpc/platforms/85xx/p5020_ds.c | |||
| @@ -0,0 +1,69 @@ | |||
| 1 | /* | ||
| 2 | * P5020 DS Setup | ||
| 3 | * | ||
| 4 | * Maintained by Kumar Gala (see MAINTAINERS for contact information) | ||
| 5 | * | ||
| 6 | * Copyright 2009-2010 Freescale Semiconductor Inc. | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the | ||
| 10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 11 | * option) any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include <linux/pci.h> | ||
| 16 | #include <linux/kdev_t.h> | ||
| 17 | #include <linux/delay.h> | ||
| 18 | #include <linux/interrupt.h> | ||
| 19 | #include <linux/phy.h> | ||
| 20 | |||
| 21 | #include <asm/system.h> | ||
| 22 | #include <asm/time.h> | ||
| 23 | #include <asm/machdep.h> | ||
| 24 | #include <asm/pci-bridge.h> | ||
| 25 | #include <mm/mmu_decl.h> | ||
| 26 | #include <asm/prom.h> | ||
| 27 | #include <asm/udbg.h> | ||
| 28 | #include <asm/mpic.h> | ||
| 29 | |||
| 30 | #include <linux/of_platform.h> | ||
| 31 | #include <sysdev/fsl_soc.h> | ||
| 32 | #include <sysdev/fsl_pci.h> | ||
| 33 | |||
| 34 | #include "corenet_ds.h" | ||
| 35 | |||
| 36 | /* | ||
| 37 | * Called very early, device-tree isn't unflattened | ||
| 38 | */ | ||
| 39 | static int __init p5020_ds_probe(void) | ||
| 40 | { | ||
| 41 | unsigned long root = of_get_flat_dt_root(); | ||
| 42 | |||
| 43 | return of_flat_dt_is_compatible(root, "fsl,P5020DS"); | ||
| 44 | } | ||
| 45 | |||
| 46 | define_machine(p5020_ds) { | ||
| 47 | .name = "P5020 DS", | ||
| 48 | .probe = p5020_ds_probe, | ||
| 49 | .setup_arch = corenet_ds_setup_arch, | ||
| 50 | .init_IRQ = corenet_ds_pic_init, | ||
| 51 | #ifdef CONFIG_PCI | ||
| 52 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | ||
| 53 | #endif | ||
| 54 | /* coreint doesn't play nice with lazy EE, use legacy mpic for now */ | ||
| 55 | #ifdef CONFIG_PPC64 | ||
| 56 | .get_irq = mpic_get_irq, | ||
| 57 | #else | ||
| 58 | .get_irq = mpic_get_coreint_irq, | ||
| 59 | #endif | ||
| 60 | .restart = fsl_rstcr_restart, | ||
| 61 | .calibrate_decr = generic_calibrate_decr, | ||
| 62 | .progress = udbg_progress, | ||
| 63 | }; | ||
| 64 | |||
| 65 | machine_device_initcall(p5020_ds, corenet_ds_publish_devices); | ||
| 66 | |||
| 67 | #ifdef CONFIG_SWIOTLB | ||
| 68 | machine_arch_initcall(p5020_ds, swiotlb_setup_bus_notifier); | ||
| 69 | #endif | ||
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index a6b106557be..5c91a992f02 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
| 17 | #include <linux/of.h> | 17 | #include <linux/of.h> |
| 18 | #include <linux/kexec.h> | 18 | #include <linux/kexec.h> |
| 19 | #include <linux/highmem.h> | ||
| 19 | 20 | ||
| 20 | #include <asm/machdep.h> | 21 | #include <asm/machdep.h> |
| 21 | #include <asm/pgtable.h> | 22 | #include <asm/pgtable.h> |
| @@ -79,6 +80,7 @@ smp_85xx_kick_cpu(int nr) | |||
| 79 | local_irq_save(flags); | 80 | local_irq_save(flags); |
| 80 | 81 | ||
| 81 | out_be32(bptr_vaddr + BOOT_ENTRY_PIR, nr); | 82 | out_be32(bptr_vaddr + BOOT_ENTRY_PIR, nr); |
| 83 | #ifdef CONFIG_PPC32 | ||
| 82 | out_be32(bptr_vaddr + BOOT_ENTRY_ADDR_LOWER, __pa(__early_start)); | 84 | out_be32(bptr_vaddr + BOOT_ENTRY_ADDR_LOWER, __pa(__early_start)); |
| 83 | 85 | ||
| 84 | if (!ioremappable) | 86 | if (!ioremappable) |
| @@ -88,6 +90,12 @@ smp_85xx_kick_cpu(int nr) | |||
| 88 | /* Wait a bit for the CPU to ack. */ | 90 | /* Wait a bit for the CPU to ack. */ |
| 89 | while ((__secondary_hold_acknowledge != nr) && (++n < 1000)) | 91 | while ((__secondary_hold_acknowledge != nr) && (++n < 1000)) |
| 90 | mdelay(1); | 92 | mdelay(1); |
| 93 | #else | ||
| 94 | out_be64((u64 *)(bptr_vaddr + BOOT_ENTRY_ADDR_UPPER), | ||
| 95 | __pa((u64)*((unsigned long long *) generic_secondary_smp_init))); | ||
| 96 | |||
| 97 | smp_generic_kick_cpu(nr); | ||
| 98 | #endif | ||
| 91 | 99 | ||
| 92 | local_irq_restore(flags); | 100 | local_irq_restore(flags); |
| 93 | 101 | ||
| @@ -114,19 +122,15 @@ struct smp_ops_t smp_85xx_ops = { | |||
| 114 | }; | 122 | }; |
| 115 | 123 | ||
| 116 | #ifdef CONFIG_KEXEC | 124 | #ifdef CONFIG_KEXEC |
| 117 | static int kexec_down_cpus = 0; | 125 | atomic_t kexec_down_cpus = ATOMIC_INIT(0); |
| 118 | 126 | ||
| 119 | void mpc85xx_smp_kexec_cpu_down(int crash_shutdown, int secondary) | 127 | void mpc85xx_smp_kexec_cpu_down(int crash_shutdown, int secondary) |
| 120 | { | 128 | { |
| 121 | mpic_teardown_this_cpu(1); | 129 | local_irq_disable(); |
| 122 | |||
| 123 | /* When crashing, this gets called on all CPU's we only | ||
| 124 | * take down the non-boot cpus */ | ||
| 125 | if (smp_processor_id() != boot_cpuid) | ||
| 126 | { | ||
| 127 | local_irq_disable(); | ||
| 128 | kexec_down_cpus++; | ||
| 129 | 130 | ||
| 131 | if (secondary) { | ||
| 132 | atomic_inc(&kexec_down_cpus); | ||
| 133 | /* loop forever */ | ||
| 130 | while (1); | 134 | while (1); |
| 131 | } | 135 | } |
| 132 | } | 136 | } |
| @@ -137,16 +141,65 @@ static void mpc85xx_smp_kexec_down(void *arg) | |||
| 137 | ppc_md.kexec_cpu_down(0,1); | 141 | ppc_md.kexec_cpu_down(0,1); |
| 138 | } | 142 | } |
| 139 | 143 | ||
| 140 | static void mpc85xx_smp_machine_kexec(struct kimage *image) | 144 | static void map_and_flush(unsigned long paddr) |
| 141 | { | 145 | { |
| 142 | int timeout = 2000; | 146 | struct page *page = pfn_to_page(paddr >> PAGE_SHIFT); |
| 147 | unsigned long kaddr = (unsigned long)kmap(page); | ||
| 148 | |||
| 149 | flush_dcache_range(kaddr, kaddr + PAGE_SIZE); | ||
| 150 | kunmap(page); | ||
| 151 | } | ||
| 152 | |||
| 153 | /** | ||
| 154 | * Before we reset the other cores, we need to flush relevant cache | ||
| 155 | * out to memory so we don't get anything corrupted, some of these flushes | ||
| 156 | * are performed out of an overabundance of caution as interrupts are not | ||
| 157 | * disabled yet and we can switch cores | ||
| 158 | */ | ||
| 159 | static void mpc85xx_smp_flush_dcache_kexec(struct kimage *image) | ||
| 160 | { | ||
| 161 | kimage_entry_t *ptr, entry; | ||
| 162 | unsigned long paddr; | ||
| 143 | int i; | 163 | int i; |
| 144 | 164 | ||
| 145 | set_cpus_allowed(current, cpumask_of_cpu(boot_cpuid)); | 165 | if (image->type == KEXEC_TYPE_DEFAULT) { |
| 166 | /* normal kexec images are stored in temporary pages */ | ||
| 167 | for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); | ||
| 168 | ptr = (entry & IND_INDIRECTION) ? | ||
| 169 | phys_to_virt(entry & PAGE_MASK) : ptr + 1) { | ||
| 170 | if (!(entry & IND_DESTINATION)) { | ||
| 171 | map_and_flush(entry); | ||
| 172 | } | ||
| 173 | } | ||
| 174 | /* flush out last IND_DONE page */ | ||
| 175 | map_and_flush(entry); | ||
| 176 | } else { | ||
| 177 | /* crash type kexec images are copied to the crash region */ | ||
| 178 | for (i = 0; i < image->nr_segments; i++) { | ||
| 179 | struct kexec_segment *seg = &image->segment[i]; | ||
| 180 | for (paddr = seg->mem; paddr < seg->mem + seg->memsz; | ||
| 181 | paddr += PAGE_SIZE) { | ||
| 182 | map_and_flush(paddr); | ||
| 183 | } | ||
| 184 | } | ||
| 185 | } | ||
| 186 | |||
| 187 | /* also flush the kimage struct to be passed in as well */ | ||
| 188 | flush_dcache_range((unsigned long)image, | ||
| 189 | (unsigned long)image + sizeof(*image)); | ||
| 190 | } | ||
| 191 | |||
| 192 | static void mpc85xx_smp_machine_kexec(struct kimage *image) | ||
| 193 | { | ||
| 194 | int timeout = INT_MAX; | ||
| 195 | int i, num_cpus = num_present_cpus(); | ||
| 196 | |||
| 197 | mpc85xx_smp_flush_dcache_kexec(image); | ||
| 146 | 198 | ||
| 147 | smp_call_function(mpc85xx_smp_kexec_down, NULL, 0); | 199 | if (image->type == KEXEC_TYPE_DEFAULT) |
| 200 | smp_call_function(mpc85xx_smp_kexec_down, NULL, 0); | ||
| 148 | 201 | ||
| 149 | while ( (kexec_down_cpus != (num_online_cpus() - 1)) && | 202 | while ( (atomic_read(&kexec_down_cpus) != (num_cpus - 1)) && |
| 150 | ( timeout > 0 ) ) | 203 | ( timeout > 0 ) ) |
| 151 | { | 204 | { |
| 152 | timeout--; | 205 | timeout--; |
| @@ -155,7 +208,7 @@ static void mpc85xx_smp_machine_kexec(struct kimage *image) | |||
| 155 | if ( !timeout ) | 208 | if ( !timeout ) |
| 156 | printk(KERN_ERR "Unable to bring down secondary cpu(s)"); | 209 | printk(KERN_ERR "Unable to bring down secondary cpu(s)"); |
| 157 | 210 | ||
| 158 | for (i = 0; i < num_present_cpus(); i++) | 211 | for (i = 0; i < num_cpus; i++) |
| 159 | { | 212 | { |
| 160 | if ( i == smp_processor_id() ) continue; | 213 | if ( i == smp_processor_id() ) continue; |
| 161 | mpic_reset_core(i); | 214 | mpic_reset_core(i); |
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index d361f8119b1..111138c55f9 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype | |||
| @@ -125,6 +125,7 @@ config 8xx | |||
| 125 | 125 | ||
| 126 | config E500 | 126 | config E500 |
| 127 | select FSL_EMB_PERFMON | 127 | select FSL_EMB_PERFMON |
| 128 | select PPC_FSL_BOOK3E | ||
| 128 | bool | 129 | bool |
| 129 | 130 | ||
| 130 | config PPC_E500MC | 131 | config PPC_E500MC |
| @@ -166,9 +167,14 @@ config BOOKE | |||
| 166 | 167 | ||
| 167 | config FSL_BOOKE | 168 | config FSL_BOOKE |
| 168 | bool | 169 | bool |
| 169 | depends on E200 || E500 | 170 | depends on (E200 || E500) && PPC32 |
| 170 | default y | 171 | default y |
| 171 | 172 | ||
| 173 | # this is for common code between PPC32 & PPC64 FSL BOOKE | ||
| 174 | config PPC_FSL_BOOK3E | ||
| 175 | bool | ||
| 176 | select FSL_EMB_PERFMON | ||
| 177 | default y if FSL_BOOKE | ||
| 172 | 178 | ||
| 173 | config PTE_64BIT | 179 | config PTE_64BIT |
| 174 | bool | 180 | bool |
diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c index 1d3c4effea1..5ec1e47a0d7 100644 --- a/arch/powerpc/platforms/cell/ras.c +++ b/arch/powerpc/platforms/cell/ras.c | |||
| @@ -173,8 +173,10 @@ static int __init cbe_ptcal_enable(void) | |||
| 173 | return -ENODEV; | 173 | return -ENODEV; |
| 174 | 174 | ||
| 175 | size = of_get_property(np, "ibm,cbe-ptcal-size", NULL); | 175 | size = of_get_property(np, "ibm,cbe-ptcal-size", NULL); |
| 176 | if (!size) | 176 | if (!size) { |
| 177 | of_node_put(np); | ||
| 177 | return -ENODEV; | 178 | return -ENODEV; |
| 179 | } | ||
| 178 | 180 | ||
| 179 | pr_debug("%s: enabling PTCAL, size = 0x%x\n", __func__, *size); | 181 | pr_debug("%s: enabling PTCAL, size = 0x%x\n", __func__, *size); |
| 180 | order = get_order(*size); | 182 | order = get_order(*size); |
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c index 5876e888e41..3f2e557344a 100644 --- a/arch/powerpc/platforms/cell/spider-pic.c +++ b/arch/powerpc/platforms/cell/spider-pic.c | |||
| @@ -258,8 +258,10 @@ static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic) | |||
| 258 | return NO_IRQ; | 258 | return NO_IRQ; |
| 259 | imap += intsize + 1; | 259 | imap += intsize + 1; |
| 260 | tmp = of_get_property(iic, "#interrupt-cells", NULL); | 260 | tmp = of_get_property(iic, "#interrupt-cells", NULL); |
| 261 | if (tmp == NULL) | 261 | if (tmp == NULL) { |
| 262 | of_node_put(iic); | ||
| 262 | return NO_IRQ; | 263 | return NO_IRQ; |
| 264 | } | ||
| 263 | intsize = *tmp; | 265 | intsize = *tmp; |
| 264 | /* Assume unit is last entry of interrupt specifier */ | 266 | /* Assume unit is last entry of interrupt specifier */ |
| 265 | unit = imap[intsize - 1]; | 267 | unit = imap[intsize - 1]; |
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 1a40da92154..02f7b113a31 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c | |||
| @@ -154,6 +154,7 @@ static const struct file_operations __fops = { \ | |||
| 154 | .release = spufs_attr_release, \ | 154 | .release = spufs_attr_release, \ |
| 155 | .read = spufs_attr_read, \ | 155 | .read = spufs_attr_read, \ |
| 156 | .write = spufs_attr_write, \ | 156 | .write = spufs_attr_write, \ |
| 157 | .llseek = generic_file_llseek, \ | ||
| 157 | }; | 158 | }; |
| 158 | 159 | ||
| 159 | 160 | ||
| @@ -521,6 +522,7 @@ static const struct file_operations spufs_cntl_fops = { | |||
| 521 | .release = spufs_cntl_release, | 522 | .release = spufs_cntl_release, |
| 522 | .read = simple_attr_read, | 523 | .read = simple_attr_read, |
| 523 | .write = simple_attr_write, | 524 | .write = simple_attr_write, |
| 525 | .llseek = generic_file_llseek, | ||
| 524 | .mmap = spufs_cntl_mmap, | 526 | .mmap = spufs_cntl_mmap, |
| 525 | }; | 527 | }; |
| 526 | 528 | ||
| @@ -714,6 +716,7 @@ static ssize_t spufs_mbox_read(struct file *file, char __user *buf, | |||
| 714 | static const struct file_operations spufs_mbox_fops = { | 716 | static const struct file_operations spufs_mbox_fops = { |
| 715 | .open = spufs_pipe_open, | 717 | .open = spufs_pipe_open, |
| 716 | .read = spufs_mbox_read, | 718 | .read = spufs_mbox_read, |
| 719 | .llseek = no_llseek, | ||
| 717 | }; | 720 | }; |
| 718 | 721 | ||
| 719 | static ssize_t spufs_mbox_stat_read(struct file *file, char __user *buf, | 722 | static ssize_t spufs_mbox_stat_read(struct file *file, char __user *buf, |
| @@ -743,6 +746,7 @@ static ssize_t spufs_mbox_stat_read(struct file *file, char __user *buf, | |||
| 743 | static const struct file_operations spufs_mbox_stat_fops = { | 746 | static const struct file_operations spufs_mbox_stat_fops = { |
| 744 | .open = spufs_pipe_open, | 747 | .open = spufs_pipe_open, |
| 745 | .read = spufs_mbox_stat_read, | 748 | .read = spufs_mbox_stat_read, |
| 749 | .llseek = no_llseek, | ||
| 746 | }; | 750 | }; |
| 747 | 751 | ||
| 748 | /* low-level ibox access function */ | 752 | /* low-level ibox access function */ |
| @@ -863,6 +867,7 @@ static const struct file_operations spufs_ibox_fops = { | |||
| 863 | .read = spufs_ibox_read, | 867 | .read = spufs_ibox_read, |
| 864 | .poll = spufs_ibox_poll, | 868 | .poll = spufs_ibox_poll, |
| 865 | .fasync = spufs_ibox_fasync, | 869 | .fasync = spufs_ibox_fasync, |
| 870 | .llseek = no_llseek, | ||
| 866 | }; | 871 | }; |
| 867 | 872 | ||
| 868 | static ssize_t spufs_ibox_stat_read(struct file *file, char __user *buf, | 873 | static ssize_t spufs_ibox_stat_read(struct file *file, char __user *buf, |
| @@ -890,6 +895,7 @@ static ssize_t spufs_ibox_stat_read(struct file *file, char __user *buf, | |||
| 890 | static const struct file_operations spufs_ibox_stat_fops = { | 895 | static const struct file_operations spufs_ibox_stat_fops = { |
| 891 | .open = spufs_pipe_open, | 896 | .open = spufs_pipe_open, |
| 892 | .read = spufs_ibox_stat_read, | 897 | .read = spufs_ibox_stat_read, |
| 898 | .llseek = no_llseek, | ||
| 893 | }; | 899 | }; |
| 894 | 900 | ||
| 895 | /* low-level mailbox write */ | 901 | /* low-level mailbox write */ |
| @@ -1011,6 +1017,7 @@ static const struct file_operations spufs_wbox_fops = { | |||
| 1011 | .write = spufs_wbox_write, | 1017 | .write = spufs_wbox_write, |
| 1012 | .poll = spufs_wbox_poll, | 1018 | .poll = spufs_wbox_poll, |
| 1013 | .fasync = spufs_wbox_fasync, | 1019 | .fasync = spufs_wbox_fasync, |
| 1020 | .llseek = no_llseek, | ||
| 1014 | }; | 1021 | }; |
| 1015 | 1022 | ||
| 1016 | static ssize_t spufs_wbox_stat_read(struct file *file, char __user *buf, | 1023 | static ssize_t spufs_wbox_stat_read(struct file *file, char __user *buf, |
| @@ -1038,6 +1045,7 @@ static ssize_t spufs_wbox_stat_read(struct file *file, char __user *buf, | |||
| 1038 | static const struct file_operations spufs_wbox_stat_fops = { | 1045 | static const struct file_operations spufs_wbox_stat_fops = { |
| 1039 | .open = spufs_pipe_open, | 1046 | .open = spufs_pipe_open, |
| 1040 | .read = spufs_wbox_stat_read, | 1047 | .read = spufs_wbox_stat_read, |
| 1048 | .llseek = no_llseek, | ||
| 1041 | }; | 1049 | }; |
| 1042 | 1050 | ||
| 1043 | static int spufs_signal1_open(struct inode *inode, struct file *file) | 1051 | static int spufs_signal1_open(struct inode *inode, struct file *file) |
| @@ -1166,6 +1174,7 @@ static const struct file_operations spufs_signal1_fops = { | |||
| 1166 | .read = spufs_signal1_read, | 1174 | .read = spufs_signal1_read, |
| 1167 | .write = spufs_signal1_write, | 1175 | .write = spufs_signal1_write, |
| 1168 | .mmap = spufs_signal1_mmap, | 1176 | .mmap = spufs_signal1_mmap, |
| 1177 | .llseek = no_llseek, | ||
| 1169 | }; | 1178 | }; |
| 1170 | 1179 | ||
| 1171 | static const struct file_operations spufs_signal1_nosched_fops = { | 1180 | static const struct file_operations spufs_signal1_nosched_fops = { |
| @@ -1173,6 +1182,7 @@ static const struct file_operations spufs_signal1_nosched_fops = { | |||
| 1173 | .release = spufs_signal1_release, | 1182 | .release = spufs_signal1_release, |
| 1174 | .write = spufs_signal1_write, | 1183 | .write = spufs_signal1_write, |
| 1175 | .mmap = spufs_signal1_mmap, | 1184 | .mmap = spufs_signal1_mmap, |
| 1185 | .llseek = no_llseek, | ||
| 1176 | }; | 1186 | }; |
| 1177 | 1187 | ||
| 1178 | static int spufs_signal2_open(struct inode *inode, struct file *file) | 1188 | static int spufs_signal2_open(struct inode *inode, struct file *file) |
| @@ -1305,6 +1315,7 @@ static const struct file_operations spufs_signal2_fops = { | |||
| 1305 | .read = spufs_signal2_read, | 1315 | .read = spufs_signal2_read, |
| 1306 | .write = spufs_signal2_write, | 1316 | .write = spufs_signal2_write, |
| 1307 | .mmap = spufs_signal2_mmap, | 1317 | .mmap = spufs_signal2_mmap, |
| 1318 | .llseek = no_llseek, | ||
| 1308 | }; | 1319 | }; |
| 1309 | 1320 | ||
| 1310 | static const struct file_operations spufs_signal2_nosched_fops = { | 1321 | static const struct file_operations spufs_signal2_nosched_fops = { |
| @@ -1312,6 +1323,7 @@ static const struct file_operations spufs_signal2_nosched_fops = { | |||
| 1312 | .release = spufs_signal2_release, | 1323 | .release = spufs_signal2_release, |
| 1313 | .write = spufs_signal2_write, | 1324 | .write = spufs_signal2_write, |
| 1314 | .mmap = spufs_signal2_mmap, | 1325 | .mmap = spufs_signal2_mmap, |
| 1326 | .llseek = no_llseek, | ||
| 1315 | }; | 1327 | }; |
| 1316 | 1328 | ||
| 1317 | /* | 1329 | /* |
| @@ -1451,6 +1463,7 @@ static const struct file_operations spufs_mss_fops = { | |||
| 1451 | .open = spufs_mss_open, | 1463 | .open = spufs_mss_open, |
| 1452 | .release = spufs_mss_release, | 1464 | .release = spufs_mss_release, |
| 1453 | .mmap = spufs_mss_mmap, | 1465 | .mmap = spufs_mss_mmap, |
| 1466 | .llseek = no_llseek, | ||
| 1454 | }; | 1467 | }; |
| 1455 | 1468 | ||
| 1456 | static int | 1469 | static int |
| @@ -1508,6 +1521,7 @@ static const struct file_operations spufs_psmap_fops = { | |||
| 1508 | .open = spufs_psmap_open, | 1521 | .open = spufs_psmap_open, |
| 1509 | .release = spufs_psmap_release, | 1522 | .release = spufs_psmap_release, |
| 1510 | .mmap = spufs_psmap_mmap, | 1523 | .mmap = spufs_psmap_mmap, |
| 1524 | .llseek = no_llseek, | ||
| 1511 | }; | 1525 | }; |
| 1512 | 1526 | ||
| 1513 | 1527 | ||
| @@ -1871,6 +1885,7 @@ static const struct file_operations spufs_mfc_fops = { | |||
| 1871 | .fsync = spufs_mfc_fsync, | 1885 | .fsync = spufs_mfc_fsync, |
| 1872 | .fasync = spufs_mfc_fasync, | 1886 | .fasync = spufs_mfc_fasync, |
| 1873 | .mmap = spufs_mfc_mmap, | 1887 | .mmap = spufs_mfc_mmap, |
| 1888 | .llseek = no_llseek, | ||
| 1874 | }; | 1889 | }; |
| 1875 | 1890 | ||
| 1876 | static int spufs_npc_set(void *data, u64 val) | 1891 | static int spufs_npc_set(void *data, u64 val) |
| @@ -2246,6 +2261,7 @@ static ssize_t spufs_dma_info_read(struct file *file, char __user *buf, | |||
| 2246 | static const struct file_operations spufs_dma_info_fops = { | 2261 | static const struct file_operations spufs_dma_info_fops = { |
| 2247 | .open = spufs_info_open, | 2262 | .open = spufs_info_open, |
| 2248 | .read = spufs_dma_info_read, | 2263 | .read = spufs_dma_info_read, |
| 2264 | .llseek = no_llseek, | ||
| 2249 | }; | 2265 | }; |
| 2250 | 2266 | ||
| 2251 | static ssize_t __spufs_proxydma_info_read(struct spu_context *ctx, | 2267 | static ssize_t __spufs_proxydma_info_read(struct spu_context *ctx, |
| @@ -2299,6 +2315,7 @@ static ssize_t spufs_proxydma_info_read(struct file *file, char __user *buf, | |||
| 2299 | static const struct file_operations spufs_proxydma_info_fops = { | 2315 | static const struct file_operations spufs_proxydma_info_fops = { |
| 2300 | .open = spufs_info_open, | 2316 | .open = spufs_info_open, |
| 2301 | .read = spufs_proxydma_info_read, | 2317 | .read = spufs_proxydma_info_read, |
| 2318 | .llseek = no_llseek, | ||
| 2302 | }; | 2319 | }; |
| 2303 | 2320 | ||
| 2304 | static int spufs_show_tid(struct seq_file *s, void *private) | 2321 | static int spufs_show_tid(struct seq_file *s, void *private) |
| @@ -2585,6 +2602,7 @@ static const struct file_operations spufs_switch_log_fops = { | |||
| 2585 | .read = spufs_switch_log_read, | 2602 | .read = spufs_switch_log_read, |
| 2586 | .poll = spufs_switch_log_poll, | 2603 | .poll = spufs_switch_log_poll, |
| 2587 | .release = spufs_switch_log_release, | 2604 | .release = spufs_switch_log_release, |
| 2605 | .llseek = no_llseek, | ||
| 2588 | }; | 2606 | }; |
| 2589 | 2607 | ||
| 2590 | /** | 2608 | /** |
diff --git a/arch/powerpc/platforms/chrp/nvram.c b/arch/powerpc/platforms/chrp/nvram.c index ba3588f2d8e..d3ceff04ffc 100644 --- a/arch/powerpc/platforms/chrp/nvram.c +++ b/arch/powerpc/platforms/chrp/nvram.c | |||
| @@ -74,8 +74,10 @@ void __init chrp_nvram_init(void) | |||
| 74 | return; | 74 | return; |
| 75 | 75 | ||
| 76 | nbytes_p = of_get_property(nvram, "#bytes", &proplen); | 76 | nbytes_p = of_get_property(nvram, "#bytes", &proplen); |
| 77 | if (nbytes_p == NULL || proplen != sizeof(unsigned int)) | 77 | if (nbytes_p == NULL || proplen != sizeof(unsigned int)) { |
| 78 | of_node_put(nvram); | ||
| 78 | return; | 79 | return; |
| 80 | } | ||
| 79 | 81 | ||
| 80 | nvram_size = *nbytes_p; | 82 | nvram_size = *nbytes_p; |
| 81 | 83 | ||
diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile index ce014928d46..a7602b11ed9 100644 --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | EXTRA_CFLAGS += -mno-minimal-toc | 1 | ccflags-y := -mno-minimal-toc |
| 2 | 2 | ||
| 3 | obj-y += exception.o | 3 | obj-y += exception.o |
| 4 | obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt.o mf.o lpevents.o \ | 4 | obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt.o mf.o lpevents.o \ |
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c index 7f45a51fe79..fdb7384c0c4 100644 --- a/arch/powerpc/platforms/iseries/dt.c +++ b/arch/powerpc/platforms/iseries/dt.c | |||
| @@ -243,7 +243,7 @@ static void __init dt_cpus(struct iseries_flat_dt *dt) | |||
| 243 | pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE); | 243 | pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE); |
| 244 | 244 | ||
| 245 | for (i = 0; i < NR_CPUS; i++) { | 245 | for (i = 0; i < NR_CPUS; i++) { |
| 246 | if (lppaca[i].dyn_proc_status >= 2) | 246 | if (lppaca_of(i).dyn_proc_status >= 2) |
| 247 | continue; | 247 | continue; |
| 248 | 248 | ||
| 249 | snprintf(p, 32 - (p - buf), "@%d", i); | 249 | snprintf(p, 32 - (p - buf), "@%d", i); |
| @@ -251,7 +251,7 @@ static void __init dt_cpus(struct iseries_flat_dt *dt) | |||
| 251 | 251 | ||
| 252 | dt_prop_str(dt, "device_type", device_type_cpu); | 252 | dt_prop_str(dt, "device_type", device_type_cpu); |
| 253 | 253 | ||
| 254 | index = lppaca[i].dyn_hv_phys_proc_index; | 254 | index = lppaca_of(i).dyn_hv_phys_proc_index; |
| 255 | d = &xIoHriProcessorVpd[index]; | 255 | d = &xIoHriProcessorVpd[index]; |
| 256 | 256 | ||
| 257 | dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024); | 257 | dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024); |
diff --git a/arch/powerpc/platforms/iseries/smp.c b/arch/powerpc/platforms/iseries/smp.c index 6590850045a..6c6029914db 100644 --- a/arch/powerpc/platforms/iseries/smp.c +++ b/arch/powerpc/platforms/iseries/smp.c | |||
| @@ -91,7 +91,7 @@ static void smp_iSeries_kick_cpu(int nr) | |||
| 91 | BUG_ON((nr < 0) || (nr >= NR_CPUS)); | 91 | BUG_ON((nr < 0) || (nr >= NR_CPUS)); |
| 92 | 92 | ||
| 93 | /* Verify that our partition has a processor nr */ | 93 | /* Verify that our partition has a processor nr */ |
| 94 | if (lppaca[nr].dyn_proc_status >= 2) | 94 | if (lppaca_of(nr).dyn_proc_status >= 2) |
| 95 | return; | 95 | return; |
| 96 | 96 | ||
| 97 | /* The processor is currently spinning, waiting | 97 | /* The processor is currently spinning, waiting |
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index 3fff8d979b4..fe34c3d9bb7 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c | |||
| @@ -358,6 +358,7 @@ static int __init maple_cpc925_edac_setup(void) | |||
| 358 | model = (const unsigned char *)of_get_property(np, "model", NULL); | 358 | model = (const unsigned char *)of_get_property(np, "model", NULL); |
| 359 | if (!model) { | 359 | if (!model) { |
| 360 | printk(KERN_ERR "%s: Unabel to get model info\n", __func__); | 360 | printk(KERN_ERR "%s: Unabel to get model info\n", __func__); |
| 361 | of_node_put(np); | ||
| 361 | return -ENODEV; | 362 | return -ENODEV; |
| 362 | } | 363 | } |
| 363 | 364 | ||
diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c index cec63594265..b0c3777528a 100644 --- a/arch/powerpc/platforms/powermac/pfunc_core.c +++ b/arch/powerpc/platforms/powermac/pfunc_core.c | |||
| @@ -837,8 +837,10 @@ struct pmf_function *__pmf_find_function(struct device_node *target, | |||
| 837 | return NULL; | 837 | return NULL; |
| 838 | find_it: | 838 | find_it: |
| 839 | dev = pmf_find_device(actor); | 839 | dev = pmf_find_device(actor); |
| 840 | if (dev == NULL) | 840 | if (dev == NULL) { |
| 841 | return NULL; | 841 | result = NULL; |
| 842 | goto out; | ||
| 843 | } | ||
| 842 | 844 | ||
| 843 | list_for_each_entry(func, &dev->functions, link) { | 845 | list_for_each_entry(func, &dev->functions, link) { |
| 844 | if (name && strcmp(name, func->name)) | 846 | if (name && strcmp(name, func->name)) |
| @@ -850,8 +852,9 @@ struct pmf_function *__pmf_find_function(struct device_node *target, | |||
| 850 | result = func; | 852 | result = func; |
| 851 | break; | 853 | break; |
| 852 | } | 854 | } |
| 853 | of_node_put(actor); | ||
| 854 | pmf_put_device(dev); | 855 | pmf_put_device(dev); |
| 856 | out: | ||
| 857 | of_node_put(actor); | ||
| 855 | return result; | 858 | return result; |
| 856 | } | 859 | } |
| 857 | 860 | ||
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 046ace9c438..59eb8bdaa79 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile | |||
| @@ -1,14 +1,9 @@ | |||
| 1 | ifeq ($(CONFIG_PPC64),y) | 1 | ccflags-$(CONFIG_PPC64) := -mno-minimal-toc |
| 2 | EXTRA_CFLAGS += -mno-minimal-toc | 2 | ccflags-$(CONFIG_PPC_PSERIES_DEBUG) += -DDEBUG |
| 3 | endif | ||
| 4 | |||
| 5 | ifeq ($(CONFIG_PPC_PSERIES_DEBUG),y) | ||
| 6 | EXTRA_CFLAGS += -DDEBUG | ||
| 7 | endif | ||
| 8 | 3 | ||
| 9 | obj-y := lpar.o hvCall.o nvram.o reconfig.o \ | 4 | obj-y := lpar.o hvCall.o nvram.o reconfig.o \ |
| 10 | setup.o iommu.o event_sources.o ras.o \ | 5 | setup.o iommu.o event_sources.o ras.o \ |
| 11 | firmware.o power.o dlpar.o | 6 | firmware.o power.o dlpar.o mobility.o |
| 12 | obj-$(CONFIG_SMP) += smp.o | 7 | obj-$(CONFIG_SMP) += smp.o |
| 13 | obj-$(CONFIG_XICS) += xics.o | 8 | obj-$(CONFIG_XICS) += xics.o |
| 14 | obj-$(CONFIG_SCANLOG) += scanlog.o | 9 | obj-$(CONFIG_SCANLOG) += scanlog.o |
| @@ -23,7 +18,7 @@ obj-$(CONFIG_MEMORY_HOTPLUG) += hotplug-memory.o | |||
| 23 | obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o | 18 | obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o |
| 24 | obj-$(CONFIG_HVCS) += hvcserver.o | 19 | obj-$(CONFIG_HVCS) += hvcserver.o |
| 25 | obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o | 20 | obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o |
| 26 | obj-$(CONFIG_PHYP_DUMP) += phyp_dump.o | 21 | obj-$(CONFIG_PHYP_DUMP) += phyp_dump.o |
| 27 | obj-$(CONFIG_CMM) += cmm.o | 22 | obj-$(CONFIG_CMM) += cmm.o |
| 28 | obj-$(CONFIG_DTL) += dtl.o | 23 | obj-$(CONFIG_DTL) += dtl.o |
| 29 | 24 | ||
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index 72d8054fa73..b74a9230edc 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c | |||
| @@ -33,7 +33,7 @@ struct cc_workarea { | |||
| 33 | u32 prop_offset; | 33 | u32 prop_offset; |
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | static void dlpar_free_cc_property(struct property *prop) | 36 | void dlpar_free_cc_property(struct property *prop) |
| 37 | { | 37 | { |
| 38 | kfree(prop->name); | 38 | kfree(prop->name); |
| 39 | kfree(prop->value); | 39 | kfree(prop->value); |
| @@ -55,13 +55,12 @@ static struct property *dlpar_parse_cc_property(struct cc_workarea *ccwa) | |||
| 55 | 55 | ||
| 56 | prop->length = ccwa->prop_length; | 56 | prop->length = ccwa->prop_length; |
| 57 | value = (char *)ccwa + ccwa->prop_offset; | 57 | value = (char *)ccwa + ccwa->prop_offset; |
| 58 | prop->value = kzalloc(prop->length, GFP_KERNEL); | 58 | prop->value = kmemdup(value, prop->length, GFP_KERNEL); |
| 59 | if (!prop->value) { | 59 | if (!prop->value) { |
| 60 | dlpar_free_cc_property(prop); | 60 | dlpar_free_cc_property(prop); |
| 61 | return NULL; | 61 | return NULL; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | memcpy(prop->value, value, prop->length); | ||
| 65 | return prop; | 64 | return prop; |
| 66 | } | 65 | } |
| 67 | 66 | ||
| @@ -102,7 +101,7 @@ static void dlpar_free_one_cc_node(struct device_node *dn) | |||
| 102 | kfree(dn); | 101 | kfree(dn); |
| 103 | } | 102 | } |
| 104 | 103 | ||
| 105 | static void dlpar_free_cc_nodes(struct device_node *dn) | 104 | void dlpar_free_cc_nodes(struct device_node *dn) |
| 106 | { | 105 | { |
| 107 | if (dn->child) | 106 | if (dn->child) |
| 108 | dlpar_free_cc_nodes(dn->child); | 107 | dlpar_free_cc_nodes(dn->child); |
diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c index a00addb5594..c371bc06434 100644 --- a/arch/powerpc/platforms/pseries/dtl.c +++ b/arch/powerpc/platforms/pseries/dtl.c | |||
| @@ -23,37 +23,22 @@ | |||
| 23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
| 24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
| 25 | #include <linux/debugfs.h> | 25 | #include <linux/debugfs.h> |
| 26 | #include <linux/spinlock.h> | ||
| 26 | #include <asm/smp.h> | 27 | #include <asm/smp.h> |
| 27 | #include <asm/system.h> | 28 | #include <asm/system.h> |
| 28 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
| 29 | #include <asm/firmware.h> | 30 | #include <asm/firmware.h> |
| 31 | #include <asm/lppaca.h> | ||
| 30 | 32 | ||
| 31 | #include "plpar_wrappers.h" | 33 | #include "plpar_wrappers.h" |
| 32 | 34 | ||
| 33 | /* | ||
| 34 | * Layout of entries in the hypervisor's DTL buffer. Although we don't | ||
| 35 | * actually access the internals of an entry (we only need to know the size), | ||
| 36 | * we might as well define it here for reference. | ||
| 37 | */ | ||
| 38 | struct dtl_entry { | ||
| 39 | u8 dispatch_reason; | ||
| 40 | u8 preempt_reason; | ||
| 41 | u16 processor_id; | ||
| 42 | u32 enqueue_to_dispatch_time; | ||
| 43 | u32 ready_to_enqueue_time; | ||
| 44 | u32 waiting_to_ready_time; | ||
| 45 | u64 timebase; | ||
| 46 | u64 fault_addr; | ||
| 47 | u64 srr0; | ||
| 48 | u64 srr1; | ||
| 49 | }; | ||
| 50 | |||
| 51 | struct dtl { | 35 | struct dtl { |
| 52 | struct dtl_entry *buf; | 36 | struct dtl_entry *buf; |
| 53 | struct dentry *file; | 37 | struct dentry *file; |
| 54 | int cpu; | 38 | int cpu; |
| 55 | int buf_entries; | 39 | int buf_entries; |
| 56 | u64 last_idx; | 40 | u64 last_idx; |
| 41 | spinlock_t lock; | ||
| 57 | }; | 42 | }; |
| 58 | static DEFINE_PER_CPU(struct dtl, cpu_dtl); | 43 | static DEFINE_PER_CPU(struct dtl, cpu_dtl); |
| 59 | 44 | ||
| @@ -72,25 +57,97 @@ static u8 dtl_event_mask = 0x7; | |||
| 72 | static int dtl_buf_entries = (16 * 85); | 57 | static int dtl_buf_entries = (16 * 85); |
| 73 | 58 | ||
| 74 | 59 | ||
| 75 | static int dtl_enable(struct dtl *dtl) | 60 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
| 61 | struct dtl_ring { | ||
| 62 | u64 write_index; | ||
| 63 | struct dtl_entry *write_ptr; | ||
| 64 | struct dtl_entry *buf; | ||
| 65 | struct dtl_entry *buf_end; | ||
| 66 | u8 saved_dtl_mask; | ||
| 67 | }; | ||
| 68 | |||
| 69 | static DEFINE_PER_CPU(struct dtl_ring, dtl_rings); | ||
| 70 | |||
| 71 | static atomic_t dtl_count; | ||
| 72 | |||
| 73 | /* | ||
| 74 | * The cpu accounting code controls the DTL ring buffer, and we get | ||
| 75 | * given entries as they are processed. | ||
| 76 | */ | ||
| 77 | static void consume_dtle(struct dtl_entry *dtle, u64 index) | ||
| 76 | { | 78 | { |
| 77 | unsigned long addr; | 79 | struct dtl_ring *dtlr = &__get_cpu_var(dtl_rings); |
| 78 | int ret, hwcpu; | 80 | struct dtl_entry *wp = dtlr->write_ptr; |
| 81 | struct lppaca *vpa = local_paca->lppaca_ptr; | ||
| 79 | 82 | ||
| 80 | /* only allow one reader */ | 83 | if (!wp) |
| 81 | if (dtl->buf) | 84 | return; |
| 82 | return -EBUSY; | ||
| 83 | 85 | ||
| 84 | /* we need to store the original allocation size for use during read */ | 86 | *wp = *dtle; |
| 85 | dtl->buf_entries = dtl_buf_entries; | 87 | barrier(); |
| 86 | 88 | ||
| 87 | dtl->buf = kmalloc_node(dtl->buf_entries * sizeof(struct dtl_entry), | 89 | /* check for hypervisor ring buffer overflow, ignore this entry if so */ |
| 88 | GFP_KERNEL, cpu_to_node(dtl->cpu)); | 90 | if (index + N_DISPATCH_LOG < vpa->dtl_idx) |
| 89 | if (!dtl->buf) { | 91 | return; |
| 90 | printk(KERN_WARNING "%s: buffer alloc failed for cpu %d\n", | 92 | |
| 91 | __func__, dtl->cpu); | 93 | ++wp; |
| 92 | return -ENOMEM; | 94 | if (wp == dtlr->buf_end) |
| 93 | } | 95 | wp = dtlr->buf; |
| 96 | dtlr->write_ptr = wp; | ||
| 97 | |||
| 98 | /* incrementing write_index makes the new entry visible */ | ||
| 99 | smp_wmb(); | ||
| 100 | ++dtlr->write_index; | ||
| 101 | } | ||
| 102 | |||
| 103 | static int dtl_start(struct dtl *dtl) | ||
| 104 | { | ||
| 105 | struct dtl_ring *dtlr = &per_cpu(dtl_rings, dtl->cpu); | ||
| 106 | |||
| 107 | dtlr->buf = dtl->buf; | ||
| 108 | dtlr->buf_end = dtl->buf + dtl->buf_entries; | ||
| 109 | dtlr->write_index = 0; | ||
| 110 | |||
| 111 | /* setting write_ptr enables logging into our buffer */ | ||
| 112 | smp_wmb(); | ||
| 113 | dtlr->write_ptr = dtl->buf; | ||
| 114 | |||
| 115 | /* enable event logging */ | ||
| 116 | dtlr->saved_dtl_mask = lppaca_of(dtl->cpu).dtl_enable_mask; | ||
| 117 | lppaca_of(dtl->cpu).dtl_enable_mask |= dtl_event_mask; | ||
| 118 | |||
| 119 | dtl_consumer = consume_dtle; | ||
| 120 | atomic_inc(&dtl_count); | ||
| 121 | return 0; | ||
| 122 | } | ||
| 123 | |||
| 124 | static void dtl_stop(struct dtl *dtl) | ||
| 125 | { | ||
| 126 | struct dtl_ring *dtlr = &per_cpu(dtl_rings, dtl->cpu); | ||
| 127 | |||
| 128 | dtlr->write_ptr = NULL; | ||
| 129 | smp_wmb(); | ||
| 130 | |||
| 131 | dtlr->buf = NULL; | ||
| 132 | |||
| 133 | /* restore dtl_enable_mask */ | ||
| 134 | lppaca_of(dtl->cpu).dtl_enable_mask = dtlr->saved_dtl_mask; | ||
| 135 | |||
| 136 | if (atomic_dec_and_test(&dtl_count)) | ||
| 137 | dtl_consumer = NULL; | ||
| 138 | } | ||
| 139 | |||
| 140 | static u64 dtl_current_index(struct dtl *dtl) | ||
| 141 | { | ||
| 142 | return per_cpu(dtl_rings, dtl->cpu).write_index; | ||
| 143 | } | ||
| 144 | |||
| 145 | #else /* CONFIG_VIRT_CPU_ACCOUNTING */ | ||
| 146 | |||
| 147 | static int dtl_start(struct dtl *dtl) | ||
| 148 | { | ||
| 149 | unsigned long addr; | ||
| 150 | int ret, hwcpu; | ||
| 94 | 151 | ||
| 95 | /* Register our dtl buffer with the hypervisor. The HV expects the | 152 | /* Register our dtl buffer with the hypervisor. The HV expects the |
| 96 | * buffer size to be passed in the second word of the buffer */ | 153 | * buffer size to be passed in the second word of the buffer */ |
| @@ -102,34 +159,82 @@ static int dtl_enable(struct dtl *dtl) | |||
| 102 | if (ret) { | 159 | if (ret) { |
| 103 | printk(KERN_WARNING "%s: DTL registration for cpu %d (hw %d) " | 160 | printk(KERN_WARNING "%s: DTL registration for cpu %d (hw %d) " |
| 104 | "failed with %d\n", __func__, dtl->cpu, hwcpu, ret); | 161 | "failed with %d\n", __func__, dtl->cpu, hwcpu, ret); |
| 105 | kfree(dtl->buf); | ||
| 106 | return -EIO; | 162 | return -EIO; |
| 107 | } | 163 | } |
| 108 | 164 | ||
| 109 | /* set our initial buffer indices */ | 165 | /* set our initial buffer indices */ |
| 110 | dtl->last_idx = lppaca[dtl->cpu].dtl_idx = 0; | 166 | lppaca_of(dtl->cpu).dtl_idx = 0; |
| 111 | 167 | ||
| 112 | /* ensure that our updates to the lppaca fields have occurred before | 168 | /* ensure that our updates to the lppaca fields have occurred before |
| 113 | * we actually enable the logging */ | 169 | * we actually enable the logging */ |
| 114 | smp_wmb(); | 170 | smp_wmb(); |
| 115 | 171 | ||
| 116 | /* enable event logging */ | 172 | /* enable event logging */ |
| 117 | lppaca[dtl->cpu].dtl_enable_mask = dtl_event_mask; | 173 | lppaca_of(dtl->cpu).dtl_enable_mask = dtl_event_mask; |
| 118 | 174 | ||
| 119 | return 0; | 175 | return 0; |
| 120 | } | 176 | } |
| 121 | 177 | ||
| 122 | static void dtl_disable(struct dtl *dtl) | 178 | static void dtl_stop(struct dtl *dtl) |
| 123 | { | 179 | { |
| 124 | int hwcpu = get_hard_smp_processor_id(dtl->cpu); | 180 | int hwcpu = get_hard_smp_processor_id(dtl->cpu); |
| 125 | 181 | ||
| 126 | lppaca[dtl->cpu].dtl_enable_mask = 0x0; | 182 | lppaca_of(dtl->cpu).dtl_enable_mask = 0x0; |
| 127 | 183 | ||
| 128 | unregister_dtl(hwcpu, __pa(dtl->buf)); | 184 | unregister_dtl(hwcpu, __pa(dtl->buf)); |
| 185 | } | ||
| 186 | |||
| 187 | static u64 dtl_current_index(struct dtl *dtl) | ||
| 188 | { | ||
| 189 | return lppaca_of(dtl->cpu).dtl_idx; | ||
| 190 | } | ||
| 191 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING */ | ||
| 192 | |||
| 193 | static int dtl_enable(struct dtl *dtl) | ||
| 194 | { | ||
| 195 | long int n_entries; | ||
| 196 | long int rc; | ||
| 197 | struct dtl_entry *buf = NULL; | ||
| 129 | 198 | ||
| 199 | /* only allow one reader */ | ||
| 200 | if (dtl->buf) | ||
| 201 | return -EBUSY; | ||
| 202 | |||
| 203 | n_entries = dtl_buf_entries; | ||
| 204 | buf = kmalloc_node(n_entries * sizeof(struct dtl_entry), | ||
| 205 | GFP_KERNEL, cpu_to_node(dtl->cpu)); | ||
| 206 | if (!buf) { | ||
| 207 | printk(KERN_WARNING "%s: buffer alloc failed for cpu %d\n", | ||
| 208 | __func__, dtl->cpu); | ||
| 209 | return -ENOMEM; | ||
| 210 | } | ||
| 211 | |||
| 212 | spin_lock(&dtl->lock); | ||
| 213 | rc = -EBUSY; | ||
| 214 | if (!dtl->buf) { | ||
| 215 | /* store the original allocation size for use during read */ | ||
| 216 | dtl->buf_entries = n_entries; | ||
| 217 | dtl->buf = buf; | ||
| 218 | dtl->last_idx = 0; | ||
| 219 | rc = dtl_start(dtl); | ||
| 220 | if (rc) | ||
| 221 | dtl->buf = NULL; | ||
| 222 | } | ||
| 223 | spin_unlock(&dtl->lock); | ||
| 224 | |||
| 225 | if (rc) | ||
| 226 | kfree(buf); | ||
| 227 | return rc; | ||
| 228 | } | ||
| 229 | |||
| 230 | static void dtl_disable(struct dtl *dtl) | ||
| 231 | { | ||
| 232 | spin_lock(&dtl->lock); | ||
| 233 | dtl_stop(dtl); | ||
| 130 | kfree(dtl->buf); | 234 | kfree(dtl->buf); |
| 131 | dtl->buf = NULL; | 235 | dtl->buf = NULL; |
| 132 | dtl->buf_entries = 0; | 236 | dtl->buf_entries = 0; |
| 237 | spin_unlock(&dtl->lock); | ||
| 133 | } | 238 | } |
| 134 | 239 | ||
| 135 | /* file interface */ | 240 | /* file interface */ |
| @@ -157,8 +262,9 @@ static int dtl_file_release(struct inode *inode, struct file *filp) | |||
| 157 | static ssize_t dtl_file_read(struct file *filp, char __user *buf, size_t len, | 262 | static ssize_t dtl_file_read(struct file *filp, char __user *buf, size_t len, |
| 158 | loff_t *pos) | 263 | loff_t *pos) |
| 159 | { | 264 | { |
| 160 | int rc, cur_idx, last_idx, n_read, n_req, read_size; | 265 | long int rc, n_read, n_req, read_size; |
| 161 | struct dtl *dtl; | 266 | struct dtl *dtl; |
| 267 | u64 cur_idx, last_idx, i; | ||
| 162 | 268 | ||
| 163 | if ((len % sizeof(struct dtl_entry)) != 0) | 269 | if ((len % sizeof(struct dtl_entry)) != 0) |
| 164 | return -EINVAL; | 270 | return -EINVAL; |
| @@ -171,41 +277,48 @@ static ssize_t dtl_file_read(struct file *filp, char __user *buf, size_t len, | |||
| 171 | /* actual number of entries read */ | 277 | /* actual number of entries read */ |
| 172 | n_read = 0; | 278 | n_read = 0; |
| 173 | 279 | ||
| 174 | cur_idx = lppaca[dtl->cpu].dtl_idx; | 280 | spin_lock(&dtl->lock); |
| 281 | |||
| 282 | cur_idx = dtl_current_index(dtl); | ||
| 175 | last_idx = dtl->last_idx; | 283 | last_idx = dtl->last_idx; |
| 176 | 284 | ||
| 177 | if (cur_idx - last_idx > dtl->buf_entries) { | 285 | if (last_idx + dtl->buf_entries <= cur_idx) |
| 178 | pr_debug("%s: hv buffer overflow for cpu %d, samples lost\n", | 286 | last_idx = cur_idx - dtl->buf_entries + 1; |
| 179 | __func__, dtl->cpu); | 287 | |
| 180 | } | 288 | if (last_idx + n_req > cur_idx) |
| 289 | n_req = cur_idx - last_idx; | ||
| 290 | |||
| 291 | if (n_req > 0) | ||
| 292 | dtl->last_idx = last_idx + n_req; | ||
| 293 | |||
| 294 | spin_unlock(&dtl->lock); | ||
| 295 | |||
| 296 | if (n_req <= 0) | ||
| 297 | return 0; | ||
| 181 | 298 | ||
| 182 | cur_idx %= dtl->buf_entries; | 299 | i = last_idx % dtl->buf_entries; |
| 183 | last_idx %= dtl->buf_entries; | ||
| 184 | 300 | ||
| 185 | /* read the tail of the buffer if we've wrapped */ | 301 | /* read the tail of the buffer if we've wrapped */ |
| 186 | if (last_idx > cur_idx) { | 302 | if (i + n_req > dtl->buf_entries) { |
| 187 | read_size = min(n_req, dtl->buf_entries - last_idx); | 303 | read_size = dtl->buf_entries - i; |
| 188 | 304 | ||
| 189 | rc = copy_to_user(buf, &dtl->buf[last_idx], | 305 | rc = copy_to_user(buf, &dtl->buf[i], |
| 190 | read_size * sizeof(struct dtl_entry)); | 306 | read_size * sizeof(struct dtl_entry)); |
| 191 | if (rc) | 307 | if (rc) |
| 192 | return -EFAULT; | 308 | return -EFAULT; |
| 193 | 309 | ||
| 194 | last_idx = 0; | 310 | i = 0; |
| 195 | n_req -= read_size; | 311 | n_req -= read_size; |
| 196 | n_read += read_size; | 312 | n_read += read_size; |
| 197 | buf += read_size * sizeof(struct dtl_entry); | 313 | buf += read_size * sizeof(struct dtl_entry); |
| 198 | } | 314 | } |
| 199 | 315 | ||
| 200 | /* .. and now the head */ | 316 | /* .. and now the head */ |
| 201 | read_size = min(n_req, cur_idx - last_idx); | 317 | rc = copy_to_user(buf, &dtl->buf[i], n_req * sizeof(struct dtl_entry)); |
| 202 | rc = copy_to_user(buf, &dtl->buf[last_idx], | ||
| 203 | read_size * sizeof(struct dtl_entry)); | ||
| 204 | if (rc) | 318 | if (rc) |
| 205 | return -EFAULT; | 319 | return -EFAULT; |
| 206 | 320 | ||
| 207 | n_read += read_size; | 321 | n_read += n_req; |
| 208 | dtl->last_idx += n_read; | ||
| 209 | 322 | ||
| 210 | return n_read * sizeof(struct dtl_entry); | 323 | return n_read * sizeof(struct dtl_entry); |
| 211 | } | 324 | } |
| @@ -263,6 +376,7 @@ static int dtl_init(void) | |||
| 263 | /* set up the per-cpu log structures */ | 376 | /* set up the per-cpu log structures */ |
| 264 | for_each_possible_cpu(i) { | 377 | for_each_possible_cpu(i) { |
| 265 | struct dtl *dtl = &per_cpu(cpu_dtl, i); | 378 | struct dtl *dtl = &per_cpu(cpu_dtl, i); |
| 379 | spin_lock_init(&dtl->lock); | ||
| 266 | dtl->cpu = i; | 380 | dtl->cpu = i; |
| 267 | 381 | ||
| 268 | rc = dtl_setup_file(dtl); | 382 | rc = dtl_setup_file(dtl); |
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index cf79b46d8f8..f129040d974 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c | |||
| @@ -248,11 +248,13 @@ void vpa_init(int cpu) | |||
| 248 | int hwcpu = get_hard_smp_processor_id(cpu); | 248 | int hwcpu = get_hard_smp_processor_id(cpu); |
| 249 | unsigned long addr; | 249 | unsigned long addr; |
| 250 | long ret; | 250 | long ret; |
| 251 | struct paca_struct *pp; | ||
| 252 | struct dtl_entry *dtl; | ||
| 251 | 253 | ||
| 252 | if (cpu_has_feature(CPU_FTR_ALTIVEC)) | 254 | if (cpu_has_feature(CPU_FTR_ALTIVEC)) |
| 253 | lppaca[cpu].vmxregs_in_use = 1; | 255 | lppaca_of(cpu).vmxregs_in_use = 1; |
| 254 | 256 | ||
| 255 | addr = __pa(&lppaca[cpu]); | 257 | addr = __pa(&lppaca_of(cpu)); |
| 256 | ret = register_vpa(hwcpu, addr); | 258 | ret = register_vpa(hwcpu, addr); |
| 257 | 259 | ||
| 258 | if (ret) { | 260 | if (ret) { |
| @@ -274,6 +276,25 @@ void vpa_init(int cpu) | |||
| 274 | "registration for cpu %d (hw %d) of area %lx " | 276 | "registration for cpu %d (hw %d) of area %lx " |
| 275 | "returns %ld\n", cpu, hwcpu, addr, ret); | 277 | "returns %ld\n", cpu, hwcpu, addr, ret); |
| 276 | } | 278 | } |
| 279 | |||
| 280 | /* | ||
| 281 | * Register dispatch trace log, if one has been allocated. | ||
| 282 | */ | ||
| 283 | pp = &paca[cpu]; | ||
| 284 | dtl = pp->dispatch_log; | ||
| 285 | if (dtl) { | ||
| 286 | pp->dtl_ridx = 0; | ||
| 287 | pp->dtl_curr = dtl; | ||
| 288 | lppaca_of(cpu).dtl_idx = 0; | ||
| 289 | |||
| 290 | /* hypervisor reads buffer length from this field */ | ||
| 291 | dtl->enqueue_to_dispatch_time = DISPATCH_LOG_BYTES; | ||
| 292 | ret = register_dtl(hwcpu, __pa(dtl)); | ||
| 293 | if (ret) | ||
| 294 | pr_warn("DTL registration failed for cpu %d (%ld)\n", | ||
| 295 | cpu, ret); | ||
| 296 | lppaca_of(cpu).dtl_enable_mask = 2; | ||
| 297 | } | ||
| 277 | } | 298 | } |
| 278 | 299 | ||
| 279 | static long pSeries_lpar_hpte_insert(unsigned long hpte_group, | 300 | static long pSeries_lpar_hpte_insert(unsigned long hpte_group, |
diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c new file mode 100644 index 00000000000..3e7f651e50a --- /dev/null +++ b/arch/powerpc/platforms/pseries/mobility.c | |||
| @@ -0,0 +1,362 @@ | |||
| 1 | /* | ||
| 2 | * Support for Partition Mobility/Migration | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Nathan Fontenot | ||
| 5 | * Copyright (C) 2010 IBM Corporation | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU General Public License version | ||
| 9 | * 2 as published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/kobject.h> | ||
| 14 | #include <linux/smp.h> | ||
| 15 | #include <linux/completion.h> | ||
| 16 | #include <linux/device.h> | ||
| 17 | #include <linux/delay.h> | ||
| 18 | #include <linux/slab.h> | ||
| 19 | |||
| 20 | #include <asm/rtas.h> | ||
| 21 | #include "pseries.h" | ||
| 22 | |||
| 23 | static struct kobject *mobility_kobj; | ||
| 24 | |||
| 25 | struct update_props_workarea { | ||
| 26 | u32 phandle; | ||
| 27 | u32 state; | ||
| 28 | u64 reserved; | ||
| 29 | u32 nprops; | ||
| 30 | }; | ||
| 31 | |||
| 32 | #define NODE_ACTION_MASK 0xff000000 | ||
| 33 | #define NODE_COUNT_MASK 0x00ffffff | ||
| 34 | |||
| 35 | #define DELETE_DT_NODE 0x01000000 | ||
| 36 | #define UPDATE_DT_NODE 0x02000000 | ||
| 37 | #define ADD_DT_NODE 0x03000000 | ||
| 38 | |||
| 39 | static int mobility_rtas_call(int token, char *buf) | ||
| 40 | { | ||
| 41 | int rc; | ||
| 42 | |||
| 43 | spin_lock(&rtas_data_buf_lock); | ||
| 44 | |||
| 45 | memcpy(rtas_data_buf, buf, RTAS_DATA_BUF_SIZE); | ||
| 46 | rc = rtas_call(token, 2, 1, NULL, rtas_data_buf, 1); | ||
| 47 | memcpy(buf, rtas_data_buf, RTAS_DATA_BUF_SIZE); | ||
| 48 | |||
| 49 | spin_unlock(&rtas_data_buf_lock); | ||
| 50 | return rc; | ||
| 51 | } | ||
| 52 | |||
| 53 | static int delete_dt_node(u32 phandle) | ||
| 54 | { | ||
| 55 | struct device_node *dn; | ||
| 56 | |||
| 57 | dn = of_find_node_by_phandle(phandle); | ||
| 58 | if (!dn) | ||
| 59 | return -ENOENT; | ||
| 60 | |||
| 61 | dlpar_detach_node(dn); | ||
| 62 | return 0; | ||
| 63 | } | ||
| 64 | |||
| 65 | static int update_dt_property(struct device_node *dn, struct property **prop, | ||
| 66 | const char *name, u32 vd, char *value) | ||
| 67 | { | ||
| 68 | struct property *new_prop = *prop; | ||
| 69 | struct property *old_prop; | ||
| 70 | int more = 0; | ||
| 71 | |||
| 72 | /* A negative 'vd' value indicates that only part of the new property | ||
| 73 | * value is contained in the buffer and we need to call | ||
| 74 | * ibm,update-properties again to get the rest of the value. | ||
| 75 | * | ||
| 76 | * A negative value is also the two's compliment of the actual value. | ||
| 77 | */ | ||
| 78 | if (vd & 0x80000000) { | ||
| 79 | vd = ~vd + 1; | ||
| 80 | more = 1; | ||
| 81 | } | ||
| 82 | |||
| 83 | if (new_prop) { | ||
| 84 | /* partial property fixup */ | ||
| 85 | char *new_data = kzalloc(new_prop->length + vd, GFP_KERNEL); | ||
| 86 | if (!new_data) | ||
| 87 | return -ENOMEM; | ||
| 88 | |||
| 89 | memcpy(new_data, new_prop->value, new_prop->length); | ||
| 90 | memcpy(new_data + new_prop->length, value, vd); | ||
| 91 | |||
| 92 | kfree(new_prop->value); | ||
| 93 | new_prop->value = new_data; | ||
| 94 | new_prop->length += vd; | ||
| 95 | } else { | ||
| 96 | new_prop = kzalloc(sizeof(*new_prop), GFP_KERNEL); | ||
| 97 | if (!new_prop) | ||
| 98 | return -ENOMEM; | ||
| 99 | |||
| 100 | new_prop->name = kstrdup(name, GFP_KERNEL); | ||
| 101 | if (!new_prop->name) { | ||
| 102 | kfree(new_prop); | ||
| 103 | return -ENOMEM; | ||
| 104 | } | ||
| 105 | |||
| 106 | new_prop->length = vd; | ||
| 107 | new_prop->value = kzalloc(new_prop->length, GFP_KERNEL); | ||
| 108 | if (!new_prop->value) { | ||
| 109 | kfree(new_prop->name); | ||
| 110 | kfree(new_prop); | ||
| 111 | return -ENOMEM; | ||
| 112 | } | ||
| 113 | |||
| 114 | memcpy(new_prop->value, value, vd); | ||
| 115 | *prop = new_prop; | ||
| 116 | } | ||
| 117 | |||
| 118 | if (!more) { | ||
| 119 | old_prop = of_find_property(dn, new_prop->name, NULL); | ||
| 120 | if (old_prop) | ||
| 121 | prom_update_property(dn, new_prop, old_prop); | ||
| 122 | else | ||
| 123 | prom_add_property(dn, new_prop); | ||
| 124 | |||
| 125 | new_prop = NULL; | ||
| 126 | } | ||
| 127 | |||
| 128 | return 0; | ||
| 129 | } | ||
| 130 | |||
| 131 | static int update_dt_node(u32 phandle) | ||
| 132 | { | ||
| 133 | struct update_props_workarea *upwa; | ||
| 134 | struct device_node *dn; | ||
| 135 | struct property *prop = NULL; | ||
| 136 | int i, rc; | ||
| 137 | char *prop_data; | ||
| 138 | char *rtas_buf; | ||
| 139 | int update_properties_token; | ||
| 140 | |||
| 141 | update_properties_token = rtas_token("ibm,update-properties"); | ||
| 142 | if (update_properties_token == RTAS_UNKNOWN_SERVICE) | ||
| 143 | return -EINVAL; | ||
| 144 | |||
| 145 | rtas_buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL); | ||
| 146 | if (!rtas_buf) | ||
| 147 | return -ENOMEM; | ||
| 148 | |||
| 149 | dn = of_find_node_by_phandle(phandle); | ||
| 150 | if (!dn) { | ||
| 151 | kfree(rtas_buf); | ||
| 152 | return -ENOENT; | ||
| 153 | } | ||
| 154 | |||
| 155 | upwa = (struct update_props_workarea *)&rtas_buf[0]; | ||
| 156 | upwa->phandle = phandle; | ||
| 157 | |||
| 158 | do { | ||
| 159 | rc = mobility_rtas_call(update_properties_token, rtas_buf); | ||
| 160 | if (rc < 0) | ||
| 161 | break; | ||
| 162 | |||
| 163 | prop_data = rtas_buf + sizeof(*upwa); | ||
| 164 | |||
| 165 | for (i = 0; i < upwa->nprops; i++) { | ||
| 166 | char *prop_name; | ||
| 167 | u32 vd; | ||
| 168 | |||
| 169 | prop_name = prop_data + 1; | ||
| 170 | prop_data += strlen(prop_name) + 1; | ||
| 171 | vd = *prop_data++; | ||
| 172 | |||
| 173 | switch (vd) { | ||
| 174 | case 0x00000000: | ||
| 175 | /* name only property, nothing to do */ | ||
| 176 | break; | ||
| 177 | |||
| 178 | case 0x80000000: | ||
| 179 | prop = of_find_property(dn, prop_name, NULL); | ||
| 180 | prom_remove_property(dn, prop); | ||
| 181 | prop = NULL; | ||
| 182 | break; | ||
| 183 | |||
| 184 | default: | ||
| 185 | rc = update_dt_property(dn, &prop, prop_name, | ||
| 186 | vd, prop_data); | ||
| 187 | if (rc) { | ||
| 188 | printk(KERN_ERR "Could not update %s" | ||
| 189 | " property\n", prop_name); | ||
| 190 | } | ||
| 191 | |||
| 192 | prop_data += vd; | ||
| 193 | } | ||
| 194 | } | ||
| 195 | } while (rc == 1); | ||
| 196 | |||
| 197 | of_node_put(dn); | ||
| 198 | kfree(rtas_buf); | ||
| 199 | return 0; | ||
| 200 | } | ||
| 201 | |||
| 202 | static int add_dt_node(u32 parent_phandle, u32 drc_index) | ||
| 203 | { | ||
| 204 | struct device_node *dn; | ||
| 205 | struct device_node *parent_dn; | ||
| 206 | int rc; | ||
| 207 | |||
| 208 | dn = dlpar_configure_connector(drc_index); | ||
| 209 | if (!dn) | ||
| 210 | return -ENOENT; | ||
| 211 | |||
| 212 | parent_dn = of_find_node_by_phandle(parent_phandle); | ||
| 213 | if (!parent_dn) { | ||
| 214 | dlpar_free_cc_nodes(dn); | ||
| 215 | return -ENOENT; | ||
| 216 | } | ||
| 217 | |||
| 218 | dn->parent = parent_dn; | ||
| 219 | rc = dlpar_attach_node(dn); | ||
| 220 | if (rc) | ||
| 221 | dlpar_free_cc_nodes(dn); | ||
| 222 | |||
| 223 | of_node_put(parent_dn); | ||
| 224 | return rc; | ||
| 225 | } | ||
| 226 | |||
| 227 | static int pseries_devicetree_update(void) | ||
| 228 | { | ||
| 229 | char *rtas_buf; | ||
| 230 | u32 *data; | ||
| 231 | int update_nodes_token; | ||
| 232 | int rc; | ||
| 233 | |||
| 234 | update_nodes_token = rtas_token("ibm,update-nodes"); | ||
| 235 | if (update_nodes_token == RTAS_UNKNOWN_SERVICE) | ||
| 236 | return -EINVAL; | ||
| 237 | |||
| 238 | rtas_buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL); | ||
| 239 | if (!rtas_buf) | ||
| 240 | return -ENOMEM; | ||
| 241 | |||
| 242 | do { | ||
| 243 | rc = mobility_rtas_call(update_nodes_token, rtas_buf); | ||
| 244 | if (rc && rc != 1) | ||
| 245 | break; | ||
| 246 | |||
| 247 | data = (u32 *)rtas_buf + 4; | ||
| 248 | while (*data & NODE_ACTION_MASK) { | ||
| 249 | int i; | ||
| 250 | u32 action = *data & NODE_ACTION_MASK; | ||
| 251 | int node_count = *data & NODE_COUNT_MASK; | ||
| 252 | |||
| 253 | data++; | ||
| 254 | |||
| 255 | for (i = 0; i < node_count; i++) { | ||
| 256 | u32 phandle = *data++; | ||
| 257 | u32 drc_index; | ||
| 258 | |||
| 259 | switch (action) { | ||
| 260 | case DELETE_DT_NODE: | ||
| 261 | delete_dt_node(phandle); | ||
| 262 | break; | ||
| 263 | case UPDATE_DT_NODE: | ||
| 264 | update_dt_node(phandle); | ||
| 265 | break; | ||
| 266 | case ADD_DT_NODE: | ||
| 267 | drc_index = *data++; | ||
| 268 | add_dt_node(phandle, drc_index); | ||
| 269 | break; | ||
| 270 | } | ||
| 271 | } | ||
| 272 | } | ||
| 273 | } while (rc == 1); | ||
| 274 | |||
| 275 | kfree(rtas_buf); | ||
| 276 | return rc; | ||
| 277 | } | ||
| 278 | |||
| 279 | void post_mobility_fixup(void) | ||
| 280 | { | ||
| 281 | int rc; | ||
| 282 | int activate_fw_token; | ||
| 283 | |||
| 284 | rc = pseries_devicetree_update(); | ||
| 285 | if (rc) { | ||
| 286 | printk(KERN_ERR "Initial post-mobility device tree update " | ||
| 287 | "failed: %d\n", rc); | ||
| 288 | return; | ||
| 289 | } | ||
| 290 | |||
| 291 | activate_fw_token = rtas_token("ibm,activate-firmware"); | ||
| 292 | if (activate_fw_token == RTAS_UNKNOWN_SERVICE) { | ||
| 293 | printk(KERN_ERR "Could not make post-mobility " | ||
| 294 | "activate-fw call.\n"); | ||
| 295 | return; | ||
| 296 | } | ||
| 297 | |||
| 298 | rc = rtas_call(activate_fw_token, 0, 1, NULL); | ||
| 299 | if (!rc) { | ||
| 300 | rc = pseries_devicetree_update(); | ||
| 301 | if (rc) | ||
| 302 | printk(KERN_ERR "Secondary post-mobility device tree " | ||
| 303 | "update failed: %d\n", rc); | ||
| 304 | } else { | ||
| 305 | printk(KERN_ERR "Post-mobility activate-fw failed: %d\n", rc); | ||
| 306 | return; | ||
| 307 | } | ||
| 308 | |||
| 309 | return; | ||
| 310 | } | ||
| 311 | |||
| 312 | static ssize_t migrate_store(struct class *class, struct class_attribute *attr, | ||
| 313 | const char *buf, size_t count) | ||
| 314 | { | ||
| 315 | struct rtas_args args; | ||
| 316 | u64 streamid; | ||
| 317 | int rc; | ||
| 318 | |||
| 319 | rc = strict_strtoull(buf, 0, &streamid); | ||
| 320 | if (rc) | ||
| 321 | return rc; | ||
| 322 | |||
| 323 | memset(&args, 0, sizeof(args)); | ||
| 324 | args.token = rtas_token("ibm,suspend-me"); | ||
| 325 | args.nargs = 2; | ||
| 326 | args.nret = 1; | ||
| 327 | |||
| 328 | args.args[0] = streamid >> 32 ; | ||
| 329 | args.args[1] = streamid & 0xffffffff; | ||
| 330 | args.rets = &args.args[args.nargs]; | ||
| 331 | |||
| 332 | do { | ||
| 333 | args.rets[0] = 0; | ||
| 334 | rc = rtas_ibm_suspend_me(&args); | ||
| 335 | if (!rc && args.rets[0] == RTAS_NOT_SUSPENDABLE) | ||
| 336 | ssleep(1); | ||
| 337 | } while (!rc && args.rets[0] == RTAS_NOT_SUSPENDABLE); | ||
| 338 | |||
| 339 | if (rc) | ||
| 340 | return rc; | ||
| 341 | else if (args.rets[0]) | ||
| 342 | return args.rets[0]; | ||
| 343 | |||
| 344 | post_mobility_fixup(); | ||
| 345 | return count; | ||
| 346 | } | ||
| 347 | |||
| 348 | static CLASS_ATTR(migration, S_IWUSR, NULL, migrate_store); | ||
| 349 | |||
| 350 | static int __init mobility_sysfs_init(void) | ||
| 351 | { | ||
| 352 | int rc; | ||
| 353 | |||
| 354 | mobility_kobj = kobject_create_and_add("mobility", kernel_kobj); | ||
| 355 | if (!mobility_kobj) | ||
| 356 | return -ENOMEM; | ||
| 357 | |||
| 358 | rc = sysfs_create_file(mobility_kobj, &class_attr_migration.attr); | ||
| 359 | |||
| 360 | return rc; | ||
| 361 | } | ||
| 362 | device_initcall(mobility_sysfs_init); | ||
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h index 40c93cad91d..e9f6d2859c3 100644 --- a/arch/powerpc/platforms/pseries/pseries.h +++ b/arch/powerpc/platforms/pseries/pseries.h | |||
| @@ -17,6 +17,8 @@ struct device_node; | |||
| 17 | extern void request_event_sources_irqs(struct device_node *np, | 17 | extern void request_event_sources_irqs(struct device_node *np, |
| 18 | irq_handler_t handler, const char *name); | 18 | irq_handler_t handler, const char *name); |
| 19 | 19 | ||
| 20 | #include <linux/of.h> | ||
| 21 | |||
| 20 | extern void __init fw_feature_init(const char *hypertas, unsigned long len); | 22 | extern void __init fw_feature_init(const char *hypertas, unsigned long len); |
| 21 | 23 | ||
| 22 | struct pt_regs; | 24 | struct pt_regs; |
| @@ -47,4 +49,11 @@ extern unsigned long rtas_poweron_auto; | |||
| 47 | 49 | ||
| 48 | extern void find_udbg_vterm(void); | 50 | extern void find_udbg_vterm(void); |
| 49 | 51 | ||
| 52 | /* Dynamic logical Partitioning/Mobility */ | ||
| 53 | extern void dlpar_free_cc_nodes(struct device_node *); | ||
| 54 | extern void dlpar_free_cc_property(struct property *); | ||
| 55 | extern struct device_node *dlpar_configure_connector(u32); | ||
| 56 | extern int dlpar_attach_node(struct device_node *); | ||
| 57 | extern int dlpar_detach_node(struct device_node *); | ||
| 58 | |||
| 50 | #endif /* _PSERIES_PSERIES_H */ | 59 | #endif /* _PSERIES_PSERIES_H */ |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index a6d19e3a505..d345bfd56bb 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
| @@ -273,6 +273,58 @@ static struct notifier_block pci_dn_reconfig_nb = { | |||
| 273 | .notifier_call = pci_dn_reconfig_notifier, | 273 | .notifier_call = pci_dn_reconfig_notifier, |
| 274 | }; | 274 | }; |
| 275 | 275 | ||
| 276 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
| 277 | /* | ||
| 278 | * Allocate space for the dispatch trace log for all possible cpus | ||
| 279 | * and register the buffers with the hypervisor. This is used for | ||
| 280 | * computing time stolen by the hypervisor. | ||
| 281 | */ | ||
| 282 | static int alloc_dispatch_logs(void) | ||
| 283 | { | ||
| 284 | int cpu, ret; | ||
| 285 | struct paca_struct *pp; | ||
| 286 | struct dtl_entry *dtl; | ||
| 287 | |||
| 288 | if (!firmware_has_feature(FW_FEATURE_SPLPAR)) | ||
| 289 | return 0; | ||
| 290 | |||
| 291 | for_each_possible_cpu(cpu) { | ||
| 292 | pp = &paca[cpu]; | ||
| 293 | dtl = kmalloc_node(DISPATCH_LOG_BYTES, GFP_KERNEL, | ||
| 294 | cpu_to_node(cpu)); | ||
| 295 | if (!dtl) { | ||
| 296 | pr_warn("Failed to allocate dispatch trace log for cpu %d\n", | ||
| 297 | cpu); | ||
| 298 | pr_warn("Stolen time statistics will be unreliable\n"); | ||
| 299 | break; | ||
| 300 | } | ||
| 301 | |||
| 302 | pp->dtl_ridx = 0; | ||
| 303 | pp->dispatch_log = dtl; | ||
| 304 | pp->dispatch_log_end = dtl + N_DISPATCH_LOG; | ||
| 305 | pp->dtl_curr = dtl; | ||
| 306 | } | ||
| 307 | |||
| 308 | /* Register the DTL for the current (boot) cpu */ | ||
| 309 | dtl = get_paca()->dispatch_log; | ||
| 310 | get_paca()->dtl_ridx = 0; | ||
| 311 | get_paca()->dtl_curr = dtl; | ||
| 312 | get_paca()->lppaca_ptr->dtl_idx = 0; | ||
| 313 | |||
| 314 | /* hypervisor reads buffer length from this field */ | ||
| 315 | dtl->enqueue_to_dispatch_time = DISPATCH_LOG_BYTES; | ||
| 316 | ret = register_dtl(hard_smp_processor_id(), __pa(dtl)); | ||
| 317 | if (ret) | ||
| 318 | pr_warn("DTL registration failed for boot cpu %d (%d)\n", | ||
| 319 | smp_processor_id(), ret); | ||
| 320 | get_paca()->lppaca_ptr->dtl_enable_mask = 2; | ||
| 321 | |||
| 322 | return 0; | ||
| 323 | } | ||
| 324 | |||
| 325 | early_initcall(alloc_dispatch_logs); | ||
| 326 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING */ | ||
| 327 | |||
| 276 | static void __init pSeries_setup_arch(void) | 328 | static void __init pSeries_setup_arch(void) |
| 277 | { | 329 | { |
| 278 | /* Discover PIC type and setup ppc_md accordingly */ | 330 | /* Discover PIC type and setup ppc_md accordingly */ |
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 67e2c4bdac8..7b96e5a270c 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c | |||
| @@ -178,7 +178,7 @@ static int get_irq_server(unsigned int virq, const struct cpumask *cpumask, | |||
| 178 | if (!distribute_irqs) | 178 | if (!distribute_irqs) |
| 179 | return default_server; | 179 | return default_server; |
| 180 | 180 | ||
| 181 | if (!cpumask_equal(cpumask, cpu_all_mask)) { | 181 | if (!cpumask_subset(cpu_possible_mask, cpumask)) { |
| 182 | int server = cpumask_first_and(cpu_online_mask, cpumask); | 182 | int server = cpumask_first_and(cpu_online_mask, cpumask); |
| 183 | 183 | ||
| 184 | if (server < nr_cpu_ids) | 184 | if (server < nr_cpu_ids) |
