diff options
37 files changed, 876 insertions, 178 deletions
diff --git a/Documentation/powerpc/dts-bindings/fsl/mpic.txt b/Documentation/powerpc/dts-bindings/fsl/mpic.txt new file mode 100644 index 000000000000..71e39cf3215b --- /dev/null +++ b/Documentation/powerpc/dts-bindings/fsl/mpic.txt | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | * OpenPIC and its interrupt numbers on Freescale's e500/e600 cores | ||
| 2 | |||
| 3 | The OpenPIC specification does not specify which interrupt source has to | ||
| 4 | become which interrupt number. This is up to the software implementation | ||
| 5 | of the interrupt controller. The only requirement is that every | ||
| 6 | interrupt source has to have an unique interrupt number / vector number. | ||
| 7 | To accomplish this the current implementation assigns the number zero to | ||
| 8 | the first source, the number one to the second source and so on until | ||
| 9 | all interrupt sources have their unique number. | ||
| 10 | Usually the assigned vector number equals the interrupt number mentioned | ||
| 11 | in the documentation for a given core / CPU. This is however not true | ||
| 12 | for the e500 cores (MPC85XX CPUs) where the documentation distinguishes | ||
| 13 | between internal and external interrupt sources and starts counting at | ||
| 14 | zero for both of them. | ||
| 15 | |||
| 16 | So what to write for external interrupt source X or internal interrupt | ||
| 17 | source Y into the device tree? Here is an example: | ||
| 18 | |||
| 19 | The memory map for the interrupt controller in the MPC8544[0] shows, | ||
| 20 | that the first interrupt source starts at 0x5_0000 (PIC Register Address | ||
| 21 | Map-Interrupt Source Configuration Registers). This source becomes the | ||
| 22 | number zero therefore: | ||
| 23 | External interrupt 0 = interrupt number 0 | ||
| 24 | External interrupt 1 = interrupt number 1 | ||
| 25 | External interrupt 2 = interrupt number 2 | ||
| 26 | ... | ||
| 27 | Every interrupt number allocates 0x20 bytes register space. So to get | ||
| 28 | its number it is sufficient to shift the lower 16bits to right by five. | ||
| 29 | So for the external interrupt 10 we have: | ||
| 30 | 0x0140 >> 5 = 10 | ||
| 31 | |||
| 32 | After the external sources, the internal sources follow. The in core I2C | ||
| 33 | controller on the MPC8544 for instance has the internal source number | ||
| 34 | 27. Oo obtain its interrupt number we take the lower 16bits of its memory | ||
| 35 | address (0x5_0560) and shift it right: | ||
| 36 | 0x0560 >> 5 = 43 | ||
| 37 | |||
| 38 | Therefore the I2C device node for the MPC8544 CPU has to have the | ||
| 39 | interrupt number 43 specified in the device tree. | ||
| 40 | |||
| 41 | [0] MPC8544E PowerQUICCTM III, Integrated Host Processor Family Reference Manual | ||
| 42 | MPC8544ERM Rev. 1 10/2007 | ||
diff --git a/arch/powerpc/boot/dts/katmai.dts b/arch/powerpc/boot/dts/katmai.dts index 51eb6ed5da2d..8f345de960cd 100644 --- a/arch/powerpc/boot/dts/katmai.dts +++ b/arch/powerpc/boot/dts/katmai.dts | |||
| @@ -108,12 +108,19 @@ | |||
| 108 | dcr-reg = <0x00c 0x002>; | 108 | dcr-reg = <0x00c 0x002>; |
| 109 | }; | 109 | }; |
| 110 | 110 | ||
| 111 | MQ0: mq { | ||
| 112 | compatible = "ibm,mq-440spe"; | ||
| 113 | dcr-reg = <0x040 0x020>; | ||
| 114 | }; | ||
| 115 | |||
| 111 | plb { | 116 | plb { |
| 112 | compatible = "ibm,plb-440spe", "ibm,plb-440gp", "ibm,plb4"; | 117 | compatible = "ibm,plb-440spe", "ibm,plb-440gp", "ibm,plb4"; |
| 113 | #address-cells = <2>; | 118 | #address-cells = <2>; |
| 114 | #size-cells = <1>; | 119 | #size-cells = <1>; |
| 115 | /* addr-child addr-parent size */ | 120 | /* addr-child addr-parent size */ |
| 116 | ranges = <0x4 0xe0000000 0x4 0xe0000000 0x20000000 | 121 | ranges = <0x4 0x00100000 0x4 0x00100000 0x00001000 |
| 122 | 0x4 0x00200000 0x4 0x00200000 0x00000400 | ||
| 123 | 0x4 0xe0000000 0x4 0xe0000000 0x20000000 | ||
| 117 | 0xc 0x00000000 0xc 0x00000000 0x20000000 | 124 | 0xc 0x00000000 0xc 0x00000000 0x20000000 |
| 118 | 0xd 0x00000000 0xd 0x00000000 0x80000000 | 125 | 0xd 0x00000000 0xd 0x00000000 0x80000000 |
| 119 | 0xd 0x80000000 0xd 0x80000000 0x80000000 | 126 | 0xd 0x80000000 0xd 0x80000000 0x80000000 |
| @@ -400,6 +407,49 @@ | |||
| 400 | 0x0 0x0 0x0 0x3 &UIC3 0xa 0x4 /* swizzled int C */ | 407 | 0x0 0x0 0x0 0x3 &UIC3 0xa 0x4 /* swizzled int C */ |
| 401 | 0x0 0x0 0x0 0x4 &UIC3 0xb 0x4 /* swizzled int D */>; | 408 | 0x0 0x0 0x0 0x4 &UIC3 0xb 0x4 /* swizzled int D */>; |
| 402 | }; | 409 | }; |
| 410 | |||
| 411 | I2O: i2o@400100000 { | ||
| 412 | compatible = "ibm,i2o-440spe"; | ||
| 413 | reg = <0x00000004 0x00100000 0x100>; | ||
| 414 | dcr-reg = <0x060 0x020>; | ||
| 415 | }; | ||
| 416 | |||
| 417 | DMA0: dma0@400100100 { | ||
| 418 | compatible = "ibm,dma-440spe"; | ||
| 419 | cell-index = <0>; | ||
| 420 | reg = <0x00000004 0x00100100 0x100>; | ||
| 421 | dcr-reg = <0x060 0x020>; | ||
| 422 | interrupt-parent = <&DMA0>; | ||
| 423 | interrupts = <0 1>; | ||
| 424 | #interrupt-cells = <1>; | ||
| 425 | #address-cells = <0>; | ||
| 426 | #size-cells = <0>; | ||
| 427 | interrupt-map = < | ||
| 428 | 0 &UIC0 0x14 4 | ||
| 429 | 1 &UIC1 0x16 4>; | ||
| 430 | }; | ||
| 431 | |||
| 432 | DMA1: dma1@400100200 { | ||
| 433 | compatible = "ibm,dma-440spe"; | ||
| 434 | cell-index = <1>; | ||
| 435 | reg = <0x00000004 0x00100200 0x100>; | ||
| 436 | dcr-reg = <0x060 0x020>; | ||
| 437 | interrupt-parent = <&DMA1>; | ||
| 438 | interrupts = <0 1>; | ||
| 439 | #interrupt-cells = <1>; | ||
| 440 | #address-cells = <0>; | ||
| 441 | #size-cells = <0>; | ||
| 442 | interrupt-map = < | ||
| 443 | 0 &UIC0 0x16 4 | ||
| 444 | 1 &UIC1 0x16 4>; | ||
| 445 | }; | ||
| 446 | |||
| 447 | xor-accel@400200000 { | ||
| 448 | compatible = "amcc,xor-accelerator"; | ||
| 449 | reg = <0x00000004 0x00200000 0x400>; | ||
| 450 | interrupt-parent = <&UIC1>; | ||
| 451 | interrupts = <0x1f 4>; | ||
| 452 | }; | ||
| 403 | }; | 453 | }; |
| 404 | 454 | ||
| 405 | chosen { | 455 | chosen { |
diff --git a/arch/powerpc/boot/dts/mpc8315erdb.dts b/arch/powerpc/boot/dts/mpc8315erdb.dts index 32e10f588c1d..8a3a4f3ef831 100644 --- a/arch/powerpc/boot/dts/mpc8315erdb.dts +++ b/arch/powerpc/boot/dts/mpc8315erdb.dts | |||
| @@ -204,6 +204,7 @@ | |||
| 204 | interrupt-parent = <&ipic>; | 204 | interrupt-parent = <&ipic>; |
| 205 | tbi-handle = <&tbi0>; | 205 | tbi-handle = <&tbi0>; |
| 206 | phy-handle = < &phy0 >; | 206 | phy-handle = < &phy0 >; |
| 207 | fsl,magic-packet; | ||
| 207 | 208 | ||
| 208 | mdio@520 { | 209 | mdio@520 { |
| 209 | #address-cells = <1>; | 210 | #address-cells = <1>; |
| @@ -246,6 +247,7 @@ | |||
| 246 | interrupt-parent = <&ipic>; | 247 | interrupt-parent = <&ipic>; |
| 247 | tbi-handle = <&tbi1>; | 248 | tbi-handle = <&tbi1>; |
| 248 | phy-handle = < &phy1 >; | 249 | phy-handle = < &phy1 >; |
| 250 | fsl,magic-packet; | ||
| 249 | 251 | ||
| 250 | mdio@520 { | 252 | mdio@520 { |
| 251 | #address-cells = <1>; | 253 | #address-cells = <1>; |
| @@ -309,6 +311,22 @@ | |||
| 309 | interrupt-parent = <&ipic>; | 311 | interrupt-parent = <&ipic>; |
| 310 | }; | 312 | }; |
| 311 | 313 | ||
| 314 | gtm1: timer@500 { | ||
| 315 | compatible = "fsl,mpc8315-gtm", "fsl,gtm"; | ||
| 316 | reg = <0x500 0x100>; | ||
| 317 | interrupts = <90 8 78 8 84 8 72 8>; | ||
| 318 | interrupt-parent = <&ipic>; | ||
| 319 | clock-frequency = <133333333>; | ||
| 320 | }; | ||
| 321 | |||
| 322 | timer@600 { | ||
| 323 | compatible = "fsl,mpc8315-gtm", "fsl,gtm"; | ||
| 324 | reg = <0x600 0x100>; | ||
| 325 | interrupts = <91 8 79 8 85 8 73 8>; | ||
| 326 | interrupt-parent = <&ipic>; | ||
| 327 | clock-frequency = <133333333>; | ||
| 328 | }; | ||
| 329 | |||
| 312 | /* IPIC | 330 | /* IPIC |
| 313 | * interrupts cell = <intr #, sense> | 331 | * interrupts cell = <intr #, sense> |
| 314 | * sense values match linux IORESOURCE_IRQ_* defines: | 332 | * sense values match linux IORESOURCE_IRQ_* defines: |
| @@ -337,6 +355,15 @@ | |||
| 337 | 0x59 0x8>; | 355 | 0x59 0x8>; |
| 338 | interrupt-parent = < &ipic >; | 356 | interrupt-parent = < &ipic >; |
| 339 | }; | 357 | }; |
| 358 | |||
| 359 | pmc: power@b00 { | ||
| 360 | compatible = "fsl,mpc8315-pmc", "fsl,mpc8313-pmc", | ||
| 361 | "fsl,mpc8349-pmc"; | ||
| 362 | reg = <0xb00 0x100 0xa00 0x100>; | ||
| 363 | interrupts = <80 8>; | ||
| 364 | interrupt-parent = <&ipic>; | ||
| 365 | fsl,mpc8313-wakeup-timer = <>m1>; | ||
| 366 | }; | ||
| 340 | }; | 367 | }; |
| 341 | 368 | ||
| 342 | pci0: pci@e0008500 { | 369 | pci0: pci@e0008500 { |
diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts index feeeb7f9d609..b53d1df11e2d 100644 --- a/arch/powerpc/boot/dts/mpc8349emitx.dts +++ b/arch/powerpc/boot/dts/mpc8349emitx.dts | |||
| @@ -63,6 +63,24 @@ | |||
| 63 | reg = <0x200 0x100>; | 63 | reg = <0x200 0x100>; |
| 64 | }; | 64 | }; |
| 65 | 65 | ||
| 66 | gpio1: gpio-controller@c00 { | ||
| 67 | #gpio-cells = <2>; | ||
| 68 | compatible = "fsl,mpc8349-gpio"; | ||
| 69 | reg = <0xc00 0x100>; | ||
| 70 | interrupts = <74 0x8>; | ||
| 71 | interrupt-parent = <&ipic>; | ||
| 72 | gpio-controller; | ||
| 73 | }; | ||
| 74 | |||
| 75 | gpio2: gpio-controller@d00 { | ||
| 76 | #gpio-cells = <2>; | ||
| 77 | compatible = "fsl,mpc8349-gpio"; | ||
| 78 | reg = <0xd00 0x100>; | ||
| 79 | interrupts = <75 0x8>; | ||
| 80 | interrupt-parent = <&ipic>; | ||
| 81 | gpio-controller; | ||
| 82 | }; | ||
| 83 | |||
| 66 | i2c@3000 { | 84 | i2c@3000 { |
| 67 | #address-cells = <1>; | 85 | #address-cells = <1>; |
| 68 | #size-cells = <0>; | 86 | #size-cells = <0>; |
| @@ -72,6 +90,12 @@ | |||
| 72 | interrupts = <14 0x8>; | 90 | interrupts = <14 0x8>; |
| 73 | interrupt-parent = <&ipic>; | 91 | interrupt-parent = <&ipic>; |
| 74 | dfsrr; | 92 | dfsrr; |
| 93 | |||
| 94 | eeprom: at24@50 { | ||
| 95 | compatible = "st-micro,24c256"; | ||
| 96 | reg = <0x50>; | ||
| 97 | }; | ||
| 98 | |||
| 75 | }; | 99 | }; |
| 76 | 100 | ||
| 77 | i2c@3100 { | 101 | i2c@3100 { |
| @@ -91,6 +115,25 @@ | |||
| 91 | interrupt-parent = <&ipic>; | 115 | interrupt-parent = <&ipic>; |
| 92 | }; | 116 | }; |
| 93 | 117 | ||
| 118 | pcf1: iexp@38 { | ||
| 119 | #gpio-cells = <2>; | ||
| 120 | compatible = "ti,pcf8574a"; | ||
| 121 | reg = <0x38>; | ||
| 122 | gpio-controller; | ||
| 123 | }; | ||
| 124 | |||
| 125 | pcf2: iexp@39 { | ||
| 126 | #gpio-cells = <2>; | ||
| 127 | compatible = "ti,pcf8574a"; | ||
| 128 | reg = <0x39>; | ||
| 129 | gpio-controller; | ||
| 130 | }; | ||
| 131 | |||
| 132 | spd: at24@51 { | ||
| 133 | compatible = "at24,spd"; | ||
| 134 | reg = <0x51>; | ||
| 135 | }; | ||
| 136 | |||
| 94 | mcu_pio: mcu@a { | 137 | mcu_pio: mcu@a { |
| 95 | #gpio-cells = <2>; | 138 | #gpio-cells = <2>; |
| 96 | compatible = "fsl,mc9s08qg8-mpc8349emitx", | 139 | compatible = "fsl,mc9s08qg8-mpc8349emitx", |
| @@ -275,6 +318,24 @@ | |||
| 275 | reg = <0x700 0x100>; | 318 | reg = <0x700 0x100>; |
| 276 | device_type = "ipic"; | 319 | device_type = "ipic"; |
| 277 | }; | 320 | }; |
| 321 | |||
| 322 | gpio-leds { | ||
| 323 | compatible = "gpio-leds"; | ||
| 324 | |||
| 325 | green { | ||
| 326 | label = "Green"; | ||
| 327 | gpios = <&pcf1 0 1>; | ||
| 328 | linux,default-trigger = "heartbeat"; | ||
| 329 | }; | ||
| 330 | |||
| 331 | yellow { | ||
| 332 | label = "Yellow"; | ||
| 333 | gpios = <&pcf1 1 1>; | ||
| 334 | /* linux,default-trigger = "heartbeat"; */ | ||
| 335 | default-state = "on"; | ||
| 336 | }; | ||
| 337 | }; | ||
| 338 | |||
| 278 | }; | 339 | }; |
| 279 | 340 | ||
| 280 | pci0: pci@e0008500 { | 341 | pci0: pci@e0008500 { |
| @@ -331,7 +392,26 @@ | |||
| 331 | compatible = "fsl,mpc8349e-localbus", | 392 | compatible = "fsl,mpc8349e-localbus", |
| 332 | "fsl,pq2pro-localbus"; | 393 | "fsl,pq2pro-localbus"; |
| 333 | reg = <0xe0005000 0xd8>; | 394 | reg = <0xe0005000 0xd8>; |
| 334 | ranges = <0x3 0x0 0xf0000000 0x210>; | 395 | ranges = <0x0 0x0 0xfe000000 0x1000000 /* flash */ |
| 396 | 0x1 0x0 0xf8000000 0x20000 /* VSC 7385 */ | ||
| 397 | 0x2 0x0 0xf9000000 0x200000 /* exp slot */ | ||
| 398 | 0x3 0x0 0xf0000000 0x210>; /* CF slot */ | ||
| 399 | |||
| 400 | flash@0,0 { | ||
| 401 | compatible = "cfi-flash"; | ||
| 402 | reg = <0x0 0x0 0x800000>; | ||
| 403 | bank-width = <2>; | ||
| 404 | device-width = <1>; | ||
| 405 | }; | ||
| 406 | |||
| 407 | flash@0,800000 { | ||
| 408 | #address-cells = <1>; | ||
| 409 | #size-cells = <1>; | ||
| 410 | compatible = "cfi-flash"; | ||
| 411 | reg = <0x0 0x800000 0x800000>; | ||
| 412 | bank-width = <2>; | ||
| 413 | device-width = <1>; | ||
| 414 | }; | ||
| 335 | 415 | ||
| 336 | pata@3,0 { | 416 | pata@3,0 { |
| 337 | compatible = "fsl,mpc8349emitx-pata", "ata-generic"; | 417 | compatible = "fsl,mpc8349emitx-pata", "ata-generic"; |
diff --git a/arch/powerpc/boot/dts/warp.dts b/arch/powerpc/boot/dts/warp.dts index 31605ee4afb6..e576ee85c42f 100644 --- a/arch/powerpc/boot/dts/warp.dts +++ b/arch/powerpc/boot/dts/warp.dts | |||
| @@ -146,7 +146,7 @@ | |||
| 146 | 146 | ||
| 147 | fpga@2,4000 { | 147 | fpga@2,4000 { |
| 148 | compatible = "pika,fpga-sd"; | 148 | compatible = "pika,fpga-sd"; |
| 149 | reg = <0x00000002 0x00004000 0x00000A00>; | 149 | reg = <0x00000002 0x00004000 0x00004000>; |
| 150 | }; | 150 | }; |
| 151 | 151 | ||
| 152 | nor@0,0 { | 152 | nor@0,0 { |
diff --git a/arch/powerpc/boot/ugecon.c b/arch/powerpc/boot/ugecon.c index 50609ea6ddf8..8f2a6b311534 100644 --- a/arch/powerpc/boot/ugecon.c +++ b/arch/powerpc/boot/ugecon.c | |||
| @@ -86,7 +86,7 @@ static void ug_putc(char ch) | |||
| 86 | 86 | ||
| 87 | while (!ug_is_txfifo_ready() && count--) | 87 | while (!ug_is_txfifo_ready() && count--) |
| 88 | barrier(); | 88 | barrier(); |
| 89 | if (count) | 89 | if (count >= 0) |
| 90 | ug_raw_putc(ch); | 90 | ug_raw_putc(ch); |
| 91 | } | 91 | } |
| 92 | 92 | ||
diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig index fc905924c022..826a65d3f002 100644 --- a/arch/powerpc/configs/g5_defconfig +++ b/arch/powerpc/configs/g5_defconfig | |||
| @@ -757,7 +757,7 @@ CONFIG_SUNGEM=y | |||
| 757 | # CONFIG_B44 is not set | 757 | # CONFIG_B44 is not set |
| 758 | # CONFIG_ATL2 is not set | 758 | # CONFIG_ATL2 is not set |
| 759 | CONFIG_NETDEV_1000=y | 759 | CONFIG_NETDEV_1000=y |
| 760 | CONFIG_ACENIC=y | 760 | CONFIG_ACENIC=m |
| 761 | CONFIG_ACENIC_OMIT_TIGON_I=y | 761 | CONFIG_ACENIC_OMIT_TIGON_I=y |
| 762 | # CONFIG_DL2K is not set | 762 | # CONFIG_DL2K is not set |
| 763 | CONFIG_E1000=y | 763 | CONFIG_E1000=y |
| @@ -794,8 +794,8 @@ CONFIG_NETDEV_10000=y | |||
| 794 | # CONFIG_BNX2X is not set | 794 | # CONFIG_BNX2X is not set |
| 795 | # CONFIG_QLGE is not set | 795 | # CONFIG_QLGE is not set |
| 796 | # CONFIG_SFC is not set | 796 | # CONFIG_SFC is not set |
| 797 | CONFIG_TR=y | 797 | # CONFIG_TR is not set |
| 798 | CONFIG_IBMOL=y | 798 | # CONFIG_IBMOL is not set |
| 799 | # CONFIG_3C359 is not set | 799 | # CONFIG_3C359 is not set |
| 800 | # CONFIG_TMS380TR is not set | 800 | # CONFIG_TMS380TR is not set |
| 801 | 801 | ||
diff --git a/arch/powerpc/configs/iseries_defconfig b/arch/powerpc/configs/iseries_defconfig index f925c555508e..76982c51a4c7 100644 --- a/arch/powerpc/configs/iseries_defconfig +++ b/arch/powerpc/configs/iseries_defconfig | |||
| @@ -714,8 +714,8 @@ CONFIG_NETDEV_10000=y | |||
| 714 | # CONFIG_BNX2X is not set | 714 | # CONFIG_BNX2X is not set |
| 715 | # CONFIG_QLGE is not set | 715 | # CONFIG_QLGE is not set |
| 716 | # CONFIG_SFC is not set | 716 | # CONFIG_SFC is not set |
| 717 | CONFIG_TR=y | 717 | # CONFIG_TR is not set |
| 718 | CONFIG_IBMOL=y | 718 | # CONFIG_IBMOL is not set |
| 719 | # CONFIG_3C359 is not set | 719 | # CONFIG_3C359 is not set |
| 720 | # CONFIG_TMS380TR is not set | 720 | # CONFIG_TMS380TR is not set |
| 721 | 721 | ||
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index 252401824575..7b3804a6e363 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig | |||
| @@ -304,11 +304,11 @@ CONFIG_TICK_ONESHOT=y | |||
| 304 | CONFIG_NO_HZ=y | 304 | CONFIG_NO_HZ=y |
| 305 | CONFIG_HIGH_RES_TIMERS=y | 305 | CONFIG_HIGH_RES_TIMERS=y |
| 306 | CONFIG_GENERIC_CLOCKEVENTS_BUILD=y | 306 | CONFIG_GENERIC_CLOCKEVENTS_BUILD=y |
| 307 | # CONFIG_HZ_100 is not set | 307 | CONFIG_HZ_100=y |
| 308 | CONFIG_HZ_250=y | 308 | # CONFIG_HZ_250 is not set |
| 309 | # CONFIG_HZ_300 is not set | 309 | # CONFIG_HZ_300 is not set |
| 310 | # CONFIG_HZ_1000 is not set | 310 | # CONFIG_HZ_1000 is not set |
| 311 | CONFIG_HZ=250 | 311 | CONFIG_HZ=100 |
| 312 | CONFIG_SCHED_HRTICK=y | 312 | CONFIG_SCHED_HRTICK=y |
| 313 | CONFIG_PREEMPT_NONE=y | 313 | CONFIG_PREEMPT_NONE=y |
| 314 | # CONFIG_PREEMPT_VOLUNTARY is not set | 314 | # CONFIG_PREEMPT_VOLUNTARY is not set |
| @@ -980,7 +980,7 @@ CONFIG_E100=y | |||
| 980 | # CONFIG_SC92031 is not set | 980 | # CONFIG_SC92031 is not set |
| 981 | # CONFIG_ATL2 is not set | 981 | # CONFIG_ATL2 is not set |
| 982 | CONFIG_NETDEV_1000=y | 982 | CONFIG_NETDEV_1000=y |
| 983 | CONFIG_ACENIC=y | 983 | CONFIG_ACENIC=m |
| 984 | CONFIG_ACENIC_OMIT_TIGON_I=y | 984 | CONFIG_ACENIC_OMIT_TIGON_I=y |
| 985 | # CONFIG_DL2K is not set | 985 | # CONFIG_DL2K is not set |
| 986 | CONFIG_E1000=y | 986 | CONFIG_E1000=y |
| @@ -1023,8 +1023,8 @@ CONFIG_PASEMI_MAC=y | |||
| 1023 | # CONFIG_BNX2X is not set | 1023 | # CONFIG_BNX2X is not set |
| 1024 | # CONFIG_QLGE is not set | 1024 | # CONFIG_QLGE is not set |
| 1025 | # CONFIG_SFC is not set | 1025 | # CONFIG_SFC is not set |
| 1026 | CONFIG_TR=y | 1026 | # CONFIG_TR is not set |
| 1027 | CONFIG_IBMOL=y | 1027 | # CONFIG_IBMOL is not set |
| 1028 | # CONFIG_3C359 is not set | 1028 | # CONFIG_3C359 is not set |
| 1029 | # CONFIG_TMS380TR is not set | 1029 | # CONFIG_TMS380TR is not set |
| 1030 | 1030 | ||
| @@ -1863,7 +1863,7 @@ CONFIG_HFSPLUS_FS=m | |||
| 1863 | # CONFIG_BEFS_FS is not set | 1863 | # CONFIG_BEFS_FS is not set |
| 1864 | # CONFIG_BFS_FS is not set | 1864 | # CONFIG_BFS_FS is not set |
| 1865 | # CONFIG_EFS_FS is not set | 1865 | # CONFIG_EFS_FS is not set |
| 1866 | CONFIG_CRAMFS=y | 1866 | CONFIG_CRAMFS=m |
| 1867 | # CONFIG_VXFS_FS is not set | 1867 | # CONFIG_VXFS_FS is not set |
| 1868 | # CONFIG_MINIX_FS is not set | 1868 | # CONFIG_MINIX_FS is not set |
| 1869 | # CONFIG_OMFS_FS is not set | 1869 | # CONFIG_OMFS_FS is not set |
diff --git a/arch/powerpc/configs/ppc64e_defconfig b/arch/powerpc/configs/ppc64e_defconfig index 18af46036258..8195f1650cbf 100644 --- a/arch/powerpc/configs/ppc64e_defconfig +++ b/arch/powerpc/configs/ppc64e_defconfig | |||
| @@ -1008,8 +1008,8 @@ CONFIG_IXGB=m | |||
| 1008 | # CONFIG_QLGE is not set | 1008 | # CONFIG_QLGE is not set |
| 1009 | # CONFIG_SFC is not set | 1009 | # CONFIG_SFC is not set |
| 1010 | # CONFIG_BE2NET is not set | 1010 | # CONFIG_BE2NET is not set |
| 1011 | CONFIG_TR=y | 1011 | # CONFIG_TR is not set |
| 1012 | CONFIG_IBMOL=y | 1012 | # CONFIG_IBMOL is not set |
| 1013 | # CONFIG_3C359 is not set | 1013 | # CONFIG_3C359 is not set |
| 1014 | # CONFIG_TMS380TR is not set | 1014 | # CONFIG_TMS380TR is not set |
| 1015 | CONFIG_WLAN=y | 1015 | CONFIG_WLAN=y |
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig index c568329723b8..ca9ff9aad74a 100644 --- a/arch/powerpc/configs/pseries_defconfig +++ b/arch/powerpc/configs/pseries_defconfig | |||
| @@ -230,11 +230,11 @@ CONFIG_TICK_ONESHOT=y | |||
| 230 | CONFIG_NO_HZ=y | 230 | CONFIG_NO_HZ=y |
| 231 | CONFIG_HIGH_RES_TIMERS=y | 231 | CONFIG_HIGH_RES_TIMERS=y |
| 232 | CONFIG_GENERIC_CLOCKEVENTS_BUILD=y | 232 | CONFIG_GENERIC_CLOCKEVENTS_BUILD=y |
| 233 | # CONFIG_HZ_100 is not set | 233 | CONFIG_HZ_100=y |
| 234 | CONFIG_HZ_250=y | 234 | # CONFIG_HZ_250 is not set |
| 235 | # CONFIG_HZ_300 is not set | 235 | # CONFIG_HZ_300 is not set |
| 236 | # CONFIG_HZ_1000 is not set | 236 | # CONFIG_HZ_1000 is not set |
| 237 | CONFIG_HZ=250 | 237 | CONFIG_HZ=100 |
| 238 | CONFIG_SCHED_HRTICK=y | 238 | CONFIG_SCHED_HRTICK=y |
| 239 | CONFIG_PREEMPT_NONE=y | 239 | CONFIG_PREEMPT_NONE=y |
| 240 | # CONFIG_PREEMPT_VOLUNTARY is not set | 240 | # CONFIG_PREEMPT_VOLUNTARY is not set |
| @@ -796,7 +796,7 @@ CONFIG_E100=y | |||
| 796 | # CONFIG_NET_POCKET is not set | 796 | # CONFIG_NET_POCKET is not set |
| 797 | # CONFIG_ATL2 is not set | 797 | # CONFIG_ATL2 is not set |
| 798 | CONFIG_NETDEV_1000=y | 798 | CONFIG_NETDEV_1000=y |
| 799 | CONFIG_ACENIC=y | 799 | CONFIG_ACENIC=m |
| 800 | CONFIG_ACENIC_OMIT_TIGON_I=y | 800 | CONFIG_ACENIC_OMIT_TIGON_I=y |
| 801 | # CONFIG_DL2K is not set | 801 | # CONFIG_DL2K is not set |
| 802 | CONFIG_E1000=y | 802 | CONFIG_E1000=y |
| @@ -834,8 +834,8 @@ CONFIG_S2IO=m | |||
| 834 | # CONFIG_BNX2X is not set | 834 | # CONFIG_BNX2X is not set |
| 835 | # CONFIG_QLGE is not set | 835 | # CONFIG_QLGE is not set |
| 836 | # CONFIG_SFC is not set | 836 | # CONFIG_SFC is not set |
| 837 | CONFIG_TR=y | 837 | # CONFIG_TR is not set |
| 838 | CONFIG_IBMOL=y | 838 | # CONFIG_IBMOL is not set |
| 839 | # CONFIG_3C359 is not set | 839 | # CONFIG_3C359 is not set |
| 840 | # CONFIG_TMS380TR is not set | 840 | # CONFIG_TMS380TR is not set |
| 841 | 841 | ||
| @@ -1494,7 +1494,7 @@ CONFIG_CONFIGFS_FS=m | |||
| 1494 | # CONFIG_BEFS_FS is not set | 1494 | # CONFIG_BEFS_FS is not set |
| 1495 | # CONFIG_BFS_FS is not set | 1495 | # CONFIG_BFS_FS is not set |
| 1496 | # CONFIG_EFS_FS is not set | 1496 | # CONFIG_EFS_FS is not set |
| 1497 | CONFIG_CRAMFS=y | 1497 | CONFIG_CRAMFS=m |
| 1498 | # CONFIG_VXFS_FS is not set | 1498 | # CONFIG_VXFS_FS is not set |
| 1499 | # CONFIG_MINIX_FS is not set | 1499 | # CONFIG_MINIX_FS is not set |
| 1500 | # CONFIG_OMFS_FS is not set | 1500 | # CONFIG_OMFS_FS is not set |
diff --git a/arch/powerpc/include/asm/bug.h b/arch/powerpc/include/asm/bug.h index 64e1fdca233e..2c15212e1700 100644 --- a/arch/powerpc/include/asm/bug.h +++ b/arch/powerpc/include/asm/bug.h | |||
| @@ -68,7 +68,7 @@ | |||
| 68 | _EMIT_BUG_ENTRY \ | 68 | _EMIT_BUG_ENTRY \ |
| 69 | : : "i" (__FILE__), "i" (__LINE__), \ | 69 | : : "i" (__FILE__), "i" (__LINE__), \ |
| 70 | "i" (0), "i" (sizeof(struct bug_entry))); \ | 70 | "i" (0), "i" (sizeof(struct bug_entry))); \ |
| 71 | for(;;) ; \ | 71 | unreachable(); \ |
| 72 | } while (0) | 72 | } while (0) |
| 73 | 73 | ||
| 74 | #define BUG_ON(x) do { \ | 74 | #define BUG_ON(x) do { \ |
diff --git a/arch/powerpc/include/asm/gpio.h b/arch/powerpc/include/asm/gpio.h index ea04632399d8..38762edb5e58 100644 --- a/arch/powerpc/include/asm/gpio.h +++ b/arch/powerpc/include/asm/gpio.h | |||
| @@ -38,12 +38,9 @@ static inline int gpio_cansleep(unsigned int gpio) | |||
| 38 | return __gpio_cansleep(gpio); | 38 | return __gpio_cansleep(gpio); |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | /* | ||
| 42 | * Not implemented, yet. | ||
| 43 | */ | ||
| 44 | static inline int gpio_to_irq(unsigned int gpio) | 41 | static inline int gpio_to_irq(unsigned int gpio) |
| 45 | { | 42 | { |
| 46 | return -ENOSYS; | 43 | return __gpio_to_irq(gpio); |
| 47 | } | 44 | } |
| 48 | 45 | ||
| 49 | static inline int irq_to_gpio(unsigned int irq) | 46 | static inline int irq_to_gpio(unsigned int irq) |
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c index 3839839f83c7..b876e989220b 100644 --- a/arch/powerpc/kernel/align.c +++ b/arch/powerpc/kernel/align.c | |||
| @@ -642,10 +642,14 @@ static int emulate_spe(struct pt_regs *regs, unsigned int reg, | |||
| 642 | */ | 642 | */ |
| 643 | static int emulate_vsx(unsigned char __user *addr, unsigned int reg, | 643 | static int emulate_vsx(unsigned char __user *addr, unsigned int reg, |
| 644 | unsigned int areg, struct pt_regs *regs, | 644 | unsigned int areg, struct pt_regs *regs, |
| 645 | unsigned int flags, unsigned int length) | 645 | unsigned int flags, unsigned int length, |
| 646 | unsigned int elsize) | ||
| 646 | { | 647 | { |
| 647 | char *ptr; | 648 | char *ptr; |
| 649 | unsigned long *lptr; | ||
| 648 | int ret = 0; | 650 | int ret = 0; |
| 651 | int sw = 0; | ||
| 652 | int i, j; | ||
| 649 | 653 | ||
| 650 | flush_vsx_to_thread(current); | 654 | flush_vsx_to_thread(current); |
| 651 | 655 | ||
| @@ -654,19 +658,35 @@ static int emulate_vsx(unsigned char __user *addr, unsigned int reg, | |||
| 654 | else | 658 | else |
| 655 | ptr = (char *) ¤t->thread.vr[reg - 32]; | 659 | ptr = (char *) ¤t->thread.vr[reg - 32]; |
| 656 | 660 | ||
| 657 | if (flags & ST) | 661 | lptr = (unsigned long *) ptr; |
| 658 | ret = __copy_to_user(addr, ptr, length); | 662 | |
| 659 | else { | 663 | if (flags & SW) |
| 660 | if (flags & SPLT){ | 664 | sw = elsize-1; |
| 661 | ret = __copy_from_user(ptr, addr, length); | 665 | |
| 662 | ptr += length; | 666 | for (j = 0; j < length; j += elsize) { |
| 667 | for (i = 0; i < elsize; ++i) { | ||
| 668 | if (flags & ST) | ||
| 669 | ret |= __put_user(ptr[i^sw], addr + i); | ||
| 670 | else | ||
| 671 | ret |= __get_user(ptr[i^sw], addr + i); | ||
| 663 | } | 672 | } |
| 664 | ret |= __copy_from_user(ptr, addr, length); | 673 | ptr += elsize; |
| 674 | addr += elsize; | ||
| 665 | } | 675 | } |
| 666 | if (flags & U) | 676 | |
| 667 | regs->gpr[areg] = regs->dar; | 677 | if (!ret) { |
| 668 | if (ret) | 678 | if (flags & U) |
| 679 | regs->gpr[areg] = regs->dar; | ||
| 680 | |||
| 681 | /* Splat load copies the same data to top and bottom 8 bytes */ | ||
| 682 | if (flags & SPLT) | ||
| 683 | lptr[1] = lptr[0]; | ||
| 684 | /* For 8 byte loads, zero the top 8 bytes */ | ||
| 685 | else if (!(flags & ST) && (8 == length)) | ||
| 686 | lptr[1] = 0; | ||
| 687 | } else | ||
| 669 | return -EFAULT; | 688 | return -EFAULT; |
| 689 | |||
| 670 | return 1; | 690 | return 1; |
| 671 | } | 691 | } |
| 672 | #endif | 692 | #endif |
| @@ -767,16 +787,25 @@ int fix_alignment(struct pt_regs *regs) | |||
| 767 | 787 | ||
| 768 | #ifdef CONFIG_VSX | 788 | #ifdef CONFIG_VSX |
| 769 | if ((instruction & 0xfc00003e) == 0x7c000018) { | 789 | if ((instruction & 0xfc00003e) == 0x7c000018) { |
| 770 | /* Additional register addressing bit (64 VSX vs 32 FPR/GPR */ | 790 | unsigned int elsize; |
| 791 | |||
| 792 | /* Additional register addressing bit (64 VSX vs 32 FPR/GPR) */ | ||
| 771 | reg |= (instruction & 0x1) << 5; | 793 | reg |= (instruction & 0x1) << 5; |
| 772 | /* Simple inline decoder instead of a table */ | 794 | /* Simple inline decoder instead of a table */ |
| 795 | /* VSX has only 8 and 16 byte memory accesses */ | ||
| 796 | nb = 8; | ||
| 773 | if (instruction & 0x200) | 797 | if (instruction & 0x200) |
| 774 | nb = 16; | 798 | nb = 16; |
| 775 | else if (instruction & 0x080) | 799 | |
| 776 | nb = 8; | 800 | /* Vector stores in little-endian mode swap individual |
| 777 | else | 801 | elements, so process them separately */ |
| 778 | nb = 4; | 802 | elsize = 4; |
| 803 | if (instruction & 0x80) | ||
| 804 | elsize = 8; | ||
| 805 | |||
| 779 | flags = 0; | 806 | flags = 0; |
| 807 | if (regs->msr & MSR_LE) | ||
| 808 | flags |= SW; | ||
| 780 | if (instruction & 0x100) | 809 | if (instruction & 0x100) |
| 781 | flags |= ST; | 810 | flags |= ST; |
| 782 | if (instruction & 0x040) | 811 | if (instruction & 0x040) |
| @@ -787,7 +816,7 @@ int fix_alignment(struct pt_regs *regs) | |||
| 787 | nb = 8; | 816 | nb = 8; |
| 788 | } | 817 | } |
| 789 | PPC_WARN_ALIGNMENT(vsx, regs); | 818 | PPC_WARN_ALIGNMENT(vsx, regs); |
| 790 | return emulate_vsx(addr, reg, areg, regs, flags, nb); | 819 | return emulate_vsx(addr, reg, areg, regs, flags, nb, elsize); |
| 791 | } | 820 | } |
| 792 | #endif | 821 | #endif |
| 793 | /* A size of 0 indicates an instruction we don't support, with | 822 | /* A size of 0 indicates an instruction we don't support, with |
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 50f867d657df..3ecdcec0a39e 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
| @@ -340,7 +340,7 @@ static int __init htab_dt_scan_page_sizes(unsigned long node, | |||
| 340 | else | 340 | else |
| 341 | def->tlbiel = 0; | 341 | def->tlbiel = 0; |
| 342 | 342 | ||
| 343 | DBG(" %d: shift=%02x, sllp=%04x, avpnm=%08x, " | 343 | DBG(" %d: shift=%02x, sllp=%04lx, avpnm=%08lx, " |
| 344 | "tlbiel=%d, penc=%d\n", | 344 | "tlbiel=%d, penc=%d\n", |
| 345 | idx, shift, def->sllp, def->avpnm, def->tlbiel, | 345 | idx, shift, def->sllp, def->avpnm, def->tlbiel, |
| 346 | def->penc); | 346 | def->penc); |
| @@ -663,7 +663,7 @@ static void __init htab_initialize(void) | |||
| 663 | base = (unsigned long)__va(lmb.memory.region[i].base); | 663 | base = (unsigned long)__va(lmb.memory.region[i].base); |
| 664 | size = lmb.memory.region[i].size; | 664 | size = lmb.memory.region[i].size; |
| 665 | 665 | ||
| 666 | DBG("creating mapping for region: %lx..%lx (prot: %x)\n", | 666 | DBG("creating mapping for region: %lx..%lx (prot: %lx)\n", |
| 667 | base, size, prot); | 667 | base, size, prot); |
| 668 | 668 | ||
| 669 | #ifdef CONFIG_U3_DART | 669 | #ifdef CONFIG_U3_DART |
| @@ -879,7 +879,7 @@ static inline int subpage_protection(struct mm_struct *mm, unsigned long ea) | |||
| 879 | */ | 879 | */ |
| 880 | int hash_page(unsigned long ea, unsigned long access, unsigned long trap) | 880 | int hash_page(unsigned long ea, unsigned long access, unsigned long trap) |
| 881 | { | 881 | { |
| 882 | void *pgdir; | 882 | pgd_t *pgdir; |
| 883 | unsigned long vsid; | 883 | unsigned long vsid; |
| 884 | struct mm_struct *mm; | 884 | struct mm_struct *mm; |
| 885 | pte_t *ptep; | 885 | pte_t *ptep; |
| @@ -1025,7 +1025,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) | |||
| 1025 | else | 1025 | else |
| 1026 | #endif /* CONFIG_PPC_HAS_HASH_64K */ | 1026 | #endif /* CONFIG_PPC_HAS_HASH_64K */ |
| 1027 | { | 1027 | { |
| 1028 | int spp = subpage_protection(pgdir, ea); | 1028 | int spp = subpage_protection(mm, ea); |
| 1029 | if (access & spp) | 1029 | if (access & spp) |
| 1030 | rc = -2; | 1030 | rc = -2; |
| 1031 | else | 1031 | else |
| @@ -1115,7 +1115,7 @@ void flush_hash_page(unsigned long va, real_pte_t pte, int psize, int ssize, | |||
| 1115 | { | 1115 | { |
| 1116 | unsigned long hash, index, shift, hidx, slot; | 1116 | unsigned long hash, index, shift, hidx, slot; |
| 1117 | 1117 | ||
| 1118 | DBG_LOW("flush_hash_page(va=%016x)\n", va); | 1118 | DBG_LOW("flush_hash_page(va=%016lx)\n", va); |
| 1119 | pte_iterate_hashed_subpages(pte, psize, va, index, shift) { | 1119 | pte_iterate_hashed_subpages(pte, psize, va, index, shift) { |
| 1120 | hash = hpt_hash(va, shift, ssize); | 1120 | hash = hpt_hash(va, shift, ssize); |
| 1121 | hidx = __rpte_to_hidx(pte, index); | 1121 | hidx = __rpte_to_hidx(pte, index); |
| @@ -1123,7 +1123,7 @@ void flush_hash_page(unsigned long va, real_pte_t pte, int psize, int ssize, | |||
| 1123 | hash = ~hash; | 1123 | hash = ~hash; |
| 1124 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; | 1124 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; |
| 1125 | slot += hidx & _PTEIDX_GROUP_IX; | 1125 | slot += hidx & _PTEIDX_GROUP_IX; |
| 1126 | DBG_LOW(" sub %d: hash=%x, hidx=%x\n", index, slot, hidx); | 1126 | DBG_LOW(" sub %ld: hash=%lx, hidx=%lx\n", index, slot, hidx); |
| 1127 | ppc_md.hpte_invalidate(slot, va, psize, ssize, local); | 1127 | ppc_md.hpte_invalidate(slot, va, psize, ssize, local); |
| 1128 | } pte_iterate_hashed_end(); | 1128 | } pte_iterate_hashed_end(); |
| 1129 | } | 1129 | } |
diff --git a/arch/powerpc/mm/mmu_context_nohash.c b/arch/powerpc/mm/mmu_context_nohash.c index be4f34c30a0b..1044a634b6d0 100644 --- a/arch/powerpc/mm/mmu_context_nohash.c +++ b/arch/powerpc/mm/mmu_context_nohash.c | |||
| @@ -353,7 +353,7 @@ static int __cpuinit mmu_context_cpu_notify(struct notifier_block *self, | |||
| 353 | read_lock(&tasklist_lock); | 353 | read_lock(&tasklist_lock); |
| 354 | for_each_process(p) { | 354 | for_each_process(p) { |
| 355 | if (p->mm) | 355 | if (p->mm) |
| 356 | cpu_mask_clear_cpu(cpu, mm_cpumask(p->mm)); | 356 | cpumask_clear_cpu(cpu, mm_cpumask(p->mm)); |
| 357 | } | 357 | } |
| 358 | read_unlock(&tasklist_lock); | 358 | read_unlock(&tasklist_lock); |
| 359 | break; | 359 | break; |
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index 177e4038b43c..573b3bd1c45b 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c | |||
| @@ -382,7 +382,7 @@ static int __change_page_attr(struct page *page, pgprot_t prot) | |||
| 382 | return 0; | 382 | return 0; |
| 383 | if (!get_pteptr(&init_mm, address, &kpte, &kpmd)) | 383 | if (!get_pteptr(&init_mm, address, &kpte, &kpmd)) |
| 384 | return -EINVAL; | 384 | return -EINVAL; |
| 385 | set_pte_at(&init_mm, address, kpte, mk_pte(page, prot)); | 385 | __set_pte_at(&init_mm, address, kpte, mk_pte(page, prot), 0); |
| 386 | wmb(); | 386 | wmb(); |
| 387 | #ifdef CONFIG_PPC_STD_MMU | 387 | #ifdef CONFIG_PPC_STD_MMU |
| 388 | flush_hash_pages(0, address, pmd_val(*kpmd), 1); | 388 | flush_hash_pages(0, address, pmd_val(*kpmd), 1); |
diff --git a/arch/powerpc/platforms/83xx/suspend.c b/arch/powerpc/platforms/83xx/suspend.c index d306f07b9aa1..43805348b81e 100644 --- a/arch/powerpc/platforms/83xx/suspend.c +++ b/arch/powerpc/platforms/83xx/suspend.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #define PMCCR1_NEXT_STATE 0x0C /* Next state for power management */ | 32 | #define PMCCR1_NEXT_STATE 0x0C /* Next state for power management */ |
| 33 | #define PMCCR1_NEXT_STATE_SHIFT 2 | 33 | #define PMCCR1_NEXT_STATE_SHIFT 2 |
| 34 | #define PMCCR1_CURR_STATE 0x03 /* Current state for power management*/ | 34 | #define PMCCR1_CURR_STATE 0x03 /* Current state for power management*/ |
| 35 | #define IMMR_SYSCR_OFFSET 0x100 | ||
| 35 | #define IMMR_RCW_OFFSET 0x900 | 36 | #define IMMR_RCW_OFFSET 0x900 |
| 36 | #define RCW_PCI_HOST 0x80000000 | 37 | #define RCW_PCI_HOST 0x80000000 |
| 37 | 38 | ||
| @@ -78,6 +79,22 @@ struct mpc83xx_clock { | |||
| 78 | u32 sccr; | 79 | u32 sccr; |
| 79 | }; | 80 | }; |
| 80 | 81 | ||
| 82 | struct mpc83xx_syscr { | ||
| 83 | __be32 sgprl; | ||
| 84 | __be32 sgprh; | ||
| 85 | __be32 spridr; | ||
| 86 | __be32 :32; | ||
| 87 | __be32 spcr; | ||
| 88 | __be32 sicrl; | ||
| 89 | __be32 sicrh; | ||
| 90 | }; | ||
| 91 | |||
| 92 | struct mpc83xx_saved { | ||
| 93 | u32 sicrl; | ||
| 94 | u32 sicrh; | ||
| 95 | u32 sccr; | ||
| 96 | }; | ||
| 97 | |||
| 81 | struct pmc_type { | 98 | struct pmc_type { |
| 82 | int has_deep_sleep; | 99 | int has_deep_sleep; |
| 83 | }; | 100 | }; |
| @@ -87,6 +104,8 @@ static int has_deep_sleep, deep_sleeping; | |||
| 87 | static int pmc_irq; | 104 | static int pmc_irq; |
| 88 | static struct mpc83xx_pmc __iomem *pmc_regs; | 105 | static struct mpc83xx_pmc __iomem *pmc_regs; |
| 89 | static struct mpc83xx_clock __iomem *clock_regs; | 106 | static struct mpc83xx_clock __iomem *clock_regs; |
| 107 | static struct mpc83xx_syscr __iomem *syscr_regs; | ||
| 108 | static struct mpc83xx_saved saved_regs; | ||
| 90 | static int is_pci_agent, wake_from_pci; | 109 | static int is_pci_agent, wake_from_pci; |
| 91 | static phys_addr_t immrbase; | 110 | static phys_addr_t immrbase; |
| 92 | static int pci_pm_state; | 111 | static int pci_pm_state; |
| @@ -137,6 +156,20 @@ static irqreturn_t pmc_irq_handler(int irq, void *dev_id) | |||
| 137 | return ret; | 156 | return ret; |
| 138 | } | 157 | } |
| 139 | 158 | ||
| 159 | static void mpc83xx_suspend_restore_regs(void) | ||
| 160 | { | ||
| 161 | out_be32(&syscr_regs->sicrl, saved_regs.sicrl); | ||
| 162 | out_be32(&syscr_regs->sicrh, saved_regs.sicrh); | ||
| 163 | out_be32(&clock_regs->sccr, saved_regs.sccr); | ||
| 164 | } | ||
| 165 | |||
| 166 | static void mpc83xx_suspend_save_regs(void) | ||
| 167 | { | ||
| 168 | saved_regs.sicrl = in_be32(&syscr_regs->sicrl); | ||
| 169 | saved_regs.sicrh = in_be32(&syscr_regs->sicrh); | ||
| 170 | saved_regs.sccr = in_be32(&clock_regs->sccr); | ||
| 171 | } | ||
| 172 | |||
| 140 | static int mpc83xx_suspend_enter(suspend_state_t state) | 173 | static int mpc83xx_suspend_enter(suspend_state_t state) |
| 141 | { | 174 | { |
| 142 | int ret = -EAGAIN; | 175 | int ret = -EAGAIN; |
| @@ -166,6 +199,8 @@ static int mpc83xx_suspend_enter(suspend_state_t state) | |||
| 166 | */ | 199 | */ |
| 167 | 200 | ||
| 168 | if (deep_sleeping) { | 201 | if (deep_sleeping) { |
| 202 | mpc83xx_suspend_save_regs(); | ||
| 203 | |||
| 169 | out_be32(&pmc_regs->mask, PMCER_ALL); | 204 | out_be32(&pmc_regs->mask, PMCER_ALL); |
| 170 | 205 | ||
| 171 | out_be32(&pmc_regs->config1, | 206 | out_be32(&pmc_regs->config1, |
| @@ -179,6 +214,8 @@ static int mpc83xx_suspend_enter(suspend_state_t state) | |||
| 179 | in_be32(&pmc_regs->config1) & ~PMCCR1_POWER_OFF); | 214 | in_be32(&pmc_regs->config1) & ~PMCCR1_POWER_OFF); |
| 180 | 215 | ||
| 181 | out_be32(&pmc_regs->mask, PMCER_PMCI); | 216 | out_be32(&pmc_regs->mask, PMCER_PMCI); |
| 217 | |||
| 218 | mpc83xx_suspend_restore_regs(); | ||
| 182 | } else { | 219 | } else { |
| 183 | out_be32(&pmc_regs->mask, PMCER_PMCI); | 220 | out_be32(&pmc_regs->mask, PMCER_PMCI); |
| 184 | 221 | ||
| @@ -194,7 +231,7 @@ out: | |||
| 194 | return ret; | 231 | return ret; |
| 195 | } | 232 | } |
| 196 | 233 | ||
| 197 | static void mpc83xx_suspend_finish(void) | 234 | static void mpc83xx_suspend_end(void) |
| 198 | { | 235 | { |
| 199 | deep_sleeping = 0; | 236 | deep_sleeping = 0; |
| 200 | } | 237 | } |
| @@ -278,7 +315,7 @@ static struct platform_suspend_ops mpc83xx_suspend_ops = { | |||
| 278 | .valid = mpc83xx_suspend_valid, | 315 | .valid = mpc83xx_suspend_valid, |
| 279 | .begin = mpc83xx_suspend_begin, | 316 | .begin = mpc83xx_suspend_begin, |
| 280 | .enter = mpc83xx_suspend_enter, | 317 | .enter = mpc83xx_suspend_enter, |
| 281 | .finish = mpc83xx_suspend_finish, | 318 | .end = mpc83xx_suspend_end, |
| 282 | }; | 319 | }; |
| 283 | 320 | ||
| 284 | static int pmc_probe(struct of_device *ofdev, | 321 | static int pmc_probe(struct of_device *ofdev, |
| @@ -333,12 +370,23 @@ static int pmc_probe(struct of_device *ofdev, | |||
| 333 | goto out_pmc; | 370 | goto out_pmc; |
| 334 | } | 371 | } |
| 335 | 372 | ||
| 373 | if (has_deep_sleep) { | ||
| 374 | syscr_regs = ioremap(immrbase + IMMR_SYSCR_OFFSET, | ||
| 375 | sizeof(*syscr_regs)); | ||
| 376 | if (!syscr_regs) { | ||
| 377 | ret = -ENOMEM; | ||
| 378 | goto out_syscr; | ||
| 379 | } | ||
| 380 | } | ||
| 381 | |||
| 336 | if (is_pci_agent) | 382 | if (is_pci_agent) |
| 337 | mpc83xx_set_agent(); | 383 | mpc83xx_set_agent(); |
| 338 | 384 | ||
| 339 | suspend_set_ops(&mpc83xx_suspend_ops); | 385 | suspend_set_ops(&mpc83xx_suspend_ops); |
| 340 | return 0; | 386 | return 0; |
| 341 | 387 | ||
| 388 | out_syscr: | ||
| 389 | iounmap(clock_regs); | ||
| 342 | out_pmc: | 390 | out_pmc: |
| 343 | iounmap(pmc_regs); | 391 | iounmap(pmc_regs); |
| 344 | out: | 392 | out: |
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index c5028a2e5a58..21f61b8c445b 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c | |||
| @@ -86,7 +86,7 @@ static int mpc8568_fixup_125_clock(struct phy_device *phydev) | |||
| 86 | scr = phy_read(phydev, MV88E1111_SCR); | 86 | scr = phy_read(phydev, MV88E1111_SCR); |
| 87 | 87 | ||
| 88 | if (scr < 0) | 88 | if (scr < 0) |
| 89 | return err; | 89 | return scr; |
| 90 | 90 | ||
| 91 | err = phy_write(phydev, MV88E1111_SCR, scr | 0x0008); | 91 | err = phy_write(phydev, MV88E1111_SCR, scr | 0x0008); |
| 92 | 92 | ||
diff --git a/arch/powerpc/platforms/embedded6xx/flipper-pic.c b/arch/powerpc/platforms/embedded6xx/flipper-pic.c index d5963285e3be..c278bd3a8fec 100644 --- a/arch/powerpc/platforms/embedded6xx/flipper-pic.c +++ b/arch/powerpc/platforms/embedded6xx/flipper-pic.c | |||
| @@ -102,7 +102,7 @@ static int flipper_pic_map(struct irq_host *h, unsigned int virq, | |||
| 102 | irq_hw_number_t hwirq) | 102 | irq_hw_number_t hwirq) |
| 103 | { | 103 | { |
| 104 | set_irq_chip_data(virq, h->host_data); | 104 | set_irq_chip_data(virq, h->host_data); |
| 105 | get_irq_desc(virq)->status |= IRQ_LEVEL; | 105 | irq_to_desc(virq)->status |= IRQ_LEVEL; |
| 106 | set_irq_chip_and_handler(virq, &flipper_pic, handle_level_irq); | 106 | set_irq_chip_and_handler(virq, &flipper_pic, handle_level_irq); |
| 107 | return 0; | 107 | return 0; |
| 108 | } | 108 | } |
diff --git a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c index dd20bff33207..a771f91e215b 100644 --- a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c +++ b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c | |||
| @@ -95,7 +95,7 @@ static int hlwd_pic_map(struct irq_host *h, unsigned int virq, | |||
| 95 | irq_hw_number_t hwirq) | 95 | irq_hw_number_t hwirq) |
| 96 | { | 96 | { |
| 97 | set_irq_chip_data(virq, h->host_data); | 97 | set_irq_chip_data(virq, h->host_data); |
| 98 | get_irq_desc(virq)->status |= IRQ_LEVEL; | 98 | irq_to_desc(virq)->status |= IRQ_LEVEL; |
| 99 | set_irq_chip_and_handler(virq, &hlwd_pic, handle_level_irq); | 99 | set_irq_chip_and_handler(virq, &hlwd_pic, handle_level_irq); |
| 100 | return 0; | 100 | return 0; |
| 101 | } | 101 | } |
| @@ -132,9 +132,9 @@ static void hlwd_pic_irq_cascade(unsigned int cascade_virq, | |||
| 132 | struct irq_host *irq_host = get_irq_data(cascade_virq); | 132 | struct irq_host *irq_host = get_irq_data(cascade_virq); |
| 133 | unsigned int virq; | 133 | unsigned int virq; |
| 134 | 134 | ||
| 135 | spin_lock(&desc->lock); | 135 | raw_spin_lock(&desc->lock); |
| 136 | desc->chip->mask(cascade_virq); /* IRQ_LEVEL */ | 136 | desc->chip->mask(cascade_virq); /* IRQ_LEVEL */ |
| 137 | spin_unlock(&desc->lock); | 137 | raw_spin_unlock(&desc->lock); |
| 138 | 138 | ||
| 139 | virq = __hlwd_pic_get_irq(irq_host); | 139 | virq = __hlwd_pic_get_irq(irq_host); |
| 140 | if (virq != NO_IRQ) | 140 | if (virq != NO_IRQ) |
| @@ -142,11 +142,11 @@ static void hlwd_pic_irq_cascade(unsigned int cascade_virq, | |||
| 142 | else | 142 | else |
| 143 | pr_err("spurious interrupt!\n"); | 143 | pr_err("spurious interrupt!\n"); |
| 144 | 144 | ||
| 145 | spin_lock(&desc->lock); | 145 | raw_spin_lock(&desc->lock); |
| 146 | desc->chip->ack(cascade_virq); /* IRQ_LEVEL */ | 146 | desc->chip->ack(cascade_virq); /* IRQ_LEVEL */ |
| 147 | if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask) | 147 | if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask) |
| 148 | desc->chip->unmask(cascade_virq); | 148 | desc->chip->unmask(cascade_virq); |
| 149 | spin_unlock(&desc->lock); | 149 | raw_spin_unlock(&desc->lock); |
| 150 | } | 150 | } |
| 151 | 151 | ||
| 152 | /* | 152 | /* |
diff --git a/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c b/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c index edc956cc8b13..20a8ed91962e 100644 --- a/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c +++ b/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c | |||
| @@ -120,7 +120,7 @@ static void ug_putc(char ch) | |||
| 120 | 120 | ||
| 121 | while (!ug_is_txfifo_ready() && count--) | 121 | while (!ug_is_txfifo_ready() && count--) |
| 122 | barrier(); | 122 | barrier(); |
| 123 | if (count) | 123 | if (count >= 0) |
| 124 | ug_raw_putc(ch); | 124 | ug_raw_putc(ch); |
| 125 | } | 125 | } |
| 126 | 126 | ||
diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index 0d9343df35bc..6617915bcb1a 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c | |||
| @@ -855,59 +855,58 @@ static int mf_get_boot_rtc(struct rtc_time *tm) | |||
| 855 | } | 855 | } |
| 856 | 856 | ||
| 857 | #ifdef CONFIG_PROC_FS | 857 | #ifdef CONFIG_PROC_FS |
| 858 | 858 | static int mf_cmdline_proc_show(struct seq_file *m, void *v) | |
| 859 | static int proc_mf_dump_cmdline(char *page, char **start, off_t off, | ||
| 860 | int count, int *eof, void *data) | ||
| 861 | { | 859 | { |
| 862 | int len; | 860 | char *page, *p; |
| 863 | char *p; | ||
| 864 | struct vsp_cmd_data vsp_cmd; | 861 | struct vsp_cmd_data vsp_cmd; |
| 865 | int rc; | 862 | int rc; |
| 866 | dma_addr_t dma_addr; | 863 | dma_addr_t dma_addr; |
| 867 | 864 | ||
| 868 | /* The HV appears to return no more than 256 bytes of command line */ | 865 | /* The HV appears to return no more than 256 bytes of command line */ |
| 869 | if (off >= 256) | 866 | page = kmalloc(256, GFP_KERNEL); |
| 870 | return 0; | 867 | if (!page) |
| 871 | if ((off + count) > 256) | 868 | return -ENOMEM; |
| 872 | count = 256 - off; | ||
| 873 | 869 | ||
| 874 | dma_addr = iseries_hv_map(page, off + count, DMA_FROM_DEVICE); | 870 | dma_addr = iseries_hv_map(page, 256, DMA_FROM_DEVICE); |
| 875 | if (dma_addr == DMA_ERROR_CODE) | 871 | if (dma_addr == DMA_ERROR_CODE) { |
| 872 | kfree(page); | ||
| 876 | return -ENOMEM; | 873 | return -ENOMEM; |
| 877 | memset(page, 0, off + count); | 874 | } |
| 875 | memset(page, 0, 256); | ||
| 878 | memset(&vsp_cmd, 0, sizeof(vsp_cmd)); | 876 | memset(&vsp_cmd, 0, sizeof(vsp_cmd)); |
| 879 | vsp_cmd.cmd = 33; | 877 | vsp_cmd.cmd = 33; |
| 880 | vsp_cmd.sub_data.kern.token = dma_addr; | 878 | vsp_cmd.sub_data.kern.token = dma_addr; |
| 881 | vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex; | 879 | vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex; |
| 882 | vsp_cmd.sub_data.kern.side = (u64)data; | 880 | vsp_cmd.sub_data.kern.side = (u64)m->private; |
| 883 | vsp_cmd.sub_data.kern.length = off + count; | 881 | vsp_cmd.sub_data.kern.length = 256; |
| 884 | mb(); | 882 | mb(); |
| 885 | rc = signal_vsp_instruction(&vsp_cmd); | 883 | rc = signal_vsp_instruction(&vsp_cmd); |
| 886 | iseries_hv_unmap(dma_addr, off + count, DMA_FROM_DEVICE); | 884 | iseries_hv_unmap(dma_addr, 256, DMA_FROM_DEVICE); |
| 887 | if (rc) | 885 | if (rc) { |
| 886 | kfree(page); | ||
| 888 | return rc; | 887 | return rc; |
| 889 | if (vsp_cmd.result_code != 0) | 888 | } |
| 889 | if (vsp_cmd.result_code != 0) { | ||
| 890 | kfree(page); | ||
| 890 | return -ENOMEM; | 891 | return -ENOMEM; |
| 892 | } | ||
| 891 | p = page; | 893 | p = page; |
| 892 | len = 0; | 894 | while (p - page < 256) { |
| 893 | while (len < (off + count)) { | 895 | if (*p == '\0' || *p == '\n') { |
| 894 | if ((*p == '\0') || (*p == '\n')) { | 896 | *p = '\n'; |
| 895 | if (*p == '\0') | ||
| 896 | *p = '\n'; | ||
| 897 | p++; | ||
| 898 | len++; | ||
| 899 | *eof = 1; | ||
| 900 | break; | 897 | break; |
| 901 | } | 898 | } |
| 902 | p++; | 899 | p++; |
| 903 | len++; | ||
| 904 | } | ||
| 905 | 900 | ||
| 906 | if (len < off) { | ||
| 907 | *eof = 1; | ||
| 908 | len = 0; | ||
| 909 | } | 901 | } |
| 910 | return len; | 902 | seq_write(m, page, p - page); |
| 903 | kfree(page); | ||
| 904 | return 0; | ||
| 905 | } | ||
| 906 | |||
| 907 | static int mf_cmdline_proc_open(struct inode *inode, struct file *file) | ||
| 908 | { | ||
| 909 | return single_open(file, mf_cmdline_proc_show, PDE(inode)->data); | ||
| 911 | } | 910 | } |
| 912 | 911 | ||
| 913 | #if 0 | 912 | #if 0 |
| @@ -962,10 +961,8 @@ static int proc_mf_dump_vmlinux(char *page, char **start, off_t off, | |||
| 962 | } | 961 | } |
| 963 | #endif | 962 | #endif |
| 964 | 963 | ||
| 965 | static int proc_mf_dump_side(char *page, char **start, off_t off, | 964 | static int mf_side_proc_show(struct seq_file *m, void *v) |
| 966 | int count, int *eof, void *data) | ||
| 967 | { | 965 | { |
| 968 | int len; | ||
| 969 | char mf_current_side = ' '; | 966 | char mf_current_side = ' '; |
| 970 | struct vsp_cmd_data vsp_cmd; | 967 | struct vsp_cmd_data vsp_cmd; |
| 971 | 968 | ||
| @@ -989,21 +986,17 @@ static int proc_mf_dump_side(char *page, char **start, off_t off, | |||
| 989 | } | 986 | } |
| 990 | } | 987 | } |
| 991 | 988 | ||
| 992 | len = sprintf(page, "%c\n", mf_current_side); | 989 | seq_printf(m, "%c\n", mf_current_side); |
| 990 | return 0; | ||
| 991 | } | ||
| 993 | 992 | ||
| 994 | if (len <= (off + count)) | 993 | static int mf_side_proc_open(struct inode *inode, struct file *file) |
| 995 | *eof = 1; | 994 | { |
| 996 | *start = page + off; | 995 | return single_open(file, mf_side_proc_show, NULL); |
| 997 | len -= off; | ||
| 998 | if (len > count) | ||
| 999 | len = count; | ||
| 1000 | if (len < 0) | ||
| 1001 | len = 0; | ||
| 1002 | return len; | ||
| 1003 | } | 996 | } |
| 1004 | 997 | ||
| 1005 | static int proc_mf_change_side(struct file *file, const char __user *buffer, | 998 | static ssize_t mf_side_proc_write(struct file *file, const char __user *buffer, |
| 1006 | unsigned long count, void *data) | 999 | size_t count, loff_t *pos) |
| 1007 | { | 1000 | { |
| 1008 | char side; | 1001 | char side; |
| 1009 | u64 newSide; | 1002 | u64 newSide; |
| @@ -1041,6 +1034,15 @@ static int proc_mf_change_side(struct file *file, const char __user *buffer, | |||
| 1041 | return count; | 1034 | return count; |
| 1042 | } | 1035 | } |
| 1043 | 1036 | ||
| 1037 | static const struct file_operations mf_side_proc_fops = { | ||
| 1038 | .owner = THIS_MODULE, | ||
| 1039 | .open = mf_side_proc_open, | ||
| 1040 | .read = seq_read, | ||
| 1041 | .llseek = seq_lseek, | ||
| 1042 | .release = single_release, | ||
| 1043 | .write = mf_side_proc_write, | ||
| 1044 | }; | ||
| 1045 | |||
| 1044 | #if 0 | 1046 | #if 0 |
| 1045 | static void mf_getSrcHistory(char *buffer, int size) | 1047 | static void mf_getSrcHistory(char *buffer, int size) |
| 1046 | { | 1048 | { |
| @@ -1087,8 +1089,7 @@ static void mf_getSrcHistory(char *buffer, int size) | |||
| 1087 | } | 1089 | } |
| 1088 | #endif | 1090 | #endif |
| 1089 | 1091 | ||
| 1090 | static int proc_mf_dump_src(char *page, char **start, off_t off, | 1092 | static int mf_src_proc_show(struct seq_file *m, void *v) |
| 1091 | int count, int *eof, void *data) | ||
| 1092 | { | 1093 | { |
| 1093 | #if 0 | 1094 | #if 0 |
| 1094 | int len; | 1095 | int len; |
| @@ -1109,8 +1110,13 @@ static int proc_mf_dump_src(char *page, char **start, off_t off, | |||
| 1109 | #endif | 1110 | #endif |
| 1110 | } | 1111 | } |
| 1111 | 1112 | ||
| 1112 | static int proc_mf_change_src(struct file *file, const char __user *buffer, | 1113 | static int mf_src_proc_open(struct inode *inode, struct file *file) |
| 1113 | unsigned long count, void *data) | 1114 | { |
| 1115 | return single_open(file, mf_src_proc_show, NULL); | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | static ssize_t mf_src_proc_write(struct file *file, const char __user *buffer, | ||
| 1119 | size_t count, loff_t *pos) | ||
| 1114 | { | 1120 | { |
| 1115 | char stkbuf[10]; | 1121 | char stkbuf[10]; |
| 1116 | 1122 | ||
| @@ -1135,9 +1141,19 @@ static int proc_mf_change_src(struct file *file, const char __user *buffer, | |||
| 1135 | return count; | 1141 | return count; |
| 1136 | } | 1142 | } |
| 1137 | 1143 | ||
| 1138 | static int proc_mf_change_cmdline(struct file *file, const char __user *buffer, | 1144 | static const struct file_operations mf_src_proc_fops = { |
| 1139 | unsigned long count, void *data) | 1145 | .owner = THIS_MODULE, |
| 1146 | .open = mf_src_proc_open, | ||
| 1147 | .read = seq_read, | ||
| 1148 | .llseek = seq_lseek, | ||
| 1149 | .release = single_release, | ||
| 1150 | .write = mf_src_proc_write, | ||
| 1151 | }; | ||
| 1152 | |||
| 1153 | static ssize_t mf_cmdline_proc_write(struct file *file, const char __user *buffer, | ||
| 1154 | size_t count, loff_t *pos) | ||
| 1140 | { | 1155 | { |
| 1156 | void *data = PDE(file->f_path.dentry->d_inode)->data; | ||
| 1141 | struct vsp_cmd_data vsp_cmd; | 1157 | struct vsp_cmd_data vsp_cmd; |
| 1142 | dma_addr_t dma_addr; | 1158 | dma_addr_t dma_addr; |
| 1143 | char *page; | 1159 | char *page; |
| @@ -1172,6 +1188,15 @@ out: | |||
| 1172 | return ret; | 1188 | return ret; |
| 1173 | } | 1189 | } |
| 1174 | 1190 | ||
| 1191 | static const struct file_operations mf_cmdline_proc_fops = { | ||
| 1192 | .owner = THIS_MODULE, | ||
| 1193 | .open = mf_cmdline_proc_open, | ||
| 1194 | .read = seq_read, | ||
| 1195 | .llseek = seq_lseek, | ||
| 1196 | .release = single_release, | ||
| 1197 | .write = mf_cmdline_proc_write, | ||
| 1198 | }; | ||
| 1199 | |||
| 1175 | static ssize_t proc_mf_change_vmlinux(struct file *file, | 1200 | static ssize_t proc_mf_change_vmlinux(struct file *file, |
| 1176 | const char __user *buf, | 1201 | const char __user *buf, |
| 1177 | size_t count, loff_t *ppos) | 1202 | size_t count, loff_t *ppos) |
| @@ -1246,12 +1271,10 @@ static int __init mf_proc_init(void) | |||
| 1246 | if (!mf) | 1271 | if (!mf) |
| 1247 | return 1; | 1272 | return 1; |
| 1248 | 1273 | ||
| 1249 | ent = create_proc_entry("cmdline", S_IFREG|S_IRUSR|S_IWUSR, mf); | 1274 | ent = proc_create_data("cmdline", S_IRUSR|S_IWUSR, mf, |
| 1275 | &mf_cmdline_proc_fops, (void *)(long)i); | ||
| 1250 | if (!ent) | 1276 | if (!ent) |
| 1251 | return 1; | 1277 | return 1; |
| 1252 | ent->data = (void *)(long)i; | ||
| 1253 | ent->read_proc = proc_mf_dump_cmdline; | ||
| 1254 | ent->write_proc = proc_mf_change_cmdline; | ||
| 1255 | 1278 | ||
| 1256 | if (i == 3) /* no vmlinux entry for 'D' */ | 1279 | if (i == 3) /* no vmlinux entry for 'D' */ |
| 1257 | continue; | 1280 | continue; |
| @@ -1263,19 +1286,15 @@ static int __init mf_proc_init(void) | |||
| 1263 | return 1; | 1286 | return 1; |
| 1264 | } | 1287 | } |
| 1265 | 1288 | ||
| 1266 | ent = create_proc_entry("side", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root); | 1289 | ent = proc_create("side", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root, |
| 1290 | &mf_side_proc_fops); | ||
| 1267 | if (!ent) | 1291 | if (!ent) |
| 1268 | return 1; | 1292 | return 1; |
| 1269 | ent->data = (void *)0; | ||
| 1270 | ent->read_proc = proc_mf_dump_side; | ||
| 1271 | ent->write_proc = proc_mf_change_side; | ||
| 1272 | 1293 | ||
| 1273 | ent = create_proc_entry("src", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root); | 1294 | ent = proc_create("src", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root, |
| 1295 | &mf_src_proc_fops); | ||
| 1274 | if (!ent) | 1296 | if (!ent) |
| 1275 | return 1; | 1297 | return 1; |
| 1276 | ent->data = (void *)0; | ||
| 1277 | ent->read_proc = proc_mf_dump_src; | ||
| 1278 | ent->write_proc = proc_mf_change_src; | ||
| 1279 | 1298 | ||
| 1280 | return 0; | 1299 | return 0; |
| 1281 | } | 1300 | } |
diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c index 49ff4dc422b7..5aea94f30836 100644 --- a/arch/powerpc/platforms/iseries/viopath.c +++ b/arch/powerpc/platforms/iseries/viopath.c | |||
| @@ -116,7 +116,7 @@ static int proc_viopath_show(struct seq_file *m, void *v) | |||
| 116 | u16 vlanMap; | 116 | u16 vlanMap; |
| 117 | dma_addr_t handle; | 117 | dma_addr_t handle; |
| 118 | HvLpEvent_Rc hvrc; | 118 | HvLpEvent_Rc hvrc; |
| 119 | DECLARE_COMPLETION(done); | 119 | DECLARE_COMPLETION_ONSTACK(done); |
| 120 | struct device_node *node; | 120 | struct device_node *node; |
| 121 | const char *sysid; | 121 | const char *sysid; |
| 122 | 122 | ||
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index 27554c807fd5..c667f0f02c34 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig | |||
| @@ -2,6 +2,8 @@ config PPC_PSERIES | |||
| 2 | depends on PPC64 && PPC_BOOK3S | 2 | depends on PPC64 && PPC_BOOK3S |
| 3 | bool "IBM pSeries & new (POWER5-based) iSeries" | 3 | bool "IBM pSeries & new (POWER5-based) iSeries" |
| 4 | select MPIC | 4 | select MPIC |
| 5 | select PCI_MSI | ||
| 6 | select XICS | ||
| 5 | select PPC_I8259 | 7 | select PPC_I8259 |
| 6 | select PPC_RTAS | 8 | select PPC_RTAS |
| 7 | select PPC_RTAS_DAEMON | 9 | select PPC_RTAS_DAEMON |
diff --git a/arch/powerpc/platforms/pseries/cmm.c b/arch/powerpc/platforms/pseries/cmm.c index bcdcf0ccc8d7..a277f2e28dbc 100644 --- a/arch/powerpc/platforms/pseries/cmm.c +++ b/arch/powerpc/platforms/pseries/cmm.c | |||
| @@ -38,19 +38,28 @@ | |||
| 38 | #include <asm/mmu.h> | 38 | #include <asm/mmu.h> |
| 39 | #include <asm/pgalloc.h> | 39 | #include <asm/pgalloc.h> |
| 40 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
| 41 | #include <linux/memory.h> | ||
| 41 | 42 | ||
| 42 | #include "plpar_wrappers.h" | 43 | #include "plpar_wrappers.h" |
| 43 | 44 | ||
| 44 | #define CMM_DRIVER_VERSION "1.0.0" | 45 | #define CMM_DRIVER_VERSION "1.0.0" |
| 45 | #define CMM_DEFAULT_DELAY 1 | 46 | #define CMM_DEFAULT_DELAY 1 |
| 47 | #define CMM_HOTPLUG_DELAY 5 | ||
| 46 | #define CMM_DEBUG 0 | 48 | #define CMM_DEBUG 0 |
| 47 | #define CMM_DISABLE 0 | 49 | #define CMM_DISABLE 0 |
| 48 | #define CMM_OOM_KB 1024 | 50 | #define CMM_OOM_KB 1024 |
| 49 | #define CMM_MIN_MEM_MB 256 | 51 | #define CMM_MIN_MEM_MB 256 |
| 50 | #define KB2PAGES(_p) ((_p)>>(PAGE_SHIFT-10)) | 52 | #define KB2PAGES(_p) ((_p)>>(PAGE_SHIFT-10)) |
| 51 | #define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10)) | 53 | #define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10)) |
| 54 | /* | ||
| 55 | * The priority level tries to ensure that this notifier is called as | ||
| 56 | * late as possible to reduce thrashing in the shared memory pool. | ||
| 57 | */ | ||
| 58 | #define CMM_MEM_HOTPLUG_PRI 1 | ||
| 59 | #define CMM_MEM_ISOLATE_PRI 15 | ||
| 52 | 60 | ||
| 53 | static unsigned int delay = CMM_DEFAULT_DELAY; | 61 | static unsigned int delay = CMM_DEFAULT_DELAY; |
| 62 | static unsigned int hotplug_delay = CMM_HOTPLUG_DELAY; | ||
| 54 | static unsigned int oom_kb = CMM_OOM_KB; | 63 | static unsigned int oom_kb = CMM_OOM_KB; |
| 55 | static unsigned int cmm_debug = CMM_DEBUG; | 64 | static unsigned int cmm_debug = CMM_DEBUG; |
| 56 | static unsigned int cmm_disabled = CMM_DISABLE; | 65 | static unsigned int cmm_disabled = CMM_DISABLE; |
| @@ -65,6 +74,10 @@ MODULE_VERSION(CMM_DRIVER_VERSION); | |||
| 65 | module_param_named(delay, delay, uint, S_IRUGO | S_IWUSR); | 74 | module_param_named(delay, delay, uint, S_IRUGO | S_IWUSR); |
| 66 | MODULE_PARM_DESC(delay, "Delay (in seconds) between polls to query hypervisor paging requests. " | 75 | MODULE_PARM_DESC(delay, "Delay (in seconds) between polls to query hypervisor paging requests. " |
| 67 | "[Default=" __stringify(CMM_DEFAULT_DELAY) "]"); | 76 | "[Default=" __stringify(CMM_DEFAULT_DELAY) "]"); |
| 77 | module_param_named(hotplug_delay, hotplug_delay, uint, S_IRUGO | S_IWUSR); | ||
| 78 | MODULE_PARM_DESC(delay, "Delay (in seconds) after memory hotplug remove " | ||
| 79 | "before loaning resumes. " | ||
| 80 | "[Default=" __stringify(CMM_HOTPLUG_DELAY) "]"); | ||
| 68 | module_param_named(oom_kb, oom_kb, uint, S_IRUGO | S_IWUSR); | 81 | module_param_named(oom_kb, oom_kb, uint, S_IRUGO | S_IWUSR); |
| 69 | MODULE_PARM_DESC(oom_kb, "Amount of memory in kb to free on OOM. " | 82 | MODULE_PARM_DESC(oom_kb, "Amount of memory in kb to free on OOM. " |
| 70 | "[Default=" __stringify(CMM_OOM_KB) "]"); | 83 | "[Default=" __stringify(CMM_OOM_KB) "]"); |
| @@ -92,6 +105,9 @@ static unsigned long oom_freed_pages; | |||
| 92 | static struct cmm_page_array *cmm_page_list; | 105 | static struct cmm_page_array *cmm_page_list; |
| 93 | static DEFINE_SPINLOCK(cmm_lock); | 106 | static DEFINE_SPINLOCK(cmm_lock); |
| 94 | 107 | ||
| 108 | static DEFINE_MUTEX(hotplug_mutex); | ||
| 109 | static int hotplug_occurred; /* protected by the hotplug mutex */ | ||
| 110 | |||
| 95 | static struct task_struct *cmm_thread_ptr; | 111 | static struct task_struct *cmm_thread_ptr; |
| 96 | 112 | ||
| 97 | /** | 113 | /** |
| @@ -110,6 +126,17 @@ static long cmm_alloc_pages(long nr) | |||
| 110 | cmm_dbg("Begin request for %ld pages\n", nr); | 126 | cmm_dbg("Begin request for %ld pages\n", nr); |
| 111 | 127 | ||
| 112 | while (nr) { | 128 | while (nr) { |
| 129 | /* Exit if a hotplug operation is in progress or occurred */ | ||
| 130 | if (mutex_trylock(&hotplug_mutex)) { | ||
| 131 | if (hotplug_occurred) { | ||
| 132 | mutex_unlock(&hotplug_mutex); | ||
| 133 | break; | ||
| 134 | } | ||
| 135 | mutex_unlock(&hotplug_mutex); | ||
| 136 | } else { | ||
| 137 | break; | ||
| 138 | } | ||
| 139 | |||
| 113 | addr = __get_free_page(GFP_NOIO | __GFP_NOWARN | | 140 | addr = __get_free_page(GFP_NOIO | __GFP_NOWARN | |
| 114 | __GFP_NORETRY | __GFP_NOMEMALLOC); | 141 | __GFP_NORETRY | __GFP_NOMEMALLOC); |
| 115 | if (!addr) | 142 | if (!addr) |
| @@ -119,8 +146,9 @@ static long cmm_alloc_pages(long nr) | |||
| 119 | if (!pa || pa->index >= CMM_NR_PAGES) { | 146 | if (!pa || pa->index >= CMM_NR_PAGES) { |
| 120 | /* Need a new page for the page list. */ | 147 | /* Need a new page for the page list. */ |
| 121 | spin_unlock(&cmm_lock); | 148 | spin_unlock(&cmm_lock); |
| 122 | npa = (struct cmm_page_array *)__get_free_page(GFP_NOIO | __GFP_NOWARN | | 149 | npa = (struct cmm_page_array *)__get_free_page( |
| 123 | __GFP_NORETRY | __GFP_NOMEMALLOC); | 150 | GFP_NOIO | __GFP_NOWARN | |
| 151 | __GFP_NORETRY | __GFP_NOMEMALLOC); | ||
| 124 | if (!npa) { | 152 | if (!npa) { |
| 125 | pr_info("%s: Can not allocate new page list\n", __func__); | 153 | pr_info("%s: Can not allocate new page list\n", __func__); |
| 126 | free_page(addr); | 154 | free_page(addr); |
| @@ -282,9 +310,28 @@ static int cmm_thread(void *dummy) | |||
| 282 | while (1) { | 310 | while (1) { |
| 283 | timeleft = msleep_interruptible(delay * 1000); | 311 | timeleft = msleep_interruptible(delay * 1000); |
| 284 | 312 | ||
| 285 | if (kthread_should_stop() || timeleft) { | 313 | if (kthread_should_stop() || timeleft) |
| 286 | loaned_pages_target = loaned_pages; | ||
| 287 | break; | 314 | break; |
| 315 | |||
| 316 | if (mutex_trylock(&hotplug_mutex)) { | ||
| 317 | if (hotplug_occurred) { | ||
| 318 | hotplug_occurred = 0; | ||
| 319 | mutex_unlock(&hotplug_mutex); | ||
| 320 | cmm_dbg("Hotplug operation has occurred, " | ||
| 321 | "loaning activity suspended " | ||
| 322 | "for %d seconds.\n", | ||
| 323 | hotplug_delay); | ||
| 324 | timeleft = msleep_interruptible(hotplug_delay * | ||
| 325 | 1000); | ||
| 326 | if (kthread_should_stop() || timeleft) | ||
| 327 | break; | ||
| 328 | continue; | ||
| 329 | } | ||
| 330 | mutex_unlock(&hotplug_mutex); | ||
| 331 | } else { | ||
| 332 | cmm_dbg("Hotplug operation in progress, activity " | ||
| 333 | "suspended\n"); | ||
| 334 | continue; | ||
| 288 | } | 335 | } |
| 289 | 336 | ||
| 290 | cmm_get_mpp(); | 337 | cmm_get_mpp(); |
| @@ -414,6 +461,193 @@ static struct notifier_block cmm_reboot_nb = { | |||
| 414 | }; | 461 | }; |
| 415 | 462 | ||
| 416 | /** | 463 | /** |
| 464 | * cmm_count_pages - Count the number of pages loaned in a particular range. | ||
| 465 | * | ||
| 466 | * @arg: memory_isolate_notify structure with address range and count | ||
| 467 | * | ||
| 468 | * Return value: | ||
| 469 | * 0 on success | ||
| 470 | **/ | ||
| 471 | static unsigned long cmm_count_pages(void *arg) | ||
| 472 | { | ||
| 473 | struct memory_isolate_notify *marg = arg; | ||
| 474 | struct cmm_page_array *pa; | ||
| 475 | unsigned long start = (unsigned long)pfn_to_kaddr(marg->start_pfn); | ||
| 476 | unsigned long end = start + (marg->nr_pages << PAGE_SHIFT); | ||
| 477 | unsigned long idx; | ||
| 478 | |||
| 479 | spin_lock(&cmm_lock); | ||
| 480 | pa = cmm_page_list; | ||
| 481 | while (pa) { | ||
| 482 | if ((unsigned long)pa >= start && (unsigned long)pa < end) | ||
| 483 | marg->pages_found++; | ||
| 484 | for (idx = 0; idx < pa->index; idx++) | ||
| 485 | if (pa->page[idx] >= start && pa->page[idx] < end) | ||
| 486 | marg->pages_found++; | ||
| 487 | pa = pa->next; | ||
| 488 | } | ||
| 489 | spin_unlock(&cmm_lock); | ||
| 490 | return 0; | ||
| 491 | } | ||
| 492 | |||
| 493 | /** | ||
| 494 | * cmm_memory_isolate_cb - Handle memory isolation notifier calls | ||
| 495 | * @self: notifier block struct | ||
| 496 | * @action: action to take | ||
| 497 | * @arg: struct memory_isolate_notify data for handler | ||
| 498 | * | ||
| 499 | * Return value: | ||
| 500 | * NOTIFY_OK or notifier error based on subfunction return value | ||
| 501 | **/ | ||
| 502 | static int cmm_memory_isolate_cb(struct notifier_block *self, | ||
| 503 | unsigned long action, void *arg) | ||
| 504 | { | ||
| 505 | int ret = 0; | ||
| 506 | |||
| 507 | if (action == MEM_ISOLATE_COUNT) | ||
| 508 | ret = cmm_count_pages(arg); | ||
| 509 | |||
| 510 | if (ret) | ||
| 511 | ret = notifier_from_errno(ret); | ||
| 512 | else | ||
| 513 | ret = NOTIFY_OK; | ||
| 514 | |||
| 515 | return ret; | ||
| 516 | } | ||
| 517 | |||
| 518 | static struct notifier_block cmm_mem_isolate_nb = { | ||
| 519 | .notifier_call = cmm_memory_isolate_cb, | ||
| 520 | .priority = CMM_MEM_ISOLATE_PRI | ||
| 521 | }; | ||
| 522 | |||
| 523 | /** | ||
| 524 | * cmm_mem_going_offline - Unloan pages where memory is to be removed | ||
| 525 | * @arg: memory_notify structure with page range to be offlined | ||
| 526 | * | ||
| 527 | * Return value: | ||
| 528 | * 0 on success | ||
| 529 | **/ | ||
| 530 | static int cmm_mem_going_offline(void *arg) | ||
| 531 | { | ||
| 532 | struct memory_notify *marg = arg; | ||
| 533 | unsigned long start_page = (unsigned long)pfn_to_kaddr(marg->start_pfn); | ||
| 534 | unsigned long end_page = start_page + (marg->nr_pages << PAGE_SHIFT); | ||
| 535 | struct cmm_page_array *pa_curr, *pa_last, *npa; | ||
| 536 | unsigned long idx; | ||
| 537 | unsigned long freed = 0; | ||
| 538 | |||
| 539 | cmm_dbg("Memory going offline, searching 0x%lx (%ld pages).\n", | ||
| 540 | start_page, marg->nr_pages); | ||
| 541 | spin_lock(&cmm_lock); | ||
| 542 | |||
| 543 | /* Search the page list for pages in the range to be offlined */ | ||
| 544 | pa_last = pa_curr = cmm_page_list; | ||
| 545 | while (pa_curr) { | ||
| 546 | for (idx = (pa_curr->index - 1); (idx + 1) > 0; idx--) { | ||
| 547 | if ((pa_curr->page[idx] < start_page) || | ||
| 548 | (pa_curr->page[idx] >= end_page)) | ||
| 549 | continue; | ||
| 550 | |||
| 551 | plpar_page_set_active(__pa(pa_curr->page[idx])); | ||
| 552 | free_page(pa_curr->page[idx]); | ||
| 553 | freed++; | ||
| 554 | loaned_pages--; | ||
| 555 | totalram_pages++; | ||
| 556 | pa_curr->page[idx] = pa_last->page[--pa_last->index]; | ||
| 557 | if (pa_last->index == 0) { | ||
| 558 | if (pa_curr == pa_last) | ||
| 559 | pa_curr = pa_last->next; | ||
| 560 | pa_last = pa_last->next; | ||
| 561 | free_page((unsigned long)cmm_page_list); | ||
| 562 | cmm_page_list = pa_last; | ||
| 563 | continue; | ||
| 564 | } | ||
| 565 | } | ||
| 566 | pa_curr = pa_curr->next; | ||
| 567 | } | ||
| 568 | |||
| 569 | /* Search for page list structures in the range to be offlined */ | ||
| 570 | pa_last = NULL; | ||
| 571 | pa_curr = cmm_page_list; | ||
| 572 | while (pa_curr) { | ||
| 573 | if (((unsigned long)pa_curr >= start_page) && | ||
| 574 | ((unsigned long)pa_curr < end_page)) { | ||
| 575 | npa = (struct cmm_page_array *)__get_free_page( | ||
| 576 | GFP_NOIO | __GFP_NOWARN | | ||
| 577 | __GFP_NORETRY | __GFP_NOMEMALLOC); | ||
| 578 | if (!npa) { | ||
| 579 | spin_unlock(&cmm_lock); | ||
| 580 | cmm_dbg("Failed to allocate memory for list " | ||
| 581 | "management. Memory hotplug " | ||
| 582 | "failed.\n"); | ||
| 583 | return ENOMEM; | ||
| 584 | } | ||
| 585 | memcpy(npa, pa_curr, PAGE_SIZE); | ||
| 586 | if (pa_curr == cmm_page_list) | ||
| 587 | cmm_page_list = npa; | ||
| 588 | if (pa_last) | ||
| 589 | pa_last->next = npa; | ||
| 590 | free_page((unsigned long) pa_curr); | ||
| 591 | freed++; | ||
| 592 | pa_curr = npa; | ||
| 593 | } | ||
| 594 | |||
| 595 | pa_last = pa_curr; | ||
| 596 | pa_curr = pa_curr->next; | ||
| 597 | } | ||
| 598 | |||
| 599 | spin_unlock(&cmm_lock); | ||
| 600 | cmm_dbg("Released %ld pages in the search range.\n", freed); | ||
| 601 | |||
| 602 | return 0; | ||
| 603 | } | ||
| 604 | |||
| 605 | /** | ||
| 606 | * cmm_memory_cb - Handle memory hotplug notifier calls | ||
| 607 | * @self: notifier block struct | ||
| 608 | * @action: action to take | ||
| 609 | * @arg: struct memory_notify data for handler | ||
| 610 | * | ||
| 611 | * Return value: | ||
| 612 | * NOTIFY_OK or notifier error based on subfunction return value | ||
| 613 | * | ||
| 614 | **/ | ||
| 615 | static int cmm_memory_cb(struct notifier_block *self, | ||
| 616 | unsigned long action, void *arg) | ||
| 617 | { | ||
| 618 | int ret = 0; | ||
| 619 | |||
| 620 | switch (action) { | ||
| 621 | case MEM_GOING_OFFLINE: | ||
| 622 | mutex_lock(&hotplug_mutex); | ||
| 623 | hotplug_occurred = 1; | ||
| 624 | ret = cmm_mem_going_offline(arg); | ||
| 625 | break; | ||
| 626 | case MEM_OFFLINE: | ||
| 627 | case MEM_CANCEL_OFFLINE: | ||
| 628 | mutex_unlock(&hotplug_mutex); | ||
| 629 | cmm_dbg("Memory offline operation complete.\n"); | ||
| 630 | break; | ||
| 631 | case MEM_GOING_ONLINE: | ||
| 632 | case MEM_ONLINE: | ||
| 633 | case MEM_CANCEL_ONLINE: | ||
| 634 | break; | ||
| 635 | } | ||
| 636 | |||
| 637 | if (ret) | ||
| 638 | ret = notifier_from_errno(ret); | ||
| 639 | else | ||
| 640 | ret = NOTIFY_OK; | ||
| 641 | |||
| 642 | return ret; | ||
| 643 | } | ||
| 644 | |||
| 645 | static struct notifier_block cmm_mem_nb = { | ||
| 646 | .notifier_call = cmm_memory_cb, | ||
| 647 | .priority = CMM_MEM_HOTPLUG_PRI | ||
| 648 | }; | ||
| 649 | |||
| 650 | /** | ||
| 417 | * cmm_init - Module initialization | 651 | * cmm_init - Module initialization |
| 418 | * | 652 | * |
| 419 | * Return value: | 653 | * Return value: |
| @@ -435,18 +669,24 @@ static int cmm_init(void) | |||
| 435 | if ((rc = cmm_sysfs_register(&cmm_sysdev))) | 669 | if ((rc = cmm_sysfs_register(&cmm_sysdev))) |
| 436 | goto out_reboot_notifier; | 670 | goto out_reboot_notifier; |
| 437 | 671 | ||
| 672 | if (register_memory_notifier(&cmm_mem_nb) || | ||
| 673 | register_memory_isolate_notifier(&cmm_mem_isolate_nb)) | ||
| 674 | goto out_unregister_notifier; | ||
| 675 | |||
| 438 | if (cmm_disabled) | 676 | if (cmm_disabled) |
| 439 | return rc; | 677 | return rc; |
| 440 | 678 | ||
| 441 | cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread"); | 679 | cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread"); |
| 442 | if (IS_ERR(cmm_thread_ptr)) { | 680 | if (IS_ERR(cmm_thread_ptr)) { |
| 443 | rc = PTR_ERR(cmm_thread_ptr); | 681 | rc = PTR_ERR(cmm_thread_ptr); |
| 444 | goto out_unregister_sysfs; | 682 | goto out_unregister_notifier; |
| 445 | } | 683 | } |
| 446 | 684 | ||
| 447 | return rc; | 685 | return rc; |
| 448 | 686 | ||
| 449 | out_unregister_sysfs: | 687 | out_unregister_notifier: |
| 688 | unregister_memory_notifier(&cmm_mem_nb); | ||
| 689 | unregister_memory_isolate_notifier(&cmm_mem_isolate_nb); | ||
| 450 | cmm_unregister_sysfs(&cmm_sysdev); | 690 | cmm_unregister_sysfs(&cmm_sysdev); |
| 451 | out_reboot_notifier: | 691 | out_reboot_notifier: |
| 452 | unregister_reboot_notifier(&cmm_reboot_nb); | 692 | unregister_reboot_notifier(&cmm_reboot_nb); |
| @@ -467,6 +707,8 @@ static void cmm_exit(void) | |||
| 467 | kthread_stop(cmm_thread_ptr); | 707 | kthread_stop(cmm_thread_ptr); |
| 468 | unregister_oom_notifier(&cmm_oom_nb); | 708 | unregister_oom_notifier(&cmm_oom_nb); |
| 469 | unregister_reboot_notifier(&cmm_reboot_nb); | 709 | unregister_reboot_notifier(&cmm_reboot_nb); |
| 710 | unregister_memory_notifier(&cmm_mem_nb); | ||
| 711 | unregister_memory_isolate_notifier(&cmm_mem_isolate_nb); | ||
| 470 | cmm_free_pages(loaned_pages); | 712 | cmm_free_pages(loaned_pages); |
| 471 | cmm_unregister_sysfs(&cmm_sysdev); | 713 | cmm_unregister_sysfs(&cmm_sysdev); |
| 472 | } | 714 | } |
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index 12df9e8812a9..67b7a10f9fce 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c | |||
| @@ -346,12 +346,14 @@ int dlpar_release_drc(u32 drc_index) | |||
| 346 | 346 | ||
| 347 | static DEFINE_MUTEX(pseries_cpu_hotplug_mutex); | 347 | static DEFINE_MUTEX(pseries_cpu_hotplug_mutex); |
| 348 | 348 | ||
| 349 | void cpu_hotplug_driver_lock() | 349 | void cpu_hotplug_driver_lock(void) |
| 350 | __acquires(pseries_cpu_hotplug_mutex) | ||
| 350 | { | 351 | { |
| 351 | mutex_lock(&pseries_cpu_hotplug_mutex); | 352 | mutex_lock(&pseries_cpu_hotplug_mutex); |
| 352 | } | 353 | } |
| 353 | 354 | ||
| 354 | void cpu_hotplug_driver_unlock() | 355 | void cpu_hotplug_driver_unlock(void) |
| 356 | __releases(pseries_cpu_hotplug_mutex) | ||
| 355 | { | 357 | { |
| 356 | mutex_unlock(&pseries_cpu_hotplug_mutex); | 358 | mutex_unlock(&pseries_cpu_hotplug_mutex); |
| 357 | } | 359 | } |
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index 8868c012268a..b4886635972c 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c | |||
| @@ -144,8 +144,8 @@ static void __devinit smp_pSeries_kick_cpu(int nr) | |||
| 144 | hcpuid = get_hard_smp_processor_id(nr); | 144 | hcpuid = get_hard_smp_processor_id(nr); |
| 145 | rc = plpar_hcall_norets(H_PROD, hcpuid); | 145 | rc = plpar_hcall_norets(H_PROD, hcpuid); |
| 146 | if (rc != H_SUCCESS) | 146 | if (rc != H_SUCCESS) |
| 147 | panic("Error: Prod to wake up processor %d Ret= %ld\n", | 147 | printk(KERN_ERR "Error: Prod to wake up processor %d\ |
| 148 | nr, rc); | 148 | Ret= %ld\n", nr, rc); |
| 149 | } | 149 | } |
| 150 | } | 150 | } |
| 151 | 151 | ||
diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c index 971483f0dfac..1709ac5aac7c 100644 --- a/arch/powerpc/sysdev/cpm2_pic.c +++ b/arch/powerpc/sysdev/cpm2_pic.c | |||
| @@ -143,13 +143,23 @@ static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type) | |||
| 143 | struct irq_desc *desc = irq_to_desc(virq); | 143 | struct irq_desc *desc = irq_to_desc(virq); |
| 144 | unsigned int vold, vnew, edibit; | 144 | unsigned int vold, vnew, edibit; |
| 145 | 145 | ||
| 146 | if (flow_type == IRQ_TYPE_NONE) | 146 | /* Port C interrupts are either IRQ_TYPE_EDGE_FALLING or |
| 147 | flow_type = IRQ_TYPE_LEVEL_LOW; | 147 | * IRQ_TYPE_EDGE_BOTH (default). All others are IRQ_TYPE_EDGE_FALLING |
| 148 | 148 | * or IRQ_TYPE_LEVEL_LOW (default) | |
| 149 | if (flow_type & IRQ_TYPE_EDGE_RISING) { | 149 | */ |
| 150 | printk(KERN_ERR "CPM2 PIC: sense type 0x%x not supported\n", | 150 | if (src >= CPM2_IRQ_PORTC15 && src <= CPM2_IRQ_PORTC0) { |
| 151 | flow_type); | 151 | if (flow_type == IRQ_TYPE_NONE) |
| 152 | return -EINVAL; | 152 | flow_type = IRQ_TYPE_EDGE_BOTH; |
| 153 | |||
| 154 | if (flow_type != IRQ_TYPE_EDGE_BOTH && | ||
| 155 | flow_type != IRQ_TYPE_EDGE_FALLING) | ||
| 156 | goto err_sense; | ||
| 157 | } else { | ||
| 158 | if (flow_type == IRQ_TYPE_NONE) | ||
| 159 | flow_type = IRQ_TYPE_LEVEL_LOW; | ||
| 160 | |||
| 161 | if (flow_type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH)) | ||
| 162 | goto err_sense; | ||
| 153 | } | 163 | } |
| 154 | 164 | ||
| 155 | desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); | 165 | desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); |
| @@ -181,6 +191,10 @@ static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type) | |||
| 181 | if (vold != vnew) | 191 | if (vold != vnew) |
| 182 | out_be32(&cpm2_intctl->ic_siexr, vnew); | 192 | out_be32(&cpm2_intctl->ic_siexr, vnew); |
| 183 | return 0; | 193 | return 0; |
| 194 | |||
| 195 | err_sense: | ||
| 196 | pr_err("CPM2 PIC: sense type 0x%x not supported\n", flow_type); | ||
| 197 | return -EINVAL; | ||
| 184 | } | 198 | } |
| 185 | 199 | ||
| 186 | static struct irq_chip cpm2_pic = { | 200 | static struct irq_chip cpm2_pic = { |
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 4e3a3e345ab3..e1a028c1f18d 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c | |||
| @@ -464,8 +464,7 @@ static void __iomem *mpc83xx_pcie_remap_cfg(struct pci_bus *bus, | |||
| 464 | { | 464 | { |
| 465 | struct pci_controller *hose = pci_bus_to_host(bus); | 465 | struct pci_controller *hose = pci_bus_to_host(bus); |
| 466 | struct mpc83xx_pcie_priv *pcie = hose->dn->data; | 466 | struct mpc83xx_pcie_priv *pcie = hose->dn->data; |
| 467 | u8 bus_no = bus->number - hose->first_busno; | 467 | u32 dev_base = bus->number << 24 | devfn << 16; |
| 468 | u32 dev_base = bus_no << 24 | devfn << 16; | ||
| 469 | int ret; | 468 | int ret; |
| 470 | 469 | ||
| 471 | ret = mpc83xx_pcie_exclude_device(bus, devfn); | 470 | ret = mpc83xx_pcie_exclude_device(bus, devfn); |
| @@ -515,12 +514,17 @@ static int mpc83xx_pcie_read_config(struct pci_bus *bus, unsigned int devfn, | |||
| 515 | static int mpc83xx_pcie_write_config(struct pci_bus *bus, unsigned int devfn, | 514 | static int mpc83xx_pcie_write_config(struct pci_bus *bus, unsigned int devfn, |
| 516 | int offset, int len, u32 val) | 515 | int offset, int len, u32 val) |
| 517 | { | 516 | { |
| 517 | struct pci_controller *hose = pci_bus_to_host(bus); | ||
| 518 | void __iomem *cfg_addr; | 518 | void __iomem *cfg_addr; |
| 519 | 519 | ||
| 520 | cfg_addr = mpc83xx_pcie_remap_cfg(bus, devfn, offset); | 520 | cfg_addr = mpc83xx_pcie_remap_cfg(bus, devfn, offset); |
| 521 | if (!cfg_addr) | 521 | if (!cfg_addr) |
| 522 | return PCIBIOS_DEVICE_NOT_FOUND; | 522 | return PCIBIOS_DEVICE_NOT_FOUND; |
| 523 | 523 | ||
| 524 | /* PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS */ | ||
| 525 | if (offset == PCI_PRIMARY_BUS && bus->number == hose->first_busno) | ||
| 526 | val &= 0xffffff00; | ||
| 527 | |||
| 524 | switch (len) { | 528 | switch (len) { |
| 525 | case 1: | 529 | case 1: |
| 526 | out_8(cfg_addr, val); | 530 | out_8(cfg_addr, val); |
diff --git a/arch/powerpc/sysdev/mpc8xxx_gpio.c b/arch/powerpc/sysdev/mpc8xxx_gpio.c index 103eace36194..ee1c0e1cf4a7 100644 --- a/arch/powerpc/sysdev/mpc8xxx_gpio.c +++ b/arch/powerpc/sysdev/mpc8xxx_gpio.c | |||
| @@ -54,6 +54,22 @@ static void mpc8xxx_gpio_save_regs(struct of_mm_gpio_chip *mm) | |||
| 54 | mpc8xxx_gc->data = in_be32(mm->regs + GPIO_DAT); | 54 | mpc8xxx_gc->data = in_be32(mm->regs + GPIO_DAT); |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | /* Workaround GPIO 1 errata on MPC8572/MPC8536. The status of GPIOs | ||
| 58 | * defined as output cannot be determined by reading GPDAT register, | ||
| 59 | * so we use shadow data register instead. The status of input pins | ||
| 60 | * is determined by reading GPDAT register. | ||
| 61 | */ | ||
| 62 | static int mpc8572_gpio_get(struct gpio_chip *gc, unsigned int gpio) | ||
| 63 | { | ||
| 64 | u32 val; | ||
| 65 | struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); | ||
| 66 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); | ||
| 67 | |||
| 68 | val = in_be32(mm->regs + GPIO_DAT) & ~in_be32(mm->regs + GPIO_DIR); | ||
| 69 | |||
| 70 | return (val | mpc8xxx_gc->data) & mpc8xxx_gpio2mask(gpio); | ||
| 71 | } | ||
| 72 | |||
| 57 | static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio) | 73 | static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio) |
| 58 | { | 74 | { |
| 59 | struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); | 75 | struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); |
| @@ -136,7 +152,10 @@ static void __init mpc8xxx_add_controller(struct device_node *np) | |||
| 136 | gc->ngpio = MPC8XXX_GPIO_PINS; | 152 | gc->ngpio = MPC8XXX_GPIO_PINS; |
| 137 | gc->direction_input = mpc8xxx_gpio_dir_in; | 153 | gc->direction_input = mpc8xxx_gpio_dir_in; |
| 138 | gc->direction_output = mpc8xxx_gpio_dir_out; | 154 | gc->direction_output = mpc8xxx_gpio_dir_out; |
| 139 | gc->get = mpc8xxx_gpio_get; | 155 | if (of_device_is_compatible(np, "fsl,mpc8572-gpio")) |
| 156 | gc->get = mpc8572_gpio_get; | ||
| 157 | else | ||
| 158 | gc->get = mpc8xxx_gpio_get; | ||
| 140 | gc->set = mpc8xxx_gpio_set; | 159 | gc->set = mpc8xxx_gpio_set; |
| 141 | 160 | ||
| 142 | ret = of_mm_gpiochip_add(np, mm_gc); | 161 | ret = of_mm_gpiochip_add(np, mm_gc); |
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index aa9d06e5925b..470dc6c11d57 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c | |||
| @@ -567,13 +567,11 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic) | |||
| 567 | #endif /* CONFIG_MPIC_U3_HT_IRQS */ | 567 | #endif /* CONFIG_MPIC_U3_HT_IRQS */ |
| 568 | 568 | ||
| 569 | #ifdef CONFIG_SMP | 569 | #ifdef CONFIG_SMP |
| 570 | static int irq_choose_cpu(unsigned int virt_irq) | 570 | static int irq_choose_cpu(const cpumask_t *mask) |
| 571 | { | 571 | { |
| 572 | cpumask_t mask; | ||
| 573 | int cpuid; | 572 | int cpuid; |
| 574 | 573 | ||
| 575 | cpumask_copy(&mask, irq_to_desc(virt_irq)->affinity); | 574 | if (cpumask_equal(mask, cpu_all_mask)) { |
| 576 | if (cpus_equal(mask, CPU_MASK_ALL)) { | ||
| 577 | static int irq_rover; | 575 | static int irq_rover; |
| 578 | static DEFINE_SPINLOCK(irq_rover_lock); | 576 | static DEFINE_SPINLOCK(irq_rover_lock); |
| 579 | unsigned long flags; | 577 | unsigned long flags; |
| @@ -594,20 +592,15 @@ static int irq_choose_cpu(unsigned int virt_irq) | |||
| 594 | 592 | ||
| 595 | spin_unlock_irqrestore(&irq_rover_lock, flags); | 593 | spin_unlock_irqrestore(&irq_rover_lock, flags); |
| 596 | } else { | 594 | } else { |
| 597 | cpumask_t tmp; | 595 | cpuid = cpumask_first_and(mask, cpu_online_mask); |
| 598 | 596 | if (cpuid >= nr_cpu_ids) | |
| 599 | cpus_and(tmp, cpu_online_map, mask); | ||
| 600 | |||
| 601 | if (cpus_empty(tmp)) | ||
| 602 | goto do_round_robin; | 597 | goto do_round_robin; |
| 603 | |||
| 604 | cpuid = first_cpu(tmp); | ||
| 605 | } | 598 | } |
| 606 | 599 | ||
| 607 | return get_hard_smp_processor_id(cpuid); | 600 | return get_hard_smp_processor_id(cpuid); |
| 608 | } | 601 | } |
| 609 | #else | 602 | #else |
| 610 | static int irq_choose_cpu(unsigned int virt_irq) | 603 | static int irq_choose_cpu(const cpumask_t *mask) |
| 611 | { | 604 | { |
| 612 | return hard_smp_processor_id(); | 605 | return hard_smp_processor_id(); |
| 613 | } | 606 | } |
| @@ -816,7 +809,7 @@ int mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask) | |||
| 816 | unsigned int src = mpic_irq_to_hw(irq); | 809 | unsigned int src = mpic_irq_to_hw(irq); |
| 817 | 810 | ||
| 818 | if (mpic->flags & MPIC_SINGLE_DEST_CPU) { | 811 | if (mpic->flags & MPIC_SINGLE_DEST_CPU) { |
| 819 | int cpuid = irq_choose_cpu(irq); | 812 | int cpuid = irq_choose_cpu(cpumask); |
| 820 | 813 | ||
| 821 | mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid); | 814 | mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid); |
| 822 | } else { | 815 | } else { |
diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c index 1d44eee80fa1..0f67cd79d481 100644 --- a/arch/powerpc/sysdev/mpic_msi.c +++ b/arch/powerpc/sysdev/mpic_msi.c | |||
| @@ -39,7 +39,12 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic) | |||
| 39 | 39 | ||
| 40 | pr_debug("mpic: found U3, guessing msi allocator setup\n"); | 40 | pr_debug("mpic: found U3, guessing msi allocator setup\n"); |
| 41 | 41 | ||
| 42 | /* Reserve source numbers we know are reserved in the HW */ | 42 | /* Reserve source numbers we know are reserved in the HW. |
| 43 | * | ||
| 44 | * This is a bit of a mix of U3 and U4 reserves but that's going | ||
| 45 | * to work fine, we have plenty enugh numbers left so let's just | ||
| 46 | * mark anything we don't like reserved. | ||
| 47 | */ | ||
| 43 | for (i = 0; i < 8; i++) | 48 | for (i = 0; i < 8; i++) |
| 44 | msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); | 49 | msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); |
| 45 | 50 | ||
| @@ -49,6 +54,10 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic) | |||
| 49 | for (i = 100; i < 105; i++) | 54 | for (i = 100; i < 105; i++) |
| 50 | msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); | 55 | msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); |
| 51 | 56 | ||
| 57 | for (i = 124; i < mpic->irq_count; i++) | ||
| 58 | msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); | ||
| 59 | |||
| 60 | |||
| 52 | np = NULL; | 61 | np = NULL; |
| 53 | while ((np = of_find_all_nodes(np))) { | 62 | while ((np = of_find_all_nodes(np))) { |
| 54 | pr_debug("mpic: mapping hwirqs for %s\n", np->full_name); | 63 | pr_debug("mpic: mapping hwirqs for %s\n", np->full_name); |
diff --git a/arch/powerpc/sysdev/mpic_u3msi.c b/arch/powerpc/sysdev/mpic_u3msi.c index d3caf23e6312..bcbfe79c704b 100644 --- a/arch/powerpc/sysdev/mpic_u3msi.c +++ b/arch/powerpc/sysdev/mpic_u3msi.c | |||
| @@ -64,12 +64,12 @@ static u64 read_ht_magic_addr(struct pci_dev *pdev, unsigned int pos) | |||
| 64 | return addr; | 64 | return addr; |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | static u64 find_ht_magic_addr(struct pci_dev *pdev) | 67 | static u64 find_ht_magic_addr(struct pci_dev *pdev, unsigned int hwirq) |
| 68 | { | 68 | { |
| 69 | struct pci_bus *bus; | 69 | struct pci_bus *bus; |
| 70 | unsigned int pos; | 70 | unsigned int pos; |
| 71 | 71 | ||
| 72 | for (bus = pdev->bus; bus; bus = bus->parent) { | 72 | for (bus = pdev->bus; bus && bus->self; bus = bus->parent) { |
| 73 | pos = pci_find_ht_capability(bus->self, HT_CAPTYPE_MSI_MAPPING); | 73 | pos = pci_find_ht_capability(bus->self, HT_CAPTYPE_MSI_MAPPING); |
| 74 | if (pos) | 74 | if (pos) |
| 75 | return read_ht_magic_addr(bus->self, pos); | 75 | return read_ht_magic_addr(bus->self, pos); |
| @@ -78,13 +78,41 @@ static u64 find_ht_magic_addr(struct pci_dev *pdev) | |||
| 78 | return 0; | 78 | return 0; |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | static u64 find_u4_magic_addr(struct pci_dev *pdev, unsigned int hwirq) | ||
| 82 | { | ||
| 83 | struct pci_controller *hose = pci_bus_to_host(pdev->bus); | ||
| 84 | |||
| 85 | /* U4 PCIe MSIs need to write to the special register in | ||
| 86 | * the bridge that generates interrupts. There should be | ||
| 87 | * theorically a register at 0xf8005000 where you just write | ||
| 88 | * the MSI number and that triggers the right interrupt, but | ||
| 89 | * unfortunately, this is busted in HW, the bridge endian swaps | ||
| 90 | * the value and hits the wrong nibble in the register. | ||
| 91 | * | ||
| 92 | * So instead we use another register set which is used normally | ||
| 93 | * for converting HT interrupts to MPIC interrupts, which decodes | ||
| 94 | * the interrupt number as part of the low address bits | ||
| 95 | * | ||
| 96 | * This will not work if we ever use more than one legacy MSI in | ||
| 97 | * a block but we never do. For one MSI or multiple MSI-X where | ||
| 98 | * each interrupt address can be specified separately, it works | ||
| 99 | * just fine. | ||
| 100 | */ | ||
| 101 | if (of_device_is_compatible(hose->dn, "u4-pcie") || | ||
| 102 | of_device_is_compatible(hose->dn, "U4-pcie")) | ||
| 103 | return 0xf8004000 | (hwirq << 4); | ||
| 104 | |||
| 105 | return 0; | ||
| 106 | } | ||
| 107 | |||
| 81 | static int u3msi_msi_check_device(struct pci_dev *pdev, int nvec, int type) | 108 | static int u3msi_msi_check_device(struct pci_dev *pdev, int nvec, int type) |
| 82 | { | 109 | { |
| 83 | if (type == PCI_CAP_ID_MSIX) | 110 | if (type == PCI_CAP_ID_MSIX) |
| 84 | pr_debug("u3msi: MSI-X untested, trying anyway.\n"); | 111 | pr_debug("u3msi: MSI-X untested, trying anyway.\n"); |
| 85 | 112 | ||
| 86 | /* If we can't find a magic address then MSI ain't gonna work */ | 113 | /* If we can't find a magic address then MSI ain't gonna work */ |
| 87 | if (find_ht_magic_addr(pdev) == 0) { | 114 | if (find_ht_magic_addr(pdev, 0) == 0 && |
| 115 | find_u4_magic_addr(pdev, 0) == 0) { | ||
| 88 | pr_debug("u3msi: no magic address found for %s\n", | 116 | pr_debug("u3msi: no magic address found for %s\n", |
| 89 | pci_name(pdev)); | 117 | pci_name(pdev)); |
| 90 | return -ENXIO; | 118 | return -ENXIO; |
| @@ -118,10 +146,6 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
| 118 | u64 addr; | 146 | u64 addr; |
| 119 | int hwirq; | 147 | int hwirq; |
| 120 | 148 | ||
| 121 | addr = find_ht_magic_addr(pdev); | ||
| 122 | msg.address_lo = addr & 0xFFFFFFFF; | ||
| 123 | msg.address_hi = addr >> 32; | ||
| 124 | |||
| 125 | list_for_each_entry(entry, &pdev->msi_list, list) { | 149 | list_for_each_entry(entry, &pdev->msi_list, list) { |
| 126 | hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap, 1); | 150 | hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap, 1); |
| 127 | if (hwirq < 0) { | 151 | if (hwirq < 0) { |
| @@ -129,6 +153,12 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
| 129 | return hwirq; | 153 | return hwirq; |
| 130 | } | 154 | } |
| 131 | 155 | ||
| 156 | addr = find_ht_magic_addr(pdev, hwirq); | ||
| 157 | if (addr == 0) | ||
| 158 | addr = find_u4_magic_addr(pdev, hwirq); | ||
| 159 | msg.address_lo = addr & 0xFFFFFFFF; | ||
| 160 | msg.address_hi = addr >> 32; | ||
| 161 | |||
| 132 | virq = irq_create_mapping(msi_mpic->irqhost, hwirq); | 162 | virq = irq_create_mapping(msi_mpic->irqhost, hwirq); |
| 133 | if (virq == NO_IRQ) { | 163 | if (virq == NO_IRQ) { |
| 134 | pr_debug("u3msi: failed mapping hwirq 0x%x\n", hwirq); | 164 | pr_debug("u3msi: failed mapping hwirq 0x%x\n", hwirq); |
| @@ -143,6 +173,8 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
| 143 | pr_debug("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n", | 173 | pr_debug("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n", |
| 144 | virq, hwirq, (unsigned long)addr); | 174 | virq, hwirq, (unsigned long)addr); |
| 145 | 175 | ||
| 176 | printk("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n", | ||
| 177 | virq, hwirq, (unsigned long)addr); | ||
| 146 | msg.data = hwirq; | 178 | msg.data = hwirq; |
| 147 | write_msi_msg(virq, &msg); | 179 | write_msi_msg(virq, &msg); |
| 148 | 180 | ||
diff --git a/drivers/base/memory.c b/drivers/base/memory.c index c4c8f2e1dd15..d7d77d4a402c 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c | |||
| @@ -63,6 +63,20 @@ void unregister_memory_notifier(struct notifier_block *nb) | |||
| 63 | } | 63 | } |
| 64 | EXPORT_SYMBOL(unregister_memory_notifier); | 64 | EXPORT_SYMBOL(unregister_memory_notifier); |
| 65 | 65 | ||
| 66 | static ATOMIC_NOTIFIER_HEAD(memory_isolate_chain); | ||
| 67 | |||
| 68 | int register_memory_isolate_notifier(struct notifier_block *nb) | ||
| 69 | { | ||
| 70 | return atomic_notifier_chain_register(&memory_isolate_chain, nb); | ||
| 71 | } | ||
| 72 | EXPORT_SYMBOL(register_memory_isolate_notifier); | ||
| 73 | |||
| 74 | void unregister_memory_isolate_notifier(struct notifier_block *nb) | ||
| 75 | { | ||
| 76 | atomic_notifier_chain_unregister(&memory_isolate_chain, nb); | ||
| 77 | } | ||
| 78 | EXPORT_SYMBOL(unregister_memory_isolate_notifier); | ||
| 79 | |||
| 66 | /* | 80 | /* |
| 67 | * register_memory - Setup a sysfs device for a memory block | 81 | * register_memory - Setup a sysfs device for a memory block |
| 68 | */ | 82 | */ |
| @@ -157,6 +171,11 @@ int memory_notify(unsigned long val, void *v) | |||
| 157 | return blocking_notifier_call_chain(&memory_chain, val, v); | 171 | return blocking_notifier_call_chain(&memory_chain, val, v); |
| 158 | } | 172 | } |
| 159 | 173 | ||
| 174 | int memory_isolate_notify(unsigned long val, void *v) | ||
| 175 | { | ||
| 176 | return atomic_notifier_call_chain(&memory_isolate_chain, val, v); | ||
| 177 | } | ||
| 178 | |||
| 160 | /* | 179 | /* |
| 161 | * MEMORY_HOTPLUG depends on SPARSEMEM in mm/Kconfig, so it is | 180 | * MEMORY_HOTPLUG depends on SPARSEMEM in mm/Kconfig, so it is |
| 162 | * OK to have direct references to sparsemem variables in here. | 181 | * OK to have direct references to sparsemem variables in here. |
diff --git a/include/linux/memory.h b/include/linux/memory.h index 37fa19b34ef5..1adfe779eb99 100644 --- a/include/linux/memory.h +++ b/include/linux/memory.h | |||
| @@ -50,6 +50,19 @@ struct memory_notify { | |||
| 50 | int status_change_nid; | 50 | int status_change_nid; |
| 51 | }; | 51 | }; |
| 52 | 52 | ||
| 53 | /* | ||
| 54 | * During pageblock isolation, count the number of pages within the | ||
| 55 | * range [start_pfn, start_pfn + nr_pages) which are owned by code | ||
| 56 | * in the notifier chain. | ||
| 57 | */ | ||
| 58 | #define MEM_ISOLATE_COUNT (1<<0) | ||
| 59 | |||
| 60 | struct memory_isolate_notify { | ||
| 61 | unsigned long start_pfn; /* Start of range to check */ | ||
| 62 | unsigned int nr_pages; /* # pages in range to check */ | ||
| 63 | unsigned int pages_found; /* # pages owned found by callbacks */ | ||
| 64 | }; | ||
| 65 | |||
| 53 | struct notifier_block; | 66 | struct notifier_block; |
| 54 | struct mem_section; | 67 | struct mem_section; |
| 55 | 68 | ||
| @@ -76,14 +89,28 @@ static inline int memory_notify(unsigned long val, void *v) | |||
| 76 | { | 89 | { |
| 77 | return 0; | 90 | return 0; |
| 78 | } | 91 | } |
| 92 | static inline int register_memory_isolate_notifier(struct notifier_block *nb) | ||
| 93 | { | ||
| 94 | return 0; | ||
| 95 | } | ||
| 96 | static inline void unregister_memory_isolate_notifier(struct notifier_block *nb) | ||
| 97 | { | ||
| 98 | } | ||
| 99 | static inline int memory_isolate_notify(unsigned long val, void *v) | ||
| 100 | { | ||
| 101 | return 0; | ||
| 102 | } | ||
| 79 | #else | 103 | #else |
| 80 | extern int register_memory_notifier(struct notifier_block *nb); | 104 | extern int register_memory_notifier(struct notifier_block *nb); |
| 81 | extern void unregister_memory_notifier(struct notifier_block *nb); | 105 | extern void unregister_memory_notifier(struct notifier_block *nb); |
| 106 | extern int register_memory_isolate_notifier(struct notifier_block *nb); | ||
| 107 | extern void unregister_memory_isolate_notifier(struct notifier_block *nb); | ||
| 82 | extern int register_new_memory(int, struct mem_section *); | 108 | extern int register_new_memory(int, struct mem_section *); |
| 83 | extern int unregister_memory_section(struct mem_section *); | 109 | extern int unregister_memory_section(struct mem_section *); |
| 84 | extern int memory_dev_init(void); | 110 | extern int memory_dev_init(void); |
| 85 | extern int remove_memory_block(unsigned long, struct mem_section *, int); | 111 | extern int remove_memory_block(unsigned long, struct mem_section *, int); |
| 86 | extern int memory_notify(unsigned long val, void *v); | 112 | extern int memory_notify(unsigned long val, void *v); |
| 113 | extern int memory_isolate_notify(unsigned long val, void *v); | ||
| 87 | extern struct memory_block *find_memory_block(struct mem_section *); | 114 | extern struct memory_block *find_memory_block(struct mem_section *); |
| 88 | #define CONFIG_MEM_BLOCK_SIZE (PAGES_PER_SECTION<<PAGE_SHIFT) | 115 | #define CONFIG_MEM_BLOCK_SIZE (PAGES_PER_SECTION<<PAGE_SHIFT) |
| 89 | enum mem_add_context { BOOT, HOTPLUG }; | 116 | enum mem_add_context { BOOT, HOTPLUG }; |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 4e869657cb51..d79b92580561 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
| @@ -48,6 +48,7 @@ | |||
| 48 | #include <linux/page_cgroup.h> | 48 | #include <linux/page_cgroup.h> |
| 49 | #include <linux/debugobjects.h> | 49 | #include <linux/debugobjects.h> |
| 50 | #include <linux/kmemleak.h> | 50 | #include <linux/kmemleak.h> |
| 51 | #include <linux/memory.h> | ||
| 51 | #include <trace/events/kmem.h> | 52 | #include <trace/events/kmem.h> |
| 52 | 53 | ||
| 53 | #include <asm/tlbflush.h> | 54 | #include <asm/tlbflush.h> |
| @@ -5008,23 +5009,65 @@ void set_pageblock_flags_group(struct page *page, unsigned long flags, | |||
| 5008 | int set_migratetype_isolate(struct page *page) | 5009 | int set_migratetype_isolate(struct page *page) |
| 5009 | { | 5010 | { |
| 5010 | struct zone *zone; | 5011 | struct zone *zone; |
| 5011 | unsigned long flags; | 5012 | struct page *curr_page; |
| 5013 | unsigned long flags, pfn, iter; | ||
| 5014 | unsigned long immobile = 0; | ||
| 5015 | struct memory_isolate_notify arg; | ||
| 5016 | int notifier_ret; | ||
| 5012 | int ret = -EBUSY; | 5017 | int ret = -EBUSY; |
| 5013 | int zone_idx; | 5018 | int zone_idx; |
| 5014 | 5019 | ||
| 5015 | zone = page_zone(page); | 5020 | zone = page_zone(page); |
| 5016 | zone_idx = zone_idx(zone); | 5021 | zone_idx = zone_idx(zone); |
| 5022 | |||
| 5017 | spin_lock_irqsave(&zone->lock, flags); | 5023 | spin_lock_irqsave(&zone->lock, flags); |
| 5024 | if (get_pageblock_migratetype(page) == MIGRATE_MOVABLE || | ||
| 5025 | zone_idx == ZONE_MOVABLE) { | ||
| 5026 | ret = 0; | ||
| 5027 | goto out; | ||
| 5028 | } | ||
| 5029 | |||
| 5030 | pfn = page_to_pfn(page); | ||
| 5031 | arg.start_pfn = pfn; | ||
| 5032 | arg.nr_pages = pageblock_nr_pages; | ||
| 5033 | arg.pages_found = 0; | ||
| 5034 | |||
| 5018 | /* | 5035 | /* |
| 5019 | * In future, more migrate types will be able to be isolation target. | 5036 | * It may be possible to isolate a pageblock even if the |
| 5037 | * migratetype is not MIGRATE_MOVABLE. The memory isolation | ||
| 5038 | * notifier chain is used by balloon drivers to return the | ||
| 5039 | * number of pages in a range that are held by the balloon | ||
| 5040 | * driver to shrink memory. If all the pages are accounted for | ||
| 5041 | * by balloons, are free, or on the LRU, isolation can continue. | ||
| 5042 | * Later, for example, when memory hotplug notifier runs, these | ||
| 5043 | * pages reported as "can be isolated" should be isolated(freed) | ||
| 5044 | * by the balloon driver through the memory notifier chain. | ||
| 5020 | */ | 5045 | */ |
| 5021 | if (get_pageblock_migratetype(page) != MIGRATE_MOVABLE && | 5046 | notifier_ret = memory_isolate_notify(MEM_ISOLATE_COUNT, &arg); |
| 5022 | zone_idx != ZONE_MOVABLE) | 5047 | notifier_ret = notifier_to_errno(notifier_ret); |
| 5048 | if (notifier_ret || !arg.pages_found) | ||
| 5023 | goto out; | 5049 | goto out; |
| 5024 | set_pageblock_migratetype(page, MIGRATE_ISOLATE); | 5050 | |
| 5025 | move_freepages_block(zone, page, MIGRATE_ISOLATE); | 5051 | for (iter = pfn; iter < (pfn + pageblock_nr_pages); iter++) { |
| 5026 | ret = 0; | 5052 | if (!pfn_valid_within(pfn)) |
| 5053 | continue; | ||
| 5054 | |||
| 5055 | curr_page = pfn_to_page(iter); | ||
| 5056 | if (!page_count(curr_page) || PageLRU(curr_page)) | ||
| 5057 | continue; | ||
| 5058 | |||
| 5059 | immobile++; | ||
| 5060 | } | ||
| 5061 | |||
| 5062 | if (arg.pages_found == immobile) | ||
| 5063 | ret = 0; | ||
| 5064 | |||
| 5027 | out: | 5065 | out: |
| 5066 | if (!ret) { | ||
| 5067 | set_pageblock_migratetype(page, MIGRATE_ISOLATE); | ||
| 5068 | move_freepages_block(zone, page, MIGRATE_ISOLATE); | ||
| 5069 | } | ||
| 5070 | |||
| 5028 | spin_unlock_irqrestore(&zone->lock, flags); | 5071 | spin_unlock_irqrestore(&zone->lock, flags); |
| 5029 | if (!ret) | 5072 | if (!ret) |
| 5030 | drain_all_pages(); | 5073 | drain_all_pages(); |
