diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-11 19:31:41 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-11 19:31:41 -0500 |
commit | 5a62f995446be44811fefa48f91f9efb7ea172d7 (patch) | |
tree | e297371f0d513dc6278bb67d582d2216eb7d74ed | |
parent | f1d6d6cd9029daa7e7d4a0b14347b5392320f22a (diff) | |
parent | 5d7d8072edc11080a7cf6cc37c9f4e61ca1e93c9 (diff) |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (72 commits)
powerpc/pseries: Fix build of topology stuff without CONFIG_NUMA
powerpc/pseries: Fix VPHN build errors on non-SMP systems
powerpc/83xx: add mpc8308_p1m DMA controller device-tree node
powerpc/83xx: add DMA controller to mpc8308 device-tree node
powerpc/512x: try to free dma descriptors in case of allocation failure
powerpc/512x: add MPC8308 dma support
powerpc/512x: fix the hanged dma transfer issue
powerpc/512x: scatter/gather dma fix
powerpc/powermac: Make auto-loading of therm_pm72 possible
of/address: Use propper endianess in get_flags
powerpc/pci: Use printf extension %pR for struct resource
powerpc: Remove unnecessary casts of void ptr
powerpc: Disable VPHN polling during a suspend operation
powerpc/pseries: Poll VPA for topology changes and update NUMA maps
powerpc: iommu: Add device name to iommu error printks
powerpc: Record vma->phys_addr in ioremap()
powerpc: Update compat_arch_ptrace
powerpc: Fix PPC_PTRACE_SETHWDEBUG on PPC_BOOK3S
powerpc/time: printk time stamp init not correct
powerpc: Minor cleanups for machdep.h
...
88 files changed, 2071 insertions, 712 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index f3dc951e949f..ed3708f8d0db 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -403,6 +403,10 @@ and is between 256 and 4096 characters. It is defined in the file | |||
403 | bttv.pll= See Documentation/video4linux/bttv/Insmod-options | 403 | bttv.pll= See Documentation/video4linux/bttv/Insmod-options |
404 | bttv.tuner= and Documentation/video4linux/bttv/CARDLIST | 404 | bttv.tuner= and Documentation/video4linux/bttv/CARDLIST |
405 | 405 | ||
406 | bulk_remove=off [PPC] This parameter disables the use of the pSeries | ||
407 | firmware feature for flushing multiple hpte entries | ||
408 | at a time. | ||
409 | |||
406 | c101= [NET] Moxa C101 synchronous serial card | 410 | c101= [NET] Moxa C101 synchronous serial card |
407 | 411 | ||
408 | cachesize= [BUGS=X86-32] Override level 2 CPU cache size detection. | 412 | cachesize= [BUGS=X86-32] Override level 2 CPU cache size detection. |
@@ -1490,6 +1494,10 @@ and is between 256 and 4096 characters. It is defined in the file | |||
1490 | mtdparts= [MTD] | 1494 | mtdparts= [MTD] |
1491 | See drivers/mtd/cmdlinepart.c. | 1495 | See drivers/mtd/cmdlinepart.c. |
1492 | 1496 | ||
1497 | multitce=off [PPC] This parameter disables the use of the pSeries | ||
1498 | firmware feature for updating multiple TCE entries | ||
1499 | at a time. | ||
1500 | |||
1493 | onenand.bdry= [HW,MTD] Flex-OneNAND Boundary Configuration | 1501 | onenand.bdry= [HW,MTD] Flex-OneNAND Boundary Configuration |
1494 | 1502 | ||
1495 | Format: [die0_boundary][,die0_lock][,die1_boundary][,die1_lock] | 1503 | Format: [die0_boundary][,die0_lock][,die1_boundary][,die1_lock] |
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt index 302db5da49b3..3272ed59dec7 100644 --- a/Documentation/powerpc/booting-without-of.txt +++ b/Documentation/powerpc/booting-without-of.txt | |||
@@ -131,7 +131,7 @@ order to avoid the degeneration that had become the ppc32 kernel entry | |||
131 | point and the way a new platform should be added to the kernel. The | 131 | point and the way a new platform should be added to the kernel. The |
132 | legacy iSeries platform breaks those rules as it predates this scheme, | 132 | legacy iSeries platform breaks those rules as it predates this scheme, |
133 | but no new board support will be accepted in the main tree that | 133 | but no new board support will be accepted in the main tree that |
134 | doesn't follows them properly. In addition, since the advent of the | 134 | doesn't follow them properly. In addition, since the advent of the |
135 | arch/powerpc merged architecture for ppc32 and ppc64, new 32-bit | 135 | arch/powerpc merged architecture for ppc32 and ppc64, new 32-bit |
136 | platforms and 32-bit platforms which move into arch/powerpc will be | 136 | platforms and 32-bit platforms which move into arch/powerpc will be |
137 | required to use these rules as well. | 137 | required to use these rules as well. |
@@ -1025,7 +1025,7 @@ dtc source code can be found at | |||
1025 | 1025 | ||
1026 | WARNING: This version is still in early development stage; the | 1026 | WARNING: This version is still in early development stage; the |
1027 | resulting device-tree "blobs" have not yet been validated with the | 1027 | resulting device-tree "blobs" have not yet been validated with the |
1028 | kernel. The current generated bloc lacks a useful reserve map (it will | 1028 | kernel. The current generated block lacks a useful reserve map (it will |
1029 | be fixed to generate an empty one, it's up to the bootloader to fill | 1029 | be fixed to generate an empty one, it's up to the bootloader to fill |
1030 | it up) among others. The error handling needs work, bugs are lurking, | 1030 | it up) among others. The error handling needs work, bugs are lurking, |
1031 | etc... | 1031 | etc... |
diff --git a/Documentation/powerpc/dts-bindings/4xx/cpm.txt b/Documentation/powerpc/dts-bindings/4xx/cpm.txt new file mode 100644 index 000000000000..ee459806d35e --- /dev/null +++ b/Documentation/powerpc/dts-bindings/4xx/cpm.txt | |||
@@ -0,0 +1,52 @@ | |||
1 | PPC4xx Clock Power Management (CPM) node | ||
2 | |||
3 | Required properties: | ||
4 | - compatible : compatible list, currently only "ibm,cpm" | ||
5 | - dcr-access-method : "native" | ||
6 | - dcr-reg : < DCR register range > | ||
7 | |||
8 | Optional properties: | ||
9 | - er-offset : All 4xx SoCs with a CPM controller have | ||
10 | one of two different order for the CPM | ||
11 | registers. Some have the CPM registers | ||
12 | in the following order (ER,FR,SR). The | ||
13 | others have them in the following order | ||
14 | (SR,ER,FR). For the second case set | ||
15 | er-offset = <1>. | ||
16 | - unused-units : specifier consist of one cell. For each | ||
17 | bit in the cell, the corresponding bit | ||
18 | in CPM will be set to turn off unused | ||
19 | devices. | ||
20 | - idle-doze : specifier consist of one cell. For each | ||
21 | bit in the cell, the corresponding bit | ||
22 | in CPM will be set to turn off unused | ||
23 | devices. This is usually just CPM[CPU]. | ||
24 | - standby : specifier consist of one cell. For each | ||
25 | bit in the cell, the corresponding bit | ||
26 | in CPM will be set on standby and | ||
27 | restored on resume. | ||
28 | - suspend : specifier consist of one cell. For each | ||
29 | bit in the cell, the corresponding bit | ||
30 | in CPM will be set on suspend (mem) and | ||
31 | restored on resume. Note, for standby | ||
32 | and suspend the corresponding bits can | ||
33 | be different or the same. Usually for | ||
34 | standby only class 2 and 3 units are set. | ||
35 | However, the interface does not care. | ||
36 | If they are the same, the additional | ||
37 | power saving will be seeing if support | ||
38 | is available to put the DDR in self | ||
39 | refresh mode and any additional power | ||
40 | saving techniques for the specific SoC. | ||
41 | |||
42 | Example: | ||
43 | CPM0: cpm { | ||
44 | compatible = "ibm,cpm"; | ||
45 | dcr-access-method = "native"; | ||
46 | dcr-reg = <0x160 0x003>; | ||
47 | er-offset = <0>; | ||
48 | unused-units = <0x00000100>; | ||
49 | idle-doze = <0x02000000>; | ||
50 | standby = <0xfeff0000>; | ||
51 | suspend = <0xfeff791d>; | ||
52 | }; | ||
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 48fb4790bfec..959f38ccb9a7 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -20,6 +20,9 @@ config WORD_SIZE | |||
20 | config ARCH_PHYS_ADDR_T_64BIT | 20 | config ARCH_PHYS_ADDR_T_64BIT |
21 | def_bool PPC64 || PHYS_64BIT | 21 | def_bool PPC64 || PHYS_64BIT |
22 | 22 | ||
23 | config ARCH_DMA_ADDR_T_64BIT | ||
24 | def_bool ARCH_PHYS_ADDR_T_64BIT | ||
25 | |||
23 | config MMU | 26 | config MMU |
24 | bool | 27 | bool |
25 | default y | 28 | default y |
@@ -209,7 +212,7 @@ config ARCH_HIBERNATION_POSSIBLE | |||
209 | config ARCH_SUSPEND_POSSIBLE | 212 | config ARCH_SUSPEND_POSSIBLE |
210 | def_bool y | 213 | def_bool y |
211 | depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx || \ | 214 | depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx || \ |
212 | PPC_85xx || PPC_86xx || PPC_PSERIES | 215 | PPC_85xx || PPC_86xx || PPC_PSERIES || 44x || 40x |
213 | 216 | ||
214 | config PPC_DCR_NATIVE | 217 | config PPC_DCR_NATIVE |
215 | bool | 218 | bool |
@@ -595,13 +598,11 @@ config EXTRA_TARGETS | |||
595 | 598 | ||
596 | If unsure, leave blank | 599 | If unsure, leave blank |
597 | 600 | ||
598 | if !44x || BROKEN | ||
599 | config ARCH_WANTS_FREEZER_CONTROL | 601 | config ARCH_WANTS_FREEZER_CONTROL |
600 | def_bool y | 602 | def_bool y |
601 | depends on ADB_PMU | 603 | depends on ADB_PMU |
602 | 604 | ||
603 | source kernel/power/Kconfig | 605 | source kernel/power/Kconfig |
604 | endif | ||
605 | 606 | ||
606 | config SECCOMP | 607 | config SECCOMP |
607 | bool "Enable seccomp to safely compute untrusted bytecode" | 608 | bool "Enable seccomp to safely compute untrusted bytecode" |
@@ -682,6 +683,15 @@ config FSL_PMC | |||
682 | Freescale MPC85xx/MPC86xx power management controller support | 683 | Freescale MPC85xx/MPC86xx power management controller support |
683 | (suspend/resume). For MPC83xx see platforms/83xx/suspend.c | 684 | (suspend/resume). For MPC83xx see platforms/83xx/suspend.c |
684 | 685 | ||
686 | config PPC4xx_CPM | ||
687 | bool | ||
688 | default y | ||
689 | depends on SUSPEND && (44x || 40x) | ||
690 | help | ||
691 | PPC4xx Clock Power Management (CPM) support (suspend/resume). | ||
692 | It also enables support for two different idle states (idle-wait | ||
693 | and idle-doze). | ||
694 | |||
685 | config 4xx_SOC | 695 | config 4xx_SOC |
686 | bool | 696 | bool |
687 | 697 | ||
diff --git a/arch/powerpc/boot/dts/canyonlands.dts b/arch/powerpc/boot/dts/canyonlands.dts index a30370396250..5b27a4b74b79 100644 --- a/arch/powerpc/boot/dts/canyonlands.dts +++ b/arch/powerpc/boot/dts/canyonlands.dts | |||
@@ -105,6 +105,15 @@ | |||
105 | dcr-reg = <0x00c 0x002>; | 105 | dcr-reg = <0x00c 0x002>; |
106 | }; | 106 | }; |
107 | 107 | ||
108 | CPM0: cpm { | ||
109 | compatible = "ibm,cpm"; | ||
110 | dcr-access-method = "native"; | ||
111 | dcr-reg = <0x160 0x003>; | ||
112 | unused-units = <0x00000100>; | ||
113 | idle-doze = <0x02000000>; | ||
114 | standby = <0xfeff791d>; | ||
115 | }; | ||
116 | |||
108 | L2C0: l2c { | 117 | L2C0: l2c { |
109 | compatible = "ibm,l2-cache-460ex", "ibm,l2-cache"; | 118 | compatible = "ibm,l2-cache-460ex", "ibm,l2-cache"; |
110 | dcr-reg = <0x020 0x008 /* Internal SRAM DCR's */ | 119 | dcr-reg = <0x020 0x008 /* Internal SRAM DCR's */ |
@@ -270,28 +279,6 @@ | |||
270 | interrupts = <0x1 0x4>; | 279 | interrupts = <0x1 0x4>; |
271 | }; | 280 | }; |
272 | 281 | ||
273 | UART2: serial@ef600500 { | ||
274 | device_type = "serial"; | ||
275 | compatible = "ns16550"; | ||
276 | reg = <0xef600500 0x00000008>; | ||
277 | virtual-reg = <0xef600500>; | ||
278 | clock-frequency = <0>; /* Filled in by U-Boot */ | ||
279 | current-speed = <0>; /* Filled in by U-Boot */ | ||
280 | interrupt-parent = <&UIC1>; | ||
281 | interrupts = <28 0x4>; | ||
282 | }; | ||
283 | |||
284 | UART3: serial@ef600600 { | ||
285 | device_type = "serial"; | ||
286 | compatible = "ns16550"; | ||
287 | reg = <0xef600600 0x00000008>; | ||
288 | virtual-reg = <0xef600600>; | ||
289 | clock-frequency = <0>; /* Filled in by U-Boot */ | ||
290 | current-speed = <0>; /* Filled in by U-Boot */ | ||
291 | interrupt-parent = <&UIC1>; | ||
292 | interrupts = <29 0x4>; | ||
293 | }; | ||
294 | |||
295 | IIC0: i2c@ef600700 { | 282 | IIC0: i2c@ef600700 { |
296 | compatible = "ibm,iic-460ex", "ibm,iic"; | 283 | compatible = "ibm,iic-460ex", "ibm,iic"; |
297 | reg = <0xef600700 0x00000014>; | 284 | reg = <0xef600700 0x00000014>; |
diff --git a/arch/powerpc/boot/dts/kilauea.dts b/arch/powerpc/boot/dts/kilauea.dts index 083e68eeaca4..89edb16649c3 100644 --- a/arch/powerpc/boot/dts/kilauea.dts +++ b/arch/powerpc/boot/dts/kilauea.dts | |||
@@ -82,6 +82,15 @@ | |||
82 | interrupt-parent = <&UIC0>; | 82 | interrupt-parent = <&UIC0>; |
83 | }; | 83 | }; |
84 | 84 | ||
85 | CPM0: cpm { | ||
86 | compatible = "ibm,cpm"; | ||
87 | dcr-access-method = "native"; | ||
88 | dcr-reg = <0x0b0 0x003>; | ||
89 | unused-units = <0x00000000>; | ||
90 | idle-doze = <0x02000000>; | ||
91 | standby = <0xe3e74800>; | ||
92 | }; | ||
93 | |||
85 | plb { | 94 | plb { |
86 | compatible = "ibm,plb-405ex", "ibm,plb4"; | 95 | compatible = "ibm,plb-405ex", "ibm,plb4"; |
87 | #address-cells = <1>; | 96 | #address-cells = <1>; |
diff --git a/arch/powerpc/boot/dts/mpc8308_p1m.dts b/arch/powerpc/boot/dts/mpc8308_p1m.dts index 05a76ccfd499..697b3f6b78bf 100644 --- a/arch/powerpc/boot/dts/mpc8308_p1m.dts +++ b/arch/powerpc/boot/dts/mpc8308_p1m.dts | |||
@@ -297,6 +297,14 @@ | |||
297 | interrupt-parent = < &ipic >; | 297 | interrupt-parent = < &ipic >; |
298 | }; | 298 | }; |
299 | 299 | ||
300 | dma@2c000 { | ||
301 | compatible = "fsl,mpc8308-dma", "fsl,mpc5121-dma"; | ||
302 | reg = <0x2c000 0x1800>; | ||
303 | interrupts = <3 0x8 | ||
304 | 94 0x8>; | ||
305 | interrupt-parent = < &ipic >; | ||
306 | }; | ||
307 | |||
300 | }; | 308 | }; |
301 | 309 | ||
302 | pci0: pcie@e0009000 { | 310 | pci0: pcie@e0009000 { |
diff --git a/arch/powerpc/boot/dts/mpc8308rdb.dts b/arch/powerpc/boot/dts/mpc8308rdb.dts index a97eb2db5a18..d3db02f98ddd 100644 --- a/arch/powerpc/boot/dts/mpc8308rdb.dts +++ b/arch/powerpc/boot/dts/mpc8308rdb.dts | |||
@@ -265,6 +265,14 @@ | |||
265 | interrupt-parent = < &ipic >; | 265 | interrupt-parent = < &ipic >; |
266 | }; | 266 | }; |
267 | 267 | ||
268 | dma@2c000 { | ||
269 | compatible = "fsl,mpc8308-dma", "fsl,mpc5121-dma"; | ||
270 | reg = <0x2c000 0x1800>; | ||
271 | interrupts = <3 0x8 | ||
272 | 94 0x8>; | ||
273 | interrupt-parent = < &ipic >; | ||
274 | }; | ||
275 | |||
268 | }; | 276 | }; |
269 | 277 | ||
270 | pci0: pcie@e0009000 { | 278 | pci0: pcie@e0009000 { |
diff --git a/arch/powerpc/configs/40x/kilauea_defconfig b/arch/powerpc/configs/40x/kilauea_defconfig index 4e19ee7ce4ee..34b8c1a1e752 100644 --- a/arch/powerpc/configs/40x/kilauea_defconfig +++ b/arch/powerpc/configs/40x/kilauea_defconfig | |||
@@ -12,6 +12,8 @@ CONFIG_MODULES=y | |||
12 | CONFIG_MODULE_UNLOAD=y | 12 | CONFIG_MODULE_UNLOAD=y |
13 | # CONFIG_BLK_DEV_BSG is not set | 13 | # CONFIG_BLK_DEV_BSG is not set |
14 | CONFIG_KILAUEA=y | 14 | CONFIG_KILAUEA=y |
15 | CONFIG_NO_HZ=y | ||
16 | CONFIG_HIGH_RES_TIMERS=y | ||
15 | # CONFIG_WALNUT is not set | 17 | # CONFIG_WALNUT is not set |
16 | CONFIG_SPARSE_IRQ=y | 18 | CONFIG_SPARSE_IRQ=y |
17 | CONFIG_PCI=y | 19 | CONFIG_PCI=y |
@@ -42,6 +44,9 @@ CONFIG_MTD_PHYSMAP_OF=y | |||
42 | CONFIG_MTD_NAND=y | 44 | CONFIG_MTD_NAND=y |
43 | CONFIG_MTD_NAND_NDFC=y | 45 | CONFIG_MTD_NAND_NDFC=y |
44 | CONFIG_PROC_DEVICETREE=y | 46 | CONFIG_PROC_DEVICETREE=y |
47 | CONFIG_PM=y | ||
48 | CONFIG_SUSPEND=y | ||
49 | CONFIG_PPC4xx_CPM=y | ||
45 | CONFIG_BLK_DEV_RAM=y | 50 | CONFIG_BLK_DEV_RAM=y |
46 | CONFIG_BLK_DEV_RAM_SIZE=35000 | 51 | CONFIG_BLK_DEV_RAM_SIZE=35000 |
47 | # CONFIG_MISC_DEVICES is not set | 52 | # CONFIG_MISC_DEVICES is not set |
diff --git a/arch/powerpc/configs/44x/canyonlands_defconfig b/arch/powerpc/configs/44x/canyonlands_defconfig index 45c64d818b2a..17e4dd98eed7 100644 --- a/arch/powerpc/configs/44x/canyonlands_defconfig +++ b/arch/powerpc/configs/44x/canyonlands_defconfig | |||
@@ -42,6 +42,9 @@ CONFIG_MTD_PHYSMAP_OF=y | |||
42 | CONFIG_MTD_NAND=y | 42 | CONFIG_MTD_NAND=y |
43 | CONFIG_MTD_NAND_NDFC=y | 43 | CONFIG_MTD_NAND_NDFC=y |
44 | CONFIG_PROC_DEVICETREE=y | 44 | CONFIG_PROC_DEVICETREE=y |
45 | CONFIG_PM=y | ||
46 | CONFIG_SUSPEND=y | ||
47 | CONFIG_PPC4xx_CPM=y | ||
45 | CONFIG_BLK_DEV_RAM=y | 48 | CONFIG_BLK_DEV_RAM=y |
46 | CONFIG_BLK_DEV_RAM_SIZE=35000 | 49 | CONFIG_BLK_DEV_RAM_SIZE=35000 |
47 | # CONFIG_MISC_DEVICES is not set | 50 | # CONFIG_MISC_DEVICES is not set |
diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h index 30964ae2d096..8a7e9314c68a 100644 --- a/arch/powerpc/include/asm/bitops.h +++ b/arch/powerpc/include/asm/bitops.h | |||
@@ -267,7 +267,16 @@ static __inline__ int fls64(__u64 x) | |||
267 | #include <asm-generic/bitops/fls64.h> | 267 | #include <asm-generic/bitops/fls64.h> |
268 | #endif /* __powerpc64__ */ | 268 | #endif /* __powerpc64__ */ |
269 | 269 | ||
270 | #ifdef CONFIG_PPC64 | ||
271 | unsigned int __arch_hweight8(unsigned int w); | ||
272 | unsigned int __arch_hweight16(unsigned int w); | ||
273 | unsigned int __arch_hweight32(unsigned int w); | ||
274 | unsigned long __arch_hweight64(__u64 w); | ||
275 | #include <asm-generic/bitops/const_hweight.h> | ||
276 | #else | ||
270 | #include <asm-generic/bitops/hweight.h> | 277 | #include <asm-generic/bitops/hweight.h> |
278 | #endif | ||
279 | |||
271 | #include <asm-generic/bitops/find.h> | 280 | #include <asm-generic/bitops/find.h> |
272 | 281 | ||
273 | /* Little-endian versions */ | 282 | /* Little-endian versions */ |
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index f3a1fdd9cf08..f0a211d96923 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h | |||
@@ -199,6 +199,8 @@ extern const char *powerpc_base_platform; | |||
199 | #define CPU_FTR_UNALIGNED_LD_STD LONG_ASM_CONST(0x0080000000000000) | 199 | #define CPU_FTR_UNALIGNED_LD_STD LONG_ASM_CONST(0x0080000000000000) |
200 | #define CPU_FTR_ASYM_SMT LONG_ASM_CONST(0x0100000000000000) | 200 | #define CPU_FTR_ASYM_SMT LONG_ASM_CONST(0x0100000000000000) |
201 | #define CPU_FTR_STCX_CHECKS_ADDRESS LONG_ASM_CONST(0x0200000000000000) | 201 | #define CPU_FTR_STCX_CHECKS_ADDRESS LONG_ASM_CONST(0x0200000000000000) |
202 | #define CPU_FTR_POPCNTB LONG_ASM_CONST(0x0400000000000000) | ||
203 | #define CPU_FTR_POPCNTD LONG_ASM_CONST(0x0800000000000000) | ||
202 | 204 | ||
203 | #ifndef __ASSEMBLY__ | 205 | #ifndef __ASSEMBLY__ |
204 | 206 | ||
@@ -403,21 +405,22 @@ extern const char *powerpc_base_platform; | |||
403 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ | 405 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ |
404 | CPU_FTR_MMCRA | CPU_FTR_SMT | \ | 406 | CPU_FTR_MMCRA | CPU_FTR_SMT | \ |
405 | CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ | 407 | CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ |
406 | CPU_FTR_PURR | CPU_FTR_STCX_CHECKS_ADDRESS) | 408 | CPU_FTR_PURR | CPU_FTR_STCX_CHECKS_ADDRESS | \ |
409 | CPU_FTR_POPCNTB) | ||
407 | #define CPU_FTRS_POWER6 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ | 410 | #define CPU_FTRS_POWER6 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ |
408 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ | 411 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ |
409 | CPU_FTR_MMCRA | CPU_FTR_SMT | \ | 412 | CPU_FTR_MMCRA | CPU_FTR_SMT | \ |
410 | CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ | 413 | CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ |
411 | CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \ | 414 | CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \ |
412 | CPU_FTR_DSCR | CPU_FTR_UNALIGNED_LD_STD | \ | 415 | CPU_FTR_DSCR | CPU_FTR_UNALIGNED_LD_STD | \ |
413 | CPU_FTR_STCX_CHECKS_ADDRESS) | 416 | CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB) |
414 | #define CPU_FTRS_POWER7 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ | 417 | #define CPU_FTRS_POWER7 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ |
415 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ | 418 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ |
416 | CPU_FTR_MMCRA | CPU_FTR_SMT | \ | 419 | CPU_FTR_MMCRA | CPU_FTR_SMT | \ |
417 | CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ | 420 | CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ |
418 | CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \ | 421 | CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \ |
419 | CPU_FTR_DSCR | CPU_FTR_SAO | CPU_FTR_ASYM_SMT | \ | 422 | CPU_FTR_DSCR | CPU_FTR_SAO | CPU_FTR_ASYM_SMT | \ |
420 | CPU_FTR_STCX_CHECKS_ADDRESS) | 423 | CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD) |
421 | #define CPU_FTRS_CELL (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ | 424 | #define CPU_FTRS_CELL (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ |
422 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ | 425 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ |
423 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ | 426 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ |
diff --git a/arch/powerpc/include/asm/cputhreads.h b/arch/powerpc/include/asm/cputhreads.h index a8e18447c62b..f71bb4c118b4 100644 --- a/arch/powerpc/include/asm/cputhreads.h +++ b/arch/powerpc/include/asm/cputhreads.h | |||
@@ -61,22 +61,25 @@ static inline cpumask_t cpu_online_cores_map(void) | |||
61 | return cpu_thread_mask_to_cores(cpu_online_map); | 61 | return cpu_thread_mask_to_cores(cpu_online_map); |
62 | } | 62 | } |
63 | 63 | ||
64 | static inline int cpu_thread_to_core(int cpu) | 64 | #ifdef CONFIG_SMP |
65 | { | 65 | int cpu_core_index_of_thread(int cpu); |
66 | return cpu >> threads_shift; | 66 | int cpu_first_thread_of_core(int core); |
67 | } | 67 | #else |
68 | static inline int cpu_core_index_of_thread(int cpu) { return cpu; } | ||
69 | static inline int cpu_first_thread_of_core(int core) { return core; } | ||
70 | #endif | ||
68 | 71 | ||
69 | static inline int cpu_thread_in_core(int cpu) | 72 | static inline int cpu_thread_in_core(int cpu) |
70 | { | 73 | { |
71 | return cpu & (threads_per_core - 1); | 74 | return cpu & (threads_per_core - 1); |
72 | } | 75 | } |
73 | 76 | ||
74 | static inline int cpu_first_thread_in_core(int cpu) | 77 | static inline int cpu_first_thread_sibling(int cpu) |
75 | { | 78 | { |
76 | return cpu & ~(threads_per_core - 1); | 79 | return cpu & ~(threads_per_core - 1); |
77 | } | 80 | } |
78 | 81 | ||
79 | static inline int cpu_last_thread_in_core(int cpu) | 82 | static inline int cpu_last_thread_sibling(int cpu) |
80 | { | 83 | { |
81 | return cpu | (threads_per_core - 1); | 84 | return cpu | (threads_per_core - 1); |
82 | } | 85 | } |
diff --git a/arch/powerpc/include/asm/device.h b/arch/powerpc/include/asm/device.h index a3954e4fcbe2..16d25c0974be 100644 --- a/arch/powerpc/include/asm/device.h +++ b/arch/powerpc/include/asm/device.h | |||
@@ -9,6 +9,12 @@ | |||
9 | struct dma_map_ops; | 9 | struct dma_map_ops; |
10 | struct device_node; | 10 | struct device_node; |
11 | 11 | ||
12 | /* | ||
13 | * Arch extensions to struct device. | ||
14 | * | ||
15 | * When adding fields, consider macio_add_one_device in | ||
16 | * drivers/macintosh/macio_asic.c | ||
17 | */ | ||
12 | struct dev_archdata { | 18 | struct dev_archdata { |
13 | /* DMA operations on that device */ | 19 | /* DMA operations on that device */ |
14 | struct dma_map_ops *dma_ops; | 20 | struct dma_map_ops *dma_ops; |
diff --git a/arch/powerpc/include/asm/firmware.h b/arch/powerpc/include/asm/firmware.h index 20778a405d7a..4ef662e4a31d 100644 --- a/arch/powerpc/include/asm/firmware.h +++ b/arch/powerpc/include/asm/firmware.h | |||
@@ -46,6 +46,7 @@ | |||
46 | #define FW_FEATURE_PS3_LV1 ASM_CONST(0x0000000000800000) | 46 | #define FW_FEATURE_PS3_LV1 ASM_CONST(0x0000000000800000) |
47 | #define FW_FEATURE_BEAT ASM_CONST(0x0000000001000000) | 47 | #define FW_FEATURE_BEAT ASM_CONST(0x0000000001000000) |
48 | #define FW_FEATURE_CMO ASM_CONST(0x0000000002000000) | 48 | #define FW_FEATURE_CMO ASM_CONST(0x0000000002000000) |
49 | #define FW_FEATURE_VPHN ASM_CONST(0x0000000004000000) | ||
49 | 50 | ||
50 | #ifndef __ASSEMBLY__ | 51 | #ifndef __ASSEMBLY__ |
51 | 52 | ||
@@ -59,7 +60,7 @@ enum { | |||
59 | FW_FEATURE_VIO | FW_FEATURE_RDMA | FW_FEATURE_LLAN | | 60 | FW_FEATURE_VIO | FW_FEATURE_RDMA | FW_FEATURE_LLAN | |
60 | FW_FEATURE_BULK_REMOVE | FW_FEATURE_XDABR | | 61 | FW_FEATURE_BULK_REMOVE | FW_FEATURE_XDABR | |
61 | FW_FEATURE_MULTITCE | FW_FEATURE_SPLPAR | FW_FEATURE_LPAR | | 62 | FW_FEATURE_MULTITCE | FW_FEATURE_SPLPAR | FW_FEATURE_LPAR | |
62 | FW_FEATURE_CMO, | 63 | FW_FEATURE_CMO | FW_FEATURE_VPHN, |
63 | FW_FEATURE_PSERIES_ALWAYS = 0, | 64 | FW_FEATURE_PSERIES_ALWAYS = 0, |
64 | FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR, | 65 | FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR, |
65 | FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR, | 66 | FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR, |
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h index de03ca58db5d..ec089acfa56b 100644 --- a/arch/powerpc/include/asm/hvcall.h +++ b/arch/powerpc/include/asm/hvcall.h | |||
@@ -232,7 +232,9 @@ | |||
232 | #define H_GET_EM_PARMS 0x2B8 | 232 | #define H_GET_EM_PARMS 0x2B8 |
233 | #define H_SET_MPP 0x2D0 | 233 | #define H_SET_MPP 0x2D0 |
234 | #define H_GET_MPP 0x2D4 | 234 | #define H_GET_MPP 0x2D4 |
235 | #define MAX_HCALL_OPCODE H_GET_MPP | 235 | #define H_HOME_NODE_ASSOCIATIVITY 0x2EC |
236 | #define H_BEST_ENERGY 0x2F4 | ||
237 | #define MAX_HCALL_OPCODE H_BEST_ENERGY | ||
236 | 238 | ||
237 | #ifndef __ASSEMBLY__ | 239 | #ifndef __ASSEMBLY__ |
238 | 240 | ||
diff --git a/arch/powerpc/include/asm/lppaca.h b/arch/powerpc/include/asm/lppaca.h index 7f5e0fefebb0..380d48bacd16 100644 --- a/arch/powerpc/include/asm/lppaca.h +++ b/arch/powerpc/include/asm/lppaca.h | |||
@@ -62,7 +62,10 @@ struct lppaca { | |||
62 | volatile u32 dyn_pir; // Dynamic ProcIdReg value x20-x23 | 62 | volatile u32 dyn_pir; // Dynamic ProcIdReg value x20-x23 |
63 | u32 dsei_data; // DSEI data x24-x27 | 63 | u32 dsei_data; // DSEI data x24-x27 |
64 | u64 sprg3; // SPRG3 value x28-x2F | 64 | u64 sprg3; // SPRG3 value x28-x2F |
65 | u8 reserved3[80]; // Reserved x30-x7F | 65 | u8 reserved3[40]; // Reserved x30-x57 |
66 | volatile u8 vphn_assoc_counts[8]; // Virtual processor home node | ||
67 | // associativity change counters x58-x5F | ||
68 | u8 reserved4[32]; // Reserved x60-x7F | ||
66 | 69 | ||
67 | //============================================================================= | 70 | //============================================================================= |
68 | // CACHE_LINE_2 0x0080 - 0x00FF Contains local read-write data | 71 | // CACHE_LINE_2 0x0080 - 0x00FF Contains local read-write data |
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index d045b0145537..8433d36619a1 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h | |||
@@ -27,9 +27,7 @@ struct iommu_table; | |||
27 | struct rtc_time; | 27 | struct rtc_time; |
28 | struct file; | 28 | struct file; |
29 | struct pci_controller; | 29 | struct pci_controller; |
30 | #ifdef CONFIG_KEXEC | ||
31 | struct kimage; | 30 | struct kimage; |
32 | #endif | ||
33 | 31 | ||
34 | #ifdef CONFIG_SMP | 32 | #ifdef CONFIG_SMP |
35 | struct smp_ops_t { | 33 | struct smp_ops_t { |
@@ -72,7 +70,7 @@ struct machdep_calls { | |||
72 | int psize, int ssize); | 70 | int psize, int ssize); |
73 | void (*flush_hash_range)(unsigned long number, int local); | 71 | void (*flush_hash_range)(unsigned long number, int local); |
74 | 72 | ||
75 | /* special for kexec, to be called in real mode, linar mapping is | 73 | /* special for kexec, to be called in real mode, linear mapping is |
76 | * destroyed as well */ | 74 | * destroyed as well */ |
77 | void (*hpte_clear_all)(void); | 75 | void (*hpte_clear_all)(void); |
78 | 76 | ||
@@ -324,8 +322,6 @@ extern sys_ctrler_t sys_ctrler; | |||
324 | 322 | ||
325 | #endif /* CONFIG_PPC_PMAC */ | 323 | #endif /* CONFIG_PPC_PMAC */ |
326 | 324 | ||
327 | extern void setup_pci_ptrs(void); | ||
328 | |||
329 | #ifdef CONFIG_SMP | 325 | #ifdef CONFIG_SMP |
330 | /* Poor default implementations */ | 326 | /* Poor default implementations */ |
331 | extern void __devinit smp_generic_give_timebase(void); | 327 | extern void __devinit smp_generic_give_timebase(void); |
diff --git a/arch/powerpc/include/asm/mmzone.h b/arch/powerpc/include/asm/mmzone.h index aac87cbceb57..fd3fd58bad84 100644 --- a/arch/powerpc/include/asm/mmzone.h +++ b/arch/powerpc/include/asm/mmzone.h | |||
@@ -33,6 +33,9 @@ extern int numa_cpu_lookup_table[]; | |||
33 | extern cpumask_var_t node_to_cpumask_map[]; | 33 | extern cpumask_var_t node_to_cpumask_map[]; |
34 | #ifdef CONFIG_MEMORY_HOTPLUG | 34 | #ifdef CONFIG_MEMORY_HOTPLUG |
35 | extern unsigned long max_pfn; | 35 | extern unsigned long max_pfn; |
36 | u64 memory_hotplug_max(void); | ||
37 | #else | ||
38 | #define memory_hotplug_max() memblock_end_of_DRAM() | ||
36 | #endif | 39 | #endif |
37 | 40 | ||
38 | /* | 41 | /* |
@@ -42,6 +45,8 @@ extern unsigned long max_pfn; | |||
42 | #define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn) | 45 | #define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn) |
43 | #define node_end_pfn(nid) (NODE_DATA(nid)->node_end_pfn) | 46 | #define node_end_pfn(nid) (NODE_DATA(nid)->node_end_pfn) |
44 | 47 | ||
48 | #else | ||
49 | #define memory_hotplug_max() memblock_end_of_DRAM() | ||
45 | #endif /* CONFIG_NEED_MULTIPLE_NODES */ | 50 | #endif /* CONFIG_NEED_MULTIPLE_NODES */ |
46 | 51 | ||
47 | #endif /* __KERNEL__ */ | 52 | #endif /* __KERNEL__ */ |
diff --git a/arch/powerpc/include/asm/nvram.h b/arch/powerpc/include/asm/nvram.h index 850b72f27445..92efe67d1c57 100644 --- a/arch/powerpc/include/asm/nvram.h +++ b/arch/powerpc/include/asm/nvram.h | |||
@@ -10,31 +10,7 @@ | |||
10 | #ifndef _ASM_POWERPC_NVRAM_H | 10 | #ifndef _ASM_POWERPC_NVRAM_H |
11 | #define _ASM_POWERPC_NVRAM_H | 11 | #define _ASM_POWERPC_NVRAM_H |
12 | 12 | ||
13 | #include <linux/errno.h> | 13 | /* Signatures for nvram partitions */ |
14 | |||
15 | #define NVRW_CNT 0x20 | ||
16 | #define NVRAM_HEADER_LEN 16 /* sizeof(struct nvram_header) */ | ||
17 | #define NVRAM_BLOCK_LEN 16 | ||
18 | #define NVRAM_MAX_REQ (2080/NVRAM_BLOCK_LEN) | ||
19 | #define NVRAM_MIN_REQ (1056/NVRAM_BLOCK_LEN) | ||
20 | |||
21 | #define NVRAM_AS0 0x74 | ||
22 | #define NVRAM_AS1 0x75 | ||
23 | #define NVRAM_DATA 0x77 | ||
24 | |||
25 | |||
26 | /* RTC Offsets */ | ||
27 | |||
28 | #define MOTO_RTC_SECONDS 0x1FF9 | ||
29 | #define MOTO_RTC_MINUTES 0x1FFA | ||
30 | #define MOTO_RTC_HOURS 0x1FFB | ||
31 | #define MOTO_RTC_DAY_OF_WEEK 0x1FFC | ||
32 | #define MOTO_RTC_DAY_OF_MONTH 0x1FFD | ||
33 | #define MOTO_RTC_MONTH 0x1FFE | ||
34 | #define MOTO_RTC_YEAR 0x1FFF | ||
35 | #define MOTO_RTC_CONTROLA 0x1FF8 | ||
36 | #define MOTO_RTC_CONTROLB 0x1FF9 | ||
37 | |||
38 | #define NVRAM_SIG_SP 0x02 /* support processor */ | 14 | #define NVRAM_SIG_SP 0x02 /* support processor */ |
39 | #define NVRAM_SIG_OF 0x50 /* open firmware config */ | 15 | #define NVRAM_SIG_OF 0x50 /* open firmware config */ |
40 | #define NVRAM_SIG_FW 0x51 /* general firmware */ | 16 | #define NVRAM_SIG_FW 0x51 /* general firmware */ |
@@ -49,32 +25,19 @@ | |||
49 | #define NVRAM_SIG_OS 0xa0 /* OS defined */ | 25 | #define NVRAM_SIG_OS 0xa0 /* OS defined */ |
50 | #define NVRAM_SIG_PANIC 0xa1 /* Apple OSX "panic" */ | 26 | #define NVRAM_SIG_PANIC 0xa1 /* Apple OSX "panic" */ |
51 | 27 | ||
52 | /* If change this size, then change the size of NVNAME_LEN */ | ||
53 | struct nvram_header { | ||
54 | unsigned char signature; | ||
55 | unsigned char checksum; | ||
56 | unsigned short length; | ||
57 | char name[12]; | ||
58 | }; | ||
59 | |||
60 | #ifdef __KERNEL__ | 28 | #ifdef __KERNEL__ |
61 | 29 | ||
30 | #include <linux/errno.h> | ||
62 | #include <linux/list.h> | 31 | #include <linux/list.h> |
63 | 32 | ||
64 | struct nvram_partition { | 33 | #ifdef CONFIG_PPC_PSERIES |
65 | struct list_head partition; | ||
66 | struct nvram_header header; | ||
67 | unsigned int index; | ||
68 | }; | ||
69 | |||
70 | |||
71 | extern int nvram_write_error_log(char * buff, int length, | 34 | extern int nvram_write_error_log(char * buff, int length, |
72 | unsigned int err_type, unsigned int err_seq); | 35 | unsigned int err_type, unsigned int err_seq); |
73 | extern int nvram_read_error_log(char * buff, int length, | 36 | extern int nvram_read_error_log(char * buff, int length, |
74 | unsigned int * err_type, unsigned int *err_seq); | 37 | unsigned int * err_type, unsigned int *err_seq); |
75 | extern int nvram_clear_error_log(void); | 38 | extern int nvram_clear_error_log(void); |
76 | |||
77 | extern int pSeries_nvram_init(void); | 39 | extern int pSeries_nvram_init(void); |
40 | #endif /* CONFIG_PPC_PSERIES */ | ||
78 | 41 | ||
79 | #ifdef CONFIG_MMIO_NVRAM | 42 | #ifdef CONFIG_MMIO_NVRAM |
80 | extern int mmio_nvram_init(void); | 43 | extern int mmio_nvram_init(void); |
@@ -85,6 +48,13 @@ static inline int mmio_nvram_init(void) | |||
85 | } | 48 | } |
86 | #endif | 49 | #endif |
87 | 50 | ||
51 | extern int __init nvram_scan_partitions(void); | ||
52 | extern loff_t nvram_create_partition(const char *name, int sig, | ||
53 | int req_size, int min_size); | ||
54 | extern int nvram_remove_partition(const char *name, int sig); | ||
55 | extern int nvram_get_partition_size(loff_t data_index); | ||
56 | extern loff_t nvram_find_partition(const char *name, int sig, int *out_size); | ||
57 | |||
88 | #endif /* __KERNEL__ */ | 58 | #endif /* __KERNEL__ */ |
89 | 59 | ||
90 | /* PowerMac specific nvram stuffs */ | 60 | /* PowerMac specific nvram stuffs */ |
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index 43adc8b819ed..1255569387b6 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h | |||
@@ -36,6 +36,8 @@ | |||
36 | #define PPC_INST_NOP 0x60000000 | 36 | #define PPC_INST_NOP 0x60000000 |
37 | #define PPC_INST_POPCNTB 0x7c0000f4 | 37 | #define PPC_INST_POPCNTB 0x7c0000f4 |
38 | #define PPC_INST_POPCNTB_MASK 0xfc0007fe | 38 | #define PPC_INST_POPCNTB_MASK 0xfc0007fe |
39 | #define PPC_INST_POPCNTD 0x7c0003f4 | ||
40 | #define PPC_INST_POPCNTW 0x7c0002f4 | ||
39 | #define PPC_INST_RFCI 0x4c000066 | 41 | #define PPC_INST_RFCI 0x4c000066 |
40 | #define PPC_INST_RFDI 0x4c00004e | 42 | #define PPC_INST_RFDI 0x4c00004e |
41 | #define PPC_INST_RFMCI 0x4c00004c | 43 | #define PPC_INST_RFMCI 0x4c00004c |
@@ -88,6 +90,12 @@ | |||
88 | __PPC_RB(b) | __PPC_EH(eh)) | 90 | __PPC_RB(b) | __PPC_EH(eh)) |
89 | #define PPC_MSGSND(b) stringify_in_c(.long PPC_INST_MSGSND | \ | 91 | #define PPC_MSGSND(b) stringify_in_c(.long PPC_INST_MSGSND | \ |
90 | __PPC_RB(b)) | 92 | __PPC_RB(b)) |
93 | #define PPC_POPCNTB(a, s) stringify_in_c(.long PPC_INST_POPCNTB | \ | ||
94 | __PPC_RA(a) | __PPC_RS(s)) | ||
95 | #define PPC_POPCNTD(a, s) stringify_in_c(.long PPC_INST_POPCNTD | \ | ||
96 | __PPC_RA(a) | __PPC_RS(s)) | ||
97 | #define PPC_POPCNTW(a, s) stringify_in_c(.long PPC_INST_POPCNTW | \ | ||
98 | __PPC_RA(a) | __PPC_RS(s)) | ||
91 | #define PPC_RFCI stringify_in_c(.long PPC_INST_RFCI) | 99 | #define PPC_RFCI stringify_in_c(.long PPC_INST_RFCI) |
92 | #define PPC_RFDI stringify_in_c(.long PPC_INST_RFDI) | 100 | #define PPC_RFDI stringify_in_c(.long PPC_INST_RFDI) |
93 | #define PPC_RFMCI stringify_in_c(.long PPC_INST_RFMCI) | 101 | #define PPC_RFMCI stringify_in_c(.long PPC_INST_RFMCI) |
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index 4c14187ba02d..de1967a1ff57 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h | |||
@@ -122,7 +122,6 @@ extern struct task_struct *last_task_used_spe; | |||
122 | TASK_UNMAPPED_BASE_USER32 : TASK_UNMAPPED_BASE_USER64 ) | 122 | TASK_UNMAPPED_BASE_USER32 : TASK_UNMAPPED_BASE_USER64 ) |
123 | #endif | 123 | #endif |
124 | 124 | ||
125 | #ifdef __KERNEL__ | ||
126 | #ifdef __powerpc64__ | 125 | #ifdef __powerpc64__ |
127 | 126 | ||
128 | #define STACK_TOP_USER64 TASK_SIZE_USER64 | 127 | #define STACK_TOP_USER64 TASK_SIZE_USER64 |
@@ -139,7 +138,6 @@ extern struct task_struct *last_task_used_spe; | |||
139 | #define STACK_TOP_MAX STACK_TOP | 138 | #define STACK_TOP_MAX STACK_TOP |
140 | 139 | ||
141 | #endif /* __powerpc64__ */ | 140 | #endif /* __powerpc64__ */ |
142 | #endif /* __KERNEL__ */ | ||
143 | 141 | ||
144 | typedef struct { | 142 | typedef struct { |
145 | unsigned long seg; | 143 | unsigned long seg; |
diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h index afe4aaa65c3b..7ef0d90defc8 100644 --- a/arch/powerpc/include/asm/topology.h +++ b/arch/powerpc/include/asm/topology.h | |||
@@ -106,9 +106,22 @@ static inline void sysfs_remove_device_from_node(struct sys_device *dev, | |||
106 | int nid) | 106 | int nid) |
107 | { | 107 | { |
108 | } | 108 | } |
109 | |||
110 | #endif /* CONFIG_NUMA */ | 109 | #endif /* CONFIG_NUMA */ |
111 | 110 | ||
111 | #if defined(CONFIG_NUMA) && defined(CONFIG_PPC_SPLPAR) | ||
112 | extern int start_topology_update(void); | ||
113 | extern int stop_topology_update(void); | ||
114 | #else | ||
115 | static inline int start_topology_update(void) | ||
116 | { | ||
117 | return 0; | ||
118 | } | ||
119 | static inline int stop_topology_update(void) | ||
120 | { | ||
121 | return 0; | ||
122 | } | ||
123 | #endif /* CONFIG_NUMA && CONFIG_PPC_SPLPAR */ | ||
124 | |||
112 | #include <asm-generic/topology.h> | 125 | #include <asm-generic/topology.h> |
113 | 126 | ||
114 | #ifdef CONFIG_SMP | 127 | #ifdef CONFIG_SMP |
diff --git a/arch/powerpc/include/asm/vdso_datapage.h b/arch/powerpc/include/asm/vdso_datapage.h index 08679c5319b8..25e39220e89c 100644 --- a/arch/powerpc/include/asm/vdso_datapage.h +++ b/arch/powerpc/include/asm/vdso_datapage.h | |||
@@ -116,9 +116,7 @@ struct vdso_data { | |||
116 | 116 | ||
117 | #endif /* CONFIG_PPC64 */ | 117 | #endif /* CONFIG_PPC64 */ |
118 | 118 | ||
119 | #ifdef __KERNEL__ | ||
120 | extern struct vdso_data *vdso_data; | 119 | extern struct vdso_data *vdso_data; |
121 | #endif | ||
122 | 120 | ||
123 | #endif /* __ASSEMBLY__ */ | 121 | #endif /* __ASSEMBLY__ */ |
124 | 122 | ||
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 36c30f31ec93..3bb2a3e6a337 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -29,8 +29,10 @@ endif | |||
29 | obj-y := cputable.o ptrace.o syscalls.o \ | 29 | obj-y := cputable.o ptrace.o syscalls.o \ |
30 | irq.o align.o signal_32.o pmc.o vdso.o \ | 30 | irq.o align.o signal_32.o pmc.o vdso.o \ |
31 | init_task.o process.o systbl.o idle.o \ | 31 | init_task.o process.o systbl.o idle.o \ |
32 | signal.o sysfs.o cacheinfo.o | 32 | signal.o sysfs.o cacheinfo.o time.o \ |
33 | obj-y += vdso32/ | 33 | prom.o traps.o setup-common.o \ |
34 | udbg.o misc.o io.o dma.o \ | ||
35 | misc_$(CONFIG_WORD_SIZE).o vdso32/ | ||
34 | obj-$(CONFIG_PPC64) += setup_64.o sys_ppc32.o \ | 36 | obj-$(CONFIG_PPC64) += setup_64.o sys_ppc32.o \ |
35 | signal_64.o ptrace32.o \ | 37 | signal_64.o ptrace32.o \ |
36 | paca.o nvram_64.o firmware.o | 38 | paca.o nvram_64.o firmware.o |
@@ -80,9 +82,6 @@ extra-$(CONFIG_FSL_BOOKE) := head_fsl_booke.o | |||
80 | extra-$(CONFIG_8xx) := head_8xx.o | 82 | extra-$(CONFIG_8xx) := head_8xx.o |
81 | extra-y += vmlinux.lds | 83 | extra-y += vmlinux.lds |
82 | 84 | ||
83 | obj-y += time.o prom.o traps.o setup-common.o \ | ||
84 | udbg.o misc.o io.o dma.o \ | ||
85 | misc_$(CONFIG_WORD_SIZE).o | ||
86 | obj-$(CONFIG_PPC32) += entry_32.o setup_32.o | 85 | obj-$(CONFIG_PPC32) += entry_32.o setup_32.o |
87 | obj-$(CONFIG_PPC64) += dma-iommu.o iommu.o | 86 | obj-$(CONFIG_PPC64) += dma-iommu.o iommu.o |
88 | obj-$(CONFIG_KGDB) += kgdb.o | 87 | obj-$(CONFIG_KGDB) += kgdb.o |
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index bd0df2e6aa8f..23e6a93145ab 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -209,7 +209,6 @@ int main(void) | |||
209 | DEFINE(RTASENTRY, offsetof(struct rtas_t, entry)); | 209 | DEFINE(RTASENTRY, offsetof(struct rtas_t, entry)); |
210 | 210 | ||
211 | /* Interrupt register frame */ | 211 | /* Interrupt register frame */ |
212 | DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD); | ||
213 | DEFINE(INT_FRAME_SIZE, STACK_INT_FRAME_SIZE); | 212 | DEFINE(INT_FRAME_SIZE, STACK_INT_FRAME_SIZE); |
214 | DEFINE(SWITCH_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs)); | 213 | DEFINE(SWITCH_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs)); |
215 | #ifdef CONFIG_PPC64 | 214 | #ifdef CONFIG_PPC64 |
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 96a908f1cd87..be5ab18b03b5 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
@@ -457,16 +457,26 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
457 | .dcache_bsize = 128, | 457 | .dcache_bsize = 128, |
458 | .num_pmcs = 6, | 458 | .num_pmcs = 6, |
459 | .pmc_type = PPC_PMC_IBM, | 459 | .pmc_type = PPC_PMC_IBM, |
460 | .cpu_setup = __setup_cpu_power7, | ||
461 | .cpu_restore = __restore_cpu_power7, | ||
462 | .oprofile_cpu_type = "ppc64/power7", | 460 | .oprofile_cpu_type = "ppc64/power7", |
463 | .oprofile_type = PPC_OPROFILE_POWER4, | 461 | .oprofile_type = PPC_OPROFILE_POWER4, |
464 | .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV, | ||
465 | .oprofile_mmcra_sipr = POWER6_MMCRA_SIPR, | ||
466 | .oprofile_mmcra_clear = POWER6_MMCRA_THRM | | ||
467 | POWER6_MMCRA_OTHER, | ||
468 | .platform = "power7", | 462 | .platform = "power7", |
469 | }, | 463 | }, |
464 | { /* Power7+ */ | ||
465 | .pvr_mask = 0xffff0000, | ||
466 | .pvr_value = 0x004A0000, | ||
467 | .cpu_name = "POWER7+ (raw)", | ||
468 | .cpu_features = CPU_FTRS_POWER7, | ||
469 | .cpu_user_features = COMMON_USER_POWER7, | ||
470 | .mmu_features = MMU_FTR_HPTE_TABLE | | ||
471 | MMU_FTR_TLBIE_206, | ||
472 | .icache_bsize = 128, | ||
473 | .dcache_bsize = 128, | ||
474 | .num_pmcs = 6, | ||
475 | .pmc_type = PPC_PMC_IBM, | ||
476 | .oprofile_cpu_type = "ppc64/power7", | ||
477 | .oprofile_type = PPC_OPROFILE_POWER4, | ||
478 | .platform = "power7+", | ||
479 | }, | ||
470 | { /* Cell Broadband Engine */ | 480 | { /* Cell Broadband Engine */ |
471 | .pvr_mask = 0xffff0000, | 481 | .pvr_mask = 0xffff0000, |
472 | .pvr_value = 0x00700000, | 482 | .pvr_value = 0x00700000, |
diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c index 8e05c16344e4..0a2af50243cb 100644 --- a/arch/powerpc/kernel/crash_dump.c +++ b/arch/powerpc/kernel/crash_dump.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <asm/prom.h> | 19 | #include <asm/prom.h> |
20 | #include <asm/firmware.h> | 20 | #include <asm/firmware.h> |
21 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
22 | #include <asm/rtas.h> | ||
22 | 23 | ||
23 | #ifdef DEBUG | 24 | #ifdef DEBUG |
24 | #include <asm/udbg.h> | 25 | #include <asm/udbg.h> |
@@ -141,3 +142,35 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf, | |||
141 | 142 | ||
142 | return csize; | 143 | return csize; |
143 | } | 144 | } |
145 | |||
146 | #ifdef CONFIG_PPC_RTAS | ||
147 | /* | ||
148 | * The crashkernel region will almost always overlap the RTAS region, so | ||
149 | * we have to be careful when shrinking the crashkernel region. | ||
150 | */ | ||
151 | void crash_free_reserved_phys_range(unsigned long begin, unsigned long end) | ||
152 | { | ||
153 | unsigned long addr; | ||
154 | const u32 *basep, *sizep; | ||
155 | unsigned int rtas_start = 0, rtas_end = 0; | ||
156 | |||
157 | basep = of_get_property(rtas.dev, "linux,rtas-base", NULL); | ||
158 | sizep = of_get_property(rtas.dev, "rtas-size", NULL); | ||
159 | |||
160 | if (basep && sizep) { | ||
161 | rtas_start = *basep; | ||
162 | rtas_end = *basep + *sizep; | ||
163 | } | ||
164 | |||
165 | for (addr = begin; addr < end; addr += PAGE_SIZE) { | ||
166 | /* Does this page overlap with the RTAS region? */ | ||
167 | if (addr <= rtas_end && ((addr + PAGE_SIZE) > rtas_start)) | ||
168 | continue; | ||
169 | |||
170 | ClearPageReserved(pfn_to_page(addr >> PAGE_SHIFT)); | ||
171 | init_page_count(pfn_to_page(addr >> PAGE_SHIFT)); | ||
172 | free_page((unsigned long)__va(addr)); | ||
173 | totalram_pages++; | ||
174 | } | ||
175 | } | ||
176 | #endif | ||
diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c index 6e54a0fd31aa..e7554154a6de 100644 --- a/arch/powerpc/kernel/dma-iommu.c +++ b/arch/powerpc/kernel/dma-iommu.c | |||
@@ -19,7 +19,7 @@ static void *dma_iommu_alloc_coherent(struct device *dev, size_t size, | |||
19 | dma_addr_t *dma_handle, gfp_t flag) | 19 | dma_addr_t *dma_handle, gfp_t flag) |
20 | { | 20 | { |
21 | return iommu_alloc_coherent(dev, get_iommu_table_base(dev), size, | 21 | return iommu_alloc_coherent(dev, get_iommu_table_base(dev), size, |
22 | dma_handle, device_to_mask(dev), flag, | 22 | dma_handle, dev->coherent_dma_mask, flag, |
23 | dev_to_node(dev)); | 23 | dev_to_node(dev)); |
24 | } | 24 | } |
25 | 25 | ||
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index ed4aeb96398b..c22dc1ec1c94 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <asm/asm-offsets.h> | 31 | #include <asm/asm-offsets.h> |
32 | #include <asm/unistd.h> | 32 | #include <asm/unistd.h> |
33 | #include <asm/ftrace.h> | 33 | #include <asm/ftrace.h> |
34 | #include <asm/ptrace.h> | ||
34 | 35 | ||
35 | #undef SHOW_SYSCALLS | 36 | #undef SHOW_SYSCALLS |
36 | #undef SHOW_SYSCALLS_TASK | 37 | #undef SHOW_SYSCALLS_TASK |
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 9f8b01d6466f..8a817995b4cd 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
@@ -13,6 +13,7 @@ | |||
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <asm/exception-64s.h> | 15 | #include <asm/exception-64s.h> |
16 | #include <asm/ptrace.h> | ||
16 | 17 | ||
17 | /* | 18 | /* |
18 | * We layout physical memory as follows: | 19 | * We layout physical memory as follows: |
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S index e86c040ae585..de369558bf0a 100644 --- a/arch/powerpc/kernel/fpu.S +++ b/arch/powerpc/kernel/fpu.S | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <asm/thread_info.h> | 23 | #include <asm/thread_info.h> |
24 | #include <asm/ppc_asm.h> | 24 | #include <asm/ppc_asm.h> |
25 | #include <asm/asm-offsets.h> | 25 | #include <asm/asm-offsets.h> |
26 | #include <asm/ptrace.h> | ||
26 | 27 | ||
27 | #ifdef CONFIG_VSX | 28 | #ifdef CONFIG_VSX |
28 | #define REST_32FPVSRS(n,c,base) \ | 29 | #define REST_32FPVSRS(n,c,base) \ |
diff --git a/arch/powerpc/kernel/head_40x.S b/arch/powerpc/kernel/head_40x.S index 8278e8bad5a0..9dd21a8c4d52 100644 --- a/arch/powerpc/kernel/head_40x.S +++ b/arch/powerpc/kernel/head_40x.S | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <asm/thread_info.h> | 40 | #include <asm/thread_info.h> |
41 | #include <asm/ppc_asm.h> | 41 | #include <asm/ppc_asm.h> |
42 | #include <asm/asm-offsets.h> | 42 | #include <asm/asm-offsets.h> |
43 | #include <asm/ptrace.h> | ||
43 | 44 | ||
44 | /* As with the other PowerPC ports, it is expected that when code | 45 | /* As with the other PowerPC ports, it is expected that when code |
45 | * execution begins here, the following registers contain valid, yet | 46 | * execution begins here, the following registers contain valid, yet |
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S index 562305b40a8e..cbb3436b592d 100644 --- a/arch/powerpc/kernel/head_44x.S +++ b/arch/powerpc/kernel/head_44x.S | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <asm/thread_info.h> | 37 | #include <asm/thread_info.h> |
38 | #include <asm/ppc_asm.h> | 38 | #include <asm/ppc_asm.h> |
39 | #include <asm/asm-offsets.h> | 39 | #include <asm/asm-offsets.h> |
40 | #include <asm/ptrace.h> | ||
40 | #include <asm/synch.h> | 41 | #include <asm/synch.h> |
41 | #include "head_booke.h" | 42 | #include "head_booke.h" |
42 | 43 | ||
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index f0dd577e4a5b..782f23df7c85 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <asm/page_64.h> | 38 | #include <asm/page_64.h> |
39 | #include <asm/irqflags.h> | 39 | #include <asm/irqflags.h> |
40 | #include <asm/kvm_book3s_asm.h> | 40 | #include <asm/kvm_book3s_asm.h> |
41 | #include <asm/ptrace.h> | ||
41 | 42 | ||
42 | /* The physical memory is layed out such that the secondary processor | 43 | /* The physical memory is layed out such that the secondary processor |
43 | * spin code sits at 0x0000...0x00ff. On server, the vectors follow | 44 | * spin code sits at 0x0000...0x00ff. On server, the vectors follow |
@@ -96,7 +97,7 @@ __secondary_hold_acknowledge: | |||
96 | .llong hvReleaseData-KERNELBASE | 97 | .llong hvReleaseData-KERNELBASE |
97 | #endif /* CONFIG_PPC_ISERIES */ | 98 | #endif /* CONFIG_PPC_ISERIES */ |
98 | 99 | ||
99 | #ifdef CONFIG_CRASH_DUMP | 100 | #ifdef CONFIG_RELOCATABLE |
100 | /* This flag is set to 1 by a loader if the kernel should run | 101 | /* This flag is set to 1 by a loader if the kernel should run |
101 | * at the loaded address instead of the linked address. This | 102 | * at the loaded address instead of the linked address. This |
102 | * is used by kexec-tools to keep the the kdump kernel in the | 103 | * is used by kexec-tools to keep the the kdump kernel in the |
@@ -384,12 +385,10 @@ _STATIC(__after_prom_start) | |||
384 | /* process relocations for the final address of the kernel */ | 385 | /* process relocations for the final address of the kernel */ |
385 | lis r25,PAGE_OFFSET@highest /* compute virtual base of kernel */ | 386 | lis r25,PAGE_OFFSET@highest /* compute virtual base of kernel */ |
386 | sldi r25,r25,32 | 387 | sldi r25,r25,32 |
387 | #ifdef CONFIG_CRASH_DUMP | ||
388 | lwz r7,__run_at_load-_stext(r26) | 388 | lwz r7,__run_at_load-_stext(r26) |
389 | cmplwi cr0,r7,1 /* kdump kernel ? - stay where we are */ | 389 | cmplwi cr0,r7,1 /* flagged to stay where we are ? */ |
390 | bne 1f | 390 | bne 1f |
391 | add r25,r25,r26 | 391 | add r25,r25,r26 |
392 | #endif | ||
393 | 1: mr r3,r25 | 392 | 1: mr r3,r25 |
394 | bl .relocate | 393 | bl .relocate |
395 | #endif | 394 | #endif |
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index 1f1a04b5c2a4..1cbf64e6b416 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <asm/thread_info.h> | 29 | #include <asm/thread_info.h> |
30 | #include <asm/ppc_asm.h> | 30 | #include <asm/ppc_asm.h> |
31 | #include <asm/asm-offsets.h> | 31 | #include <asm/asm-offsets.h> |
32 | #include <asm/ptrace.h> | ||
32 | 33 | ||
33 | /* Macro to make the code more readable. */ | 34 | /* Macro to make the code more readable. */ |
34 | #ifdef CONFIG_8xx_CPU6 | 35 | #ifdef CONFIG_8xx_CPU6 |
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 529b817f473b..3e02710d9562 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <asm/ppc_asm.h> | 41 | #include <asm/ppc_asm.h> |
42 | #include <asm/asm-offsets.h> | 42 | #include <asm/asm-offsets.h> |
43 | #include <asm/cache.h> | 43 | #include <asm/cache.h> |
44 | #include <asm/ptrace.h> | ||
44 | #include "head_booke.h" | 45 | #include "head_booke.h" |
45 | 46 | ||
46 | /* As with the other PowerPC ports, it is expected that when code | 47 | /* As with the other PowerPC ports, it is expected that when code |
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index d5839179ec77..961bb03413f3 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c | |||
@@ -311,8 +311,9 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, | |||
311 | /* Handle failure */ | 311 | /* Handle failure */ |
312 | if (unlikely(entry == DMA_ERROR_CODE)) { | 312 | if (unlikely(entry == DMA_ERROR_CODE)) { |
313 | if (printk_ratelimit()) | 313 | if (printk_ratelimit()) |
314 | printk(KERN_INFO "iommu_alloc failed, tbl %p vaddr %lx" | 314 | dev_info(dev, "iommu_alloc failed, tbl %p " |
315 | " npages %lx\n", tbl, vaddr, npages); | 315 | "vaddr %lx npages %lu\n", tbl, vaddr, |
316 | npages); | ||
316 | goto failure; | 317 | goto failure; |
317 | } | 318 | } |
318 | 319 | ||
@@ -579,9 +580,9 @@ dma_addr_t iommu_map_page(struct device *dev, struct iommu_table *tbl, | |||
579 | attrs); | 580 | attrs); |
580 | if (dma_handle == DMA_ERROR_CODE) { | 581 | if (dma_handle == DMA_ERROR_CODE) { |
581 | if (printk_ratelimit()) { | 582 | if (printk_ratelimit()) { |
582 | printk(KERN_INFO "iommu_alloc failed, " | 583 | dev_info(dev, "iommu_alloc failed, tbl %p " |
583 | "tbl %p vaddr %p npages %d\n", | 584 | "vaddr %p npages %d\n", tbl, vaddr, |
584 | tbl, vaddr, npages); | 585 | npages); |
585 | } | 586 | } |
586 | } else | 587 | } else |
587 | dma_handle |= (uaddr & ~IOMMU_PAGE_MASK); | 588 | dma_handle |= (uaddr & ~IOMMU_PAGE_MASK); |
@@ -627,7 +628,8 @@ void *iommu_alloc_coherent(struct device *dev, struct iommu_table *tbl, | |||
627 | * the tce tables. | 628 | * the tce tables. |
628 | */ | 629 | */ |
629 | if (order >= IOMAP_MAX_ORDER) { | 630 | if (order >= IOMAP_MAX_ORDER) { |
630 | printk("iommu_alloc_consistent size too large: 0x%lx\n", size); | 631 | dev_info(dev, "iommu_alloc_consistent size too large: 0x%lx\n", |
632 | size); | ||
631 | return NULL; | 633 | return NULL; |
632 | } | 634 | } |
633 | 635 | ||
diff --git a/arch/powerpc/kernel/misc.S b/arch/powerpc/kernel/misc.S index 2d29752cbe16..b69463ec2010 100644 --- a/arch/powerpc/kernel/misc.S +++ b/arch/powerpc/kernel/misc.S | |||
@@ -122,8 +122,3 @@ _GLOBAL(longjmp) | |||
122 | mtlr r0 | 122 | mtlr r0 |
123 | mr r3,r4 | 123 | mr r3,r4 |
124 | blr | 124 | blr |
125 | |||
126 | _GLOBAL(__setup_cpu_power7) | ||
127 | _GLOBAL(__restore_cpu_power7) | ||
128 | /* place holder */ | ||
129 | blr | ||
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index a7a570dcdd57..094bd9821ad4 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <asm/processor.h> | 30 | #include <asm/processor.h> |
31 | #include <asm/kexec.h> | 31 | #include <asm/kexec.h> |
32 | #include <asm/bug.h> | 32 | #include <asm/bug.h> |
33 | #include <asm/ptrace.h> | ||
33 | 34 | ||
34 | .text | 35 | .text |
35 | 36 | ||
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index e5144906a56d..206a321a71d3 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <asm/cputable.h> | 25 | #include <asm/cputable.h> |
26 | #include <asm/thread_info.h> | 26 | #include <asm/thread_info.h> |
27 | #include <asm/kexec.h> | 27 | #include <asm/kexec.h> |
28 | #include <asm/ptrace.h> | ||
28 | 29 | ||
29 | .text | 30 | .text |
30 | 31 | ||
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index 9cf197f01e94..bb12b3248f13 100644 --- a/arch/powerpc/kernel/nvram_64.c +++ b/arch/powerpc/kernel/nvram_64.c | |||
@@ -34,15 +34,26 @@ | |||
34 | 34 | ||
35 | #undef DEBUG_NVRAM | 35 | #undef DEBUG_NVRAM |
36 | 36 | ||
37 | static struct nvram_partition * nvram_part; | 37 | #define NVRAM_HEADER_LEN sizeof(struct nvram_header) |
38 | static long nvram_error_log_index = -1; | 38 | #define NVRAM_BLOCK_LEN NVRAM_HEADER_LEN |
39 | static long nvram_error_log_size = 0; | 39 | |
40 | /* If change this size, then change the size of NVNAME_LEN */ | ||
41 | struct nvram_header { | ||
42 | unsigned char signature; | ||
43 | unsigned char checksum; | ||
44 | unsigned short length; | ||
45 | /* Terminating null required only for names < 12 chars. */ | ||
46 | char name[12]; | ||
47 | }; | ||
40 | 48 | ||
41 | struct err_log_info { | 49 | struct nvram_partition { |
42 | int error_type; | 50 | struct list_head partition; |
43 | unsigned int seq_num; | 51 | struct nvram_header header; |
52 | unsigned int index; | ||
44 | }; | 53 | }; |
45 | 54 | ||
55 | static LIST_HEAD(nvram_partitions); | ||
56 | |||
46 | static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin) | 57 | static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin) |
47 | { | 58 | { |
48 | int size; | 59 | int size; |
@@ -186,14 +197,12 @@ static struct miscdevice nvram_dev = { | |||
186 | #ifdef DEBUG_NVRAM | 197 | #ifdef DEBUG_NVRAM |
187 | static void __init nvram_print_partitions(char * label) | 198 | static void __init nvram_print_partitions(char * label) |
188 | { | 199 | { |
189 | struct list_head * p; | ||
190 | struct nvram_partition * tmp_part; | 200 | struct nvram_partition * tmp_part; |
191 | 201 | ||
192 | printk(KERN_WARNING "--------%s---------\n", label); | 202 | printk(KERN_WARNING "--------%s---------\n", label); |
193 | printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n"); | 203 | printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n"); |
194 | list_for_each(p, &nvram_part->partition) { | 204 | list_for_each_entry(tmp_part, &nvram_partitions, partition) { |
195 | tmp_part = list_entry(p, struct nvram_partition, partition); | 205 | printk(KERN_WARNING "%4d \t%02x\t%02x\t%d\t%12s\n", |
196 | printk(KERN_WARNING "%4d \t%02x\t%02x\t%d\t%s\n", | ||
197 | tmp_part->index, tmp_part->header.signature, | 206 | tmp_part->index, tmp_part->header.signature, |
198 | tmp_part->header.checksum, tmp_part->header.length, | 207 | tmp_part->header.checksum, tmp_part->header.length, |
199 | tmp_part->header.name); | 208 | tmp_part->header.name); |
@@ -228,95 +237,113 @@ static unsigned char __init nvram_checksum(struct nvram_header *p) | |||
228 | return c_sum; | 237 | return c_sum; |
229 | } | 238 | } |
230 | 239 | ||
231 | static int __init nvram_remove_os_partition(void) | 240 | /** |
241 | * nvram_remove_partition - Remove one or more partitions in nvram | ||
242 | * @name: name of the partition to remove, or NULL for a | ||
243 | * signature only match | ||
244 | * @sig: signature of the partition(s) to remove | ||
245 | */ | ||
246 | |||
247 | int __init nvram_remove_partition(const char *name, int sig) | ||
232 | { | 248 | { |
233 | struct list_head *i; | 249 | struct nvram_partition *part, *prev, *tmp; |
234 | struct list_head *j; | ||
235 | struct nvram_partition * part; | ||
236 | struct nvram_partition * cur_part; | ||
237 | int rc; | 250 | int rc; |
238 | 251 | ||
239 | list_for_each(i, &nvram_part->partition) { | 252 | list_for_each_entry(part, &nvram_partitions, partition) { |
240 | part = list_entry(i, struct nvram_partition, partition); | 253 | if (part->header.signature != sig) |
241 | if (part->header.signature != NVRAM_SIG_OS) | ||
242 | continue; | 254 | continue; |
243 | 255 | if (name && strncmp(name, part->header.name, 12)) | |
244 | /* Make os partition a free partition */ | 256 | continue; |
257 | |||
258 | /* Make partition a free partition */ | ||
245 | part->header.signature = NVRAM_SIG_FREE; | 259 | part->header.signature = NVRAM_SIG_FREE; |
246 | sprintf(part->header.name, "wwwwwwwwwwww"); | 260 | strncpy(part->header.name, "wwwwwwwwwwww", 12); |
247 | part->header.checksum = nvram_checksum(&part->header); | 261 | part->header.checksum = nvram_checksum(&part->header); |
248 | |||
249 | /* Merge contiguous free partitions backwards */ | ||
250 | list_for_each_prev(j, &part->partition) { | ||
251 | cur_part = list_entry(j, struct nvram_partition, partition); | ||
252 | if (cur_part == nvram_part || cur_part->header.signature != NVRAM_SIG_FREE) { | ||
253 | break; | ||
254 | } | ||
255 | |||
256 | part->header.length += cur_part->header.length; | ||
257 | part->header.checksum = nvram_checksum(&part->header); | ||
258 | part->index = cur_part->index; | ||
259 | |||
260 | list_del(&cur_part->partition); | ||
261 | kfree(cur_part); | ||
262 | j = &part->partition; /* fixup our loop */ | ||
263 | } | ||
264 | |||
265 | /* Merge contiguous free partitions forwards */ | ||
266 | list_for_each(j, &part->partition) { | ||
267 | cur_part = list_entry(j, struct nvram_partition, partition); | ||
268 | if (cur_part == nvram_part || cur_part->header.signature != NVRAM_SIG_FREE) { | ||
269 | break; | ||
270 | } | ||
271 | |||
272 | part->header.length += cur_part->header.length; | ||
273 | part->header.checksum = nvram_checksum(&part->header); | ||
274 | |||
275 | list_del(&cur_part->partition); | ||
276 | kfree(cur_part); | ||
277 | j = &part->partition; /* fixup our loop */ | ||
278 | } | ||
279 | |||
280 | rc = nvram_write_header(part); | 262 | rc = nvram_write_header(part); |
281 | if (rc <= 0) { | 263 | if (rc <= 0) { |
282 | printk(KERN_ERR "nvram_remove_os_partition: nvram_write failed (%d)\n", rc); | 264 | printk(KERN_ERR "nvram_remove_partition: nvram_write failed (%d)\n", rc); |
283 | return rc; | 265 | return rc; |
284 | } | 266 | } |
267 | } | ||
285 | 268 | ||
269 | /* Merge contiguous ones */ | ||
270 | prev = NULL; | ||
271 | list_for_each_entry_safe(part, tmp, &nvram_partitions, partition) { | ||
272 | if (part->header.signature != NVRAM_SIG_FREE) { | ||
273 | prev = NULL; | ||
274 | continue; | ||
275 | } | ||
276 | if (prev) { | ||
277 | prev->header.length += part->header.length; | ||
278 | prev->header.checksum = nvram_checksum(&part->header); | ||
279 | rc = nvram_write_header(part); | ||
280 | if (rc <= 0) { | ||
281 | printk(KERN_ERR "nvram_remove_partition: nvram_write failed (%d)\n", rc); | ||
282 | return rc; | ||
283 | } | ||
284 | list_del(&part->partition); | ||
285 | kfree(part); | ||
286 | } else | ||
287 | prev = part; | ||
286 | } | 288 | } |
287 | 289 | ||
288 | return 0; | 290 | return 0; |
289 | } | 291 | } |
290 | 292 | ||
291 | /* nvram_create_os_partition | 293 | /** |
294 | * nvram_create_partition - Create a partition in nvram | ||
295 | * @name: name of the partition to create | ||
296 | * @sig: signature of the partition to create | ||
297 | * @req_size: size of data to allocate in bytes | ||
298 | * @min_size: minimum acceptable size (0 means req_size) | ||
292 | * | 299 | * |
293 | * Create a OS linux partition to buffer error logs. | 300 | * Returns a negative error code or a positive nvram index |
294 | * Will create a partition starting at the first free | 301 | * of the beginning of the data area of the newly created |
295 | * space found if space has enough room. | 302 | * partition. If you provided a min_size smaller than req_size |
303 | * you need to query for the actual size yourself after the | ||
304 | * call using nvram_partition_get_size(). | ||
296 | */ | 305 | */ |
297 | static int __init nvram_create_os_partition(void) | 306 | loff_t __init nvram_create_partition(const char *name, int sig, |
307 | int req_size, int min_size) | ||
298 | { | 308 | { |
299 | struct nvram_partition *part; | 309 | struct nvram_partition *part; |
300 | struct nvram_partition *new_part; | 310 | struct nvram_partition *new_part; |
301 | struct nvram_partition *free_part = NULL; | 311 | struct nvram_partition *free_part = NULL; |
302 | int seq_init[2] = { 0, 0 }; | 312 | static char nv_init_vals[16]; |
303 | loff_t tmp_index; | 313 | loff_t tmp_index; |
304 | long size = 0; | 314 | long size = 0; |
305 | int rc; | 315 | int rc; |
306 | 316 | ||
317 | /* Convert sizes from bytes to blocks */ | ||
318 | req_size = _ALIGN_UP(req_size, NVRAM_BLOCK_LEN) / NVRAM_BLOCK_LEN; | ||
319 | min_size = _ALIGN_UP(min_size, NVRAM_BLOCK_LEN) / NVRAM_BLOCK_LEN; | ||
320 | |||
321 | /* If no minimum size specified, make it the same as the | ||
322 | * requested size | ||
323 | */ | ||
324 | if (min_size == 0) | ||
325 | min_size = req_size; | ||
326 | if (min_size > req_size) | ||
327 | return -EINVAL; | ||
328 | |||
329 | /* Now add one block to each for the header */ | ||
330 | req_size += 1; | ||
331 | min_size += 1; | ||
332 | |||
307 | /* Find a free partition that will give us the maximum needed size | 333 | /* Find a free partition that will give us the maximum needed size |
308 | If can't find one that will give us the minimum size needed */ | 334 | If can't find one that will give us the minimum size needed */ |
309 | list_for_each_entry(part, &nvram_part->partition, partition) { | 335 | list_for_each_entry(part, &nvram_partitions, partition) { |
310 | if (part->header.signature != NVRAM_SIG_FREE) | 336 | if (part->header.signature != NVRAM_SIG_FREE) |
311 | continue; | 337 | continue; |
312 | 338 | ||
313 | if (part->header.length >= NVRAM_MAX_REQ) { | 339 | if (part->header.length >= req_size) { |
314 | size = NVRAM_MAX_REQ; | 340 | size = req_size; |
315 | free_part = part; | 341 | free_part = part; |
316 | break; | 342 | break; |
317 | } | 343 | } |
318 | if (!size && part->header.length >= NVRAM_MIN_REQ) { | 344 | if (part->header.length > size && |
319 | size = NVRAM_MIN_REQ; | 345 | part->header.length >= min_size) { |
346 | size = part->header.length; | ||
320 | free_part = part; | 347 | free_part = part; |
321 | } | 348 | } |
322 | } | 349 | } |
@@ -326,136 +353,95 @@ static int __init nvram_create_os_partition(void) | |||
326 | /* Create our OS partition */ | 353 | /* Create our OS partition */ |
327 | new_part = kmalloc(sizeof(*new_part), GFP_KERNEL); | 354 | new_part = kmalloc(sizeof(*new_part), GFP_KERNEL); |
328 | if (!new_part) { | 355 | if (!new_part) { |
329 | printk(KERN_ERR "nvram_create_os_partition: kmalloc failed\n"); | 356 | pr_err("nvram_create_os_partition: kmalloc failed\n"); |
330 | return -ENOMEM; | 357 | return -ENOMEM; |
331 | } | 358 | } |
332 | 359 | ||
333 | new_part->index = free_part->index; | 360 | new_part->index = free_part->index; |
334 | new_part->header.signature = NVRAM_SIG_OS; | 361 | new_part->header.signature = sig; |
335 | new_part->header.length = size; | 362 | new_part->header.length = size; |
336 | strcpy(new_part->header.name, "ppc64,linux"); | 363 | strncpy(new_part->header.name, name, 12); |
337 | new_part->header.checksum = nvram_checksum(&new_part->header); | 364 | new_part->header.checksum = nvram_checksum(&new_part->header); |
338 | 365 | ||
339 | rc = nvram_write_header(new_part); | 366 | rc = nvram_write_header(new_part); |
340 | if (rc <= 0) { | 367 | if (rc <= 0) { |
341 | printk(KERN_ERR "nvram_create_os_partition: nvram_write_header " | 368 | pr_err("nvram_create_os_partition: nvram_write_header " |
342 | "failed (%d)\n", rc); | ||
343 | return rc; | ||
344 | } | ||
345 | |||
346 | /* make sure and initialize to zero the sequence number and the error | ||
347 | type logged */ | ||
348 | tmp_index = new_part->index + NVRAM_HEADER_LEN; | ||
349 | rc = ppc_md.nvram_write((char *)&seq_init, sizeof(seq_init), &tmp_index); | ||
350 | if (rc <= 0) { | ||
351 | printk(KERN_ERR "nvram_create_os_partition: nvram_write " | ||
352 | "failed (%d)\n", rc); | 369 | "failed (%d)\n", rc); |
353 | return rc; | 370 | return rc; |
354 | } | 371 | } |
355 | |||
356 | nvram_error_log_index = new_part->index + NVRAM_HEADER_LEN; | ||
357 | nvram_error_log_size = ((part->header.length - 1) * | ||
358 | NVRAM_BLOCK_LEN) - sizeof(struct err_log_info); | ||
359 | |||
360 | list_add_tail(&new_part->partition, &free_part->partition); | 372 | list_add_tail(&new_part->partition, &free_part->partition); |
361 | 373 | ||
362 | if (free_part->header.length <= size) { | 374 | /* Adjust or remove the partition we stole the space from */ |
375 | if (free_part->header.length > size) { | ||
376 | free_part->index += size * NVRAM_BLOCK_LEN; | ||
377 | free_part->header.length -= size; | ||
378 | free_part->header.checksum = nvram_checksum(&free_part->header); | ||
379 | rc = nvram_write_header(free_part); | ||
380 | if (rc <= 0) { | ||
381 | pr_err("nvram_create_os_partition: nvram_write_header " | ||
382 | "failed (%d)\n", rc); | ||
383 | return rc; | ||
384 | } | ||
385 | } else { | ||
363 | list_del(&free_part->partition); | 386 | list_del(&free_part->partition); |
364 | kfree(free_part); | 387 | kfree(free_part); |
365 | return 0; | ||
366 | } | 388 | } |
367 | 389 | ||
368 | /* Adjust the partition we stole the space from */ | 390 | /* Clear the new partition */ |
369 | free_part->index += size * NVRAM_BLOCK_LEN; | 391 | for (tmp_index = new_part->index + NVRAM_HEADER_LEN; |
370 | free_part->header.length -= size; | 392 | tmp_index < ((size - 1) * NVRAM_BLOCK_LEN); |
371 | free_part->header.checksum = nvram_checksum(&free_part->header); | 393 | tmp_index += NVRAM_BLOCK_LEN) { |
372 | 394 | rc = ppc_md.nvram_write(nv_init_vals, NVRAM_BLOCK_LEN, &tmp_index); | |
373 | rc = nvram_write_header(free_part); | 395 | if (rc <= 0) { |
374 | if (rc <= 0) { | 396 | pr_err("nvram_create_partition: nvram_write failed (%d)\n", rc); |
375 | printk(KERN_ERR "nvram_create_os_partition: nvram_write_header " | 397 | return rc; |
376 | "failed (%d)\n", rc); | 398 | } |
377 | return rc; | ||
378 | } | 399 | } |
379 | 400 | ||
380 | return 0; | 401 | return new_part->index + NVRAM_HEADER_LEN; |
381 | } | 402 | } |
382 | 403 | ||
383 | 404 | /** | |
384 | /* nvram_setup_partition | 405 | * nvram_get_partition_size - Get the data size of an nvram partition |
385 | * | 406 | * @data_index: This is the offset of the start of the data of |
386 | * This will setup the partition we need for buffering the | 407 | * the partition. The same value that is returned by |
387 | * error logs and cleanup partitions if needed. | 408 | * nvram_create_partition(). |
388 | * | ||
389 | * The general strategy is the following: | ||
390 | * 1.) If there is ppc64,linux partition large enough then use it. | ||
391 | * 2.) If there is not a ppc64,linux partition large enough, search | ||
392 | * for a free partition that is large enough. | ||
393 | * 3.) If there is not a free partition large enough remove | ||
394 | * _all_ OS partitions and consolidate the space. | ||
395 | * 4.) Will first try getting a chunk that will satisfy the maximum | ||
396 | * error log size (NVRAM_MAX_REQ). | ||
397 | * 5.) If the max chunk cannot be allocated then try finding a chunk | ||
398 | * that will satisfy the minum needed (NVRAM_MIN_REQ). | ||
399 | */ | 409 | */ |
400 | static int __init nvram_setup_partition(void) | 410 | int nvram_get_partition_size(loff_t data_index) |
401 | { | 411 | { |
402 | struct list_head * p; | 412 | struct nvram_partition *part; |
403 | struct nvram_partition * part; | 413 | |
404 | int rc; | 414 | list_for_each_entry(part, &nvram_partitions, partition) { |
405 | 415 | if (part->index + NVRAM_HEADER_LEN == data_index) | |
406 | /* For now, we don't do any of this on pmac, until I | 416 | return (part->header.length - 1) * NVRAM_BLOCK_LEN; |
407 | * have figured out if it's worth killing some unused stuffs | 417 | } |
408 | * in our nvram, as Apple defined partitions use pretty much | 418 | return -1; |
409 | * all of the space | 419 | } |
410 | */ | ||
411 | if (machine_is(powermac)) | ||
412 | return -ENOSPC; | ||
413 | |||
414 | /* see if we have an OS partition that meets our needs. | ||
415 | will try getting the max we need. If not we'll delete | ||
416 | partitions and try again. */ | ||
417 | list_for_each(p, &nvram_part->partition) { | ||
418 | part = list_entry(p, struct nvram_partition, partition); | ||
419 | if (part->header.signature != NVRAM_SIG_OS) | ||
420 | continue; | ||
421 | 420 | ||
422 | if (strcmp(part->header.name, "ppc64,linux")) | ||
423 | continue; | ||
424 | 421 | ||
425 | if (part->header.length >= NVRAM_MIN_REQ) { | 422 | /** |
426 | /* found our partition */ | 423 | * nvram_find_partition - Find an nvram partition by signature and name |
427 | nvram_error_log_index = part->index + NVRAM_HEADER_LEN; | 424 | * @name: Name of the partition or NULL for any name |
428 | nvram_error_log_size = ((part->header.length - 1) * | 425 | * @sig: Signature to test against |
429 | NVRAM_BLOCK_LEN) - sizeof(struct err_log_info); | 426 | * @out_size: if non-NULL, returns the size of the data part of the partition |
430 | return 0; | 427 | */ |
428 | loff_t nvram_find_partition(const char *name, int sig, int *out_size) | ||
429 | { | ||
430 | struct nvram_partition *p; | ||
431 | |||
432 | list_for_each_entry(p, &nvram_partitions, partition) { | ||
433 | if (p->header.signature == sig && | ||
434 | (!name || !strncmp(p->header.name, name, 12))) { | ||
435 | if (out_size) | ||
436 | *out_size = (p->header.length - 1) * | ||
437 | NVRAM_BLOCK_LEN; | ||
438 | return p->index + NVRAM_HEADER_LEN; | ||
431 | } | 439 | } |
432 | } | 440 | } |
433 | |||
434 | /* try creating a partition with the free space we have */ | ||
435 | rc = nvram_create_os_partition(); | ||
436 | if (!rc) { | ||
437 | return 0; | ||
438 | } | ||
439 | |||
440 | /* need to free up some space */ | ||
441 | rc = nvram_remove_os_partition(); | ||
442 | if (rc) { | ||
443 | return rc; | ||
444 | } | ||
445 | |||
446 | /* create a partition in this new space */ | ||
447 | rc = nvram_create_os_partition(); | ||
448 | if (rc) { | ||
449 | printk(KERN_ERR "nvram_create_os_partition: Could not find a " | ||
450 | "NVRAM partition large enough\n"); | ||
451 | return rc; | ||
452 | } | ||
453 | |||
454 | return 0; | 441 | return 0; |
455 | } | 442 | } |
456 | 443 | ||
457 | 444 | int __init nvram_scan_partitions(void) | |
458 | static int __init nvram_scan_partitions(void) | ||
459 | { | 445 | { |
460 | loff_t cur_index = 0; | 446 | loff_t cur_index = 0; |
461 | struct nvram_header phead; | 447 | struct nvram_header phead; |
@@ -465,7 +451,7 @@ static int __init nvram_scan_partitions(void) | |||
465 | int total_size; | 451 | int total_size; |
466 | int err; | 452 | int err; |
467 | 453 | ||
468 | if (ppc_md.nvram_size == NULL) | 454 | if (ppc_md.nvram_size == NULL || ppc_md.nvram_size() <= 0) |
469 | return -ENODEV; | 455 | return -ENODEV; |
470 | total_size = ppc_md.nvram_size(); | 456 | total_size = ppc_md.nvram_size(); |
471 | 457 | ||
@@ -512,12 +498,16 @@ static int __init nvram_scan_partitions(void) | |||
512 | 498 | ||
513 | memcpy(&tmp_part->header, &phead, NVRAM_HEADER_LEN); | 499 | memcpy(&tmp_part->header, &phead, NVRAM_HEADER_LEN); |
514 | tmp_part->index = cur_index; | 500 | tmp_part->index = cur_index; |
515 | list_add_tail(&tmp_part->partition, &nvram_part->partition); | 501 | list_add_tail(&tmp_part->partition, &nvram_partitions); |
516 | 502 | ||
517 | cur_index += phead.length * NVRAM_BLOCK_LEN; | 503 | cur_index += phead.length * NVRAM_BLOCK_LEN; |
518 | } | 504 | } |
519 | err = 0; | 505 | err = 0; |
520 | 506 | ||
507 | #ifdef DEBUG_NVRAM | ||
508 | nvram_print_partitions("NVRAM Partitions"); | ||
509 | #endif | ||
510 | |||
521 | out: | 511 | out: |
522 | kfree(header); | 512 | kfree(header); |
523 | return err; | 513 | return err; |
@@ -525,9 +515,10 @@ static int __init nvram_scan_partitions(void) | |||
525 | 515 | ||
526 | static int __init nvram_init(void) | 516 | static int __init nvram_init(void) |
527 | { | 517 | { |
528 | int error; | ||
529 | int rc; | 518 | int rc; |
530 | 519 | ||
520 | BUILD_BUG_ON(NVRAM_BLOCK_LEN != 16); | ||
521 | |||
531 | if (ppc_md.nvram_size == NULL || ppc_md.nvram_size() <= 0) | 522 | if (ppc_md.nvram_size == NULL || ppc_md.nvram_size() <= 0) |
532 | return -ENODEV; | 523 | return -ENODEV; |
533 | 524 | ||
@@ -537,29 +528,6 @@ static int __init nvram_init(void) | |||
537 | return rc; | 528 | return rc; |
538 | } | 529 | } |
539 | 530 | ||
540 | /* initialize our anchor for the nvram partition list */ | ||
541 | nvram_part = kmalloc(sizeof(struct nvram_partition), GFP_KERNEL); | ||
542 | if (!nvram_part) { | ||
543 | printk(KERN_ERR "nvram_init: Failed kmalloc\n"); | ||
544 | return -ENOMEM; | ||
545 | } | ||
546 | INIT_LIST_HEAD(&nvram_part->partition); | ||
547 | |||
548 | /* Get all the NVRAM partitions */ | ||
549 | error = nvram_scan_partitions(); | ||
550 | if (error) { | ||
551 | printk(KERN_ERR "nvram_init: Failed nvram_scan_partitions\n"); | ||
552 | return error; | ||
553 | } | ||
554 | |||
555 | if(nvram_setup_partition()) | ||
556 | printk(KERN_WARNING "nvram_init: Could not find nvram partition" | ||
557 | " for nvram buffered error logging.\n"); | ||
558 | |||
559 | #ifdef DEBUG_NVRAM | ||
560 | nvram_print_partitions("NVRAM Partitions"); | ||
561 | #endif | ||
562 | |||
563 | return rc; | 531 | return rc; |
564 | } | 532 | } |
565 | 533 | ||
@@ -568,135 +536,6 @@ void __exit nvram_cleanup(void) | |||
568 | misc_deregister( &nvram_dev ); | 536 | misc_deregister( &nvram_dev ); |
569 | } | 537 | } |
570 | 538 | ||
571 | |||
572 | #ifdef CONFIG_PPC_PSERIES | ||
573 | |||
574 | /* nvram_write_error_log | ||
575 | * | ||
576 | * We need to buffer the error logs into nvram to ensure that we have | ||
577 | * the failure information to decode. If we have a severe error there | ||
578 | * is no way to guarantee that the OS or the machine is in a state to | ||
579 | * get back to user land and write the error to disk. For example if | ||
580 | * the SCSI device driver causes a Machine Check by writing to a bad | ||
581 | * IO address, there is no way of guaranteeing that the device driver | ||
582 | * is in any state that is would also be able to write the error data | ||
583 | * captured to disk, thus we buffer it in NVRAM for analysis on the | ||
584 | * next boot. | ||
585 | * | ||
586 | * In NVRAM the partition containing the error log buffer will looks like: | ||
587 | * Header (in bytes): | ||
588 | * +-----------+----------+--------+------------+------------------+ | ||
589 | * | signature | checksum | length | name | data | | ||
590 | * |0 |1 |2 3|4 15|16 length-1| | ||
591 | * +-----------+----------+--------+------------+------------------+ | ||
592 | * | ||
593 | * The 'data' section would look like (in bytes): | ||
594 | * +--------------+------------+-----------------------------------+ | ||
595 | * | event_logged | sequence # | error log | | ||
596 | * |0 3|4 7|8 nvram_error_log_size-1| | ||
597 | * +--------------+------------+-----------------------------------+ | ||
598 | * | ||
599 | * event_logged: 0 if event has not been logged to syslog, 1 if it has | ||
600 | * sequence #: The unique sequence # for each event. (until it wraps) | ||
601 | * error log: The error log from event_scan | ||
602 | */ | ||
603 | int nvram_write_error_log(char * buff, int length, | ||
604 | unsigned int err_type, unsigned int error_log_cnt) | ||
605 | { | ||
606 | int rc; | ||
607 | loff_t tmp_index; | ||
608 | struct err_log_info info; | ||
609 | |||
610 | if (nvram_error_log_index == -1) { | ||
611 | return -ESPIPE; | ||
612 | } | ||
613 | |||
614 | if (length > nvram_error_log_size) { | ||
615 | length = nvram_error_log_size; | ||
616 | } | ||
617 | |||
618 | info.error_type = err_type; | ||
619 | info.seq_num = error_log_cnt; | ||
620 | |||
621 | tmp_index = nvram_error_log_index; | ||
622 | |||
623 | rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info), &tmp_index); | ||
624 | if (rc <= 0) { | ||
625 | printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc); | ||
626 | return rc; | ||
627 | } | ||
628 | |||
629 | rc = ppc_md.nvram_write(buff, length, &tmp_index); | ||
630 | if (rc <= 0) { | ||
631 | printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc); | ||
632 | return rc; | ||
633 | } | ||
634 | |||
635 | return 0; | ||
636 | } | ||
637 | |||
638 | /* nvram_read_error_log | ||
639 | * | ||
640 | * Reads nvram for error log for at most 'length' | ||
641 | */ | ||
642 | int nvram_read_error_log(char * buff, int length, | ||
643 | unsigned int * err_type, unsigned int * error_log_cnt) | ||
644 | { | ||
645 | int rc; | ||
646 | loff_t tmp_index; | ||
647 | struct err_log_info info; | ||
648 | |||
649 | if (nvram_error_log_index == -1) | ||
650 | return -1; | ||
651 | |||
652 | if (length > nvram_error_log_size) | ||
653 | length = nvram_error_log_size; | ||
654 | |||
655 | tmp_index = nvram_error_log_index; | ||
656 | |||
657 | rc = ppc_md.nvram_read((char *)&info, sizeof(struct err_log_info), &tmp_index); | ||
658 | if (rc <= 0) { | ||
659 | printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc); | ||
660 | return rc; | ||
661 | } | ||
662 | |||
663 | rc = ppc_md.nvram_read(buff, length, &tmp_index); | ||
664 | if (rc <= 0) { | ||
665 | printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc); | ||
666 | return rc; | ||
667 | } | ||
668 | |||
669 | *error_log_cnt = info.seq_num; | ||
670 | *err_type = info.error_type; | ||
671 | |||
672 | return 0; | ||
673 | } | ||
674 | |||
675 | /* This doesn't actually zero anything, but it sets the event_logged | ||
676 | * word to tell that this event is safely in syslog. | ||
677 | */ | ||
678 | int nvram_clear_error_log(void) | ||
679 | { | ||
680 | loff_t tmp_index; | ||
681 | int clear_word = ERR_FLAG_ALREADY_LOGGED; | ||
682 | int rc; | ||
683 | |||
684 | if (nvram_error_log_index == -1) | ||
685 | return -1; | ||
686 | |||
687 | tmp_index = nvram_error_log_index; | ||
688 | |||
689 | rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index); | ||
690 | if (rc <= 0) { | ||
691 | printk(KERN_ERR "nvram_clear_error_log: Failed nvram_write (%d)\n", rc); | ||
692 | return rc; | ||
693 | } | ||
694 | |||
695 | return 0; | ||
696 | } | ||
697 | |||
698 | #endif /* CONFIG_PPC_PSERIES */ | ||
699 | |||
700 | module_init(nvram_init); | 539 | module_init(nvram_init); |
701 | module_exit(nvram_cleanup); | 540 | module_exit(nvram_cleanup); |
702 | MODULE_LICENSE("GPL"); | 541 | MODULE_LICENSE("GPL"); |
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index d43fc65749c1..851577608a78 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c | |||
@@ -193,8 +193,7 @@ int __devinit pcibios_map_io_space(struct pci_bus *bus) | |||
193 | hose->io_resource.start += io_virt_offset; | 193 | hose->io_resource.start += io_virt_offset; |
194 | hose->io_resource.end += io_virt_offset; | 194 | hose->io_resource.end += io_virt_offset; |
195 | 195 | ||
196 | pr_debug(" hose->io_resource=0x%016llx...0x%016llx\n", | 196 | pr_debug(" hose->io_resource=%pR\n", &hose->io_resource); |
197 | hose->io_resource.start, hose->io_resource.end); | ||
198 | 197 | ||
199 | return 0; | 198 | return 0; |
200 | } | 199 | } |
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index ab3e392ac63c..ef3ef566235e 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c | |||
@@ -186,3 +186,10 @@ EXPORT_SYMBOL(__mtdcr); | |||
186 | EXPORT_SYMBOL(__mfdcr); | 186 | EXPORT_SYMBOL(__mfdcr); |
187 | #endif | 187 | #endif |
188 | EXPORT_SYMBOL(empty_zero_page); | 188 | EXPORT_SYMBOL(empty_zero_page); |
189 | |||
190 | #ifdef CONFIG_PPC64 | ||
191 | EXPORT_SYMBOL(__arch_hweight8); | ||
192 | EXPORT_SYMBOL(__arch_hweight16); | ||
193 | EXPORT_SYMBOL(__arch_hweight32); | ||
194 | EXPORT_SYMBOL(__arch_hweight64); | ||
195 | #endif | ||
diff --git a/arch/powerpc/kernel/ppc_save_regs.S b/arch/powerpc/kernel/ppc_save_regs.S index 5113bd2285e1..e83ba3f078e4 100644 --- a/arch/powerpc/kernel/ppc_save_regs.S +++ b/arch/powerpc/kernel/ppc_save_regs.S | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <asm/processor.h> | 11 | #include <asm/processor.h> |
12 | #include <asm/ppc_asm.h> | 12 | #include <asm/ppc_asm.h> |
13 | #include <asm/asm-offsets.h> | 13 | #include <asm/asm-offsets.h> |
14 | #include <asm/ptrace.h> | ||
14 | 15 | ||
15 | /* | 16 | /* |
16 | * Grab the register values as they are now. | 17 | * Grab the register values as they are now. |
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index a9b32967cff6..906536998291 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
@@ -1316,6 +1316,10 @@ static int set_dac_range(struct task_struct *child, | |||
1316 | static long ppc_set_hwdebug(struct task_struct *child, | 1316 | static long ppc_set_hwdebug(struct task_struct *child, |
1317 | struct ppc_hw_breakpoint *bp_info) | 1317 | struct ppc_hw_breakpoint *bp_info) |
1318 | { | 1318 | { |
1319 | #ifndef CONFIG_PPC_ADV_DEBUG_REGS | ||
1320 | unsigned long dabr; | ||
1321 | #endif | ||
1322 | |||
1319 | if (bp_info->version != 1) | 1323 | if (bp_info->version != 1) |
1320 | return -ENOTSUPP; | 1324 | return -ENOTSUPP; |
1321 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | 1325 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
@@ -1353,11 +1357,10 @@ static long ppc_set_hwdebug(struct task_struct *child, | |||
1353 | /* | 1357 | /* |
1354 | * We only support one data breakpoint | 1358 | * We only support one data breakpoint |
1355 | */ | 1359 | */ |
1356 | if (((bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_RW) == 0) || | 1360 | if ((bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_RW) == 0 || |
1357 | ((bp_info->trigger_type & ~PPC_BREAKPOINT_TRIGGER_RW) != 0) || | 1361 | (bp_info->trigger_type & ~PPC_BREAKPOINT_TRIGGER_RW) != 0 || |
1358 | (bp_info->trigger_type != PPC_BREAKPOINT_TRIGGER_WRITE) || | 1362 | bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT || |
1359 | (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT) || | 1363 | bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE) |
1360 | (bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE)) | ||
1361 | return -EINVAL; | 1364 | return -EINVAL; |
1362 | 1365 | ||
1363 | if (child->thread.dabr) | 1366 | if (child->thread.dabr) |
@@ -1366,7 +1369,14 @@ static long ppc_set_hwdebug(struct task_struct *child, | |||
1366 | if ((unsigned long)bp_info->addr >= TASK_SIZE) | 1369 | if ((unsigned long)bp_info->addr >= TASK_SIZE) |
1367 | return -EIO; | 1370 | return -EIO; |
1368 | 1371 | ||
1369 | child->thread.dabr = (unsigned long)bp_info->addr; | 1372 | dabr = (unsigned long)bp_info->addr & ~7UL; |
1373 | dabr |= DABR_TRANSLATION; | ||
1374 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ) | ||
1375 | dabr |= DABR_DATA_READ; | ||
1376 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE) | ||
1377 | dabr |= DABR_DATA_WRITE; | ||
1378 | |||
1379 | child->thread.dabr = dabr; | ||
1370 | 1380 | ||
1371 | return 1; | 1381 | return 1; |
1372 | #endif /* !CONFIG_PPC_ADV_DEBUG_DVCS */ | 1382 | #endif /* !CONFIG_PPC_ADV_DEBUG_DVCS */ |
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c index 8a6daf4129f6..69c4be917d07 100644 --- a/arch/powerpc/kernel/ptrace32.c +++ b/arch/powerpc/kernel/ptrace32.c | |||
@@ -280,7 +280,11 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | |||
280 | /* We only support one DABR and no IABRS at the moment */ | 280 | /* We only support one DABR and no IABRS at the moment */ |
281 | if (addr > 0) | 281 | if (addr > 0) |
282 | break; | 282 | break; |
283 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | ||
284 | ret = put_user(child->thread.dac1, (u32 __user *)data); | ||
285 | #else | ||
283 | ret = put_user(child->thread.dabr, (u32 __user *)data); | 286 | ret = put_user(child->thread.dabr, (u32 __user *)data); |
287 | #endif | ||
284 | break; | 288 | break; |
285 | } | 289 | } |
286 | 290 | ||
@@ -312,6 +316,9 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | |||
312 | case PTRACE_SET_DEBUGREG: | 316 | case PTRACE_SET_DEBUGREG: |
313 | case PTRACE_SYSCALL: | 317 | case PTRACE_SYSCALL: |
314 | case PTRACE_CONT: | 318 | case PTRACE_CONT: |
319 | case PPC_PTRACE_GETHWDBGINFO: | ||
320 | case PPC_PTRACE_SETHWDEBUG: | ||
321 | case PPC_PTRACE_DELHWDEBUG: | ||
315 | ret = arch_ptrace(child, request, addr, data); | 322 | ret = arch_ptrace(child, request, addr, data); |
316 | break; | 323 | break; |
317 | 324 | ||
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 8fe8bc61c10a..2097f2b3cba8 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <asm/atomic.h> | 41 | #include <asm/atomic.h> |
42 | #include <asm/time.h> | 42 | #include <asm/time.h> |
43 | #include <asm/mmu.h> | 43 | #include <asm/mmu.h> |
44 | #include <asm/topology.h> | ||
44 | 45 | ||
45 | struct rtas_t rtas = { | 46 | struct rtas_t rtas = { |
46 | .lock = __ARCH_SPIN_LOCK_UNLOCKED | 47 | .lock = __ARCH_SPIN_LOCK_UNLOCKED |
@@ -713,6 +714,7 @@ static int __rtas_suspend_last_cpu(struct rtas_suspend_me_data *data, int wake_w | |||
713 | int cpu; | 714 | int cpu; |
714 | 715 | ||
715 | slb_set_size(SLB_MIN_SIZE); | 716 | slb_set_size(SLB_MIN_SIZE); |
717 | stop_topology_update(); | ||
716 | printk(KERN_DEBUG "calling ibm,suspend-me on cpu %i\n", smp_processor_id()); | 718 | printk(KERN_DEBUG "calling ibm,suspend-me on cpu %i\n", smp_processor_id()); |
717 | 719 | ||
718 | while (rc == H_MULTI_THREADS_ACTIVE && !atomic_read(&data->done) && | 720 | while (rc == H_MULTI_THREADS_ACTIVE && !atomic_read(&data->done) && |
@@ -728,6 +730,7 @@ static int __rtas_suspend_last_cpu(struct rtas_suspend_me_data *data, int wake_w | |||
728 | rc = atomic_read(&data->error); | 730 | rc = atomic_read(&data->error); |
729 | 731 | ||
730 | atomic_set(&data->error, rc); | 732 | atomic_set(&data->error, rc); |
733 | start_topology_update(); | ||
731 | 734 | ||
732 | if (wake_when_done) { | 735 | if (wake_when_done) { |
733 | atomic_set(&data->done, 1); | 736 | atomic_set(&data->done, 1); |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index ce6f61c6f871..5a0401fcaebd 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -437,8 +437,8 @@ static void __init irqstack_early_init(void) | |||
437 | unsigned int i; | 437 | unsigned int i; |
438 | 438 | ||
439 | /* | 439 | /* |
440 | * interrupt stacks must be under 256MB, we cannot afford to take | 440 | * Interrupt stacks must be in the first segment since we |
441 | * SLB misses on them. | 441 | * cannot afford to take SLB misses on them. |
442 | */ | 442 | */ |
443 | for_each_possible_cpu(i) { | 443 | for_each_possible_cpu(i) { |
444 | softirq_ctx[i] = (struct thread_info *) | 444 | softirq_ctx[i] = (struct thread_info *) |
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 68034bbf2e4f..981360509172 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
@@ -466,7 +466,20 @@ out: | |||
466 | return id; | 466 | return id; |
467 | } | 467 | } |
468 | 468 | ||
469 | /* Must be called when no change can occur to cpu_present_mask, | 469 | /* Helper routines for cpu to core mapping */ |
470 | int cpu_core_index_of_thread(int cpu) | ||
471 | { | ||
472 | return cpu >> threads_shift; | ||
473 | } | ||
474 | EXPORT_SYMBOL_GPL(cpu_core_index_of_thread); | ||
475 | |||
476 | int cpu_first_thread_of_core(int core) | ||
477 | { | ||
478 | return core << threads_shift; | ||
479 | } | ||
480 | EXPORT_SYMBOL_GPL(cpu_first_thread_of_core); | ||
481 | |||
482 | /* Must be called when no change can occur to cpu_present_map, | ||
470 | * i.e. during cpu online or offline. | 483 | * i.e. during cpu online or offline. |
471 | */ | 484 | */ |
472 | static struct device_node *cpu_to_l2cache(int cpu) | 485 | static struct device_node *cpu_to_l2cache(int cpu) |
@@ -514,7 +527,7 @@ int __devinit start_secondary(void *unused) | |||
514 | notify_cpu_starting(cpu); | 527 | notify_cpu_starting(cpu); |
515 | set_cpu_online(cpu, true); | 528 | set_cpu_online(cpu, true); |
516 | /* Update sibling maps */ | 529 | /* Update sibling maps */ |
517 | base = cpu_first_thread_in_core(cpu); | 530 | base = cpu_first_thread_sibling(cpu); |
518 | for (i = 0; i < threads_per_core; i++) { | 531 | for (i = 0; i < threads_per_core; i++) { |
519 | if (cpu_is_offline(base + i)) | 532 | if (cpu_is_offline(base + i)) |
520 | continue; | 533 | continue; |
@@ -600,7 +613,7 @@ int __cpu_disable(void) | |||
600 | return err; | 613 | return err; |
601 | 614 | ||
602 | /* Update sibling maps */ | 615 | /* Update sibling maps */ |
603 | base = cpu_first_thread_in_core(cpu); | 616 | base = cpu_first_thread_sibling(cpu); |
604 | for (i = 0; i < threads_per_core; i++) { | 617 | for (i = 0; i < threads_per_core; i++) { |
605 | cpumask_clear_cpu(cpu, cpu_sibling_mask(base + i)); | 618 | cpumask_clear_cpu(cpu, cpu_sibling_mask(base + i)); |
606 | cpumask_clear_cpu(base + i, cpu_sibling_mask(cpu)); | 619 | cpumask_clear_cpu(base + i, cpu_sibling_mask(cpu)); |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 010406958d97..09e4dea4a85a 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -155,7 +155,7 @@ EXPORT_SYMBOL_GPL(rtc_lock); | |||
155 | 155 | ||
156 | static u64 tb_to_ns_scale __read_mostly; | 156 | static u64 tb_to_ns_scale __read_mostly; |
157 | static unsigned tb_to_ns_shift __read_mostly; | 157 | static unsigned tb_to_ns_shift __read_mostly; |
158 | static unsigned long boot_tb __read_mostly; | 158 | static u64 boot_tb __read_mostly; |
159 | 159 | ||
160 | extern struct timezone sys_tz; | 160 | extern struct timezone sys_tz; |
161 | static long timezone_offset; | 161 | static long timezone_offset; |
diff --git a/arch/powerpc/kernel/vector.S b/arch/powerpc/kernel/vector.S index fe460482fa68..9de6f396cf85 100644 --- a/arch/powerpc/kernel/vector.S +++ b/arch/powerpc/kernel/vector.S | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <asm/cputable.h> | 5 | #include <asm/cputable.h> |
6 | #include <asm/thread_info.h> | 6 | #include <asm/thread_info.h> |
7 | #include <asm/page.h> | 7 | #include <asm/page.h> |
8 | #include <asm/ptrace.h> | ||
8 | 9 | ||
9 | /* | 10 | /* |
10 | * load_up_altivec(unused, unused, tsk) | 11 | * load_up_altivec(unused, unused, tsk) |
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 441d2a722f06..1b695fdc362b 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c | |||
@@ -600,6 +600,11 @@ static void vio_dma_iommu_unmap_sg(struct device *dev, | |||
600 | vio_cmo_dealloc(viodev, alloc_size); | 600 | vio_cmo_dealloc(viodev, alloc_size); |
601 | } | 601 | } |
602 | 602 | ||
603 | static int vio_dma_iommu_dma_supported(struct device *dev, u64 mask) | ||
604 | { | ||
605 | return dma_iommu_ops.dma_supported(dev, mask); | ||
606 | } | ||
607 | |||
603 | struct dma_map_ops vio_dma_mapping_ops = { | 608 | struct dma_map_ops vio_dma_mapping_ops = { |
604 | .alloc_coherent = vio_dma_iommu_alloc_coherent, | 609 | .alloc_coherent = vio_dma_iommu_alloc_coherent, |
605 | .free_coherent = vio_dma_iommu_free_coherent, | 610 | .free_coherent = vio_dma_iommu_free_coherent, |
@@ -607,6 +612,7 @@ struct dma_map_ops vio_dma_mapping_ops = { | |||
607 | .unmap_sg = vio_dma_iommu_unmap_sg, | 612 | .unmap_sg = vio_dma_iommu_unmap_sg, |
608 | .map_page = vio_dma_iommu_map_page, | 613 | .map_page = vio_dma_iommu_map_page, |
609 | .unmap_page = vio_dma_iommu_unmap_page, | 614 | .unmap_page = vio_dma_iommu_unmap_page, |
615 | .dma_supported = vio_dma_iommu_dma_supported, | ||
610 | 616 | ||
611 | }; | 617 | }; |
612 | 618 | ||
@@ -858,8 +864,7 @@ static void vio_cmo_bus_remove(struct vio_dev *viodev) | |||
858 | 864 | ||
859 | static void vio_cmo_set_dma_ops(struct vio_dev *viodev) | 865 | static void vio_cmo_set_dma_ops(struct vio_dev *viodev) |
860 | { | 866 | { |
861 | vio_dma_mapping_ops.dma_supported = dma_iommu_ops.dma_supported; | 867 | set_dma_ops(&viodev->dev, &vio_dma_mapping_ops); |
862 | viodev->dev.archdata.dma_ops = &vio_dma_mapping_ops; | ||
863 | } | 868 | } |
864 | 869 | ||
865 | /** | 870 | /** |
@@ -1244,7 +1249,7 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node) | |||
1244 | if (firmware_has_feature(FW_FEATURE_CMO)) | 1249 | if (firmware_has_feature(FW_FEATURE_CMO)) |
1245 | vio_cmo_set_dma_ops(viodev); | 1250 | vio_cmo_set_dma_ops(viodev); |
1246 | else | 1251 | else |
1247 | viodev->dev.archdata.dma_ops = &dma_iommu_ops; | 1252 | set_dma_ops(&viodev->dev, &dma_iommu_ops); |
1248 | set_iommu_table_base(&viodev->dev, vio_build_iommu_table(viodev)); | 1253 | set_iommu_table_base(&viodev->dev, vio_build_iommu_table(viodev)); |
1249 | set_dev_node(&viodev->dev, of_node_to_nid(of_node)); | 1254 | set_dev_node(&viodev->dev, of_node_to_nid(of_node)); |
1250 | 1255 | ||
@@ -1252,6 +1257,10 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node) | |||
1252 | viodev->dev.parent = &vio_bus_device.dev; | 1257 | viodev->dev.parent = &vio_bus_device.dev; |
1253 | viodev->dev.bus = &vio_bus_type; | 1258 | viodev->dev.bus = &vio_bus_type; |
1254 | viodev->dev.release = vio_dev_release; | 1259 | viodev->dev.release = vio_dev_release; |
1260 | /* needed to ensure proper operation of coherent allocations | ||
1261 | * later, in case driver doesn't set it explicitly */ | ||
1262 | dma_set_mask(&viodev->dev, DMA_BIT_MASK(64)); | ||
1263 | dma_set_coherent_mask(&viodev->dev, DMA_BIT_MASK(64)); | ||
1255 | 1264 | ||
1256 | /* register with generic device framework */ | 1265 | /* register with generic device framework */ |
1257 | if (device_register(&viodev->dev)) { | 1266 | if (device_register(&viodev->dev)) { |
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile index 889f2bc106dd..166a6a0ad544 100644 --- a/arch/powerpc/lib/Makefile +++ b/arch/powerpc/lib/Makefile | |||
@@ -16,7 +16,7 @@ obj-$(CONFIG_HAS_IOMEM) += devres.o | |||
16 | 16 | ||
17 | obj-$(CONFIG_PPC64) += copypage_64.o copyuser_64.o \ | 17 | obj-$(CONFIG_PPC64) += copypage_64.o copyuser_64.o \ |
18 | memcpy_64.o usercopy_64.o mem_64.o string.o \ | 18 | memcpy_64.o usercopy_64.o mem_64.o string.o \ |
19 | checksum_wrappers_64.o | 19 | checksum_wrappers_64.o hweight_64.o |
20 | obj-$(CONFIG_XMON) += sstep.o ldstfp.o | 20 | obj-$(CONFIG_XMON) += sstep.o ldstfp.o |
21 | obj-$(CONFIG_KPROBES) += sstep.o ldstfp.o | 21 | obj-$(CONFIG_KPROBES) += sstep.o ldstfp.o |
22 | obj-$(CONFIG_HAVE_HW_BREAKPOINT) += sstep.o ldstfp.o | 22 | obj-$(CONFIG_HAVE_HW_BREAKPOINT) += sstep.o ldstfp.o |
diff --git a/arch/powerpc/lib/hweight_64.S b/arch/powerpc/lib/hweight_64.S new file mode 100644 index 000000000000..fda27868cf8c --- /dev/null +++ b/arch/powerpc/lib/hweight_64.S | |||
@@ -0,0 +1,110 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify | ||
3 | * it under the terms of the GNU General Public License as published by | ||
4 | * the Free Software Foundation; either version 2 of the License, or | ||
5 | * (at your option) any later version. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
15 | * | ||
16 | * Copyright (C) IBM Corporation, 2010 | ||
17 | * | ||
18 | * Author: Anton Blanchard <anton@au.ibm.com> | ||
19 | */ | ||
20 | #include <asm/processor.h> | ||
21 | #include <asm/ppc_asm.h> | ||
22 | |||
23 | /* Note: This code relies on -mminimal-toc */ | ||
24 | |||
25 | _GLOBAL(__arch_hweight8) | ||
26 | BEGIN_FTR_SECTION | ||
27 | b .__sw_hweight8 | ||
28 | nop | ||
29 | nop | ||
30 | FTR_SECTION_ELSE | ||
31 | PPC_POPCNTB(r3,r3) | ||
32 | clrldi r3,r3,64-8 | ||
33 | blr | ||
34 | ALT_FTR_SECTION_END_IFCLR(CPU_FTR_POPCNTB) | ||
35 | |||
36 | _GLOBAL(__arch_hweight16) | ||
37 | BEGIN_FTR_SECTION | ||
38 | b .__sw_hweight16 | ||
39 | nop | ||
40 | nop | ||
41 | nop | ||
42 | nop | ||
43 | FTR_SECTION_ELSE | ||
44 | BEGIN_FTR_SECTION_NESTED(50) | ||
45 | PPC_POPCNTB(r3,r3) | ||
46 | srdi r4,r3,8 | ||
47 | add r3,r4,r3 | ||
48 | clrldi r3,r3,64-8 | ||
49 | blr | ||
50 | FTR_SECTION_ELSE_NESTED(50) | ||
51 | clrlwi r3,r3,16 | ||
52 | PPC_POPCNTW(r3,r3) | ||
53 | clrldi r3,r3,64-8 | ||
54 | blr | ||
55 | ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_POPCNTD, 50) | ||
56 | ALT_FTR_SECTION_END_IFCLR(CPU_FTR_POPCNTB) | ||
57 | |||
58 | _GLOBAL(__arch_hweight32) | ||
59 | BEGIN_FTR_SECTION | ||
60 | b .__sw_hweight32 | ||
61 | nop | ||
62 | nop | ||
63 | nop | ||
64 | nop | ||
65 | nop | ||
66 | nop | ||
67 | FTR_SECTION_ELSE | ||
68 | BEGIN_FTR_SECTION_NESTED(51) | ||
69 | PPC_POPCNTB(r3,r3) | ||
70 | srdi r4,r3,16 | ||
71 | add r3,r4,r3 | ||
72 | srdi r4,r3,8 | ||
73 | add r3,r4,r3 | ||
74 | clrldi r3,r3,64-8 | ||
75 | blr | ||
76 | FTR_SECTION_ELSE_NESTED(51) | ||
77 | PPC_POPCNTW(r3,r3) | ||
78 | clrldi r3,r3,64-8 | ||
79 | blr | ||
80 | ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_POPCNTD, 51) | ||
81 | ALT_FTR_SECTION_END_IFCLR(CPU_FTR_POPCNTB) | ||
82 | |||
83 | _GLOBAL(__arch_hweight64) | ||
84 | BEGIN_FTR_SECTION | ||
85 | b .__sw_hweight64 | ||
86 | nop | ||
87 | nop | ||
88 | nop | ||
89 | nop | ||
90 | nop | ||
91 | nop | ||
92 | nop | ||
93 | nop | ||
94 | FTR_SECTION_ELSE | ||
95 | BEGIN_FTR_SECTION_NESTED(52) | ||
96 | PPC_POPCNTB(r3,r3) | ||
97 | srdi r4,r3,32 | ||
98 | add r3,r4,r3 | ||
99 | srdi r4,r3,16 | ||
100 | add r3,r4,r3 | ||
101 | srdi r4,r3,8 | ||
102 | add r3,r4,r3 | ||
103 | clrldi r3,r3,64-8 | ||
104 | blr | ||
105 | FTR_SECTION_ELSE_NESTED(52) | ||
106 | PPC_POPCNTD(r3,r3) | ||
107 | clrldi r3,r3,64-8 | ||
108 | blr | ||
109 | ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_POPCNTD, 52) | ||
110 | ALT_FTR_SECTION_END_IFCLR(CPU_FTR_POPCNTB) | ||
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 5e9584405c45..a5991facddce 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
@@ -1070,7 +1070,7 @@ void hash_preload(struct mm_struct *mm, unsigned long ea, | |||
1070 | unsigned long access, unsigned long trap) | 1070 | unsigned long access, unsigned long trap) |
1071 | { | 1071 | { |
1072 | unsigned long vsid; | 1072 | unsigned long vsid; |
1073 | void *pgdir; | 1073 | pgd_t *pgdir; |
1074 | pte_t *ptep; | 1074 | pte_t *ptep; |
1075 | unsigned long flags; | 1075 | unsigned long flags; |
1076 | int rc, ssize, local = 0; | 1076 | int rc, ssize, local = 0; |
diff --git a/arch/powerpc/mm/mmu_context_nohash.c b/arch/powerpc/mm/mmu_context_nohash.c index 5ce99848d91e..c0aab52da3a5 100644 --- a/arch/powerpc/mm/mmu_context_nohash.c +++ b/arch/powerpc/mm/mmu_context_nohash.c | |||
@@ -111,8 +111,8 @@ static unsigned int steal_context_smp(unsigned int id) | |||
111 | * a core map instead but this will do for now. | 111 | * a core map instead but this will do for now. |
112 | */ | 112 | */ |
113 | for_each_cpu(cpu, mm_cpumask(mm)) { | 113 | for_each_cpu(cpu, mm_cpumask(mm)) { |
114 | for (i = cpu_first_thread_in_core(cpu); | 114 | for (i = cpu_first_thread_sibling(cpu); |
115 | i <= cpu_last_thread_in_core(cpu); i++) | 115 | i <= cpu_last_thread_sibling(cpu); i++) |
116 | __set_bit(id, stale_map[i]); | 116 | __set_bit(id, stale_map[i]); |
117 | cpu = i - 1; | 117 | cpu = i - 1; |
118 | } | 118 | } |
@@ -264,14 +264,14 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next) | |||
264 | */ | 264 | */ |
265 | if (test_bit(id, stale_map[cpu])) { | 265 | if (test_bit(id, stale_map[cpu])) { |
266 | pr_hardcont(" | stale flush %d [%d..%d]", | 266 | pr_hardcont(" | stale flush %d [%d..%d]", |
267 | id, cpu_first_thread_in_core(cpu), | 267 | id, cpu_first_thread_sibling(cpu), |
268 | cpu_last_thread_in_core(cpu)); | 268 | cpu_last_thread_sibling(cpu)); |
269 | 269 | ||
270 | local_flush_tlb_mm(next); | 270 | local_flush_tlb_mm(next); |
271 | 271 | ||
272 | /* XXX This clear should ultimately be part of local_flush_tlb_mm */ | 272 | /* XXX This clear should ultimately be part of local_flush_tlb_mm */ |
273 | for (i = cpu_first_thread_in_core(cpu); | 273 | for (i = cpu_first_thread_sibling(cpu); |
274 | i <= cpu_last_thread_in_core(cpu); i++) { | 274 | i <= cpu_last_thread_sibling(cpu); i++) { |
275 | __clear_bit(id, stale_map[i]); | 275 | __clear_bit(id, stale_map[i]); |
276 | } | 276 | } |
277 | } | 277 | } |
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 74505b245374..bf5cb91f07de 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c | |||
@@ -20,10 +20,15 @@ | |||
20 | #include <linux/memblock.h> | 20 | #include <linux/memblock.h> |
21 | #include <linux/of.h> | 21 | #include <linux/of.h> |
22 | #include <linux/pfn.h> | 22 | #include <linux/pfn.h> |
23 | #include <linux/cpuset.h> | ||
24 | #include <linux/node.h> | ||
23 | #include <asm/sparsemem.h> | 25 | #include <asm/sparsemem.h> |
24 | #include <asm/prom.h> | 26 | #include <asm/prom.h> |
25 | #include <asm/system.h> | 27 | #include <asm/system.h> |
26 | #include <asm/smp.h> | 28 | #include <asm/smp.h> |
29 | #include <asm/firmware.h> | ||
30 | #include <asm/paca.h> | ||
31 | #include <asm/hvcall.h> | ||
27 | 32 | ||
28 | static int numa_enabled = 1; | 33 | static int numa_enabled = 1; |
29 | 34 | ||
@@ -163,7 +168,7 @@ static void __init get_node_active_region(unsigned long start_pfn, | |||
163 | work_with_active_regions(nid, get_active_region_work_fn, node_ar); | 168 | work_with_active_regions(nid, get_active_region_work_fn, node_ar); |
164 | } | 169 | } |
165 | 170 | ||
166 | static void __cpuinit map_cpu_to_node(int cpu, int node) | 171 | static void map_cpu_to_node(int cpu, int node) |
167 | { | 172 | { |
168 | numa_cpu_lookup_table[cpu] = node; | 173 | numa_cpu_lookup_table[cpu] = node; |
169 | 174 | ||
@@ -173,7 +178,7 @@ static void __cpuinit map_cpu_to_node(int cpu, int node) | |||
173 | cpumask_set_cpu(cpu, node_to_cpumask_map[node]); | 178 | cpumask_set_cpu(cpu, node_to_cpumask_map[node]); |
174 | } | 179 | } |
175 | 180 | ||
176 | #ifdef CONFIG_HOTPLUG_CPU | 181 | #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PPC_SPLPAR) |
177 | static void unmap_cpu_from_node(unsigned long cpu) | 182 | static void unmap_cpu_from_node(unsigned long cpu) |
178 | { | 183 | { |
179 | int node = numa_cpu_lookup_table[cpu]; | 184 | int node = numa_cpu_lookup_table[cpu]; |
@@ -187,7 +192,7 @@ static void unmap_cpu_from_node(unsigned long cpu) | |||
187 | cpu, node); | 192 | cpu, node); |
188 | } | 193 | } |
189 | } | 194 | } |
190 | #endif /* CONFIG_HOTPLUG_CPU */ | 195 | #endif /* CONFIG_HOTPLUG_CPU || CONFIG_PPC_SPLPAR */ |
191 | 196 | ||
192 | /* must hold reference to node during call */ | 197 | /* must hold reference to node during call */ |
193 | static const int *of_get_associativity(struct device_node *dev) | 198 | static const int *of_get_associativity(struct device_node *dev) |
@@ -246,32 +251,41 @@ static void initialize_distance_lookup_table(int nid, | |||
246 | /* Returns nid in the range [0..MAX_NUMNODES-1], or -1 if no useful numa | 251 | /* Returns nid in the range [0..MAX_NUMNODES-1], or -1 if no useful numa |
247 | * info is found. | 252 | * info is found. |
248 | */ | 253 | */ |
249 | static int of_node_to_nid_single(struct device_node *device) | 254 | static int associativity_to_nid(const unsigned int *associativity) |
250 | { | 255 | { |
251 | int nid = -1; | 256 | int nid = -1; |
252 | const unsigned int *tmp; | ||
253 | 257 | ||
254 | if (min_common_depth == -1) | 258 | if (min_common_depth == -1) |
255 | goto out; | 259 | goto out; |
256 | 260 | ||
257 | tmp = of_get_associativity(device); | 261 | if (associativity[0] >= min_common_depth) |
258 | if (!tmp) | 262 | nid = associativity[min_common_depth]; |
259 | goto out; | ||
260 | |||
261 | if (tmp[0] >= min_common_depth) | ||
262 | nid = tmp[min_common_depth]; | ||
263 | 263 | ||
264 | /* POWER4 LPAR uses 0xffff as invalid node */ | 264 | /* POWER4 LPAR uses 0xffff as invalid node */ |
265 | if (nid == 0xffff || nid >= MAX_NUMNODES) | 265 | if (nid == 0xffff || nid >= MAX_NUMNODES) |
266 | nid = -1; | 266 | nid = -1; |
267 | 267 | ||
268 | if (nid > 0 && tmp[0] >= distance_ref_points_depth) | 268 | if (nid > 0 && associativity[0] >= distance_ref_points_depth) |
269 | initialize_distance_lookup_table(nid, tmp); | 269 | initialize_distance_lookup_table(nid, associativity); |
270 | 270 | ||
271 | out: | 271 | out: |
272 | return nid; | 272 | return nid; |
273 | } | 273 | } |
274 | 274 | ||
275 | /* Returns the nid associated with the given device tree node, | ||
276 | * or -1 if not found. | ||
277 | */ | ||
278 | static int of_node_to_nid_single(struct device_node *device) | ||
279 | { | ||
280 | int nid = -1; | ||
281 | const unsigned int *tmp; | ||
282 | |||
283 | tmp = of_get_associativity(device); | ||
284 | if (tmp) | ||
285 | nid = associativity_to_nid(tmp); | ||
286 | return nid; | ||
287 | } | ||
288 | |||
275 | /* Walk the device tree upwards, looking for an associativity id */ | 289 | /* Walk the device tree upwards, looking for an associativity id */ |
276 | int of_node_to_nid(struct device_node *device) | 290 | int of_node_to_nid(struct device_node *device) |
277 | { | 291 | { |
@@ -1247,4 +1261,275 @@ int hot_add_scn_to_nid(unsigned long scn_addr) | |||
1247 | return nid; | 1261 | return nid; |
1248 | } | 1262 | } |
1249 | 1263 | ||
1264 | static u64 hot_add_drconf_memory_max(void) | ||
1265 | { | ||
1266 | struct device_node *memory = NULL; | ||
1267 | unsigned int drconf_cell_cnt = 0; | ||
1268 | u64 lmb_size = 0; | ||
1269 | const u32 *dm = 0; | ||
1270 | |||
1271 | memory = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory"); | ||
1272 | if (memory) { | ||
1273 | drconf_cell_cnt = of_get_drconf_memory(memory, &dm); | ||
1274 | lmb_size = of_get_lmb_size(memory); | ||
1275 | of_node_put(memory); | ||
1276 | } | ||
1277 | return lmb_size * drconf_cell_cnt; | ||
1278 | } | ||
1279 | |||
1280 | /* | ||
1281 | * memory_hotplug_max - return max address of memory that may be added | ||
1282 | * | ||
1283 | * This is currently only used on systems that support drconfig memory | ||
1284 | * hotplug. | ||
1285 | */ | ||
1286 | u64 memory_hotplug_max(void) | ||
1287 | { | ||
1288 | return max(hot_add_drconf_memory_max(), memblock_end_of_DRAM()); | ||
1289 | } | ||
1250 | #endif /* CONFIG_MEMORY_HOTPLUG */ | 1290 | #endif /* CONFIG_MEMORY_HOTPLUG */ |
1291 | |||
1292 | /* Vrtual Processor Home Node (VPHN) support */ | ||
1293 | #ifdef CONFIG_PPC_SPLPAR | ||
1294 | #define VPHN_NR_CHANGE_CTRS (8) | ||
1295 | static u8 vphn_cpu_change_counts[NR_CPUS][VPHN_NR_CHANGE_CTRS]; | ||
1296 | static cpumask_t cpu_associativity_changes_mask; | ||
1297 | static int vphn_enabled; | ||
1298 | static void set_topology_timer(void); | ||
1299 | |||
1300 | /* | ||
1301 | * Store the current values of the associativity change counters in the | ||
1302 | * hypervisor. | ||
1303 | */ | ||
1304 | static void setup_cpu_associativity_change_counters(void) | ||
1305 | { | ||
1306 | int cpu = 0; | ||
1307 | |||
1308 | for_each_possible_cpu(cpu) { | ||
1309 | int i = 0; | ||
1310 | u8 *counts = vphn_cpu_change_counts[cpu]; | ||
1311 | volatile u8 *hypervisor_counts = lppaca[cpu].vphn_assoc_counts; | ||
1312 | |||
1313 | for (i = 0; i < VPHN_NR_CHANGE_CTRS; i++) { | ||
1314 | counts[i] = hypervisor_counts[i]; | ||
1315 | } | ||
1316 | } | ||
1317 | } | ||
1318 | |||
1319 | /* | ||
1320 | * The hypervisor maintains a set of 8 associativity change counters in | ||
1321 | * the VPA of each cpu that correspond to the associativity levels in the | ||
1322 | * ibm,associativity-reference-points property. When an associativity | ||
1323 | * level changes, the corresponding counter is incremented. | ||
1324 | * | ||
1325 | * Set a bit in cpu_associativity_changes_mask for each cpu whose home | ||
1326 | * node associativity levels have changed. | ||
1327 | * | ||
1328 | * Returns the number of cpus with unhandled associativity changes. | ||
1329 | */ | ||
1330 | static int update_cpu_associativity_changes_mask(void) | ||
1331 | { | ||
1332 | int cpu = 0, nr_cpus = 0; | ||
1333 | cpumask_t *changes = &cpu_associativity_changes_mask; | ||
1334 | |||
1335 | cpumask_clear(changes); | ||
1336 | |||
1337 | for_each_possible_cpu(cpu) { | ||
1338 | int i, changed = 0; | ||
1339 | u8 *counts = vphn_cpu_change_counts[cpu]; | ||
1340 | volatile u8 *hypervisor_counts = lppaca[cpu].vphn_assoc_counts; | ||
1341 | |||
1342 | for (i = 0; i < VPHN_NR_CHANGE_CTRS; i++) { | ||
1343 | if (hypervisor_counts[i] > counts[i]) { | ||
1344 | counts[i] = hypervisor_counts[i]; | ||
1345 | changed = 1; | ||
1346 | } | ||
1347 | } | ||
1348 | if (changed) { | ||
1349 | cpumask_set_cpu(cpu, changes); | ||
1350 | nr_cpus++; | ||
1351 | } | ||
1352 | } | ||
1353 | |||
1354 | return nr_cpus; | ||
1355 | } | ||
1356 | |||
1357 | /* 6 64-bit registers unpacked into 12 32-bit associativity values */ | ||
1358 | #define VPHN_ASSOC_BUFSIZE (6*sizeof(u64)/sizeof(u32)) | ||
1359 | |||
1360 | /* | ||
1361 | * Convert the associativity domain numbers returned from the hypervisor | ||
1362 | * to the sequence they would appear in the ibm,associativity property. | ||
1363 | */ | ||
1364 | static int vphn_unpack_associativity(const long *packed, unsigned int *unpacked) | ||
1365 | { | ||
1366 | int i = 0; | ||
1367 | int nr_assoc_doms = 0; | ||
1368 | const u16 *field = (const u16*) packed; | ||
1369 | |||
1370 | #define VPHN_FIELD_UNUSED (0xffff) | ||
1371 | #define VPHN_FIELD_MSB (0x8000) | ||
1372 | #define VPHN_FIELD_MASK (~VPHN_FIELD_MSB) | ||
1373 | |||
1374 | for (i = 0; i < VPHN_ASSOC_BUFSIZE; i++) { | ||
1375 | if (*field == VPHN_FIELD_UNUSED) { | ||
1376 | /* All significant fields processed, and remaining | ||
1377 | * fields contain the reserved value of all 1's. | ||
1378 | * Just store them. | ||
1379 | */ | ||
1380 | unpacked[i] = *((u32*)field); | ||
1381 | field += 2; | ||
1382 | } | ||
1383 | else if (*field & VPHN_FIELD_MSB) { | ||
1384 | /* Data is in the lower 15 bits of this field */ | ||
1385 | unpacked[i] = *field & VPHN_FIELD_MASK; | ||
1386 | field++; | ||
1387 | nr_assoc_doms++; | ||
1388 | } | ||
1389 | else { | ||
1390 | /* Data is in the lower 15 bits of this field | ||
1391 | * concatenated with the next 16 bit field | ||
1392 | */ | ||
1393 | unpacked[i] = *((u32*)field); | ||
1394 | field += 2; | ||
1395 | nr_assoc_doms++; | ||
1396 | } | ||
1397 | } | ||
1398 | |||
1399 | return nr_assoc_doms; | ||
1400 | } | ||
1401 | |||
1402 | /* | ||
1403 | * Retrieve the new associativity information for a virtual processor's | ||
1404 | * home node. | ||
1405 | */ | ||
1406 | static long hcall_vphn(unsigned long cpu, unsigned int *associativity) | ||
1407 | { | ||
1408 | long rc = 0; | ||
1409 | long retbuf[PLPAR_HCALL9_BUFSIZE] = {0}; | ||
1410 | u64 flags = 1; | ||
1411 | int hwcpu = get_hard_smp_processor_id(cpu); | ||
1412 | |||
1413 | rc = plpar_hcall9(H_HOME_NODE_ASSOCIATIVITY, retbuf, flags, hwcpu); | ||
1414 | vphn_unpack_associativity(retbuf, associativity); | ||
1415 | |||
1416 | return rc; | ||
1417 | } | ||
1418 | |||
1419 | static long vphn_get_associativity(unsigned long cpu, | ||
1420 | unsigned int *associativity) | ||
1421 | { | ||
1422 | long rc = 0; | ||
1423 | |||
1424 | rc = hcall_vphn(cpu, associativity); | ||
1425 | |||
1426 | switch (rc) { | ||
1427 | case H_FUNCTION: | ||
1428 | printk(KERN_INFO | ||
1429 | "VPHN is not supported. Disabling polling...\n"); | ||
1430 | stop_topology_update(); | ||
1431 | break; | ||
1432 | case H_HARDWARE: | ||
1433 | printk(KERN_ERR | ||
1434 | "hcall_vphn() experienced a hardware fault " | ||
1435 | "preventing VPHN. Disabling polling...\n"); | ||
1436 | stop_topology_update(); | ||
1437 | } | ||
1438 | |||
1439 | return rc; | ||
1440 | } | ||
1441 | |||
1442 | /* | ||
1443 | * Update the node maps and sysfs entries for each cpu whose home node | ||
1444 | * has changed. | ||
1445 | */ | ||
1446 | int arch_update_cpu_topology(void) | ||
1447 | { | ||
1448 | int cpu = 0, nid = 0, old_nid = 0; | ||
1449 | unsigned int associativity[VPHN_ASSOC_BUFSIZE] = {0}; | ||
1450 | struct sys_device *sysdev = NULL; | ||
1451 | |||
1452 | for_each_cpu_mask(cpu, cpu_associativity_changes_mask) { | ||
1453 | vphn_get_associativity(cpu, associativity); | ||
1454 | nid = associativity_to_nid(associativity); | ||
1455 | |||
1456 | if (nid < 0 || !node_online(nid)) | ||
1457 | nid = first_online_node; | ||
1458 | |||
1459 | old_nid = numa_cpu_lookup_table[cpu]; | ||
1460 | |||
1461 | /* Disable hotplug while we update the cpu | ||
1462 | * masks and sysfs. | ||
1463 | */ | ||
1464 | get_online_cpus(); | ||
1465 | unregister_cpu_under_node(cpu, old_nid); | ||
1466 | unmap_cpu_from_node(cpu); | ||
1467 | map_cpu_to_node(cpu, nid); | ||
1468 | register_cpu_under_node(cpu, nid); | ||
1469 | put_online_cpus(); | ||
1470 | |||
1471 | sysdev = get_cpu_sysdev(cpu); | ||
1472 | if (sysdev) | ||
1473 | kobject_uevent(&sysdev->kobj, KOBJ_CHANGE); | ||
1474 | } | ||
1475 | |||
1476 | return 1; | ||
1477 | } | ||
1478 | |||
1479 | static void topology_work_fn(struct work_struct *work) | ||
1480 | { | ||
1481 | rebuild_sched_domains(); | ||
1482 | } | ||
1483 | static DECLARE_WORK(topology_work, topology_work_fn); | ||
1484 | |||
1485 | void topology_schedule_update(void) | ||
1486 | { | ||
1487 | schedule_work(&topology_work); | ||
1488 | } | ||
1489 | |||
1490 | static void topology_timer_fn(unsigned long ignored) | ||
1491 | { | ||
1492 | if (!vphn_enabled) | ||
1493 | return; | ||
1494 | if (update_cpu_associativity_changes_mask() > 0) | ||
1495 | topology_schedule_update(); | ||
1496 | set_topology_timer(); | ||
1497 | } | ||
1498 | static struct timer_list topology_timer = | ||
1499 | TIMER_INITIALIZER(topology_timer_fn, 0, 0); | ||
1500 | |||
1501 | static void set_topology_timer(void) | ||
1502 | { | ||
1503 | topology_timer.data = 0; | ||
1504 | topology_timer.expires = jiffies + 60 * HZ; | ||
1505 | add_timer(&topology_timer); | ||
1506 | } | ||
1507 | |||
1508 | /* | ||
1509 | * Start polling for VPHN associativity changes. | ||
1510 | */ | ||
1511 | int start_topology_update(void) | ||
1512 | { | ||
1513 | int rc = 0; | ||
1514 | |||
1515 | if (firmware_has_feature(FW_FEATURE_VPHN)) { | ||
1516 | vphn_enabled = 1; | ||
1517 | setup_cpu_associativity_change_counters(); | ||
1518 | init_timer_deferrable(&topology_timer); | ||
1519 | set_topology_timer(); | ||
1520 | rc = 1; | ||
1521 | } | ||
1522 | |||
1523 | return rc; | ||
1524 | } | ||
1525 | __initcall(start_topology_update); | ||
1526 | |||
1527 | /* | ||
1528 | * Disable polling for VPHN associativity changes. | ||
1529 | */ | ||
1530 | int stop_topology_update(void) | ||
1531 | { | ||
1532 | vphn_enabled = 0; | ||
1533 | return del_timer_sync(&topology_timer); | ||
1534 | } | ||
1535 | #endif /* CONFIG_PPC_SPLPAR */ | ||
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index a87ead0138b4..8dc41c0157fe 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c | |||
@@ -78,7 +78,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm) | |||
78 | 78 | ||
79 | /* pgdir take page or two with 4K pages and a page fraction otherwise */ | 79 | /* pgdir take page or two with 4K pages and a page fraction otherwise */ |
80 | #ifndef CONFIG_PPC_4K_PAGES | 80 | #ifndef CONFIG_PPC_4K_PAGES |
81 | ret = (pgd_t *)kzalloc(1 << PGDIR_ORDER, GFP_KERNEL); | 81 | ret = kzalloc(1 << PGDIR_ORDER, GFP_KERNEL); |
82 | #else | 82 | #else |
83 | ret = (pgd_t *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, | 83 | ret = (pgd_t *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, |
84 | PGDIR_ORDER - PAGE_SHIFT); | 84 | PGDIR_ORDER - PAGE_SHIFT); |
@@ -230,6 +230,7 @@ __ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags, | |||
230 | area = get_vm_area_caller(size, VM_IOREMAP, caller); | 230 | area = get_vm_area_caller(size, VM_IOREMAP, caller); |
231 | if (area == 0) | 231 | if (area == 0) |
232 | return NULL; | 232 | return NULL; |
233 | area->phys_addr = p; | ||
233 | v = (unsigned long) area->addr; | 234 | v = (unsigned long) area->addr; |
234 | } else { | 235 | } else { |
235 | v = (ioremap_bot -= size); | 236 | v = (ioremap_bot -= size); |
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index 21d6dfab7942..88927a05cdc2 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c | |||
@@ -223,6 +223,8 @@ void __iomem * __ioremap_caller(phys_addr_t addr, unsigned long size, | |||
223 | caller); | 223 | caller); |
224 | if (area == NULL) | 224 | if (area == NULL) |
225 | return NULL; | 225 | return NULL; |
226 | |||
227 | area->phys_addr = paligned; | ||
226 | ret = __ioremap_at(paligned, area->addr, size, flags); | 228 | ret = __ioremap_at(paligned, area->addr, size, flags); |
227 | if (!ret) | 229 | if (!ret) |
228 | vunmap(area->addr); | 230 | vunmap(area->addr); |
diff --git a/arch/powerpc/platforms/44x/Makefile b/arch/powerpc/platforms/44x/Makefile index 82ff326e0795..c04d16df8488 100644 --- a/arch/powerpc/platforms/44x/Makefile +++ b/arch/powerpc/platforms/44x/Makefile | |||
@@ -1,4 +1,7 @@ | |||
1 | obj-$(CONFIG_44x) := misc_44x.o idle.o | 1 | obj-$(CONFIG_44x) += misc_44x.o |
2 | ifneq ($(CONFIG_PPC4xx_CPM),y) | ||
3 | obj-$(CONFIG_44x) += idle.o | ||
4 | endif | ||
2 | obj-$(CONFIG_PPC44x_SIMPLE) += ppc44x_simple.o | 5 | obj-$(CONFIG_PPC44x_SIMPLE) += ppc44x_simple.o |
3 | obj-$(CONFIG_EBONY) += ebony.o | 6 | obj-$(CONFIG_EBONY) += ebony.o |
4 | obj-$(CONFIG_SAM440EP) += sam440ep.o | 7 | obj-$(CONFIG_SAM440EP) += sam440ep.o |
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index 956154f32cfe..20576829eca5 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig | |||
@@ -313,13 +313,14 @@ config OF_RTC | |||
313 | source "arch/powerpc/sysdev/bestcomm/Kconfig" | 313 | source "arch/powerpc/sysdev/bestcomm/Kconfig" |
314 | 314 | ||
315 | config MPC8xxx_GPIO | 315 | config MPC8xxx_GPIO |
316 | bool "MPC8xxx GPIO support" | 316 | bool "MPC512x/MPC8xxx GPIO support" |
317 | depends on PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || FSL_SOC_BOOKE || PPC_86xx | 317 | depends on PPC_MPC512x || PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || \ |
318 | FSL_SOC_BOOKE || PPC_86xx | ||
318 | select GENERIC_GPIO | 319 | select GENERIC_GPIO |
319 | select ARCH_REQUIRE_GPIOLIB | 320 | select ARCH_REQUIRE_GPIOLIB |
320 | help | 321 | help |
321 | Say Y here if you're going to use hardware that connects to the | 322 | Say Y here if you're going to use hardware that connects to the |
322 | MPC831x/834x/837x/8572/8610 GPIOs. | 323 | MPC512x/831x/834x/837x/8572/8610 GPIOs. |
323 | 324 | ||
324 | config SIMPLE_GPIO | 325 | config SIMPLE_GPIO |
325 | bool "Support for simple, memory-mapped GPIO controllers" | 326 | bool "Support for simple, memory-mapped GPIO controllers" |
diff --git a/arch/powerpc/platforms/cell/beat_iommu.c b/arch/powerpc/platforms/cell/beat_iommu.c index beec405eb6f8..3ce685568935 100644 --- a/arch/powerpc/platforms/cell/beat_iommu.c +++ b/arch/powerpc/platforms/cell/beat_iommu.c | |||
@@ -76,7 +76,7 @@ static void __init celleb_init_direct_mapping(void) | |||
76 | 76 | ||
77 | static void celleb_dma_dev_setup(struct device *dev) | 77 | static void celleb_dma_dev_setup(struct device *dev) |
78 | { | 78 | { |
79 | dev->archdata.dma_ops = get_pci_dma_ops(); | 79 | set_dma_ops(dev, &dma_direct_ops); |
80 | set_dma_offset(dev, celleb_dma_direct_offset); | 80 | set_dma_offset(dev, celleb_dma_direct_offset); |
81 | } | 81 | } |
82 | 82 | ||
@@ -106,7 +106,6 @@ static struct notifier_block celleb_of_bus_notifier = { | |||
106 | static int __init celleb_init_iommu(void) | 106 | static int __init celleb_init_iommu(void) |
107 | { | 107 | { |
108 | celleb_init_direct_mapping(); | 108 | celleb_init_direct_mapping(); |
109 | set_pci_dma_ops(&dma_direct_ops); | ||
110 | ppc_md.pci_dma_dev_setup = celleb_pci_dma_dev_setup; | 109 | ppc_md.pci_dma_dev_setup = celleb_pci_dma_dev_setup; |
111 | bus_register_notifier(&platform_bus_type, &celleb_of_bus_notifier); | 110 | bus_register_notifier(&platform_bus_type, &celleb_of_bus_notifier); |
112 | 111 | ||
diff --git a/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c b/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c index a101abf17504..3b894f585280 100644 --- a/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c +++ b/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c | |||
@@ -36,10 +36,9 @@ static int spu_alloc_lscsa_std(struct spu_state *csa) | |||
36 | struct spu_lscsa *lscsa; | 36 | struct spu_lscsa *lscsa; |
37 | unsigned char *p; | 37 | unsigned char *p; |
38 | 38 | ||
39 | lscsa = vmalloc(sizeof(struct spu_lscsa)); | 39 | lscsa = vzalloc(sizeof(struct spu_lscsa)); |
40 | if (!lscsa) | 40 | if (!lscsa) |
41 | return -ENOMEM; | 41 | return -ENOMEM; |
42 | memset(lscsa, 0, sizeof(struct spu_lscsa)); | ||
43 | csa->lscsa = lscsa; | 42 | csa->lscsa = lscsa; |
44 | 43 | ||
45 | /* Set LS pages reserved to allow for user-space mapping. */ | 44 | /* Set LS pages reserved to allow for user-space mapping. */ |
diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c index 054dfe5b8e77..f803f4b8ab6f 100644 --- a/arch/powerpc/platforms/chrp/time.c +++ b/arch/powerpc/platforms/chrp/time.c | |||
@@ -29,6 +29,10 @@ | |||
29 | 29 | ||
30 | extern spinlock_t rtc_lock; | 30 | extern spinlock_t rtc_lock; |
31 | 31 | ||
32 | #define NVRAM_AS0 0x74 | ||
33 | #define NVRAM_AS1 0x75 | ||
34 | #define NVRAM_DATA 0x77 | ||
35 | |||
32 | static int nvram_as1 = NVRAM_AS1; | 36 | static int nvram_as1 = NVRAM_AS1; |
33 | static int nvram_as0 = NVRAM_AS0; | 37 | static int nvram_as0 = NVRAM_AS0; |
34 | static int nvram_data = NVRAM_DATA; | 38 | static int nvram_data = NVRAM_DATA; |
diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index 42d0a886de05..b5e026bdca21 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c | |||
@@ -1045,71 +1045,9 @@ static const struct file_operations mf_side_proc_fops = { | |||
1045 | .write = mf_side_proc_write, | 1045 | .write = mf_side_proc_write, |
1046 | }; | 1046 | }; |
1047 | 1047 | ||
1048 | #if 0 | ||
1049 | static void mf_getSrcHistory(char *buffer, int size) | ||
1050 | { | ||
1051 | struct IplTypeReturnStuff return_stuff; | ||
1052 | struct pending_event *ev = new_pending_event(); | ||
1053 | int rc = 0; | ||
1054 | char *pages[4]; | ||
1055 | |||
1056 | pages[0] = kmalloc(4096, GFP_ATOMIC); | ||
1057 | pages[1] = kmalloc(4096, GFP_ATOMIC); | ||
1058 | pages[2] = kmalloc(4096, GFP_ATOMIC); | ||
1059 | pages[3] = kmalloc(4096, GFP_ATOMIC); | ||
1060 | if ((ev == NULL) || (pages[0] == NULL) || (pages[1] == NULL) | ||
1061 | || (pages[2] == NULL) || (pages[3] == NULL)) | ||
1062 | return -ENOMEM; | ||
1063 | |||
1064 | return_stuff.xType = 0; | ||
1065 | return_stuff.xRc = 0; | ||
1066 | return_stuff.xDone = 0; | ||
1067 | ev->event.hp_lp_event.xSubtype = 6; | ||
1068 | ev->event.hp_lp_event.x.xSubtypeData = | ||
1069 | subtype_data('M', 'F', 'V', 'I'); | ||
1070 | ev->event.data.vsp_cmd.xEvent = &return_stuff; | ||
1071 | ev->event.data.vsp_cmd.cmd = 4; | ||
1072 | ev->event.data.vsp_cmd.lp_index = HvLpConfig_getLpIndex(); | ||
1073 | ev->event.data.vsp_cmd.result_code = 0xFF; | ||
1074 | ev->event.data.vsp_cmd.reserved = 0; | ||
1075 | ev->event.data.vsp_cmd.sub_data.page[0] = iseries_hv_addr(pages[0]); | ||
1076 | ev->event.data.vsp_cmd.sub_data.page[1] = iseries_hv_addr(pages[1]); | ||
1077 | ev->event.data.vsp_cmd.sub_data.page[2] = iseries_hv_addr(pages[2]); | ||
1078 | ev->event.data.vsp_cmd.sub_data.page[3] = iseries_hv_addr(pages[3]); | ||
1079 | mb(); | ||
1080 | if (signal_event(ev) != 0) | ||
1081 | return; | ||
1082 | |||
1083 | while (return_stuff.xDone != 1) | ||
1084 | udelay(10); | ||
1085 | if (return_stuff.xRc == 0) | ||
1086 | memcpy(buffer, pages[0], size); | ||
1087 | kfree(pages[0]); | ||
1088 | kfree(pages[1]); | ||
1089 | kfree(pages[2]); | ||
1090 | kfree(pages[3]); | ||
1091 | } | ||
1092 | #endif | ||
1093 | |||
1094 | static int mf_src_proc_show(struct seq_file *m, void *v) | 1048 | static int mf_src_proc_show(struct seq_file *m, void *v) |
1095 | { | 1049 | { |
1096 | #if 0 | ||
1097 | int len; | ||
1098 | |||
1099 | mf_getSrcHistory(page, count); | ||
1100 | len = count; | ||
1101 | len -= off; | ||
1102 | if (len < count) { | ||
1103 | *eof = 1; | ||
1104 | if (len <= 0) | ||
1105 | return 0; | ||
1106 | } else | ||
1107 | len = count; | ||
1108 | *start = page + off; | ||
1109 | return len; | ||
1110 | #else | ||
1111 | return 0; | 1050 | return 0; |
1112 | #endif | ||
1113 | } | 1051 | } |
1114 | 1052 | ||
1115 | static int mf_src_proc_open(struct inode *inode, struct file *file) | 1053 | static int mf_src_proc_open(struct inode *inode, struct file *file) |
diff --git a/arch/powerpc/platforms/pasemi/iommu.c b/arch/powerpc/platforms/pasemi/iommu.c index 1f9fb2c57761..14943ef01918 100644 --- a/arch/powerpc/platforms/pasemi/iommu.c +++ b/arch/powerpc/platforms/pasemi/iommu.c | |||
@@ -156,20 +156,12 @@ static void iommu_table_iobmap_setup(void) | |||
156 | 156 | ||
157 | static void pci_dma_bus_setup_pasemi(struct pci_bus *bus) | 157 | static void pci_dma_bus_setup_pasemi(struct pci_bus *bus) |
158 | { | 158 | { |
159 | struct device_node *dn; | ||
160 | |||
161 | pr_debug("pci_dma_bus_setup, bus %p, bus->self %p\n", bus, bus->self); | 159 | pr_debug("pci_dma_bus_setup, bus %p, bus->self %p\n", bus, bus->self); |
162 | 160 | ||
163 | if (!iommu_table_iobmap_inited) { | 161 | if (!iommu_table_iobmap_inited) { |
164 | iommu_table_iobmap_inited = 1; | 162 | iommu_table_iobmap_inited = 1; |
165 | iommu_table_iobmap_setup(); | 163 | iommu_table_iobmap_setup(); |
166 | } | 164 | } |
167 | |||
168 | dn = pci_bus_to_OF_node(bus); | ||
169 | |||
170 | if (dn) | ||
171 | PCI_DN(dn)->iommu_table = &iommu_table_iobmap; | ||
172 | |||
173 | } | 165 | } |
174 | 166 | ||
175 | 167 | ||
@@ -192,9 +184,6 @@ static void pci_dma_dev_setup_pasemi(struct pci_dev *dev) | |||
192 | set_iommu_table_base(&dev->dev, &iommu_table_iobmap); | 184 | set_iommu_table_base(&dev->dev, &iommu_table_iobmap); |
193 | } | 185 | } |
194 | 186 | ||
195 | static void pci_dma_bus_setup_null(struct pci_bus *b) { } | ||
196 | static void pci_dma_dev_setup_null(struct pci_dev *d) { } | ||
197 | |||
198 | int __init iob_init(struct device_node *dn) | 187 | int __init iob_init(struct device_node *dn) |
199 | { | 188 | { |
200 | unsigned long tmp; | 189 | unsigned long tmp; |
@@ -251,14 +240,8 @@ void __init iommu_init_early_pasemi(void) | |||
251 | iommu_off = of_chosen && | 240 | iommu_off = of_chosen && |
252 | of_get_property(of_chosen, "linux,iommu-off", NULL); | 241 | of_get_property(of_chosen, "linux,iommu-off", NULL); |
253 | #endif | 242 | #endif |
254 | if (iommu_off) { | 243 | if (iommu_off) |
255 | /* Direct I/O, IOMMU off */ | ||
256 | ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_null; | ||
257 | ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_null; | ||
258 | set_pci_dma_ops(&dma_direct_ops); | ||
259 | |||
260 | return; | 244 | return; |
261 | } | ||
262 | 245 | ||
263 | iob_init(NULL); | 246 | iob_init(NULL); |
264 | 247 | ||
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 9deb274841f1..d5aceb7fb125 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c | |||
@@ -506,6 +506,15 @@ static int __init pmac_declare_of_platform_devices(void) | |||
506 | of_platform_device_create(np, "smu", NULL); | 506 | of_platform_device_create(np, "smu", NULL); |
507 | of_node_put(np); | 507 | of_node_put(np); |
508 | } | 508 | } |
509 | np = of_find_node_by_type(NULL, "fcu"); | ||
510 | if (np == NULL) { | ||
511 | /* Some machines have strangely broken device-tree */ | ||
512 | np = of_find_node_by_path("/u3@0,f8000000/i2c@f8001000/fan@15e"); | ||
513 | } | ||
514 | if (np) { | ||
515 | of_platform_device_create(np, "temperature", NULL); | ||
516 | of_node_put(np); | ||
517 | } | ||
509 | 518 | ||
510 | return 0; | 519 | return 0; |
511 | } | 520 | } |
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index 3139814f6439..5d1b743dbe7e 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig | |||
@@ -33,6 +33,16 @@ config PSERIES_MSI | |||
33 | depends on PCI_MSI && EEH | 33 | depends on PCI_MSI && EEH |
34 | default y | 34 | default y |
35 | 35 | ||
36 | config PSERIES_ENERGY | ||
37 | tristate "pSeries energy management capabilities driver" | ||
38 | depends on PPC_PSERIES | ||
39 | default y | ||
40 | help | ||
41 | Provides interface to platform energy management capabilities | ||
42 | on supported PSERIES platforms. | ||
43 | Provides: /sys/devices/system/cpu/pseries_(de)activation_hint_list | ||
44 | and /sys/devices/system/cpu/cpuN/pseries_(de)activation_hint | ||
45 | |||
36 | config SCANLOG | 46 | config SCANLOG |
37 | tristate "Scanlog dump interface" | 47 | tristate "Scanlog dump interface" |
38 | depends on RTAS_PROC && PPC_PSERIES | 48 | depends on RTAS_PROC && PPC_PSERIES |
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 59eb8bdaa79d..fc5237810ece 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile | |||
@@ -11,6 +11,7 @@ obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o eeh_sysfs.o | |||
11 | obj-$(CONFIG_KEXEC) += kexec.o | 11 | obj-$(CONFIG_KEXEC) += kexec.o |
12 | obj-$(CONFIG_PCI) += pci.o pci_dlpar.o | 12 | obj-$(CONFIG_PCI) += pci.o pci_dlpar.o |
13 | obj-$(CONFIG_PSERIES_MSI) += msi.o | 13 | obj-$(CONFIG_PSERIES_MSI) += msi.o |
14 | obj-$(CONFIG_PSERIES_ENERGY) += pseries_energy.o | ||
14 | 15 | ||
15 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o | 16 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o |
16 | obj-$(CONFIG_MEMORY_HOTPLUG) += hotplug-memory.o | 17 | obj-$(CONFIG_MEMORY_HOTPLUG) += hotplug-memory.o |
diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c index 0a14d8cd314f..0b0eff0cce35 100644 --- a/arch/powerpc/platforms/pseries/firmware.c +++ b/arch/powerpc/platforms/pseries/firmware.c | |||
@@ -55,6 +55,7 @@ firmware_features_table[FIRMWARE_MAX_FEATURES] = { | |||
55 | {FW_FEATURE_XDABR, "hcall-xdabr"}, | 55 | {FW_FEATURE_XDABR, "hcall-xdabr"}, |
56 | {FW_FEATURE_MULTITCE, "hcall-multi-tce"}, | 56 | {FW_FEATURE_MULTITCE, "hcall-multi-tce"}, |
57 | {FW_FEATURE_SPLPAR, "hcall-splpar"}, | 57 | {FW_FEATURE_SPLPAR, "hcall-splpar"}, |
58 | {FW_FEATURE_VPHN, "hcall-vphn"}, | ||
58 | }; | 59 | }; |
59 | 60 | ||
60 | /* Build up the firmware features bitmask using the contents of | 61 | /* Build up the firmware features bitmask using the contents of |
diff --git a/arch/powerpc/platforms/pseries/hvCall.S b/arch/powerpc/platforms/pseries/hvCall.S index 48d20573e4de..fd05fdee576a 100644 --- a/arch/powerpc/platforms/pseries/hvCall.S +++ b/arch/powerpc/platforms/pseries/hvCall.S | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <asm/processor.h> | 11 | #include <asm/processor.h> |
12 | #include <asm/ppc_asm.h> | 12 | #include <asm/ppc_asm.h> |
13 | #include <asm/asm-offsets.h> | 13 | #include <asm/asm-offsets.h> |
14 | #include <asm/ptrace.h> | ||
14 | 15 | ||
15 | #define STK_PARM(i) (48 + ((i)-3)*8) | 16 | #define STK_PARM(i) (48 + ((i)-3)*8) |
16 | 17 | ||
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index a77bcaed80af..edea60b7ee90 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c | |||
@@ -140,7 +140,7 @@ static int tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum, | |||
140 | return ret; | 140 | return ret; |
141 | } | 141 | } |
142 | 142 | ||
143 | static DEFINE_PER_CPU(u64 *, tce_page) = NULL; | 143 | static DEFINE_PER_CPU(u64 *, tce_page); |
144 | 144 | ||
145 | static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, | 145 | static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, |
146 | long npages, unsigned long uaddr, | 146 | long npages, unsigned long uaddr, |
@@ -323,14 +323,13 @@ static void iommu_table_setparms(struct pci_controller *phb, | |||
323 | static void iommu_table_setparms_lpar(struct pci_controller *phb, | 323 | static void iommu_table_setparms_lpar(struct pci_controller *phb, |
324 | struct device_node *dn, | 324 | struct device_node *dn, |
325 | struct iommu_table *tbl, | 325 | struct iommu_table *tbl, |
326 | const void *dma_window, | 326 | const void *dma_window) |
327 | int bussubno) | ||
328 | { | 327 | { |
329 | unsigned long offset, size; | 328 | unsigned long offset, size; |
330 | 329 | ||
331 | tbl->it_busno = bussubno; | ||
332 | of_parse_dma_window(dn, dma_window, &tbl->it_index, &offset, &size); | 330 | of_parse_dma_window(dn, dma_window, &tbl->it_index, &offset, &size); |
333 | 331 | ||
332 | tbl->it_busno = phb->bus->number; | ||
334 | tbl->it_base = 0; | 333 | tbl->it_base = 0; |
335 | tbl->it_blocksize = 16; | 334 | tbl->it_blocksize = 16; |
336 | tbl->it_type = TCE_PCI; | 335 | tbl->it_type = TCE_PCI; |
@@ -450,14 +449,10 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus) | |||
450 | if (!ppci->iommu_table) { | 449 | if (!ppci->iommu_table) { |
451 | tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL, | 450 | tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL, |
452 | ppci->phb->node); | 451 | ppci->phb->node); |
453 | iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window, | 452 | iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window); |
454 | bus->number); | ||
455 | ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node); | 453 | ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node); |
456 | pr_debug(" created table: %p\n", ppci->iommu_table); | 454 | pr_debug(" created table: %p\n", ppci->iommu_table); |
457 | } | 455 | } |
458 | |||
459 | if (pdn != dn) | ||
460 | PCI_DN(dn)->iommu_table = ppci->iommu_table; | ||
461 | } | 456 | } |
462 | 457 | ||
463 | 458 | ||
@@ -533,21 +528,11 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) | |||
533 | } | 528 | } |
534 | pr_debug(" parent is %s\n", pdn->full_name); | 529 | pr_debug(" parent is %s\n", pdn->full_name); |
535 | 530 | ||
536 | /* Check for parent == NULL so we don't try to setup the empty EADS | ||
537 | * slots on POWER4 machines. | ||
538 | */ | ||
539 | if (dma_window == NULL || pdn->parent == NULL) { | ||
540 | pr_debug(" no dma window for device, linking to parent\n"); | ||
541 | set_iommu_table_base(&dev->dev, PCI_DN(pdn)->iommu_table); | ||
542 | return; | ||
543 | } | ||
544 | |||
545 | pci = PCI_DN(pdn); | 531 | pci = PCI_DN(pdn); |
546 | if (!pci->iommu_table) { | 532 | if (!pci->iommu_table) { |
547 | tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL, | 533 | tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL, |
548 | pci->phb->node); | 534 | pci->phb->node); |
549 | iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window, | 535 | iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window); |
550 | pci->phb->bus->number); | ||
551 | pci->iommu_table = iommu_init_table(tbl, pci->phb->node); | 536 | pci->iommu_table = iommu_init_table(tbl, pci->phb->node); |
552 | pr_debug(" created table: %p\n", pci->iommu_table); | 537 | pr_debug(" created table: %p\n", pci->iommu_table); |
553 | } else { | 538 | } else { |
@@ -571,8 +556,7 @@ static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long acti | |||
571 | 556 | ||
572 | switch (action) { | 557 | switch (action) { |
573 | case PSERIES_RECONFIG_REMOVE: | 558 | case PSERIES_RECONFIG_REMOVE: |
574 | if (pci && pci->iommu_table && | 559 | if (pci && pci->iommu_table) |
575 | of_get_property(np, "ibm,dma-window", NULL)) | ||
576 | iommu_free_table(pci->iommu_table, np->full_name); | 560 | iommu_free_table(pci->iommu_table, np->full_name); |
577 | break; | 561 | break; |
578 | default: | 562 | default: |
@@ -589,13 +573,8 @@ static struct notifier_block iommu_reconfig_nb = { | |||
589 | /* These are called very early. */ | 573 | /* These are called very early. */ |
590 | void iommu_init_early_pSeries(void) | 574 | void iommu_init_early_pSeries(void) |
591 | { | 575 | { |
592 | if (of_chosen && of_get_property(of_chosen, "linux,iommu-off", NULL)) { | 576 | if (of_chosen && of_get_property(of_chosen, "linux,iommu-off", NULL)) |
593 | /* Direct I/O, IOMMU off */ | ||
594 | ppc_md.pci_dma_dev_setup = NULL; | ||
595 | ppc_md.pci_dma_bus_setup = NULL; | ||
596 | set_pci_dma_ops(&dma_direct_ops); | ||
597 | return; | 577 | return; |
598 | } | ||
599 | 578 | ||
600 | if (firmware_has_feature(FW_FEATURE_LPAR)) { | 579 | if (firmware_has_feature(FW_FEATURE_LPAR)) { |
601 | if (firmware_has_feature(FW_FEATURE_MULTITCE)) { | 580 | if (firmware_has_feature(FW_FEATURE_MULTITCE)) { |
@@ -622,3 +601,17 @@ void iommu_init_early_pSeries(void) | |||
622 | set_pci_dma_ops(&dma_iommu_ops); | 601 | set_pci_dma_ops(&dma_iommu_ops); |
623 | } | 602 | } |
624 | 603 | ||
604 | static int __init disable_multitce(char *str) | ||
605 | { | ||
606 | if (strcmp(str, "off") == 0 && | ||
607 | firmware_has_feature(FW_FEATURE_LPAR) && | ||
608 | firmware_has_feature(FW_FEATURE_MULTITCE)) { | ||
609 | printk(KERN_INFO "Disabling MULTITCE firmware feature\n"); | ||
610 | ppc_md.tce_build = tce_build_pSeriesLP; | ||
611 | ppc_md.tce_free = tce_free_pSeriesLP; | ||
612 | powerpc_firmware_features &= ~FW_FEATURE_MULTITCE; | ||
613 | } | ||
614 | return 1; | ||
615 | } | ||
616 | |||
617 | __setup("multitce=", disable_multitce); | ||
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index f129040d974c..5d3ea9f60dd7 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c | |||
@@ -627,6 +627,18 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local) | |||
627 | spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags); | 627 | spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags); |
628 | } | 628 | } |
629 | 629 | ||
630 | static int __init disable_bulk_remove(char *str) | ||
631 | { | ||
632 | if (strcmp(str, "off") == 0 && | ||
633 | firmware_has_feature(FW_FEATURE_BULK_REMOVE)) { | ||
634 | printk(KERN_INFO "Disabling BULK_REMOVE firmware feature"); | ||
635 | powerpc_firmware_features &= ~FW_FEATURE_BULK_REMOVE; | ||
636 | } | ||
637 | return 1; | ||
638 | } | ||
639 | |||
640 | __setup("bulk_remove=", disable_bulk_remove); | ||
641 | |||
630 | void __init hpte_init_lpar(void) | 642 | void __init hpte_init_lpar(void) |
631 | { | 643 | { |
632 | ppc_md.hpte_invalidate = pSeries_lpar_hpte_invalidate; | 644 | ppc_md.hpte_invalidate = pSeries_lpar_hpte_invalidate; |
diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c index bc3c7f2abd79..7e828ba29bc3 100644 --- a/arch/powerpc/platforms/pseries/nvram.c +++ b/arch/powerpc/platforms/pseries/nvram.c | |||
@@ -22,11 +22,25 @@ | |||
22 | #include <asm/prom.h> | 22 | #include <asm/prom.h> |
23 | #include <asm/machdep.h> | 23 | #include <asm/machdep.h> |
24 | 24 | ||
25 | /* Max bytes to read/write in one go */ | ||
26 | #define NVRW_CNT 0x20 | ||
27 | |||
25 | static unsigned int nvram_size; | 28 | static unsigned int nvram_size; |
26 | static int nvram_fetch, nvram_store; | 29 | static int nvram_fetch, nvram_store; |
27 | static char nvram_buf[NVRW_CNT]; /* assume this is in the first 4GB */ | 30 | static char nvram_buf[NVRW_CNT]; /* assume this is in the first 4GB */ |
28 | static DEFINE_SPINLOCK(nvram_lock); | 31 | static DEFINE_SPINLOCK(nvram_lock); |
29 | 32 | ||
33 | static long nvram_error_log_index = -1; | ||
34 | static long nvram_error_log_size = 0; | ||
35 | |||
36 | struct err_log_info { | ||
37 | int error_type; | ||
38 | unsigned int seq_num; | ||
39 | }; | ||
40 | #define NVRAM_MAX_REQ 2079 | ||
41 | #define NVRAM_MIN_REQ 1055 | ||
42 | |||
43 | #define NVRAM_LOG_PART_NAME "ibm,rtas-log" | ||
30 | 44 | ||
31 | static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index) | 45 | static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index) |
32 | { | 46 | { |
@@ -119,6 +133,197 @@ static ssize_t pSeries_nvram_get_size(void) | |||
119 | return nvram_size ? nvram_size : -ENODEV; | 133 | return nvram_size ? nvram_size : -ENODEV; |
120 | } | 134 | } |
121 | 135 | ||
136 | |||
137 | /* nvram_write_error_log | ||
138 | * | ||
139 | * We need to buffer the error logs into nvram to ensure that we have | ||
140 | * the failure information to decode. If we have a severe error there | ||
141 | * is no way to guarantee that the OS or the machine is in a state to | ||
142 | * get back to user land and write the error to disk. For example if | ||
143 | * the SCSI device driver causes a Machine Check by writing to a bad | ||
144 | * IO address, there is no way of guaranteeing that the device driver | ||
145 | * is in any state that is would also be able to write the error data | ||
146 | * captured to disk, thus we buffer it in NVRAM for analysis on the | ||
147 | * next boot. | ||
148 | * | ||
149 | * In NVRAM the partition containing the error log buffer will looks like: | ||
150 | * Header (in bytes): | ||
151 | * +-----------+----------+--------+------------+------------------+ | ||
152 | * | signature | checksum | length | name | data | | ||
153 | * |0 |1 |2 3|4 15|16 length-1| | ||
154 | * +-----------+----------+--------+------------+------------------+ | ||
155 | * | ||
156 | * The 'data' section would look like (in bytes): | ||
157 | * +--------------+------------+-----------------------------------+ | ||
158 | * | event_logged | sequence # | error log | | ||
159 | * |0 3|4 7|8 nvram_error_log_size-1| | ||
160 | * +--------------+------------+-----------------------------------+ | ||
161 | * | ||
162 | * event_logged: 0 if event has not been logged to syslog, 1 if it has | ||
163 | * sequence #: The unique sequence # for each event. (until it wraps) | ||
164 | * error log: The error log from event_scan | ||
165 | */ | ||
166 | int nvram_write_error_log(char * buff, int length, | ||
167 | unsigned int err_type, unsigned int error_log_cnt) | ||
168 | { | ||
169 | int rc; | ||
170 | loff_t tmp_index; | ||
171 | struct err_log_info info; | ||
172 | |||
173 | if (nvram_error_log_index == -1) { | ||
174 | return -ESPIPE; | ||
175 | } | ||
176 | |||
177 | if (length > nvram_error_log_size) { | ||
178 | length = nvram_error_log_size; | ||
179 | } | ||
180 | |||
181 | info.error_type = err_type; | ||
182 | info.seq_num = error_log_cnt; | ||
183 | |||
184 | tmp_index = nvram_error_log_index; | ||
185 | |||
186 | rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info), &tmp_index); | ||
187 | if (rc <= 0) { | ||
188 | printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc); | ||
189 | return rc; | ||
190 | } | ||
191 | |||
192 | rc = ppc_md.nvram_write(buff, length, &tmp_index); | ||
193 | if (rc <= 0) { | ||
194 | printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc); | ||
195 | return rc; | ||
196 | } | ||
197 | |||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | /* nvram_read_error_log | ||
202 | * | ||
203 | * Reads nvram for error log for at most 'length' | ||
204 | */ | ||
205 | int nvram_read_error_log(char * buff, int length, | ||
206 | unsigned int * err_type, unsigned int * error_log_cnt) | ||
207 | { | ||
208 | int rc; | ||
209 | loff_t tmp_index; | ||
210 | struct err_log_info info; | ||
211 | |||
212 | if (nvram_error_log_index == -1) | ||
213 | return -1; | ||
214 | |||
215 | if (length > nvram_error_log_size) | ||
216 | length = nvram_error_log_size; | ||
217 | |||
218 | tmp_index = nvram_error_log_index; | ||
219 | |||
220 | rc = ppc_md.nvram_read((char *)&info, sizeof(struct err_log_info), &tmp_index); | ||
221 | if (rc <= 0) { | ||
222 | printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc); | ||
223 | return rc; | ||
224 | } | ||
225 | |||
226 | rc = ppc_md.nvram_read(buff, length, &tmp_index); | ||
227 | if (rc <= 0) { | ||
228 | printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc); | ||
229 | return rc; | ||
230 | } | ||
231 | |||
232 | *error_log_cnt = info.seq_num; | ||
233 | *err_type = info.error_type; | ||
234 | |||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | /* This doesn't actually zero anything, but it sets the event_logged | ||
239 | * word to tell that this event is safely in syslog. | ||
240 | */ | ||
241 | int nvram_clear_error_log(void) | ||
242 | { | ||
243 | loff_t tmp_index; | ||
244 | int clear_word = ERR_FLAG_ALREADY_LOGGED; | ||
245 | int rc; | ||
246 | |||
247 | if (nvram_error_log_index == -1) | ||
248 | return -1; | ||
249 | |||
250 | tmp_index = nvram_error_log_index; | ||
251 | |||
252 | rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index); | ||
253 | if (rc <= 0) { | ||
254 | printk(KERN_ERR "nvram_clear_error_log: Failed nvram_write (%d)\n", rc); | ||
255 | return rc; | ||
256 | } | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | /* pseries_nvram_init_log_partition | ||
262 | * | ||
263 | * This will setup the partition we need for buffering the | ||
264 | * error logs and cleanup partitions if needed. | ||
265 | * | ||
266 | * The general strategy is the following: | ||
267 | * 1.) If there is log partition large enough then use it. | ||
268 | * 2.) If there is none large enough, search | ||
269 | * for a free partition that is large enough. | ||
270 | * 3.) If there is not a free partition large enough remove | ||
271 | * _all_ OS partitions and consolidate the space. | ||
272 | * 4.) Will first try getting a chunk that will satisfy the maximum | ||
273 | * error log size (NVRAM_MAX_REQ). | ||
274 | * 5.) If the max chunk cannot be allocated then try finding a chunk | ||
275 | * that will satisfy the minum needed (NVRAM_MIN_REQ). | ||
276 | */ | ||
277 | static int __init pseries_nvram_init_log_partition(void) | ||
278 | { | ||
279 | loff_t p; | ||
280 | int size; | ||
281 | |||
282 | /* Scan nvram for partitions */ | ||
283 | nvram_scan_partitions(); | ||
284 | |||
285 | /* Lookg for ours */ | ||
286 | p = nvram_find_partition(NVRAM_LOG_PART_NAME, NVRAM_SIG_OS, &size); | ||
287 | |||
288 | /* Found one but too small, remove it */ | ||
289 | if (p && size < NVRAM_MIN_REQ) { | ||
290 | pr_info("nvram: Found too small "NVRAM_LOG_PART_NAME" partition" | ||
291 | ",removing it..."); | ||
292 | nvram_remove_partition(NVRAM_LOG_PART_NAME, NVRAM_SIG_OS); | ||
293 | p = 0; | ||
294 | } | ||
295 | |||
296 | /* Create one if we didn't find */ | ||
297 | if (!p) { | ||
298 | p = nvram_create_partition(NVRAM_LOG_PART_NAME, NVRAM_SIG_OS, | ||
299 | NVRAM_MAX_REQ, NVRAM_MIN_REQ); | ||
300 | /* No room for it, try to get rid of any OS partition | ||
301 | * and try again | ||
302 | */ | ||
303 | if (p == -ENOSPC) { | ||
304 | pr_info("nvram: No room to create "NVRAM_LOG_PART_NAME | ||
305 | " partition, deleting all OS partitions..."); | ||
306 | nvram_remove_partition(NULL, NVRAM_SIG_OS); | ||
307 | p = nvram_create_partition(NVRAM_LOG_PART_NAME, | ||
308 | NVRAM_SIG_OS, NVRAM_MAX_REQ, | ||
309 | NVRAM_MIN_REQ); | ||
310 | } | ||
311 | } | ||
312 | |||
313 | if (p <= 0) { | ||
314 | pr_err("nvram: Failed to find or create "NVRAM_LOG_PART_NAME | ||
315 | " partition, err %d\n", (int)p); | ||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | nvram_error_log_index = p; | ||
320 | nvram_error_log_size = nvram_get_partition_size(p) - | ||
321 | sizeof(struct err_log_info); | ||
322 | |||
323 | return 0; | ||
324 | } | ||
325 | machine_arch_initcall(pseries, pseries_nvram_init_log_partition); | ||
326 | |||
122 | int __init pSeries_nvram_init(void) | 327 | int __init pSeries_nvram_init(void) |
123 | { | 328 | { |
124 | struct device_node *nvram; | 329 | struct device_node *nvram; |
diff --git a/arch/powerpc/platforms/pseries/pseries_energy.c b/arch/powerpc/platforms/pseries/pseries_energy.c new file mode 100644 index 000000000000..c8b3c69fe891 --- /dev/null +++ b/arch/powerpc/platforms/pseries/pseries_energy.c | |||
@@ -0,0 +1,326 @@ | |||
1 | /* | ||
2 | * POWER platform energy management driver | ||
3 | * Copyright (C) 2010 IBM Corporation | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License | ||
7 | * version 2 as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This pseries platform device driver provides access to | ||
10 | * platform energy management capabilities. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/types.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/seq_file.h> | ||
18 | #include <linux/sysdev.h> | ||
19 | #include <linux/cpu.h> | ||
20 | #include <linux/of.h> | ||
21 | #include <asm/cputhreads.h> | ||
22 | #include <asm/page.h> | ||
23 | #include <asm/hvcall.h> | ||
24 | |||
25 | |||
26 | #define MODULE_VERS "1.0" | ||
27 | #define MODULE_NAME "pseries_energy" | ||
28 | |||
29 | /* Driver flags */ | ||
30 | |||
31 | static int sysfs_entries; | ||
32 | |||
33 | /* Helper routines */ | ||
34 | |||
35 | /* | ||
36 | * Routine to detect firmware support for hcall | ||
37 | * return 1 if H_BEST_ENERGY is supported | ||
38 | * else return 0 | ||
39 | */ | ||
40 | |||
41 | static int check_for_h_best_energy(void) | ||
42 | { | ||
43 | struct device_node *rtas = NULL; | ||
44 | const char *hypertas, *s; | ||
45 | int length; | ||
46 | int rc = 0; | ||
47 | |||
48 | rtas = of_find_node_by_path("/rtas"); | ||
49 | if (!rtas) | ||
50 | return 0; | ||
51 | |||
52 | hypertas = of_get_property(rtas, "ibm,hypertas-functions", &length); | ||
53 | if (!hypertas) { | ||
54 | of_node_put(rtas); | ||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | /* hypertas will have list of strings with hcall names */ | ||
59 | for (s = hypertas; s < hypertas + length; s += strlen(s) + 1) { | ||
60 | if (!strncmp("hcall-best-energy-1", s, 19)) { | ||
61 | rc = 1; /* Found the string */ | ||
62 | break; | ||
63 | } | ||
64 | } | ||
65 | of_node_put(rtas); | ||
66 | return rc; | ||
67 | } | ||
68 | |||
69 | /* Helper Routines to convert between drc_index to cpu numbers */ | ||
70 | |||
71 | static u32 cpu_to_drc_index(int cpu) | ||
72 | { | ||
73 | struct device_node *dn = NULL; | ||
74 | const int *indexes; | ||
75 | int i; | ||
76 | int rc = 1; | ||
77 | u32 ret = 0; | ||
78 | |||
79 | dn = of_find_node_by_path("/cpus"); | ||
80 | if (dn == NULL) | ||
81 | goto err; | ||
82 | indexes = of_get_property(dn, "ibm,drc-indexes", NULL); | ||
83 | if (indexes == NULL) | ||
84 | goto err_of_node_put; | ||
85 | /* Convert logical cpu number to core number */ | ||
86 | i = cpu_core_index_of_thread(cpu); | ||
87 | /* | ||
88 | * The first element indexes[0] is the number of drc_indexes | ||
89 | * returned in the list. Hence i+1 will get the drc_index | ||
90 | * corresponding to core number i. | ||
91 | */ | ||
92 | WARN_ON(i > indexes[0]); | ||
93 | ret = indexes[i + 1]; | ||
94 | rc = 0; | ||
95 | |||
96 | err_of_node_put: | ||
97 | of_node_put(dn); | ||
98 | err: | ||
99 | if (rc) | ||
100 | printk(KERN_WARNING "cpu_to_drc_index(%d) failed", cpu); | ||
101 | return ret; | ||
102 | } | ||
103 | |||
104 | static int drc_index_to_cpu(u32 drc_index) | ||
105 | { | ||
106 | struct device_node *dn = NULL; | ||
107 | const int *indexes; | ||
108 | int i, cpu = 0; | ||
109 | int rc = 1; | ||
110 | |||
111 | dn = of_find_node_by_path("/cpus"); | ||
112 | if (dn == NULL) | ||
113 | goto err; | ||
114 | indexes = of_get_property(dn, "ibm,drc-indexes", NULL); | ||
115 | if (indexes == NULL) | ||
116 | goto err_of_node_put; | ||
117 | /* | ||
118 | * First element in the array is the number of drc_indexes | ||
119 | * returned. Search through the list to find the matching | ||
120 | * drc_index and get the core number | ||
121 | */ | ||
122 | for (i = 0; i < indexes[0]; i++) { | ||
123 | if (indexes[i + 1] == drc_index) | ||
124 | break; | ||
125 | } | ||
126 | /* Convert core number to logical cpu number */ | ||
127 | cpu = cpu_first_thread_of_core(i); | ||
128 | rc = 0; | ||
129 | |||
130 | err_of_node_put: | ||
131 | of_node_put(dn); | ||
132 | err: | ||
133 | if (rc) | ||
134 | printk(KERN_WARNING "drc_index_to_cpu(%d) failed", drc_index); | ||
135 | return cpu; | ||
136 | } | ||
137 | |||
138 | /* | ||
139 | * pseries hypervisor call H_BEST_ENERGY provides hints to OS on | ||
140 | * preferred logical cpus to activate or deactivate for optimized | ||
141 | * energy consumption. | ||
142 | */ | ||
143 | |||
144 | #define FLAGS_MODE1 0x004E200000080E01 | ||
145 | #define FLAGS_MODE2 0x004E200000080401 | ||
146 | #define FLAGS_ACTIVATE 0x100 | ||
147 | |||
148 | static ssize_t get_best_energy_list(char *page, int activate) | ||
149 | { | ||
150 | int rc, cnt, i, cpu; | ||
151 | unsigned long retbuf[PLPAR_HCALL9_BUFSIZE]; | ||
152 | unsigned long flags = 0; | ||
153 | u32 *buf_page; | ||
154 | char *s = page; | ||
155 | |||
156 | buf_page = (u32 *) get_zeroed_page(GFP_KERNEL); | ||
157 | if (!buf_page) | ||
158 | return -ENOMEM; | ||
159 | |||
160 | flags = FLAGS_MODE1; | ||
161 | if (activate) | ||
162 | flags |= FLAGS_ACTIVATE; | ||
163 | |||
164 | rc = plpar_hcall9(H_BEST_ENERGY, retbuf, flags, 0, __pa(buf_page), | ||
165 | 0, 0, 0, 0, 0, 0); | ||
166 | if (rc != H_SUCCESS) { | ||
167 | free_page((unsigned long) buf_page); | ||
168 | return -EINVAL; | ||
169 | } | ||
170 | |||
171 | cnt = retbuf[0]; | ||
172 | for (i = 0; i < cnt; i++) { | ||
173 | cpu = drc_index_to_cpu(buf_page[2*i+1]); | ||
174 | if ((cpu_online(cpu) && !activate) || | ||
175 | (!cpu_online(cpu) && activate)) | ||
176 | s += sprintf(s, "%d,", cpu); | ||
177 | } | ||
178 | if (s > page) { /* Something to show */ | ||
179 | s--; /* Suppress last comma */ | ||
180 | s += sprintf(s, "\n"); | ||
181 | } | ||
182 | |||
183 | free_page((unsigned long) buf_page); | ||
184 | return s-page; | ||
185 | } | ||
186 | |||
187 | static ssize_t get_best_energy_data(struct sys_device *dev, | ||
188 | char *page, int activate) | ||
189 | { | ||
190 | int rc; | ||
191 | unsigned long retbuf[PLPAR_HCALL9_BUFSIZE]; | ||
192 | unsigned long flags = 0; | ||
193 | |||
194 | flags = FLAGS_MODE2; | ||
195 | if (activate) | ||
196 | flags |= FLAGS_ACTIVATE; | ||
197 | |||
198 | rc = plpar_hcall9(H_BEST_ENERGY, retbuf, flags, | ||
199 | cpu_to_drc_index(dev->id), | ||
200 | 0, 0, 0, 0, 0, 0, 0); | ||
201 | |||
202 | if (rc != H_SUCCESS) | ||
203 | return -EINVAL; | ||
204 | |||
205 | return sprintf(page, "%lu\n", retbuf[1] >> 32); | ||
206 | } | ||
207 | |||
208 | /* Wrapper functions */ | ||
209 | |||
210 | static ssize_t cpu_activate_hint_list_show(struct sysdev_class *class, | ||
211 | struct sysdev_class_attribute *attr, char *page) | ||
212 | { | ||
213 | return get_best_energy_list(page, 1); | ||
214 | } | ||
215 | |||
216 | static ssize_t cpu_deactivate_hint_list_show(struct sysdev_class *class, | ||
217 | struct sysdev_class_attribute *attr, char *page) | ||
218 | { | ||
219 | return get_best_energy_list(page, 0); | ||
220 | } | ||
221 | |||
222 | static ssize_t percpu_activate_hint_show(struct sys_device *dev, | ||
223 | struct sysdev_attribute *attr, char *page) | ||
224 | { | ||
225 | return get_best_energy_data(dev, page, 1); | ||
226 | } | ||
227 | |||
228 | static ssize_t percpu_deactivate_hint_show(struct sys_device *dev, | ||
229 | struct sysdev_attribute *attr, char *page) | ||
230 | { | ||
231 | return get_best_energy_data(dev, page, 0); | ||
232 | } | ||
233 | |||
234 | /* | ||
235 | * Create sysfs interface: | ||
236 | * /sys/devices/system/cpu/pseries_activate_hint_list | ||
237 | * /sys/devices/system/cpu/pseries_deactivate_hint_list | ||
238 | * Comma separated list of cpus to activate or deactivate | ||
239 | * /sys/devices/system/cpu/cpuN/pseries_activate_hint | ||
240 | * /sys/devices/system/cpu/cpuN/pseries_deactivate_hint | ||
241 | * Per-cpu value of the hint | ||
242 | */ | ||
243 | |||
244 | struct sysdev_class_attribute attr_cpu_activate_hint_list = | ||
245 | _SYSDEV_CLASS_ATTR(pseries_activate_hint_list, 0444, | ||
246 | cpu_activate_hint_list_show, NULL); | ||
247 | |||
248 | struct sysdev_class_attribute attr_cpu_deactivate_hint_list = | ||
249 | _SYSDEV_CLASS_ATTR(pseries_deactivate_hint_list, 0444, | ||
250 | cpu_deactivate_hint_list_show, NULL); | ||
251 | |||
252 | struct sysdev_attribute attr_percpu_activate_hint = | ||
253 | _SYSDEV_ATTR(pseries_activate_hint, 0444, | ||
254 | percpu_activate_hint_show, NULL); | ||
255 | |||
256 | struct sysdev_attribute attr_percpu_deactivate_hint = | ||
257 | _SYSDEV_ATTR(pseries_deactivate_hint, 0444, | ||
258 | percpu_deactivate_hint_show, NULL); | ||
259 | |||
260 | static int __init pseries_energy_init(void) | ||
261 | { | ||
262 | int cpu, err; | ||
263 | struct sys_device *cpu_sys_dev; | ||
264 | |||
265 | if (!check_for_h_best_energy()) { | ||
266 | printk(KERN_INFO "Hypercall H_BEST_ENERGY not supported\n"); | ||
267 | return 0; | ||
268 | } | ||
269 | /* Create the sysfs files */ | ||
270 | err = sysfs_create_file(&cpu_sysdev_class.kset.kobj, | ||
271 | &attr_cpu_activate_hint_list.attr); | ||
272 | if (!err) | ||
273 | err = sysfs_create_file(&cpu_sysdev_class.kset.kobj, | ||
274 | &attr_cpu_deactivate_hint_list.attr); | ||
275 | |||
276 | if (err) | ||
277 | return err; | ||
278 | for_each_possible_cpu(cpu) { | ||
279 | cpu_sys_dev = get_cpu_sysdev(cpu); | ||
280 | err = sysfs_create_file(&cpu_sys_dev->kobj, | ||
281 | &attr_percpu_activate_hint.attr); | ||
282 | if (err) | ||
283 | break; | ||
284 | err = sysfs_create_file(&cpu_sys_dev->kobj, | ||
285 | &attr_percpu_deactivate_hint.attr); | ||
286 | if (err) | ||
287 | break; | ||
288 | } | ||
289 | |||
290 | if (err) | ||
291 | return err; | ||
292 | |||
293 | sysfs_entries = 1; /* Removed entries on cleanup */ | ||
294 | return 0; | ||
295 | |||
296 | } | ||
297 | |||
298 | static void __exit pseries_energy_cleanup(void) | ||
299 | { | ||
300 | int cpu; | ||
301 | struct sys_device *cpu_sys_dev; | ||
302 | |||
303 | if (!sysfs_entries) | ||
304 | return; | ||
305 | |||
306 | /* Remove the sysfs files */ | ||
307 | sysfs_remove_file(&cpu_sysdev_class.kset.kobj, | ||
308 | &attr_cpu_activate_hint_list.attr); | ||
309 | |||
310 | sysfs_remove_file(&cpu_sysdev_class.kset.kobj, | ||
311 | &attr_cpu_deactivate_hint_list.attr); | ||
312 | |||
313 | for_each_possible_cpu(cpu) { | ||
314 | cpu_sys_dev = get_cpu_sysdev(cpu); | ||
315 | sysfs_remove_file(&cpu_sys_dev->kobj, | ||
316 | &attr_percpu_activate_hint.attr); | ||
317 | sysfs_remove_file(&cpu_sys_dev->kobj, | ||
318 | &attr_percpu_deactivate_hint.attr); | ||
319 | } | ||
320 | } | ||
321 | |||
322 | module_init(pseries_energy_init); | ||
323 | module_exit(pseries_energy_cleanup); | ||
324 | MODULE_DESCRIPTION("Driver for pSeries platform energy management"); | ||
325 | MODULE_AUTHOR("Vaidyanathan Srinivasan"); | ||
326 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 0bef9dacb64e..9c2973479142 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile | |||
@@ -41,6 +41,7 @@ obj-$(CONFIG_OF_RTC) += of_rtc.o | |||
41 | ifeq ($(CONFIG_PCI),y) | 41 | ifeq ($(CONFIG_PCI),y) |
42 | obj-$(CONFIG_4xx) += ppc4xx_pci.o | 42 | obj-$(CONFIG_4xx) += ppc4xx_pci.o |
43 | endif | 43 | endif |
44 | obj-$(CONFIG_PPC4xx_CPM) += ppc4xx_cpm.o | ||
44 | obj-$(CONFIG_PPC4xx_GPIO) += ppc4xx_gpio.o | 45 | obj-$(CONFIG_PPC4xx_GPIO) += ppc4xx_gpio.o |
45 | 46 | ||
46 | obj-$(CONFIG_CPM) += cpm_common.o | 47 | obj-$(CONFIG_CPM) += cpm_common.o |
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index 17cf15ec38be..8e9e06a7ca59 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c | |||
@@ -312,17 +312,10 @@ static void pci_dma_dev_setup_dart(struct pci_dev *dev) | |||
312 | 312 | ||
313 | static void pci_dma_bus_setup_dart(struct pci_bus *bus) | 313 | static void pci_dma_bus_setup_dart(struct pci_bus *bus) |
314 | { | 314 | { |
315 | struct device_node *dn; | ||
316 | |||
317 | if (!iommu_table_dart_inited) { | 315 | if (!iommu_table_dart_inited) { |
318 | iommu_table_dart_inited = 1; | 316 | iommu_table_dart_inited = 1; |
319 | iommu_table_dart_setup(); | 317 | iommu_table_dart_setup(); |
320 | } | 318 | } |
321 | |||
322 | dn = pci_bus_to_OF_node(bus); | ||
323 | |||
324 | if (dn) | ||
325 | PCI_DN(dn)->iommu_table = &iommu_table_dart; | ||
326 | } | 319 | } |
327 | 320 | ||
328 | static bool dart_device_on_pcie(struct device *dev) | 321 | static bool dart_device_on_pcie(struct device *dev) |
@@ -373,7 +366,7 @@ void __init iommu_init_early_dart(void) | |||
373 | if (dn == NULL) { | 366 | if (dn == NULL) { |
374 | dn = of_find_compatible_node(NULL, "dart", "u4-dart"); | 367 | dn = of_find_compatible_node(NULL, "dart", "u4-dart"); |
375 | if (dn == NULL) | 368 | if (dn == NULL) |
376 | goto bail; | 369 | return; /* use default direct_dma_ops */ |
377 | dart_is_u4 = 1; | 370 | dart_is_u4 = 1; |
378 | } | 371 | } |
379 | 372 | ||
diff --git a/arch/powerpc/sysdev/mpc8xxx_gpio.c b/arch/powerpc/sysdev/mpc8xxx_gpio.c index c0ea05e87f1d..c48cd8178079 100644 --- a/arch/powerpc/sysdev/mpc8xxx_gpio.c +++ b/arch/powerpc/sysdev/mpc8xxx_gpio.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * GPIOs on MPC8349/8572/8610 and compatible | 2 | * GPIOs on MPC512x/8349/8572/8610 and compatible |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Peter Korsgaard <jacmet@sunsite.dk> | 4 | * Copyright (C) 2008 Peter Korsgaard <jacmet@sunsite.dk> |
5 | * | 5 | * |
@@ -26,6 +26,7 @@ | |||
26 | #define GPIO_IER 0x0c | 26 | #define GPIO_IER 0x0c |
27 | #define GPIO_IMR 0x10 | 27 | #define GPIO_IMR 0x10 |
28 | #define GPIO_ICR 0x14 | 28 | #define GPIO_ICR 0x14 |
29 | #define GPIO_ICR2 0x18 | ||
29 | 30 | ||
30 | struct mpc8xxx_gpio_chip { | 31 | struct mpc8xxx_gpio_chip { |
31 | struct of_mm_gpio_chip mm_gc; | 32 | struct of_mm_gpio_chip mm_gc; |
@@ -37,6 +38,7 @@ struct mpc8xxx_gpio_chip { | |||
37 | */ | 38 | */ |
38 | u32 data; | 39 | u32 data; |
39 | struct irq_host *irq; | 40 | struct irq_host *irq; |
41 | void *of_dev_id_data; | ||
40 | }; | 42 | }; |
41 | 43 | ||
42 | static inline u32 mpc8xxx_gpio2mask(unsigned int gpio) | 44 | static inline u32 mpc8xxx_gpio2mask(unsigned int gpio) |
@@ -215,6 +217,51 @@ static int mpc8xxx_irq_set_type(unsigned int virq, unsigned int flow_type) | |||
215 | return 0; | 217 | return 0; |
216 | } | 218 | } |
217 | 219 | ||
220 | static int mpc512x_irq_set_type(unsigned int virq, unsigned int flow_type) | ||
221 | { | ||
222 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq); | ||
223 | struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc; | ||
224 | unsigned long gpio = virq_to_hw(virq); | ||
225 | void __iomem *reg; | ||
226 | unsigned int shift; | ||
227 | unsigned long flags; | ||
228 | |||
229 | if (gpio < 16) { | ||
230 | reg = mm->regs + GPIO_ICR; | ||
231 | shift = (15 - gpio) * 2; | ||
232 | } else { | ||
233 | reg = mm->regs + GPIO_ICR2; | ||
234 | shift = (15 - (gpio % 16)) * 2; | ||
235 | } | ||
236 | |||
237 | switch (flow_type) { | ||
238 | case IRQ_TYPE_EDGE_FALLING: | ||
239 | case IRQ_TYPE_LEVEL_LOW: | ||
240 | spin_lock_irqsave(&mpc8xxx_gc->lock, flags); | ||
241 | clrsetbits_be32(reg, 3 << shift, 2 << shift); | ||
242 | spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); | ||
243 | break; | ||
244 | |||
245 | case IRQ_TYPE_EDGE_RISING: | ||
246 | case IRQ_TYPE_LEVEL_HIGH: | ||
247 | spin_lock_irqsave(&mpc8xxx_gc->lock, flags); | ||
248 | clrsetbits_be32(reg, 3 << shift, 1 << shift); | ||
249 | spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); | ||
250 | break; | ||
251 | |||
252 | case IRQ_TYPE_EDGE_BOTH: | ||
253 | spin_lock_irqsave(&mpc8xxx_gc->lock, flags); | ||
254 | clrbits32(reg, 3 << shift); | ||
255 | spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); | ||
256 | break; | ||
257 | |||
258 | default: | ||
259 | return -EINVAL; | ||
260 | } | ||
261 | |||
262 | return 0; | ||
263 | } | ||
264 | |||
218 | static struct irq_chip mpc8xxx_irq_chip = { | 265 | static struct irq_chip mpc8xxx_irq_chip = { |
219 | .name = "mpc8xxx-gpio", | 266 | .name = "mpc8xxx-gpio", |
220 | .unmask = mpc8xxx_irq_unmask, | 267 | .unmask = mpc8xxx_irq_unmask, |
@@ -226,6 +273,11 @@ static struct irq_chip mpc8xxx_irq_chip = { | |||
226 | static int mpc8xxx_gpio_irq_map(struct irq_host *h, unsigned int virq, | 273 | static int mpc8xxx_gpio_irq_map(struct irq_host *h, unsigned int virq, |
227 | irq_hw_number_t hw) | 274 | irq_hw_number_t hw) |
228 | { | 275 | { |
276 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = h->host_data; | ||
277 | |||
278 | if (mpc8xxx_gc->of_dev_id_data) | ||
279 | mpc8xxx_irq_chip.set_type = mpc8xxx_gc->of_dev_id_data; | ||
280 | |||
229 | set_irq_chip_data(virq, h->host_data); | 281 | set_irq_chip_data(virq, h->host_data); |
230 | set_irq_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq); | 282 | set_irq_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq); |
231 | set_irq_type(virq, IRQ_TYPE_NONE); | 283 | set_irq_type(virq, IRQ_TYPE_NONE); |
@@ -253,11 +305,20 @@ static struct irq_host_ops mpc8xxx_gpio_irq_ops = { | |||
253 | .xlate = mpc8xxx_gpio_irq_xlate, | 305 | .xlate = mpc8xxx_gpio_irq_xlate, |
254 | }; | 306 | }; |
255 | 307 | ||
308 | static struct of_device_id mpc8xxx_gpio_ids[] __initdata = { | ||
309 | { .compatible = "fsl,mpc8349-gpio", }, | ||
310 | { .compatible = "fsl,mpc8572-gpio", }, | ||
311 | { .compatible = "fsl,mpc8610-gpio", }, | ||
312 | { .compatible = "fsl,mpc5121-gpio", .data = mpc512x_irq_set_type, }, | ||
313 | {} | ||
314 | }; | ||
315 | |||
256 | static void __init mpc8xxx_add_controller(struct device_node *np) | 316 | static void __init mpc8xxx_add_controller(struct device_node *np) |
257 | { | 317 | { |
258 | struct mpc8xxx_gpio_chip *mpc8xxx_gc; | 318 | struct mpc8xxx_gpio_chip *mpc8xxx_gc; |
259 | struct of_mm_gpio_chip *mm_gc; | 319 | struct of_mm_gpio_chip *mm_gc; |
260 | struct gpio_chip *gc; | 320 | struct gpio_chip *gc; |
321 | const struct of_device_id *id; | ||
261 | unsigned hwirq; | 322 | unsigned hwirq; |
262 | int ret; | 323 | int ret; |
263 | 324 | ||
@@ -297,6 +358,10 @@ static void __init mpc8xxx_add_controller(struct device_node *np) | |||
297 | if (!mpc8xxx_gc->irq) | 358 | if (!mpc8xxx_gc->irq) |
298 | goto skip_irq; | 359 | goto skip_irq; |
299 | 360 | ||
361 | id = of_match_node(mpc8xxx_gpio_ids, np); | ||
362 | if (id) | ||
363 | mpc8xxx_gc->of_dev_id_data = id->data; | ||
364 | |||
300 | mpc8xxx_gc->irq->host_data = mpc8xxx_gc; | 365 | mpc8xxx_gc->irq->host_data = mpc8xxx_gc; |
301 | 366 | ||
302 | /* ack and mask all irqs */ | 367 | /* ack and mask all irqs */ |
@@ -321,13 +386,7 @@ static int __init mpc8xxx_add_gpiochips(void) | |||
321 | { | 386 | { |
322 | struct device_node *np; | 387 | struct device_node *np; |
323 | 388 | ||
324 | for_each_compatible_node(np, NULL, "fsl,mpc8349-gpio") | 389 | for_each_matching_node(np, mpc8xxx_gpio_ids) |
325 | mpc8xxx_add_controller(np); | ||
326 | |||
327 | for_each_compatible_node(np, NULL, "fsl,mpc8572-gpio") | ||
328 | mpc8xxx_add_controller(np); | ||
329 | |||
330 | for_each_compatible_node(np, NULL, "fsl,mpc8610-gpio") | ||
331 | mpc8xxx_add_controller(np); | 390 | mpc8xxx_add_controller(np); |
332 | 391 | ||
333 | for_each_compatible_node(np, NULL, "fsl,qoriq-gpio") | 392 | for_each_compatible_node(np, NULL, "fsl,qoriq-gpio") |
diff --git a/arch/powerpc/sysdev/ppc4xx_cpm.c b/arch/powerpc/sysdev/ppc4xx_cpm.c new file mode 100644 index 000000000000..73b86cc5ea74 --- /dev/null +++ b/arch/powerpc/sysdev/ppc4xx_cpm.c | |||
@@ -0,0 +1,346 @@ | |||
1 | /* | ||
2 | * PowerPC 4xx Clock and Power Management | ||
3 | * | ||
4 | * Copyright (C) 2010, Applied Micro Circuits Corporation | ||
5 | * Victor Gallardo (vgallardo@apm.com) | ||
6 | * | ||
7 | * Based on arch/powerpc/platforms/44x/idle.c: | ||
8 | * Jerone Young <jyoung5@us.ibm.com> | ||
9 | * Copyright 2008 IBM Corp. | ||
10 | * | ||
11 | * Based on arch/powerpc/sysdev/fsl_pmc.c: | ||
12 | * Anton Vorontsov <avorontsov@ru.mvista.com> | ||
13 | * Copyright 2009 MontaVista Software, Inc. | ||
14 | * | ||
15 | * See file CREDITS for list of people who contributed to this | ||
16 | * project. | ||
17 | * | ||
18 | * This program is free software; you can redistribute it and/or | ||
19 | * modify it under the terms of the GNU General Public License as | ||
20 | * published by the Free Software Foundation; either version 2 of | ||
21 | * the License, or (at your option) any later version. | ||
22 | * | ||
23 | * This program is distributed in the hope that it will be useful, | ||
24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
26 | * GNU General Public License for more details. | ||
27 | * | ||
28 | * You should have received a copy of the GNU General Public License | ||
29 | * along with this program; if not, write to the Free Software | ||
30 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | ||
31 | * MA 02111-1307 USA | ||
32 | */ | ||
33 | |||
34 | #include <linux/kernel.h> | ||
35 | #include <linux/of_platform.h> | ||
36 | #include <linux/sysfs.h> | ||
37 | #include <linux/cpu.h> | ||
38 | #include <linux/suspend.h> | ||
39 | #include <asm/dcr.h> | ||
40 | #include <asm/dcr-native.h> | ||
41 | #include <asm/machdep.h> | ||
42 | |||
43 | #define CPM_ER 0 | ||
44 | #define CPM_FR 1 | ||
45 | #define CPM_SR 2 | ||
46 | |||
47 | #define CPM_IDLE_WAIT 0 | ||
48 | #define CPM_IDLE_DOZE 1 | ||
49 | |||
50 | struct cpm { | ||
51 | dcr_host_t dcr_host; | ||
52 | unsigned int dcr_offset[3]; | ||
53 | unsigned int powersave_off; | ||
54 | unsigned int unused; | ||
55 | unsigned int idle_doze; | ||
56 | unsigned int standby; | ||
57 | unsigned int suspend; | ||
58 | }; | ||
59 | |||
60 | static struct cpm cpm; | ||
61 | |||
62 | struct cpm_idle_mode { | ||
63 | unsigned int enabled; | ||
64 | const char *name; | ||
65 | }; | ||
66 | |||
67 | static struct cpm_idle_mode idle_mode[] = { | ||
68 | [CPM_IDLE_WAIT] = { 1, "wait" }, /* default */ | ||
69 | [CPM_IDLE_DOZE] = { 0, "doze" }, | ||
70 | }; | ||
71 | |||
72 | static unsigned int cpm_set(unsigned int cpm_reg, unsigned int mask) | ||
73 | { | ||
74 | unsigned int value; | ||
75 | |||
76 | /* CPM controller supports 3 different types of sleep interface | ||
77 | * known as class 1, 2 and 3. For class 1 units, they are | ||
78 | * unconditionally put to sleep when the corresponding CPM bit is | ||
79 | * set. For class 2 and 3 units this is not case; if they can be | ||
80 | * put to to sleep, they will. Here we do not verify, we just | ||
81 | * set them and expect them to eventually go off when they can. | ||
82 | */ | ||
83 | value = dcr_read(cpm.dcr_host, cpm.dcr_offset[cpm_reg]); | ||
84 | dcr_write(cpm.dcr_host, cpm.dcr_offset[cpm_reg], value | mask); | ||
85 | |||
86 | /* return old state, to restore later if needed */ | ||
87 | return value; | ||
88 | } | ||
89 | |||
90 | static void cpm_idle_wait(void) | ||
91 | { | ||
92 | unsigned long msr_save; | ||
93 | |||
94 | /* save off initial state */ | ||
95 | msr_save = mfmsr(); | ||
96 | /* sync required when CPM0_ER[CPU] is set */ | ||
97 | mb(); | ||
98 | /* set wait state MSR */ | ||
99 | mtmsr(msr_save|MSR_WE|MSR_EE|MSR_CE|MSR_DE); | ||
100 | isync(); | ||
101 | /* return to initial state */ | ||
102 | mtmsr(msr_save); | ||
103 | isync(); | ||
104 | } | ||
105 | |||
106 | static void cpm_idle_sleep(unsigned int mask) | ||
107 | { | ||
108 | unsigned int er_save; | ||
109 | |||
110 | /* update CPM_ER state */ | ||
111 | er_save = cpm_set(CPM_ER, mask); | ||
112 | |||
113 | /* go to wait state so that CPM0_ER[CPU] can take effect */ | ||
114 | cpm_idle_wait(); | ||
115 | |||
116 | /* restore CPM_ER state */ | ||
117 | dcr_write(cpm.dcr_host, cpm.dcr_offset[CPM_ER], er_save); | ||
118 | } | ||
119 | |||
120 | static void cpm_idle_doze(void) | ||
121 | { | ||
122 | cpm_idle_sleep(cpm.idle_doze); | ||
123 | } | ||
124 | |||
125 | static void cpm_idle_config(int mode) | ||
126 | { | ||
127 | int i; | ||
128 | |||
129 | if (idle_mode[mode].enabled) | ||
130 | return; | ||
131 | |||
132 | for (i = 0; i < ARRAY_SIZE(idle_mode); i++) | ||
133 | idle_mode[i].enabled = 0; | ||
134 | |||
135 | idle_mode[mode].enabled = 1; | ||
136 | } | ||
137 | |||
138 | static ssize_t cpm_idle_show(struct kobject *kobj, | ||
139 | struct kobj_attribute *attr, char *buf) | ||
140 | { | ||
141 | char *s = buf; | ||
142 | int i; | ||
143 | |||
144 | for (i = 0; i < ARRAY_SIZE(idle_mode); i++) { | ||
145 | if (idle_mode[i].enabled) | ||
146 | s += sprintf(s, "[%s] ", idle_mode[i].name); | ||
147 | else | ||
148 | s += sprintf(s, "%s ", idle_mode[i].name); | ||
149 | } | ||
150 | |||
151 | *(s-1) = '\n'; /* convert the last space to a newline */ | ||
152 | |||
153 | return s - buf; | ||
154 | } | ||
155 | |||
156 | static ssize_t cpm_idle_store(struct kobject *kobj, | ||
157 | struct kobj_attribute *attr, | ||
158 | const char *buf, size_t n) | ||
159 | { | ||
160 | int i; | ||
161 | char *p; | ||
162 | int len; | ||
163 | |||
164 | p = memchr(buf, '\n', n); | ||
165 | len = p ? p - buf : n; | ||
166 | |||
167 | for (i = 0; i < ARRAY_SIZE(idle_mode); i++) { | ||
168 | if (strncmp(buf, idle_mode[i].name, len) == 0) { | ||
169 | cpm_idle_config(i); | ||
170 | return n; | ||
171 | } | ||
172 | } | ||
173 | |||
174 | return -EINVAL; | ||
175 | } | ||
176 | |||
177 | static struct kobj_attribute cpm_idle_attr = | ||
178 | __ATTR(idle, 0644, cpm_idle_show, cpm_idle_store); | ||
179 | |||
180 | static void cpm_idle_config_sysfs(void) | ||
181 | { | ||
182 | struct sys_device *sys_dev; | ||
183 | unsigned long ret; | ||
184 | |||
185 | sys_dev = get_cpu_sysdev(0); | ||
186 | |||
187 | ret = sysfs_create_file(&sys_dev->kobj, | ||
188 | &cpm_idle_attr.attr); | ||
189 | if (ret) | ||
190 | printk(KERN_WARNING | ||
191 | "cpm: failed to create idle sysfs entry\n"); | ||
192 | } | ||
193 | |||
194 | static void cpm_idle(void) | ||
195 | { | ||
196 | if (idle_mode[CPM_IDLE_DOZE].enabled) | ||
197 | cpm_idle_doze(); | ||
198 | else | ||
199 | cpm_idle_wait(); | ||
200 | } | ||
201 | |||
202 | static int cpm_suspend_valid(suspend_state_t state) | ||
203 | { | ||
204 | switch (state) { | ||
205 | case PM_SUSPEND_STANDBY: | ||
206 | return !!cpm.standby; | ||
207 | case PM_SUSPEND_MEM: | ||
208 | return !!cpm.suspend; | ||
209 | default: | ||
210 | return 0; | ||
211 | } | ||
212 | } | ||
213 | |||
214 | static void cpm_suspend_standby(unsigned int mask) | ||
215 | { | ||
216 | unsigned long tcr_save; | ||
217 | |||
218 | /* disable decrement interrupt */ | ||
219 | tcr_save = mfspr(SPRN_TCR); | ||
220 | mtspr(SPRN_TCR, tcr_save & ~TCR_DIE); | ||
221 | |||
222 | /* go to sleep state */ | ||
223 | cpm_idle_sleep(mask); | ||
224 | |||
225 | /* restore decrement interrupt */ | ||
226 | mtspr(SPRN_TCR, tcr_save); | ||
227 | } | ||
228 | |||
229 | static int cpm_suspend_enter(suspend_state_t state) | ||
230 | { | ||
231 | switch (state) { | ||
232 | case PM_SUSPEND_STANDBY: | ||
233 | cpm_suspend_standby(cpm.standby); | ||
234 | break; | ||
235 | case PM_SUSPEND_MEM: | ||
236 | cpm_suspend_standby(cpm.suspend); | ||
237 | break; | ||
238 | } | ||
239 | |||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static struct platform_suspend_ops cpm_suspend_ops = { | ||
244 | .valid = cpm_suspend_valid, | ||
245 | .enter = cpm_suspend_enter, | ||
246 | }; | ||
247 | |||
248 | static int cpm_get_uint_property(struct device_node *np, | ||
249 | const char *name) | ||
250 | { | ||
251 | int len; | ||
252 | const unsigned int *prop = of_get_property(np, name, &len); | ||
253 | |||
254 | if (prop == NULL || len < sizeof(u32)) | ||
255 | return 0; | ||
256 | |||
257 | return *prop; | ||
258 | } | ||
259 | |||
260 | static int __init cpm_init(void) | ||
261 | { | ||
262 | struct device_node *np; | ||
263 | int dcr_base, dcr_len; | ||
264 | int ret = 0; | ||
265 | |||
266 | if (!cpm.powersave_off) { | ||
267 | cpm_idle_config(CPM_IDLE_WAIT); | ||
268 | ppc_md.power_save = &cpm_idle; | ||
269 | } | ||
270 | |||
271 | np = of_find_compatible_node(NULL, NULL, "ibm,cpm"); | ||
272 | if (!np) { | ||
273 | ret = -EINVAL; | ||
274 | goto out; | ||
275 | } | ||
276 | |||
277 | dcr_base = dcr_resource_start(np, 0); | ||
278 | dcr_len = dcr_resource_len(np, 0); | ||
279 | |||
280 | if (dcr_base == 0 || dcr_len == 0) { | ||
281 | printk(KERN_ERR "cpm: could not parse dcr property for %s\n", | ||
282 | np->full_name); | ||
283 | ret = -EINVAL; | ||
284 | goto out; | ||
285 | } | ||
286 | |||
287 | cpm.dcr_host = dcr_map(np, dcr_base, dcr_len); | ||
288 | |||
289 | if (!DCR_MAP_OK(cpm.dcr_host)) { | ||
290 | printk(KERN_ERR "cpm: failed to map dcr property for %s\n", | ||
291 | np->full_name); | ||
292 | ret = -EINVAL; | ||
293 | goto out; | ||
294 | } | ||
295 | |||
296 | /* All 4xx SoCs with a CPM controller have one of two | ||
297 | * different order for the CPM registers. Some have the | ||
298 | * CPM registers in the following order (ER,FR,SR). The | ||
299 | * others have them in the following order (SR,ER,FR). | ||
300 | */ | ||
301 | |||
302 | if (cpm_get_uint_property(np, "er-offset") == 0) { | ||
303 | cpm.dcr_offset[CPM_ER] = 0; | ||
304 | cpm.dcr_offset[CPM_FR] = 1; | ||
305 | cpm.dcr_offset[CPM_SR] = 2; | ||
306 | } else { | ||
307 | cpm.dcr_offset[CPM_ER] = 1; | ||
308 | cpm.dcr_offset[CPM_FR] = 2; | ||
309 | cpm.dcr_offset[CPM_SR] = 0; | ||
310 | } | ||
311 | |||
312 | /* Now let's see what IPs to turn off for the following modes */ | ||
313 | |||
314 | cpm.unused = cpm_get_uint_property(np, "unused-units"); | ||
315 | cpm.idle_doze = cpm_get_uint_property(np, "idle-doze"); | ||
316 | cpm.standby = cpm_get_uint_property(np, "standby"); | ||
317 | cpm.suspend = cpm_get_uint_property(np, "suspend"); | ||
318 | |||
319 | /* If some IPs are unused let's turn them off now */ | ||
320 | |||
321 | if (cpm.unused) { | ||
322 | cpm_set(CPM_ER, cpm.unused); | ||
323 | cpm_set(CPM_FR, cpm.unused); | ||
324 | } | ||
325 | |||
326 | /* Now let's export interfaces */ | ||
327 | |||
328 | if (!cpm.powersave_off && cpm.idle_doze) | ||
329 | cpm_idle_config_sysfs(); | ||
330 | |||
331 | if (cpm.standby || cpm.suspend) | ||
332 | suspend_set_ops(&cpm_suspend_ops); | ||
333 | out: | ||
334 | if (np) | ||
335 | of_node_put(np); | ||
336 | return ret; | ||
337 | } | ||
338 | |||
339 | late_initcall(cpm_init); | ||
340 | |||
341 | static int __init cpm_powersave_off(char *arg) | ||
342 | { | ||
343 | cpm.powersave_off = 1; | ||
344 | return 0; | ||
345 | } | ||
346 | __setup("powersave=off", cpm_powersave_off); | ||
diff --git a/arch/powerpc/sysdev/tsi108_dev.c b/arch/powerpc/sysdev/tsi108_dev.c index c2d675b6392c..ee056807b52c 100644 --- a/arch/powerpc/sysdev/tsi108_dev.c +++ b/arch/powerpc/sysdev/tsi108_dev.c | |||
@@ -84,8 +84,8 @@ static int __init tsi108_eth_of_init(void) | |||
84 | memset(&tsi_eth_data, 0, sizeof(tsi_eth_data)); | 84 | memset(&tsi_eth_data, 0, sizeof(tsi_eth_data)); |
85 | 85 | ||
86 | ret = of_address_to_resource(np, 0, &r[0]); | 86 | ret = of_address_to_resource(np, 0, &r[0]); |
87 | DBG("%s: name:start->end = %s:0x%lx-> 0x%lx\n", | 87 | DBG("%s: name:start->end = %s:%pR\n", |
88 | __func__,r[0].name, r[0].start, r[0].end); | 88 | __func__, r[0].name, &r[0]); |
89 | if (ret) | 89 | if (ret) |
90 | goto err; | 90 | goto err; |
91 | 91 | ||
@@ -93,8 +93,8 @@ static int __init tsi108_eth_of_init(void) | |||
93 | r[1].start = irq_of_parse_and_map(np, 0); | 93 | r[1].start = irq_of_parse_and_map(np, 0); |
94 | r[1].end = irq_of_parse_and_map(np, 0); | 94 | r[1].end = irq_of_parse_and_map(np, 0); |
95 | r[1].flags = IORESOURCE_IRQ; | 95 | r[1].flags = IORESOURCE_IRQ; |
96 | DBG("%s: name:start->end = %s:0x%lx-> 0x%lx\n", | 96 | DBG("%s: name:start->end = %s:%pR\n", |
97 | __func__,r[1].name, r[1].start, r[1].end); | 97 | __func__, r[1].name, &r[1]); |
98 | 98 | ||
99 | tsi_eth_dev = | 99 | tsi_eth_dev = |
100 | platform_device_register_simple("tsi-ethernet", i++, &r[0], | 100 | platform_device_register_simple("tsi-ethernet", i++, &r[0], |
diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c index 27370e99c66f..5e2f52b33327 100644 --- a/drivers/char/hvc_vio.c +++ b/drivers/char/hvc_vio.c | |||
@@ -39,7 +39,7 @@ | |||
39 | 39 | ||
40 | #include "hvc_console.h" | 40 | #include "hvc_console.h" |
41 | 41 | ||
42 | char hvc_driver_name[] = "hvc_console"; | 42 | static const char hvc_driver_name[] = "hvc_console"; |
43 | 43 | ||
44 | static struct vio_device_id hvc_driver_table[] __devinitdata = { | 44 | static struct vio_device_id hvc_driver_table[] __devinitdata = { |
45 | {"serial", "hvterm1"}, | 45 | {"serial", "hvterm1"}, |
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 6ee23592700a..ef138731c0ea 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig | |||
@@ -109,7 +109,7 @@ config FSL_DMA | |||
109 | 109 | ||
110 | config MPC512X_DMA | 110 | config MPC512X_DMA |
111 | tristate "Freescale MPC512x built-in DMA engine support" | 111 | tristate "Freescale MPC512x built-in DMA engine support" |
112 | depends on PPC_MPC512x | 112 | depends on PPC_MPC512x || PPC_MPC831x |
113 | select DMA_ENGINE | 113 | select DMA_ENGINE |
114 | ---help--- | 114 | ---help--- |
115 | Enable support for the Freescale MPC512x built-in DMA engine. | 115 | Enable support for the Freescale MPC512x built-in DMA engine. |
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c index 4e9cbf300594..59c270192ccc 100644 --- a/drivers/dma/mpc512x_dma.c +++ b/drivers/dma/mpc512x_dma.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) Freescale Semicondutor, Inc. 2007, 2008. | 2 | * Copyright (C) Freescale Semicondutor, Inc. 2007, 2008. |
3 | * Copyright (C) Semihalf 2009 | 3 | * Copyright (C) Semihalf 2009 |
4 | * Copyright (C) Ilya Yanok, Emcraft Systems 2010 | ||
4 | * | 5 | * |
5 | * Written by Piotr Ziecik <kosmo@semihalf.com>. Hardware description | 6 | * Written by Piotr Ziecik <kosmo@semihalf.com>. Hardware description |
6 | * (defines, structures and comments) was taken from MPC5121 DMA driver | 7 | * (defines, structures and comments) was taken from MPC5121 DMA driver |
@@ -70,6 +71,8 @@ | |||
70 | #define MPC_DMA_DMAES_SBE (1 << 1) | 71 | #define MPC_DMA_DMAES_SBE (1 << 1) |
71 | #define MPC_DMA_DMAES_DBE (1 << 0) | 72 | #define MPC_DMA_DMAES_DBE (1 << 0) |
72 | 73 | ||
74 | #define MPC_DMA_DMAGPOR_SNOOP_ENABLE (1 << 6) | ||
75 | |||
73 | #define MPC_DMA_TSIZE_1 0x00 | 76 | #define MPC_DMA_TSIZE_1 0x00 |
74 | #define MPC_DMA_TSIZE_2 0x01 | 77 | #define MPC_DMA_TSIZE_2 0x01 |
75 | #define MPC_DMA_TSIZE_4 0x02 | 78 | #define MPC_DMA_TSIZE_4 0x02 |
@@ -104,7 +107,10 @@ struct __attribute__ ((__packed__)) mpc_dma_regs { | |||
104 | /* 0x30 */ | 107 | /* 0x30 */ |
105 | u32 dmahrsh; /* DMA hw request status high(ch63~32) */ | 108 | u32 dmahrsh; /* DMA hw request status high(ch63~32) */ |
106 | u32 dmahrsl; /* DMA hardware request status low(ch31~0) */ | 109 | u32 dmahrsl; /* DMA hardware request status low(ch31~0) */ |
107 | u32 dmaihsa; /* DMA interrupt high select AXE(ch63~32) */ | 110 | union { |
111 | u32 dmaihsa; /* DMA interrupt high select AXE(ch63~32) */ | ||
112 | u32 dmagpor; /* (General purpose register on MPC8308) */ | ||
113 | }; | ||
108 | u32 dmailsa; /* DMA interrupt low select AXE(ch31~0) */ | 114 | u32 dmailsa; /* DMA interrupt low select AXE(ch31~0) */ |
109 | /* 0x40 ~ 0xff */ | 115 | /* 0x40 ~ 0xff */ |
110 | u32 reserve0[48]; /* Reserved */ | 116 | u32 reserve0[48]; /* Reserved */ |
@@ -195,7 +201,9 @@ struct mpc_dma { | |||
195 | struct mpc_dma_regs __iomem *regs; | 201 | struct mpc_dma_regs __iomem *regs; |
196 | struct mpc_dma_tcd __iomem *tcd; | 202 | struct mpc_dma_tcd __iomem *tcd; |
197 | int irq; | 203 | int irq; |
204 | int irq2; | ||
198 | uint error_status; | 205 | uint error_status; |
206 | int is_mpc8308; | ||
199 | 207 | ||
200 | /* Lock for error_status field in this structure */ | 208 | /* Lock for error_status field in this structure */ |
201 | spinlock_t error_status_lock; | 209 | spinlock_t error_status_lock; |
@@ -252,11 +260,13 @@ static void mpc_dma_execute(struct mpc_dma_chan *mchan) | |||
252 | prev = mdesc; | 260 | prev = mdesc; |
253 | } | 261 | } |
254 | 262 | ||
255 | prev->tcd->start = 0; | ||
256 | prev->tcd->int_maj = 1; | 263 | prev->tcd->int_maj = 1; |
257 | 264 | ||
258 | /* Send first descriptor in chain into hardware */ | 265 | /* Send first descriptor in chain into hardware */ |
259 | memcpy_toio(&mdma->tcd[cid], first->tcd, sizeof(struct mpc_dma_tcd)); | 266 | memcpy_toio(&mdma->tcd[cid], first->tcd, sizeof(struct mpc_dma_tcd)); |
267 | |||
268 | if (first != prev) | ||
269 | mdma->tcd[cid].e_sg = 1; | ||
260 | out_8(&mdma->regs->dmassrt, cid); | 270 | out_8(&mdma->regs->dmassrt, cid); |
261 | } | 271 | } |
262 | 272 | ||
@@ -274,6 +284,9 @@ static void mpc_dma_irq_process(struct mpc_dma *mdma, u32 is, u32 es, int off) | |||
274 | 284 | ||
275 | spin_lock(&mchan->lock); | 285 | spin_lock(&mchan->lock); |
276 | 286 | ||
287 | out_8(&mdma->regs->dmacint, ch + off); | ||
288 | out_8(&mdma->regs->dmacerr, ch + off); | ||
289 | |||
277 | /* Check error status */ | 290 | /* Check error status */ |
278 | if (es & (1 << ch)) | 291 | if (es & (1 << ch)) |
279 | list_for_each_entry(mdesc, &mchan->active, node) | 292 | list_for_each_entry(mdesc, &mchan->active, node) |
@@ -302,36 +315,68 @@ static irqreturn_t mpc_dma_irq(int irq, void *data) | |||
302 | spin_unlock(&mdma->error_status_lock); | 315 | spin_unlock(&mdma->error_status_lock); |
303 | 316 | ||
304 | /* Handle interrupt on each channel */ | 317 | /* Handle interrupt on each channel */ |
305 | mpc_dma_irq_process(mdma, in_be32(&mdma->regs->dmainth), | 318 | if (mdma->dma.chancnt > 32) { |
319 | mpc_dma_irq_process(mdma, in_be32(&mdma->regs->dmainth), | ||
306 | in_be32(&mdma->regs->dmaerrh), 32); | 320 | in_be32(&mdma->regs->dmaerrh), 32); |
321 | } | ||
307 | mpc_dma_irq_process(mdma, in_be32(&mdma->regs->dmaintl), | 322 | mpc_dma_irq_process(mdma, in_be32(&mdma->regs->dmaintl), |
308 | in_be32(&mdma->regs->dmaerrl), 0); | 323 | in_be32(&mdma->regs->dmaerrl), 0); |
309 | 324 | ||
310 | /* Ack interrupt on all channels */ | ||
311 | out_be32(&mdma->regs->dmainth, 0xFFFFFFFF); | ||
312 | out_be32(&mdma->regs->dmaintl, 0xFFFFFFFF); | ||
313 | out_be32(&mdma->regs->dmaerrh, 0xFFFFFFFF); | ||
314 | out_be32(&mdma->regs->dmaerrl, 0xFFFFFFFF); | ||
315 | |||
316 | /* Schedule tasklet */ | 325 | /* Schedule tasklet */ |
317 | tasklet_schedule(&mdma->tasklet); | 326 | tasklet_schedule(&mdma->tasklet); |
318 | 327 | ||
319 | return IRQ_HANDLED; | 328 | return IRQ_HANDLED; |
320 | } | 329 | } |
321 | 330 | ||
322 | /* DMA Tasklet */ | 331 | /* proccess completed descriptors */ |
323 | static void mpc_dma_tasklet(unsigned long data) | 332 | static void mpc_dma_process_completed(struct mpc_dma *mdma) |
324 | { | 333 | { |
325 | struct mpc_dma *mdma = (void *)data; | ||
326 | dma_cookie_t last_cookie = 0; | 334 | dma_cookie_t last_cookie = 0; |
327 | struct mpc_dma_chan *mchan; | 335 | struct mpc_dma_chan *mchan; |
328 | struct mpc_dma_desc *mdesc; | 336 | struct mpc_dma_desc *mdesc; |
329 | struct dma_async_tx_descriptor *desc; | 337 | struct dma_async_tx_descriptor *desc; |
330 | unsigned long flags; | 338 | unsigned long flags; |
331 | LIST_HEAD(list); | 339 | LIST_HEAD(list); |
332 | uint es; | ||
333 | int i; | 340 | int i; |
334 | 341 | ||
342 | for (i = 0; i < mdma->dma.chancnt; i++) { | ||
343 | mchan = &mdma->channels[i]; | ||
344 | |||
345 | /* Get all completed descriptors */ | ||
346 | spin_lock_irqsave(&mchan->lock, flags); | ||
347 | if (!list_empty(&mchan->completed)) | ||
348 | list_splice_tail_init(&mchan->completed, &list); | ||
349 | spin_unlock_irqrestore(&mchan->lock, flags); | ||
350 | |||
351 | if (list_empty(&list)) | ||
352 | continue; | ||
353 | |||
354 | /* Execute callbacks and run dependencies */ | ||
355 | list_for_each_entry(mdesc, &list, node) { | ||
356 | desc = &mdesc->desc; | ||
357 | |||
358 | if (desc->callback) | ||
359 | desc->callback(desc->callback_param); | ||
360 | |||
361 | last_cookie = desc->cookie; | ||
362 | dma_run_dependencies(desc); | ||
363 | } | ||
364 | |||
365 | /* Free descriptors */ | ||
366 | spin_lock_irqsave(&mchan->lock, flags); | ||
367 | list_splice_tail_init(&list, &mchan->free); | ||
368 | mchan->completed_cookie = last_cookie; | ||
369 | spin_unlock_irqrestore(&mchan->lock, flags); | ||
370 | } | ||
371 | } | ||
372 | |||
373 | /* DMA Tasklet */ | ||
374 | static void mpc_dma_tasklet(unsigned long data) | ||
375 | { | ||
376 | struct mpc_dma *mdma = (void *)data; | ||
377 | unsigned long flags; | ||
378 | uint es; | ||
379 | |||
335 | spin_lock_irqsave(&mdma->error_status_lock, flags); | 380 | spin_lock_irqsave(&mdma->error_status_lock, flags); |
336 | es = mdma->error_status; | 381 | es = mdma->error_status; |
337 | mdma->error_status = 0; | 382 | mdma->error_status = 0; |
@@ -370,35 +415,7 @@ static void mpc_dma_tasklet(unsigned long data) | |||
370 | dev_err(mdma->dma.dev, "- Destination Bus Error\n"); | 415 | dev_err(mdma->dma.dev, "- Destination Bus Error\n"); |
371 | } | 416 | } |
372 | 417 | ||
373 | for (i = 0; i < mdma->dma.chancnt; i++) { | 418 | mpc_dma_process_completed(mdma); |
374 | mchan = &mdma->channels[i]; | ||
375 | |||
376 | /* Get all completed descriptors */ | ||
377 | spin_lock_irqsave(&mchan->lock, flags); | ||
378 | if (!list_empty(&mchan->completed)) | ||
379 | list_splice_tail_init(&mchan->completed, &list); | ||
380 | spin_unlock_irqrestore(&mchan->lock, flags); | ||
381 | |||
382 | if (list_empty(&list)) | ||
383 | continue; | ||
384 | |||
385 | /* Execute callbacks and run dependencies */ | ||
386 | list_for_each_entry(mdesc, &list, node) { | ||
387 | desc = &mdesc->desc; | ||
388 | |||
389 | if (desc->callback) | ||
390 | desc->callback(desc->callback_param); | ||
391 | |||
392 | last_cookie = desc->cookie; | ||
393 | dma_run_dependencies(desc); | ||
394 | } | ||
395 | |||
396 | /* Free descriptors */ | ||
397 | spin_lock_irqsave(&mchan->lock, flags); | ||
398 | list_splice_tail_init(&list, &mchan->free); | ||
399 | mchan->completed_cookie = last_cookie; | ||
400 | spin_unlock_irqrestore(&mchan->lock, flags); | ||
401 | } | ||
402 | } | 419 | } |
403 | 420 | ||
404 | /* Submit descriptor to hardware */ | 421 | /* Submit descriptor to hardware */ |
@@ -563,6 +580,7 @@ static struct dma_async_tx_descriptor * | |||
563 | mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src, | 580 | mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src, |
564 | size_t len, unsigned long flags) | 581 | size_t len, unsigned long flags) |
565 | { | 582 | { |
583 | struct mpc_dma *mdma = dma_chan_to_mpc_dma(chan); | ||
566 | struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(chan); | 584 | struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(chan); |
567 | struct mpc_dma_desc *mdesc = NULL; | 585 | struct mpc_dma_desc *mdesc = NULL; |
568 | struct mpc_dma_tcd *tcd; | 586 | struct mpc_dma_tcd *tcd; |
@@ -577,8 +595,11 @@ mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src, | |||
577 | } | 595 | } |
578 | spin_unlock_irqrestore(&mchan->lock, iflags); | 596 | spin_unlock_irqrestore(&mchan->lock, iflags); |
579 | 597 | ||
580 | if (!mdesc) | 598 | if (!mdesc) { |
599 | /* try to free completed descriptors */ | ||
600 | mpc_dma_process_completed(mdma); | ||
581 | return NULL; | 601 | return NULL; |
602 | } | ||
582 | 603 | ||
583 | mdesc->error = 0; | 604 | mdesc->error = 0; |
584 | tcd = mdesc->tcd; | 605 | tcd = mdesc->tcd; |
@@ -591,7 +612,8 @@ mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src, | |||
591 | tcd->dsize = MPC_DMA_TSIZE_32; | 612 | tcd->dsize = MPC_DMA_TSIZE_32; |
592 | tcd->soff = 32; | 613 | tcd->soff = 32; |
593 | tcd->doff = 32; | 614 | tcd->doff = 32; |
594 | } else if (IS_ALIGNED(src | dst | len, 16)) { | 615 | } else if (!mdma->is_mpc8308 && IS_ALIGNED(src | dst | len, 16)) { |
616 | /* MPC8308 doesn't support 16 byte transfers */ | ||
595 | tcd->ssize = MPC_DMA_TSIZE_16; | 617 | tcd->ssize = MPC_DMA_TSIZE_16; |
596 | tcd->dsize = MPC_DMA_TSIZE_16; | 618 | tcd->dsize = MPC_DMA_TSIZE_16; |
597 | tcd->soff = 16; | 619 | tcd->soff = 16; |
@@ -651,6 +673,15 @@ static int __devinit mpc_dma_probe(struct platform_device *op, | |||
651 | return -EINVAL; | 673 | return -EINVAL; |
652 | } | 674 | } |
653 | 675 | ||
676 | if (of_device_is_compatible(dn, "fsl,mpc8308-dma")) { | ||
677 | mdma->is_mpc8308 = 1; | ||
678 | mdma->irq2 = irq_of_parse_and_map(dn, 1); | ||
679 | if (mdma->irq2 == NO_IRQ) { | ||
680 | dev_err(dev, "Error mapping IRQ!\n"); | ||
681 | return -EINVAL; | ||
682 | } | ||
683 | } | ||
684 | |||
654 | retval = of_address_to_resource(dn, 0, &res); | 685 | retval = of_address_to_resource(dn, 0, &res); |
655 | if (retval) { | 686 | if (retval) { |
656 | dev_err(dev, "Error parsing memory region!\n"); | 687 | dev_err(dev, "Error parsing memory region!\n"); |
@@ -681,11 +712,23 @@ static int __devinit mpc_dma_probe(struct platform_device *op, | |||
681 | return -EINVAL; | 712 | return -EINVAL; |
682 | } | 713 | } |
683 | 714 | ||
715 | if (mdma->is_mpc8308) { | ||
716 | retval = devm_request_irq(dev, mdma->irq2, &mpc_dma_irq, 0, | ||
717 | DRV_NAME, mdma); | ||
718 | if (retval) { | ||
719 | dev_err(dev, "Error requesting IRQ2!\n"); | ||
720 | return -EINVAL; | ||
721 | } | ||
722 | } | ||
723 | |||
684 | spin_lock_init(&mdma->error_status_lock); | 724 | spin_lock_init(&mdma->error_status_lock); |
685 | 725 | ||
686 | dma = &mdma->dma; | 726 | dma = &mdma->dma; |
687 | dma->dev = dev; | 727 | dma->dev = dev; |
688 | dma->chancnt = MPC_DMA_CHANNELS; | 728 | if (!mdma->is_mpc8308) |
729 | dma->chancnt = MPC_DMA_CHANNELS; | ||
730 | else | ||
731 | dma->chancnt = 16; /* MPC8308 DMA has only 16 channels */ | ||
689 | dma->device_alloc_chan_resources = mpc_dma_alloc_chan_resources; | 732 | dma->device_alloc_chan_resources = mpc_dma_alloc_chan_resources; |
690 | dma->device_free_chan_resources = mpc_dma_free_chan_resources; | 733 | dma->device_free_chan_resources = mpc_dma_free_chan_resources; |
691 | dma->device_issue_pending = mpc_dma_issue_pending; | 734 | dma->device_issue_pending = mpc_dma_issue_pending; |
@@ -721,26 +764,40 @@ static int __devinit mpc_dma_probe(struct platform_device *op, | |||
721 | * - Round-robin group arbitration, | 764 | * - Round-robin group arbitration, |
722 | * - Round-robin channel arbitration. | 765 | * - Round-robin channel arbitration. |
723 | */ | 766 | */ |
724 | out_be32(&mdma->regs->dmacr, MPC_DMA_DMACR_EDCG | | 767 | if (!mdma->is_mpc8308) { |
725 | MPC_DMA_DMACR_ERGA | MPC_DMA_DMACR_ERCA); | 768 | out_be32(&mdma->regs->dmacr, MPC_DMA_DMACR_EDCG | |
726 | 769 | MPC_DMA_DMACR_ERGA | MPC_DMA_DMACR_ERCA); | |
727 | /* Disable hardware DMA requests */ | 770 | |
728 | out_be32(&mdma->regs->dmaerqh, 0); | 771 | /* Disable hardware DMA requests */ |
729 | out_be32(&mdma->regs->dmaerql, 0); | 772 | out_be32(&mdma->regs->dmaerqh, 0); |
730 | 773 | out_be32(&mdma->regs->dmaerql, 0); | |
731 | /* Disable error interrupts */ | 774 | |
732 | out_be32(&mdma->regs->dmaeeih, 0); | 775 | /* Disable error interrupts */ |
733 | out_be32(&mdma->regs->dmaeeil, 0); | 776 | out_be32(&mdma->regs->dmaeeih, 0); |
734 | 777 | out_be32(&mdma->regs->dmaeeil, 0); | |
735 | /* Clear interrupts status */ | 778 | |
736 | out_be32(&mdma->regs->dmainth, 0xFFFFFFFF); | 779 | /* Clear interrupts status */ |
737 | out_be32(&mdma->regs->dmaintl, 0xFFFFFFFF); | 780 | out_be32(&mdma->regs->dmainth, 0xFFFFFFFF); |
738 | out_be32(&mdma->regs->dmaerrh, 0xFFFFFFFF); | 781 | out_be32(&mdma->regs->dmaintl, 0xFFFFFFFF); |
739 | out_be32(&mdma->regs->dmaerrl, 0xFFFFFFFF); | 782 | out_be32(&mdma->regs->dmaerrh, 0xFFFFFFFF); |
740 | 783 | out_be32(&mdma->regs->dmaerrl, 0xFFFFFFFF); | |
741 | /* Route interrupts to IPIC */ | 784 | |
742 | out_be32(&mdma->regs->dmaihsa, 0); | 785 | /* Route interrupts to IPIC */ |
743 | out_be32(&mdma->regs->dmailsa, 0); | 786 | out_be32(&mdma->regs->dmaihsa, 0); |
787 | out_be32(&mdma->regs->dmailsa, 0); | ||
788 | } else { | ||
789 | /* MPC8308 has 16 channels and lacks some registers */ | ||
790 | out_be32(&mdma->regs->dmacr, MPC_DMA_DMACR_ERCA); | ||
791 | |||
792 | /* enable snooping */ | ||
793 | out_be32(&mdma->regs->dmagpor, MPC_DMA_DMAGPOR_SNOOP_ENABLE); | ||
794 | /* Disable error interrupts */ | ||
795 | out_be32(&mdma->regs->dmaeeil, 0); | ||
796 | |||
797 | /* Clear interrupts status */ | ||
798 | out_be32(&mdma->regs->dmaintl, 0xFFFF); | ||
799 | out_be32(&mdma->regs->dmaerrl, 0xFFFF); | ||
800 | } | ||
744 | 801 | ||
745 | /* Register DMA engine */ | 802 | /* Register DMA engine */ |
746 | dev_set_drvdata(dev, mdma); | 803 | dev_set_drvdata(dev, mdma); |
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index b6e7ddc09d76..4daf9e5a7736 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c | |||
@@ -387,11 +387,10 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, | |||
387 | /* Set the DMA ops to the ones from the PCI device, this could be | 387 | /* Set the DMA ops to the ones from the PCI device, this could be |
388 | * fishy if we didn't know that on PowerMac it's always direct ops | 388 | * fishy if we didn't know that on PowerMac it's always direct ops |
389 | * or iommu ops that will work fine | 389 | * or iommu ops that will work fine |
390 | * | ||
391 | * To get all the fields, copy all archdata | ||
390 | */ | 392 | */ |
391 | dev->ofdev.dev.archdata.dma_ops = | 393 | dev->ofdev.dev.archdata = chip->lbus.pdev->dev.archdata; |
392 | chip->lbus.pdev->dev.archdata.dma_ops; | ||
393 | dev->ofdev.dev.archdata.dma_data = | ||
394 | chip->lbus.pdev->dev.archdata.dma_data; | ||
395 | #endif /* CONFIG_PCI */ | 394 | #endif /* CONFIG_PCI */ |
396 | 395 | ||
397 | #ifdef DEBUG | 396 | #ifdef DEBUG |
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c index 44549272333c..2e041fd0a00c 100644 --- a/drivers/macintosh/therm_pm72.c +++ b/drivers/macintosh/therm_pm72.c | |||
@@ -2213,6 +2213,9 @@ static void fcu_lookup_fans(struct device_node *fcu_node) | |||
2213 | static int fcu_of_probe(struct platform_device* dev, const struct of_device_id *match) | 2213 | static int fcu_of_probe(struct platform_device* dev, const struct of_device_id *match) |
2214 | { | 2214 | { |
2215 | state = state_detached; | 2215 | state = state_detached; |
2216 | of_dev = dev; | ||
2217 | |||
2218 | dev_info(&dev->dev, "PowerMac G5 Thermal control driver %s\n", VERSION); | ||
2216 | 2219 | ||
2217 | /* Lookup the fans in the device tree */ | 2220 | /* Lookup the fans in the device tree */ |
2218 | fcu_lookup_fans(dev->dev.of_node); | 2221 | fcu_lookup_fans(dev->dev.of_node); |
@@ -2235,6 +2238,7 @@ static const struct of_device_id fcu_match[] = | |||
2235 | }, | 2238 | }, |
2236 | {}, | 2239 | {}, |
2237 | }; | 2240 | }; |
2241 | MODULE_DEVICE_TABLE(of, fcu_match); | ||
2238 | 2242 | ||
2239 | static struct of_platform_driver fcu_of_platform_driver = | 2243 | static struct of_platform_driver fcu_of_platform_driver = |
2240 | { | 2244 | { |
@@ -2252,8 +2256,6 @@ static struct of_platform_driver fcu_of_platform_driver = | |||
2252 | */ | 2256 | */ |
2253 | static int __init therm_pm72_init(void) | 2257 | static int __init therm_pm72_init(void) |
2254 | { | 2258 | { |
2255 | struct device_node *np; | ||
2256 | |||
2257 | rackmac = of_machine_is_compatible("RackMac3,1"); | 2259 | rackmac = of_machine_is_compatible("RackMac3,1"); |
2258 | 2260 | ||
2259 | if (!of_machine_is_compatible("PowerMac7,2") && | 2261 | if (!of_machine_is_compatible("PowerMac7,2") && |
@@ -2261,34 +2263,12 @@ static int __init therm_pm72_init(void) | |||
2261 | !rackmac) | 2263 | !rackmac) |
2262 | return -ENODEV; | 2264 | return -ENODEV; |
2263 | 2265 | ||
2264 | printk(KERN_INFO "PowerMac G5 Thermal control driver %s\n", VERSION); | 2266 | return of_register_platform_driver(&fcu_of_platform_driver); |
2265 | |||
2266 | np = of_find_node_by_type(NULL, "fcu"); | ||
2267 | if (np == NULL) { | ||
2268 | /* Some machines have strangely broken device-tree */ | ||
2269 | np = of_find_node_by_path("/u3@0,f8000000/i2c@f8001000/fan@15e"); | ||
2270 | if (np == NULL) { | ||
2271 | printk(KERN_ERR "Can't find FCU in device-tree !\n"); | ||
2272 | return -ENODEV; | ||
2273 | } | ||
2274 | } | ||
2275 | of_dev = of_platform_device_create(np, "temperature", NULL); | ||
2276 | if (of_dev == NULL) { | ||
2277 | printk(KERN_ERR "Can't register FCU platform device !\n"); | ||
2278 | return -ENODEV; | ||
2279 | } | ||
2280 | |||
2281 | of_register_platform_driver(&fcu_of_platform_driver); | ||
2282 | |||
2283 | return 0; | ||
2284 | } | 2267 | } |
2285 | 2268 | ||
2286 | static void __exit therm_pm72_exit(void) | 2269 | static void __exit therm_pm72_exit(void) |
2287 | { | 2270 | { |
2288 | of_unregister_platform_driver(&fcu_of_platform_driver); | 2271 | of_unregister_platform_driver(&fcu_of_platform_driver); |
2289 | |||
2290 | if (of_dev) | ||
2291 | of_device_unregister(of_dev); | ||
2292 | } | 2272 | } |
2293 | 2273 | ||
2294 | module_init(therm_pm72_init); | 2274 | module_init(therm_pm72_init); |
diff --git a/drivers/ps3/Makefile b/drivers/ps3/Makefile index ccea15c11c19..50cb1e1b4a12 100644 --- a/drivers/ps3/Makefile +++ b/drivers/ps3/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | obj-$(CONFIG_PS3_VUART) += ps3-vuart.o | 1 | obj-$(CONFIG_PS3_VUART) += ps3-vuart.o |
2 | obj-$(CONFIG_PS3_PS3AV) += ps3av_mod.o | 2 | obj-$(CONFIG_PS3_PS3AV) += ps3av_mod.o |
3 | ps3av_mod-objs += ps3av.o ps3av_cmd.o | 3 | ps3av_mod-y := ps3av.o ps3av_cmd.o |
4 | obj-$(CONFIG_PPC_PS3) += sys-manager-core.o | 4 | obj-$(CONFIG_PPC_PS3) += sys-manager-core.o |
5 | obj-$(CONFIG_PS3_SYS_MANAGER) += ps3-sys-manager.o | 5 | obj-$(CONFIG_PS3_SYS_MANAGER) += ps3-sys-manager.o |
6 | obj-$(CONFIG_PS3_STORAGE) += ps3stor_lib.o | 6 | obj-$(CONFIG_PS3_STORAGE) += ps3stor_lib.o |
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 5856167a0c90..7e6ce626b7f1 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -687,7 +687,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
687 | #if defined(CONFIG_ATARI) | 687 | #if defined(CONFIG_ATARI) |
688 | address_space = 64; | 688 | address_space = 64; |
689 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) \ | 689 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) \ |
690 | || defined(__sparc__) || defined(__mips__) | 690 | || defined(__sparc__) || defined(__mips__) \ |
691 | || defined(__powerpc__) | ||
691 | address_space = 128; | 692 | address_space = 128; |
692 | #else | 693 | #else |
693 | #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. | 694 | #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. |