aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/44x/Kconfig16
-rw-r--r--arch/powerpc/platforms/44x/ppc44x_simple.c1
-rw-r--r--arch/powerpc/platforms/83xx/Kconfig4
-rw-r--r--arch/powerpc/platforms/83xx/mpc830x_rdb.c3
-rw-r--r--arch/powerpc/platforms/85xx/Kconfig28
-rw-r--r--arch/powerpc/platforms/85xx/Makefile2
-rw-r--r--arch/powerpc/platforms/85xx/p1022_ds.c2
-rw-r--r--arch/powerpc/platforms/85xx/p3041_ds.c64
-rw-r--r--arch/powerpc/platforms/85xx/p5020_ds.c69
-rw-r--r--arch/powerpc/platforms/85xx/smp.c83
-rw-r--r--arch/powerpc/platforms/Kconfig.cputype8
-rw-r--r--arch/powerpc/platforms/cell/ras.c4
-rw-r--r--arch/powerpc/platforms/cell/spider-pic.c4
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c18
-rw-r--r--arch/powerpc/platforms/chrp/nvram.c4
-rw-r--r--arch/powerpc/platforms/iseries/Makefile2
-rw-r--r--arch/powerpc/platforms/iseries/dt.c4
-rw-r--r--arch/powerpc/platforms/iseries/smp.c2
-rw-r--r--arch/powerpc/platforms/maple/setup.c1
-rw-r--r--arch/powerpc/platforms/powermac/pfunc_core.c9
-rw-r--r--arch/powerpc/platforms/pseries/Makefile13
-rw-r--r--arch/powerpc/platforms/pseries/dlpar.c7
-rw-r--r--arch/powerpc/platforms/pseries/dtl.c224
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c25
-rw-r--r--arch/powerpc/platforms/pseries/mobility.c362
-rw-r--r--arch/powerpc/platforms/pseries/pseries.h9
-rw-r--r--arch/powerpc/platforms/pseries/setup.c52
-rw-r--r--arch/powerpc/platforms/pseries/xics.c2
28 files changed, 921 insertions, 101 deletions
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
index 69d668c072ae..0f979c5c756b 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
20config 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
20config EBONY 30config 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
306config 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
297config IBM440EP_ERR42 313config 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 5f7a29d7f590..7ddcba3b9397 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);
52static char *board[] __initdata = { 52static 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 021763a32c2f..73f4135f3a1a 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -10,12 +10,12 @@ menuconfig PPC_83xx
10if PPC_83xx 10if PPC_83xx
11 11
12config MPC830x_RDB 12config 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
20config MPC831x_RDB 20config 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 ac102ee9abe8..846831d495b5 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
71static struct of_device_id __initdata of_bus_ids[] = { 72static struct of_device_id __initdata of_bus_ids[] = {
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index bea1f5905ad4..b6976e1726e4 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -11,6 +11,8 @@ menuconfig FSL_SOC_BOOKE
11 11
12if FSL_SOC_BOOKE 12if FSL_SOC_BOOKE
13 13
14if PPC32
15
14config MPC8540_ADS 16config 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
158config 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
156config P4080_DS 169config 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
180endif # PPC32
181
182config 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
168endif # FSL_SOC_BOOKE 194endif # FSL_SOC_BOOKE
169 195
170config TQM85xx 196config TQM85xx
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index a2ec3f8f4d06..dd70db77d63e 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -11,7 +11,9 @@ obj-$(CONFIG_MPC85xx_DS) += mpc85xx_ds.o
11obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o 11obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o
12obj-$(CONFIG_MPC85xx_RDB) += mpc85xx_rdb.o 12obj-$(CONFIG_MPC85xx_RDB) += mpc85xx_rdb.o
13obj-$(CONFIG_P1022_DS) += p1022_ds.o 13obj-$(CONFIG_P1022_DS) += p1022_ds.o
14obj-$(CONFIG_P3041_DS) += p3041_ds.o corenet_ds.o
14obj-$(CONFIG_P4080_DS) += p4080_ds.o corenet_ds.o 15obj-$(CONFIG_P4080_DS) += p4080_ds.o corenet_ds.o
16obj-$(CONFIG_P5020_DS) += p5020_ds.o corenet_ds.o
15obj-$(CONFIG_STX_GP3) += stx_gp3.o 17obj-$(CONFIG_STX_GP3) += stx_gp3.o
16obj-$(CONFIG_TQM85xx) += tqm85xx.o 18obj-$(CONFIG_TQM85xx) += tqm85xx.o
17obj-$(CONFIG_SBC8560) += sbc8560.o 19obj-$(CONFIG_SBC8560) += sbc8560.o
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index 34e00902ce86..2b390d19a1d1 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 000000000000..0ed52e18298c
--- /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 */
39static 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
46define_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
60machine_device_initcall(p3041_ds, corenet_ds_publish_devices);
61
62#ifdef CONFIG_SWIOTLB
63machine_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 000000000000..7467b712ee00
--- /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 */
39static 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
46define_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
65machine_device_initcall(p5020_ds, corenet_ds_publish_devices);
66
67#ifdef CONFIG_SWIOTLB
68machine_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 a6b106557be4..5c91a992f02b 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
117static int kexec_down_cpus = 0; 125atomic_t kexec_down_cpus = ATOMIC_INIT(0);
118 126
119void mpc85xx_smp_kexec_cpu_down(int crash_shutdown, int secondary) 127void 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
140static void mpc85xx_smp_machine_kexec(struct kimage *image) 144static 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 */
159static 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
192static 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 d361f8119b1e..111138c55f9c 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -125,6 +125,7 @@ config 8xx
125 125
126config E500 126config E500
127 select FSL_EMB_PERFMON 127 select FSL_EMB_PERFMON
128 select PPC_FSL_BOOK3E
128 bool 129 bool
129 130
130config PPC_E500MC 131config PPC_E500MC
@@ -166,9 +167,14 @@ config BOOKE
166 167
167config FSL_BOOKE 168config 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
174config PPC_FSL_BOOK3E
175 bool
176 select FSL_EMB_PERFMON
177 default y if FSL_BOOKE
172 178
173config PTE_64BIT 179config PTE_64BIT
174 bool 180 bool
diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c
index 1d3c4effea10..5ec1e47a0d77 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 5876e888e412..3f2e557344a3 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 1a40da92154c..02f7b113a31b 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,
714static const struct file_operations spufs_mbox_fops = { 716static 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
719static ssize_t spufs_mbox_stat_read(struct file *file, char __user *buf, 722static 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,
743static const struct file_operations spufs_mbox_stat_fops = { 746static 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
868static ssize_t spufs_ibox_stat_read(struct file *file, char __user *buf, 873static 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,
890static const struct file_operations spufs_ibox_stat_fops = { 895static 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
1016static ssize_t spufs_wbox_stat_read(struct file *file, char __user *buf, 1023static 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,
1038static const struct file_operations spufs_wbox_stat_fops = { 1045static 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
1043static int spufs_signal1_open(struct inode *inode, struct file *file) 1051static 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
1171static const struct file_operations spufs_signal1_nosched_fops = { 1180static 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
1178static int spufs_signal2_open(struct inode *inode, struct file *file) 1188static 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
1310static const struct file_operations spufs_signal2_nosched_fops = { 1321static 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
1456static int 1469static 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
1876static int spufs_npc_set(void *data, u64 val) 1891static 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,
2246static const struct file_operations spufs_dma_info_fops = { 2261static 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
2251static ssize_t __spufs_proxydma_info_read(struct spu_context *ctx, 2267static 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,
2299static const struct file_operations spufs_proxydma_info_fops = { 2315static 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
2304static int spufs_show_tid(struct seq_file *s, void *private) 2321static 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 ba3588f2d8e0..d3ceff04ffc7 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 ce014928d460..a7602b11ed9d 100644
--- a/arch/powerpc/platforms/iseries/Makefile
+++ b/arch/powerpc/platforms/iseries/Makefile
@@ -1,4 +1,4 @@
1EXTRA_CFLAGS += -mno-minimal-toc 1ccflags-y := -mno-minimal-toc
2 2
3obj-y += exception.o 3obj-y += exception.o
4obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt.o mf.o lpevents.o \ 4obj-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 7f45a51fe793..fdb7384c0c4f 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 6590850045af..6c6029914dbc 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 3fff8d979b41..fe34c3d9bb74 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 cec635942657..b0c3777528a1 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);
856out:
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 046ace9c4381..59eb8bdaa79d 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -1,14 +1,9 @@
1ifeq ($(CONFIG_PPC64),y) 1ccflags-$(CONFIG_PPC64) := -mno-minimal-toc
2EXTRA_CFLAGS += -mno-minimal-toc 2ccflags-$(CONFIG_PPC_PSERIES_DEBUG) += -DDEBUG
3endif
4
5ifeq ($(CONFIG_PPC_PSERIES_DEBUG),y)
6EXTRA_CFLAGS += -DDEBUG
7endif
8 3
9obj-y := lpar.o hvCall.o nvram.o reconfig.o \ 4obj-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
12obj-$(CONFIG_SMP) += smp.o 7obj-$(CONFIG_SMP) += smp.o
13obj-$(CONFIG_XICS) += xics.o 8obj-$(CONFIG_XICS) += xics.o
14obj-$(CONFIG_SCANLOG) += scanlog.o 9obj-$(CONFIG_SCANLOG) += scanlog.o
@@ -23,7 +18,7 @@ obj-$(CONFIG_MEMORY_HOTPLUG) += hotplug-memory.o
23obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o 18obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
24obj-$(CONFIG_HVCS) += hvcserver.o 19obj-$(CONFIG_HVCS) += hvcserver.o
25obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o 20obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o
26obj-$(CONFIG_PHYP_DUMP) += phyp_dump.o 21obj-$(CONFIG_PHYP_DUMP) += phyp_dump.o
27obj-$(CONFIG_CMM) += cmm.o 22obj-$(CONFIG_CMM) += cmm.o
28obj-$(CONFIG_DTL) += dtl.o 23obj-$(CONFIG_DTL) += dtl.o
29 24
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c
index 72d8054fa739..b74a9230edc9 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
36static void dlpar_free_cc_property(struct property *prop) 36void 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
105static void dlpar_free_cc_nodes(struct device_node *dn) 104void 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 a00addb55945..c371bc06434b 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 */
38struct 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
51struct dtl { 35struct 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};
58static DEFINE_PER_CPU(struct dtl, cpu_dtl); 43static DEFINE_PER_CPU(struct dtl, cpu_dtl);
59 44
@@ -72,25 +57,97 @@ static u8 dtl_event_mask = 0x7;
72static int dtl_buf_entries = (16 * 85); 57static int dtl_buf_entries = (16 * 85);
73 58
74 59
75static int dtl_enable(struct dtl *dtl) 60#ifdef CONFIG_VIRT_CPU_ACCOUNTING
61struct 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
69static DEFINE_PER_CPU(struct dtl_ring, dtl_rings);
70
71static 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 */
77static 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
103static 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
124static 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
140static 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
147static 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
122static void dtl_disable(struct dtl *dtl) 178static 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
187static u64 dtl_current_index(struct dtl *dtl)
188{
189 return lppaca_of(dtl->cpu).dtl_idx;
190}
191#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
192
193static 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
230static 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)
157static ssize_t dtl_file_read(struct file *filp, char __user *buf, size_t len, 262static 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 cf79b46d8f88..f129040d974c 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
279static long pSeries_lpar_hpte_insert(unsigned long hpte_group, 300static 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 000000000000..3e7f651e50ac
--- /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
23static struct kobject *mobility_kobj;
24
25struct 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
39static 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
53static 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
65static 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
131static 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
202static 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
227static 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
279void 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
312static 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
348static CLASS_ATTR(migration, S_IWUSR, NULL, migrate_store);
349
350static 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}
362device_initcall(mobility_sysfs_init);
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h
index 40c93cad91d2..e9f6d2859c3c 100644
--- a/arch/powerpc/platforms/pseries/pseries.h
+++ b/arch/powerpc/platforms/pseries/pseries.h
@@ -17,6 +17,8 @@ struct device_node;
17extern void request_event_sources_irqs(struct device_node *np, 17extern 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
20extern void __init fw_feature_init(const char *hypertas, unsigned long len); 22extern void __init fw_feature_init(const char *hypertas, unsigned long len);
21 23
22struct pt_regs; 24struct pt_regs;
@@ -47,4 +49,11 @@ extern unsigned long rtas_poweron_auto;
47 49
48extern void find_udbg_vterm(void); 50extern void find_udbg_vterm(void);
49 51
52/* Dynamic logical Partitioning/Mobility */
53extern void dlpar_free_cc_nodes(struct device_node *);
54extern void dlpar_free_cc_property(struct property *);
55extern struct device_node *dlpar_configure_connector(u32);
56extern int dlpar_attach_node(struct device_node *);
57extern 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 a6d19e3a505e..d345bfd56bbe 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 */
282static 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
325early_initcall(alloc_dispatch_logs);
326#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
327
276static void __init pSeries_setup_arch(void) 328static 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 67e2c4bdac8f..7b96e5a270ce 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)