diff options
161 files changed, 5477 insertions, 3284 deletions
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/board.txt b/Documentation/devicetree/bindings/powerpc/fsl/board.txt index 700dec4774fa..cff38bdbc0e4 100644 --- a/Documentation/devicetree/bindings/powerpc/fsl/board.txt +++ b/Documentation/devicetree/bindings/powerpc/fsl/board.txt | |||
| @@ -84,3 +84,19 @@ Example: | |||
| 84 | compatible = "fsl,bsc9132qds-fpga", "fsl,fpga-qixis-i2c"; | 84 | compatible = "fsl,bsc9132qds-fpga", "fsl,fpga-qixis-i2c"; |
| 85 | reg = <0x66>; | 85 | reg = <0x66>; |
| 86 | }; | 86 | }; |
| 87 | |||
| 88 | * Freescale on-board CPLD | ||
| 89 | |||
| 90 | Some Freescale boards like T1040RDB have an on board CPLD connected. | ||
| 91 | |||
| 92 | Required properties: | ||
| 93 | - compatible: Should be a board-specific string like "fsl,<board>-cpld" | ||
| 94 | Example: | ||
| 95 | "fsl,t1040rdb-cpld", "fsl,t1042rdb-cpld", "fsl,t1042rdb_pi-cpld" | ||
| 96 | - reg: should describe CPLD registers | ||
| 97 | |||
| 98 | Example: | ||
| 99 | cpld@3,0 { | ||
| 100 | compatible = "fsl,t1040rdb-cpld"; | ||
| 101 | reg = <3 0 0x300>; | ||
| 102 | }; | ||
diff --git a/Documentation/vfio.txt b/Documentation/vfio.txt index b9ca02370d46..96978eced341 100644 --- a/Documentation/vfio.txt +++ b/Documentation/vfio.txt | |||
| @@ -305,7 +305,15 @@ faster, the map/unmap handling has been implemented in real mode which provides | |||
| 305 | an excellent performance which has limitations such as inability to do | 305 | an excellent performance which has limitations such as inability to do |
| 306 | locked pages accounting in real time. | 306 | locked pages accounting in real time. |
| 307 | 307 | ||
| 308 | So 3 additional ioctls have been added: | 308 | 4) According to sPAPR specification, A Partitionable Endpoint (PE) is an I/O |
| 309 | subtree that can be treated as a unit for the purposes of partitioning and | ||
| 310 | error recovery. A PE may be a single or multi-function IOA (IO Adapter), a | ||
| 311 | function of a multi-function IOA, or multiple IOAs (possibly including switch | ||
| 312 | and bridge structures above the multiple IOAs). PPC64 guests detect PCI errors | ||
| 313 | and recover from them via EEH RTAS services, which works on the basis of | ||
| 314 | additional ioctl commands. | ||
| 315 | |||
| 316 | So 4 additional ioctls have been added: | ||
| 309 | 317 | ||
| 310 | VFIO_IOMMU_SPAPR_TCE_GET_INFO - returns the size and the start | 318 | VFIO_IOMMU_SPAPR_TCE_GET_INFO - returns the size and the start |
| 311 | of the DMA window on the PCI bus. | 319 | of the DMA window on the PCI bus. |
| @@ -316,9 +324,12 @@ So 3 additional ioctls have been added: | |||
| 316 | 324 | ||
| 317 | VFIO_IOMMU_DISABLE - disables the container. | 325 | VFIO_IOMMU_DISABLE - disables the container. |
| 318 | 326 | ||
| 327 | VFIO_EEH_PE_OP - provides an API for EEH setup, error detection and recovery. | ||
| 319 | 328 | ||
| 320 | The code flow from the example above should be slightly changed: | 329 | The code flow from the example above should be slightly changed: |
| 321 | 330 | ||
| 331 | struct vfio_eeh_pe_op pe_op = { .argsz = sizeof(pe_op), .flags = 0 }; | ||
| 332 | |||
| 322 | ..... | 333 | ..... |
| 323 | /* Add the group to the container */ | 334 | /* Add the group to the container */ |
| 324 | ioctl(group, VFIO_GROUP_SET_CONTAINER, &container); | 335 | ioctl(group, VFIO_GROUP_SET_CONTAINER, &container); |
| @@ -342,9 +353,79 @@ The code flow from the example above should be slightly changed: | |||
| 342 | dma_map.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE; | 353 | dma_map.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE; |
| 343 | 354 | ||
| 344 | /* Check here is .iova/.size are within DMA window from spapr_iommu_info */ | 355 | /* Check here is .iova/.size are within DMA window from spapr_iommu_info */ |
| 345 | |||
| 346 | ioctl(container, VFIO_IOMMU_MAP_DMA, &dma_map); | 356 | ioctl(container, VFIO_IOMMU_MAP_DMA, &dma_map); |
| 347 | ..... | 357 | |
| 358 | /* Get a file descriptor for the device */ | ||
| 359 | device = ioctl(group, VFIO_GROUP_GET_DEVICE_FD, "0000:06:0d.0"); | ||
| 360 | |||
| 361 | .... | ||
| 362 | |||
| 363 | /* Gratuitous device reset and go... */ | ||
| 364 | ioctl(device, VFIO_DEVICE_RESET); | ||
| 365 | |||
| 366 | /* Make sure EEH is supported */ | ||
| 367 | ioctl(container, VFIO_CHECK_EXTENSION, VFIO_EEH); | ||
| 368 | |||
| 369 | /* Enable the EEH functionality on the device */ | ||
| 370 | pe_op.op = VFIO_EEH_PE_ENABLE; | ||
| 371 | ioctl(container, VFIO_EEH_PE_OP, &pe_op); | ||
| 372 | |||
| 373 | /* You're suggested to create additional data struct to represent | ||
| 374 | * PE, and put child devices belonging to same IOMMU group to the | ||
| 375 | * PE instance for later reference. | ||
| 376 | */ | ||
| 377 | |||
| 378 | /* Check the PE's state and make sure it's in functional state */ | ||
| 379 | pe_op.op = VFIO_EEH_PE_GET_STATE; | ||
| 380 | ioctl(container, VFIO_EEH_PE_OP, &pe_op); | ||
| 381 | |||
| 382 | /* Save device state using pci_save_state(). | ||
| 383 | * EEH should be enabled on the specified device. | ||
| 384 | */ | ||
| 385 | |||
| 386 | .... | ||
| 387 | |||
| 388 | /* When 0xFF's returned from reading PCI config space or IO BARs | ||
| 389 | * of the PCI device. Check the PE's state to see if that has been | ||
| 390 | * frozen. | ||
| 391 | */ | ||
| 392 | ioctl(container, VFIO_EEH_PE_OP, &pe_op); | ||
| 393 | |||
| 394 | /* Waiting for pending PCI transactions to be completed and don't | ||
| 395 | * produce any more PCI traffic from/to the affected PE until | ||
| 396 | * recovery is finished. | ||
| 397 | */ | ||
| 398 | |||
| 399 | /* Enable IO for the affected PE and collect logs. Usually, the | ||
| 400 | * standard part of PCI config space, AER registers are dumped | ||
| 401 | * as logs for further analysis. | ||
| 402 | */ | ||
| 403 | pe_op.op = VFIO_EEH_PE_UNFREEZE_IO; | ||
| 404 | ioctl(container, VFIO_EEH_PE_OP, &pe_op); | ||
| 405 | |||
| 406 | /* | ||
| 407 | * Issue PE reset: hot or fundamental reset. Usually, hot reset | ||
| 408 | * is enough. However, the firmware of some PCI adapters would | ||
| 409 | * require fundamental reset. | ||
| 410 | */ | ||
| 411 | pe_op.op = VFIO_EEH_PE_RESET_HOT; | ||
| 412 | ioctl(container, VFIO_EEH_PE_OP, &pe_op); | ||
| 413 | pe_op.op = VFIO_EEH_PE_RESET_DEACTIVATE; | ||
| 414 | ioctl(container, VFIO_EEH_PE_OP, &pe_op); | ||
| 415 | |||
| 416 | /* Configure the PCI bridges for the affected PE */ | ||
| 417 | pe_op.op = VFIO_EEH_PE_CONFIGURE; | ||
| 418 | ioctl(container, VFIO_EEH_PE_OP, &pe_op); | ||
| 419 | |||
| 420 | /* Restored state we saved at initialization time. pci_restore_state() | ||
| 421 | * is good enough as an example. | ||
| 422 | */ | ||
| 423 | |||
| 424 | /* Hopefully, error is recovered successfully. Now, you can resume to | ||
| 425 | * start PCI traffic to/from the affected PE. | ||
| 426 | */ | ||
| 427 | |||
| 428 | .... | ||
| 348 | 429 | ||
| 349 | ------------------------------------------------------------------------------- | 430 | ------------------------------------------------------------------------------- |
| 350 | 431 | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 05e545096100..946a67e6c4ea 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -5424,6 +5424,7 @@ F: arch/powerpc/boot/rs6000.h | |||
| 5424 | LINUX FOR POWERPC (32-BIT AND 64-BIT) | 5424 | LINUX FOR POWERPC (32-BIT AND 64-BIT) |
| 5425 | M: Benjamin Herrenschmidt <benh@kernel.crashing.org> | 5425 | M: Benjamin Herrenschmidt <benh@kernel.crashing.org> |
| 5426 | M: Paul Mackerras <paulus@samba.org> | 5426 | M: Paul Mackerras <paulus@samba.org> |
| 5427 | M: Michael Ellerman <mpe@ellerman.id.au> | ||
| 5427 | W: http://www.penguinppc.org/ | 5428 | W: http://www.penguinppc.org/ |
| 5428 | L: linuxppc-dev@lists.ozlabs.org | 5429 | L: linuxppc-dev@lists.ozlabs.org |
| 5429 | Q: http://patchwork.ozlabs.org/project/linuxppc-dev/list/ | 5430 | Q: http://patchwork.ozlabs.org/project/linuxppc-dev/list/ |
| @@ -5465,16 +5466,17 @@ F: arch/powerpc/*/*/*virtex* | |||
| 5465 | 5466 | ||
| 5466 | LINUX FOR POWERPC EMBEDDED PPC8XX | 5467 | LINUX FOR POWERPC EMBEDDED PPC8XX |
| 5467 | M: Vitaly Bordug <vitb@kernel.crashing.org> | 5468 | M: Vitaly Bordug <vitb@kernel.crashing.org> |
| 5468 | M: Marcelo Tosatti <marcelo@kvack.org> | ||
| 5469 | W: http://www.penguinppc.org/ | 5469 | W: http://www.penguinppc.org/ |
| 5470 | L: linuxppc-dev@lists.ozlabs.org | 5470 | L: linuxppc-dev@lists.ozlabs.org |
| 5471 | S: Maintained | 5471 | S: Maintained |
| 5472 | F: arch/powerpc/platforms/8xx/ | 5472 | F: arch/powerpc/platforms/8xx/ |
| 5473 | 5473 | ||
| 5474 | LINUX FOR POWERPC EMBEDDED PPC83XX AND PPC85XX | 5474 | LINUX FOR POWERPC EMBEDDED PPC83XX AND PPC85XX |
| 5475 | M: Scott Wood <scottwood@freescale.com> | ||
| 5475 | M: Kumar Gala <galak@kernel.crashing.org> | 5476 | M: Kumar Gala <galak@kernel.crashing.org> |
| 5476 | W: http://www.penguinppc.org/ | 5477 | W: http://www.penguinppc.org/ |
| 5477 | L: linuxppc-dev@lists.ozlabs.org | 5478 | L: linuxppc-dev@lists.ozlabs.org |
| 5479 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/scottwood/linux.git | ||
| 5478 | S: Maintained | 5480 | S: Maintained |
| 5479 | F: arch/powerpc/platforms/83xx/ | 5481 | F: arch/powerpc/platforms/83xx/ |
| 5480 | F: arch/powerpc/platforms/85xx/ | 5482 | F: arch/powerpc/platforms/85xx/ |
diff --git a/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi b/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi index 5290df83ff30..69ce1026c948 100644 --- a/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi | |||
| @@ -359,6 +359,7 @@ | |||
| 359 | compatible = "fsl,qoriq-core-mux-1.0"; | 359 | compatible = "fsl,qoriq-core-mux-1.0"; |
| 360 | clocks = <&pll0 0>, <&pll0 1>, <&pll1 0>, <&pll1 1>; | 360 | clocks = <&pll0 0>, <&pll0 1>, <&pll1 0>, <&pll1 1>; |
| 361 | clock-names = "pll0", "pll0-div2", "pll1", "pll1-div2"; | 361 | clock-names = "pll0", "pll0-div2", "pll1", "pll1-div2"; |
| 362 | clock-output-names = "cmux2"; | ||
| 362 | }; | 363 | }; |
| 363 | 364 | ||
| 364 | mux3: mux3@60 { | 365 | mux3: mux3@60 { |
diff --git a/arch/powerpc/boot/dts/fsl/t2080si-post.dtsi b/arch/powerpc/boot/dts/fsl/t2080si-post.dtsi new file mode 100644 index 000000000000..082ec2044060 --- /dev/null +++ b/arch/powerpc/boot/dts/fsl/t2080si-post.dtsi | |||
| @@ -0,0 +1,69 @@ | |||
| 1 | /* | ||
| 2 | * T2080 Silicon/SoC Device Tree Source (post include) | ||
| 3 | * | ||
| 4 | * Copyright 2013 Freescale Semiconductor Inc. | ||
| 5 | * | ||
| 6 | * Redistribution and use in source and binary forms, with or without | ||
| 7 | * modification, are permitted provided that the following conditions are met: | ||
| 8 | * * Redistributions of source code must retain the above copyright | ||
| 9 | * notice, this list of conditions and the following disclaimer. | ||
| 10 | * * Redistributions in binary form must reproduce the above copyright | ||
| 11 | * notice, this list of conditions and the following disclaimer in the | ||
| 12 | * documentation and/or other materials provided with the distribution. | ||
| 13 | * * Neither the name of Freescale Semiconductor nor the | ||
| 14 | * names of its contributors may be used to endorse or promote products | ||
| 15 | * derived from this software without specific prior written permission. | ||
| 16 | * | ||
| 17 | * | ||
| 18 | * ALTERNATIVELY, this software may be distributed under the terms of the | ||
| 19 | * GNU General Public License ("GPL") as published by the Free Software | ||
| 20 | * Foundation, either version 2 of that License or (at your option) any | ||
| 21 | * later version. | ||
| 22 | * | ||
| 23 | * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY | ||
| 24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
| 25 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
| 26 | * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY | ||
| 27 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
| 28 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
| 29 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
| 30 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
| 32 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 33 | */ | ||
| 34 | |||
| 35 | /include/ "t2081si-post.dtsi" | ||
| 36 | |||
| 37 | &soc { | ||
| 38 | /include/ "qoriq-sata2-0.dtsi" | ||
| 39 | sata@220000 { | ||
| 40 | fsl,iommu-parent = <&pamu1>; | ||
| 41 | fsl,liodn-reg = <&guts 0x550>; /* SATA1LIODNR */ | ||
| 42 | }; | ||
| 43 | |||
| 44 | /include/ "qoriq-sata2-1.dtsi" | ||
| 45 | sata@221000 { | ||
| 46 | fsl,iommu-parent = <&pamu1>; | ||
| 47 | fsl,liodn-reg = <&guts 0x554>; /* SATA2LIODNR */ | ||
| 48 | }; | ||
| 49 | }; | ||
| 50 | |||
| 51 | &rio { | ||
| 52 | compatible = "fsl,srio"; | ||
| 53 | interrupts = <16 2 1 11>; | ||
| 54 | #address-cells = <2>; | ||
| 55 | #size-cells = <2>; | ||
| 56 | ranges; | ||
| 57 | |||
| 58 | port1 { | ||
| 59 | #address-cells = <2>; | ||
| 60 | #size-cells = <2>; | ||
| 61 | cell-index = <1>; | ||
| 62 | }; | ||
| 63 | |||
| 64 | port2 { | ||
| 65 | #address-cells = <2>; | ||
| 66 | #size-cells = <2>; | ||
| 67 | cell-index = <2>; | ||
| 68 | }; | ||
| 69 | }; | ||
diff --git a/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi b/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi new file mode 100644 index 000000000000..97479f0ce630 --- /dev/null +++ b/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi | |||
| @@ -0,0 +1,435 @@ | |||
| 1 | /* | ||
| 2 | * T2081 Silicon/SoC Device Tree Source (post include) | ||
| 3 | * | ||
| 4 | * Copyright 2013 Freescale Semiconductor Inc. | ||
| 5 | * | ||
| 6 | * Redistribution and use in source and binary forms, with or without | ||
| 7 | * modification, are permitted provided that the following conditions are met: | ||
| 8 | * * Redistributions of source code must retain the above copyright | ||
| 9 | * notice, this list of conditions and the following disclaimer. | ||
| 10 | * * Redistributions in binary form must reproduce the above copyright | ||
| 11 | * notice, this list of conditions and the following disclaimer in the | ||
| 12 | * documentation and/or other materials provided with the distribution. | ||
| 13 | * * Neither the name of Freescale Semiconductor nor the | ||
| 14 | * names of its contributors may be used to endorse or promote products | ||
| 15 | * derived from this software without specific prior written permission. | ||
| 16 | * | ||
| 17 | * | ||
| 18 | * ALTERNATIVELY, this software may be distributed under the terms of the | ||
| 19 | * GNU General Public License ("GPL") as published by the Free Software | ||
| 20 | * Foundation, either version 2 of that License or (at your option) any | ||
| 21 | * later version. | ||
| 22 | * | ||
| 23 | * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY | ||
| 24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
| 25 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
| 26 | * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY | ||
| 27 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
| 28 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
| 29 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
| 30 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
| 32 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 33 | */ | ||
| 34 | |||
| 35 | &ifc { | ||
| 36 | #address-cells = <2>; | ||
| 37 | #size-cells = <1>; | ||
| 38 | compatible = "fsl,ifc", "simple-bus"; | ||
| 39 | interrupts = <25 2 0 0>; | ||
| 40 | }; | ||
| 41 | |||
| 42 | /* controller at 0x240000 */ | ||
| 43 | &pci0 { | ||
| 44 | compatible = "fsl,t2080-pcie", "fsl,qoriq-pcie-v3.0", "fsl,qoriq-pcie"; | ||
| 45 | device_type = "pci"; | ||
| 46 | #size-cells = <2>; | ||
| 47 | #address-cells = <3>; | ||
| 48 | bus-range = <0x0 0xff>; | ||
| 49 | interrupts = <20 2 0 0>; | ||
| 50 | fsl,iommu-parent = <&pamu0>; | ||
| 51 | pcie@0 { | ||
| 52 | reg = <0 0 0 0 0>; | ||
| 53 | #interrupt-cells = <1>; | ||
| 54 | #size-cells = <2>; | ||
| 55 | #address-cells = <3>; | ||
| 56 | device_type = "pci"; | ||
| 57 | interrupts = <20 2 0 0>; | ||
| 58 | interrupt-map-mask = <0xf800 0 0 7>; | ||
| 59 | interrupt-map = < | ||
| 60 | /* IDSEL 0x0 */ | ||
| 61 | 0000 0 0 1 &mpic 40 1 0 0 | ||
| 62 | 0000 0 0 2 &mpic 1 1 0 0 | ||
| 63 | 0000 0 0 3 &mpic 2 1 0 0 | ||
| 64 | 0000 0 0 4 &mpic 3 1 0 0 | ||
| 65 | >; | ||
| 66 | }; | ||
| 67 | }; | ||
| 68 | |||
| 69 | /* controller at 0x250000 */ | ||
| 70 | &pci1 { | ||
| 71 | compatible = "fsl,t2080-pcie", "fsl,qoriq-pcie-v3.0", "fsl,qoriq-pcie"; | ||
| 72 | device_type = "pci"; | ||
| 73 | #size-cells = <2>; | ||
| 74 | #address-cells = <3>; | ||
| 75 | bus-range = <0 0xff>; | ||
| 76 | interrupts = <21 2 0 0>; | ||
| 77 | fsl,iommu-parent = <&pamu0>; | ||
| 78 | pcie@0 { | ||
| 79 | reg = <0 0 0 0 0>; | ||
| 80 | #interrupt-cells = <1>; | ||
| 81 | #size-cells = <2>; | ||
| 82 | #address-cells = <3>; | ||
| 83 | device_type = "pci"; | ||
| 84 | interrupts = <21 2 0 0>; | ||
| 85 | interrupt-map-mask = <0xf800 0 0 7>; | ||
| 86 | interrupt-map = < | ||
| 87 | /* IDSEL 0x0 */ | ||
| 88 | 0000 0 0 1 &mpic 41 1 0 0 | ||
| 89 | 0000 0 0 2 &mpic 5 1 0 0 | ||
| 90 | 0000 0 0 3 &mpic 6 1 0 0 | ||
| 91 | 0000 0 0 4 &mpic 7 1 0 0 | ||
| 92 | >; | ||
| 93 | }; | ||
| 94 | }; | ||
| 95 | |||
| 96 | /* controller at 0x260000 */ | ||
| 97 | &pci2 { | ||
| 98 | compatible = "fsl,t2080-pcie", "fsl,qoriq-pcie-v3.0", "fsl,qoriq-pcie"; | ||
| 99 | device_type = "pci"; | ||
| 100 | #size-cells = <2>; | ||
| 101 | #address-cells = <3>; | ||
| 102 | bus-range = <0x0 0xff>; | ||
| 103 | interrupts = <22 2 0 0>; | ||
| 104 | fsl,iommu-parent = <&pamu0>; | ||
| 105 | pcie@0 { | ||
| 106 | reg = <0 0 0 0 0>; | ||
| 107 | #interrupt-cells = <1>; | ||
| 108 | #size-cells = <2>; | ||
| 109 | #address-cells = <3>; | ||
| 110 | device_type = "pci"; | ||
| 111 | interrupts = <22 2 0 0>; | ||
| 112 | interrupt-map-mask = <0xf800 0 0 7>; | ||
| 113 | interrupt-map = < | ||
| 114 | /* IDSEL 0x0 */ | ||
| 115 | 0000 0 0 1 &mpic 42 1 0 0 | ||
| 116 | 0000 0 0 2 &mpic 9 1 0 0 | ||
| 117 | 0000 0 0 3 &mpic 10 1 0 0 | ||
| 118 | 0000 0 0 4 &mpic 11 1 0 0 | ||
| 119 | >; | ||
| 120 | }; | ||
| 121 | }; | ||
| 122 | |||
| 123 | /* controller at 0x270000 */ | ||
| 124 | &pci3 { | ||
| 125 | compatible = "fsl,t2080-pcie", "fsl,qoriq-pcie-v3.0", "fsl,qoriq-pcie"; | ||
| 126 | device_type = "pci"; | ||
| 127 | #size-cells = <2>; | ||
| 128 | #address-cells = <3>; | ||
| 129 | bus-range = <0x0 0xff>; | ||
| 130 | interrupts = <23 2 0 0>; | ||
| 131 | fsl,iommu-parent = <&pamu0>; | ||
| 132 | pcie@0 { | ||
| 133 | reg = <0 0 0 0 0>; | ||
| 134 | #interrupt-cells = <1>; | ||
| 135 | #size-cells = <2>; | ||
| 136 | #address-cells = <3>; | ||
| 137 | device_type = "pci"; | ||
| 138 | interrupts = <23 2 0 0>; | ||
| 139 | interrupt-map-mask = <0xf800 0 0 7>; | ||
| 140 | interrupt-map = < | ||
| 141 | /* IDSEL 0x0 */ | ||
| 142 | 0000 0 0 1 &mpic 43 1 0 0 | ||
| 143 | 0000 0 0 2 &mpic 0 1 0 0 | ||
| 144 | 0000 0 0 3 &mpic 4 1 0 0 | ||
| 145 | 0000 0 0 4 &mpic 8 1 0 0 | ||
| 146 | >; | ||
| 147 | }; | ||
| 148 | }; | ||
| 149 | |||
| 150 | &dcsr { | ||
| 151 | #address-cells = <1>; | ||
| 152 | #size-cells = <1>; | ||
| 153 | compatible = "fsl,dcsr", "simple-bus"; | ||
| 154 | |||
| 155 | dcsr-epu@0 { | ||
| 156 | compatible = "fsl,t2080-dcsr-epu", "fsl,dcsr-epu"; | ||
| 157 | interrupts = <52 2 0 0 | ||
| 158 | 84 2 0 0 | ||
| 159 | 85 2 0 0 | ||
| 160 | 94 2 0 0 | ||
| 161 | 95 2 0 0>; | ||
| 162 | reg = <0x0 0x1000>; | ||
| 163 | }; | ||
| 164 | dcsr-npc { | ||
| 165 | compatible = "fsl,t2080-dcsr-cnpc", "fsl,dcsr-cnpc"; | ||
| 166 | reg = <0x1000 0x1000 0x1002000 0x10000>; | ||
| 167 | }; | ||
| 168 | dcsr-nxc@2000 { | ||
| 169 | compatible = "fsl,dcsr-nxc"; | ||
| 170 | reg = <0x2000 0x1000>; | ||
| 171 | }; | ||
| 172 | dcsr-corenet { | ||
| 173 | compatible = "fsl,dcsr-corenet"; | ||
| 174 | reg = <0x8000 0x1000 0x1A000 0x1000>; | ||
| 175 | }; | ||
| 176 | dcsr-ocn@11000 { | ||
| 177 | compatible = "fsl,t2080-dcsr-ocn", "fsl,dcsr-ocn"; | ||
| 178 | reg = <0x11000 0x1000>; | ||
| 179 | }; | ||
| 180 | dcsr-ddr@12000 { | ||
| 181 | compatible = "fsl,dcsr-ddr"; | ||
| 182 | dev-handle = <&ddr1>; | ||
| 183 | reg = <0x12000 0x1000>; | ||
| 184 | }; | ||
| 185 | dcsr-nal@18000 { | ||
| 186 | compatible = "fsl,t2080-dcsr-nal", "fsl,dcsr-nal"; | ||
| 187 | reg = <0x18000 0x1000>; | ||
| 188 | }; | ||
| 189 | dcsr-rcpm@22000 { | ||
| 190 | compatible = "fsl,t2080-dcsr-rcpm", "fsl,dcsr-rcpm"; | ||
| 191 | reg = <0x22000 0x1000>; | ||
| 192 | }; | ||
| 193 | dcsr-snpc@30000 { | ||
| 194 | compatible = "fsl,t2080-dcsr-snpc", "fsl,dcsr-snpc"; | ||
| 195 | reg = <0x30000 0x1000 0x1022000 0x10000>; | ||
| 196 | }; | ||
| 197 | dcsr-snpc@31000 { | ||
| 198 | compatible = "fsl,t2080-dcsr-snpc", "fsl,dcsr-snpc"; | ||
| 199 | reg = <0x31000 0x1000 0x1042000 0x10000>; | ||
| 200 | }; | ||
| 201 | dcsr-snpc@32000 { | ||
| 202 | compatible = "fsl,t2080-dcsr-snpc", "fsl,dcsr-snpc"; | ||
| 203 | reg = <0x32000 0x1000 0x1062000 0x10000>; | ||
| 204 | }; | ||
| 205 | dcsr-cpu-sb-proxy@100000 { | ||
| 206 | compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; | ||
| 207 | cpu-handle = <&cpu0>; | ||
| 208 | reg = <0x100000 0x1000 0x101000 0x1000>; | ||
| 209 | }; | ||
| 210 | dcsr-cpu-sb-proxy@108000 { | ||
| 211 | compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; | ||
| 212 | cpu-handle = <&cpu1>; | ||
| 213 | reg = <0x108000 0x1000 0x109000 0x1000>; | ||
| 214 | }; | ||
| 215 | dcsr-cpu-sb-proxy@110000 { | ||
| 216 | compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; | ||
| 217 | cpu-handle = <&cpu2>; | ||
| 218 | reg = <0x110000 0x1000 0x111000 0x1000>; | ||
| 219 | }; | ||
| 220 | dcsr-cpu-sb-proxy@118000 { | ||
| 221 | compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; | ||
| 222 | cpu-handle = <&cpu3>; | ||
| 223 | reg = <0x118000 0x1000 0x119000 0x1000>; | ||
| 224 | }; | ||
| 225 | }; | ||
| 226 | |||
| 227 | &soc { | ||
| 228 | #address-cells = <1>; | ||
| 229 | #size-cells = <1>; | ||
| 230 | device_type = "soc"; | ||
| 231 | compatible = "simple-bus"; | ||
| 232 | |||
| 233 | soc-sram-error { | ||
| 234 | compatible = "fsl,soc-sram-error"; | ||
| 235 | interrupts = <16 2 1 29>; | ||
| 236 | }; | ||
| 237 | |||
| 238 | corenet-law@0 { | ||
| 239 | compatible = "fsl,corenet-law"; | ||
| 240 | reg = <0x0 0x1000>; | ||
| 241 | fsl,num-laws = <32>; | ||
| 242 | }; | ||
| 243 | |||
| 244 | ddr1: memory-controller@8000 { | ||
| 245 | compatible = "fsl,qoriq-memory-controller-v4.7", | ||
| 246 | "fsl,qoriq-memory-controller"; | ||
| 247 | reg = <0x8000 0x1000>; | ||
| 248 | interrupts = <16 2 1 23>; | ||
| 249 | }; | ||
| 250 | |||
| 251 | cpc: l3-cache-controller@10000 { | ||
| 252 | compatible = "fsl,t2080-l3-cache-controller", "cache"; | ||
| 253 | reg = <0x10000 0x1000 | ||
| 254 | 0x11000 0x1000 | ||
| 255 | 0x12000 0x1000>; | ||
| 256 | interrupts = <16 2 1 27 | ||
| 257 | 16 2 1 26 | ||
| 258 | 16 2 1 25>; | ||
| 259 | }; | ||
| 260 | |||
| 261 | corenet-cf@18000 { | ||
| 262 | compatible = "fsl,corenet2-cf", "fsl,corenet-cf"; | ||
| 263 | reg = <0x18000 0x1000>; | ||
| 264 | interrupts = <16 2 1 31>; | ||
| 265 | fsl,ccf-num-csdids = <32>; | ||
| 266 | fsl,ccf-num-snoopids = <32>; | ||
| 267 | }; | ||
| 268 | |||
| 269 | iommu@20000 { | ||
| 270 | compatible = "fsl,pamu-v1.0", "fsl,pamu"; | ||
| 271 | reg = <0x20000 0x3000>; | ||
| 272 | fsl,portid-mapping = <0x8000>; | ||
| 273 | ranges = <0 0x20000 0x3000>; | ||
| 274 | #address-cells = <1>; | ||
| 275 | #size-cells = <1>; | ||
| 276 | interrupts = < | ||
| 277 | 24 2 0 0 | ||
| 278 | 16 2 1 30>; | ||
| 279 | |||
| 280 | pamu0: pamu@0 { | ||
| 281 | reg = <0 0x1000>; | ||
| 282 | fsl,primary-cache-geometry = <32 1>; | ||
| 283 | fsl,secondary-cache-geometry = <128 2>; | ||
| 284 | }; | ||
| 285 | |||
| 286 | pamu1: pamu@1000 { | ||
| 287 | reg = <0x1000 0x1000>; | ||
| 288 | fsl,primary-cache-geometry = <32 1>; | ||
| 289 | fsl,secondary-cache-geometry = <128 2>; | ||
| 290 | }; | ||
| 291 | |||
| 292 | pamu2: pamu@2000 { | ||
| 293 | reg = <0x2000 0x1000>; | ||
| 294 | fsl,primary-cache-geometry = <32 1>; | ||
| 295 | fsl,secondary-cache-geometry = <128 2>; | ||
| 296 | }; | ||
| 297 | }; | ||
| 298 | |||
| 299 | /include/ "qoriq-mpic4.3.dtsi" | ||
| 300 | |||
| 301 | guts: global-utilities@e0000 { | ||
| 302 | compatible = "fsl,t2080-device-config", "fsl,qoriq-device-config-2.0"; | ||
| 303 | reg = <0xe0000 0xe00>; | ||
| 304 | fsl,has-rstcr; | ||
| 305 | fsl,liodn-bits = <12>; | ||
| 306 | }; | ||
| 307 | |||
| 308 | clockgen: global-utilities@e1000 { | ||
| 309 | compatible = "fsl,t2080-clockgen", "fsl,qoriq-clockgen-2.0"; | ||
| 310 | ranges = <0x0 0xe1000 0x1000>; | ||
| 311 | reg = <0xe1000 0x1000>; | ||
| 312 | #address-cells = <1>; | ||
| 313 | #size-cells = <1>; | ||
| 314 | |||
| 315 | sysclk: sysclk { | ||
| 316 | #clock-cells = <0>; | ||
| 317 | compatible = "fsl,qoriq-sysclk-2.0"; | ||
| 318 | clock-output-names = "sysclk", "fixed-clock"; | ||
| 319 | }; | ||
| 320 | |||
| 321 | pll0: pll0@800 { | ||
| 322 | #clock-cells = <1>; | ||
| 323 | reg = <0x800 4>; | ||
| 324 | compatible = "fsl,qoriq-core-pll-2.0"; | ||
| 325 | clocks = <&sysclk>; | ||
| 326 | clock-output-names = "pll0", "pll0-div2", "pll0-div4"; | ||
| 327 | }; | ||
| 328 | |||
| 329 | pll1: pll1@820 { | ||
| 330 | #clock-cells = <1>; | ||
| 331 | reg = <0x820 4>; | ||
| 332 | compatible = "fsl,qoriq-core-pll-2.0"; | ||
| 333 | clocks = <&sysclk>; | ||
| 334 | clock-output-names = "pll1", "pll1-div2", "pll1-div4"; | ||
| 335 | }; | ||
| 336 | |||
| 337 | mux0: mux0@0 { | ||
| 338 | #clock-cells = <0>; | ||
| 339 | reg = <0x0 4>; | ||
| 340 | compatible = "fsl,qoriq-core-mux-2.0"; | ||
| 341 | clocks = <&pll0 0>, <&pll0 1>, <&pll0 2>, | ||
| 342 | <&pll1 0>, <&pll1 1>, <&pll1 2>; | ||
| 343 | clock-names = "pll0", "pll0-div2", "pll1-div4", | ||
| 344 | "pll1", "pll1-div2", "pll1-div4"; | ||
| 345 | clock-output-names = "cmux0"; | ||
| 346 | }; | ||
| 347 | |||
| 348 | mux1: mux1@20 { | ||
| 349 | #clock-cells = <0>; | ||
| 350 | reg = <0x20 4>; | ||
| 351 | compatible = "fsl,qoriq-core-mux-2.0"; | ||
| 352 | clocks = <&pll0 0>, <&pll0 1>, <&pll0 2>, | ||
| 353 | <&pll1 0>, <&pll1 1>, <&pll1 2>; | ||
| 354 | clock-names = "pll0", "pll0-div2", "pll1-div4", | ||
| 355 | "pll1", "pll1-div2", "pll1-div4"; | ||
| 356 | clock-output-names = "cmux1"; | ||
| 357 | }; | ||
| 358 | }; | ||
| 359 | |||
| 360 | rcpm: global-utilities@e2000 { | ||
| 361 | compatible = "fsl,t2080-rcpm", "fsl,qoriq-rcpm-2.0"; | ||
| 362 | reg = <0xe2000 0x1000>; | ||
| 363 | }; | ||
| 364 | |||
| 365 | sfp: sfp@e8000 { | ||
| 366 | compatible = "fsl,t2080-sfp"; | ||
| 367 | reg = <0xe8000 0x1000>; | ||
| 368 | }; | ||
| 369 | |||
| 370 | serdes: serdes@ea000 { | ||
| 371 | compatible = "fsl,t2080-serdes"; | ||
| 372 | reg = <0xea000 0x4000>; | ||
| 373 | }; | ||
| 374 | |||
| 375 | /include/ "elo3-dma-0.dtsi" | ||
| 376 | dma@100300 { | ||
| 377 | fsl,iommu-parent = <&pamu0>; | ||
| 378 | fsl,liodn-reg = <&guts 0x580>; /* DMA1LIODNR */ | ||
| 379 | }; | ||
| 380 | /include/ "elo3-dma-1.dtsi" | ||
| 381 | dma@101300 { | ||
| 382 | fsl,iommu-parent = <&pamu0>; | ||
| 383 | fsl,liodn-reg = <&guts 0x584>; /* DMA2LIODNR */ | ||
| 384 | }; | ||
| 385 | /include/ "elo3-dma-2.dtsi" | ||
| 386 | dma@102300 { | ||
| 387 | fsl,iommu-parent = <&pamu0>; | ||
| 388 | fsl,liodn-reg = <&guts 0x588>; /* DMA3LIODNR */ | ||
| 389 | }; | ||
| 390 | |||
| 391 | /include/ "qoriq-espi-0.dtsi" | ||
| 392 | spi@110000 { | ||
| 393 | fsl,espi-num-chipselects = <4>; | ||
| 394 | }; | ||
| 395 | |||
| 396 | /include/ "qoriq-esdhc-0.dtsi" | ||
| 397 | sdhc@114000 { | ||
| 398 | compatible = "fsl,t2080-esdhc", "fsl,esdhc"; | ||
| 399 | fsl,iommu-parent = <&pamu1>; | ||
| 400 | fsl,liodn-reg = <&guts 0x530>; /* SDMMCLIODNR */ | ||
| 401 | sdhci,auto-cmd12; | ||
| 402 | }; | ||
| 403 | /include/ "qoriq-i2c-0.dtsi" | ||
| 404 | /include/ "qoriq-i2c-1.dtsi" | ||
| 405 | /include/ "qoriq-duart-0.dtsi" | ||
| 406 | /include/ "qoriq-duart-1.dtsi" | ||
| 407 | /include/ "qoriq-gpio-0.dtsi" | ||
| 408 | /include/ "qoriq-gpio-1.dtsi" | ||
| 409 | /include/ "qoriq-gpio-2.dtsi" | ||
| 410 | /include/ "qoriq-gpio-3.dtsi" | ||
| 411 | /include/ "qoriq-usb2-mph-0.dtsi" | ||
| 412 | usb0: usb@210000 { | ||
| 413 | compatible = "fsl-usb2-mph-v2.4", "fsl-usb2-mph"; | ||
| 414 | fsl,iommu-parent = <&pamu1>; | ||
| 415 | fsl,liodn-reg = <&guts 0x520>; /* USB1LIODNR */ | ||
| 416 | phy_type = "utmi"; | ||
| 417 | port0; | ||
| 418 | }; | ||
| 419 | /include/ "qoriq-usb2-dr-0.dtsi" | ||
| 420 | usb1: usb@211000 { | ||
| 421 | compatible = "fsl-usb2-dr-v2.4", "fsl-usb2-dr"; | ||
| 422 | fsl,iommu-parent = <&pamu1>; | ||
| 423 | fsl,liodn-reg = <&guts 0x524>; /* USB1LIODNR */ | ||
| 424 | dr_mode = "host"; | ||
| 425 | phy_type = "utmi"; | ||
| 426 | }; | ||
| 427 | /include/ "qoriq-sec5.2-0.dtsi" | ||
| 428 | |||
| 429 | L2_1: l2-cache-controller@c20000 { | ||
| 430 | /* Cluster 0 L2 cache */ | ||
| 431 | compatible = "fsl,t2080-l2-cache-controller"; | ||
| 432 | reg = <0xc20000 0x40000>; | ||
| 433 | next-level-cache = <&cpc>; | ||
| 434 | }; | ||
| 435 | }; | ||
diff --git a/arch/powerpc/boot/dts/fsl/t208xsi-pre.dtsi b/arch/powerpc/boot/dts/fsl/t208xsi-pre.dtsi new file mode 100644 index 000000000000..e71ceb0e1100 --- /dev/null +++ b/arch/powerpc/boot/dts/fsl/t208xsi-pre.dtsi | |||
| @@ -0,0 +1,99 @@ | |||
| 1 | /* | ||
| 2 | * T2080/T2081 Silicon/SoC Device Tree Source (pre include) | ||
| 3 | * | ||
| 4 | * Copyright 2013 Freescale Semiconductor Inc. | ||
| 5 | * | ||
| 6 | * Redistribution and use in source and binary forms, with or without | ||
| 7 | * modification, are permitted provided that the following conditions are met: | ||
| 8 | * * Redistributions of source code must retain the above copyright | ||
| 9 | * notice, this list of conditions and the following disclaimer. | ||
| 10 | * * Redistributions in binary form must reproduce the above copyright | ||
| 11 | * notice, this list of conditions and the following disclaimer in the | ||
| 12 | * documentation and/or other materials provided with the distribution. | ||
| 13 | * * Neither the name of Freescale Semiconductor nor the | ||
| 14 | * names of its contributors may be used to endorse or promote products | ||
| 15 | * derived from this software without specific prior written permission. | ||
| 16 | * | ||
| 17 | * | ||
| 18 | * ALTERNATIVELY, this software may be distributed under the terms of the | ||
| 19 | * GNU General Public License ("GPL") as published by the Free Software | ||
| 20 | * Foundation, either version 2 of that License or (at your option) any | ||
| 21 | * later version. | ||
| 22 | * | ||
| 23 | * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY | ||
| 24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
| 25 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
| 26 | * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY | ||
| 27 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
| 28 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
| 29 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
| 30 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
| 32 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 33 | */ | ||
| 34 | |||
| 35 | /dts-v1/; | ||
| 36 | |||
| 37 | /include/ "e6500_power_isa.dtsi" | ||
| 38 | |||
| 39 | / { | ||
| 40 | #address-cells = <2>; | ||
| 41 | #size-cells = <2>; | ||
| 42 | interrupt-parent = <&mpic>; | ||
| 43 | |||
| 44 | aliases { | ||
| 45 | ccsr = &soc; | ||
| 46 | dcsr = &dcsr; | ||
| 47 | |||
| 48 | serial0 = &serial0; | ||
| 49 | serial1 = &serial1; | ||
| 50 | serial2 = &serial2; | ||
| 51 | serial3 = &serial3; | ||
| 52 | |||
| 53 | crypto = &crypto; | ||
| 54 | pci0 = &pci0; | ||
| 55 | pci1 = &pci1; | ||
| 56 | pci2 = &pci2; | ||
| 57 | pci3 = &pci3; | ||
| 58 | usb0 = &usb0; | ||
| 59 | usb1 = &usb1; | ||
| 60 | dma0 = &dma0; | ||
| 61 | dma1 = &dma1; | ||
| 62 | dma2 = &dma2; | ||
| 63 | sdhc = &sdhc; | ||
| 64 | }; | ||
| 65 | |||
| 66 | cpus { | ||
| 67 | #address-cells = <1>; | ||
| 68 | #size-cells = <0>; | ||
| 69 | |||
| 70 | cpu0: PowerPC,e6500@0 { | ||
| 71 | device_type = "cpu"; | ||
| 72 | reg = <0 1>; | ||
| 73 | clocks = <&mux0>; | ||
| 74 | next-level-cache = <&L2_1>; | ||
| 75 | fsl,portid-mapping = <0x80000000>; | ||
| 76 | }; | ||
| 77 | cpu1: PowerPC,e6500@2 { | ||
| 78 | device_type = "cpu"; | ||
| 79 | reg = <2 3>; | ||
| 80 | clocks = <&mux0>; | ||
| 81 | next-level-cache = <&L2_1>; | ||
| 82 | fsl,portid-mapping = <0x80000000>; | ||
| 83 | }; | ||
| 84 | cpu2: PowerPC,e6500@4 { | ||
| 85 | device_type = "cpu"; | ||
| 86 | reg = <4 5>; | ||
| 87 | clocks = <&mux0>; | ||
| 88 | next-level-cache = <&L2_1>; | ||
| 89 | fsl,portid-mapping = <0x80000000>; | ||
| 90 | }; | ||
| 91 | cpu3: PowerPC,e6500@6 { | ||
| 92 | device_type = "cpu"; | ||
| 93 | reg = <6 7>; | ||
| 94 | clocks = <&mux0>; | ||
| 95 | next-level-cache = <&L2_1>; | ||
| 96 | fsl,portid-mapping = <0x80000000>; | ||
| 97 | }; | ||
| 98 | }; | ||
| 99 | }; | ||
diff --git a/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi b/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi index 793669baa13e..a3d582e0361a 100644 --- a/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi | |||
| @@ -476,6 +476,7 @@ | |||
| 476 | 476 | ||
| 477 | /include/ "elo3-dma-0.dtsi" | 477 | /include/ "elo3-dma-0.dtsi" |
| 478 | /include/ "elo3-dma-1.dtsi" | 478 | /include/ "elo3-dma-1.dtsi" |
| 479 | /include/ "elo3-dma-2.dtsi" | ||
| 479 | 480 | ||
| 480 | /include/ "qoriq-espi-0.dtsi" | 481 | /include/ "qoriq-espi-0.dtsi" |
| 481 | spi@110000 { | 482 | spi@110000 { |
diff --git a/arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi b/arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi index d2f157edbe81..261a3abb1a55 100644 --- a/arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi +++ b/arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi | |||
| @@ -57,6 +57,7 @@ | |||
| 57 | pci3 = &pci3; | 57 | pci3 = &pci3; |
| 58 | dma0 = &dma0; | 58 | dma0 = &dma0; |
| 59 | dma1 = &dma1; | 59 | dma1 = &dma1; |
| 60 | dma2 = &dma2; | ||
| 60 | sdhc = &sdhc; | 61 | sdhc = &sdhc; |
| 61 | }; | 62 | }; |
| 62 | 63 | ||
diff --git a/arch/powerpc/boot/dts/t2080qds.dts b/arch/powerpc/boot/dts/t2080qds.dts new file mode 100644 index 000000000000..aa1d6d8c169b --- /dev/null +++ b/arch/powerpc/boot/dts/t2080qds.dts | |||
| @@ -0,0 +1,57 @@ | |||
| 1 | /* | ||
| 2 | * T2080QDS Device Tree Source | ||
| 3 | * | ||
| 4 | * Copyright 2013 Freescale Semiconductor Inc. | ||
| 5 | * | ||
| 6 | * Redistribution and use in source and binary forms, with or without | ||
| 7 | * modification, are permitted provided that the following conditions are met: | ||
| 8 | * * Redistributions of source code must retain the above copyright | ||
| 9 | * notice, this list of conditions and the following disclaimer. | ||
| 10 | * * Redistributions in binary form must reproduce the above copyright | ||
| 11 | * notice, this list of conditions and the following disclaimer in the | ||
| 12 | * documentation and/or other materials provided with the distribution. | ||
| 13 | * * Neither the name of Freescale Semiconductor nor the | ||
| 14 | * names of its contributors may be used to endorse or promote products | ||
| 15 | * derived from this software without specific prior written permission. | ||
| 16 | * | ||
| 17 | * | ||
| 18 | * ALTERNATIVELY, this software may be distributed under the terms of the | ||
| 19 | * GNU General Public License ("GPL") as published by the Free Software | ||
| 20 | * Foundation, either version 2 of that License or (at your option) any | ||
| 21 | * later version. | ||
| 22 | * | ||
| 23 | * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY | ||
| 24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
| 25 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
| 26 | * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY | ||
| 27 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
| 28 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
| 29 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
| 30 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
| 32 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 33 | */ | ||
| 34 | |||
| 35 | /include/ "fsl/t208xsi-pre.dtsi" | ||
| 36 | /include/ "t208xqds.dtsi" | ||
| 37 | |||
| 38 | / { | ||
| 39 | model = "fsl,T2080QDS"; | ||
| 40 | compatible = "fsl,T2080QDS"; | ||
| 41 | #address-cells = <2>; | ||
| 42 | #size-cells = <2>; | ||
| 43 | interrupt-parent = <&mpic>; | ||
| 44 | |||
| 45 | rio: rapidio@ffe0c0000 { | ||
| 46 | reg = <0xf 0xfe0c0000 0 0x11000>; | ||
| 47 | |||
| 48 | port1 { | ||
| 49 | ranges = <0 0 0xc 0x20000000 0 0x10000000>; | ||
| 50 | }; | ||
| 51 | port2 { | ||
| 52 | ranges = <0 0 0xc 0x30000000 0 0x10000000>; | ||
| 53 | }; | ||
| 54 | }; | ||
| 55 | }; | ||
| 56 | |||
| 57 | /include/ "fsl/t2080si-post.dtsi" | ||
diff --git a/arch/powerpc/boot/dts/t2080rdb.dts b/arch/powerpc/boot/dts/t2080rdb.dts new file mode 100644 index 000000000000..e8891047600c --- /dev/null +++ b/arch/powerpc/boot/dts/t2080rdb.dts | |||
| @@ -0,0 +1,57 @@ | |||
| 1 | /* | ||
| 2 | * T2080PCIe-RDB Board Device Tree Source | ||
| 3 | * | ||
| 4 | * Copyright 2014 Freescale Semiconductor Inc. | ||
| 5 | * | ||
| 6 | * Redistribution and use in source and binary forms, with or without | ||
| 7 | * modification, are permitted provided that the following conditions are met: | ||
| 8 | * * Redistributions of source code must retain the above copyright | ||
| 9 | * notice, this list of conditions and the following disclaimer. | ||
| 10 | * * Redistributions in binary form must reproduce the above copyright | ||
| 11 | * notice, this list of conditions and the following disclaimer in the | ||
| 12 | * documentation and/or other materials provided with the distribution. | ||
| 13 | * * Neither the name of Freescale Semiconductor nor the | ||
| 14 | * names of its contributors may be used to endorse or promote products | ||
| 15 | * derived from this software without specific prior written permission. | ||
| 16 | * | ||
| 17 | * | ||
| 18 | * ALTERNATIVELY, this software may be distributed under the terms of the | ||
| 19 | * GNU General Public License ("GPL") as published by the Free Software | ||
| 20 | * Foundation, either version 2 of that License or (at your option) any | ||
| 21 | * later version. | ||
| 22 | * | ||
| 23 | * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY | ||
| 24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
| 25 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
| 26 | * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY | ||
| 27 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
| 28 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
| 29 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
| 30 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
| 32 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 33 | */ | ||
| 34 | |||
| 35 | /include/ "fsl/t208xsi-pre.dtsi" | ||
| 36 | /include/ "t208xrdb.dtsi" | ||
| 37 | |||
| 38 | / { | ||
| 39 | model = "fsl,T2080RDB"; | ||
| 40 | compatible = "fsl,T2080RDB"; | ||
| 41 | #address-cells = <2>; | ||
| 42 | #size-cells = <2>; | ||
| 43 | interrupt-parent = <&mpic>; | ||
| 44 | |||
| 45 | rio: rapidio@ffe0c0000 { | ||
| 46 | reg = <0xf 0xfe0c0000 0 0x11000>; | ||
| 47 | |||
| 48 | port1 { | ||
| 49 | ranges = <0 0 0xc 0x20000000 0 0x10000000>; | ||
| 50 | }; | ||
| 51 | port2 { | ||
| 52 | ranges = <0 0 0xc 0x30000000 0 0x10000000>; | ||
| 53 | }; | ||
| 54 | }; | ||
| 55 | }; | ||
| 56 | |||
| 57 | /include/ "fsl/t2080si-post.dtsi" | ||
diff --git a/arch/powerpc/boot/dts/t2081qds.dts b/arch/powerpc/boot/dts/t2081qds.dts new file mode 100644 index 000000000000..8ec80a71e102 --- /dev/null +++ b/arch/powerpc/boot/dts/t2081qds.dts | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | /* | ||
| 2 | * T2081QDS Device Tree Source | ||
| 3 | * | ||
| 4 | * Copyright 2013 Freescale Semiconductor Inc. | ||
| 5 | * | ||
| 6 | * Redistribution and use in source and binary forms, with or without | ||
| 7 | * modification, are permitted provided that the following conditions are met: | ||
| 8 | * * Redistributions of source code must retain the above copyright | ||
| 9 | * notice, this list of conditions and the following disclaimer. | ||
| 10 | * * Redistributions in binary form must reproduce the above copyright | ||
| 11 | * notice, this list of conditions and the following disclaimer in the | ||
| 12 | * documentation and/or other materials provided with the distribution. | ||
| 13 | * * Neither the name of Freescale Semiconductor nor the | ||
| 14 | * names of its contributors may be used to endorse or promote products | ||
| 15 | * derived from this software without specific prior written permission. | ||
| 16 | * | ||
| 17 | * | ||
| 18 | * ALTERNATIVELY, this software may be distributed under the terms of the | ||
| 19 | * GNU General Public License ("GPL") as published by the Free Software | ||
| 20 | * Foundation, either version 2 of that License or (at your option) any | ||
| 21 | * later version. | ||
| 22 | * | ||
| 23 | * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY | ||
| 24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
| 25 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
| 26 | * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY | ||
| 27 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
| 28 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
| 29 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
| 30 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
| 32 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 33 | */ | ||
| 34 | |||
| 35 | /include/ "fsl/t208xsi-pre.dtsi" | ||
| 36 | /include/ "t208xqds.dtsi" | ||
| 37 | |||
| 38 | / { | ||
| 39 | model = "fsl,T2081QDS"; | ||
| 40 | compatible = "fsl,T2081QDS"; | ||
| 41 | #address-cells = <2>; | ||
| 42 | #size-cells = <2>; | ||
| 43 | interrupt-parent = <&mpic>; | ||
| 44 | }; | ||
| 45 | |||
| 46 | /include/ "fsl/t2081si-post.dtsi" | ||
diff --git a/arch/powerpc/boot/dts/t208xqds.dtsi b/arch/powerpc/boot/dts/t208xqds.dtsi new file mode 100644 index 000000000000..555dc6e03d89 --- /dev/null +++ b/arch/powerpc/boot/dts/t208xqds.dtsi | |||
| @@ -0,0 +1,239 @@ | |||
| 1 | /* | ||
| 2 | * T2080/T2081 QDS Device Tree Source | ||
| 3 | * | ||
| 4 | * Copyright 2013 Freescale Semiconductor Inc. | ||
| 5 | * | ||
| 6 | * Redistribution and use in source and binary forms, with or without | ||
| 7 | * modification, are permitted provided that the following conditions are met: | ||
| 8 | * * Redistributions of source code must retain the above copyright | ||
| 9 | * notice, this list of conditions and the following disclaimer. | ||
| 10 | * * Redistributions in binary form must reproduce the above copyright | ||
| 11 | * notice, this list of conditions and the following disclaimer in the | ||
| 12 | * documentation and/or other materials provided with the distribution. | ||
| 13 | * * Neither the name of Freescale Semiconductor nor the | ||
| 14 | * names of its contributors may be used to endorse or promote products | ||
| 15 | * derived from this software without specific prior written permission. | ||
| 16 | * | ||
| 17 | * | ||
| 18 | * ALTERNATIVELY, this software may be distributed under the terms of the | ||
| 19 | * GNU General Public License ("GPL") as published by the Free Software | ||
| 20 | * Foundation, either version 2 of that License or (at your option) any | ||
| 21 | * later version. | ||
| 22 | * | ||
| 23 | * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY | ||
| 24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
| 25 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
| 26 | * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY | ||
| 27 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
| 28 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
| 29 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
| 30 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
| 32 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 33 | */ | ||
| 34 | |||
| 35 | / { | ||
| 36 | model = "fsl,T2080QDS"; | ||
| 37 | compatible = "fsl,T2080QDS"; | ||
| 38 | #address-cells = <2>; | ||
| 39 | #size-cells = <2>; | ||
| 40 | interrupt-parent = <&mpic>; | ||
| 41 | |||
| 42 | ifc: localbus@ffe124000 { | ||
| 43 | reg = <0xf 0xfe124000 0 0x2000>; | ||
| 44 | ranges = <0 0 0xf 0xe8000000 0x08000000 | ||
| 45 | 2 0 0xf 0xff800000 0x00010000 | ||
| 46 | 3 0 0xf 0xffdf0000 0x00008000>; | ||
| 47 | |||
| 48 | nor@0,0 { | ||
| 49 | #address-cells = <1>; | ||
| 50 | #size-cells = <1>; | ||
| 51 | compatible = "cfi-flash"; | ||
| 52 | reg = <0x0 0x0 0x8000000>; | ||
| 53 | bank-width = <2>; | ||
| 54 | device-width = <1>; | ||
| 55 | }; | ||
| 56 | |||
| 57 | nand@2,0 { | ||
| 58 | #address-cells = <1>; | ||
| 59 | #size-cells = <1>; | ||
| 60 | compatible = "fsl,ifc-nand"; | ||
| 61 | reg = <0x2 0x0 0x10000>; | ||
| 62 | }; | ||
| 63 | |||
| 64 | boardctrl: board-control@3,0 { | ||
| 65 | #address-cells = <1>; | ||
| 66 | #size-cells = <1>; | ||
| 67 | compatible = "fsl,fpga-qixis"; | ||
| 68 | reg = <3 0 0x300>; | ||
| 69 | ranges = <0 3 0 0x300>; | ||
| 70 | }; | ||
| 71 | }; | ||
| 72 | |||
| 73 | memory { | ||
| 74 | device_type = "memory"; | ||
| 75 | }; | ||
| 76 | |||
| 77 | dcsr: dcsr@f00000000 { | ||
| 78 | ranges = <0x00000000 0xf 0x00000000 0x01072000>; | ||
| 79 | }; | ||
| 80 | |||
| 81 | soc: soc@ffe000000 { | ||
| 82 | ranges = <0x00000000 0xf 0xfe000000 0x1000000>; | ||
| 83 | reg = <0xf 0xfe000000 0 0x00001000>; | ||
| 84 | spi@110000 { | ||
| 85 | flash@0 { | ||
| 86 | #address-cells = <1>; | ||
| 87 | #size-cells = <1>; | ||
| 88 | compatible = "micron,n25q128a11"; /* 16MB */ | ||
| 89 | reg = <0>; | ||
| 90 | spi-max-frequency = <40000000>; /* input clock */ | ||
| 91 | }; | ||
| 92 | |||
| 93 | flash@1 { | ||
| 94 | #address-cells = <1>; | ||
| 95 | #size-cells = <1>; | ||
| 96 | compatible = "sst,sst25wf040"; | ||
| 97 | reg = <1>; | ||
| 98 | spi-max-frequency = <35000000>; | ||
| 99 | }; | ||
| 100 | |||
| 101 | flash@2 { | ||
| 102 | #address-cells = <1>; | ||
| 103 | #size-cells = <1>; | ||
| 104 | compatible = "eon,en25s64"; | ||
| 105 | reg = <2>; | ||
| 106 | spi-max-frequency = <35000000>; | ||
| 107 | }; | ||
| 108 | }; | ||
| 109 | |||
| 110 | i2c@118000 { | ||
| 111 | pca9547@77 { | ||
| 112 | compatible = "nxp,pca9547"; | ||
| 113 | reg = <0x77>; | ||
| 114 | #address-cells = <1>; | ||
| 115 | #size-cells = <0>; | ||
| 116 | |||
| 117 | i2c@0 { | ||
| 118 | #address-cells = <1>; | ||
| 119 | #size-cells = <0>; | ||
| 120 | reg = <0x0>; | ||
| 121 | |||
| 122 | eeprom@50 { | ||
| 123 | compatible = "at24,24c512"; | ||
| 124 | reg = <0x50>; | ||
| 125 | }; | ||
| 126 | |||
| 127 | eeprom@51 { | ||
| 128 | compatible = "at24,24c02"; | ||
| 129 | reg = <0x51>; | ||
| 130 | }; | ||
| 131 | |||
| 132 | eeprom@57 { | ||
| 133 | compatible = "at24,24c02"; | ||
| 134 | reg = <0x57>; | ||
| 135 | }; | ||
| 136 | |||
| 137 | rtc@68 { | ||
| 138 | compatible = "dallas,ds3232"; | ||
| 139 | reg = <0x68>; | ||
| 140 | interrupts = <0x1 0x1 0 0>; | ||
| 141 | }; | ||
| 142 | }; | ||
| 143 | |||
| 144 | i2c@1 { | ||
| 145 | #address-cells = <1>; | ||
| 146 | #size-cells = <0>; | ||
| 147 | reg = <0x1>; | ||
| 148 | |||
| 149 | eeprom@55 { | ||
| 150 | compatible = "at24,24c02"; | ||
| 151 | reg = <0x55>; | ||
| 152 | }; | ||
| 153 | }; | ||
| 154 | |||
| 155 | i2c@2 { | ||
| 156 | #address-cells = <1>; | ||
| 157 | #size-cells = <0>; | ||
| 158 | reg = <0x2>; | ||
| 159 | |||
| 160 | ina220@40 { | ||
| 161 | compatible = "ti,ina220"; | ||
| 162 | reg = <0x40>; | ||
| 163 | shunt-resistor = <1000>; | ||
| 164 | }; | ||
| 165 | |||
| 166 | ina220@41 { | ||
| 167 | compatible = "ti,ina220"; | ||
| 168 | reg = <0x41>; | ||
| 169 | shunt-resistor = <1000>; | ||
| 170 | }; | ||
| 171 | }; | ||
| 172 | }; | ||
| 173 | }; | ||
| 174 | |||
| 175 | sdhc@114000 { | ||
| 176 | voltage-ranges = <1800 1800 3300 3300>; | ||
| 177 | }; | ||
| 178 | }; | ||
| 179 | |||
| 180 | pci0: pcie@ffe240000 { | ||
| 181 | reg = <0xf 0xfe240000 0 0x10000>; | ||
| 182 | ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000 | ||
| 183 | 0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>; | ||
| 184 | pcie@0 { | ||
| 185 | ranges = <0x02000000 0 0xe0000000 | ||
| 186 | 0x02000000 0 0xe0000000 | ||
| 187 | 0 0x20000000 | ||
| 188 | |||
| 189 | 0x01000000 0 0x00000000 | ||
| 190 | 0x01000000 0 0x00000000 | ||
| 191 | 0 0x00010000>; | ||
| 192 | }; | ||
| 193 | }; | ||
| 194 | |||
| 195 | pci1: pcie@ffe250000 { | ||
| 196 | reg = <0xf 0xfe250000 0 0x10000>; | ||
| 197 | ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x10000000 | ||
| 198 | 0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>; | ||
| 199 | pcie@0 { | ||
| 200 | ranges = <0x02000000 0 0xe0000000 | ||
| 201 | 0x02000000 0 0xe0000000 | ||
| 202 | 0 0x20000000 | ||
| 203 | |||
| 204 | 0x01000000 0 0x00000000 | ||
| 205 | 0x01000000 0 0x00000000 | ||
| 206 | 0 0x00010000>; | ||
| 207 | }; | ||
| 208 | }; | ||
| 209 | |||
| 210 | pci2: pcie@ffe260000 { | ||
| 211 | reg = <0xf 0xfe260000 0 0x1000>; | ||
| 212 | ranges = <0x02000000 0 0xe0000000 0xc 0x30000000 0 0x10000000 | ||
| 213 | 0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>; | ||
| 214 | pcie@0 { | ||
| 215 | ranges = <0x02000000 0 0xe0000000 | ||
| 216 | 0x02000000 0 0xe0000000 | ||
| 217 | 0 0x20000000 | ||
| 218 | |||
| 219 | 0x01000000 0 0x00000000 | ||
| 220 | 0x01000000 0 0x00000000 | ||
| 221 | 0 0x00010000>; | ||
| 222 | }; | ||
| 223 | }; | ||
| 224 | |||
| 225 | pci3: pcie@ffe270000 { | ||
| 226 | reg = <0xf 0xfe270000 0 0x10000>; | ||
| 227 | ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x10000000 | ||
| 228 | 0x01000000 0 0x00000000 0xf 0xf8030000 0 0x00010000>; | ||
| 229 | pcie@0 { | ||
| 230 | ranges = <0x02000000 0 0xe0000000 | ||
| 231 | 0x02000000 0 0xe0000000 | ||
| 232 | 0 0x20000000 | ||
| 233 | |||
| 234 | 0x01000000 0 0x00000000 | ||
| 235 | 0x01000000 0 0x00000000 | ||
| 236 | 0 0x00010000>; | ||
| 237 | }; | ||
| 238 | }; | ||
| 239 | }; | ||
diff --git a/arch/powerpc/boot/dts/t208xrdb.dtsi b/arch/powerpc/boot/dts/t208xrdb.dtsi new file mode 100644 index 000000000000..1481e192e783 --- /dev/null +++ b/arch/powerpc/boot/dts/t208xrdb.dtsi | |||
| @@ -0,0 +1,184 @@ | |||
| 1 | /* | ||
| 2 | * T2080PCIe-RDB Board Device Tree Source | ||
| 3 | * | ||
| 4 | * Copyright 2014 Freescale Semiconductor Inc. | ||
| 5 | * | ||
| 6 | * Redistribution and use in source and binary forms, with or without | ||
| 7 | * modification, are permitted provided that the following conditions are met: | ||
| 8 | * * Redistributions of source code must retain the above copyright | ||
| 9 | * notice, this list of conditions and the following disclaimer. | ||
| 10 | * * Redistributions in binary form must reproduce the above copyright | ||
| 11 | * notice, this list of conditions and the following disclaimer in the | ||
| 12 | * documentation and/or other materials provided with the distribution. | ||
| 13 | * * Neither the name of Freescale Semiconductor nor the | ||
| 14 | * names of its contributors may be used to endorse or promote products | ||
| 15 | * derived from this software without specific prior written permission. | ||
| 16 | * | ||
| 17 | * | ||
| 18 | * ALTERNATIVELY, this software may be distributed under the terms of the | ||
| 19 | * GNU General Public License ("GPL") as published by the Free Software | ||
| 20 | * Foundation, either version 2 of that License or (at your option) any | ||
| 21 | * later version. | ||
| 22 | * | ||
| 23 | * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY | ||
| 24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
| 25 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
| 26 | * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY | ||
| 27 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
| 28 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
| 29 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
| 30 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
| 32 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 33 | */ | ||
| 34 | |||
| 35 | / { | ||
| 36 | model = "fsl,T2080RDB"; | ||
| 37 | compatible = "fsl,T2080RDB"; | ||
| 38 | #address-cells = <2>; | ||
| 39 | #size-cells = <2>; | ||
| 40 | interrupt-parent = <&mpic>; | ||
| 41 | |||
| 42 | ifc: localbus@ffe124000 { | ||
| 43 | reg = <0xf 0xfe124000 0 0x2000>; | ||
| 44 | ranges = <0 0 0xf 0xe8000000 0x08000000 | ||
| 45 | 2 0 0xf 0xff800000 0x00010000 | ||
| 46 | 3 0 0xf 0xffdf0000 0x00008000>; | ||
| 47 | |||
| 48 | nor@0,0 { | ||
| 49 | #address-cells = <1>; | ||
| 50 | #size-cells = <1>; | ||
| 51 | compatible = "cfi-flash"; | ||
| 52 | reg = <0x0 0x0 0x8000000>; | ||
| 53 | |||
| 54 | bank-width = <2>; | ||
| 55 | device-width = <1>; | ||
| 56 | }; | ||
| 57 | |||
| 58 | nand@1,0 { | ||
| 59 | #address-cells = <1>; | ||
| 60 | #size-cells = <1>; | ||
| 61 | compatible = "fsl,ifc-nand"; | ||
| 62 | reg = <0x2 0x0 0x10000>; | ||
| 63 | }; | ||
| 64 | |||
| 65 | boardctrl: board-control@2,0 { | ||
| 66 | #address-cells = <1>; | ||
| 67 | #size-cells = <1>; | ||
| 68 | compatible = "fsl,t2080-cpld"; | ||
| 69 | reg = <3 0 0x300>; | ||
| 70 | ranges = <0 3 0 0x300>; | ||
| 71 | }; | ||
| 72 | }; | ||
| 73 | |||
| 74 | memory { | ||
| 75 | device_type = "memory"; | ||
| 76 | }; | ||
| 77 | |||
| 78 | dcsr: dcsr@f00000000 { | ||
| 79 | ranges = <0x00000000 0xf 0x00000000 0x01072000>; | ||
| 80 | }; | ||
| 81 | |||
| 82 | soc: soc@ffe000000 { | ||
| 83 | ranges = <0x00000000 0xf 0xfe000000 0x1000000>; | ||
| 84 | reg = <0xf 0xfe000000 0 0x00001000>; | ||
| 85 | spi@110000 { | ||
| 86 | flash@0 { | ||
| 87 | #address-cells = <1>; | ||
| 88 | #size-cells = <1>; | ||
| 89 | compatible = "micron,n25q512a"; | ||
| 90 | reg = <0>; | ||
| 91 | spi-max-frequency = <10000000>; /* input clock */ | ||
| 92 | }; | ||
| 93 | }; | ||
| 94 | |||
| 95 | i2c@118000 { | ||
| 96 | adt7481@4c { | ||
| 97 | compatible = "adi,adt7481"; | ||
| 98 | reg = <0x4c>; | ||
| 99 | }; | ||
| 100 | |||
| 101 | rtc@68 { | ||
| 102 | compatible = "dallas,ds1339"; | ||
| 103 | reg = <0x68>; | ||
| 104 | interrupts = <0x1 0x1 0 0>; | ||
| 105 | }; | ||
| 106 | |||
| 107 | eeprom@50 { | ||
| 108 | compatible = "atmel,24c256"; | ||
| 109 | reg = <0x50>; | ||
| 110 | }; | ||
| 111 | }; | ||
| 112 | |||
| 113 | i2c@118100 { | ||
| 114 | pca9546@77 { | ||
| 115 | compatible = "nxp,pca9546"; | ||
| 116 | reg = <0x77>; | ||
| 117 | }; | ||
| 118 | }; | ||
| 119 | |||
| 120 | sdhc@114000 { | ||
| 121 | voltage-ranges = <1800 1800 3300 3300>; | ||
| 122 | }; | ||
| 123 | }; | ||
| 124 | |||
| 125 | pci0: pcie@ffe240000 { | ||
| 126 | reg = <0xf 0xfe240000 0 0x10000>; | ||
| 127 | ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000 | ||
| 128 | 0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>; | ||
| 129 | pcie@0 { | ||
| 130 | ranges = <0x02000000 0 0xe0000000 | ||
| 131 | 0x02000000 0 0xe0000000 | ||
| 132 | 0 0x20000000 | ||
| 133 | |||
| 134 | 0x01000000 0 0x00000000 | ||
| 135 | 0x01000000 0 0x00000000 | ||
| 136 | 0 0x00010000>; | ||
| 137 | }; | ||
| 138 | }; | ||
| 139 | |||
| 140 | pci1: pcie@ffe250000 { | ||
| 141 | reg = <0xf 0xfe250000 0 0x10000>; | ||
| 142 | ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x10000000 | ||
| 143 | 0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>; | ||
| 144 | pcie@0 { | ||
| 145 | ranges = <0x02000000 0 0xe0000000 | ||
| 146 | 0x02000000 0 0xe0000000 | ||
| 147 | 0 0x20000000 | ||
| 148 | |||
| 149 | 0x01000000 0 0x00000000 | ||
| 150 | 0x01000000 0 0x00000000 | ||
| 151 | 0 0x00010000>; | ||
| 152 | }; | ||
| 153 | }; | ||
| 154 | |||
| 155 | pci2: pcie@ffe260000 { | ||
| 156 | reg = <0xf 0xfe260000 0 0x1000>; | ||
| 157 | ranges = <0x02000000 0 0xe0000000 0xc 0x30000000 0 0x10000000 | ||
| 158 | 0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>; | ||
| 159 | pcie@0 { | ||
| 160 | ranges = <0x02000000 0 0xe0000000 | ||
| 161 | 0x02000000 0 0xe0000000 | ||
| 162 | 0 0x20000000 | ||
| 163 | |||
| 164 | 0x01000000 0 0x00000000 | ||
| 165 | 0x01000000 0 0x00000000 | ||
| 166 | 0 0x00010000>; | ||
| 167 | }; | ||
| 168 | }; | ||
| 169 | |||
| 170 | pci3: pcie@ffe270000 { | ||
| 171 | reg = <0xf 0xfe270000 0 0x10000>; | ||
| 172 | ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x10000000 | ||
| 173 | 0x01000000 0 0x00000000 0xf 0xf8030000 0 0x00010000>; | ||
| 174 | pcie@0 { | ||
| 175 | ranges = <0x02000000 0 0xe0000000 | ||
| 176 | 0x02000000 0 0xe0000000 | ||
| 177 | 0 0x20000000 | ||
| 178 | |||
| 179 | 0x01000000 0 0x00000000 | ||
| 180 | 0x01000000 0 0x00000000 | ||
| 181 | 0 0x00010000>; | ||
| 182 | }; | ||
| 183 | }; | ||
| 184 | }; | ||
diff --git a/arch/powerpc/boot/dts/t4240rdb.dts b/arch/powerpc/boot/dts/t4240rdb.dts new file mode 100644 index 000000000000..53761d4e8c51 --- /dev/null +++ b/arch/powerpc/boot/dts/t4240rdb.dts | |||
| @@ -0,0 +1,186 @@ | |||
| 1 | /* | ||
| 2 | * T4240RDB Device Tree Source | ||
| 3 | * | ||
| 4 | * Copyright 2014 Freescale Semiconductor Inc. | ||
| 5 | * | ||
| 6 | * Redistribution and use in source and binary forms, with or without | ||
| 7 | * modification, are permitted provided that the following conditions are met: | ||
| 8 | * * Redistributions of source code must retain the above copyright | ||
| 9 | * notice, this list of conditions and the following disclaimer. | ||
| 10 | * * Redistributions in binary form must reproduce the above copyright | ||
| 11 | * notice, this list of conditions and the following disclaimer in the | ||
| 12 | * documentation and/or other materials provided with the distribution. | ||
| 13 | * * Neither the name of Freescale Semiconductor nor the | ||
| 14 | * names of its contributors may be used to endorse or promote products | ||
| 15 | * derived from this software without specific prior written permission. | ||
| 16 | * | ||
| 17 | * | ||
| 18 | * ALTERNATIVELY, this software may be distributed under the terms of the | ||
| 19 | * GNU General Public License ("GPL") as published by the Free Software | ||
| 20 | * Foundation, either version 2 of that License or (at your option) any | ||
| 21 | * later version. | ||
| 22 | * | ||
| 23 | * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY | ||
| 24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
| 25 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
| 26 | * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY | ||
| 27 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
| 28 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
| 29 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
| 30 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
| 32 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 33 | */ | ||
| 34 | |||
| 35 | /include/ "fsl/t4240si-pre.dtsi" | ||
| 36 | |||
| 37 | / { | ||
| 38 | model = "fsl,T4240RDB"; | ||
| 39 | compatible = "fsl,T4240RDB"; | ||
| 40 | #address-cells = <2>; | ||
| 41 | #size-cells = <2>; | ||
| 42 | interrupt-parent = <&mpic>; | ||
| 43 | |||
| 44 | ifc: localbus@ffe124000 { | ||
| 45 | reg = <0xf 0xfe124000 0 0x2000>; | ||
| 46 | ranges = <0 0 0xf 0xe8000000 0x08000000 | ||
| 47 | 2 0 0xf 0xff800000 0x00010000 | ||
| 48 | 3 0 0xf 0xffdf0000 0x00008000>; | ||
| 49 | |||
| 50 | nor@0,0 { | ||
| 51 | #address-cells = <1>; | ||
| 52 | #size-cells = <1>; | ||
| 53 | compatible = "cfi-flash"; | ||
| 54 | reg = <0x0 0x0 0x8000000>; | ||
| 55 | |||
| 56 | bank-width = <2>; | ||
| 57 | device-width = <1>; | ||
| 58 | }; | ||
| 59 | |||
| 60 | nand@2,0 { | ||
| 61 | #address-cells = <1>; | ||
| 62 | #size-cells = <1>; | ||
| 63 | compatible = "fsl,ifc-nand"; | ||
| 64 | reg = <0x2 0x0 0x10000>; | ||
| 65 | }; | ||
| 66 | }; | ||
| 67 | |||
| 68 | memory { | ||
| 69 | device_type = "memory"; | ||
| 70 | }; | ||
| 71 | |||
| 72 | dcsr: dcsr@f00000000 { | ||
| 73 | ranges = <0x00000000 0xf 0x00000000 0x01072000>; | ||
| 74 | }; | ||
| 75 | |||
| 76 | soc: soc@ffe000000 { | ||
| 77 | ranges = <0x00000000 0xf 0xfe000000 0x1000000>; | ||
| 78 | reg = <0xf 0xfe000000 0 0x00001000>; | ||
| 79 | spi@110000 { | ||
| 80 | flash@0 { | ||
| 81 | #address-cells = <1>; | ||
| 82 | #size-cells = <1>; | ||
| 83 | compatible = "sst,sst25wf040"; | ||
| 84 | reg = <0>; | ||
| 85 | spi-max-frequency = <40000000>; /* input clock */ | ||
| 86 | }; | ||
| 87 | }; | ||
| 88 | |||
| 89 | i2c@118000 { | ||
| 90 | eeprom@52 { | ||
| 91 | compatible = "at24,24c256"; | ||
| 92 | reg = <0x52>; | ||
| 93 | }; | ||
| 94 | eeprom@54 { | ||
| 95 | compatible = "at24,24c256"; | ||
| 96 | reg = <0x54>; | ||
| 97 | }; | ||
| 98 | eeprom@56 { | ||
| 99 | compatible = "at24,24c256"; | ||
| 100 | reg = <0x56>; | ||
| 101 | }; | ||
| 102 | rtc@68 { | ||
| 103 | compatible = "dallas,ds1374"; | ||
| 104 | reg = <0x68>; | ||
| 105 | interrupts = <0x1 0x1 0 0>; | ||
| 106 | }; | ||
| 107 | }; | ||
| 108 | |||
| 109 | sdhc@114000 { | ||
| 110 | voltage-ranges = <1800 1800 3300 3300>; | ||
| 111 | }; | ||
| 112 | }; | ||
| 113 | |||
| 114 | pci0: pcie@ffe240000 { | ||
| 115 | reg = <0xf 0xfe240000 0 0x10000>; | ||
| 116 | ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000 | ||
| 117 | 0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>; | ||
| 118 | pcie@0 { | ||
| 119 | ranges = <0x02000000 0 0xe0000000 | ||
| 120 | 0x02000000 0 0xe0000000 | ||
| 121 | 0 0x20000000 | ||
| 122 | |||
| 123 | 0x01000000 0 0x00000000 | ||
| 124 | 0x01000000 0 0x00000000 | ||
| 125 | 0 0x00010000>; | ||
| 126 | }; | ||
| 127 | }; | ||
| 128 | |||
| 129 | pci1: pcie@ffe250000 { | ||
| 130 | reg = <0xf 0xfe250000 0 0x10000>; | ||
| 131 | ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000 | ||
| 132 | 0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>; | ||
| 133 | pcie@0 { | ||
| 134 | ranges = <0x02000000 0 0xe0000000 | ||
| 135 | 0x02000000 0 0xe0000000 | ||
| 136 | 0 0x20000000 | ||
| 137 | |||
| 138 | 0x01000000 0 0x00000000 | ||
| 139 | 0x01000000 0 0x00000000 | ||
| 140 | 0 0x00010000>; | ||
| 141 | }; | ||
| 142 | }; | ||
| 143 | |||
| 144 | pci2: pcie@ffe260000 { | ||
| 145 | reg = <0xf 0xfe260000 0 0x1000>; | ||
| 146 | ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000 | ||
| 147 | 0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>; | ||
| 148 | pcie@0 { | ||
| 149 | ranges = <0x02000000 0 0xe0000000 | ||
| 150 | 0x02000000 0 0xe0000000 | ||
| 151 | 0 0x20000000 | ||
| 152 | |||
| 153 | 0x01000000 0 0x00000000 | ||
| 154 | 0x01000000 0 0x00000000 | ||
| 155 | 0 0x00010000>; | ||
| 156 | }; | ||
| 157 | }; | ||
| 158 | |||
| 159 | pci3: pcie@ffe270000 { | ||
| 160 | reg = <0xf 0xfe270000 0 0x10000>; | ||
| 161 | ranges = <0x02000000 0 0xe0000000 0xc 0x60000000 0 0x20000000 | ||
| 162 | 0x01000000 0 0x00000000 0xf 0xf8030000 0 0x00010000>; | ||
| 163 | pcie@0 { | ||
| 164 | ranges = <0x02000000 0 0xe0000000 | ||
| 165 | 0x02000000 0 0xe0000000 | ||
| 166 | 0 0x20000000 | ||
| 167 | |||
| 168 | 0x01000000 0 0x00000000 | ||
| 169 | 0x01000000 0 0x00000000 | ||
| 170 | 0 0x00010000>; | ||
| 171 | }; | ||
| 172 | }; | ||
| 173 | |||
| 174 | rio: rapidio@ffe0c0000 { | ||
| 175 | reg = <0xf 0xfe0c0000 0 0x11000>; | ||
| 176 | |||
| 177 | port1 { | ||
| 178 | ranges = <0 0 0xc 0x20000000 0 0x10000000>; | ||
| 179 | }; | ||
| 180 | port2 { | ||
| 181 | ranges = <0 0 0xc 0x30000000 0 0x10000000>; | ||
| 182 | }; | ||
| 183 | }; | ||
| 184 | }; | ||
| 185 | |||
| 186 | /include/ "fsl/t4240si-post.dtsi" | ||
diff --git a/arch/powerpc/boot/io.h b/arch/powerpc/boot/io.h index 7c09f4861fe1..394da5500466 100644 --- a/arch/powerpc/boot/io.h +++ b/arch/powerpc/boot/io.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | #ifndef _IO_H | 1 | #ifndef _IO_H |
| 2 | #define __IO_H | 2 | #define _IO_H |
| 3 | 3 | ||
| 4 | #include "types.h" | 4 | #include "types.h" |
| 5 | 5 | ||
diff --git a/arch/powerpc/configs/corenet32_smp_defconfig b/arch/powerpc/configs/corenet32_smp_defconfig index c19ff057d0f9..6a3c58adf253 100644 --- a/arch/powerpc/configs/corenet32_smp_defconfig +++ b/arch/powerpc/configs/corenet32_smp_defconfig | |||
| @@ -139,8 +139,9 @@ CONFIG_EDAC=y | |||
| 139 | CONFIG_EDAC_MM_EDAC=y | 139 | CONFIG_EDAC_MM_EDAC=y |
| 140 | CONFIG_EDAC_MPC85XX=y | 140 | CONFIG_EDAC_MPC85XX=y |
| 141 | CONFIG_RTC_CLASS=y | 141 | CONFIG_RTC_CLASS=y |
| 142 | CONFIG_RTC_DRV_DS1307=y | ||
| 143 | CONFIG_RTC_DRV_DS1374=y | ||
| 142 | CONFIG_RTC_DRV_DS3232=y | 144 | CONFIG_RTC_DRV_DS3232=y |
| 143 | CONFIG_RTC_DRV_CMOS=y | ||
| 144 | CONFIG_UIO=y | 145 | CONFIG_UIO=y |
| 145 | CONFIG_STAGING=y | 146 | CONFIG_STAGING=y |
| 146 | CONFIG_VIRT_DRIVERS=y | 147 | CONFIG_VIRT_DRIVERS=y |
| @@ -179,3 +180,4 @@ CONFIG_CRYPTO_SHA512=y | |||
| 179 | CONFIG_CRYPTO_AES=y | 180 | CONFIG_CRYPTO_AES=y |
| 180 | # CONFIG_CRYPTO_ANSI_CPRNG is not set | 181 | # CONFIG_CRYPTO_ANSI_CPRNG is not set |
| 181 | CONFIG_CRYPTO_DEV_FSL_CAAM=y | 182 | CONFIG_CRYPTO_DEV_FSL_CAAM=y |
| 183 | CONFIG_FSL_CORENET_CF=y | ||
diff --git a/arch/powerpc/configs/corenet64_smp_defconfig b/arch/powerpc/configs/corenet64_smp_defconfig index 5c7fa19ae4ef..4b07bade1ba9 100644 --- a/arch/powerpc/configs/corenet64_smp_defconfig +++ b/arch/powerpc/configs/corenet64_smp_defconfig | |||
| @@ -123,6 +123,10 @@ CONFIG_USB_EHCI_FSL=y | |||
| 123 | CONFIG_USB_STORAGE=y | 123 | CONFIG_USB_STORAGE=y |
| 124 | CONFIG_MMC=y | 124 | CONFIG_MMC=y |
| 125 | CONFIG_MMC_SDHCI=y | 125 | CONFIG_MMC_SDHCI=y |
| 126 | CONFIG_RTC_CLASS=y | ||
| 127 | CONFIG_RTC_DRV_DS1307=y | ||
| 128 | CONFIG_RTC_DRV_DS1374=y | ||
| 129 | CONFIG_RTC_DRV_DS3232=y | ||
| 126 | CONFIG_EDAC=y | 130 | CONFIG_EDAC=y |
| 127 | CONFIG_EDAC_MM_EDAC=y | 131 | CONFIG_EDAC_MM_EDAC=y |
| 128 | CONFIG_DMADEVICES=y | 132 | CONFIG_DMADEVICES=y |
| @@ -175,3 +179,4 @@ CONFIG_CRYPTO_SHA256=y | |||
| 175 | CONFIG_CRYPTO_SHA512=y | 179 | CONFIG_CRYPTO_SHA512=y |
| 176 | # CONFIG_CRYPTO_ANSI_CPRNG is not set | 180 | # CONFIG_CRYPTO_ANSI_CPRNG is not set |
| 177 | CONFIG_CRYPTO_DEV_FSL_CAAM=y | 181 | CONFIG_CRYPTO_DEV_FSL_CAAM=y |
| 182 | CONFIG_FSL_CORENET_CF=y | ||
diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig index 55765c8cb08f..fa1bfd37f1ec 100644 --- a/arch/powerpc/configs/mpc85xx_defconfig +++ b/arch/powerpc/configs/mpc85xx_defconfig | |||
| @@ -209,6 +209,9 @@ CONFIG_MMC_SDHCI_OF_ESDHC=y | |||
| 209 | CONFIG_EDAC=y | 209 | CONFIG_EDAC=y |
| 210 | CONFIG_EDAC_MM_EDAC=y | 210 | CONFIG_EDAC_MM_EDAC=y |
| 211 | CONFIG_RTC_CLASS=y | 211 | CONFIG_RTC_CLASS=y |
| 212 | CONFIG_RTC_DRV_DS1307=y | ||
| 213 | CONFIG_RTC_DRV_DS1374=y | ||
| 214 | CONFIG_RTC_DRV_DS3232=y | ||
| 212 | CONFIG_RTC_DRV_CMOS=y | 215 | CONFIG_RTC_DRV_CMOS=y |
| 213 | CONFIG_RTC_DRV_DS1307=y | 216 | CONFIG_RTC_DRV_DS1307=y |
| 214 | CONFIG_DMADEVICES=y | 217 | CONFIG_DMADEVICES=y |
diff --git a/arch/powerpc/configs/mpc85xx_smp_defconfig b/arch/powerpc/configs/mpc85xx_smp_defconfig index 5c6ecdc0f70e..0b452ebd8b3d 100644 --- a/arch/powerpc/configs/mpc85xx_smp_defconfig +++ b/arch/powerpc/configs/mpc85xx_smp_defconfig | |||
| @@ -210,6 +210,9 @@ CONFIG_MMC_SDHCI_OF_ESDHC=y | |||
| 210 | CONFIG_EDAC=y | 210 | CONFIG_EDAC=y |
| 211 | CONFIG_EDAC_MM_EDAC=y | 211 | CONFIG_EDAC_MM_EDAC=y |
| 212 | CONFIG_RTC_CLASS=y | 212 | CONFIG_RTC_CLASS=y |
| 213 | CONFIG_RTC_DRV_DS1307=y | ||
| 214 | CONFIG_RTC_DRV_DS1374=y | ||
| 215 | CONFIG_RTC_DRV_DS3232=y | ||
| 213 | CONFIG_RTC_DRV_CMOS=y | 216 | CONFIG_RTC_DRV_CMOS=y |
| 214 | CONFIG_RTC_DRV_DS1307=y | 217 | CONFIG_RTC_DRV_DS1307=y |
| 215 | CONFIG_DMADEVICES=y | 218 | CONFIG_DMADEVICES=y |
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index 0fdd7eece6d9..642e436d4595 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h | |||
| @@ -195,8 +195,7 @@ extern const char *powerpc_base_platform; | |||
| 195 | 195 | ||
| 196 | #define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_NOEXECUTE | CPU_FTR_NODSISRALIGN) | 196 | #define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_NOEXECUTE | CPU_FTR_NODSISRALIGN) |
| 197 | 197 | ||
| 198 | #define MMU_FTR_PPCAS_ARCH_V2 (MMU_FTR_SLB | MMU_FTR_TLBIEL | \ | 198 | #define MMU_FTR_PPCAS_ARCH_V2 (MMU_FTR_TLBIEL | MMU_FTR_16M_PAGE) |
| 199 | MMU_FTR_16M_PAGE) | ||
| 200 | 199 | ||
| 201 | /* We only set the altivec features if the kernel was compiled with altivec | 200 | /* We only set the altivec features if the kernel was compiled with altivec |
| 202 | * support | 201 | * support |
| @@ -268,10 +267,6 @@ extern const char *powerpc_base_platform; | |||
| 268 | #define CPU_FTR_MAYBE_CAN_NAP 0 | 267 | #define CPU_FTR_MAYBE_CAN_NAP 0 |
| 269 | #endif | 268 | #endif |
| 270 | 269 | ||
| 271 | #define CLASSIC_PPC (!defined(CONFIG_8xx) && !defined(CONFIG_4xx) && \ | ||
| 272 | !defined(CONFIG_POWER3) && !defined(CONFIG_POWER4) && \ | ||
| 273 | !defined(CONFIG_BOOKE)) | ||
| 274 | |||
| 275 | #define CPU_FTRS_PPC601 (CPU_FTR_COMMON | CPU_FTR_601 | \ | 270 | #define CPU_FTRS_PPC601 (CPU_FTR_COMMON | CPU_FTR_601 | \ |
| 276 | CPU_FTR_COHERENT_ICACHE | CPU_FTR_UNIFIED_ID_CACHE) | 271 | CPU_FTR_COHERENT_ICACHE | CPU_FTR_UNIFIED_ID_CACHE) |
| 277 | #define CPU_FTRS_603 (CPU_FTR_COMMON | \ | 272 | #define CPU_FTRS_603 (CPU_FTR_COMMON | \ |
| @@ -396,15 +391,10 @@ extern const char *powerpc_base_platform; | |||
| 396 | CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \ | 391 | CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \ |
| 397 | CPU_FTR_DBELL | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ | 392 | CPU_FTR_DBELL | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ |
| 398 | CPU_FTR_DEBUG_LVL_EXC | CPU_FTR_EMB_HV | CPU_FTR_ALTIVEC_COMP | \ | 393 | CPU_FTR_DEBUG_LVL_EXC | CPU_FTR_EMB_HV | CPU_FTR_ALTIVEC_COMP | \ |
| 399 | CPU_FTR_CELL_TB_BUG) | 394 | CPU_FTR_CELL_TB_BUG | CPU_FTR_SMT) |
| 400 | #define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN) | 395 | #define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN) |
| 401 | 396 | ||
| 402 | /* 64-bit CPUs */ | 397 | /* 64-bit CPUs */ |
| 403 | #define CPU_FTRS_POWER3 (CPU_FTR_USE_TB | \ | ||
| 404 | CPU_FTR_IABR | CPU_FTR_PPC_LE) | ||
| 405 | #define CPU_FTRS_RS64 (CPU_FTR_USE_TB | \ | ||
| 406 | CPU_FTR_IABR | \ | ||
| 407 | CPU_FTR_MMCRA | CPU_FTR_CTRL) | ||
| 408 | #define CPU_FTRS_POWER4 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ | 398 | #define CPU_FTRS_POWER4 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ |
| 409 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ | 399 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ |
| 410 | CPU_FTR_MMCRA | CPU_FTR_CP_USE_DCBTZ | \ | 400 | CPU_FTR_MMCRA | CPU_FTR_CP_USE_DCBTZ | \ |
| @@ -467,15 +457,14 @@ extern const char *powerpc_base_platform; | |||
| 467 | #define CPU_FTRS_POSSIBLE (CPU_FTRS_E6500 | CPU_FTRS_E5500 | CPU_FTRS_A2) | 457 | #define CPU_FTRS_POSSIBLE (CPU_FTRS_E6500 | CPU_FTRS_E5500 | CPU_FTRS_A2) |
| 468 | #else | 458 | #else |
| 469 | #define CPU_FTRS_POSSIBLE \ | 459 | #define CPU_FTRS_POSSIBLE \ |
| 470 | (CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 | \ | 460 | (CPU_FTRS_POWER4 | CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | \ |
| 471 | CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_POWER6 | \ | 461 | CPU_FTRS_POWER6 | CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | \ |
| 472 | CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | CPU_FTRS_POWER8 | \ | 462 | CPU_FTRS_POWER8 | CPU_FTRS_CELL | CPU_FTRS_PA6T | CPU_FTR_VSX) |
| 473 | CPU_FTRS_CELL | CPU_FTRS_PA6T | CPU_FTR_VSX) | ||
| 474 | #endif | 463 | #endif |
| 475 | #else | 464 | #else |
| 476 | enum { | 465 | enum { |
| 477 | CPU_FTRS_POSSIBLE = | 466 | CPU_FTRS_POSSIBLE = |
| 478 | #if CLASSIC_PPC | 467 | #ifdef CONFIG_PPC_BOOK3S_32 |
| 479 | CPU_FTRS_PPC601 | CPU_FTRS_603 | CPU_FTRS_604 | CPU_FTRS_740_NOTAU | | 468 | CPU_FTRS_PPC601 | CPU_FTRS_603 | CPU_FTRS_604 | CPU_FTRS_740_NOTAU | |
| 480 | CPU_FTRS_740 | CPU_FTRS_750 | CPU_FTRS_750FX1 | | 469 | CPU_FTRS_740 | CPU_FTRS_750 | CPU_FTRS_750FX1 | |
| 481 | CPU_FTRS_750FX2 | CPU_FTRS_750FX | CPU_FTRS_750GX | | 470 | CPU_FTRS_750FX2 | CPU_FTRS_750FX | CPU_FTRS_750GX | |
| @@ -518,14 +507,14 @@ enum { | |||
| 518 | #define CPU_FTRS_ALWAYS (CPU_FTRS_E6500 & CPU_FTRS_E5500 & CPU_FTRS_A2) | 507 | #define CPU_FTRS_ALWAYS (CPU_FTRS_E6500 & CPU_FTRS_E5500 & CPU_FTRS_A2) |
| 519 | #else | 508 | #else |
| 520 | #define CPU_FTRS_ALWAYS \ | 509 | #define CPU_FTRS_ALWAYS \ |
| 521 | (CPU_FTRS_POWER3 & CPU_FTRS_RS64 & CPU_FTRS_POWER4 & \ | 510 | (CPU_FTRS_POWER4 & CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & \ |
| 522 | CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & CPU_FTRS_POWER6 & \ | 511 | CPU_FTRS_POWER6 & CPU_FTRS_POWER7 & CPU_FTRS_CELL & \ |
| 523 | CPU_FTRS_POWER7 & CPU_FTRS_CELL & CPU_FTRS_PA6T & CPU_FTRS_POSSIBLE) | 512 | CPU_FTRS_PA6T & CPU_FTRS_POSSIBLE) |
| 524 | #endif | 513 | #endif |
| 525 | #else | 514 | #else |
| 526 | enum { | 515 | enum { |
| 527 | CPU_FTRS_ALWAYS = | 516 | CPU_FTRS_ALWAYS = |
| 528 | #if CLASSIC_PPC | 517 | #ifdef CONFIG_PPC_BOOK3S_32 |
| 529 | CPU_FTRS_PPC601 & CPU_FTRS_603 & CPU_FTRS_604 & CPU_FTRS_740_NOTAU & | 518 | CPU_FTRS_PPC601 & CPU_FTRS_603 & CPU_FTRS_604 & CPU_FTRS_740_NOTAU & |
| 530 | CPU_FTRS_740 & CPU_FTRS_750 & CPU_FTRS_750FX1 & | 519 | CPU_FTRS_740 & CPU_FTRS_750 & CPU_FTRS_750FX1 & |
| 531 | CPU_FTRS_750FX2 & CPU_FTRS_750FX & CPU_FTRS_750GX & | 520 | CPU_FTRS_750FX2 & CPU_FTRS_750FX & CPU_FTRS_750GX & |
diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index fab7743c2640..9983c3d26bca 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <linux/list.h> | 25 | #include <linux/list.h> |
| 26 | #include <linux/string.h> | 26 | #include <linux/string.h> |
| 27 | #include <linux/time.h> | 27 | #include <linux/time.h> |
| 28 | #include <linux/atomic.h> | ||
| 28 | 29 | ||
| 29 | struct pci_dev; | 30 | struct pci_dev; |
| 30 | struct pci_bus; | 31 | struct pci_bus; |
| @@ -33,10 +34,11 @@ struct device_node; | |||
| 33 | #ifdef CONFIG_EEH | 34 | #ifdef CONFIG_EEH |
| 34 | 35 | ||
| 35 | /* EEH subsystem flags */ | 36 | /* EEH subsystem flags */ |
| 36 | #define EEH_ENABLED 0x1 /* EEH enabled */ | 37 | #define EEH_ENABLED 0x01 /* EEH enabled */ |
| 37 | #define EEH_FORCE_DISABLED 0x2 /* EEH disabled */ | 38 | #define EEH_FORCE_DISABLED 0x02 /* EEH disabled */ |
| 38 | #define EEH_PROBE_MODE_DEV 0x4 /* From PCI device */ | 39 | #define EEH_PROBE_MODE_DEV 0x04 /* From PCI device */ |
| 39 | #define EEH_PROBE_MODE_DEVTREE 0x8 /* From device tree */ | 40 | #define EEH_PROBE_MODE_DEVTREE 0x08 /* From device tree */ |
| 41 | #define EEH_ENABLE_IO_FOR_LOG 0x10 /* Enable IO for log */ | ||
| 40 | 42 | ||
| 41 | /* | 43 | /* |
| 42 | * Delay for PE reset, all in ms | 44 | * Delay for PE reset, all in ms |
| @@ -84,7 +86,9 @@ struct eeh_pe { | |||
| 84 | int freeze_count; /* Times of froze up */ | 86 | int freeze_count; /* Times of froze up */ |
| 85 | struct timeval tstamp; /* Time on first-time freeze */ | 87 | struct timeval tstamp; /* Time on first-time freeze */ |
| 86 | int false_positives; /* Times of reported #ff's */ | 88 | int false_positives; /* Times of reported #ff's */ |
| 89 | atomic_t pass_dev_cnt; /* Count of passed through devs */ | ||
| 87 | struct eeh_pe *parent; /* Parent PE */ | 90 | struct eeh_pe *parent; /* Parent PE */ |
| 91 | void *data; /* PE auxillary data */ | ||
| 88 | struct list_head child_list; /* Link PE to the child list */ | 92 | struct list_head child_list; /* Link PE to the child list */ |
| 89 | struct list_head edevs; /* Link list of EEH devices */ | 93 | struct list_head edevs; /* Link list of EEH devices */ |
| 90 | struct list_head child; /* Child PEs */ | 94 | struct list_head child; /* Child PEs */ |
| @@ -93,6 +97,11 @@ struct eeh_pe { | |||
| 93 | #define eeh_pe_for_each_dev(pe, edev, tmp) \ | 97 | #define eeh_pe_for_each_dev(pe, edev, tmp) \ |
| 94 | list_for_each_entry_safe(edev, tmp, &pe->edevs, list) | 98 | list_for_each_entry_safe(edev, tmp, &pe->edevs, list) |
| 95 | 99 | ||
| 100 | static inline bool eeh_pe_passed(struct eeh_pe *pe) | ||
| 101 | { | ||
| 102 | return pe ? !!atomic_read(&pe->pass_dev_cnt) : false; | ||
| 103 | } | ||
| 104 | |||
| 96 | /* | 105 | /* |
| 97 | * The struct is used to trace EEH state for the associated | 106 | * The struct is used to trace EEH state for the associated |
| 98 | * PCI device node or PCI device. In future, it might | 107 | * PCI device node or PCI device. In future, it might |
| @@ -165,6 +174,11 @@ enum { | |||
| 165 | #define EEH_STATE_DMA_ACTIVE (1 << 4) /* Active DMA */ | 174 | #define EEH_STATE_DMA_ACTIVE (1 << 4) /* Active DMA */ |
| 166 | #define EEH_STATE_MMIO_ENABLED (1 << 5) /* MMIO enabled */ | 175 | #define EEH_STATE_MMIO_ENABLED (1 << 5) /* MMIO enabled */ |
| 167 | #define EEH_STATE_DMA_ENABLED (1 << 6) /* DMA enabled */ | 176 | #define EEH_STATE_DMA_ENABLED (1 << 6) /* DMA enabled */ |
| 177 | #define EEH_PE_STATE_NORMAL 0 /* Normal state */ | ||
| 178 | #define EEH_PE_STATE_RESET 1 /* PE reset asserted */ | ||
| 179 | #define EEH_PE_STATE_STOPPED_IO_DMA 2 /* Frozen PE */ | ||
| 180 | #define EEH_PE_STATE_STOPPED_DMA 4 /* Stopped DMA, Enabled IO */ | ||
| 181 | #define EEH_PE_STATE_UNAVAIL 5 /* Unavailable */ | ||
| 168 | #define EEH_RESET_DEACTIVATE 0 /* Deactivate the PE reset */ | 182 | #define EEH_RESET_DEACTIVATE 0 /* Deactivate the PE reset */ |
| 169 | #define EEH_RESET_HOT 1 /* Hot reset */ | 183 | #define EEH_RESET_HOT 1 /* Hot reset */ |
| 170 | #define EEH_RESET_FUNDAMENTAL 3 /* Fundamental reset */ | 184 | #define EEH_RESET_FUNDAMENTAL 3 /* Fundamental reset */ |
| @@ -194,36 +208,28 @@ extern int eeh_subsystem_flags; | |||
| 194 | extern struct eeh_ops *eeh_ops; | 208 | extern struct eeh_ops *eeh_ops; |
| 195 | extern raw_spinlock_t confirm_error_lock; | 209 | extern raw_spinlock_t confirm_error_lock; |
| 196 | 210 | ||
| 197 | static inline bool eeh_enabled(void) | 211 | static inline void eeh_add_flag(int flag) |
| 198 | { | 212 | { |
| 199 | if ((eeh_subsystem_flags & EEH_FORCE_DISABLED) || | 213 | eeh_subsystem_flags |= flag; |
| 200 | !(eeh_subsystem_flags & EEH_ENABLED)) | ||
| 201 | return false; | ||
| 202 | |||
| 203 | return true; | ||
| 204 | } | 214 | } |
| 205 | 215 | ||
| 206 | static inline void eeh_set_enable(bool mode) | 216 | static inline void eeh_clear_flag(int flag) |
| 207 | { | 217 | { |
| 208 | if (mode) | 218 | eeh_subsystem_flags &= ~flag; |
| 209 | eeh_subsystem_flags |= EEH_ENABLED; | ||
| 210 | else | ||
| 211 | eeh_subsystem_flags &= ~EEH_ENABLED; | ||
| 212 | } | 219 | } |
| 213 | 220 | ||
| 214 | static inline void eeh_probe_mode_set(int flag) | 221 | static inline bool eeh_has_flag(int flag) |
| 215 | { | 222 | { |
| 216 | eeh_subsystem_flags |= flag; | 223 | return !!(eeh_subsystem_flags & flag); |
| 217 | } | 224 | } |
| 218 | 225 | ||
| 219 | static inline int eeh_probe_mode_devtree(void) | 226 | static inline bool eeh_enabled(void) |
| 220 | { | 227 | { |
| 221 | return (eeh_subsystem_flags & EEH_PROBE_MODE_DEVTREE); | 228 | if (eeh_has_flag(EEH_FORCE_DISABLED) || |
| 222 | } | 229 | !eeh_has_flag(EEH_ENABLED)) |
| 230 | return false; | ||
| 223 | 231 | ||
| 224 | static inline int eeh_probe_mode_dev(void) | 232 | return true; |
| 225 | { | ||
| 226 | return (eeh_subsystem_flags & EEH_PROBE_MODE_DEV); | ||
| 227 | } | 233 | } |
| 228 | 234 | ||
| 229 | static inline void eeh_serialize_lock(unsigned long *flags) | 235 | static inline void eeh_serialize_lock(unsigned long *flags) |
| @@ -243,6 +249,7 @@ static inline void eeh_serialize_unlock(unsigned long flags) | |||
| 243 | #define EEH_MAX_ALLOWED_FREEZES 5 | 249 | #define EEH_MAX_ALLOWED_FREEZES 5 |
| 244 | 250 | ||
| 245 | typedef void *(*eeh_traverse_func)(void *data, void *flag); | 251 | typedef void *(*eeh_traverse_func)(void *data, void *flag); |
| 252 | void eeh_set_pe_aux_size(int size); | ||
| 246 | int eeh_phb_pe_create(struct pci_controller *phb); | 253 | int eeh_phb_pe_create(struct pci_controller *phb); |
| 247 | struct eeh_pe *eeh_phb_pe_get(struct pci_controller *phb); | 254 | struct eeh_pe *eeh_phb_pe_get(struct pci_controller *phb); |
| 248 | struct eeh_pe *eeh_pe_get(struct eeh_dev *edev); | 255 | struct eeh_pe *eeh_pe_get(struct eeh_dev *edev); |
| @@ -272,6 +279,13 @@ void eeh_add_device_late(struct pci_dev *); | |||
| 272 | void eeh_add_device_tree_late(struct pci_bus *); | 279 | void eeh_add_device_tree_late(struct pci_bus *); |
| 273 | void eeh_add_sysfs_files(struct pci_bus *); | 280 | void eeh_add_sysfs_files(struct pci_bus *); |
| 274 | void eeh_remove_device(struct pci_dev *); | 281 | void eeh_remove_device(struct pci_dev *); |
| 282 | int eeh_dev_open(struct pci_dev *pdev); | ||
| 283 | void eeh_dev_release(struct pci_dev *pdev); | ||
| 284 | struct eeh_pe *eeh_iommu_group_to_pe(struct iommu_group *group); | ||
| 285 | int eeh_pe_set_option(struct eeh_pe *pe, int option); | ||
| 286 | int eeh_pe_get_state(struct eeh_pe *pe); | ||
| 287 | int eeh_pe_reset(struct eeh_pe *pe, int option); | ||
| 288 | int eeh_pe_configure(struct eeh_pe *pe); | ||
| 275 | 289 | ||
| 276 | /** | 290 | /** |
| 277 | * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure. | 291 | * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure. |
| @@ -295,8 +309,6 @@ static inline bool eeh_enabled(void) | |||
| 295 | return false; | 309 | return false; |
| 296 | } | 310 | } |
| 297 | 311 | ||
| 298 | static inline void eeh_set_enable(bool mode) { } | ||
| 299 | |||
| 300 | static inline int eeh_init(void) | 312 | static inline int eeh_init(void) |
| 301 | { | 313 | { |
| 302 | return 0; | 314 | return 0; |
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index 8f35cd7d59cc..77f52b26dad6 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h | |||
| @@ -425,6 +425,8 @@ label##_relon_hv: \ | |||
| 425 | #define SOFTEN_VALUE_0xa00 PACA_IRQ_DBELL | 425 | #define SOFTEN_VALUE_0xa00 PACA_IRQ_DBELL |
| 426 | #define SOFTEN_VALUE_0xe80 PACA_IRQ_DBELL | 426 | #define SOFTEN_VALUE_0xe80 PACA_IRQ_DBELL |
| 427 | #define SOFTEN_VALUE_0xe82 PACA_IRQ_DBELL | 427 | #define SOFTEN_VALUE_0xe82 PACA_IRQ_DBELL |
| 428 | #define SOFTEN_VALUE_0xe60 PACA_IRQ_HMI | ||
| 429 | #define SOFTEN_VALUE_0xe62 PACA_IRQ_HMI | ||
| 428 | 430 | ||
| 429 | #define __SOFTEN_TEST(h, vec) \ | 431 | #define __SOFTEN_TEST(h, vec) \ |
| 430 | lbz r10,PACASOFTIRQEN(r13); \ | 432 | lbz r10,PACASOFTIRQEN(r13); \ |
| @@ -513,8 +515,11 @@ label##_relon_hv: \ | |||
| 513 | * runlatch, etc... | 515 | * runlatch, etc... |
| 514 | */ | 516 | */ |
| 515 | 517 | ||
| 516 | /* Exception addition: Hard disable interrupts */ | 518 | /* |
| 517 | #define DISABLE_INTS RECONCILE_IRQ_STATE(r10,r11) | 519 | * This addition reconciles our actual IRQ state with the various software |
| 520 | * flags that track it. This may call C code. | ||
| 521 | */ | ||
| 522 | #define ADD_RECONCILE RECONCILE_IRQ_STATE(r10,r11) | ||
| 518 | 523 | ||
| 519 | #define ADD_NVGPRS \ | 524 | #define ADD_NVGPRS \ |
| 520 | bl save_nvgprs | 525 | bl save_nvgprs |
| @@ -532,6 +537,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_CTRL) | |||
| 532 | .globl label##_common; \ | 537 | .globl label##_common; \ |
| 533 | label##_common: \ | 538 | label##_common: \ |
| 534 | EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \ | 539 | EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \ |
| 540 | /* Volatile regs are potentially clobbered here */ \ | ||
| 535 | additions; \ | 541 | additions; \ |
| 536 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | 542 | addi r3,r1,STACK_FRAME_OVERHEAD; \ |
| 537 | bl hdlr; \ | 543 | bl hdlr; \ |
| @@ -539,7 +545,7 @@ label##_common: \ | |||
| 539 | 545 | ||
| 540 | #define STD_EXCEPTION_COMMON(trap, label, hdlr) \ | 546 | #define STD_EXCEPTION_COMMON(trap, label, hdlr) \ |
| 541 | EXCEPTION_COMMON(trap, label, hdlr, ret_from_except, \ | 547 | EXCEPTION_COMMON(trap, label, hdlr, ret_from_except, \ |
| 542 | ADD_NVGPRS;DISABLE_INTS) | 548 | ADD_NVGPRS;ADD_RECONCILE) |
| 543 | 549 | ||
| 544 | /* | 550 | /* |
| 545 | * Like STD_EXCEPTION_COMMON, but for exceptions that can occur | 551 | * Like STD_EXCEPTION_COMMON, but for exceptions that can occur |
| @@ -548,7 +554,7 @@ label##_common: \ | |||
| 548 | */ | 554 | */ |
| 549 | #define STD_EXCEPTION_COMMON_ASYNC(trap, label, hdlr) \ | 555 | #define STD_EXCEPTION_COMMON_ASYNC(trap, label, hdlr) \ |
| 550 | EXCEPTION_COMMON(trap, label, hdlr, ret_from_except_lite, \ | 556 | EXCEPTION_COMMON(trap, label, hdlr, ret_from_except_lite, \ |
| 551 | FINISH_NAP;DISABLE_INTS;RUNLATCH_ON) | 557 | FINISH_NAP;ADD_RECONCILE;RUNLATCH_ON) |
| 552 | 558 | ||
| 553 | /* | 559 | /* |
| 554 | * When the idle code in power4_idle puts the CPU into NAP mode, | 560 | * When the idle code in power4_idle puts the CPU into NAP mode, |
diff --git a/arch/powerpc/include/asm/fs_pd.h b/arch/powerpc/include/asm/fs_pd.h index 9361cd5342cc..f79d6c74eb2a 100644 --- a/arch/powerpc/include/asm/fs_pd.h +++ b/arch/powerpc/include/asm/fs_pd.h | |||
| @@ -28,7 +28,6 @@ | |||
| 28 | 28 | ||
| 29 | #ifdef CONFIG_8xx | 29 | #ifdef CONFIG_8xx |
| 30 | #include <asm/8xx_immap.h> | 30 | #include <asm/8xx_immap.h> |
| 31 | #include <asm/mpc8xx.h> | ||
| 32 | 31 | ||
| 33 | extern immap_t __iomem *mpc8xx_immr; | 32 | extern immap_t __iomem *mpc8xx_immr; |
| 34 | 33 | ||
diff --git a/arch/powerpc/include/asm/hardirq.h b/arch/powerpc/include/asm/hardirq.h index 418fb654370d..1bbb3013d6aa 100644 --- a/arch/powerpc/include/asm/hardirq.h +++ b/arch/powerpc/include/asm/hardirq.h | |||
| @@ -11,6 +11,7 @@ typedef struct { | |||
| 11 | unsigned int pmu_irqs; | 11 | unsigned int pmu_irqs; |
| 12 | unsigned int mce_exceptions; | 12 | unsigned int mce_exceptions; |
| 13 | unsigned int spurious_irqs; | 13 | unsigned int spurious_irqs; |
| 14 | unsigned int hmi_exceptions; | ||
| 14 | #ifdef CONFIG_PPC_DOORBELL | 15 | #ifdef CONFIG_PPC_DOORBELL |
| 15 | unsigned int doorbell_irqs; | 16 | unsigned int doorbell_irqs; |
| 16 | #endif | 17 | #endif |
diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h index 10be1dd01c6b..b59ac27a6b7d 100644 --- a/arch/powerpc/include/asm/hw_irq.h +++ b/arch/powerpc/include/asm/hw_irq.h | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #define PACA_IRQ_EE 0x04 | 25 | #define PACA_IRQ_EE 0x04 |
| 26 | #define PACA_IRQ_DEC 0x08 /* Or FIT */ | 26 | #define PACA_IRQ_DEC 0x08 /* Or FIT */ |
| 27 | #define PACA_IRQ_EE_EDGE 0x10 /* BookE only */ | 27 | #define PACA_IRQ_EE_EDGE 0x10 /* BookE only */ |
| 28 | #define PACA_IRQ_HMI 0x20 | ||
| 28 | 29 | ||
| 29 | #endif /* CONFIG_PPC64 */ | 30 | #endif /* CONFIG_PPC64 */ |
| 30 | 31 | ||
diff --git a/arch/powerpc/include/asm/irqflags.h b/arch/powerpc/include/asm/irqflags.h index e20eb95429a8..f2149066fe5d 100644 --- a/arch/powerpc/include/asm/irqflags.h +++ b/arch/powerpc/include/asm/irqflags.h | |||
| @@ -32,9 +32,8 @@ | |||
| 32 | #endif | 32 | #endif |
| 33 | 33 | ||
| 34 | /* | 34 | /* |
| 35 | * Most of the CPU's IRQ-state tracing is done from assembly code; we | 35 | * These are calls to C code, so the caller must be prepared for volatiles to |
| 36 | * have to call a C function so call a wrapper that saves all the | 36 | * be clobbered. |
| 37 | * C-clobbered registers. | ||
| 38 | */ | 37 | */ |
| 39 | #define TRACE_ENABLE_INTS TRACE_WITH_FRAME_BUFFER(trace_hardirqs_on) | 38 | #define TRACE_ENABLE_INTS TRACE_WITH_FRAME_BUFFER(trace_hardirqs_on) |
| 40 | #define TRACE_DISABLE_INTS TRACE_WITH_FRAME_BUFFER(trace_hardirqs_off) | 39 | #define TRACE_DISABLE_INTS TRACE_WITH_FRAME_BUFFER(trace_hardirqs_off) |
| @@ -42,6 +41,9 @@ | |||
| 42 | /* | 41 | /* |
| 43 | * This is used by assembly code to soft-disable interrupts first and | 42 | * This is used by assembly code to soft-disable interrupts first and |
| 44 | * reconcile irq state. | 43 | * reconcile irq state. |
| 44 | * | ||
| 45 | * NB: This may call C code, so the caller must be prepared for volatiles to | ||
| 46 | * be clobbered. | ||
| 45 | */ | 47 | */ |
| 46 | #define RECONCILE_IRQ_STATE(__rA, __rB) \ | 48 | #define RECONCILE_IRQ_STATE(__rA, __rB) \ |
| 47 | lbz __rA,PACASOFTIRQEN(r13); \ | 49 | lbz __rA,PACASOFTIRQEN(r13); \ |
diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h index f016bb699b5f..efbf9a322a23 100644 --- a/arch/powerpc/include/asm/jump_label.h +++ b/arch/powerpc/include/asm/jump_label.h | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | * 2 of the License, or (at your option) any later version. | 10 | * 2 of the License, or (at your option) any later version. |
| 11 | */ | 11 | */ |
| 12 | 12 | ||
| 13 | #ifndef __ASSEMBLY__ | ||
| 13 | #include <linux/types.h> | 14 | #include <linux/types.h> |
| 14 | 15 | ||
| 15 | #include <asm/feature-fixups.h> | 16 | #include <asm/feature-fixups.h> |
| @@ -42,4 +43,12 @@ struct jump_entry { | |||
| 42 | jump_label_t key; | 43 | jump_label_t key; |
| 43 | }; | 44 | }; |
| 44 | 45 | ||
| 46 | #else | ||
| 47 | #define ARCH_STATIC_BRANCH(LABEL, KEY) \ | ||
| 48 | 1098: nop; \ | ||
| 49 | .pushsection __jump_table, "aw"; \ | ||
| 50 | FTR_ENTRY_LONG 1098b, LABEL, KEY; \ | ||
| 51 | .popsection | ||
| 52 | #endif | ||
| 53 | |||
| 45 | #endif /* _ASM_POWERPC_JUMP_LABEL_H */ | 54 | #endif /* _ASM_POWERPC_JUMP_LABEL_H */ |
diff --git a/arch/powerpc/include/asm/kvm_asm.h b/arch/powerpc/include/asm/kvm_asm.h index 9601741080e5..ecf7e133a4f2 100644 --- a/arch/powerpc/include/asm/kvm_asm.h +++ b/arch/powerpc/include/asm/kvm_asm.h | |||
| @@ -98,6 +98,7 @@ | |||
| 98 | #define BOOK3S_INTERRUPT_H_DATA_STORAGE 0xe00 | 98 | #define BOOK3S_INTERRUPT_H_DATA_STORAGE 0xe00 |
| 99 | #define BOOK3S_INTERRUPT_H_INST_STORAGE 0xe20 | 99 | #define BOOK3S_INTERRUPT_H_INST_STORAGE 0xe20 |
| 100 | #define BOOK3S_INTERRUPT_H_EMUL_ASSIST 0xe40 | 100 | #define BOOK3S_INTERRUPT_H_EMUL_ASSIST 0xe40 |
| 101 | #define BOOK3S_INTERRUPT_HMI 0xe60 | ||
| 101 | #define BOOK3S_INTERRUPT_H_DOORBELL 0xe80 | 102 | #define BOOK3S_INTERRUPT_H_DOORBELL 0xe80 |
| 102 | #define BOOK3S_INTERRUPT_PERFMON 0xf00 | 103 | #define BOOK3S_INTERRUPT_PERFMON 0xf00 |
| 103 | #define BOOK3S_INTERRUPT_ALTIVEC 0xf20 | 104 | #define BOOK3S_INTERRUPT_ALTIVEC 0xf20 |
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index f92b0b54e921..44e90516519b 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h | |||
| @@ -174,6 +174,10 @@ struct machdep_calls { | |||
| 174 | /* Exception handlers */ | 174 | /* Exception handlers */ |
| 175 | int (*system_reset_exception)(struct pt_regs *regs); | 175 | int (*system_reset_exception)(struct pt_regs *regs); |
| 176 | int (*machine_check_exception)(struct pt_regs *regs); | 176 | int (*machine_check_exception)(struct pt_regs *regs); |
| 177 | int (*handle_hmi_exception)(struct pt_regs *regs); | ||
| 178 | |||
| 179 | /* Early exception handlers called in realmode */ | ||
| 180 | int (*hmi_exception_early)(struct pt_regs *regs); | ||
| 177 | 181 | ||
| 178 | /* Called during machine check exception to retrive fixup address. */ | 182 | /* Called during machine check exception to retrive fixup address. */ |
| 179 | bool (*mce_check_early_recovery)(struct pt_regs *regs); | 183 | bool (*mce_check_early_recovery)(struct pt_regs *regs); |
| @@ -366,6 +370,7 @@ static inline void log_error(char *buf, unsigned int err_type, int fatal) | |||
| 366 | } \ | 370 | } \ |
| 367 | __define_initcall(__machine_initcall_##mach##_##fn, id); | 371 | __define_initcall(__machine_initcall_##mach##_##fn, id); |
| 368 | 372 | ||
| 373 | #define machine_early_initcall(mach, fn) __define_machine_initcall(mach, fn, early) | ||
| 369 | #define machine_core_initcall(mach, fn) __define_machine_initcall(mach, fn, 1) | 374 | #define machine_core_initcall(mach, fn) __define_machine_initcall(mach, fn, 1) |
| 370 | #define machine_core_initcall_sync(mach, fn) __define_machine_initcall(mach, fn, 1s) | 375 | #define machine_core_initcall_sync(mach, fn) __define_machine_initcall(mach, fn, 1s) |
| 371 | #define machine_postcore_initcall(mach, fn) __define_machine_initcall(mach, fn, 2) | 376 | #define machine_postcore_initcall(mach, fn) __define_machine_initcall(mach, fn, 2) |
diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h index c2b4dcf23d03..d76514487d6f 100644 --- a/arch/powerpc/include/asm/mmu-hash64.h +++ b/arch/powerpc/include/asm/mmu-hash64.h | |||
| @@ -25,26 +25,6 @@ | |||
| 25 | #include <asm/processor.h> | 25 | #include <asm/processor.h> |
| 26 | 26 | ||
| 27 | /* | 27 | /* |
| 28 | * Segment table | ||
| 29 | */ | ||
| 30 | |||
| 31 | #define STE_ESID_V 0x80 | ||
| 32 | #define STE_ESID_KS 0x20 | ||
| 33 | #define STE_ESID_KP 0x10 | ||
| 34 | #define STE_ESID_N 0x08 | ||
| 35 | |||
| 36 | #define STE_VSID_SHIFT 12 | ||
| 37 | |||
| 38 | /* Location of cpu0's segment table */ | ||
| 39 | #define STAB0_PAGE 0x8 | ||
| 40 | #define STAB0_OFFSET (STAB0_PAGE << 12) | ||
| 41 | #define STAB0_PHYS_ADDR (STAB0_OFFSET + PHYSICAL_START) | ||
| 42 | |||
| 43 | #ifndef __ASSEMBLY__ | ||
| 44 | extern char initial_stab[]; | ||
| 45 | #endif /* ! __ASSEMBLY */ | ||
| 46 | |||
| 47 | /* | ||
| 48 | * SLB | 28 | * SLB |
| 49 | */ | 29 | */ |
| 50 | 30 | ||
| @@ -370,10 +350,8 @@ extern void hpte_init_lpar(void); | |||
| 370 | extern void hpte_init_beat(void); | 350 | extern void hpte_init_beat(void); |
| 371 | extern void hpte_init_beat_v3(void); | 351 | extern void hpte_init_beat_v3(void); |
| 372 | 352 | ||
| 373 | extern void stabs_alloc(void); | ||
| 374 | extern void slb_initialize(void); | 353 | extern void slb_initialize(void); |
| 375 | extern void slb_flush_and_rebolt(void); | 354 | extern void slb_flush_and_rebolt(void); |
| 376 | extern void stab_initialize(unsigned long stab); | ||
| 377 | 355 | ||
| 378 | extern void slb_vmalloc_update(void); | 356 | extern void slb_vmalloc_update(void); |
| 379 | extern void slb_set_size(u16 size); | 357 | extern void slb_set_size(u16 size); |
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h index e61f24ed4e65..3d5abfe6ba67 100644 --- a/arch/powerpc/include/asm/mmu.h +++ b/arch/powerpc/include/asm/mmu.h | |||
| @@ -64,9 +64,9 @@ | |||
| 64 | */ | 64 | */ |
| 65 | #define MMU_FTR_USE_PAIRED_MAS ASM_CONST(0x01000000) | 65 | #define MMU_FTR_USE_PAIRED_MAS ASM_CONST(0x01000000) |
| 66 | 66 | ||
| 67 | /* MMU is SLB-based | 67 | /* Doesn't support the B bit (1T segment) in SLBIE |
| 68 | */ | 68 | */ |
| 69 | #define MMU_FTR_SLB ASM_CONST(0x02000000) | 69 | #define MMU_FTR_NO_SLBIE_B ASM_CONST(0x02000000) |
| 70 | 70 | ||
| 71 | /* Support 16M large pages | 71 | /* Support 16M large pages |
| 72 | */ | 72 | */ |
| @@ -88,10 +88,6 @@ | |||
| 88 | */ | 88 | */ |
| 89 | #define MMU_FTR_1T_SEGMENT ASM_CONST(0x40000000) | 89 | #define MMU_FTR_1T_SEGMENT ASM_CONST(0x40000000) |
| 90 | 90 | ||
| 91 | /* Doesn't support the B bit (1T segment) in SLBIE | ||
| 92 | */ | ||
| 93 | #define MMU_FTR_NO_SLBIE_B ASM_CONST(0x80000000) | ||
| 94 | |||
| 95 | /* MMU feature bit sets for various CPUs */ | 91 | /* MMU feature bit sets for various CPUs */ |
| 96 | #define MMU_FTRS_DEFAULT_HPTE_ARCH_V2 \ | 92 | #define MMU_FTRS_DEFAULT_HPTE_ARCH_V2 \ |
| 97 | MMU_FTR_HPTE_TABLE | MMU_FTR_PPCAS_ARCH_V2 | 93 | MMU_FTR_HPTE_TABLE | MMU_FTR_PPCAS_ARCH_V2 |
diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h index b467530e2485..73382eba02dc 100644 --- a/arch/powerpc/include/asm/mmu_context.h +++ b/arch/powerpc/include/asm/mmu_context.h | |||
| @@ -18,7 +18,6 @@ extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm); | |||
| 18 | extern void destroy_context(struct mm_struct *mm); | 18 | extern void destroy_context(struct mm_struct *mm); |
| 19 | 19 | ||
| 20 | extern void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next); | 20 | extern void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next); |
| 21 | extern void switch_stab(struct task_struct *tsk, struct mm_struct *mm); | ||
| 22 | extern void switch_slb(struct task_struct *tsk, struct mm_struct *mm); | 21 | extern void switch_slb(struct task_struct *tsk, struct mm_struct *mm); |
| 23 | extern void set_context(unsigned long id, pgd_t *pgd); | 22 | extern void set_context(unsigned long id, pgd_t *pgd); |
| 24 | 23 | ||
| @@ -77,10 +76,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, | |||
| 77 | * sub architectures. | 76 | * sub architectures. |
| 78 | */ | 77 | */ |
| 79 | #ifdef CONFIG_PPC_STD_MMU_64 | 78 | #ifdef CONFIG_PPC_STD_MMU_64 |
| 80 | if (mmu_has_feature(MMU_FTR_SLB)) | 79 | switch_slb(tsk, next); |
| 81 | switch_slb(tsk, next); | ||
| 82 | else | ||
| 83 | switch_stab(tsk, next); | ||
| 84 | #else | 80 | #else |
| 85 | /* Out of line for now */ | 81 | /* Out of line for now */ |
| 86 | switch_mmu_context(prev, next); | 82 | switch_mmu_context(prev, next); |
diff --git a/arch/powerpc/include/asm/mpc85xx.h b/arch/powerpc/include/asm/mpc85xx.h index 736d4acc05a8..3bef74a9914b 100644 --- a/arch/powerpc/include/asm/mpc85xx.h +++ b/arch/powerpc/include/asm/mpc85xx.h | |||
| @@ -77,6 +77,8 @@ | |||
| 77 | #define SVR_T1020 0x852100 | 77 | #define SVR_T1020 0x852100 |
| 78 | #define SVR_T1021 0x852101 | 78 | #define SVR_T1021 0x852101 |
| 79 | #define SVR_T1022 0x852102 | 79 | #define SVR_T1022 0x852102 |
| 80 | #define SVR_T2080 0x853000 | ||
| 81 | #define SVR_T2081 0x853100 | ||
| 80 | 82 | ||
| 81 | #define SVR_8610 0x80A000 | 83 | #define SVR_8610 0x80A000 |
| 82 | #define SVR_8641 0x809000 | 84 | #define SVR_8641 0x809000 |
diff --git a/arch/powerpc/include/asm/mpc8xx.h b/arch/powerpc/include/asm/mpc8xx.h deleted file mode 100644 index 98f3c4f17328..000000000000 --- a/arch/powerpc/include/asm/mpc8xx.h +++ /dev/null | |||
| @@ -1,12 +0,0 @@ | |||
| 1 | /* This is the single file included by all MPC8xx build options. | ||
| 2 | * Since there are many different boards and no standard configuration, | ||
| 3 | * we have a unique include file for each. Rather than change every | ||
| 4 | * file that has to include MPC8xx configuration, they all include | ||
| 5 | * this one and the configuration switching is done here. | ||
| 6 | */ | ||
| 7 | #ifndef __CONFIG_8xx_DEFS | ||
| 8 | #define __CONFIG_8xx_DEFS | ||
| 9 | |||
| 10 | extern struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops; | ||
| 11 | |||
| 12 | #endif /* __CONFIG_8xx_DEFS */ | ||
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index 0da1dbd42e02..b2f8ce1fd0d7 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h | |||
| @@ -147,6 +147,8 @@ struct opal_sg_list { | |||
| 147 | #define OPAL_SET_PARAM 90 | 147 | #define OPAL_SET_PARAM 90 |
| 148 | #define OPAL_DUMP_RESEND 91 | 148 | #define OPAL_DUMP_RESEND 91 |
| 149 | #define OPAL_DUMP_INFO2 94 | 149 | #define OPAL_DUMP_INFO2 94 |
| 150 | #define OPAL_PCI_EEH_FREEZE_SET 97 | ||
| 151 | #define OPAL_HANDLE_HMI 98 | ||
| 150 | 152 | ||
| 151 | #ifndef __ASSEMBLY__ | 153 | #ifndef __ASSEMBLY__ |
| 152 | 154 | ||
| @@ -170,7 +172,11 @@ enum OpalFreezeState { | |||
| 170 | enum OpalEehFreezeActionToken { | 172 | enum OpalEehFreezeActionToken { |
| 171 | OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO = 1, | 173 | OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO = 1, |
| 172 | OPAL_EEH_ACTION_CLEAR_FREEZE_DMA = 2, | 174 | OPAL_EEH_ACTION_CLEAR_FREEZE_DMA = 2, |
| 173 | OPAL_EEH_ACTION_CLEAR_FREEZE_ALL = 3 | 175 | OPAL_EEH_ACTION_CLEAR_FREEZE_ALL = 3, |
| 176 | |||
| 177 | OPAL_EEH_ACTION_SET_FREEZE_MMIO = 1, | ||
| 178 | OPAL_EEH_ACTION_SET_FREEZE_DMA = 2, | ||
| 179 | OPAL_EEH_ACTION_SET_FREEZE_ALL = 3 | ||
| 174 | }; | 180 | }; |
| 175 | 181 | ||
| 176 | enum OpalPciStatusToken { | 182 | enum OpalPciStatusToken { |
| @@ -240,6 +246,7 @@ enum OpalMessageType { | |||
| 240 | OPAL_MSG_MEM_ERR, | 246 | OPAL_MSG_MEM_ERR, |
| 241 | OPAL_MSG_EPOW, | 247 | OPAL_MSG_EPOW, |
| 242 | OPAL_MSG_SHUTDOWN, | 248 | OPAL_MSG_SHUTDOWN, |
| 249 | OPAL_MSG_HMI_EVT, | ||
| 243 | OPAL_MSG_TYPE_MAX, | 250 | OPAL_MSG_TYPE_MAX, |
| 244 | }; | 251 | }; |
| 245 | 252 | ||
| @@ -340,6 +347,12 @@ enum OpalMveEnableAction { | |||
| 340 | OPAL_ENABLE_MVE = 1 | 347 | OPAL_ENABLE_MVE = 1 |
| 341 | }; | 348 | }; |
| 342 | 349 | ||
| 350 | enum OpalM64EnableAction { | ||
| 351 | OPAL_DISABLE_M64 = 0, | ||
| 352 | OPAL_ENABLE_M64_SPLIT = 1, | ||
| 353 | OPAL_ENABLE_M64_NON_SPLIT = 2 | ||
| 354 | }; | ||
| 355 | |||
| 343 | enum OpalPciResetScope { | 356 | enum OpalPciResetScope { |
| 344 | OPAL_PHB_COMPLETE = 1, OPAL_PCI_LINK = 2, OPAL_PHB_ERROR = 3, | 357 | OPAL_PHB_COMPLETE = 1, OPAL_PCI_LINK = 2, OPAL_PHB_ERROR = 3, |
| 345 | OPAL_PCI_HOT_RESET = 4, OPAL_PCI_FUNDAMENTAL_RESET = 5, | 358 | OPAL_PCI_HOT_RESET = 4, OPAL_PCI_FUNDAMENTAL_RESET = 5, |
| @@ -502,6 +515,50 @@ struct OpalMemoryErrorData { | |||
| 502 | } u; | 515 | } u; |
| 503 | }; | 516 | }; |
| 504 | 517 | ||
| 518 | /* HMI interrupt event */ | ||
| 519 | enum OpalHMI_Version { | ||
| 520 | OpalHMIEvt_V1 = 1, | ||
| 521 | }; | ||
| 522 | |||
| 523 | enum OpalHMI_Severity { | ||
| 524 | OpalHMI_SEV_NO_ERROR = 0, | ||
| 525 | OpalHMI_SEV_WARNING = 1, | ||
| 526 | OpalHMI_SEV_ERROR_SYNC = 2, | ||
| 527 | OpalHMI_SEV_FATAL = 3, | ||
| 528 | }; | ||
| 529 | |||
| 530 | enum OpalHMI_Disposition { | ||
| 531 | OpalHMI_DISPOSITION_RECOVERED = 0, | ||
| 532 | OpalHMI_DISPOSITION_NOT_RECOVERED = 1, | ||
| 533 | }; | ||
| 534 | |||
| 535 | enum OpalHMI_ErrType { | ||
| 536 | OpalHMI_ERROR_MALFUNC_ALERT = 0, | ||
| 537 | OpalHMI_ERROR_PROC_RECOV_DONE, | ||
| 538 | OpalHMI_ERROR_PROC_RECOV_DONE_AGAIN, | ||
| 539 | OpalHMI_ERROR_PROC_RECOV_MASKED, | ||
| 540 | OpalHMI_ERROR_TFAC, | ||
| 541 | OpalHMI_ERROR_TFMR_PARITY, | ||
| 542 | OpalHMI_ERROR_HA_OVERFLOW_WARN, | ||
| 543 | OpalHMI_ERROR_XSCOM_FAIL, | ||
| 544 | OpalHMI_ERROR_XSCOM_DONE, | ||
| 545 | OpalHMI_ERROR_SCOM_FIR, | ||
| 546 | OpalHMI_ERROR_DEBUG_TRIG_FIR, | ||
| 547 | OpalHMI_ERROR_HYP_RESOURCE, | ||
| 548 | }; | ||
| 549 | |||
| 550 | struct OpalHMIEvent { | ||
| 551 | uint8_t version; /* 0x00 */ | ||
| 552 | uint8_t severity; /* 0x01 */ | ||
| 553 | uint8_t type; /* 0x02 */ | ||
| 554 | uint8_t disposition; /* 0x03 */ | ||
| 555 | uint8_t reserved_1[4]; /* 0x04 */ | ||
| 556 | |||
| 557 | __be64 hmer; | ||
| 558 | /* TFMR register. Valid only for TFAC and TFMR_PARITY error type. */ | ||
| 559 | __be64 tfmr; | ||
| 560 | }; | ||
| 561 | |||
| 505 | enum { | 562 | enum { |
| 506 | OPAL_P7IOC_DIAG_TYPE_NONE = 0, | 563 | OPAL_P7IOC_DIAG_TYPE_NONE = 0, |
| 507 | OPAL_P7IOC_DIAG_TYPE_RGC = 1, | 564 | OPAL_P7IOC_DIAG_TYPE_RGC = 1, |
| @@ -513,40 +570,40 @@ enum { | |||
| 513 | }; | 570 | }; |
| 514 | 571 | ||
| 515 | struct OpalIoP7IOCErrorData { | 572 | struct OpalIoP7IOCErrorData { |
| 516 | uint16_t type; | 573 | __be16 type; |
| 517 | 574 | ||
| 518 | /* GEM */ | 575 | /* GEM */ |
| 519 | uint64_t gemXfir; | 576 | __be64 gemXfir; |
| 520 | uint64_t gemRfir; | 577 | __be64 gemRfir; |
| 521 | uint64_t gemRirqfir; | 578 | __be64 gemRirqfir; |
| 522 | uint64_t gemMask; | 579 | __be64 gemMask; |
| 523 | uint64_t gemRwof; | 580 | __be64 gemRwof; |
| 524 | 581 | ||
| 525 | /* LEM */ | 582 | /* LEM */ |
| 526 | uint64_t lemFir; | 583 | __be64 lemFir; |
| 527 | uint64_t lemErrMask; | 584 | __be64 lemErrMask; |
| 528 | uint64_t lemAction0; | 585 | __be64 lemAction0; |
| 529 | uint64_t lemAction1; | 586 | __be64 lemAction1; |
| 530 | uint64_t lemWof; | 587 | __be64 lemWof; |
| 531 | 588 | ||
| 532 | union { | 589 | union { |
| 533 | struct OpalIoP7IOCRgcErrorData { | 590 | struct OpalIoP7IOCRgcErrorData { |
| 534 | uint64_t rgcStatus; /* 3E1C10 */ | 591 | __be64 rgcStatus; /* 3E1C10 */ |
| 535 | uint64_t rgcLdcp; /* 3E1C18 */ | 592 | __be64 rgcLdcp; /* 3E1C18 */ |
| 536 | }rgc; | 593 | }rgc; |
| 537 | struct OpalIoP7IOCBiErrorData { | 594 | struct OpalIoP7IOCBiErrorData { |
| 538 | uint64_t biLdcp0; /* 3C0100, 3C0118 */ | 595 | __be64 biLdcp0; /* 3C0100, 3C0118 */ |
| 539 | uint64_t biLdcp1; /* 3C0108, 3C0120 */ | 596 | __be64 biLdcp1; /* 3C0108, 3C0120 */ |
| 540 | uint64_t biLdcp2; /* 3C0110, 3C0128 */ | 597 | __be64 biLdcp2; /* 3C0110, 3C0128 */ |
| 541 | uint64_t biFenceStatus; /* 3C0130, 3C0130 */ | 598 | __be64 biFenceStatus; /* 3C0130, 3C0130 */ |
| 542 | 599 | ||
| 543 | uint8_t biDownbound; /* BI Downbound or Upbound */ | 600 | u8 biDownbound; /* BI Downbound or Upbound */ |
| 544 | }bi; | 601 | }bi; |
| 545 | struct OpalIoP7IOCCiErrorData { | 602 | struct OpalIoP7IOCCiErrorData { |
| 546 | uint64_t ciPortStatus; /* 3Dn008 */ | 603 | __be64 ciPortStatus; /* 3Dn008 */ |
| 547 | uint64_t ciPortLdcp; /* 3Dn010 */ | 604 | __be64 ciPortLdcp; /* 3Dn010 */ |
| 548 | 605 | ||
| 549 | uint8_t ciPort; /* Index of CI port: 0/1 */ | 606 | u8 ciPort; /* Index of CI port: 0/1 */ |
| 550 | }ci; | 607 | }ci; |
| 551 | }; | 608 | }; |
| 552 | }; | 609 | }; |
| @@ -578,60 +635,60 @@ struct OpalIoPhbErrorCommon { | |||
| 578 | struct OpalIoP7IOCPhbErrorData { | 635 | struct OpalIoP7IOCPhbErrorData { |
| 579 | struct OpalIoPhbErrorCommon common; | 636 | struct OpalIoPhbErrorCommon common; |
| 580 | 637 | ||
| 581 | uint32_t brdgCtl; | 638 | __be32 brdgCtl; |
| 582 | 639 | ||
| 583 | // P7IOC utl regs | 640 | // P7IOC utl regs |
| 584 | uint32_t portStatusReg; | 641 | __be32 portStatusReg; |
| 585 | uint32_t rootCmplxStatus; | 642 | __be32 rootCmplxStatus; |
| 586 | uint32_t busAgentStatus; | 643 | __be32 busAgentStatus; |
| 587 | 644 | ||
| 588 | // P7IOC cfg regs | 645 | // P7IOC cfg regs |
| 589 | uint32_t deviceStatus; | 646 | __be32 deviceStatus; |
| 590 | uint32_t slotStatus; | 647 | __be32 slotStatus; |
| 591 | uint32_t linkStatus; | 648 | __be32 linkStatus; |
| 592 | uint32_t devCmdStatus; | 649 | __be32 devCmdStatus; |
| 593 | uint32_t devSecStatus; | 650 | __be32 devSecStatus; |
| 594 | 651 | ||
| 595 | // cfg AER regs | 652 | // cfg AER regs |
| 596 | uint32_t rootErrorStatus; | 653 | __be32 rootErrorStatus; |
| 597 | uint32_t uncorrErrorStatus; | 654 | __be32 uncorrErrorStatus; |
| 598 | uint32_t corrErrorStatus; | 655 | __be32 corrErrorStatus; |
| 599 | uint32_t tlpHdr1; | 656 | __be32 tlpHdr1; |
| 600 | uint32_t tlpHdr2; | 657 | __be32 tlpHdr2; |
| 601 | uint32_t tlpHdr3; | 658 | __be32 tlpHdr3; |
| 602 | uint32_t tlpHdr4; | 659 | __be32 tlpHdr4; |
| 603 | uint32_t sourceId; | 660 | __be32 sourceId; |
| 604 | 661 | ||
| 605 | uint32_t rsv3; | 662 | __be32 rsv3; |
| 606 | 663 | ||
| 607 | // Record data about the call to allocate a buffer. | 664 | // Record data about the call to allocate a buffer. |
| 608 | uint64_t errorClass; | 665 | __be64 errorClass; |
| 609 | uint64_t correlator; | 666 | __be64 correlator; |
| 610 | 667 | ||
| 611 | //P7IOC MMIO Error Regs | 668 | //P7IOC MMIO Error Regs |
| 612 | uint64_t p7iocPlssr; // n120 | 669 | __be64 p7iocPlssr; // n120 |
| 613 | uint64_t p7iocCsr; // n110 | 670 | __be64 p7iocCsr; // n110 |
| 614 | uint64_t lemFir; // nC00 | 671 | __be64 lemFir; // nC00 |
| 615 | uint64_t lemErrorMask; // nC18 | 672 | __be64 lemErrorMask; // nC18 |
| 616 | uint64_t lemWOF; // nC40 | 673 | __be64 lemWOF; // nC40 |
| 617 | uint64_t phbErrorStatus; // nC80 | 674 | __be64 phbErrorStatus; // nC80 |
| 618 | uint64_t phbFirstErrorStatus; // nC88 | 675 | __be64 phbFirstErrorStatus; // nC88 |
| 619 | uint64_t phbErrorLog0; // nCC0 | 676 | __be64 phbErrorLog0; // nCC0 |
| 620 | uint64_t phbErrorLog1; // nCC8 | 677 | __be64 phbErrorLog1; // nCC8 |
| 621 | uint64_t mmioErrorStatus; // nD00 | 678 | __be64 mmioErrorStatus; // nD00 |
| 622 | uint64_t mmioFirstErrorStatus; // nD08 | 679 | __be64 mmioFirstErrorStatus; // nD08 |
| 623 | uint64_t mmioErrorLog0; // nD40 | 680 | __be64 mmioErrorLog0; // nD40 |
| 624 | uint64_t mmioErrorLog1; // nD48 | 681 | __be64 mmioErrorLog1; // nD48 |
| 625 | uint64_t dma0ErrorStatus; // nD80 | 682 | __be64 dma0ErrorStatus; // nD80 |
| 626 | uint64_t dma0FirstErrorStatus; // nD88 | 683 | __be64 dma0FirstErrorStatus; // nD88 |
| 627 | uint64_t dma0ErrorLog0; // nDC0 | 684 | __be64 dma0ErrorLog0; // nDC0 |
| 628 | uint64_t dma0ErrorLog1; // nDC8 | 685 | __be64 dma0ErrorLog1; // nDC8 |
| 629 | uint64_t dma1ErrorStatus; // nE00 | 686 | __be64 dma1ErrorStatus; // nE00 |
| 630 | uint64_t dma1FirstErrorStatus; // nE08 | 687 | __be64 dma1FirstErrorStatus; // nE08 |
| 631 | uint64_t dma1ErrorLog0; // nE40 | 688 | __be64 dma1ErrorLog0; // nE40 |
| 632 | uint64_t dma1ErrorLog1; // nE48 | 689 | __be64 dma1ErrorLog1; // nE48 |
| 633 | uint64_t pestA[OPAL_P7IOC_NUM_PEST_REGS]; | 690 | __be64 pestA[OPAL_P7IOC_NUM_PEST_REGS]; |
| 634 | uint64_t pestB[OPAL_P7IOC_NUM_PEST_REGS]; | 691 | __be64 pestB[OPAL_P7IOC_NUM_PEST_REGS]; |
| 635 | }; | 692 | }; |
| 636 | 693 | ||
| 637 | struct OpalIoPhb3ErrorData { | 694 | struct OpalIoPhb3ErrorData { |
| @@ -758,6 +815,8 @@ int64_t opal_pci_eeh_freeze_status(uint64_t phb_id, uint64_t pe_number, | |||
| 758 | __be64 *phb_status); | 815 | __be64 *phb_status); |
| 759 | int64_t opal_pci_eeh_freeze_clear(uint64_t phb_id, uint64_t pe_number, | 816 | int64_t opal_pci_eeh_freeze_clear(uint64_t phb_id, uint64_t pe_number, |
| 760 | uint64_t eeh_action_token); | 817 | uint64_t eeh_action_token); |
| 818 | int64_t opal_pci_eeh_freeze_set(uint64_t phb_id, uint64_t pe_number, | ||
| 819 | uint64_t eeh_action_token); | ||
| 761 | int64_t opal_pci_shpc(uint64_t phb_id, uint64_t shpc_action, uint8_t *state); | 820 | int64_t opal_pci_shpc(uint64_t phb_id, uint64_t shpc_action, uint8_t *state); |
| 762 | 821 | ||
| 763 | 822 | ||
| @@ -768,7 +827,7 @@ int64_t opal_pci_set_phb_mem_window(uint64_t phb_id, uint16_t window_type, | |||
| 768 | uint16_t window_num, | 827 | uint16_t window_num, |
| 769 | uint64_t starting_real_address, | 828 | uint64_t starting_real_address, |
| 770 | uint64_t starting_pci_address, | 829 | uint64_t starting_pci_address, |
| 771 | uint16_t segment_size); | 830 | uint64_t size); |
| 772 | int64_t opal_pci_map_pe_mmio_window(uint64_t phb_id, uint16_t pe_number, | 831 | int64_t opal_pci_map_pe_mmio_window(uint64_t phb_id, uint16_t pe_number, |
| 773 | uint16_t window_type, uint16_t window_num, | 832 | uint16_t window_type, uint16_t window_num, |
| 774 | uint16_t segment_num); | 833 | uint16_t segment_num); |
| @@ -860,6 +919,7 @@ int64_t opal_get_param(uint64_t token, uint32_t param_id, uint64_t buffer, | |||
| 860 | int64_t opal_set_param(uint64_t token, uint32_t param_id, uint64_t buffer, | 919 | int64_t opal_set_param(uint64_t token, uint32_t param_id, uint64_t buffer, |
| 861 | uint64_t length); | 920 | uint64_t length); |
| 862 | int64_t opal_sensor_read(uint32_t sensor_hndl, int token, __be32 *sensor_data); | 921 | int64_t opal_sensor_read(uint32_t sensor_hndl, int token, __be32 *sensor_data); |
| 922 | int64_t opal_handle_hmi(void); | ||
| 863 | 923 | ||
| 864 | /* Internal functions */ | 924 | /* Internal functions */ |
| 865 | extern int early_init_dt_scan_opal(unsigned long node, const char *uname, | 925 | extern int early_init_dt_scan_opal(unsigned long node, const char *uname, |
| @@ -902,6 +962,8 @@ extern void opal_msglog_init(void); | |||
| 902 | 962 | ||
| 903 | extern int opal_machine_check(struct pt_regs *regs); | 963 | extern int opal_machine_check(struct pt_regs *regs); |
| 904 | extern bool opal_mce_check_early_recovery(struct pt_regs *regs); | 964 | extern bool opal_mce_check_early_recovery(struct pt_regs *regs); |
| 965 | extern int opal_hmi_exception_early(struct pt_regs *regs); | ||
| 966 | extern int opal_handle_hmi_exception(struct pt_regs *regs); | ||
| 905 | 967 | ||
| 906 | extern void opal_shutdown(void); | 968 | extern void opal_shutdown(void); |
| 907 | extern int opal_resync_timebase(void); | 969 | extern int opal_resync_timebase(void); |
diff --git a/arch/powerpc/include/asm/oprofile_impl.h b/arch/powerpc/include/asm/oprofile_impl.h index d697b08994c9..61fe5d6f18e1 100644 --- a/arch/powerpc/include/asm/oprofile_impl.h +++ b/arch/powerpc/include/asm/oprofile_impl.h | |||
| @@ -61,7 +61,6 @@ struct op_powerpc_model { | |||
| 61 | }; | 61 | }; |
| 62 | 62 | ||
| 63 | extern struct op_powerpc_model op_model_fsl_emb; | 63 | extern struct op_powerpc_model op_model_fsl_emb; |
| 64 | extern struct op_powerpc_model op_model_rs64; | ||
| 65 | extern struct op_powerpc_model op_model_power4; | 64 | extern struct op_powerpc_model op_model_power4; |
| 66 | extern struct op_powerpc_model op_model_7450; | 65 | extern struct op_powerpc_model op_model_7450; |
| 67 | extern struct op_powerpc_model op_model_cell; | 66 | extern struct op_powerpc_model op_model_cell; |
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index bb0bd25f20d0..a5139ea6910b 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h | |||
| @@ -78,10 +78,6 @@ struct paca_struct { | |||
| 78 | u64 kernel_toc; /* Kernel TOC address */ | 78 | u64 kernel_toc; /* Kernel TOC address */ |
| 79 | u64 kernelbase; /* Base address of kernel */ | 79 | u64 kernelbase; /* Base address of kernel */ |
| 80 | u64 kernel_msr; /* MSR while running in kernel */ | 80 | u64 kernel_msr; /* MSR while running in kernel */ |
| 81 | #ifdef CONFIG_PPC_STD_MMU_64 | ||
| 82 | u64 stab_real; /* Absolute address of segment table */ | ||
| 83 | u64 stab_addr; /* Virtual address of segment table */ | ||
| 84 | #endif /* CONFIG_PPC_STD_MMU_64 */ | ||
| 85 | void *emergency_sp; /* pointer to emergency stack */ | 81 | void *emergency_sp; /* pointer to emergency stack */ |
| 86 | u64 data_offset; /* per cpu data offset */ | 82 | u64 data_offset; /* per cpu data offset */ |
| 87 | s16 hw_cpu_id; /* Physical processor number */ | 83 | s16 hw_cpu_id; /* Physical processor number */ |
| @@ -171,6 +167,7 @@ struct paca_struct { | |||
| 171 | * and already using emergency stack. | 167 | * and already using emergency stack. |
| 172 | */ | 168 | */ |
| 173 | u16 in_mce; | 169 | u16 in_mce; |
| 170 | u8 hmi_event_available; /* HMI event is available */ | ||
| 174 | #endif | 171 | #endif |
| 175 | 172 | ||
| 176 | /* Stuff for accurate time accounting */ | 173 | /* Stuff for accurate time accounting */ |
diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h index b3e936027b26..814622146d5a 100644 --- a/arch/powerpc/include/asm/perf_event_server.h +++ b/arch/powerpc/include/asm/perf_event_server.h | |||
| @@ -19,6 +19,8 @@ | |||
| 19 | #define MAX_EVENT_ALTERNATIVES 8 | 19 | #define MAX_EVENT_ALTERNATIVES 8 |
| 20 | #define MAX_LIMITED_HWCOUNTERS 2 | 20 | #define MAX_LIMITED_HWCOUNTERS 2 |
| 21 | 21 | ||
| 22 | struct perf_event; | ||
| 23 | |||
| 22 | /* | 24 | /* |
| 23 | * This struct provides the constants and functions needed to | 25 | * This struct provides the constants and functions needed to |
| 24 | * describe the PMU on a particular POWER-family CPU. | 26 | * describe the PMU on a particular POWER-family CPU. |
| @@ -30,7 +32,8 @@ struct power_pmu { | |||
| 30 | unsigned long add_fields; | 32 | unsigned long add_fields; |
| 31 | unsigned long test_adder; | 33 | unsigned long test_adder; |
| 32 | int (*compute_mmcr)(u64 events[], int n_ev, | 34 | int (*compute_mmcr)(u64 events[], int n_ev, |
| 33 | unsigned int hwc[], unsigned long mmcr[]); | 35 | unsigned int hwc[], unsigned long mmcr[], |
| 36 | struct perf_event *pevents[]); | ||
| 34 | int (*get_constraint)(u64 event_id, unsigned long *mskp, | 37 | int (*get_constraint)(u64 event_id, unsigned long *mskp, |
| 35 | unsigned long *valp); | 38 | unsigned long *valp); |
| 36 | int (*get_alternatives)(u64 event_id, unsigned int flags, | 39 | int (*get_alternatives)(u64 event_id, unsigned int flags, |
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index 3132bb9365f3..e316dad6ba76 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h | |||
| @@ -150,8 +150,10 @@ | |||
| 150 | #define PPC_INST_MCRXR_MASK 0xfc0007fe | 150 | #define PPC_INST_MCRXR_MASK 0xfc0007fe |
| 151 | #define PPC_INST_MFSPR_PVR 0x7c1f42a6 | 151 | #define PPC_INST_MFSPR_PVR 0x7c1f42a6 |
| 152 | #define PPC_INST_MFSPR_PVR_MASK 0xfc1fffff | 152 | #define PPC_INST_MFSPR_PVR_MASK 0xfc1fffff |
| 153 | #define PPC_INST_MFTMR 0x7c0002dc | ||
| 153 | #define PPC_INST_MSGSND 0x7c00019c | 154 | #define PPC_INST_MSGSND 0x7c00019c |
| 154 | #define PPC_INST_MSGSNDP 0x7c00011c | 155 | #define PPC_INST_MSGSNDP 0x7c00011c |
| 156 | #define PPC_INST_MTTMR 0x7c0003dc | ||
| 155 | #define PPC_INST_NOP 0x60000000 | 157 | #define PPC_INST_NOP 0x60000000 |
| 156 | #define PPC_INST_POPCNTB 0x7c0000f4 | 158 | #define PPC_INST_POPCNTB 0x7c0000f4 |
| 157 | #define PPC_INST_POPCNTB_MASK 0xfc0007fe | 159 | #define PPC_INST_POPCNTB_MASK 0xfc0007fe |
| @@ -369,4 +371,11 @@ | |||
| 369 | #define TABORT(r) stringify_in_c(.long PPC_INST_TABORT \ | 371 | #define TABORT(r) stringify_in_c(.long PPC_INST_TABORT \ |
| 370 | | __PPC_RA(r)) | 372 | | __PPC_RA(r)) |
| 371 | 373 | ||
| 374 | /* book3e thread control instructions */ | ||
| 375 | #define TMRN(x) ((((x) & 0x1f) << 16) | (((x) & 0x3e0) << 6)) | ||
| 376 | #define MTTMR(tmr, r) stringify_in_c(.long PPC_INST_MTTMR | \ | ||
| 377 | TMRN(tmr) | ___PPC_RS(r)) | ||
| 378 | #define MFTMR(tmr, r) stringify_in_c(.long PPC_INST_MFTMR | \ | ||
| 379 | TMRN(tmr) | ___PPC_RT(r)) | ||
| 380 | |||
| 372 | #endif /* _ASM_POWERPC_PPC_OPCODE_H */ | 381 | #endif /* _ASM_POWERPC_PPC_OPCODE_H */ |
diff --git a/arch/powerpc/include/asm/pte-fsl-booke.h b/arch/powerpc/include/asm/pte-fsl-booke.h index 2c12be5f677a..e84dd7ed505e 100644 --- a/arch/powerpc/include/asm/pte-fsl-booke.h +++ b/arch/powerpc/include/asm/pte-fsl-booke.h | |||
| @@ -37,5 +37,7 @@ | |||
| 37 | #define _PMD_PRESENT_MASK (PAGE_MASK) | 37 | #define _PMD_PRESENT_MASK (PAGE_MASK) |
| 38 | #define _PMD_BAD (~PAGE_MASK) | 38 | #define _PMD_BAD (~PAGE_MASK) |
| 39 | 39 | ||
| 40 | #define PTE_WIMGE_SHIFT (6) | ||
| 41 | |||
| 40 | #endif /* __KERNEL__ */ | 42 | #endif /* __KERNEL__ */ |
| 41 | #endif /* _ASM_POWERPC_PTE_FSL_BOOKE_H */ | 43 | #endif /* _ASM_POWERPC_PTE_FSL_BOOKE_H */ |
diff --git a/arch/powerpc/include/asm/pte-hash64-64k.h b/arch/powerpc/include/asm/pte-hash64-64k.h index d836d945068d..b6d2d42f84b5 100644 --- a/arch/powerpc/include/asm/pte-hash64-64k.h +++ b/arch/powerpc/include/asm/pte-hash64-64k.h | |||
| @@ -75,7 +75,8 @@ | |||
| 75 | (((pte) & _PAGE_COMBO)? MMU_PAGE_4K: MMU_PAGE_64K) | 75 | (((pte) & _PAGE_COMBO)? MMU_PAGE_4K: MMU_PAGE_64K) |
| 76 | 76 | ||
| 77 | #define remap_4k_pfn(vma, addr, pfn, prot) \ | 77 | #define remap_4k_pfn(vma, addr, pfn, prot) \ |
| 78 | remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, \ | 78 | (WARN_ON(((pfn) >= (1UL << (64 - PTE_RPN_SHIFT)))) ? -EINVAL : \ |
| 79 | __pgprot(pgprot_val((prot)) | _PAGE_4K_PFN)) | 79 | remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, \ |
| 80 | __pgprot(pgprot_val((prot)) | _PAGE_4K_PFN))) | ||
| 80 | 81 | ||
| 81 | #endif /* __ASSEMBLY__ */ | 82 | #endif /* __ASSEMBLY__ */ |
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index bffd89d27301..f7b97b895708 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h | |||
| @@ -254,7 +254,7 @@ | |||
| 254 | #define DSISR_PROTFAULT 0x08000000 /* protection fault */ | 254 | #define DSISR_PROTFAULT 0x08000000 /* protection fault */ |
| 255 | #define DSISR_ISSTORE 0x02000000 /* access was a store */ | 255 | #define DSISR_ISSTORE 0x02000000 /* access was a store */ |
| 256 | #define DSISR_DABRMATCH 0x00400000 /* hit data breakpoint */ | 256 | #define DSISR_DABRMATCH 0x00400000 /* hit data breakpoint */ |
| 257 | #define DSISR_NOSEGMENT 0x00200000 /* STAB/SLB miss */ | 257 | #define DSISR_NOSEGMENT 0x00200000 /* SLB miss */ |
| 258 | #define DSISR_KEYFAULT 0x00200000 /* Key fault */ | 258 | #define DSISR_KEYFAULT 0x00200000 /* Key fault */ |
| 259 | #define SPRN_TBRL 0x10C /* Time Base Read Lower Register (user, R/O) */ | 259 | #define SPRN_TBRL 0x10C /* Time Base Read Lower Register (user, R/O) */ |
| 260 | #define SPRN_TBRU 0x10D /* Time Base Read Upper Register (user, R/O) */ | 260 | #define SPRN_TBRU 0x10D /* Time Base Read Upper Register (user, R/O) */ |
diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h index 464f1089b532..1d653308a33c 100644 --- a/arch/powerpc/include/asm/reg_booke.h +++ b/arch/powerpc/include/asm/reg_booke.h | |||
| @@ -15,16 +15,28 @@ | |||
| 15 | #ifndef __ASM_POWERPC_REG_BOOKE_H__ | 15 | #ifndef __ASM_POWERPC_REG_BOOKE_H__ |
| 16 | #define __ASM_POWERPC_REG_BOOKE_H__ | 16 | #define __ASM_POWERPC_REG_BOOKE_H__ |
| 17 | 17 | ||
| 18 | #include <asm/ppc-opcode.h> | ||
| 19 | |||
| 18 | /* Machine State Register (MSR) Fields */ | 20 | /* Machine State Register (MSR) Fields */ |
| 19 | #define MSR_GS (1<<28) /* Guest state */ | 21 | #define MSR_GS_LG 28 /* Guest state */ |
| 20 | #define MSR_UCLE (1<<26) /* User-mode cache lock enable */ | 22 | #define MSR_UCLE_LG 26 /* User-mode cache lock enable */ |
| 21 | #define MSR_SPE (1<<25) /* Enable SPE */ | 23 | #define MSR_SPE_LG 25 /* Enable SPE */ |
| 22 | #define MSR_DWE (1<<10) /* Debug Wait Enable */ | 24 | #define MSR_DWE_LG 10 /* Debug Wait Enable */ |
| 23 | #define MSR_UBLE (1<<10) /* BTB lock enable (e500) */ | 25 | #define MSR_UBLE_LG 10 /* BTB lock enable (e500) */ |
| 24 | #define MSR_IS MSR_IR /* Instruction Space */ | 26 | #define MSR_IS_LG MSR_IR_LG /* Instruction Space */ |
| 25 | #define MSR_DS MSR_DR /* Data Space */ | 27 | #define MSR_DS_LG MSR_DR_LG /* Data Space */ |
| 26 | #define MSR_PMM (1<<2) /* Performance monitor mark bit */ | 28 | #define MSR_PMM_LG 2 /* Performance monitor mark bit */ |
| 27 | #define MSR_CM (1<<31) /* Computation Mode (0=32-bit, 1=64-bit) */ | 29 | #define MSR_CM_LG 31 /* Computation Mode (0=32-bit, 1=64-bit) */ |
| 30 | |||
| 31 | #define MSR_GS __MASK(MSR_GS_LG) | ||
| 32 | #define MSR_UCLE __MASK(MSR_UCLE_LG) | ||
| 33 | #define MSR_SPE __MASK(MSR_SPE_LG) | ||
| 34 | #define MSR_DWE __MASK(MSR_DWE_LG) | ||
| 35 | #define MSR_UBLE __MASK(MSR_UBLE_LG) | ||
| 36 | #define MSR_IS __MASK(MSR_IS_LG) | ||
| 37 | #define MSR_DS __MASK(MSR_DS_LG) | ||
| 38 | #define MSR_PMM __MASK(MSR_PMM_LG) | ||
| 39 | #define MSR_CM __MASK(MSR_CM_LG) | ||
| 28 | 40 | ||
| 29 | #if defined(CONFIG_PPC_BOOK3E_64) | 41 | #if defined(CONFIG_PPC_BOOK3E_64) |
| 30 | #define MSR_64BIT MSR_CM | 42 | #define MSR_64BIT MSR_CM |
| @@ -260,7 +272,7 @@ | |||
| 260 | 272 | ||
| 261 | /* e500mc */ | 273 | /* e500mc */ |
| 262 | #define MCSR_DCPERR_MC 0x20000000UL /* D-Cache Parity Error */ | 274 | #define MCSR_DCPERR_MC 0x20000000UL /* D-Cache Parity Error */ |
| 263 | #define MCSR_L2MMU_MHIT 0x04000000UL /* Hit on multiple TLB entries */ | 275 | #define MCSR_L2MMU_MHIT 0x08000000UL /* Hit on multiple TLB entries */ |
| 264 | #define MCSR_NMI 0x00100000UL /* Non-Maskable Interrupt */ | 276 | #define MCSR_NMI 0x00100000UL /* Non-Maskable Interrupt */ |
| 265 | #define MCSR_MAV 0x00080000UL /* MCAR address valid */ | 277 | #define MCSR_MAV 0x00080000UL /* MCAR address valid */ |
| 266 | #define MCSR_MEA 0x00040000UL /* MCAR is effective address */ | 278 | #define MCSR_MEA 0x00040000UL /* MCAR is effective address */ |
| @@ -598,6 +610,13 @@ | |||
| 598 | /* Bit definitions for L1CSR2. */ | 610 | /* Bit definitions for L1CSR2. */ |
| 599 | #define L1CSR2_DCWS 0x40000000 /* Data Cache write shadow */ | 611 | #define L1CSR2_DCWS 0x40000000 /* Data Cache write shadow */ |
| 600 | 612 | ||
| 613 | /* Bit definitions for BUCSR. */ | ||
| 614 | #define BUCSR_STAC_EN 0x01000000 /* Segment Target Address Cache */ | ||
| 615 | #define BUCSR_LS_EN 0x00400000 /* Link Stack */ | ||
| 616 | #define BUCSR_BBFI 0x00000200 /* Branch Buffer flash invalidate */ | ||
| 617 | #define BUCSR_BPEN 0x00000001 /* Branch prediction enable */ | ||
| 618 | #define BUCSR_INIT (BUCSR_STAC_EN | BUCSR_LS_EN | BUCSR_BBFI | BUCSR_BPEN) | ||
| 619 | |||
| 601 | /* Bit definitions for L2CSR0. */ | 620 | /* Bit definitions for L2CSR0. */ |
| 602 | #define L2CSR0_L2E 0x80000000 /* L2 Cache Enable */ | 621 | #define L2CSR0_L2E 0x80000000 /* L2 Cache Enable */ |
| 603 | #define L2CSR0_L2PE 0x40000000 /* L2 Cache Parity/ECC Enable */ | 622 | #define L2CSR0_L2PE 0x40000000 /* L2 Cache Parity/ECC Enable */ |
| @@ -721,5 +740,23 @@ | |||
| 721 | #define MMUBE1_VBE4 0x00000002 | 740 | #define MMUBE1_VBE4 0x00000002 |
| 722 | #define MMUBE1_VBE5 0x00000001 | 741 | #define MMUBE1_VBE5 0x00000001 |
| 723 | 742 | ||
| 743 | #define TMRN_IMSR0 0x120 /* Initial MSR Register 0 (e6500) */ | ||
| 744 | #define TMRN_IMSR1 0x121 /* Initial MSR Register 1 (e6500) */ | ||
| 745 | #define TMRN_INIA0 0x140 /* Next Instruction Address Register 0 */ | ||
| 746 | #define TMRN_INIA1 0x141 /* Next Instruction Address Register 1 */ | ||
| 747 | #define SPRN_TENSR 0x1b5 /* Thread Enable Status Register */ | ||
| 748 | #define SPRN_TENS 0x1b6 /* Thread Enable Set Register */ | ||
| 749 | #define SPRN_TENC 0x1b7 /* Thread Enable Clear Register */ | ||
| 750 | |||
| 751 | #define TEN_THREAD(x) (1 << (x)) | ||
| 752 | |||
| 753 | #ifndef __ASSEMBLY__ | ||
| 754 | #define mftmr(rn) ({unsigned long rval; \ | ||
| 755 | asm volatile(MFTMR(rn, %0) : "=r" (rval)); rval;}) | ||
| 756 | #define mttmr(rn, v) asm volatile(MTTMR(rn, %0) : \ | ||
| 757 | : "r" ((unsigned long)(v)) \ | ||
| 758 | : "memory") | ||
| 759 | #endif /* !__ASSEMBLY__ */ | ||
| 760 | |||
| 724 | #endif /* __ASM_POWERPC_REG_BOOKE_H__ */ | 761 | #endif /* __ASM_POWERPC_REG_BOOKE_H__ */ |
| 725 | #endif /* __KERNEL__ */ | 762 | #endif /* __KERNEL__ */ |
diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h index babbeca6850f..542bc0f0673f 100644 --- a/arch/powerpc/include/asm/systbl.h +++ b/arch/powerpc/include/asm/systbl.h | |||
| @@ -77,10 +77,10 @@ SYSCALL_SPU(setreuid) | |||
| 77 | SYSCALL_SPU(setregid) | 77 | SYSCALL_SPU(setregid) |
| 78 | #define compat_sys_sigsuspend sys_sigsuspend | 78 | #define compat_sys_sigsuspend sys_sigsuspend |
| 79 | SYS32ONLY(sigsuspend) | 79 | SYS32ONLY(sigsuspend) |
| 80 | COMPAT_SYS(sigpending) | 80 | SYSX(sys_ni_syscall,compat_sys_sigpending,sys_sigpending) |
| 81 | SYSCALL_SPU(sethostname) | 81 | SYSCALL_SPU(sethostname) |
| 82 | COMPAT_SYS_SPU(setrlimit) | 82 | COMPAT_SYS_SPU(setrlimit) |
| 83 | COMPAT_SYS(old_getrlimit) | 83 | SYSX(sys_ni_syscall,compat_sys_old_getrlimit,sys_old_getrlimit) |
| 84 | COMPAT_SYS_SPU(getrusage) | 84 | COMPAT_SYS_SPU(getrusage) |
| 85 | COMPAT_SYS_SPU(gettimeofday) | 85 | COMPAT_SYS_SPU(gettimeofday) |
| 86 | COMPAT_SYS_SPU(settimeofday) | 86 | COMPAT_SYS_SPU(settimeofday) |
diff --git a/arch/powerpc/include/asm/trace.h b/arch/powerpc/include/asm/trace.h index 5712f06905a9..c15da6073cb8 100644 --- a/arch/powerpc/include/asm/trace.h +++ b/arch/powerpc/include/asm/trace.h | |||
| @@ -99,6 +99,51 @@ TRACE_EVENT_FN(hcall_exit, | |||
| 99 | ); | 99 | ); |
| 100 | #endif | 100 | #endif |
| 101 | 101 | ||
| 102 | #ifdef CONFIG_PPC_POWERNV | ||
| 103 | extern void opal_tracepoint_regfunc(void); | ||
| 104 | extern void opal_tracepoint_unregfunc(void); | ||
| 105 | |||
| 106 | TRACE_EVENT_FN(opal_entry, | ||
| 107 | |||
| 108 | TP_PROTO(unsigned long opcode, unsigned long *args), | ||
| 109 | |||
| 110 | TP_ARGS(opcode, args), | ||
| 111 | |||
| 112 | TP_STRUCT__entry( | ||
| 113 | __field(unsigned long, opcode) | ||
| 114 | ), | ||
| 115 | |||
| 116 | TP_fast_assign( | ||
| 117 | __entry->opcode = opcode; | ||
| 118 | ), | ||
| 119 | |||
| 120 | TP_printk("opcode=%lu", __entry->opcode), | ||
| 121 | |||
| 122 | opal_tracepoint_regfunc, opal_tracepoint_unregfunc | ||
| 123 | ); | ||
| 124 | |||
| 125 | TRACE_EVENT_FN(opal_exit, | ||
| 126 | |||
| 127 | TP_PROTO(unsigned long opcode, unsigned long retval), | ||
| 128 | |||
| 129 | TP_ARGS(opcode, retval), | ||
| 130 | |||
| 131 | TP_STRUCT__entry( | ||
| 132 | __field(unsigned long, opcode) | ||
| 133 | __field(unsigned long, retval) | ||
| 134 | ), | ||
| 135 | |||
| 136 | TP_fast_assign( | ||
| 137 | __entry->opcode = opcode; | ||
| 138 | __entry->retval = retval; | ||
| 139 | ), | ||
| 140 | |||
| 141 | TP_printk("opcode=%lu retval=%lu", __entry->opcode, __entry->retval), | ||
| 142 | |||
| 143 | opal_tracepoint_regfunc, opal_tracepoint_unregfunc | ||
| 144 | ); | ||
| 145 | #endif | ||
| 146 | |||
| 102 | #endif /* _TRACE_POWERPC_H */ | 147 | #endif /* _TRACE_POWERPC_H */ |
| 103 | 148 | ||
| 104 | #undef TRACE_INCLUDE_PATH | 149 | #undef TRACE_INCLUDE_PATH |
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index f5995a912213..e35054054c32 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
| @@ -216,8 +216,6 @@ int main(void) | |||
| 216 | #endif /* CONFIG_PPC_BOOK3E */ | 216 | #endif /* CONFIG_PPC_BOOK3E */ |
| 217 | 217 | ||
| 218 | #ifdef CONFIG_PPC_STD_MMU_64 | 218 | #ifdef CONFIG_PPC_STD_MMU_64 |
| 219 | DEFINE(PACASTABREAL, offsetof(struct paca_struct, stab_real)); | ||
| 220 | DEFINE(PACASTABVIRT, offsetof(struct paca_struct, stab_addr)); | ||
| 221 | DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); | 219 | DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); |
| 222 | DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); | 220 | DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); |
| 223 | DEFINE(PACAVMALLOCSLLP, offsetof(struct paca_struct, vmalloc_sllp)); | 221 | DEFINE(PACAVMALLOCSLLP, offsetof(struct paca_struct, vmalloc_sllp)); |
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 0c157642c2a1..9b6dcaaec1a3 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
| @@ -123,96 +123,6 @@ extern void __restore_cpu_e6500(void); | |||
| 123 | 123 | ||
| 124 | static struct cpu_spec __initdata cpu_specs[] = { | 124 | static struct cpu_spec __initdata cpu_specs[] = { |
| 125 | #ifdef CONFIG_PPC_BOOK3S_64 | 125 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 126 | { /* Power3 */ | ||
| 127 | .pvr_mask = 0xffff0000, | ||
| 128 | .pvr_value = 0x00400000, | ||
| 129 | .cpu_name = "POWER3 (630)", | ||
| 130 | .cpu_features = CPU_FTRS_POWER3, | ||
| 131 | .cpu_user_features = COMMON_USER_PPC64|PPC_FEATURE_PPC_LE, | ||
| 132 | .mmu_features = MMU_FTR_HPTE_TABLE, | ||
| 133 | .icache_bsize = 128, | ||
| 134 | .dcache_bsize = 128, | ||
| 135 | .num_pmcs = 8, | ||
| 136 | .pmc_type = PPC_PMC_IBM, | ||
| 137 | .oprofile_cpu_type = "ppc64/power3", | ||
| 138 | .oprofile_type = PPC_OPROFILE_RS64, | ||
| 139 | .platform = "power3", | ||
| 140 | }, | ||
| 141 | { /* Power3+ */ | ||
| 142 | .pvr_mask = 0xffff0000, | ||
| 143 | .pvr_value = 0x00410000, | ||
| 144 | .cpu_name = "POWER3 (630+)", | ||
| 145 | .cpu_features = CPU_FTRS_POWER3, | ||
| 146 | .cpu_user_features = COMMON_USER_PPC64|PPC_FEATURE_PPC_LE, | ||
| 147 | .mmu_features = MMU_FTR_HPTE_TABLE, | ||
| 148 | .icache_bsize = 128, | ||
| 149 | .dcache_bsize = 128, | ||
| 150 | .num_pmcs = 8, | ||
| 151 | .pmc_type = PPC_PMC_IBM, | ||
| 152 | .oprofile_cpu_type = "ppc64/power3", | ||
| 153 | .oprofile_type = PPC_OPROFILE_RS64, | ||
| 154 | .platform = "power3", | ||
| 155 | }, | ||
| 156 | { /* Northstar */ | ||
| 157 | .pvr_mask = 0xffff0000, | ||
| 158 | .pvr_value = 0x00330000, | ||
| 159 | .cpu_name = "RS64-II (northstar)", | ||
| 160 | .cpu_features = CPU_FTRS_RS64, | ||
| 161 | .cpu_user_features = COMMON_USER_PPC64, | ||
| 162 | .mmu_features = MMU_FTR_HPTE_TABLE, | ||
| 163 | .icache_bsize = 128, | ||
| 164 | .dcache_bsize = 128, | ||
| 165 | .num_pmcs = 8, | ||
| 166 | .pmc_type = PPC_PMC_IBM, | ||
| 167 | .oprofile_cpu_type = "ppc64/rs64", | ||
| 168 | .oprofile_type = PPC_OPROFILE_RS64, | ||
| 169 | .platform = "rs64", | ||
| 170 | }, | ||
| 171 | { /* Pulsar */ | ||
| 172 | .pvr_mask = 0xffff0000, | ||
| 173 | .pvr_value = 0x00340000, | ||
| 174 | .cpu_name = "RS64-III (pulsar)", | ||
| 175 | .cpu_features = CPU_FTRS_RS64, | ||
| 176 | .cpu_user_features = COMMON_USER_PPC64, | ||
| 177 | .mmu_features = MMU_FTR_HPTE_TABLE, | ||
| 178 | .icache_bsize = 128, | ||
| 179 | .dcache_bsize = 128, | ||
| 180 | .num_pmcs = 8, | ||
| 181 | .pmc_type = PPC_PMC_IBM, | ||
| 182 | .oprofile_cpu_type = "ppc64/rs64", | ||
| 183 | .oprofile_type = PPC_OPROFILE_RS64, | ||
| 184 | .platform = "rs64", | ||
| 185 | }, | ||
| 186 | { /* I-star */ | ||
| 187 | .pvr_mask = 0xffff0000, | ||
| 188 | .pvr_value = 0x00360000, | ||
| 189 | .cpu_name = "RS64-III (icestar)", | ||
| 190 | .cpu_features = CPU_FTRS_RS64, | ||
| 191 | .cpu_user_features = COMMON_USER_PPC64, | ||
| 192 | .mmu_features = MMU_FTR_HPTE_TABLE, | ||
| 193 | .icache_bsize = 128, | ||
| 194 | .dcache_bsize = 128, | ||
| 195 | .num_pmcs = 8, | ||
| 196 | .pmc_type = PPC_PMC_IBM, | ||
| 197 | .oprofile_cpu_type = "ppc64/rs64", | ||
| 198 | .oprofile_type = PPC_OPROFILE_RS64, | ||
| 199 | .platform = "rs64", | ||
| 200 | }, | ||
| 201 | { /* S-star */ | ||
| 202 | .pvr_mask = 0xffff0000, | ||
| 203 | .pvr_value = 0x00370000, | ||
| 204 | .cpu_name = "RS64-IV (sstar)", | ||
| 205 | .cpu_features = CPU_FTRS_RS64, | ||
| 206 | .cpu_user_features = COMMON_USER_PPC64, | ||
| 207 | .mmu_features = MMU_FTR_HPTE_TABLE, | ||
| 208 | .icache_bsize = 128, | ||
| 209 | .dcache_bsize = 128, | ||
| 210 | .num_pmcs = 8, | ||
| 211 | .pmc_type = PPC_PMC_IBM, | ||
| 212 | .oprofile_cpu_type = "ppc64/rs64", | ||
| 213 | .oprofile_type = PPC_OPROFILE_RS64, | ||
| 214 | .platform = "rs64", | ||
| 215 | }, | ||
| 216 | { /* Power4 */ | 126 | { /* Power4 */ |
| 217 | .pvr_mask = 0xffff0000, | 127 | .pvr_mask = 0xffff0000, |
| 218 | .pvr_value = 0x00350000, | 128 | .pvr_value = 0x00350000, |
| @@ -617,7 +527,7 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
| 617 | #endif /* CONFIG_PPC_BOOK3S_64 */ | 527 | #endif /* CONFIG_PPC_BOOK3S_64 */ |
| 618 | 528 | ||
| 619 | #ifdef CONFIG_PPC32 | 529 | #ifdef CONFIG_PPC32 |
| 620 | #if CLASSIC_PPC | 530 | #ifdef CONFIG_PPC_BOOK3S_32 |
| 621 | { /* 601 */ | 531 | { /* 601 */ |
| 622 | .pvr_mask = 0xffff0000, | 532 | .pvr_mask = 0xffff0000, |
| 623 | .pvr_value = 0x00010000, | 533 | .pvr_value = 0x00010000, |
| @@ -1257,7 +1167,7 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
| 1257 | .machine_check = machine_check_generic, | 1167 | .machine_check = machine_check_generic, |
| 1258 | .platform = "ppc603", | 1168 | .platform = "ppc603", |
| 1259 | }, | 1169 | }, |
| 1260 | #endif /* CLASSIC_PPC */ | 1170 | #endif /* CONFIG_PPC_BOOK3S_32 */ |
| 1261 | #ifdef CONFIG_8xx | 1171 | #ifdef CONFIG_8xx |
| 1262 | { /* 8xx */ | 1172 | { /* 8xx */ |
| 1263 | .pvr_mask = 0xffff0000, | 1173 | .pvr_mask = 0xffff0000, |
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index 86e25702aaca..59a64f8dc85f 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
| 28 | #include <linux/list.h> | 28 | #include <linux/list.h> |
| 29 | #include <linux/pci.h> | 29 | #include <linux/pci.h> |
| 30 | #include <linux/iommu.h> | ||
| 30 | #include <linux/proc_fs.h> | 31 | #include <linux/proc_fs.h> |
| 31 | #include <linux/rbtree.h> | 32 | #include <linux/rbtree.h> |
| 32 | #include <linux/reboot.h> | 33 | #include <linux/reboot.h> |
| @@ -40,6 +41,7 @@ | |||
| 40 | #include <asm/eeh.h> | 41 | #include <asm/eeh.h> |
| 41 | #include <asm/eeh_event.h> | 42 | #include <asm/eeh_event.h> |
| 42 | #include <asm/io.h> | 43 | #include <asm/io.h> |
| 44 | #include <asm/iommu.h> | ||
| 43 | #include <asm/machdep.h> | 45 | #include <asm/machdep.h> |
| 44 | #include <asm/ppc-pci.h> | 46 | #include <asm/ppc-pci.h> |
| 45 | #include <asm/rtas.h> | 47 | #include <asm/rtas.h> |
| @@ -108,6 +110,9 @@ struct eeh_ops *eeh_ops = NULL; | |||
| 108 | /* Lock to avoid races due to multiple reports of an error */ | 110 | /* Lock to avoid races due to multiple reports of an error */ |
| 109 | DEFINE_RAW_SPINLOCK(confirm_error_lock); | 111 | DEFINE_RAW_SPINLOCK(confirm_error_lock); |
| 110 | 112 | ||
| 113 | /* Lock to protect passed flags */ | ||
| 114 | static DEFINE_MUTEX(eeh_dev_mutex); | ||
| 115 | |||
| 111 | /* Buffer for reporting pci register dumps. Its here in BSS, and | 116 | /* Buffer for reporting pci register dumps. Its here in BSS, and |
| 112 | * not dynamically alloced, so that it ends up in RMO where RTAS | 117 | * not dynamically alloced, so that it ends up in RMO where RTAS |
| 113 | * can access it. | 118 | * can access it. |
| @@ -137,7 +142,7 @@ static struct eeh_stats eeh_stats; | |||
| 137 | static int __init eeh_setup(char *str) | 142 | static int __init eeh_setup(char *str) |
| 138 | { | 143 | { |
| 139 | if (!strcmp(str, "off")) | 144 | if (!strcmp(str, "off")) |
| 140 | eeh_subsystem_flags |= EEH_FORCE_DISABLED; | 145 | eeh_add_flag(EEH_FORCE_DISABLED); |
| 141 | 146 | ||
| 142 | return 1; | 147 | return 1; |
| 143 | } | 148 | } |
| @@ -152,12 +157,13 @@ __setup("eeh=", eeh_setup); | |||
| 152 | * This routine captures assorted PCI configuration space data, | 157 | * This routine captures assorted PCI configuration space data, |
| 153 | * and puts them into a buffer for RTAS error logging. | 158 | * and puts them into a buffer for RTAS error logging. |
| 154 | */ | 159 | */ |
| 155 | static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len) | 160 | static size_t eeh_gather_pci_data(struct eeh_dev *edev, char *buf, size_t len) |
| 156 | { | 161 | { |
| 157 | struct device_node *dn = eeh_dev_to_of_node(edev); | 162 | struct device_node *dn = eeh_dev_to_of_node(edev); |
| 158 | u32 cfg; | 163 | u32 cfg; |
| 159 | int cap, i; | 164 | int cap, i; |
| 160 | int n = 0; | 165 | int n = 0, l = 0; |
| 166 | char buffer[128]; | ||
| 161 | 167 | ||
| 162 | n += scnprintf(buf+n, len-n, "%s\n", dn->full_name); | 168 | n += scnprintf(buf+n, len-n, "%s\n", dn->full_name); |
| 163 | pr_warn("EEH: of node=%s\n", dn->full_name); | 169 | pr_warn("EEH: of node=%s\n", dn->full_name); |
| @@ -202,8 +208,22 @@ static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len) | |||
| 202 | for (i=0; i<=8; i++) { | 208 | for (i=0; i<=8; i++) { |
| 203 | eeh_ops->read_config(dn, cap+4*i, 4, &cfg); | 209 | eeh_ops->read_config(dn, cap+4*i, 4, &cfg); |
| 204 | n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); | 210 | n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); |
| 205 | pr_warn("EEH: PCI-E %02x: %08x\n", i, cfg); | 211 | |
| 212 | if ((i % 4) == 0) { | ||
| 213 | if (i != 0) | ||
| 214 | pr_warn("%s\n", buffer); | ||
| 215 | |||
| 216 | l = scnprintf(buffer, sizeof(buffer), | ||
| 217 | "EEH: PCI-E %02x: %08x ", | ||
| 218 | 4*i, cfg); | ||
| 219 | } else { | ||
| 220 | l += scnprintf(buffer+l, sizeof(buffer)-l, | ||
| 221 | "%08x ", cfg); | ||
| 222 | } | ||
| 223 | |||
| 206 | } | 224 | } |
| 225 | |||
| 226 | pr_warn("%s\n", buffer); | ||
| 207 | } | 227 | } |
| 208 | 228 | ||
| 209 | /* If AER capable, dump it */ | 229 | /* If AER capable, dump it */ |
| @@ -212,11 +232,24 @@ static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len) | |||
| 212 | n += scnprintf(buf+n, len-n, "pci-e AER:\n"); | 232 | n += scnprintf(buf+n, len-n, "pci-e AER:\n"); |
| 213 | pr_warn("EEH: PCI-E AER capability register set follows:\n"); | 233 | pr_warn("EEH: PCI-E AER capability register set follows:\n"); |
| 214 | 234 | ||
| 215 | for (i=0; i<14; i++) { | 235 | for (i=0; i<=13; i++) { |
| 216 | eeh_ops->read_config(dn, cap+4*i, 4, &cfg); | 236 | eeh_ops->read_config(dn, cap+4*i, 4, &cfg); |
| 217 | n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); | 237 | n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); |
| 218 | pr_warn("EEH: PCI-E AER %02x: %08x\n", i, cfg); | 238 | |
| 239 | if ((i % 4) == 0) { | ||
| 240 | if (i != 0) | ||
| 241 | pr_warn("%s\n", buffer); | ||
| 242 | |||
| 243 | l = scnprintf(buffer, sizeof(buffer), | ||
| 244 | "EEH: PCI-E AER %02x: %08x ", | ||
| 245 | 4*i, cfg); | ||
| 246 | } else { | ||
| 247 | l += scnprintf(buffer+l, sizeof(buffer)-l, | ||
| 248 | "%08x ", cfg); | ||
| 249 | } | ||
| 219 | } | 250 | } |
| 251 | |||
| 252 | pr_warn("%s\n", buffer); | ||
| 220 | } | 253 | } |
| 221 | 254 | ||
| 222 | return n; | 255 | return n; |
| @@ -247,7 +280,7 @@ void eeh_slot_error_detail(struct eeh_pe *pe, int severity) | |||
| 247 | * 0xFF's is always returned from PCI config space. | 280 | * 0xFF's is always returned from PCI config space. |
| 248 | */ | 281 | */ |
| 249 | if (!(pe->type & EEH_PE_PHB)) { | 282 | if (!(pe->type & EEH_PE_PHB)) { |
| 250 | if (eeh_probe_mode_devtree()) | 283 | if (eeh_has_flag(EEH_ENABLE_IO_FOR_LOG)) |
| 251 | eeh_pci_enable(pe, EEH_OPT_THAW_MMIO); | 284 | eeh_pci_enable(pe, EEH_OPT_THAW_MMIO); |
| 252 | eeh_ops->configure_bridge(pe); | 285 | eeh_ops->configure_bridge(pe); |
| 253 | eeh_pe_restore_bars(pe); | 286 | eeh_pe_restore_bars(pe); |
| @@ -298,14 +331,14 @@ static int eeh_phb_check_failure(struct eeh_pe *pe) | |||
| 298 | unsigned long flags; | 331 | unsigned long flags; |
| 299 | int ret; | 332 | int ret; |
| 300 | 333 | ||
| 301 | if (!eeh_probe_mode_dev()) | 334 | if (!eeh_has_flag(EEH_PROBE_MODE_DEV)) |
| 302 | return -EPERM; | 335 | return -EPERM; |
| 303 | 336 | ||
| 304 | /* Find the PHB PE */ | 337 | /* Find the PHB PE */ |
| 305 | phb_pe = eeh_phb_pe_get(pe->phb); | 338 | phb_pe = eeh_phb_pe_get(pe->phb); |
| 306 | if (!phb_pe) { | 339 | if (!phb_pe) { |
| 307 | pr_warning("%s Can't find PE for PHB#%d\n", | 340 | pr_warn("%s Can't find PE for PHB#%d\n", |
| 308 | __func__, pe->phb->global_number); | 341 | __func__, pe->phb->global_number); |
| 309 | return -EEXIST; | 342 | return -EEXIST; |
| 310 | } | 343 | } |
| 311 | 344 | ||
| @@ -400,6 +433,14 @@ int eeh_dev_check_failure(struct eeh_dev *edev) | |||
| 400 | if (ret > 0) | 433 | if (ret > 0) |
| 401 | return ret; | 434 | return ret; |
| 402 | 435 | ||
| 436 | /* | ||
| 437 | * If the PE isn't owned by us, we shouldn't check the | ||
| 438 | * state. Instead, let the owner handle it if the PE has | ||
| 439 | * been frozen. | ||
| 440 | */ | ||
| 441 | if (eeh_pe_passed(pe)) | ||
| 442 | return 0; | ||
| 443 | |||
| 403 | /* If we already have a pending isolation event for this | 444 | /* If we already have a pending isolation event for this |
| 404 | * slot, we know it's bad already, we don't need to check. | 445 | * slot, we know it's bad already, we don't need to check. |
| 405 | * Do this checking under a lock; as multiple PCI devices | 446 | * Do this checking under a lock; as multiple PCI devices |
| @@ -746,13 +787,13 @@ void eeh_save_bars(struct eeh_dev *edev) | |||
| 746 | int __init eeh_ops_register(struct eeh_ops *ops) | 787 | int __init eeh_ops_register(struct eeh_ops *ops) |
| 747 | { | 788 | { |
| 748 | if (!ops->name) { | 789 | if (!ops->name) { |
| 749 | pr_warning("%s: Invalid EEH ops name for %p\n", | 790 | pr_warn("%s: Invalid EEH ops name for %p\n", |
| 750 | __func__, ops); | 791 | __func__, ops); |
| 751 | return -EINVAL; | 792 | return -EINVAL; |
| 752 | } | 793 | } |
| 753 | 794 | ||
| 754 | if (eeh_ops && eeh_ops != ops) { | 795 | if (eeh_ops && eeh_ops != ops) { |
| 755 | pr_warning("%s: EEH ops of platform %s already existing (%s)\n", | 796 | pr_warn("%s: EEH ops of platform %s already existing (%s)\n", |
| 756 | __func__, eeh_ops->name, ops->name); | 797 | __func__, eeh_ops->name, ops->name); |
| 757 | return -EEXIST; | 798 | return -EEXIST; |
| 758 | } | 799 | } |
| @@ -772,7 +813,7 @@ int __init eeh_ops_register(struct eeh_ops *ops) | |||
| 772 | int __exit eeh_ops_unregister(const char *name) | 813 | int __exit eeh_ops_unregister(const char *name) |
| 773 | { | 814 | { |
| 774 | if (!name || !strlen(name)) { | 815 | if (!name || !strlen(name)) { |
| 775 | pr_warning("%s: Invalid EEH ops name\n", | 816 | pr_warn("%s: Invalid EEH ops name\n", |
| 776 | __func__); | 817 | __func__); |
| 777 | return -EINVAL; | 818 | return -EINVAL; |
| 778 | } | 819 | } |
| @@ -788,7 +829,7 @@ int __exit eeh_ops_unregister(const char *name) | |||
| 788 | static int eeh_reboot_notifier(struct notifier_block *nb, | 829 | static int eeh_reboot_notifier(struct notifier_block *nb, |
| 789 | unsigned long action, void *unused) | 830 | unsigned long action, void *unused) |
| 790 | { | 831 | { |
| 791 | eeh_set_enable(false); | 832 | eeh_clear_flag(EEH_ENABLED); |
| 792 | return NOTIFY_DONE; | 833 | return NOTIFY_DONE; |
| 793 | } | 834 | } |
| 794 | 835 | ||
| @@ -837,11 +878,11 @@ int eeh_init(void) | |||
| 837 | 878 | ||
| 838 | /* call platform initialization function */ | 879 | /* call platform initialization function */ |
| 839 | if (!eeh_ops) { | 880 | if (!eeh_ops) { |
| 840 | pr_warning("%s: Platform EEH operation not found\n", | 881 | pr_warn("%s: Platform EEH operation not found\n", |
| 841 | __func__); | 882 | __func__); |
| 842 | return -EEXIST; | 883 | return -EEXIST; |
| 843 | } else if ((ret = eeh_ops->init())) { | 884 | } else if ((ret = eeh_ops->init())) { |
| 844 | pr_warning("%s: Failed to call platform init function (%d)\n", | 885 | pr_warn("%s: Failed to call platform init function (%d)\n", |
| 845 | __func__, ret); | 886 | __func__, ret); |
| 846 | return ret; | 887 | return ret; |
| 847 | } | 888 | } |
| @@ -852,13 +893,13 @@ int eeh_init(void) | |||
| 852 | return ret; | 893 | return ret; |
| 853 | 894 | ||
| 854 | /* Enable EEH for all adapters */ | 895 | /* Enable EEH for all adapters */ |
| 855 | if (eeh_probe_mode_devtree()) { | 896 | if (eeh_has_flag(EEH_PROBE_MODE_DEVTREE)) { |
| 856 | list_for_each_entry_safe(hose, tmp, | 897 | list_for_each_entry_safe(hose, tmp, |
| 857 | &hose_list, list_node) { | 898 | &hose_list, list_node) { |
| 858 | phb = hose->dn; | 899 | phb = hose->dn; |
| 859 | traverse_pci_devices(phb, eeh_ops->of_probe, NULL); | 900 | traverse_pci_devices(phb, eeh_ops->of_probe, NULL); |
| 860 | } | 901 | } |
| 861 | } else if (eeh_probe_mode_dev()) { | 902 | } else if (eeh_has_flag(EEH_PROBE_MODE_DEV)) { |
| 862 | list_for_each_entry_safe(hose, tmp, | 903 | list_for_each_entry_safe(hose, tmp, |
| 863 | &hose_list, list_node) | 904 | &hose_list, list_node) |
| 864 | pci_walk_bus(hose->bus, eeh_ops->dev_probe, NULL); | 905 | pci_walk_bus(hose->bus, eeh_ops->dev_probe, NULL); |
| @@ -882,7 +923,7 @@ int eeh_init(void) | |||
| 882 | if (eeh_enabled()) | 923 | if (eeh_enabled()) |
| 883 | pr_info("EEH: PCI Enhanced I/O Error Handling Enabled\n"); | 924 | pr_info("EEH: PCI Enhanced I/O Error Handling Enabled\n"); |
| 884 | else | 925 | else |
| 885 | pr_warning("EEH: No capable adapters found\n"); | 926 | pr_warn("EEH: No capable adapters found\n"); |
| 886 | 927 | ||
| 887 | return ret; | 928 | return ret; |
| 888 | } | 929 | } |
| @@ -910,7 +951,7 @@ void eeh_add_device_early(struct device_node *dn) | |||
| 910 | * would delay the probe until late stage because | 951 | * would delay the probe until late stage because |
| 911 | * the PCI device isn't available this moment. | 952 | * the PCI device isn't available this moment. |
| 912 | */ | 953 | */ |
| 913 | if (!eeh_probe_mode_devtree()) | 954 | if (!eeh_has_flag(EEH_PROBE_MODE_DEVTREE)) |
| 914 | return; | 955 | return; |
| 915 | 956 | ||
| 916 | if (!of_node_to_eeh_dev(dn)) | 957 | if (!of_node_to_eeh_dev(dn)) |
| @@ -996,7 +1037,7 @@ void eeh_add_device_late(struct pci_dev *dev) | |||
| 996 | * We have to do the EEH probe here because the PCI device | 1037 | * We have to do the EEH probe here because the PCI device |
| 997 | * hasn't been created yet in the early stage. | 1038 | * hasn't been created yet in the early stage. |
| 998 | */ | 1039 | */ |
| 999 | if (eeh_probe_mode_dev()) | 1040 | if (eeh_has_flag(EEH_PROBE_MODE_DEV)) |
| 1000 | eeh_ops->dev_probe(dev, NULL); | 1041 | eeh_ops->dev_probe(dev, NULL); |
| 1001 | 1042 | ||
| 1002 | eeh_addr_cache_insert_dev(dev); | 1043 | eeh_addr_cache_insert_dev(dev); |
| @@ -1100,6 +1141,285 @@ void eeh_remove_device(struct pci_dev *dev) | |||
| 1100 | edev->mode &= ~EEH_DEV_SYSFS; | 1141 | edev->mode &= ~EEH_DEV_SYSFS; |
| 1101 | } | 1142 | } |
| 1102 | 1143 | ||
| 1144 | /** | ||
| 1145 | * eeh_dev_open - Increase count of pass through devices for PE | ||
| 1146 | * @pdev: PCI device | ||
| 1147 | * | ||
| 1148 | * Increase count of passed through devices for the indicated | ||
| 1149 | * PE. In the result, the EEH errors detected on the PE won't be | ||
| 1150 | * reported. The PE owner will be responsible for detection | ||
| 1151 | * and recovery. | ||
| 1152 | */ | ||
| 1153 | int eeh_dev_open(struct pci_dev *pdev) | ||
| 1154 | { | ||
| 1155 | struct eeh_dev *edev; | ||
| 1156 | |||
| 1157 | mutex_lock(&eeh_dev_mutex); | ||
| 1158 | |||
| 1159 | /* No PCI device ? */ | ||
| 1160 | if (!pdev) | ||
| 1161 | goto out; | ||
| 1162 | |||
| 1163 | /* No EEH device or PE ? */ | ||
| 1164 | edev = pci_dev_to_eeh_dev(pdev); | ||
| 1165 | if (!edev || !edev->pe) | ||
| 1166 | goto out; | ||
| 1167 | |||
| 1168 | /* Increase PE's pass through count */ | ||
| 1169 | atomic_inc(&edev->pe->pass_dev_cnt); | ||
| 1170 | mutex_unlock(&eeh_dev_mutex); | ||
| 1171 | |||
| 1172 | return 0; | ||
| 1173 | out: | ||
| 1174 | mutex_unlock(&eeh_dev_mutex); | ||
| 1175 | return -ENODEV; | ||
| 1176 | } | ||
| 1177 | EXPORT_SYMBOL_GPL(eeh_dev_open); | ||
| 1178 | |||
| 1179 | /** | ||
| 1180 | * eeh_dev_release - Decrease count of pass through devices for PE | ||
| 1181 | * @pdev: PCI device | ||
| 1182 | * | ||
| 1183 | * Decrease count of pass through devices for the indicated PE. If | ||
| 1184 | * there is no passed through device in PE, the EEH errors detected | ||
| 1185 | * on the PE will be reported and handled as usual. | ||
| 1186 | */ | ||
| 1187 | void eeh_dev_release(struct pci_dev *pdev) | ||
| 1188 | { | ||
| 1189 | struct eeh_dev *edev; | ||
| 1190 | |||
| 1191 | mutex_lock(&eeh_dev_mutex); | ||
| 1192 | |||
| 1193 | /* No PCI device ? */ | ||
| 1194 | if (!pdev) | ||
| 1195 | goto out; | ||
| 1196 | |||
| 1197 | /* No EEH device ? */ | ||
| 1198 | edev = pci_dev_to_eeh_dev(pdev); | ||
| 1199 | if (!edev || !edev->pe || !eeh_pe_passed(edev->pe)) | ||
| 1200 | goto out; | ||
| 1201 | |||
| 1202 | /* Decrease PE's pass through count */ | ||
| 1203 | atomic_dec(&edev->pe->pass_dev_cnt); | ||
| 1204 | WARN_ON(atomic_read(&edev->pe->pass_dev_cnt) < 0); | ||
| 1205 | out: | ||
| 1206 | mutex_unlock(&eeh_dev_mutex); | ||
| 1207 | } | ||
| 1208 | EXPORT_SYMBOL(eeh_dev_release); | ||
| 1209 | |||
| 1210 | #ifdef CONFIG_IOMMU_API | ||
| 1211 | |||
| 1212 | static int dev_has_iommu_table(struct device *dev, void *data) | ||
| 1213 | { | ||
| 1214 | struct pci_dev *pdev = to_pci_dev(dev); | ||
| 1215 | struct pci_dev **ppdev = data; | ||
| 1216 | struct iommu_table *tbl; | ||
| 1217 | |||
| 1218 | if (!dev) | ||
| 1219 | return 0; | ||
| 1220 | |||
| 1221 | tbl = get_iommu_table_base(dev); | ||
| 1222 | if (tbl && tbl->it_group) { | ||
| 1223 | *ppdev = pdev; | ||
| 1224 | return 1; | ||
| 1225 | } | ||
| 1226 | |||
| 1227 | return 0; | ||
| 1228 | } | ||
| 1229 | |||
| 1230 | /** | ||
| 1231 | * eeh_iommu_group_to_pe - Convert IOMMU group to EEH PE | ||
| 1232 | * @group: IOMMU group | ||
| 1233 | * | ||
| 1234 | * The routine is called to convert IOMMU group to EEH PE. | ||
| 1235 | */ | ||
| 1236 | struct eeh_pe *eeh_iommu_group_to_pe(struct iommu_group *group) | ||
| 1237 | { | ||
| 1238 | struct pci_dev *pdev = NULL; | ||
| 1239 | struct eeh_dev *edev; | ||
| 1240 | int ret; | ||
| 1241 | |||
| 1242 | /* No IOMMU group ? */ | ||
| 1243 | if (!group) | ||
| 1244 | return NULL; | ||
| 1245 | |||
| 1246 | ret = iommu_group_for_each_dev(group, &pdev, dev_has_iommu_table); | ||
| 1247 | if (!ret || !pdev) | ||
| 1248 | return NULL; | ||
| 1249 | |||
| 1250 | /* No EEH device or PE ? */ | ||
| 1251 | edev = pci_dev_to_eeh_dev(pdev); | ||
| 1252 | if (!edev || !edev->pe) | ||
| 1253 | return NULL; | ||
| 1254 | |||
| 1255 | return edev->pe; | ||
| 1256 | } | ||
| 1257 | EXPORT_SYMBOL_GPL(eeh_iommu_group_to_pe); | ||
| 1258 | |||
| 1259 | #endif /* CONFIG_IOMMU_API */ | ||
| 1260 | |||
| 1261 | /** | ||
| 1262 | * eeh_pe_set_option - Set options for the indicated PE | ||
| 1263 | * @pe: EEH PE | ||
| 1264 | * @option: requested option | ||
| 1265 | * | ||
| 1266 | * The routine is called to enable or disable EEH functionality | ||
| 1267 | * on the indicated PE, to enable IO or DMA for the frozen PE. | ||
| 1268 | */ | ||
| 1269 | int eeh_pe_set_option(struct eeh_pe *pe, int option) | ||
| 1270 | { | ||
| 1271 | int ret = 0; | ||
| 1272 | |||
| 1273 | /* Invalid PE ? */ | ||
| 1274 | if (!pe) | ||
| 1275 | return -ENODEV; | ||
| 1276 | |||
| 1277 | /* | ||
| 1278 | * EEH functionality could possibly be disabled, just | ||
| 1279 | * return error for the case. And the EEH functinality | ||
| 1280 | * isn't expected to be disabled on one specific PE. | ||
| 1281 | */ | ||
| 1282 | switch (option) { | ||
| 1283 | case EEH_OPT_ENABLE: | ||
| 1284 | if (eeh_enabled()) | ||
| 1285 | break; | ||
| 1286 | ret = -EIO; | ||
| 1287 | break; | ||
| 1288 | case EEH_OPT_DISABLE: | ||
| 1289 | break; | ||
| 1290 | case EEH_OPT_THAW_MMIO: | ||
| 1291 | case EEH_OPT_THAW_DMA: | ||
| 1292 | if (!eeh_ops || !eeh_ops->set_option) { | ||
| 1293 | ret = -ENOENT; | ||
| 1294 | break; | ||
| 1295 | } | ||
| 1296 | |||
| 1297 | ret = eeh_ops->set_option(pe, option); | ||
| 1298 | break; | ||
| 1299 | default: | ||
| 1300 | pr_debug("%s: Option %d out of range (%d, %d)\n", | ||
| 1301 | __func__, option, EEH_OPT_DISABLE, EEH_OPT_THAW_DMA); | ||
| 1302 | ret = -EINVAL; | ||
| 1303 | } | ||
| 1304 | |||
| 1305 | return ret; | ||
| 1306 | } | ||
| 1307 | EXPORT_SYMBOL_GPL(eeh_pe_set_option); | ||
| 1308 | |||
| 1309 | /** | ||
| 1310 | * eeh_pe_get_state - Retrieve PE's state | ||
| 1311 | * @pe: EEH PE | ||
| 1312 | * | ||
| 1313 | * Retrieve the PE's state, which includes 3 aspects: enabled | ||
| 1314 | * DMA, enabled IO and asserted reset. | ||
| 1315 | */ | ||
| 1316 | int eeh_pe_get_state(struct eeh_pe *pe) | ||
| 1317 | { | ||
| 1318 | int result, ret = 0; | ||
| 1319 | bool rst_active, dma_en, mmio_en; | ||
| 1320 | |||
| 1321 | /* Existing PE ? */ | ||
| 1322 | if (!pe) | ||
| 1323 | return -ENODEV; | ||
| 1324 | |||
| 1325 | if (!eeh_ops || !eeh_ops->get_state) | ||
| 1326 | return -ENOENT; | ||
| 1327 | |||
| 1328 | result = eeh_ops->get_state(pe, NULL); | ||
| 1329 | rst_active = !!(result & EEH_STATE_RESET_ACTIVE); | ||
| 1330 | dma_en = !!(result & EEH_STATE_DMA_ENABLED); | ||
| 1331 | mmio_en = !!(result & EEH_STATE_MMIO_ENABLED); | ||
| 1332 | |||
| 1333 | if (rst_active) | ||
| 1334 | ret = EEH_PE_STATE_RESET; | ||
| 1335 | else if (dma_en && mmio_en) | ||
| 1336 | ret = EEH_PE_STATE_NORMAL; | ||
| 1337 | else if (!dma_en && !mmio_en) | ||
| 1338 | ret = EEH_PE_STATE_STOPPED_IO_DMA; | ||
| 1339 | else if (!dma_en && mmio_en) | ||
| 1340 | ret = EEH_PE_STATE_STOPPED_DMA; | ||
| 1341 | else | ||
| 1342 | ret = EEH_PE_STATE_UNAVAIL; | ||
| 1343 | |||
| 1344 | return ret; | ||
| 1345 | } | ||
| 1346 | EXPORT_SYMBOL_GPL(eeh_pe_get_state); | ||
| 1347 | |||
| 1348 | /** | ||
| 1349 | * eeh_pe_reset - Issue PE reset according to specified type | ||
| 1350 | * @pe: EEH PE | ||
| 1351 | * @option: reset type | ||
| 1352 | * | ||
| 1353 | * The routine is called to reset the specified PE with the | ||
| 1354 | * indicated type, either fundamental reset or hot reset. | ||
| 1355 | * PE reset is the most important part for error recovery. | ||
| 1356 | */ | ||
| 1357 | int eeh_pe_reset(struct eeh_pe *pe, int option) | ||
| 1358 | { | ||
| 1359 | int ret = 0; | ||
| 1360 | |||
| 1361 | /* Invalid PE ? */ | ||
| 1362 | if (!pe) | ||
| 1363 | return -ENODEV; | ||
| 1364 | |||
| 1365 | if (!eeh_ops || !eeh_ops->set_option || !eeh_ops->reset) | ||
| 1366 | return -ENOENT; | ||
| 1367 | |||
| 1368 | switch (option) { | ||
| 1369 | case EEH_RESET_DEACTIVATE: | ||
| 1370 | ret = eeh_ops->reset(pe, option); | ||
| 1371 | if (ret) | ||
| 1372 | break; | ||
| 1373 | |||
| 1374 | /* | ||
| 1375 | * The PE is still in frozen state and we need to clear | ||
| 1376 | * that. It's good to clear frozen state after deassert | ||
| 1377 | * to avoid messy IO access during reset, which might | ||
| 1378 | * cause recursive frozen PE. | ||
| 1379 | */ | ||
| 1380 | ret = eeh_ops->set_option(pe, EEH_OPT_THAW_MMIO); | ||
| 1381 | if (!ret) | ||
| 1382 | ret = eeh_ops->set_option(pe, EEH_OPT_THAW_DMA); | ||
| 1383 | if (!ret) | ||
| 1384 | eeh_pe_state_clear(pe, EEH_PE_ISOLATED); | ||
| 1385 | break; | ||
| 1386 | case EEH_RESET_HOT: | ||
| 1387 | case EEH_RESET_FUNDAMENTAL: | ||
| 1388 | ret = eeh_ops->reset(pe, option); | ||
| 1389 | break; | ||
| 1390 | default: | ||
| 1391 | pr_debug("%s: Unsupported option %d\n", | ||
| 1392 | __func__, option); | ||
| 1393 | ret = -EINVAL; | ||
| 1394 | } | ||
| 1395 | |||
| 1396 | return ret; | ||
| 1397 | } | ||
| 1398 | EXPORT_SYMBOL_GPL(eeh_pe_reset); | ||
| 1399 | |||
| 1400 | /** | ||
| 1401 | * eeh_pe_configure - Configure PCI bridges after PE reset | ||
| 1402 | * @pe: EEH PE | ||
| 1403 | * | ||
| 1404 | * The routine is called to restore the PCI config space for | ||
| 1405 | * those PCI devices, especially PCI bridges affected by PE | ||
| 1406 | * reset issued previously. | ||
| 1407 | */ | ||
| 1408 | int eeh_pe_configure(struct eeh_pe *pe) | ||
| 1409 | { | ||
| 1410 | int ret = 0; | ||
| 1411 | |||
| 1412 | /* Invalid PE ? */ | ||
| 1413 | if (!pe) | ||
| 1414 | return -ENODEV; | ||
| 1415 | |||
| 1416 | /* Restore config space for the affected devices */ | ||
| 1417 | eeh_pe_restore_bars(pe); | ||
| 1418 | |||
| 1419 | return ret; | ||
| 1420 | } | ||
| 1421 | EXPORT_SYMBOL_GPL(eeh_pe_configure); | ||
| 1422 | |||
| 1103 | static int proc_eeh_show(struct seq_file *m, void *v) | 1423 | static int proc_eeh_show(struct seq_file *m, void *v) |
| 1104 | { | 1424 | { |
| 1105 | if (!eeh_enabled()) { | 1425 | if (!eeh_enabled()) { |
| @@ -1143,9 +1463,9 @@ static const struct file_operations proc_eeh_operations = { | |||
| 1143 | static int eeh_enable_dbgfs_set(void *data, u64 val) | 1463 | static int eeh_enable_dbgfs_set(void *data, u64 val) |
| 1144 | { | 1464 | { |
| 1145 | if (val) | 1465 | if (val) |
| 1146 | eeh_subsystem_flags &= ~EEH_FORCE_DISABLED; | 1466 | eeh_clear_flag(EEH_FORCE_DISABLED); |
| 1147 | else | 1467 | else |
| 1148 | eeh_subsystem_flags |= EEH_FORCE_DISABLED; | 1468 | eeh_add_flag(EEH_FORCE_DISABLED); |
| 1149 | 1469 | ||
| 1150 | /* Notify the backend */ | 1470 | /* Notify the backend */ |
| 1151 | if (eeh_ops->post_init) | 1471 | if (eeh_ops->post_init) |
diff --git a/arch/powerpc/kernel/eeh_cache.c b/arch/powerpc/kernel/eeh_cache.c index e8c9fd546a5c..07d8a2423a61 100644 --- a/arch/powerpc/kernel/eeh_cache.c +++ b/arch/powerpc/kernel/eeh_cache.c | |||
| @@ -143,7 +143,7 @@ eeh_addr_cache_insert(struct pci_dev *dev, unsigned long alo, | |||
| 143 | } else { | 143 | } else { |
| 144 | if (dev != piar->pcidev || | 144 | if (dev != piar->pcidev || |
| 145 | alo != piar->addr_lo || ahi != piar->addr_hi) { | 145 | alo != piar->addr_lo || ahi != piar->addr_hi) { |
| 146 | pr_warning("PIAR: overlapping address range\n"); | 146 | pr_warn("PIAR: overlapping address range\n"); |
| 147 | } | 147 | } |
| 148 | return piar; | 148 | return piar; |
| 149 | } | 149 | } |
| @@ -177,19 +177,20 @@ static void __eeh_addr_cache_insert_dev(struct pci_dev *dev) | |||
| 177 | 177 | ||
| 178 | dn = pci_device_to_OF_node(dev); | 178 | dn = pci_device_to_OF_node(dev); |
| 179 | if (!dn) { | 179 | if (!dn) { |
| 180 | pr_warning("PCI: no pci dn found for dev=%s\n", pci_name(dev)); | 180 | pr_warn("PCI: no pci dn found for dev=%s\n", |
| 181 | pci_name(dev)); | ||
| 181 | return; | 182 | return; |
| 182 | } | 183 | } |
| 183 | 184 | ||
| 184 | edev = of_node_to_eeh_dev(dn); | 185 | edev = of_node_to_eeh_dev(dn); |
| 185 | if (!edev) { | 186 | if (!edev) { |
| 186 | pr_warning("PCI: no EEH dev found for dn=%s\n", | 187 | pr_warn("PCI: no EEH dev found for dn=%s\n", |
| 187 | dn->full_name); | 188 | dn->full_name); |
| 188 | return; | 189 | return; |
| 189 | } | 190 | } |
| 190 | 191 | ||
| 191 | /* Skip any devices for which EEH is not enabled. */ | 192 | /* Skip any devices for which EEH is not enabled. */ |
| 192 | if (!eeh_probe_mode_dev() && !edev->pe) { | 193 | if (!edev->pe) { |
| 193 | #ifdef DEBUG | 194 | #ifdef DEBUG |
| 194 | pr_info("PCI: skip building address cache for=%s - %s\n", | 195 | pr_info("PCI: skip building address cache for=%s - %s\n", |
| 195 | pci_name(dev), dn->full_name); | 196 | pci_name(dev), dn->full_name); |
diff --git a/arch/powerpc/kernel/eeh_dev.c b/arch/powerpc/kernel/eeh_dev.c index 1efa28f5fc54..e5274ee9a75f 100644 --- a/arch/powerpc/kernel/eeh_dev.c +++ b/arch/powerpc/kernel/eeh_dev.c | |||
| @@ -57,7 +57,8 @@ void *eeh_dev_init(struct device_node *dn, void *data) | |||
| 57 | /* Allocate EEH device */ | 57 | /* Allocate EEH device */ |
| 58 | edev = kzalloc(sizeof(*edev), GFP_KERNEL); | 58 | edev = kzalloc(sizeof(*edev), GFP_KERNEL); |
| 59 | if (!edev) { | 59 | if (!edev) { |
| 60 | pr_warning("%s: out of memory\n", __func__); | 60 | pr_warn("%s: out of memory\n", |
| 61 | __func__); | ||
| 61 | return NULL; | 62 | return NULL; |
| 62 | } | 63 | } |
| 63 | 64 | ||
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c index 420da61d4ce0..6a0dcee8e931 100644 --- a/arch/powerpc/kernel/eeh_driver.c +++ b/arch/powerpc/kernel/eeh_driver.c | |||
| @@ -599,7 +599,7 @@ static void eeh_handle_normal_event(struct eeh_pe *pe) | |||
| 599 | pe->freeze_count++; | 599 | pe->freeze_count++; |
| 600 | if (pe->freeze_count > EEH_MAX_ALLOWED_FREEZES) | 600 | if (pe->freeze_count > EEH_MAX_ALLOWED_FREEZES) |
| 601 | goto excess_failures; | 601 | goto excess_failures; |
| 602 | pr_warning("EEH: This PCI device has failed %d times in the last hour\n", | 602 | pr_warn("EEH: This PCI device has failed %d times in the last hour\n", |
| 603 | pe->freeze_count); | 603 | pe->freeze_count); |
| 604 | 604 | ||
| 605 | /* Walk the various device drivers attached to this slot through | 605 | /* Walk the various device drivers attached to this slot through |
| @@ -616,7 +616,7 @@ static void eeh_handle_normal_event(struct eeh_pe *pe) | |||
| 616 | */ | 616 | */ |
| 617 | rc = eeh_ops->wait_state(pe, MAX_WAIT_FOR_RECOVERY*1000); | 617 | rc = eeh_ops->wait_state(pe, MAX_WAIT_FOR_RECOVERY*1000); |
| 618 | if (rc < 0 || rc == EEH_STATE_NOT_SUPPORT) { | 618 | if (rc < 0 || rc == EEH_STATE_NOT_SUPPORT) { |
| 619 | pr_warning("EEH: Permanent failure\n"); | 619 | pr_warn("EEH: Permanent failure\n"); |
| 620 | goto hard_fail; | 620 | goto hard_fail; |
| 621 | } | 621 | } |
| 622 | 622 | ||
| @@ -635,8 +635,8 @@ static void eeh_handle_normal_event(struct eeh_pe *pe) | |||
| 635 | pr_info("EEH: Reset with hotplug activity\n"); | 635 | pr_info("EEH: Reset with hotplug activity\n"); |
| 636 | rc = eeh_reset_device(pe, frozen_bus); | 636 | rc = eeh_reset_device(pe, frozen_bus); |
| 637 | if (rc) { | 637 | if (rc) { |
| 638 | pr_warning("%s: Unable to reset, err=%d\n", | 638 | pr_warn("%s: Unable to reset, err=%d\n", |
| 639 | __func__, rc); | 639 | __func__, rc); |
| 640 | goto hard_fail; | 640 | goto hard_fail; |
| 641 | } | 641 | } |
| 642 | } | 642 | } |
| @@ -678,7 +678,7 @@ static void eeh_handle_normal_event(struct eeh_pe *pe) | |||
| 678 | 678 | ||
| 679 | /* If any device has a hard failure, then shut off everything. */ | 679 | /* If any device has a hard failure, then shut off everything. */ |
| 680 | if (result == PCI_ERS_RESULT_DISCONNECT) { | 680 | if (result == PCI_ERS_RESULT_DISCONNECT) { |
| 681 | pr_warning("EEH: Device driver gave up\n"); | 681 | pr_warn("EEH: Device driver gave up\n"); |
| 682 | goto hard_fail; | 682 | goto hard_fail; |
| 683 | } | 683 | } |
| 684 | 684 | ||
| @@ -687,8 +687,8 @@ static void eeh_handle_normal_event(struct eeh_pe *pe) | |||
| 687 | pr_info("EEH: Reset without hotplug activity\n"); | 687 | pr_info("EEH: Reset without hotplug activity\n"); |
| 688 | rc = eeh_reset_device(pe, NULL); | 688 | rc = eeh_reset_device(pe, NULL); |
| 689 | if (rc) { | 689 | if (rc) { |
| 690 | pr_warning("%s: Cannot reset, err=%d\n", | 690 | pr_warn("%s: Cannot reset, err=%d\n", |
| 691 | __func__, rc); | 691 | __func__, rc); |
| 692 | goto hard_fail; | 692 | goto hard_fail; |
| 693 | } | 693 | } |
| 694 | 694 | ||
| @@ -701,7 +701,7 @@ static void eeh_handle_normal_event(struct eeh_pe *pe) | |||
| 701 | /* All devices should claim they have recovered by now. */ | 701 | /* All devices should claim they have recovered by now. */ |
| 702 | if ((result != PCI_ERS_RESULT_RECOVERED) && | 702 | if ((result != PCI_ERS_RESULT_RECOVERED) && |
| 703 | (result != PCI_ERS_RESULT_NONE)) { | 703 | (result != PCI_ERS_RESULT_NONE)) { |
| 704 | pr_warning("EEH: Not recovered\n"); | 704 | pr_warn("EEH: Not recovered\n"); |
| 705 | goto hard_fail; | 705 | goto hard_fail; |
| 706 | } | 706 | } |
| 707 | 707 | ||
diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c index fbd01eba4473..00e3844525a6 100644 --- a/arch/powerpc/kernel/eeh_pe.c +++ b/arch/powerpc/kernel/eeh_pe.c | |||
| @@ -32,9 +32,24 @@ | |||
| 32 | #include <asm/pci-bridge.h> | 32 | #include <asm/pci-bridge.h> |
| 33 | #include <asm/ppc-pci.h> | 33 | #include <asm/ppc-pci.h> |
| 34 | 34 | ||
| 35 | static int eeh_pe_aux_size = 0; | ||
| 35 | static LIST_HEAD(eeh_phb_pe); | 36 | static LIST_HEAD(eeh_phb_pe); |
| 36 | 37 | ||
| 37 | /** | 38 | /** |
| 39 | * eeh_set_pe_aux_size - Set PE auxillary data size | ||
| 40 | * @size: PE auxillary data size | ||
| 41 | * | ||
| 42 | * Set PE auxillary data size | ||
| 43 | */ | ||
| 44 | void eeh_set_pe_aux_size(int size) | ||
| 45 | { | ||
| 46 | if (size < 0) | ||
| 47 | return; | ||
| 48 | |||
| 49 | eeh_pe_aux_size = size; | ||
| 50 | } | ||
| 51 | |||
| 52 | /** | ||
| 38 | * eeh_pe_alloc - Allocate PE | 53 | * eeh_pe_alloc - Allocate PE |
| 39 | * @phb: PCI controller | 54 | * @phb: PCI controller |
| 40 | * @type: PE type | 55 | * @type: PE type |
| @@ -44,9 +59,16 @@ static LIST_HEAD(eeh_phb_pe); | |||
| 44 | static struct eeh_pe *eeh_pe_alloc(struct pci_controller *phb, int type) | 59 | static struct eeh_pe *eeh_pe_alloc(struct pci_controller *phb, int type) |
| 45 | { | 60 | { |
| 46 | struct eeh_pe *pe; | 61 | struct eeh_pe *pe; |
| 62 | size_t alloc_size; | ||
| 63 | |||
| 64 | alloc_size = sizeof(struct eeh_pe); | ||
| 65 | if (eeh_pe_aux_size) { | ||
| 66 | alloc_size = ALIGN(alloc_size, cache_line_size()); | ||
| 67 | alloc_size += eeh_pe_aux_size; | ||
| 68 | } | ||
| 47 | 69 | ||
| 48 | /* Allocate PHB PE */ | 70 | /* Allocate PHB PE */ |
| 49 | pe = kzalloc(sizeof(struct eeh_pe), GFP_KERNEL); | 71 | pe = kzalloc(alloc_size, GFP_KERNEL); |
| 50 | if (!pe) return NULL; | 72 | if (!pe) return NULL; |
| 51 | 73 | ||
| 52 | /* Initialize PHB PE */ | 74 | /* Initialize PHB PE */ |
| @@ -56,6 +78,8 @@ static struct eeh_pe *eeh_pe_alloc(struct pci_controller *phb, int type) | |||
| 56 | INIT_LIST_HEAD(&pe->child); | 78 | INIT_LIST_HEAD(&pe->child); |
| 57 | INIT_LIST_HEAD(&pe->edevs); | 79 | INIT_LIST_HEAD(&pe->edevs); |
| 58 | 80 | ||
| 81 | pe->data = (void *)pe + ALIGN(sizeof(struct eeh_pe), | ||
| 82 | cache_line_size()); | ||
| 59 | return pe; | 83 | return pe; |
| 60 | } | 84 | } |
| 61 | 85 | ||
| @@ -179,7 +203,8 @@ void *eeh_pe_dev_traverse(struct eeh_pe *root, | |||
| 179 | void *ret; | 203 | void *ret; |
| 180 | 204 | ||
| 181 | if (!root) { | 205 | if (!root) { |
| 182 | pr_warning("%s: Invalid PE %p\n", __func__, root); | 206 | pr_warn("%s: Invalid PE %p\n", |
| 207 | __func__, root); | ||
| 183 | return NULL; | 208 | return NULL; |
| 184 | } | 209 | } |
| 185 | 210 | ||
| @@ -351,17 +376,6 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev) | |||
| 351 | pe->config_addr = edev->config_addr; | 376 | pe->config_addr = edev->config_addr; |
| 352 | 377 | ||
| 353 | /* | 378 | /* |
| 354 | * While doing PE reset, we probably hot-reset the | ||
| 355 | * upstream bridge. However, the PCI devices including | ||
| 356 | * the associated EEH devices might be removed when EEH | ||
| 357 | * core is doing recovery. So that won't safe to retrieve | ||
| 358 | * the bridge through downstream EEH device. We have to | ||
| 359 | * trace the parent PCI bus, then the upstream bridge. | ||
| 360 | */ | ||
| 361 | if (eeh_probe_mode_dev()) | ||
| 362 | pe->bus = eeh_dev_to_pci_dev(edev)->bus; | ||
| 363 | |||
| 364 | /* | ||
| 365 | * Put the new EEH PE into hierarchy tree. If the parent | 379 | * Put the new EEH PE into hierarchy tree. If the parent |
| 366 | * can't be found, the newly created PE will be attached | 380 | * can't be found, the newly created PE will be attached |
| 367 | * to PHB directly. Otherwise, we have to associate the | 381 | * to PHB directly. Otherwise, we have to associate the |
| @@ -802,53 +816,33 @@ void eeh_pe_restore_bars(struct eeh_pe *pe) | |||
| 802 | */ | 816 | */ |
| 803 | const char *eeh_pe_loc_get(struct eeh_pe *pe) | 817 | const char *eeh_pe_loc_get(struct eeh_pe *pe) |
| 804 | { | 818 | { |
| 805 | struct pci_controller *hose; | ||
| 806 | struct pci_bus *bus = eeh_pe_bus_get(pe); | 819 | struct pci_bus *bus = eeh_pe_bus_get(pe); |
| 807 | struct pci_dev *pdev; | 820 | struct device_node *dn = pci_bus_to_OF_node(bus); |
| 808 | struct device_node *dn; | 821 | const char *loc = NULL; |
| 809 | const char *loc; | ||
| 810 | 822 | ||
| 811 | if (!bus) | 823 | if (!dn) |
| 812 | return "N/A"; | 824 | goto out; |
| 813 | 825 | ||
| 814 | /* PHB PE or root PE ? */ | 826 | /* PHB PE or root PE ? */ |
| 815 | if (pci_is_root_bus(bus)) { | 827 | if (pci_is_root_bus(bus)) { |
| 816 | hose = pci_bus_to_host(bus); | 828 | loc = of_get_property(dn, "ibm,loc-code", NULL); |
| 817 | loc = of_get_property(hose->dn, | 829 | if (!loc) |
| 818 | "ibm,loc-code", NULL); | 830 | loc = of_get_property(dn, "ibm,io-base-loc-code", NULL); |
| 819 | if (loc) | 831 | if (loc) |
| 820 | return loc; | 832 | goto out; |
| 821 | loc = of_get_property(hose->dn, | ||
| 822 | "ibm,io-base-loc-code", NULL); | ||
| 823 | if (loc) | ||
| 824 | return loc; | ||
| 825 | |||
| 826 | pdev = pci_get_slot(bus, 0x0); | ||
| 827 | } else { | ||
| 828 | pdev = bus->self; | ||
| 829 | } | ||
| 830 | |||
| 831 | if (!pdev) { | ||
| 832 | loc = "N/A"; | ||
| 833 | goto out; | ||
| 834 | } | ||
| 835 | 833 | ||
| 836 | dn = pci_device_to_OF_node(pdev); | 834 | /* Check the root port */ |
| 837 | if (!dn) { | 835 | dn = dn->child; |
| 838 | loc = "N/A"; | 836 | if (!dn) |
| 839 | goto out; | 837 | goto out; |
| 840 | } | 838 | } |
| 841 | 839 | ||
| 842 | loc = of_get_property(dn, "ibm,loc-code", NULL); | 840 | loc = of_get_property(dn, "ibm,loc-code", NULL); |
| 843 | if (!loc) | 841 | if (!loc) |
| 844 | loc = of_get_property(dn, "ibm,slot-location-code", NULL); | 842 | loc = of_get_property(dn, "ibm,slot-location-code", NULL); |
| 845 | if (!loc) | ||
| 846 | loc = "N/A"; | ||
| 847 | 843 | ||
| 848 | out: | 844 | out: |
| 849 | if (pci_is_root_bus(bus) && pdev) | 845 | return loc ? loc : "N/A"; |
| 850 | pci_dev_put(pdev); | ||
| 851 | return loc; | ||
| 852 | } | 846 | } |
| 853 | 847 | ||
| 854 | /** | 848 | /** |
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 6528c5e2cc44..5bbd1bc8c3b0 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
| @@ -482,16 +482,12 @@ END_FTR_SECTION_IFSET(CPU_FTR_STCX_CHECKS_ADDRESS) | |||
| 482 | ld r8,KSP(r4) /* new stack pointer */ | 482 | ld r8,KSP(r4) /* new stack pointer */ |
| 483 | #ifdef CONFIG_PPC_BOOK3S | 483 | #ifdef CONFIG_PPC_BOOK3S |
| 484 | BEGIN_FTR_SECTION | 484 | BEGIN_FTR_SECTION |
| 485 | BEGIN_FTR_SECTION_NESTED(95) | ||
| 486 | clrrdi r6,r8,28 /* get its ESID */ | 485 | clrrdi r6,r8,28 /* get its ESID */ |
| 487 | clrrdi r9,r1,28 /* get current sp ESID */ | 486 | clrrdi r9,r1,28 /* get current sp ESID */ |
| 488 | FTR_SECTION_ELSE_NESTED(95) | 487 | FTR_SECTION_ELSE |
| 489 | clrrdi r6,r8,40 /* get its 1T ESID */ | 488 | clrrdi r6,r8,40 /* get its 1T ESID */ |
| 490 | clrrdi r9,r1,40 /* get current sp 1T ESID */ | 489 | clrrdi r9,r1,40 /* get current sp 1T ESID */ |
| 491 | ALT_MMU_FTR_SECTION_END_NESTED_IFCLR(MMU_FTR_1T_SEGMENT, 95) | 490 | ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_1T_SEGMENT) |
| 492 | FTR_SECTION_ELSE | ||
| 493 | b 2f | ||
| 494 | ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_SLB) | ||
| 495 | clrldi. r0,r6,2 /* is new ESID c00000000? */ | 491 | clrldi. r0,r6,2 /* is new ESID c00000000? */ |
| 496 | cmpd cr1,r6,r9 /* or is new ESID the same as current ESID? */ | 492 | cmpd cr1,r6,r9 /* or is new ESID the same as current ESID? */ |
| 497 | cror eq,4*cr1+eq,eq | 493 | cror eq,4*cr1+eq,eq |
| @@ -919,6 +915,11 @@ restore_check_irq_replay: | |||
| 919 | addi r3,r1,STACK_FRAME_OVERHEAD; | 915 | addi r3,r1,STACK_FRAME_OVERHEAD; |
| 920 | bl do_IRQ | 916 | bl do_IRQ |
| 921 | b ret_from_except | 917 | b ret_from_except |
| 918 | 1: cmpwi cr0,r3,0xe60 | ||
| 919 | bne 1f | ||
| 920 | addi r3,r1,STACK_FRAME_OVERHEAD; | ||
| 921 | bl handle_hmi_exception | ||
| 922 | b ret_from_except | ||
| 922 | 1: cmpwi cr0,r3,0x900 | 923 | 1: cmpwi cr0,r3,0x900 |
| 923 | bne 1f | 924 | bne 1f |
| 924 | addi r3,r1,STACK_FRAME_OVERHEAD; | 925 | addi r3,r1,STACK_FRAME_OVERHEAD; |
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index a7d36b19221d..6144d5a6bfe7 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
| @@ -188,10 +188,6 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE) | |||
| 188 | data_access_pSeries: | 188 | data_access_pSeries: |
| 189 | HMT_MEDIUM_PPR_DISCARD | 189 | HMT_MEDIUM_PPR_DISCARD |
| 190 | SET_SCRATCH0(r13) | 190 | SET_SCRATCH0(r13) |
| 191 | BEGIN_FTR_SECTION | ||
| 192 | b data_access_check_stab | ||
| 193 | data_access_not_stab: | ||
| 194 | END_MMU_FTR_SECTION_IFCLR(MMU_FTR_SLB) | ||
| 195 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common, EXC_STD, | 191 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common, EXC_STD, |
| 196 | KVMTEST, 0x300) | 192 | KVMTEST, 0x300) |
| 197 | 193 | ||
| @@ -339,7 +335,7 @@ emulation_assist_trampoline: | |||
| 339 | hv_exception_trampoline: | 335 | hv_exception_trampoline: |
| 340 | SET_SCRATCH0(r13) | 336 | SET_SCRATCH0(r13) |
| 341 | EXCEPTION_PROLOG_0(PACA_EXGEN) | 337 | EXCEPTION_PROLOG_0(PACA_EXGEN) |
| 342 | b hmi_exception_hv | 338 | b hmi_exception_early |
| 343 | 339 | ||
| 344 | . = 0xe80 | 340 | . = 0xe80 |
| 345 | hv_doorbell_trampoline: | 341 | hv_doorbell_trampoline: |
| @@ -514,34 +510,6 @@ machine_check_pSeries_0: | |||
| 514 | EXCEPTION_PROLOG_1(PACA_EXMC, KVMTEST, 0x200) | 510 | EXCEPTION_PROLOG_1(PACA_EXMC, KVMTEST, 0x200) |
| 515 | EXCEPTION_PROLOG_PSERIES_1(machine_check_common, EXC_STD) | 511 | EXCEPTION_PROLOG_PSERIES_1(machine_check_common, EXC_STD) |
| 516 | KVM_HANDLER_SKIP(PACA_EXMC, EXC_STD, 0x200) | 512 | KVM_HANDLER_SKIP(PACA_EXMC, EXC_STD, 0x200) |
| 517 | |||
| 518 | /* moved from 0x300 */ | ||
| 519 | data_access_check_stab: | ||
| 520 | GET_PACA(r13) | ||
| 521 | std r9,PACA_EXSLB+EX_R9(r13) | ||
| 522 | std r10,PACA_EXSLB+EX_R10(r13) | ||
| 523 | mfspr r10,SPRN_DAR | ||
| 524 | mfspr r9,SPRN_DSISR | ||
| 525 | srdi r10,r10,60 | ||
| 526 | rlwimi r10,r9,16,0x20 | ||
| 527 | #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE | ||
| 528 | lbz r9,HSTATE_IN_GUEST(r13) | ||
| 529 | rlwimi r10,r9,8,0x300 | ||
| 530 | #endif | ||
| 531 | mfcr r9 | ||
| 532 | cmpwi r10,0x2c | ||
| 533 | beq do_stab_bolted_pSeries | ||
| 534 | mtcrf 0x80,r9 | ||
| 535 | ld r9,PACA_EXSLB+EX_R9(r13) | ||
| 536 | ld r10,PACA_EXSLB+EX_R10(r13) | ||
| 537 | b data_access_not_stab | ||
| 538 | do_stab_bolted_pSeries: | ||
| 539 | std r11,PACA_EXSLB+EX_R11(r13) | ||
| 540 | std r12,PACA_EXSLB+EX_R12(r13) | ||
| 541 | GET_SCRATCH0(r10) | ||
| 542 | std r10,PACA_EXSLB+EX_R13(r13) | ||
| 543 | EXCEPTION_PROLOG_PSERIES_1(do_stab_bolted, EXC_STD) | ||
| 544 | |||
| 545 | KVM_HANDLER_SKIP(PACA_EXGEN, EXC_STD, 0x300) | 513 | KVM_HANDLER_SKIP(PACA_EXGEN, EXC_STD, 0x300) |
| 546 | KVM_HANDLER_SKIP(PACA_EXSLB, EXC_STD, 0x380) | 514 | KVM_HANDLER_SKIP(PACA_EXSLB, EXC_STD, 0x380) |
| 547 | KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x400) | 515 | KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x400) |
| @@ -621,8 +589,64 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR) | |||
| 621 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe22) | 589 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe22) |
| 622 | STD_EXCEPTION_HV_OOL(0xe42, emulation_assist) | 590 | STD_EXCEPTION_HV_OOL(0xe42, emulation_assist) |
| 623 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe42) | 591 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe42) |
| 624 | STD_EXCEPTION_HV_OOL(0xe62, hmi_exception) /* need to flush cache ? */ | 592 | MASKABLE_EXCEPTION_HV_OOL(0xe62, hmi_exception) |
| 625 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe62) | 593 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe62) |
| 594 | |||
| 595 | .globl hmi_exception_early | ||
| 596 | hmi_exception_early: | ||
| 597 | EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, 0xe60) | ||
| 598 | mr r10,r1 /* Save r1 */ | ||
| 599 | ld r1,PACAEMERGSP(r13) /* Use emergency stack */ | ||
| 600 | subi r1,r1,INT_FRAME_SIZE /* alloc stack frame */ | ||
| 601 | std r9,_CCR(r1) /* save CR in stackframe */ | ||
| 602 | mfspr r11,SPRN_HSRR0 /* Save HSRR0 */ | ||
| 603 | std r11,_NIP(r1) /* save HSRR0 in stackframe */ | ||
| 604 | mfspr r12,SPRN_HSRR1 /* Save SRR1 */ | ||
| 605 | std r12,_MSR(r1) /* save SRR1 in stackframe */ | ||
| 606 | std r10,0(r1) /* make stack chain pointer */ | ||
| 607 | std r0,GPR0(r1) /* save r0 in stackframe */ | ||
| 608 | std r10,GPR1(r1) /* save r1 in stackframe */ | ||
| 609 | EXCEPTION_PROLOG_COMMON_2(PACA_EXGEN) | ||
| 610 | EXCEPTION_PROLOG_COMMON_3(0xe60) | ||
| 611 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
| 612 | bl hmi_exception_realmode | ||
| 613 | /* Windup the stack. */ | ||
| 614 | /* Clear MSR_RI before setting SRR0 and SRR1. */ | ||
| 615 | li r0,MSR_RI | ||
| 616 | mfmsr r9 /* get MSR value */ | ||
| 617 | andc r9,r9,r0 | ||
| 618 | mtmsrd r9,1 /* Clear MSR_RI */ | ||
| 619 | /* Move original HSRR0 and HSRR1 into the respective regs */ | ||
| 620 | ld r9,_MSR(r1) | ||
| 621 | mtspr SPRN_HSRR1,r9 | ||
| 622 | ld r3,_NIP(r1) | ||
| 623 | mtspr SPRN_HSRR0,r3 | ||
| 624 | ld r9,_CTR(r1) | ||
| 625 | mtctr r9 | ||
| 626 | ld r9,_XER(r1) | ||
| 627 | mtxer r9 | ||
| 628 | ld r9,_LINK(r1) | ||
| 629 | mtlr r9 | ||
| 630 | REST_GPR(0, r1) | ||
| 631 | REST_8GPRS(2, r1) | ||
| 632 | REST_GPR(10, r1) | ||
| 633 | ld r11,_CCR(r1) | ||
| 634 | mtcr r11 | ||
| 635 | REST_GPR(11, r1) | ||
| 636 | REST_2GPRS(12, r1) | ||
| 637 | /* restore original r1. */ | ||
| 638 | ld r1,GPR1(r1) | ||
| 639 | |||
| 640 | /* | ||
| 641 | * Go to virtual mode and pull the HMI event information from | ||
| 642 | * firmware. | ||
| 643 | */ | ||
| 644 | .globl hmi_exception_after_realmode | ||
| 645 | hmi_exception_after_realmode: | ||
| 646 | SET_SCRATCH0(r13) | ||
| 647 | EXCEPTION_PROLOG_0(PACA_EXGEN) | ||
| 648 | b hmi_exception_hv | ||
| 649 | |||
| 626 | MASKABLE_EXCEPTION_HV_OOL(0xe82, h_doorbell) | 650 | MASKABLE_EXCEPTION_HV_OOL(0xe82, h_doorbell) |
| 627 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe82) | 651 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe82) |
| 628 | 652 | ||
| @@ -643,6 +667,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR) | |||
| 643 | * - If it was a decrementer interrupt, we bump the dec to max and and return. | 667 | * - If it was a decrementer interrupt, we bump the dec to max and and return. |
| 644 | * - If it was a doorbell we return immediately since doorbells are edge | 668 | * - If it was a doorbell we return immediately since doorbells are edge |
| 645 | * triggered and won't automatically refire. | 669 | * triggered and won't automatically refire. |
| 670 | * - If it was a HMI we return immediately since we handled it in realmode | ||
| 671 | * and it won't refire. | ||
| 646 | * - else we hard disable and return. | 672 | * - else we hard disable and return. |
| 647 | * This is called with r10 containing the value to OR to the paca field. | 673 | * This is called with r10 containing the value to OR to the paca field. |
| 648 | */ | 674 | */ |
| @@ -660,6 +686,8 @@ masked_##_H##interrupt: \ | |||
| 660 | b 2f; \ | 686 | b 2f; \ |
| 661 | 1: cmpwi r10,PACA_IRQ_DBELL; \ | 687 | 1: cmpwi r10,PACA_IRQ_DBELL; \ |
| 662 | beq 2f; \ | 688 | beq 2f; \ |
| 689 | cmpwi r10,PACA_IRQ_HMI; \ | ||
| 690 | beq 2f; \ | ||
| 663 | mfspr r10,SPRN_##_H##SRR1; \ | 691 | mfspr r10,SPRN_##_H##SRR1; \ |
| 664 | rldicl r10,r10,48,1; /* clear MSR_EE */ \ | 692 | rldicl r10,r10,48,1; /* clear MSR_EE */ \ |
| 665 | rotldi r10,r10,16; \ | 693 | rotldi r10,r10,16; \ |
| @@ -799,7 +827,7 @@ kvmppc_skip_Hinterrupt: | |||
| 799 | STD_EXCEPTION_COMMON(0xd00, single_step, single_step_exception) | 827 | STD_EXCEPTION_COMMON(0xd00, single_step, single_step_exception) |
| 800 | STD_EXCEPTION_COMMON(0xe00, trap_0e, unknown_exception) | 828 | STD_EXCEPTION_COMMON(0xe00, trap_0e, unknown_exception) |
| 801 | STD_EXCEPTION_COMMON(0xe40, emulation_assist, emulation_assist_interrupt) | 829 | STD_EXCEPTION_COMMON(0xe40, emulation_assist, emulation_assist_interrupt) |
| 802 | STD_EXCEPTION_COMMON(0xe60, hmi_exception, unknown_exception) | 830 | STD_EXCEPTION_COMMON_ASYNC(0xe60, hmi_exception, handle_hmi_exception) |
| 803 | #ifdef CONFIG_PPC_DOORBELL | 831 | #ifdef CONFIG_PPC_DOORBELL |
| 804 | STD_EXCEPTION_COMMON_ASYNC(0xe80, h_doorbell, doorbell_exception) | 832 | STD_EXCEPTION_COMMON_ASYNC(0xe80, h_doorbell, doorbell_exception) |
| 805 | #else | 833 | #else |
| @@ -985,66 +1013,6 @@ ppc64_runlatch_on_trampoline: | |||
| 985 | b __ppc64_runlatch_on | 1013 | b __ppc64_runlatch_on |
| 986 | 1014 | ||
| 987 | /* | 1015 | /* |
| 988 | * Here we have detected that the kernel stack pointer is bad. | ||
| 989 | * R9 contains the saved CR, r13 points to the paca, | ||
| 990 | * r10 contains the (bad) kernel stack pointer, | ||
| 991 | * r11 and r12 contain the saved SRR0 and SRR1. | ||
| 992 | * We switch to using an emergency stack, save the registers there, | ||
| 993 | * and call kernel_bad_stack(), which panics. | ||
| 994 | */ | ||
| 995 | bad_stack: | ||
| 996 | ld r1,PACAEMERGSP(r13) | ||
| 997 | subi r1,r1,64+INT_FRAME_SIZE | ||
| 998 | std r9,_CCR(r1) | ||
| 999 | std r10,GPR1(r1) | ||
| 1000 | std r11,_NIP(r1) | ||
| 1001 | std r12,_MSR(r1) | ||
| 1002 | mfspr r11,SPRN_DAR | ||
| 1003 | mfspr r12,SPRN_DSISR | ||
| 1004 | std r11,_DAR(r1) | ||
| 1005 | std r12,_DSISR(r1) | ||
| 1006 | mflr r10 | ||
| 1007 | mfctr r11 | ||
| 1008 | mfxer r12 | ||
| 1009 | std r10,_LINK(r1) | ||
| 1010 | std r11,_CTR(r1) | ||
| 1011 | std r12,_XER(r1) | ||
| 1012 | SAVE_GPR(0,r1) | ||
| 1013 | SAVE_GPR(2,r1) | ||
| 1014 | ld r10,EX_R3(r3) | ||
| 1015 | std r10,GPR3(r1) | ||
| 1016 | SAVE_GPR(4,r1) | ||
| 1017 | SAVE_4GPRS(5,r1) | ||
| 1018 | ld r9,EX_R9(r3) | ||
| 1019 | ld r10,EX_R10(r3) | ||
| 1020 | SAVE_2GPRS(9,r1) | ||
| 1021 | ld r9,EX_R11(r3) | ||
| 1022 | ld r10,EX_R12(r3) | ||
| 1023 | ld r11,EX_R13(r3) | ||
| 1024 | std r9,GPR11(r1) | ||
| 1025 | std r10,GPR12(r1) | ||
| 1026 | std r11,GPR13(r1) | ||
| 1027 | BEGIN_FTR_SECTION | ||
| 1028 | ld r10,EX_CFAR(r3) | ||
| 1029 | std r10,ORIG_GPR3(r1) | ||
| 1030 | END_FTR_SECTION_IFSET(CPU_FTR_CFAR) | ||
| 1031 | SAVE_8GPRS(14,r1) | ||
| 1032 | SAVE_10GPRS(22,r1) | ||
| 1033 | lhz r12,PACA_TRAP_SAVE(r13) | ||
| 1034 | std r12,_TRAP(r1) | ||
| 1035 | addi r11,r1,INT_FRAME_SIZE | ||
| 1036 | std r11,0(r1) | ||
| 1037 | li r12,0 | ||
| 1038 | std r12,0(r11) | ||
| 1039 | ld r2,PACATOC(r13) | ||
| 1040 | ld r11,exception_marker@toc(r2) | ||
| 1041 | std r12,RESULT(r1) | ||
| 1042 | std r11,STACK_FRAME_OVERHEAD-16(r1) | ||
| 1043 | 1: addi r3,r1,STACK_FRAME_OVERHEAD | ||
| 1044 | bl kernel_bad_stack | ||
| 1045 | b 1b | ||
| 1046 | |||
| 1047 | /* | ||
| 1048 | * Here r13 points to the paca, r9 contains the saved CR, | 1016 | * Here r13 points to the paca, r9 contains the saved CR, |
| 1049 | * SRR0 and SRR1 are saved in r11 and r12, | 1017 | * SRR0 and SRR1 are saved in r11 and r12, |
| 1050 | * r9 - r13 are saved in paca->exgen. | 1018 | * r9 - r13 are saved in paca->exgen. |
| @@ -1057,7 +1025,7 @@ data_access_common: | |||
| 1057 | mfspr r10,SPRN_DSISR | 1025 | mfspr r10,SPRN_DSISR |
| 1058 | stw r10,PACA_EXGEN+EX_DSISR(r13) | 1026 | stw r10,PACA_EXGEN+EX_DSISR(r13) |
| 1059 | EXCEPTION_PROLOG_COMMON(0x300, PACA_EXGEN) | 1027 | EXCEPTION_PROLOG_COMMON(0x300, PACA_EXGEN) |
| 1060 | DISABLE_INTS | 1028 | RECONCILE_IRQ_STATE(r10, r11) |
| 1061 | ld r12,_MSR(r1) | 1029 | ld r12,_MSR(r1) |
| 1062 | ld r3,PACA_EXGEN+EX_DAR(r13) | 1030 | ld r3,PACA_EXGEN+EX_DAR(r13) |
| 1063 | lwz r4,PACA_EXGEN+EX_DSISR(r13) | 1031 | lwz r4,PACA_EXGEN+EX_DSISR(r13) |
| @@ -1073,7 +1041,7 @@ h_data_storage_common: | |||
| 1073 | stw r10,PACA_EXGEN+EX_DSISR(r13) | 1041 | stw r10,PACA_EXGEN+EX_DSISR(r13) |
| 1074 | EXCEPTION_PROLOG_COMMON(0xe00, PACA_EXGEN) | 1042 | EXCEPTION_PROLOG_COMMON(0xe00, PACA_EXGEN) |
| 1075 | bl save_nvgprs | 1043 | bl save_nvgprs |
| 1076 | DISABLE_INTS | 1044 | RECONCILE_IRQ_STATE(r10, r11) |
| 1077 | addi r3,r1,STACK_FRAME_OVERHEAD | 1045 | addi r3,r1,STACK_FRAME_OVERHEAD |
| 1078 | bl unknown_exception | 1046 | bl unknown_exception |
| 1079 | b ret_from_except | 1047 | b ret_from_except |
| @@ -1082,7 +1050,7 @@ h_data_storage_common: | |||
| 1082 | .globl instruction_access_common | 1050 | .globl instruction_access_common |
| 1083 | instruction_access_common: | 1051 | instruction_access_common: |
| 1084 | EXCEPTION_PROLOG_COMMON(0x400, PACA_EXGEN) | 1052 | EXCEPTION_PROLOG_COMMON(0x400, PACA_EXGEN) |
| 1085 | DISABLE_INTS | 1053 | RECONCILE_IRQ_STATE(r10, r11) |
| 1086 | ld r12,_MSR(r1) | 1054 | ld r12,_MSR(r1) |
| 1087 | ld r3,_NIP(r1) | 1055 | ld r3,_NIP(r1) |
| 1088 | andis. r4,r12,0x5820 | 1056 | andis. r4,r12,0x5820 |
| @@ -1146,7 +1114,7 @@ slb_miss_fault: | |||
| 1146 | 1114 | ||
| 1147 | unrecov_user_slb: | 1115 | unrecov_user_slb: |
| 1148 | EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN) | 1116 | EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN) |
| 1149 | DISABLE_INTS | 1117 | RECONCILE_IRQ_STATE(r10, r11) |
| 1150 | bl save_nvgprs | 1118 | bl save_nvgprs |
| 1151 | 1: addi r3,r1,STACK_FRAME_OVERHEAD | 1119 | 1: addi r3,r1,STACK_FRAME_OVERHEAD |
| 1152 | bl unrecoverable_exception | 1120 | bl unrecoverable_exception |
| @@ -1169,7 +1137,7 @@ machine_check_common: | |||
| 1169 | stw r10,PACA_EXGEN+EX_DSISR(r13) | 1137 | stw r10,PACA_EXGEN+EX_DSISR(r13) |
| 1170 | EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC) | 1138 | EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC) |
| 1171 | FINISH_NAP | 1139 | FINISH_NAP |
| 1172 | DISABLE_INTS | 1140 | RECONCILE_IRQ_STATE(r10, r11) |
| 1173 | ld r3,PACA_EXGEN+EX_DAR(r13) | 1141 | ld r3,PACA_EXGEN+EX_DAR(r13) |
| 1174 | lwz r4,PACA_EXGEN+EX_DSISR(r13) | 1142 | lwz r4,PACA_EXGEN+EX_DSISR(r13) |
| 1175 | std r3,_DAR(r1) | 1143 | std r3,_DAR(r1) |
| @@ -1192,7 +1160,7 @@ alignment_common: | |||
| 1192 | std r3,_DAR(r1) | 1160 | std r3,_DAR(r1) |
| 1193 | std r4,_DSISR(r1) | 1161 | std r4,_DSISR(r1) |
| 1194 | bl save_nvgprs | 1162 | bl save_nvgprs |
| 1195 | DISABLE_INTS | 1163 | RECONCILE_IRQ_STATE(r10, r11) |
| 1196 | addi r3,r1,STACK_FRAME_OVERHEAD | 1164 | addi r3,r1,STACK_FRAME_OVERHEAD |
| 1197 | bl alignment_exception | 1165 | bl alignment_exception |
| 1198 | b ret_from_except | 1166 | b ret_from_except |
| @@ -1202,7 +1170,7 @@ alignment_common: | |||
| 1202 | program_check_common: | 1170 | program_check_common: |
| 1203 | EXCEPTION_PROLOG_COMMON(0x700, PACA_EXGEN) | 1171 | EXCEPTION_PROLOG_COMMON(0x700, PACA_EXGEN) |
| 1204 | bl save_nvgprs | 1172 | bl save_nvgprs |
| 1205 | DISABLE_INTS | 1173 | RECONCILE_IRQ_STATE(r10, r11) |
| 1206 | addi r3,r1,STACK_FRAME_OVERHEAD | 1174 | addi r3,r1,STACK_FRAME_OVERHEAD |
| 1207 | bl program_check_exception | 1175 | bl program_check_exception |
| 1208 | b ret_from_except | 1176 | b ret_from_except |
| @@ -1213,7 +1181,7 @@ fp_unavailable_common: | |||
| 1213 | EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN) | 1181 | EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN) |
| 1214 | bne 1f /* if from user, just load it up */ | 1182 | bne 1f /* if from user, just load it up */ |
| 1215 | bl save_nvgprs | 1183 | bl save_nvgprs |
| 1216 | DISABLE_INTS | 1184 | RECONCILE_IRQ_STATE(r10, r11) |
| 1217 | addi r3,r1,STACK_FRAME_OVERHEAD | 1185 | addi r3,r1,STACK_FRAME_OVERHEAD |
| 1218 | bl kernel_fp_unavailable_exception | 1186 | bl kernel_fp_unavailable_exception |
| 1219 | BUG_OPCODE | 1187 | BUG_OPCODE |
| @@ -1232,7 +1200,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_TM) | |||
| 1232 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | 1200 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM |
| 1233 | 2: /* User process was in a transaction */ | 1201 | 2: /* User process was in a transaction */ |
| 1234 | bl save_nvgprs | 1202 | bl save_nvgprs |
| 1235 | DISABLE_INTS | 1203 | RECONCILE_IRQ_STATE(r10, r11) |
| 1236 | addi r3,r1,STACK_FRAME_OVERHEAD | 1204 | addi r3,r1,STACK_FRAME_OVERHEAD |
| 1237 | bl fp_unavailable_tm | 1205 | bl fp_unavailable_tm |
| 1238 | b ret_from_except | 1206 | b ret_from_except |
| @@ -1258,7 +1226,7 @@ BEGIN_FTR_SECTION | |||
| 1258 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | 1226 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM |
| 1259 | 2: /* User process was in a transaction */ | 1227 | 2: /* User process was in a transaction */ |
| 1260 | bl save_nvgprs | 1228 | bl save_nvgprs |
| 1261 | DISABLE_INTS | 1229 | RECONCILE_IRQ_STATE(r10, r11) |
| 1262 | addi r3,r1,STACK_FRAME_OVERHEAD | 1230 | addi r3,r1,STACK_FRAME_OVERHEAD |
| 1263 | bl altivec_unavailable_tm | 1231 | bl altivec_unavailable_tm |
| 1264 | b ret_from_except | 1232 | b ret_from_except |
| @@ -1267,7 +1235,7 @@ BEGIN_FTR_SECTION | |||
| 1267 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | 1235 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) |
| 1268 | #endif | 1236 | #endif |
| 1269 | bl save_nvgprs | 1237 | bl save_nvgprs |
| 1270 | DISABLE_INTS | 1238 | RECONCILE_IRQ_STATE(r10, r11) |
| 1271 | addi r3,r1,STACK_FRAME_OVERHEAD | 1239 | addi r3,r1,STACK_FRAME_OVERHEAD |
| 1272 | bl altivec_unavailable_exception | 1240 | bl altivec_unavailable_exception |
| 1273 | b ret_from_except | 1241 | b ret_from_except |
| @@ -1292,7 +1260,7 @@ BEGIN_FTR_SECTION | |||
| 1292 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | 1260 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM |
| 1293 | 2: /* User process was in a transaction */ | 1261 | 2: /* User process was in a transaction */ |
| 1294 | bl save_nvgprs | 1262 | bl save_nvgprs |
| 1295 | DISABLE_INTS | 1263 | RECONCILE_IRQ_STATE(r10, r11) |
| 1296 | addi r3,r1,STACK_FRAME_OVERHEAD | 1264 | addi r3,r1,STACK_FRAME_OVERHEAD |
| 1297 | bl vsx_unavailable_tm | 1265 | bl vsx_unavailable_tm |
| 1298 | b ret_from_except | 1266 | b ret_from_except |
| @@ -1301,7 +1269,7 @@ BEGIN_FTR_SECTION | |||
| 1301 | END_FTR_SECTION_IFSET(CPU_FTR_VSX) | 1269 | END_FTR_SECTION_IFSET(CPU_FTR_VSX) |
| 1302 | #endif | 1270 | #endif |
| 1303 | bl save_nvgprs | 1271 | bl save_nvgprs |
| 1304 | DISABLE_INTS | 1272 | RECONCILE_IRQ_STATE(r10, r11) |
| 1305 | addi r3,r1,STACK_FRAME_OVERHEAD | 1273 | addi r3,r1,STACK_FRAME_OVERHEAD |
| 1306 | bl vsx_unavailable_exception | 1274 | bl vsx_unavailable_exception |
| 1307 | b ret_from_except | 1275 | b ret_from_except |
| @@ -1338,12 +1306,6 @@ fwnmi_data_area: | |||
| 1338 | . = 0x8000 | 1306 | . = 0x8000 |
| 1339 | #endif /* defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */ | 1307 | #endif /* defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */ |
| 1340 | 1308 | ||
| 1341 | /* Space for CPU0's segment table */ | ||
| 1342 | .balign 4096 | ||
| 1343 | .globl initial_stab | ||
| 1344 | initial_stab: | ||
| 1345 | .space 4096 | ||
| 1346 | |||
| 1347 | #ifdef CONFIG_PPC_POWERNV | 1309 | #ifdef CONFIG_PPC_POWERNV |
| 1348 | _GLOBAL(opal_mc_secondary_handler) | 1310 | _GLOBAL(opal_mc_secondary_handler) |
| 1349 | HMT_MEDIUM_PPR_DISCARD | 1311 | HMT_MEDIUM_PPR_DISCARD |
| @@ -1566,7 +1528,7 @@ slb_miss_realmode: | |||
| 1566 | 1528 | ||
| 1567 | unrecov_slb: | 1529 | unrecov_slb: |
| 1568 | EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB) | 1530 | EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB) |
| 1569 | DISABLE_INTS | 1531 | RECONCILE_IRQ_STATE(r10, r11) |
| 1570 | bl save_nvgprs | 1532 | bl save_nvgprs |
| 1571 | 1: addi r3,r1,STACK_FRAME_OVERHEAD | 1533 | 1: addi r3,r1,STACK_FRAME_OVERHEAD |
| 1572 | bl unrecoverable_exception | 1534 | bl unrecoverable_exception |
| @@ -1594,12 +1556,6 @@ do_hash_page: | |||
| 1594 | bne- handle_page_fault /* if not, try to insert a HPTE */ | 1556 | bne- handle_page_fault /* if not, try to insert a HPTE */ |
| 1595 | andis. r0,r4,DSISR_DABRMATCH@h | 1557 | andis. r0,r4,DSISR_DABRMATCH@h |
| 1596 | bne- handle_dabr_fault | 1558 | bne- handle_dabr_fault |
| 1597 | |||
| 1598 | BEGIN_FTR_SECTION | ||
| 1599 | andis. r0,r4,0x0020 /* Is it a segment table fault? */ | ||
| 1600 | bne- do_ste_alloc /* If so handle it */ | ||
| 1601 | END_MMU_FTR_SECTION_IFCLR(MMU_FTR_SLB) | ||
| 1602 | |||
| 1603 | CURRENT_THREAD_INFO(r11, r1) | 1559 | CURRENT_THREAD_INFO(r11, r1) |
| 1604 | lwz r0,TI_PREEMPT(r11) /* If we're in an "NMI" */ | 1560 | lwz r0,TI_PREEMPT(r11) /* If we're in an "NMI" */ |
| 1605 | andis. r0,r0,NMI_MASK@h /* (i.e. an irq when soft-disabled) */ | 1561 | andis. r0,r0,NMI_MASK@h /* (i.e. an irq when soft-disabled) */ |
| @@ -1681,113 +1637,62 @@ handle_dabr_fault: | |||
| 1681 | bl bad_page_fault | 1637 | bl bad_page_fault |
| 1682 | b ret_from_except | 1638 | b ret_from_except |
| 1683 | 1639 | ||
| 1684 | /* here we have a segment miss */ | ||
| 1685 | do_ste_alloc: | ||
| 1686 | bl ste_allocate /* try to insert stab entry */ | ||
| 1687 | cmpdi r3,0 | ||
| 1688 | bne- handle_page_fault | ||
| 1689 | b fast_exception_return | ||
| 1690 | |||
| 1691 | /* | 1640 | /* |
| 1692 | * r13 points to the PACA, r9 contains the saved CR, | 1641 | * Here we have detected that the kernel stack pointer is bad. |
| 1642 | * R9 contains the saved CR, r13 points to the paca, | ||
| 1643 | * r10 contains the (bad) kernel stack pointer, | ||
| 1693 | * r11 and r12 contain the saved SRR0 and SRR1. | 1644 | * r11 and r12 contain the saved SRR0 and SRR1. |
| 1694 | * r9 - r13 are saved in paca->exslb. | 1645 | * We switch to using an emergency stack, save the registers there, |
| 1695 | * We assume we aren't going to take any exceptions during this procedure. | 1646 | * and call kernel_bad_stack(), which panics. |
| 1696 | * We assume (DAR >> 60) == 0xc. | ||
| 1697 | */ | 1647 | */ |
| 1698 | .align 7 | 1648 | bad_stack: |
| 1699 | do_stab_bolted: | 1649 | ld r1,PACAEMERGSP(r13) |
| 1700 | stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */ | 1650 | subi r1,r1,64+INT_FRAME_SIZE |
| 1701 | std r11,PACA_EXSLB+EX_SRR0(r13) /* save SRR0 in exc. frame */ | 1651 | std r9,_CCR(r1) |
| 1702 | mfspr r11,SPRN_DAR /* ea */ | 1652 | std r10,GPR1(r1) |
| 1703 | 1653 | std r11,_NIP(r1) | |
| 1704 | /* | 1654 | std r12,_MSR(r1) |
| 1705 | * check for bad kernel/user address | 1655 | mfspr r11,SPRN_DAR |
| 1706 | * (ea & ~REGION_MASK) >= PGTABLE_RANGE | 1656 | mfspr r12,SPRN_DSISR |
| 1707 | */ | 1657 | std r11,_DAR(r1) |
| 1708 | rldicr. r9,r11,4,(63 - 46 - 4) | 1658 | std r12,_DSISR(r1) |
| 1709 | li r9,0 /* VSID = 0 for bad address */ | 1659 | mflr r10 |
| 1710 | bne- 0f | 1660 | mfctr r11 |
| 1711 | 1661 | mfxer r12 | |
| 1712 | /* | 1662 | std r10,_LINK(r1) |
| 1713 | * Calculate VSID: | 1663 | std r11,_CTR(r1) |
| 1714 | * This is the kernel vsid, we take the top for context from | 1664 | std r12,_XER(r1) |
| 1715 | * the range. context = (MAX_USER_CONTEXT) + ((ea >> 60) - 0xc) + 1 | 1665 | SAVE_GPR(0,r1) |
| 1716 | * Here we know that (ea >> 60) == 0xc | 1666 | SAVE_GPR(2,r1) |
| 1717 | */ | 1667 | ld r10,EX_R3(r3) |
| 1718 | lis r9,(MAX_USER_CONTEXT + 1)@ha | 1668 | std r10,GPR3(r1) |
| 1719 | addi r9,r9,(MAX_USER_CONTEXT + 1)@l | 1669 | SAVE_GPR(4,r1) |
| 1720 | 1670 | SAVE_4GPRS(5,r1) | |
| 1721 | srdi r10,r11,SID_SHIFT | 1671 | ld r9,EX_R9(r3) |
| 1722 | rldimi r10,r9,ESID_BITS,0 /* proto vsid */ | 1672 | ld r10,EX_R10(r3) |
| 1723 | ASM_VSID_SCRAMBLE(r10, r9, 256M) | 1673 | SAVE_2GPRS(9,r1) |
| 1724 | rldic r9,r10,12,16 /* r9 = vsid << 12 */ | 1674 | ld r9,EX_R11(r3) |
| 1725 | 1675 | ld r10,EX_R12(r3) | |
| 1726 | 0: | 1676 | ld r11,EX_R13(r3) |
| 1727 | /* Hash to the primary group */ | 1677 | std r9,GPR11(r1) |
| 1728 | ld r10,PACASTABVIRT(r13) | 1678 | std r10,GPR12(r1) |
| 1729 | srdi r11,r11,SID_SHIFT | 1679 | std r11,GPR13(r1) |
| 1730 | rldimi r10,r11,7,52 /* r10 = first ste of the group */ | 1680 | BEGIN_FTR_SECTION |
| 1731 | 1681 | ld r10,EX_CFAR(r3) | |
| 1732 | /* Search the primary group for a free entry */ | 1682 | std r10,ORIG_GPR3(r1) |
| 1733 | 1: ld r11,0(r10) /* Test valid bit of the current ste */ | 1683 | END_FTR_SECTION_IFSET(CPU_FTR_CFAR) |
| 1734 | andi. r11,r11,0x80 | 1684 | SAVE_8GPRS(14,r1) |
| 1735 | beq 2f | 1685 | SAVE_10GPRS(22,r1) |
| 1736 | addi r10,r10,16 | 1686 | lhz r12,PACA_TRAP_SAVE(r13) |
| 1737 | andi. r11,r10,0x70 | 1687 | std r12,_TRAP(r1) |
| 1738 | bne 1b | 1688 | addi r11,r1,INT_FRAME_SIZE |
| 1739 | 1689 | std r11,0(r1) | |
| 1740 | /* Stick for only searching the primary group for now. */ | 1690 | li r12,0 |
| 1741 | /* At least for now, we use a very simple random castout scheme */ | 1691 | std r12,0(r11) |
| 1742 | /* Use the TB as a random number ; OR in 1 to avoid entry 0 */ | 1692 | ld r2,PACATOC(r13) |
| 1743 | mftb r11 | 1693 | ld r11,exception_marker@toc(r2) |
| 1744 | rldic r11,r11,4,57 /* r11 = (r11 << 4) & 0x70 */ | 1694 | std r12,RESULT(r1) |
| 1745 | ori r11,r11,0x10 | 1695 | std r11,STACK_FRAME_OVERHEAD-16(r1) |
| 1746 | 1696 | 1: addi r3,r1,STACK_FRAME_OVERHEAD | |
| 1747 | /* r10 currently points to an ste one past the group of interest */ | 1697 | bl kernel_bad_stack |
| 1748 | /* make it point to the randomly selected entry */ | 1698 | b 1b |
| 1749 | subi r10,r10,128 | ||
| 1750 | or r10,r10,r11 /* r10 is the entry to invalidate */ | ||
| 1751 | |||
| 1752 | isync /* mark the entry invalid */ | ||
| 1753 | ld r11,0(r10) | ||
| 1754 | rldicl r11,r11,56,1 /* clear the valid bit */ | ||
| 1755 | rotldi r11,r11,8 | ||
| 1756 | std r11,0(r10) | ||
| 1757 | sync | ||
| 1758 | |||
| 1759 | clrrdi r11,r11,28 /* Get the esid part of the ste */ | ||
| 1760 | slbie r11 | ||
| 1761 | |||
| 1762 | 2: std r9,8(r10) /* Store the vsid part of the ste */ | ||
| 1763 | eieio | ||
| 1764 | |||
| 1765 | mfspr r11,SPRN_DAR /* Get the new esid */ | ||
| 1766 | clrrdi r11,r11,28 /* Permits a full 32b of ESID */ | ||
| 1767 | ori r11,r11,0x90 /* Turn on valid and kp */ | ||
| 1768 | std r11,0(r10) /* Put new entry back into the stab */ | ||
| 1769 | |||
| 1770 | sync | ||
| 1771 | |||
| 1772 | /* All done -- return from exception. */ | ||
| 1773 | lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ | ||
| 1774 | ld r11,PACA_EXSLB+EX_SRR0(r13) /* get saved SRR0 */ | ||
| 1775 | |||
| 1776 | andi. r10,r12,MSR_RI | ||
| 1777 | beq- unrecov_slb | ||
| 1778 | |||
| 1779 | mtcrf 0x80,r9 /* restore CR */ | ||
| 1780 | |||
| 1781 | mfmsr r10 | ||
| 1782 | clrrdi r10,r10,2 | ||
| 1783 | mtmsrd r10,1 | ||
| 1784 | |||
| 1785 | mtspr SPRN_SRR0,r11 | ||
| 1786 | mtspr SPRN_SRR1,r12 | ||
| 1787 | ld r9,PACA_EXSLB+EX_R9(r13) | ||
| 1788 | ld r10,PACA_EXSLB+EX_R10(r13) | ||
| 1789 | ld r11,PACA_EXSLB+EX_R11(r13) | ||
| 1790 | ld r12,PACA_EXSLB+EX_R12(r13) | ||
| 1791 | ld r13,PACA_EXSLB+EX_R13(r13) | ||
| 1792 | rfid | ||
| 1793 | b . /* prevent speculative execution */ | ||
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index a95145d7f61b..d48125d0c048 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
| @@ -180,6 +180,28 @@ exception_marker: | |||
| 180 | #include "exceptions-64s.S" | 180 | #include "exceptions-64s.S" |
| 181 | #endif | 181 | #endif |
| 182 | 182 | ||
| 183 | #ifdef CONFIG_PPC_BOOK3E | ||
| 184 | _GLOBAL(fsl_secondary_thread_init) | ||
| 185 | /* Enable branch prediction */ | ||
| 186 | lis r3,BUCSR_INIT@h | ||
| 187 | ori r3,r3,BUCSR_INIT@l | ||
| 188 | mtspr SPRN_BUCSR,r3 | ||
| 189 | isync | ||
| 190 | |||
| 191 | /* | ||
| 192 | * Fix PIR to match the linear numbering in the device tree. | ||
| 193 | * | ||
| 194 | * On e6500, the reset value of PIR uses the low three bits for | ||
| 195 | * the thread within a core, and the upper bits for the core | ||
| 196 | * number. There are two threads per core, so shift everything | ||
| 197 | * but the low bit right by two bits so that the cpu numbering is | ||
| 198 | * continuous. | ||
| 199 | */ | ||
| 200 | mfspr r3, SPRN_PIR | ||
| 201 | rlwimi r3, r3, 30, 2, 30 | ||
| 202 | mtspr SPRN_PIR, r3 | ||
| 203 | #endif | ||
| 204 | |||
| 183 | _GLOBAL(generic_secondary_thread_init) | 205 | _GLOBAL(generic_secondary_thread_init) |
| 184 | mr r24,r3 | 206 | mr r24,r3 |
| 185 | 207 | ||
| @@ -618,7 +640,7 @@ __secondary_start: | |||
| 618 | addi r14,r14,THREAD_SIZE-STACK_FRAME_OVERHEAD | 640 | addi r14,r14,THREAD_SIZE-STACK_FRAME_OVERHEAD |
| 619 | std r14,PACAKSAVE(r13) | 641 | std r14,PACAKSAVE(r13) |
| 620 | 642 | ||
| 621 | /* Do early setup for that CPU (stab, slb, hash table pointer) */ | 643 | /* Do early setup for that CPU (SLB and hash table pointer) */ |
| 622 | bl early_setup_secondary | 644 | bl early_setup_secondary |
| 623 | 645 | ||
| 624 | /* | 646 | /* |
| @@ -771,8 +793,10 @@ start_here_multiplatform: | |||
| 771 | li r0,0 | 793 | li r0,0 |
| 772 | stdu r0,-STACK_FRAME_OVERHEAD(r1) | 794 | stdu r0,-STACK_FRAME_OVERHEAD(r1) |
| 773 | 795 | ||
| 774 | /* Do very early kernel initializations, including initial hash table, | 796 | /* |
| 775 | * stab and slb setup before we turn on relocation. */ | 797 | * Do very early kernel initializations, including initial hash table |
| 798 | * and SLB setup before we turn on relocation. | ||
| 799 | */ | ||
| 776 | 800 | ||
| 777 | /* Restore parameters passed from prom_init/kexec */ | 801 | /* Restore parameters passed from prom_init/kexec */ |
| 778 | mr r3,r31 | 802 | mr r3,r31 |
diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S index 5cf3d367190d..be05841396cf 100644 --- a/arch/powerpc/kernel/idle_power7.S +++ b/arch/powerpc/kernel/idle_power7.S | |||
| @@ -135,17 +135,68 @@ _GLOBAL(power7_sleep) | |||
| 135 | b power7_powersave_common | 135 | b power7_powersave_common |
| 136 | /* No return */ | 136 | /* No return */ |
| 137 | 137 | ||
| 138 | /* | ||
| 139 | * Make opal call in realmode. This is a generic function to be called | ||
| 140 | * from realmode from reset vector. It handles endianess. | ||
| 141 | * | ||
| 142 | * r13 - paca pointer | ||
| 143 | * r1 - stack pointer | ||
| 144 | * r3 - opal token | ||
| 145 | */ | ||
| 146 | opal_call_realmode: | ||
| 147 | mflr r12 | ||
| 148 | std r12,_LINK(r1) | ||
| 149 | ld r2,PACATOC(r13) | ||
| 150 | /* Set opal return address */ | ||
| 151 | LOAD_REG_ADDR(r0,return_from_opal_call) | ||
| 152 | mtlr r0 | ||
| 153 | /* Handle endian-ness */ | ||
| 154 | li r0,MSR_LE | ||
| 155 | mfmsr r12 | ||
| 156 | andc r12,r12,r0 | ||
| 157 | mtspr SPRN_HSRR1,r12 | ||
| 158 | mr r0,r3 /* Move opal token to r0 */ | ||
| 159 | LOAD_REG_ADDR(r11,opal) | ||
| 160 | ld r12,8(r11) | ||
| 161 | ld r2,0(r11) | ||
| 162 | mtspr SPRN_HSRR0,r12 | ||
| 163 | hrfid | ||
| 164 | |||
| 165 | return_from_opal_call: | ||
| 166 | FIXUP_ENDIAN | ||
| 167 | ld r0,_LINK(r1) | ||
| 168 | mtlr r0 | ||
| 169 | blr | ||
| 170 | |||
| 171 | #define CHECK_HMI_INTERRUPT \ | ||
| 172 | mfspr r0,SPRN_SRR1; \ | ||
| 173 | BEGIN_FTR_SECTION_NESTED(66); \ | ||
| 174 | rlwinm r0,r0,45-31,0xf; /* extract wake reason field (P8) */ \ | ||
| 175 | FTR_SECTION_ELSE_NESTED(66); \ | ||
| 176 | rlwinm r0,r0,45-31,0xe; /* P7 wake reason field is 3 bits */ \ | ||
| 177 | ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66); \ | ||
| 178 | cmpwi r0,0xa; /* Hypervisor maintenance ? */ \ | ||
| 179 | bne 20f; \ | ||
| 180 | /* Invoke opal call to handle hmi */ \ | ||
| 181 | ld r2,PACATOC(r13); \ | ||
| 182 | ld r1,PACAR1(r13); \ | ||
| 183 | std r3,ORIG_GPR3(r1); /* Save original r3 */ \ | ||
| 184 | li r3,OPAL_HANDLE_HMI; /* Pass opal token argument*/ \ | ||
| 185 | bl opal_call_realmode; \ | ||
| 186 | ld r3,ORIG_GPR3(r1); /* Restore original r3 */ \ | ||
| 187 | 20: nop; | ||
| 188 | |||
| 189 | |||
| 138 | _GLOBAL(power7_wakeup_tb_loss) | 190 | _GLOBAL(power7_wakeup_tb_loss) |
| 139 | ld r2,PACATOC(r13); | 191 | ld r2,PACATOC(r13); |
| 140 | ld r1,PACAR1(r13) | 192 | ld r1,PACAR1(r13) |
| 141 | 193 | ||
| 194 | BEGIN_FTR_SECTION | ||
| 195 | CHECK_HMI_INTERRUPT | ||
| 196 | END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) | ||
| 142 | /* Time base re-sync */ | 197 | /* Time base re-sync */ |
| 143 | li r0,OPAL_RESYNC_TIMEBASE | 198 | li r3,OPAL_RESYNC_TIMEBASE |
| 144 | LOAD_REG_ADDR(r11,opal); | 199 | bl opal_call_realmode; |
| 145 | ld r12,8(r11); | ||
| 146 | ld r2,0(r11); | ||
| 147 | mtctr r12 | ||
| 148 | bctrl | ||
| 149 | 200 | ||
| 150 | /* TODO: Check r3 for failure */ | 201 | /* TODO: Check r3 for failure */ |
| 151 | 202 | ||
| @@ -163,6 +214,9 @@ _GLOBAL(power7_wakeup_tb_loss) | |||
| 163 | 214 | ||
| 164 | _GLOBAL(power7_wakeup_loss) | 215 | _GLOBAL(power7_wakeup_loss) |
| 165 | ld r1,PACAR1(r13) | 216 | ld r1,PACAR1(r13) |
| 217 | BEGIN_FTR_SECTION | ||
| 218 | CHECK_HMI_INTERRUPT | ||
| 219 | END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) | ||
| 166 | REST_NVGPRS(r1) | 220 | REST_NVGPRS(r1) |
| 167 | REST_GPR(2, r1) | 221 | REST_GPR(2, r1) |
| 168 | ld r3,_CCR(r1) | 222 | ld r3,_CCR(r1) |
| @@ -178,6 +232,9 @@ _GLOBAL(power7_wakeup_noloss) | |||
| 178 | lbz r0,PACA_NAPSTATELOST(r13) | 232 | lbz r0,PACA_NAPSTATELOST(r13) |
| 179 | cmpwi r0,0 | 233 | cmpwi r0,0 |
| 180 | bne power7_wakeup_loss | 234 | bne power7_wakeup_loss |
| 235 | BEGIN_FTR_SECTION | ||
| 236 | CHECK_HMI_INTERRUPT | ||
| 237 | END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) | ||
| 181 | ld r1,PACAR1(r13) | 238 | ld r1,PACAR1(r13) |
| 182 | ld r4,_MSR(r1) | 239 | ld r4,_MSR(r1) |
| 183 | ld r5,_NIP(r1) | 240 | ld r5,_NIP(r1) |
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 88e3ec6e1d96..f84f799babb1 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c | |||
| @@ -1037,7 +1037,7 @@ int iommu_tce_build(struct iommu_table *tbl, unsigned long entry, | |||
| 1037 | 1037 | ||
| 1038 | /* if (unlikely(ret)) | 1038 | /* if (unlikely(ret)) |
| 1039 | pr_err("iommu_tce: %s failed on hwaddr=%lx ioba=%lx kva=%lx ret=%d\n", | 1039 | pr_err("iommu_tce: %s failed on hwaddr=%lx ioba=%lx kva=%lx ret=%d\n", |
| 1040 | __func__, hwaddr, entry << IOMMU_PAGE_SHIFT(tbl), | 1040 | __func__, hwaddr, entry << tbl->it_page_shift, |
| 1041 | hwaddr, ret); */ | 1041 | hwaddr, ret); */ |
| 1042 | 1042 | ||
| 1043 | return ret; | 1043 | return ret; |
| @@ -1056,7 +1056,7 @@ int iommu_put_tce_user_mode(struct iommu_table *tbl, unsigned long entry, | |||
| 1056 | direction != DMA_TO_DEVICE, &page); | 1056 | direction != DMA_TO_DEVICE, &page); |
| 1057 | if (unlikely(ret != 1)) { | 1057 | if (unlikely(ret != 1)) { |
| 1058 | /* pr_err("iommu_tce: get_user_pages_fast failed tce=%lx ioba=%lx ret=%d\n", | 1058 | /* pr_err("iommu_tce: get_user_pages_fast failed tce=%lx ioba=%lx ret=%d\n", |
| 1059 | tce, entry << IOMMU_PAGE_SHIFT(tbl), ret); */ | 1059 | tce, entry << tbl->it_page_shift, ret); */ |
| 1060 | return -EFAULT; | 1060 | return -EFAULT; |
| 1061 | } | 1061 | } |
| 1062 | hwaddr = (unsigned long) page_address(page) + offset; | 1062 | hwaddr = (unsigned long) page_address(page) + offset; |
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 248ee7e5bebd..4c5891de162e 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
| @@ -189,6 +189,11 @@ notrace unsigned int __check_irq_replay(void) | |||
| 189 | } | 189 | } |
| 190 | #endif /* CONFIG_PPC_BOOK3E */ | 190 | #endif /* CONFIG_PPC_BOOK3E */ |
| 191 | 191 | ||
| 192 | /* Check if an hypervisor Maintenance interrupt happened */ | ||
| 193 | local_paca->irq_happened &= ~PACA_IRQ_HMI; | ||
| 194 | if (happened & PACA_IRQ_HMI) | ||
| 195 | return 0xe60; | ||
| 196 | |||
| 192 | /* There should be nothing left ! */ | 197 | /* There should be nothing left ! */ |
| 193 | BUG_ON(local_paca->irq_happened != 0); | 198 | BUG_ON(local_paca->irq_happened != 0); |
| 194 | 199 | ||
| @@ -377,6 +382,14 @@ int arch_show_interrupts(struct seq_file *p, int prec) | |||
| 377 | seq_printf(p, "%10u ", per_cpu(irq_stat, j).mce_exceptions); | 382 | seq_printf(p, "%10u ", per_cpu(irq_stat, j).mce_exceptions); |
| 378 | seq_printf(p, " Machine check exceptions\n"); | 383 | seq_printf(p, " Machine check exceptions\n"); |
| 379 | 384 | ||
| 385 | if (cpu_has_feature(CPU_FTR_HVMODE)) { | ||
| 386 | seq_printf(p, "%*s: ", prec, "HMI"); | ||
| 387 | for_each_online_cpu(j) | ||
| 388 | seq_printf(p, "%10u ", | ||
| 389 | per_cpu(irq_stat, j).hmi_exceptions); | ||
| 390 | seq_printf(p, " Hypervisor Maintenance Interrupts\n"); | ||
| 391 | } | ||
| 392 | |||
| 380 | #ifdef CONFIG_PPC_DOORBELL | 393 | #ifdef CONFIG_PPC_DOORBELL |
| 381 | if (cpu_has_feature(CPU_FTR_DBELL)) { | 394 | if (cpu_has_feature(CPU_FTR_DBELL)) { |
| 382 | seq_printf(p, "%*s: ", prec, "DBL"); | 395 | seq_printf(p, "%*s: ", prec, "DBL"); |
| @@ -400,6 +413,7 @@ u64 arch_irq_stat_cpu(unsigned int cpu) | |||
| 400 | sum += per_cpu(irq_stat, cpu).mce_exceptions; | 413 | sum += per_cpu(irq_stat, cpu).mce_exceptions; |
| 401 | sum += per_cpu(irq_stat, cpu).spurious_irqs; | 414 | sum += per_cpu(irq_stat, cpu).spurious_irqs; |
| 402 | sum += per_cpu(irq_stat, cpu).timer_irqs_others; | 415 | sum += per_cpu(irq_stat, cpu).timer_irqs_others; |
| 416 | sum += per_cpu(irq_stat, cpu).hmi_exceptions; | ||
| 403 | #ifdef CONFIG_PPC_DOORBELL | 417 | #ifdef CONFIG_PPC_DOORBELL |
| 404 | sum += per_cpu(irq_stat, cpu).doorbell_irqs; | 418 | sum += per_cpu(irq_stat, cpu).doorbell_irqs; |
| 405 | #endif | 419 | #endif |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index be99774d3f44..bf44ae962ab8 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
| @@ -1095,6 +1095,23 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) | |||
| 1095 | return 0; | 1095 | return 0; |
| 1096 | } | 1096 | } |
| 1097 | 1097 | ||
| 1098 | static void setup_ksp_vsid(struct task_struct *p, unsigned long sp) | ||
| 1099 | { | ||
| 1100 | #ifdef CONFIG_PPC_STD_MMU_64 | ||
| 1101 | unsigned long sp_vsid; | ||
| 1102 | unsigned long llp = mmu_psize_defs[mmu_linear_psize].sllp; | ||
| 1103 | |||
| 1104 | if (mmu_has_feature(MMU_FTR_1T_SEGMENT)) | ||
| 1105 | sp_vsid = get_kernel_vsid(sp, MMU_SEGSIZE_1T) | ||
| 1106 | << SLB_VSID_SHIFT_1T; | ||
| 1107 | else | ||
| 1108 | sp_vsid = get_kernel_vsid(sp, MMU_SEGSIZE_256M) | ||
| 1109 | << SLB_VSID_SHIFT; | ||
| 1110 | sp_vsid |= SLB_VSID_KERNEL | llp; | ||
| 1111 | p->thread.ksp_vsid = sp_vsid; | ||
| 1112 | #endif | ||
| 1113 | } | ||
| 1114 | |||
| 1098 | /* | 1115 | /* |
| 1099 | * Copy a thread.. | 1116 | * Copy a thread.. |
| 1100 | */ | 1117 | */ |
| @@ -1174,21 +1191,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
| 1174 | p->thread.vr_save_area = NULL; | 1191 | p->thread.vr_save_area = NULL; |
| 1175 | #endif | 1192 | #endif |
| 1176 | 1193 | ||
| 1177 | #ifdef CONFIG_PPC_STD_MMU_64 | 1194 | setup_ksp_vsid(p, sp); |
| 1178 | if (mmu_has_feature(MMU_FTR_SLB)) { | ||
| 1179 | unsigned long sp_vsid; | ||
| 1180 | unsigned long llp = mmu_psize_defs[mmu_linear_psize].sllp; | ||
| 1181 | 1195 | ||
| 1182 | if (mmu_has_feature(MMU_FTR_1T_SEGMENT)) | ||
| 1183 | sp_vsid = get_kernel_vsid(sp, MMU_SEGSIZE_1T) | ||
| 1184 | << SLB_VSID_SHIFT_1T; | ||
| 1185 | else | ||
| 1186 | sp_vsid = get_kernel_vsid(sp, MMU_SEGSIZE_256M) | ||
| 1187 | << SLB_VSID_SHIFT; | ||
| 1188 | sp_vsid |= SLB_VSID_KERNEL | llp; | ||
| 1189 | p->thread.ksp_vsid = sp_vsid; | ||
| 1190 | } | ||
| 1191 | #endif /* CONFIG_PPC_STD_MMU_64 */ | ||
| 1192 | #ifdef CONFIG_PPC64 | 1196 | #ifdef CONFIG_PPC64 |
| 1193 | if (cpu_has_feature(CPU_FTR_DSCR)) { | 1197 | if (cpu_has_feature(CPU_FTR_DSCR)) { |
| 1194 | p->thread.dscr_inherit = current->thread.dscr_inherit; | 1198 | p->thread.dscr_inherit = current->thread.dscr_inherit; |
| @@ -1577,7 +1581,7 @@ void show_stack(struct task_struct *tsk, unsigned long *stack) | |||
| 1577 | struct pt_regs *regs = (struct pt_regs *) | 1581 | struct pt_regs *regs = (struct pt_regs *) |
| 1578 | (sp + STACK_FRAME_OVERHEAD); | 1582 | (sp + STACK_FRAME_OVERHEAD); |
| 1579 | lr = regs->link; | 1583 | lr = regs->link; |
| 1580 | printk("--- Exception: %lx at %pS\n LR = %pS\n", | 1584 | printk("--- interrupt: %lx at %pS\n LR = %pS\n", |
| 1581 | regs->trap, (void *)regs->nip, (void *)lr); | 1585 | regs->trap, (void *)regs->nip, (void *)lr); |
| 1582 | firstframe = 1; | 1586 | firstframe = 1; |
| 1583 | } | 1587 | } |
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index b694b0730971..1a3b1055f5eb 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
| @@ -155,7 +155,6 @@ static struct ibm_pa_feature { | |||
| 155 | } ibm_pa_features[] __initdata = { | 155 | } ibm_pa_features[] __initdata = { |
| 156 | {0, 0, PPC_FEATURE_HAS_MMU, 0, 0, 0}, | 156 | {0, 0, PPC_FEATURE_HAS_MMU, 0, 0, 0}, |
| 157 | {0, 0, PPC_FEATURE_HAS_FPU, 0, 1, 0}, | 157 | {0, 0, PPC_FEATURE_HAS_FPU, 0, 1, 0}, |
| 158 | {0, MMU_FTR_SLB, 0, 0, 2, 0}, | ||
| 159 | {CPU_FTR_CTRL, 0, 0, 0, 3, 0}, | 158 | {CPU_FTR_CTRL, 0, 0, 0, 3, 0}, |
| 160 | {CPU_FTR_NOEXECUTE, 0, 0, 0, 6, 0}, | 159 | {CPU_FTR_NOEXECUTE, 0, 0, 0, 6, 0}, |
| 161 | {CPU_FTR_NODSISRALIGN, 0, 0, 1, 1, 1}, | 160 | {CPU_FTR_NODSISRALIGN, 0, 0, 1, 1, 1}, |
| @@ -309,12 +308,10 @@ static int __init early_init_dt_scan_cpus(unsigned long node, | |||
| 309 | 308 | ||
| 310 | /* Get physical cpuid */ | 309 | /* Get physical cpuid */ |
| 311 | intserv = of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", &len); | 310 | intserv = of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", &len); |
| 312 | if (intserv) { | 311 | if (!intserv) |
| 313 | nthreads = len / sizeof(int); | 312 | intserv = of_get_flat_dt_prop(node, "reg", &len); |
| 314 | } else { | 313 | |
| 315 | intserv = of_get_flat_dt_prop(node, "reg", NULL); | 314 | nthreads = len / sizeof(int); |
| 316 | nthreads = 1; | ||
| 317 | } | ||
| 318 | 315 | ||
| 319 | /* | 316 | /* |
| 320 | * Now see if any of these threads match our boot cpu. | 317 | * Now see if any of these threads match our boot cpu. |
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index e5b022c55ccd..1b0e26013a62 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c | |||
| @@ -456,18 +456,20 @@ void __init smp_setup_cpu_maps(void) | |||
| 456 | intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s", | 456 | intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s", |
| 457 | &len); | 457 | &len); |
| 458 | if (intserv) { | 458 | if (intserv) { |
| 459 | nthreads = len / sizeof(int); | ||
| 460 | DBG(" ibm,ppc-interrupt-server#s -> %d threads\n", | 459 | DBG(" ibm,ppc-interrupt-server#s -> %d threads\n", |
| 461 | nthreads); | 460 | nthreads); |
| 462 | } else { | 461 | } else { |
| 463 | DBG(" no ibm,ppc-interrupt-server#s -> 1 thread\n"); | 462 | DBG(" no ibm,ppc-interrupt-server#s -> 1 thread\n"); |
| 464 | intserv = of_get_property(dn, "reg", NULL); | 463 | intserv = of_get_property(dn, "reg", &len); |
| 465 | if (!intserv) { | 464 | if (!intserv) { |
| 466 | cpu_be = cpu_to_be32(cpu); | 465 | cpu_be = cpu_to_be32(cpu); |
| 467 | intserv = &cpu_be; /* assume logical == phys */ | 466 | intserv = &cpu_be; /* assume logical == phys */ |
| 467 | len = 4; | ||
| 468 | } | 468 | } |
| 469 | } | 469 | } |
| 470 | 470 | ||
| 471 | nthreads = len / sizeof(int); | ||
| 472 | |||
| 471 | for (j = 0; j < nthreads && cpu < nr_cpu_ids; j++) { | 473 | for (j = 0; j < nthreads && cpu < nr_cpu_ids; j++) { |
| 472 | bool avail; | 474 | bool avail; |
| 473 | 475 | ||
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index ee082d771178..d0225572faa1 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
| @@ -201,7 +201,11 @@ static void cpu_ready_for_interrupts(void) | |||
| 201 | /* Set IR and DR in PACA MSR */ | 201 | /* Set IR and DR in PACA MSR */ |
| 202 | get_paca()->kernel_msr = MSR_KERNEL; | 202 | get_paca()->kernel_msr = MSR_KERNEL; |
| 203 | 203 | ||
| 204 | /* Enable AIL if supported */ | 204 | /* |
| 205 | * Enable AIL if supported, and we are in hypervisor mode. If we are | ||
| 206 | * not in hypervisor mode, we enable relocation-on interrupts later | ||
| 207 | * in pSeries_setup_arch() using the H_SET_MODE hcall. | ||
| 208 | */ | ||
| 205 | if (cpu_has_feature(CPU_FTR_HVMODE) && | 209 | if (cpu_has_feature(CPU_FTR_HVMODE) && |
| 206 | cpu_has_feature(CPU_FTR_ARCH_207S)) { | 210 | cpu_has_feature(CPU_FTR_ARCH_207S)) { |
| 207 | unsigned long lpcr = mfspr(SPRN_LPCR); | 211 | unsigned long lpcr = mfspr(SPRN_LPCR); |
| @@ -507,7 +511,11 @@ void __init setup_system(void) | |||
| 507 | check_smt_enabled(); | 511 | check_smt_enabled(); |
| 508 | setup_tlb_core_data(); | 512 | setup_tlb_core_data(); |
| 509 | 513 | ||
| 510 | #ifdef CONFIG_SMP | 514 | /* |
| 515 | * Freescale Book3e parts spin in a loop provided by firmware, | ||
| 516 | * so smp_release_cpus() does nothing for them | ||
| 517 | */ | ||
| 518 | #if defined(CONFIG_SMP) && !defined(CONFIG_PPC_FSL_BOOK3E) | ||
| 511 | /* Release secondary cpus out of their spinloops at 0x60 now that | 519 | /* Release secondary cpus out of their spinloops at 0x60 now that |
| 512 | * we can map physical -> logical CPU ids | 520 | * we can map physical -> logical CPU ids |
| 513 | */ | 521 | */ |
| @@ -673,9 +681,6 @@ void __init setup_arch(char **cmdline_p) | |||
| 673 | exc_lvl_early_init(); | 681 | exc_lvl_early_init(); |
| 674 | emergency_stack_init(); | 682 | emergency_stack_init(); |
| 675 | 683 | ||
| 676 | #ifdef CONFIG_PPC_STD_MMU_64 | ||
| 677 | stabs_alloc(); | ||
| 678 | #endif | ||
| 679 | /* set up the bootmem stuff with available memory */ | 684 | /* set up the bootmem stuff with available memory */ |
| 680 | do_init_bootmem(); | 685 | do_init_bootmem(); |
| 681 | sparse_init(); | 686 | sparse_init(); |
diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S index 895c50ca943c..7ab5d434e2ee 100644 --- a/arch/powerpc/kernel/systbl.S +++ b/arch/powerpc/kernel/systbl.S | |||
| @@ -39,9 +39,6 @@ | |||
| 39 | .section .rodata,"a" | 39 | .section .rodata,"a" |
| 40 | 40 | ||
| 41 | #ifdef CONFIG_PPC64 | 41 | #ifdef CONFIG_PPC64 |
| 42 | #define sys_sigpending sys_ni_syscall | ||
| 43 | #define sys_old_getrlimit sys_ni_syscall | ||
| 44 | |||
| 45 | .p2align 3 | 42 | .p2align 3 |
| 46 | #endif | 43 | #endif |
| 47 | 44 | ||
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 239f1cde3fff..0dc43f9932cf 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
| @@ -302,6 +302,16 @@ long machine_check_early(struct pt_regs *regs) | |||
| 302 | return handled; | 302 | return handled; |
| 303 | } | 303 | } |
| 304 | 304 | ||
| 305 | long hmi_exception_realmode(struct pt_regs *regs) | ||
| 306 | { | ||
| 307 | __get_cpu_var(irq_stat).hmi_exceptions++; | ||
| 308 | |||
| 309 | if (ppc_md.hmi_exception_early) | ||
| 310 | ppc_md.hmi_exception_early(regs); | ||
| 311 | |||
| 312 | return 0; | ||
| 313 | } | ||
| 314 | |||
| 305 | #endif | 315 | #endif |
| 306 | 316 | ||
| 307 | /* | 317 | /* |
| @@ -609,7 +619,7 @@ int machine_check_e500(struct pt_regs *regs) | |||
| 609 | if (reason & MCSR_BUS_RBERR) | 619 | if (reason & MCSR_BUS_RBERR) |
| 610 | printk("Bus - Read Data Bus Error\n"); | 620 | printk("Bus - Read Data Bus Error\n"); |
| 611 | if (reason & MCSR_BUS_WBERR) | 621 | if (reason & MCSR_BUS_WBERR) |
| 612 | printk("Bus - Read Data Bus Error\n"); | 622 | printk("Bus - Write Data Bus Error\n"); |
| 613 | if (reason & MCSR_BUS_IPERR) | 623 | if (reason & MCSR_BUS_IPERR) |
| 614 | printk("Bus - Instruction Parity Error\n"); | 624 | printk("Bus - Instruction Parity Error\n"); |
| 615 | if (reason & MCSR_BUS_RPERR) | 625 | if (reason & MCSR_BUS_RPERR) |
| @@ -738,6 +748,20 @@ void SMIException(struct pt_regs *regs) | |||
| 738 | die("System Management Interrupt", regs, SIGABRT); | 748 | die("System Management Interrupt", regs, SIGABRT); |
| 739 | } | 749 | } |
| 740 | 750 | ||
| 751 | void handle_hmi_exception(struct pt_regs *regs) | ||
| 752 | { | ||
| 753 | struct pt_regs *old_regs; | ||
| 754 | |||
| 755 | old_regs = set_irq_regs(regs); | ||
| 756 | irq_enter(); | ||
| 757 | |||
| 758 | if (ppc_md.handle_hmi_exception) | ||
| 759 | ppc_md.handle_hmi_exception(regs); | ||
| 760 | |||
| 761 | irq_exit(); | ||
| 762 | set_irq_regs(old_regs); | ||
| 763 | } | ||
| 764 | |||
| 741 | void unknown_exception(struct pt_regs *regs) | 765 | void unknown_exception(struct pt_regs *regs) |
| 742 | { | 766 | { |
| 743 | enum ctx_state prev_state = exception_enter(); | 767 | enum ctx_state prev_state = exception_enter(); |
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index 558a67df8126..7faf8fd05738 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S | |||
| @@ -159,6 +159,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) | |||
| 159 | cmpwi r12, BOOK3S_INTERRUPT_EXTERNAL | 159 | cmpwi r12, BOOK3S_INTERRUPT_EXTERNAL |
| 160 | BEGIN_FTR_SECTION | 160 | BEGIN_FTR_SECTION |
| 161 | beq 11f | 161 | beq 11f |
| 162 | cmpwi cr2, r12, BOOK3S_INTERRUPT_HMI | ||
| 163 | beq cr2, 14f /* HMI check */ | ||
| 162 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) | 164 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) |
| 163 | 165 | ||
| 164 | /* RFI into the highmem handler, or branch to interrupt handler */ | 166 | /* RFI into the highmem handler, or branch to interrupt handler */ |
| @@ -179,6 +181,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) | |||
| 179 | 181 | ||
| 180 | 13: b machine_check_fwnmi | 182 | 13: b machine_check_fwnmi |
| 181 | 183 | ||
| 184 | 14: mtspr SPRN_HSRR0, r8 | ||
| 185 | mtspr SPRN_HSRR1, r7 | ||
| 186 | b hmi_exception_after_realmode | ||
| 187 | |||
| 182 | kvmppc_primary_no_guest: | 188 | kvmppc_primary_no_guest: |
| 183 | /* We handle this much like a ceded vcpu */ | 189 | /* We handle this much like a ceded vcpu */ |
| 184 | /* set our bit in napping_threads */ | 190 | /* set our bit in napping_threads */ |
diff --git a/arch/powerpc/lib/copyuser_64.S b/arch/powerpc/lib/copyuser_64.S index 0860ee46013c..f09899e35991 100644 --- a/arch/powerpc/lib/copyuser_64.S +++ b/arch/powerpc/lib/copyuser_64.S | |||
| @@ -461,8 +461,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD) | |||
| 461 | /* | 461 | /* |
| 462 | * Routine to copy a whole page of data, optimized for POWER4. | 462 | * Routine to copy a whole page of data, optimized for POWER4. |
| 463 | * On POWER4 it is more than 50% faster than the simple loop | 463 | * On POWER4 it is more than 50% faster than the simple loop |
| 464 | * above (following the .Ldst_aligned label) but it runs slightly | 464 | * above (following the .Ldst_aligned label). |
| 465 | * slower on POWER3. | ||
| 466 | */ | 465 | */ |
| 467 | .Lcopy_page_4K: | 466 | .Lcopy_page_4K: |
| 468 | std r31,-32(1) | 467 | std r31,-32(1) |
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile index 51230ee6a407..d0130fff20e5 100644 --- a/arch/powerpc/mm/Makefile +++ b/arch/powerpc/mm/Makefile | |||
| @@ -13,9 +13,7 @@ obj-$(CONFIG_PPC_MMU_NOHASH) += mmu_context_nohash.o tlb_nohash.o \ | |||
| 13 | tlb_nohash_low.o | 13 | tlb_nohash_low.o |
| 14 | obj-$(CONFIG_PPC_BOOK3E) += tlb_low_$(CONFIG_WORD_SIZE)e.o | 14 | obj-$(CONFIG_PPC_BOOK3E) += tlb_low_$(CONFIG_WORD_SIZE)e.o |
| 15 | hash64-$(CONFIG_PPC_NATIVE) := hash_native_64.o | 15 | hash64-$(CONFIG_PPC_NATIVE) := hash_native_64.o |
| 16 | obj-$(CONFIG_PPC_STD_MMU_64) += hash_utils_64.o \ | 16 | obj-$(CONFIG_PPC_STD_MMU_64) += hash_utils_64.o slb_low.o slb.o $(hash64-y) |
| 17 | slb_low.o slb.o stab.o \ | ||
| 18 | $(hash64-y) | ||
| 19 | obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o | 17 | obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o |
| 20 | obj-$(CONFIG_PPC_STD_MMU) += hash_low_$(CONFIG_WORD_SIZE).o \ | 18 | obj-$(CONFIG_PPC_STD_MMU) += hash_low_$(CONFIG_WORD_SIZE).o \ |
| 21 | tlb_hash$(CONFIG_WORD_SIZE).o \ | 19 | tlb_hash$(CONFIG_WORD_SIZE).o \ |
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 88fdd9d25077..daee7f4e5a14 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
| @@ -243,7 +243,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, | |||
| 243 | } | 243 | } |
| 244 | 244 | ||
| 245 | #ifdef CONFIG_MEMORY_HOTPLUG | 245 | #ifdef CONFIG_MEMORY_HOTPLUG |
| 246 | static int htab_remove_mapping(unsigned long vstart, unsigned long vend, | 246 | int htab_remove_mapping(unsigned long vstart, unsigned long vend, |
| 247 | int psize, int ssize) | 247 | int psize, int ssize) |
| 248 | { | 248 | { |
| 249 | unsigned long vaddr; | 249 | unsigned long vaddr; |
| @@ -821,21 +821,14 @@ static void __init htab_initialize(void) | |||
| 821 | 821 | ||
| 822 | void __init early_init_mmu(void) | 822 | void __init early_init_mmu(void) |
| 823 | { | 823 | { |
| 824 | /* Setup initial STAB address in the PACA */ | ||
| 825 | get_paca()->stab_real = __pa((u64)&initial_stab); | ||
| 826 | get_paca()->stab_addr = (u64)&initial_stab; | ||
| 827 | |||
| 828 | /* Initialize the MMU Hash table and create the linear mapping | 824 | /* Initialize the MMU Hash table and create the linear mapping |
| 829 | * of memory. Has to be done before stab/slb initialization as | 825 | * of memory. Has to be done before SLB initialization as this is |
| 830 | * this is currently where the page size encoding is obtained | 826 | * currently where the page size encoding is obtained. |
| 831 | */ | 827 | */ |
| 832 | htab_initialize(); | 828 | htab_initialize(); |
| 833 | 829 | ||
| 834 | /* Initialize stab / SLB management */ | 830 | /* Initialize SLB management */ |
| 835 | if (mmu_has_feature(MMU_FTR_SLB)) | 831 | slb_initialize(); |
| 836 | slb_initialize(); | ||
| 837 | else | ||
| 838 | stab_initialize(get_paca()->stab_real); | ||
| 839 | } | 832 | } |
| 840 | 833 | ||
| 841 | #ifdef CONFIG_SMP | 834 | #ifdef CONFIG_SMP |
| @@ -845,13 +838,8 @@ void early_init_mmu_secondary(void) | |||
| 845 | if (!firmware_has_feature(FW_FEATURE_LPAR)) | 838 | if (!firmware_has_feature(FW_FEATURE_LPAR)) |
| 846 | mtspr(SPRN_SDR1, _SDR1); | 839 | mtspr(SPRN_SDR1, _SDR1); |
| 847 | 840 | ||
| 848 | /* Initialize STAB/SLB. We use a virtual address as it works | 841 | /* Initialize SLB */ |
| 849 | * in real mode on pSeries. | 842 | slb_initialize(); |
| 850 | */ | ||
| 851 | if (mmu_has_feature(MMU_FTR_SLB)) | ||
| 852 | slb_initialize(); | ||
| 853 | else | ||
| 854 | stab_initialize(get_paca()->stab_addr); | ||
| 855 | } | 843 | } |
| 856 | #endif /* CONFIG_SMP */ | 844 | #endif /* CONFIG_SMP */ |
| 857 | 845 | ||
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index e3734edffa69..253b4b971c8a 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c | |||
| @@ -175,9 +175,10 @@ static unsigned long __meminit vmemmap_section_start(unsigned long page) | |||
| 175 | static int __meminit vmemmap_populated(unsigned long start, int page_size) | 175 | static int __meminit vmemmap_populated(unsigned long start, int page_size) |
| 176 | { | 176 | { |
| 177 | unsigned long end = start + page_size; | 177 | unsigned long end = start + page_size; |
| 178 | start = (unsigned long)(pfn_to_page(vmemmap_section_start(start))); | ||
| 178 | 179 | ||
| 179 | for (; start < end; start += (PAGES_PER_SECTION * sizeof(struct page))) | 180 | for (; start < end; start += (PAGES_PER_SECTION * sizeof(struct page))) |
| 180 | if (pfn_valid(vmemmap_section_start(start))) | 181 | if (pfn_valid(page_to_pfn((struct page *)start))) |
| 181 | return 1; | 182 | return 1; |
| 182 | 183 | ||
| 183 | return 0; | 184 | return 0; |
| @@ -212,6 +213,13 @@ static void __meminit vmemmap_create_mapping(unsigned long start, | |||
| 212 | for (i = 0; i < page_size; i += PAGE_SIZE) | 213 | for (i = 0; i < page_size; i += PAGE_SIZE) |
| 213 | BUG_ON(map_kernel_page(start + i, phys, flags)); | 214 | BUG_ON(map_kernel_page(start + i, phys, flags)); |
| 214 | } | 215 | } |
| 216 | |||
| 217 | #ifdef CONFIG_MEMORY_HOTPLUG | ||
| 218 | static void vmemmap_remove_mapping(unsigned long start, | ||
| 219 | unsigned long page_size) | ||
| 220 | { | ||
| 221 | } | ||
| 222 | #endif | ||
| 215 | #else /* CONFIG_PPC_BOOK3E */ | 223 | #else /* CONFIG_PPC_BOOK3E */ |
| 216 | static void __meminit vmemmap_create_mapping(unsigned long start, | 224 | static void __meminit vmemmap_create_mapping(unsigned long start, |
| 217 | unsigned long page_size, | 225 | unsigned long page_size, |
| @@ -223,17 +231,42 @@ static void __meminit vmemmap_create_mapping(unsigned long start, | |||
| 223 | mmu_kernel_ssize); | 231 | mmu_kernel_ssize); |
| 224 | BUG_ON(mapped < 0); | 232 | BUG_ON(mapped < 0); |
| 225 | } | 233 | } |
| 234 | |||
| 235 | #ifdef CONFIG_MEMORY_HOTPLUG | ||
| 236 | extern int htab_remove_mapping(unsigned long vstart, unsigned long vend, | ||
| 237 | int psize, int ssize); | ||
| 238 | |||
| 239 | static void vmemmap_remove_mapping(unsigned long start, | ||
| 240 | unsigned long page_size) | ||
| 241 | { | ||
| 242 | int mapped = htab_remove_mapping(start, start + page_size, | ||
| 243 | mmu_vmemmap_psize, | ||
| 244 | mmu_kernel_ssize); | ||
| 245 | BUG_ON(mapped < 0); | ||
| 246 | } | ||
| 247 | #endif | ||
| 248 | |||
| 226 | #endif /* CONFIG_PPC_BOOK3E */ | 249 | #endif /* CONFIG_PPC_BOOK3E */ |
| 227 | 250 | ||
| 228 | struct vmemmap_backing *vmemmap_list; | 251 | struct vmemmap_backing *vmemmap_list; |
| 252 | static struct vmemmap_backing *next; | ||
| 253 | static int num_left; | ||
| 254 | static int num_freed; | ||
| 229 | 255 | ||
| 230 | static __meminit struct vmemmap_backing * vmemmap_list_alloc(int node) | 256 | static __meminit struct vmemmap_backing * vmemmap_list_alloc(int node) |
| 231 | { | 257 | { |
| 232 | static struct vmemmap_backing *next; | 258 | struct vmemmap_backing *vmem_back; |
| 233 | static int num_left; | 259 | /* get from freed entries first */ |
| 260 | if (num_freed) { | ||
| 261 | num_freed--; | ||
| 262 | vmem_back = next; | ||
| 263 | next = next->list; | ||
| 264 | |||
| 265 | return vmem_back; | ||
| 266 | } | ||
| 234 | 267 | ||
| 235 | /* allocate a page when required and hand out chunks */ | 268 | /* allocate a page when required and hand out chunks */ |
| 236 | if (!next || !num_left) { | 269 | if (!num_left) { |
| 237 | next = vmemmap_alloc_block(PAGE_SIZE, node); | 270 | next = vmemmap_alloc_block(PAGE_SIZE, node); |
| 238 | if (unlikely(!next)) { | 271 | if (unlikely(!next)) { |
| 239 | WARN_ON(1); | 272 | WARN_ON(1); |
| @@ -296,10 +329,85 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node) | |||
| 296 | return 0; | 329 | return 0; |
| 297 | } | 330 | } |
| 298 | 331 | ||
| 299 | void vmemmap_free(unsigned long start, unsigned long end) | 332 | #ifdef CONFIG_MEMORY_HOTPLUG |
| 333 | static unsigned long vmemmap_list_free(unsigned long start) | ||
| 300 | { | 334 | { |
| 335 | struct vmemmap_backing *vmem_back, *vmem_back_prev; | ||
| 336 | |||
| 337 | vmem_back_prev = vmem_back = vmemmap_list; | ||
| 338 | |||
| 339 | /* look for it with prev pointer recorded */ | ||
| 340 | for (; vmem_back; vmem_back = vmem_back->list) { | ||
| 341 | if (vmem_back->virt_addr == start) | ||
| 342 | break; | ||
| 343 | vmem_back_prev = vmem_back; | ||
| 344 | } | ||
| 345 | |||
| 346 | if (unlikely(!vmem_back)) { | ||
| 347 | WARN_ON(1); | ||
| 348 | return 0; | ||
| 349 | } | ||
| 350 | |||
| 351 | /* remove it from vmemmap_list */ | ||
| 352 | if (vmem_back == vmemmap_list) /* remove head */ | ||
| 353 | vmemmap_list = vmem_back->list; | ||
| 354 | else | ||
| 355 | vmem_back_prev->list = vmem_back->list; | ||
| 356 | |||
| 357 | /* next point to this freed entry */ | ||
| 358 | vmem_back->list = next; | ||
| 359 | next = vmem_back; | ||
| 360 | num_freed++; | ||
| 361 | |||
| 362 | return vmem_back->phys; | ||
| 301 | } | 363 | } |
| 302 | 364 | ||
| 365 | void __ref vmemmap_free(unsigned long start, unsigned long end) | ||
| 366 | { | ||
| 367 | unsigned long page_size = 1 << mmu_psize_defs[mmu_vmemmap_psize].shift; | ||
| 368 | |||
| 369 | start = _ALIGN_DOWN(start, page_size); | ||
| 370 | |||
| 371 | pr_debug("vmemmap_free %lx...%lx\n", start, end); | ||
| 372 | |||
| 373 | for (; start < end; start += page_size) { | ||
| 374 | unsigned long addr; | ||
| 375 | |||
| 376 | /* | ||
| 377 | * the section has already be marked as invalid, so | ||
| 378 | * vmemmap_populated() true means some other sections still | ||
| 379 | * in this page, so skip it. | ||
| 380 | */ | ||
| 381 | if (vmemmap_populated(start, page_size)) | ||
| 382 | continue; | ||
| 383 | |||
| 384 | addr = vmemmap_list_free(start); | ||
| 385 | if (addr) { | ||
| 386 | struct page *page = pfn_to_page(addr >> PAGE_SHIFT); | ||
| 387 | |||
| 388 | if (PageReserved(page)) { | ||
| 389 | /* allocated from bootmem */ | ||
| 390 | if (page_size < PAGE_SIZE) { | ||
| 391 | /* | ||
| 392 | * this shouldn't happen, but if it is | ||
| 393 | * the case, leave the memory there | ||
| 394 | */ | ||
| 395 | WARN_ON_ONCE(1); | ||
| 396 | } else { | ||
| 397 | unsigned int nr_pages = | ||
| 398 | 1 << get_order(page_size); | ||
| 399 | while (nr_pages--) | ||
| 400 | free_reserved_page(page++); | ||
| 401 | } | ||
| 402 | } else | ||
| 403 | free_pages((unsigned long)(__va(addr)), | ||
| 404 | get_order(page_size)); | ||
| 405 | |||
| 406 | vmemmap_remove_mapping(start, page_size); | ||
| 407 | } | ||
| 408 | } | ||
| 409 | } | ||
| 410 | #endif | ||
| 303 | void register_page_bootmem_memmap(unsigned long section_nr, | 411 | void register_page_bootmem_memmap(unsigned long section_nr, |
| 304 | struct page *start_page, unsigned long size) | 412 | struct page *start_page, unsigned long size) |
| 305 | { | 413 | { |
| @@ -331,16 +439,16 @@ struct page *realmode_pfn_to_page(unsigned long pfn) | |||
| 331 | if (pg_va < vmem_back->virt_addr) | 439 | if (pg_va < vmem_back->virt_addr) |
| 332 | continue; | 440 | continue; |
| 333 | 441 | ||
| 334 | /* Check that page struct is not split between real pages */ | 442 | /* After vmemmap_list entry free is possible, need check all */ |
| 335 | if ((pg_va + sizeof(struct page)) > | 443 | if ((pg_va + sizeof(struct page)) <= |
| 336 | (vmem_back->virt_addr + page_size)) | 444 | (vmem_back->virt_addr + page_size)) { |
| 337 | return NULL; | 445 | page = (struct page *) (vmem_back->phys + pg_va - |
| 338 | |||
| 339 | page = (struct page *) (vmem_back->phys + pg_va - | ||
| 340 | vmem_back->virt_addr); | 446 | vmem_back->virt_addr); |
| 341 | return page; | 447 | return page; |
| 448 | } | ||
| 342 | } | 449 | } |
| 343 | 450 | ||
| 451 | /* Probably that page struct is split between real pages */ | ||
| 344 | return NULL; | 452 | return NULL; |
| 345 | } | 453 | } |
| 346 | EXPORT_SYMBOL_GPL(realmode_pfn_to_page); | 454 | EXPORT_SYMBOL_GPL(realmode_pfn_to_page); |
diff --git a/arch/powerpc/mm/mmu_context_hash32.c b/arch/powerpc/mm/mmu_context_hash32.c index 78fef6726e10..aa5a7fd89461 100644 --- a/arch/powerpc/mm/mmu_context_hash32.c +++ b/arch/powerpc/mm/mmu_context_hash32.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * This file contains the routines for handling the MMU on those | 2 | * This file contains the routines for handling the MMU on those |
| 3 | * PowerPC implementations where the MMU substantially follows the | 3 | * PowerPC implementations where the MMU substantially follows the |
| 4 | * architecture specification. This includes the 6xx, 7xx, 7xxx, | 4 | * architecture specification. This includes the 6xx, 7xx, 7xxx, |
| 5 | * 8260, and POWER3 implementations but excludes the 8xx and 4xx. | 5 | * and 8260 implementations but excludes the 8xx and 4xx. |
| 6 | * -- paulus | 6 | * -- paulus |
| 7 | * | 7 | * |
| 8 | * Derived from arch/ppc/mm/init.c: | 8 | * Derived from arch/ppc/mm/init.c: |
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 3b181b22cd46..d3e9a78eaed3 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c | |||
| @@ -611,8 +611,8 @@ static int cpu_numa_callback(struct notifier_block *nfb, unsigned long action, | |||
| 611 | case CPU_UP_CANCELED: | 611 | case CPU_UP_CANCELED: |
| 612 | case CPU_UP_CANCELED_FROZEN: | 612 | case CPU_UP_CANCELED_FROZEN: |
| 613 | unmap_cpu_from_node(lcpu); | 613 | unmap_cpu_from_node(lcpu); |
| 614 | break; | ||
| 615 | ret = NOTIFY_OK; | 614 | ret = NOTIFY_OK; |
| 615 | break; | ||
| 616 | #endif | 616 | #endif |
| 617 | } | 617 | } |
| 618 | return ret; | 618 | return ret; |
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index 343a87fa78b5..cf11342bf519 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c | |||
| @@ -41,7 +41,7 @@ unsigned long ioremap_base; | |||
| 41 | unsigned long ioremap_bot; | 41 | unsigned long ioremap_bot; |
| 42 | EXPORT_SYMBOL(ioremap_bot); /* aka VMALLOC_END */ | 42 | EXPORT_SYMBOL(ioremap_bot); /* aka VMALLOC_END */ |
| 43 | 43 | ||
| 44 | #if defined(CONFIG_6xx) || defined(CONFIG_POWER3) | 44 | #ifdef CONFIG_6xx |
| 45 | #define HAVE_BATS 1 | 45 | #define HAVE_BATS 1 |
| 46 | #endif | 46 | #endif |
| 47 | 47 | ||
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index f6ce1f111f5b..3b3c4d34c7a0 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c | |||
| @@ -68,7 +68,7 @@ | |||
| 68 | unsigned long ioremap_bot = IOREMAP_BASE; | 68 | unsigned long ioremap_bot = IOREMAP_BASE; |
| 69 | 69 | ||
| 70 | #ifdef CONFIG_PPC_MMU_NOHASH | 70 | #ifdef CONFIG_PPC_MMU_NOHASH |
| 71 | static void *early_alloc_pgtable(unsigned long size) | 71 | static __ref void *early_alloc_pgtable(unsigned long size) |
| 72 | { | 72 | { |
| 73 | void *pt; | 73 | void *pt; |
| 74 | 74 | ||
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c index 11571e118831..5029dc19b517 100644 --- a/arch/powerpc/mm/ppc_mmu_32.c +++ b/arch/powerpc/mm/ppc_mmu_32.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * This file contains the routines for handling the MMU on those | 2 | * This file contains the routines for handling the MMU on those |
| 3 | * PowerPC implementations where the MMU substantially follows the | 3 | * PowerPC implementations where the MMU substantially follows the |
| 4 | * architecture specification. This includes the 6xx, 7xx, 7xxx, | 4 | * architecture specification. This includes the 6xx, 7xx, 7xxx, |
| 5 | * 8260, and POWER3 implementations but excludes the 8xx and 4xx. | 5 | * and 8260 implementations but excludes the 8xx and 4xx. |
| 6 | * -- paulus | 6 | * -- paulus |
| 7 | * | 7 | * |
| 8 | * Derived from arch/ppc/mm/init.c: | 8 | * Derived from arch/ppc/mm/init.c: |
diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c deleted file mode 100644 index 3f8efa6f2997..000000000000 --- a/arch/powerpc/mm/stab.c +++ /dev/null | |||
| @@ -1,286 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * PowerPC64 Segment Translation Support. | ||
| 3 | * | ||
| 4 | * Dave Engebretsen and Mike Corrigan {engebret|mikejc}@us.ibm.com | ||
| 5 | * Copyright (c) 2001 Dave Engebretsen | ||
| 6 | * | ||
| 7 | * Copyright (C) 2002 Anton Blanchard <anton@au.ibm.com>, IBM | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or | ||
| 10 | * modify it under the terms of the GNU General Public License | ||
| 11 | * as published by the Free Software Foundation; either version | ||
| 12 | * 2 of the License, or (at your option) any later version. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/memblock.h> | ||
| 16 | |||
| 17 | #include <asm/pgtable.h> | ||
| 18 | #include <asm/mmu.h> | ||
| 19 | #include <asm/mmu_context.h> | ||
| 20 | #include <asm/paca.h> | ||
| 21 | #include <asm/cputable.h> | ||
| 22 | #include <asm/prom.h> | ||
| 23 | |||
| 24 | struct stab_entry { | ||
| 25 | unsigned long esid_data; | ||
| 26 | unsigned long vsid_data; | ||
| 27 | }; | ||
| 28 | |||
| 29 | #define NR_STAB_CACHE_ENTRIES 8 | ||
| 30 | static DEFINE_PER_CPU(long, stab_cache_ptr); | ||
| 31 | static DEFINE_PER_CPU(long [NR_STAB_CACHE_ENTRIES], stab_cache); | ||
| 32 | |||
| 33 | /* | ||
| 34 | * Create a segment table entry for the given esid/vsid pair. | ||
| 35 | */ | ||
| 36 | static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid) | ||
| 37 | { | ||
| 38 | unsigned long esid_data, vsid_data; | ||
| 39 | unsigned long entry, group, old_esid, castout_entry, i; | ||
| 40 | unsigned int global_entry; | ||
| 41 | struct stab_entry *ste, *castout_ste; | ||
| 42 | unsigned long kernel_segment = (esid << SID_SHIFT) >= PAGE_OFFSET; | ||
| 43 | |||
| 44 | vsid_data = vsid << STE_VSID_SHIFT; | ||
| 45 | esid_data = esid << SID_SHIFT | STE_ESID_KP | STE_ESID_V; | ||
| 46 | if (! kernel_segment) | ||
| 47 | esid_data |= STE_ESID_KS; | ||
| 48 | |||
| 49 | /* Search the primary group first. */ | ||
| 50 | global_entry = (esid & 0x1f) << 3; | ||
| 51 | ste = (struct stab_entry *)(stab | ((esid & 0x1f) << 7)); | ||
| 52 | |||
| 53 | /* Find an empty entry, if one exists. */ | ||
| 54 | for (group = 0; group < 2; group++) { | ||
| 55 | for (entry = 0; entry < 8; entry++, ste++) { | ||
| 56 | if (!(ste->esid_data & STE_ESID_V)) { | ||
| 57 | ste->vsid_data = vsid_data; | ||
| 58 | eieio(); | ||
| 59 | ste->esid_data = esid_data; | ||
| 60 | return (global_entry | entry); | ||
| 61 | } | ||
| 62 | } | ||
| 63 | /* Now search the secondary group. */ | ||
| 64 | global_entry = ((~esid) & 0x1f) << 3; | ||
| 65 | ste = (struct stab_entry *)(stab | (((~esid) & 0x1f) << 7)); | ||
| 66 | } | ||
| 67 | |||
| 68 | /* | ||
| 69 | * Could not find empty entry, pick one with a round robin selection. | ||
| 70 | * Search all entries in the two groups. | ||
| 71 | */ | ||
| 72 | castout_entry = get_paca()->stab_rr; | ||
| 73 | for (i = 0; i < 16; i++) { | ||
| 74 | if (castout_entry < 8) { | ||
| 75 | global_entry = (esid & 0x1f) << 3; | ||
| 76 | ste = (struct stab_entry *)(stab | ((esid & 0x1f) << 7)); | ||
| 77 | castout_ste = ste + castout_entry; | ||
| 78 | } else { | ||
| 79 | global_entry = ((~esid) & 0x1f) << 3; | ||
| 80 | ste = (struct stab_entry *)(stab | (((~esid) & 0x1f) << 7)); | ||
| 81 | castout_ste = ste + (castout_entry - 8); | ||
| 82 | } | ||
| 83 | |||
| 84 | /* Dont cast out the first kernel segment */ | ||
| 85 | if ((castout_ste->esid_data & ESID_MASK) != PAGE_OFFSET) | ||
| 86 | break; | ||
| 87 | |||
| 88 | castout_entry = (castout_entry + 1) & 0xf; | ||
| 89 | } | ||
| 90 | |||
| 91 | get_paca()->stab_rr = (castout_entry + 1) & 0xf; | ||
| 92 | |||
| 93 | /* Modify the old entry to the new value. */ | ||
| 94 | |||
| 95 | /* Force previous translations to complete. DRENG */ | ||
| 96 | asm volatile("isync" : : : "memory"); | ||
| 97 | |||
| 98 | old_esid = castout_ste->esid_data >> SID_SHIFT; | ||
| 99 | castout_ste->esid_data = 0; /* Invalidate old entry */ | ||
| 100 | |||
| 101 | asm volatile("sync" : : : "memory"); /* Order update */ | ||
| 102 | |||
| 103 | castout_ste->vsid_data = vsid_data; | ||
| 104 | eieio(); /* Order update */ | ||
| 105 | castout_ste->esid_data = esid_data; | ||
| 106 | |||
| 107 | asm volatile("slbie %0" : : "r" (old_esid << SID_SHIFT)); | ||
| 108 | /* Ensure completion of slbie */ | ||
| 109 | asm volatile("sync" : : : "memory"); | ||
| 110 | |||
| 111 | return (global_entry | (castout_entry & 0x7)); | ||
| 112 | } | ||
| 113 | |||
| 114 | /* | ||
| 115 | * Allocate a segment table entry for the given ea and mm | ||
| 116 | */ | ||
| 117 | static int __ste_allocate(unsigned long ea, struct mm_struct *mm) | ||
| 118 | { | ||
| 119 | unsigned long vsid; | ||
| 120 | unsigned char stab_entry; | ||
| 121 | unsigned long offset; | ||
| 122 | |||
| 123 | /* Kernel or user address? */ | ||
| 124 | if (is_kernel_addr(ea)) { | ||
| 125 | vsid = get_kernel_vsid(ea, MMU_SEGSIZE_256M); | ||
| 126 | } else { | ||
| 127 | if ((ea >= TASK_SIZE_USER64) || (! mm)) | ||
| 128 | return 1; | ||
| 129 | |||
| 130 | vsid = get_vsid(mm->context.id, ea, MMU_SEGSIZE_256M); | ||
| 131 | } | ||
| 132 | |||
| 133 | stab_entry = make_ste(get_paca()->stab_addr, GET_ESID(ea), vsid); | ||
| 134 | |||
| 135 | if (!is_kernel_addr(ea)) { | ||
| 136 | offset = __get_cpu_var(stab_cache_ptr); | ||
| 137 | if (offset < NR_STAB_CACHE_ENTRIES) | ||
| 138 | __get_cpu_var(stab_cache[offset++]) = stab_entry; | ||
| 139 | else | ||
| 140 | offset = NR_STAB_CACHE_ENTRIES+1; | ||
| 141 | __get_cpu_var(stab_cache_ptr) = offset; | ||
| 142 | |||
| 143 | /* Order update */ | ||
| 144 | asm volatile("sync":::"memory"); | ||
| 145 | } | ||
| 146 | |||
| 147 | return 0; | ||
| 148 | } | ||
| 149 | |||
| 150 | int ste_allocate(unsigned long ea) | ||
| 151 | { | ||
| 152 | return __ste_allocate(ea, current->mm); | ||
| 153 | } | ||
| 154 | |||
| 155 | /* | ||
| 156 | * Do the segment table work for a context switch: flush all user | ||
| 157 | * entries from the table, then preload some probably useful entries | ||
| 158 | * for the new task | ||
| 159 | */ | ||
| 160 | void switch_stab(struct task_struct *tsk, struct mm_struct *mm) | ||
| 161 | { | ||
| 162 | struct stab_entry *stab = (struct stab_entry *) get_paca()->stab_addr; | ||
| 163 | struct stab_entry *ste; | ||
| 164 | unsigned long offset; | ||
| 165 | unsigned long pc = KSTK_EIP(tsk); | ||
| 166 | unsigned long stack = KSTK_ESP(tsk); | ||
| 167 | unsigned long unmapped_base; | ||
| 168 | |||
| 169 | /* Force previous translations to complete. DRENG */ | ||
| 170 | asm volatile("isync" : : : "memory"); | ||
| 171 | |||
| 172 | /* | ||
| 173 | * We need interrupts hard-disabled here, not just soft-disabled, | ||
| 174 | * so that a PMU interrupt can't occur, which might try to access | ||
| 175 | * user memory (to get a stack trace) and possible cause an STAB miss | ||
| 176 | * which would update the stab_cache/stab_cache_ptr per-cpu variables. | ||
| 177 | */ | ||
| 178 | hard_irq_disable(); | ||
| 179 | |||
| 180 | offset = __get_cpu_var(stab_cache_ptr); | ||
| 181 | if (offset <= NR_STAB_CACHE_ENTRIES) { | ||
| 182 | int i; | ||
| 183 | |||
| 184 | for (i = 0; i < offset; i++) { | ||
| 185 | ste = stab + __get_cpu_var(stab_cache[i]); | ||
| 186 | ste->esid_data = 0; /* invalidate entry */ | ||
| 187 | } | ||
| 188 | } else { | ||
| 189 | unsigned long entry; | ||
| 190 | |||
| 191 | /* Invalidate all entries. */ | ||
| 192 | ste = stab; | ||
| 193 | |||
| 194 | /* Never flush the first entry. */ | ||
| 195 | ste += 1; | ||
| 196 | for (entry = 1; | ||
| 197 | entry < (HW_PAGE_SIZE / sizeof(struct stab_entry)); | ||
| 198 | entry++, ste++) { | ||
| 199 | unsigned long ea; | ||
| 200 | ea = ste->esid_data & ESID_MASK; | ||
| 201 | if (!is_kernel_addr(ea)) { | ||
| 202 | ste->esid_data = 0; | ||
| 203 | } | ||
| 204 | } | ||
| 205 | } | ||
| 206 | |||
| 207 | asm volatile("sync; slbia; sync":::"memory"); | ||
| 208 | |||
| 209 | __get_cpu_var(stab_cache_ptr) = 0; | ||
| 210 | |||
| 211 | /* Now preload some entries for the new task */ | ||
| 212 | if (test_tsk_thread_flag(tsk, TIF_32BIT)) | ||
| 213 | unmapped_base = TASK_UNMAPPED_BASE_USER32; | ||
| 214 | else | ||
| 215 | unmapped_base = TASK_UNMAPPED_BASE_USER64; | ||
| 216 | |||
| 217 | __ste_allocate(pc, mm); | ||
| 218 | |||
| 219 | if (GET_ESID(pc) == GET_ESID(stack)) | ||
| 220 | return; | ||
| 221 | |||
| 222 | __ste_allocate(stack, mm); | ||
| 223 | |||
| 224 | if ((GET_ESID(pc) == GET_ESID(unmapped_base)) | ||
| 225 | || (GET_ESID(stack) == GET_ESID(unmapped_base))) | ||
| 226 | return; | ||
| 227 | |||
| 228 | __ste_allocate(unmapped_base, mm); | ||
| 229 | |||
| 230 | /* Order update */ | ||
| 231 | asm volatile("sync" : : : "memory"); | ||
| 232 | } | ||
| 233 | |||
| 234 | /* | ||
| 235 | * Allocate segment tables for secondary CPUs. These must all go in | ||
| 236 | * the first (bolted) segment, so that do_stab_bolted won't get a | ||
| 237 | * recursive segment miss on the segment table itself. | ||
| 238 | */ | ||
| 239 | void __init stabs_alloc(void) | ||
| 240 | { | ||
| 241 | int cpu; | ||
| 242 | |||
| 243 | if (mmu_has_feature(MMU_FTR_SLB)) | ||
| 244 | return; | ||
| 245 | |||
| 246 | for_each_possible_cpu(cpu) { | ||
| 247 | unsigned long newstab; | ||
| 248 | |||
| 249 | if (cpu == 0) | ||
| 250 | continue; /* stab for CPU 0 is statically allocated */ | ||
| 251 | |||
| 252 | newstab = memblock_alloc_base(HW_PAGE_SIZE, HW_PAGE_SIZE, | ||
| 253 | 1<<SID_SHIFT); | ||
| 254 | newstab = (unsigned long)__va(newstab); | ||
| 255 | |||
| 256 | memset((void *)newstab, 0, HW_PAGE_SIZE); | ||
| 257 | |||
| 258 | paca[cpu].stab_addr = newstab; | ||
| 259 | paca[cpu].stab_real = __pa(newstab); | ||
| 260 | printk(KERN_INFO "Segment table for CPU %d at 0x%llx " | ||
| 261 | "virtual, 0x%llx absolute\n", | ||
| 262 | cpu, paca[cpu].stab_addr, paca[cpu].stab_real); | ||
| 263 | } | ||
| 264 | } | ||
| 265 | |||
| 266 | /* | ||
| 267 | * Build an entry for the base kernel segment and put it into | ||
| 268 | * the segment table or SLB. All other segment table or SLB | ||
| 269 | * entries are faulted in. | ||
| 270 | */ | ||
| 271 | void stab_initialize(unsigned long stab) | ||
| 272 | { | ||
| 273 | unsigned long vsid = get_kernel_vsid(PAGE_OFFSET, MMU_SEGSIZE_256M); | ||
| 274 | unsigned long stabreal; | ||
| 275 | |||
| 276 | asm volatile("isync; slbia; isync":::"memory"); | ||
| 277 | make_ste(stab, GET_ESID(PAGE_OFFSET), vsid); | ||
| 278 | |||
| 279 | /* Order update */ | ||
| 280 | asm volatile("sync":::"memory"); | ||
| 281 | |||
| 282 | /* Set ASR */ | ||
| 283 | stabreal = get_paca()->stab_real | 0x1ul; | ||
| 284 | |||
| 285 | mtspr(SPRN_ASR, stabreal); | ||
| 286 | } | ||
diff --git a/arch/powerpc/mm/tlb_low_64e.S b/arch/powerpc/mm/tlb_low_64e.S index 356e8b41fb09..89bf95bd63b1 100644 --- a/arch/powerpc/mm/tlb_low_64e.S +++ b/arch/powerpc/mm/tlb_low_64e.S | |||
| @@ -296,9 +296,12 @@ itlb_miss_fault_bolted: | |||
| 296 | * r14 = page table base | 296 | * r14 = page table base |
| 297 | * r13 = PACA | 297 | * r13 = PACA |
| 298 | * r11 = tlb_per_core ptr | 298 | * r11 = tlb_per_core ptr |
| 299 | * r10 = cpu number | 299 | * r10 = crap (free to use) |
| 300 | */ | 300 | */ |
| 301 | tlb_miss_common_e6500: | 301 | tlb_miss_common_e6500: |
| 302 | crmove cr2*4+2,cr0*4+2 /* cr2.eq != 0 if kernel address */ | ||
| 303 | |||
| 304 | BEGIN_FTR_SECTION /* CPU_FTR_SMT */ | ||
| 302 | /* | 305 | /* |
| 303 | * Search if we already have an indirect entry for that virtual | 306 | * Search if we already have an indirect entry for that virtual |
| 304 | * address, and if we do, bail out. | 307 | * address, and if we do, bail out. |
| @@ -309,6 +312,7 @@ tlb_miss_common_e6500: | |||
| 309 | lhz r10,PACAPACAINDEX(r13) | 312 | lhz r10,PACAPACAINDEX(r13) |
| 310 | cmpdi r15,0 | 313 | cmpdi r15,0 |
| 311 | cmpdi cr1,r15,1 /* set cr1.eq = 0 for non-recursive */ | 314 | cmpdi cr1,r15,1 /* set cr1.eq = 0 for non-recursive */ |
| 315 | addi r10,r10,1 | ||
| 312 | bne 2f | 316 | bne 2f |
| 313 | stbcx. r10,0,r11 | 317 | stbcx. r10,0,r11 |
| 314 | bne 1b | 318 | bne 1b |
| @@ -322,18 +326,62 @@ tlb_miss_common_e6500: | |||
| 322 | b 1b | 326 | b 1b |
| 323 | .previous | 327 | .previous |
| 324 | 328 | ||
| 329 | /* | ||
| 330 | * Erratum A-008139 says that we can't use tlbwe to change | ||
| 331 | * an indirect entry in any way (including replacing or | ||
| 332 | * invalidating) if the other thread could be in the process | ||
| 333 | * of a lookup. The workaround is to invalidate the entry | ||
| 334 | * with tlbilx before overwriting. | ||
| 335 | */ | ||
| 336 | |||
| 337 | lbz r15,TCD_ESEL_NEXT(r11) | ||
| 338 | rlwinm r10,r15,16,0xff0000 | ||
| 339 | oris r10,r10,MAS0_TLBSEL(1)@h | ||
| 340 | mtspr SPRN_MAS0,r10 | ||
| 341 | isync | ||
| 342 | tlbre | ||
| 343 | mfspr r15,SPRN_MAS1 | ||
| 344 | andis. r15,r15,MAS1_VALID@h | ||
| 345 | beq 5f | ||
| 346 | |||
| 347 | BEGIN_FTR_SECTION_NESTED(532) | ||
| 348 | mfspr r10,SPRN_MAS8 | ||
| 349 | rlwinm r10,r10,0,0x80000fff /* tgs,tlpid -> sgs,slpid */ | ||
| 350 | mtspr SPRN_MAS5,r10 | ||
| 351 | END_FTR_SECTION_NESTED(CPU_FTR_EMB_HV,CPU_FTR_EMB_HV,532) | ||
| 352 | |||
| 353 | mfspr r10,SPRN_MAS1 | ||
| 354 | rlwinm r15,r10,0,0x3fff0000 /* tid -> spid */ | ||
| 355 | rlwimi r15,r10,20,0x00000003 /* ind,ts -> sind,sas */ | ||
| 356 | mfspr r10,SPRN_MAS6 | ||
| 357 | mtspr SPRN_MAS6,r15 | ||
| 358 | |||
| 325 | mfspr r15,SPRN_MAS2 | 359 | mfspr r15,SPRN_MAS2 |
| 360 | isync | ||
| 361 | tlbilxva 0,r15 | ||
| 362 | isync | ||
| 363 | |||
| 364 | mtspr SPRN_MAS6,r10 | ||
| 365 | |||
| 366 | 5: | ||
| 367 | BEGIN_FTR_SECTION_NESTED(532) | ||
| 368 | li r10,0 | ||
| 369 | mtspr SPRN_MAS8,r10 | ||
| 370 | mtspr SPRN_MAS5,r10 | ||
| 371 | END_FTR_SECTION_NESTED(CPU_FTR_EMB_HV,CPU_FTR_EMB_HV,532) | ||
| 326 | 372 | ||
| 327 | tlbsx 0,r16 | 373 | tlbsx 0,r16 |
| 328 | mfspr r10,SPRN_MAS1 | 374 | mfspr r10,SPRN_MAS1 |
| 329 | andis. r10,r10,MAS1_VALID@h | 375 | andis. r15,r10,MAS1_VALID@h |
| 330 | bne tlb_miss_done_e6500 | 376 | bne tlb_miss_done_e6500 |
| 331 | 377 | FTR_SECTION_ELSE | |
| 332 | /* Undo MAS-damage from the tlbsx */ | ||
| 333 | mfspr r10,SPRN_MAS1 | 378 | mfspr r10,SPRN_MAS1 |
| 379 | ALT_FTR_SECTION_END_IFSET(CPU_FTR_SMT) | ||
| 380 | |||
| 334 | oris r10,r10,MAS1_VALID@h | 381 | oris r10,r10,MAS1_VALID@h |
| 335 | mtspr SPRN_MAS1,r10 | 382 | beq cr2,4f |
| 336 | mtspr SPRN_MAS2,r15 | 383 | rlwinm r10,r10,0,16,1 /* Clear TID */ |
| 384 | 4: mtspr SPRN_MAS1,r10 | ||
| 337 | 385 | ||
| 338 | /* Now, we need to walk the page tables. First check if we are in | 386 | /* Now, we need to walk the page tables. First check if we are in |
| 339 | * range. | 387 | * range. |
| @@ -394,11 +442,13 @@ tlb_miss_common_e6500: | |||
| 394 | 442 | ||
| 395 | tlb_miss_done_e6500: | 443 | tlb_miss_done_e6500: |
| 396 | .macro tlb_unlock_e6500 | 444 | .macro tlb_unlock_e6500 |
| 445 | BEGIN_FTR_SECTION | ||
| 397 | beq cr1,1f /* no unlock if lock was recursively grabbed */ | 446 | beq cr1,1f /* no unlock if lock was recursively grabbed */ |
| 398 | li r15,0 | 447 | li r15,0 |
| 399 | isync | 448 | isync |
| 400 | stb r15,0(r11) | 449 | stb r15,0(r11) |
| 401 | 1: | 450 | 1: |
| 451 | END_FTR_SECTION_IFSET(CPU_FTR_SMT) | ||
| 402 | .endm | 452 | .endm |
| 403 | 453 | ||
| 404 | tlb_unlock_e6500 | 454 | tlb_unlock_e6500 |
| @@ -407,12 +457,9 @@ tlb_miss_done_e6500: | |||
| 407 | rfi | 457 | rfi |
| 408 | 458 | ||
| 409 | tlb_miss_kernel_e6500: | 459 | tlb_miss_kernel_e6500: |
| 410 | mfspr r10,SPRN_MAS1 | ||
| 411 | ld r14,PACA_KERNELPGD(r13) | 460 | ld r14,PACA_KERNELPGD(r13) |
| 412 | cmpldi cr0,r15,8 /* Check for vmalloc region */ | 461 | cmpldi cr1,r15,8 /* Check for vmalloc region */ |
| 413 | rlwinm r10,r10,0,16,1 /* Clear TID */ | 462 | beq+ cr1,tlb_miss_common_e6500 |
| 414 | mtspr SPRN_MAS1,r10 | ||
| 415 | beq+ tlb_miss_common_e6500 | ||
| 416 | 463 | ||
| 417 | tlb_miss_fault_e6500: | 464 | tlb_miss_fault_e6500: |
| 418 | tlb_unlock_e6500 | 465 | tlb_unlock_e6500 |
diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile index 751ec7bd5018..cedbbeced632 100644 --- a/arch/powerpc/oprofile/Makefile +++ b/arch/powerpc/oprofile/Makefile | |||
| @@ -14,6 +14,6 @@ oprofile-y := $(DRIVER_OBJS) common.o backtrace.o | |||
| 14 | oprofile-$(CONFIG_OPROFILE_CELL) += op_model_cell.o \ | 14 | oprofile-$(CONFIG_OPROFILE_CELL) += op_model_cell.o \ |
| 15 | cell/spu_profiler.o cell/vma_map.o \ | 15 | cell/spu_profiler.o cell/vma_map.o \ |
| 16 | cell/spu_task_sync.o | 16 | cell/spu_task_sync.o |
| 17 | oprofile-$(CONFIG_PPC_BOOK3S_64) += op_model_rs64.o op_model_power4.o op_model_pa6t.o | 17 | oprofile-$(CONFIG_PPC_BOOK3S_64) += op_model_power4.o op_model_pa6t.o |
| 18 | oprofile-$(CONFIG_FSL_EMB_PERFMON) += op_model_fsl_emb.o | 18 | oprofile-$(CONFIG_FSL_EMB_PERFMON) += op_model_fsl_emb.o |
| 19 | oprofile-$(CONFIG_6xx) += op_model_7450.o | 19 | oprofile-$(CONFIG_6xx) += op_model_7450.o |
diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c index c77348c5d463..bf094c5a4bd9 100644 --- a/arch/powerpc/oprofile/common.c +++ b/arch/powerpc/oprofile/common.c | |||
| @@ -205,9 +205,6 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) | |||
| 205 | ops->sync_stop = model->sync_stop; | 205 | ops->sync_stop = model->sync_stop; |
| 206 | break; | 206 | break; |
| 207 | #endif | 207 | #endif |
| 208 | case PPC_OPROFILE_RS64: | ||
| 209 | model = &op_model_rs64; | ||
| 210 | break; | ||
| 211 | case PPC_OPROFILE_POWER4: | 208 | case PPC_OPROFILE_POWER4: |
| 212 | model = &op_model_power4; | 209 | model = &op_model_power4; |
| 213 | break; | 210 | break; |
diff --git a/arch/powerpc/oprofile/op_model_rs64.c b/arch/powerpc/oprofile/op_model_rs64.c deleted file mode 100644 index 7e5b8ed3a1b7..000000000000 --- a/arch/powerpc/oprofile/op_model_rs64.c +++ /dev/null | |||
| @@ -1,222 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or | ||
| 5 | * modify it under the terms of the GNU General Public License | ||
| 6 | * as published by the Free Software Foundation; either version | ||
| 7 | * 2 of the License, or (at your option) any later version. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/oprofile.h> | ||
| 11 | #include <linux/smp.h> | ||
| 12 | #include <asm/ptrace.h> | ||
| 13 | #include <asm/processor.h> | ||
| 14 | #include <asm/cputable.h> | ||
| 15 | #include <asm/oprofile_impl.h> | ||
| 16 | |||
| 17 | #define dbg(args...) | ||
| 18 | |||
| 19 | static void ctrl_write(unsigned int i, unsigned int val) | ||
| 20 | { | ||
| 21 | unsigned int tmp = 0; | ||
| 22 | unsigned long shift = 0, mask = 0; | ||
| 23 | |||
| 24 | dbg("ctrl_write %d %x\n", i, val); | ||
| 25 | |||
| 26 | switch(i) { | ||
| 27 | case 0: | ||
| 28 | tmp = mfspr(SPRN_MMCR0); | ||
| 29 | shift = 6; | ||
| 30 | mask = 0x7F; | ||
| 31 | break; | ||
| 32 | case 1: | ||
| 33 | tmp = mfspr(SPRN_MMCR0); | ||
| 34 | shift = 0; | ||
| 35 | mask = 0x3F; | ||
| 36 | break; | ||
| 37 | case 2: | ||
| 38 | tmp = mfspr(SPRN_MMCR1); | ||
| 39 | shift = 31 - 4; | ||
| 40 | mask = 0x1F; | ||
| 41 | break; | ||
| 42 | case 3: | ||
| 43 | tmp = mfspr(SPRN_MMCR1); | ||
| 44 | shift = 31 - 9; | ||
| 45 | mask = 0x1F; | ||
| 46 | break; | ||
| 47 | case 4: | ||
| 48 | tmp = mfspr(SPRN_MMCR1); | ||
| 49 | shift = 31 - 14; | ||
| 50 | mask = 0x1F; | ||
| 51 | break; | ||
| 52 | case 5: | ||
| 53 | tmp = mfspr(SPRN_MMCR1); | ||
| 54 | shift = 31 - 19; | ||
| 55 | mask = 0x1F; | ||
| 56 | break; | ||
| 57 | case 6: | ||
| 58 | tmp = mfspr(SPRN_MMCR1); | ||
| 59 | shift = 31 - 24; | ||
| 60 | mask = 0x1F; | ||
| 61 | break; | ||
| 62 | case 7: | ||
| 63 | tmp = mfspr(SPRN_MMCR1); | ||
| 64 | shift = 31 - 28; | ||
| 65 | mask = 0xF; | ||
| 66 | break; | ||
| 67 | } | ||
| 68 | |||
| 69 | tmp = tmp & ~(mask << shift); | ||
| 70 | tmp |= val << shift; | ||
| 71 | |||
| 72 | switch(i) { | ||
| 73 | case 0: | ||
| 74 | case 1: | ||
| 75 | mtspr(SPRN_MMCR0, tmp); | ||
| 76 | break; | ||
| 77 | default: | ||
| 78 | mtspr(SPRN_MMCR1, tmp); | ||
| 79 | } | ||
| 80 | |||
| 81 | dbg("ctrl_write mmcr0 %lx mmcr1 %lx\n", mfspr(SPRN_MMCR0), | ||
| 82 | mfspr(SPRN_MMCR1)); | ||
| 83 | } | ||
| 84 | |||
| 85 | static unsigned long reset_value[OP_MAX_COUNTER]; | ||
| 86 | |||
| 87 | static int num_counters; | ||
| 88 | |||
| 89 | static int rs64_reg_setup(struct op_counter_config *ctr, | ||
| 90 | struct op_system_config *sys, | ||
| 91 | int num_ctrs) | ||
| 92 | { | ||
| 93 | int i; | ||
| 94 | |||
| 95 | num_counters = num_ctrs; | ||
| 96 | |||
| 97 | for (i = 0; i < num_counters; ++i) | ||
| 98 | reset_value[i] = 0x80000000UL - ctr[i].count; | ||
| 99 | |||
| 100 | /* XXX setup user and kernel profiling */ | ||
| 101 | return 0; | ||
| 102 | } | ||
| 103 | |||
| 104 | static int rs64_cpu_setup(struct op_counter_config *ctr) | ||
| 105 | { | ||
| 106 | unsigned int mmcr0; | ||
| 107 | |||
| 108 | /* reset MMCR0 and set the freeze bit */ | ||
| 109 | mmcr0 = MMCR0_FC; | ||
| 110 | mtspr(SPRN_MMCR0, mmcr0); | ||
| 111 | |||
| 112 | /* reset MMCR1, MMCRA */ | ||
| 113 | mtspr(SPRN_MMCR1, 0); | ||
| 114 | |||
| 115 | if (cpu_has_feature(CPU_FTR_MMCRA)) | ||
| 116 | mtspr(SPRN_MMCRA, 0); | ||
| 117 | |||
| 118 | mmcr0 |= MMCR0_FCM1|MMCR0_PMXE|MMCR0_FCECE; | ||
| 119 | /* Only applies to POWER3, but should be safe on RS64 */ | ||
| 120 | mmcr0 |= MMCR0_PMC1CE|MMCR0_PMCjCE; | ||
| 121 | mtspr(SPRN_MMCR0, mmcr0); | ||
| 122 | |||
| 123 | dbg("setup on cpu %d, mmcr0 %lx\n", smp_processor_id(), | ||
| 124 | mfspr(SPRN_MMCR0)); | ||
| 125 | dbg("setup on cpu %d, mmcr1 %lx\n", smp_processor_id(), | ||
| 126 | mfspr(SPRN_MMCR1)); | ||
| 127 | |||
| 128 | return 0; | ||
| 129 | } | ||
| 130 | |||
| 131 | static int rs64_start(struct op_counter_config *ctr) | ||
| 132 | { | ||
| 133 | int i; | ||
| 134 | unsigned int mmcr0; | ||
| 135 | |||
| 136 | /* set the PMM bit (see comment below) */ | ||
| 137 | mtmsrd(mfmsr() | MSR_PMM); | ||
| 138 | |||
| 139 | for (i = 0; i < num_counters; ++i) { | ||
| 140 | if (ctr[i].enabled) { | ||
| 141 | classic_ctr_write(i, reset_value[i]); | ||
| 142 | ctrl_write(i, ctr[i].event); | ||
| 143 | } else { | ||
| 144 | classic_ctr_write(i, 0); | ||
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | mmcr0 = mfspr(SPRN_MMCR0); | ||
| 149 | |||
| 150 | /* | ||
| 151 | * now clear the freeze bit, counting will not start until we | ||
| 152 | * rfid from this excetion, because only at that point will | ||
| 153 | * the PMM bit be cleared | ||
| 154 | */ | ||
| 155 | mmcr0 &= ~MMCR0_FC; | ||
| 156 | mtspr(SPRN_MMCR0, mmcr0); | ||
| 157 | |||
| 158 | dbg("start on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0); | ||
| 159 | return 0; | ||
| 160 | } | ||
| 161 | |||
| 162 | static void rs64_stop(void) | ||
| 163 | { | ||
| 164 | unsigned int mmcr0; | ||
| 165 | |||
| 166 | /* freeze counters */ | ||
| 167 | mmcr0 = mfspr(SPRN_MMCR0); | ||
| 168 | mmcr0 |= MMCR0_FC; | ||
| 169 | mtspr(SPRN_MMCR0, mmcr0); | ||
| 170 | |||
| 171 | dbg("stop on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0); | ||
| 172 | |||
| 173 | mb(); | ||
| 174 | } | ||
| 175 | |||
| 176 | static void rs64_handle_interrupt(struct pt_regs *regs, | ||
| 177 | struct op_counter_config *ctr) | ||
| 178 | { | ||
| 179 | unsigned int mmcr0; | ||
| 180 | int is_kernel; | ||
| 181 | int val; | ||
| 182 | int i; | ||
| 183 | unsigned long pc = mfspr(SPRN_SIAR); | ||
| 184 | |||
| 185 | is_kernel = is_kernel_addr(pc); | ||
| 186 | |||
| 187 | /* set the PMM bit (see comment below) */ | ||
| 188 | mtmsrd(mfmsr() | MSR_PMM); | ||
| 189 | |||
| 190 | for (i = 0; i < num_counters; ++i) { | ||
| 191 | val = classic_ctr_read(i); | ||
| 192 | if (val < 0) { | ||
| 193 | if (ctr[i].enabled) { | ||
| 194 | oprofile_add_ext_sample(pc, regs, i, is_kernel); | ||
| 195 | classic_ctr_write(i, reset_value[i]); | ||
| 196 | } else { | ||
| 197 | classic_ctr_write(i, 0); | ||
| 198 | } | ||
| 199 | } | ||
| 200 | } | ||
| 201 | |||
| 202 | mmcr0 = mfspr(SPRN_MMCR0); | ||
| 203 | |||
| 204 | /* reset the perfmon trigger */ | ||
| 205 | mmcr0 |= MMCR0_PMXE; | ||
| 206 | |||
| 207 | /* | ||
| 208 | * now clear the freeze bit, counting will not start until we | ||
| 209 | * rfid from this exception, because only at that point will | ||
| 210 | * the PMM bit be cleared | ||
| 211 | */ | ||
| 212 | mmcr0 &= ~MMCR0_FC; | ||
| 213 | mtspr(SPRN_MMCR0, mmcr0); | ||
| 214 | } | ||
| 215 | |||
| 216 | struct op_powerpc_model op_model_rs64 = { | ||
| 217 | .reg_setup = rs64_reg_setup, | ||
| 218 | .cpu_setup = rs64_cpu_setup, | ||
| 219 | .start = rs64_start, | ||
| 220 | .stop = rs64_stop, | ||
| 221 | .handle_interrupt = rs64_handle_interrupt, | ||
| 222 | }; | ||
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c index fe52db2eea6a..b7cd00b0171e 100644 --- a/arch/powerpc/perf/core-book3s.c +++ b/arch/powerpc/perf/core-book3s.c | |||
| @@ -36,7 +36,12 @@ struct cpu_hw_events { | |||
| 36 | struct perf_event *event[MAX_HWEVENTS]; | 36 | struct perf_event *event[MAX_HWEVENTS]; |
| 37 | u64 events[MAX_HWEVENTS]; | 37 | u64 events[MAX_HWEVENTS]; |
| 38 | unsigned int flags[MAX_HWEVENTS]; | 38 | unsigned int flags[MAX_HWEVENTS]; |
| 39 | unsigned long mmcr[3]; | 39 | /* |
| 40 | * The order of the MMCR array is: | ||
| 41 | * - 64-bit, MMCR0, MMCR1, MMCRA, MMCR2 | ||
| 42 | * - 32-bit, MMCR0, MMCR1, MMCR2 | ||
| 43 | */ | ||
| 44 | unsigned long mmcr[4]; | ||
| 40 | struct perf_event *limited_counter[MAX_LIMITED_HWCOUNTERS]; | 45 | struct perf_event *limited_counter[MAX_LIMITED_HWCOUNTERS]; |
| 41 | u8 limited_hwidx[MAX_LIMITED_HWCOUNTERS]; | 46 | u8 limited_hwidx[MAX_LIMITED_HWCOUNTERS]; |
| 42 | u64 alternatives[MAX_HWEVENTS][MAX_EVENT_ALTERNATIVES]; | 47 | u64 alternatives[MAX_HWEVENTS][MAX_EVENT_ALTERNATIVES]; |
| @@ -112,9 +117,9 @@ static bool is_ebb_event(struct perf_event *event) { return false; } | |||
| 112 | static int ebb_event_check(struct perf_event *event) { return 0; } | 117 | static int ebb_event_check(struct perf_event *event) { return 0; } |
| 113 | static void ebb_event_add(struct perf_event *event) { } | 118 | static void ebb_event_add(struct perf_event *event) { } |
| 114 | static void ebb_switch_out(unsigned long mmcr0) { } | 119 | static void ebb_switch_out(unsigned long mmcr0) { } |
| 115 | static unsigned long ebb_switch_in(bool ebb, unsigned long mmcr0) | 120 | static unsigned long ebb_switch_in(bool ebb, struct cpu_hw_events *cpuhw) |
| 116 | { | 121 | { |
| 117 | return mmcr0; | 122 | return cpuhw->mmcr[0]; |
| 118 | } | 123 | } |
| 119 | 124 | ||
| 120 | static inline void power_pmu_bhrb_enable(struct perf_event *event) {} | 125 | static inline void power_pmu_bhrb_enable(struct perf_event *event) {} |
| @@ -542,8 +547,10 @@ static void ebb_switch_out(unsigned long mmcr0) | |||
| 542 | current->thread.mmcr2 = mfspr(SPRN_MMCR2) & MMCR2_USER_MASK; | 547 | current->thread.mmcr2 = mfspr(SPRN_MMCR2) & MMCR2_USER_MASK; |
| 543 | } | 548 | } |
| 544 | 549 | ||
| 545 | static unsigned long ebb_switch_in(bool ebb, unsigned long mmcr0) | 550 | static unsigned long ebb_switch_in(bool ebb, struct cpu_hw_events *cpuhw) |
| 546 | { | 551 | { |
| 552 | unsigned long mmcr0 = cpuhw->mmcr[0]; | ||
| 553 | |||
| 547 | if (!ebb) | 554 | if (!ebb) |
| 548 | goto out; | 555 | goto out; |
| 549 | 556 | ||
| @@ -568,7 +575,15 @@ static unsigned long ebb_switch_in(bool ebb, unsigned long mmcr0) | |||
| 568 | mtspr(SPRN_SIAR, current->thread.siar); | 575 | mtspr(SPRN_SIAR, current->thread.siar); |
| 569 | mtspr(SPRN_SIER, current->thread.sier); | 576 | mtspr(SPRN_SIER, current->thread.sier); |
| 570 | mtspr(SPRN_SDAR, current->thread.sdar); | 577 | mtspr(SPRN_SDAR, current->thread.sdar); |
| 571 | mtspr(SPRN_MMCR2, current->thread.mmcr2); | 578 | |
| 579 | /* | ||
| 580 | * Merge the kernel & user values of MMCR2. The semantics we implement | ||
| 581 | * are that the user MMCR2 can set bits, ie. cause counters to freeze, | ||
| 582 | * but not clear bits. If a task wants to be able to clear bits, ie. | ||
| 583 | * unfreeze counters, it should not set exclude_xxx in its events and | ||
| 584 | * instead manage the MMCR2 entirely by itself. | ||
| 585 | */ | ||
| 586 | mtspr(SPRN_MMCR2, cpuhw->mmcr[3] | current->thread.mmcr2); | ||
| 572 | out: | 587 | out: |
| 573 | return mmcr0; | 588 | return mmcr0; |
| 574 | } | 589 | } |
| @@ -915,6 +930,14 @@ static int check_excludes(struct perf_event **ctrs, unsigned int cflags[], | |||
| 915 | int i, n, first; | 930 | int i, n, first; |
| 916 | struct perf_event *event; | 931 | struct perf_event *event; |
| 917 | 932 | ||
| 933 | /* | ||
| 934 | * If the PMU we're on supports per event exclude settings then we | ||
| 935 | * don't need to do any of this logic. NB. This assumes no PMU has both | ||
| 936 | * per event exclude and limited PMCs. | ||
| 937 | */ | ||
| 938 | if (ppmu->flags & PPMU_ARCH_207S) | ||
| 939 | return 0; | ||
| 940 | |||
| 918 | n = n_prev + n_new; | 941 | n = n_prev + n_new; |
| 919 | if (n <= 1) | 942 | if (n <= 1) |
| 920 | return 0; | 943 | return 0; |
| @@ -1219,28 +1242,31 @@ static void power_pmu_enable(struct pmu *pmu) | |||
| 1219 | } | 1242 | } |
| 1220 | 1243 | ||
| 1221 | /* | 1244 | /* |
| 1222 | * Compute MMCR* values for the new set of events | 1245 | * Clear all MMCR settings and recompute them for the new set of events. |
| 1223 | */ | 1246 | */ |
| 1247 | memset(cpuhw->mmcr, 0, sizeof(cpuhw->mmcr)); | ||
| 1248 | |||
| 1224 | if (ppmu->compute_mmcr(cpuhw->events, cpuhw->n_events, hwc_index, | 1249 | if (ppmu->compute_mmcr(cpuhw->events, cpuhw->n_events, hwc_index, |
| 1225 | cpuhw->mmcr)) { | 1250 | cpuhw->mmcr, cpuhw->event)) { |
| 1226 | /* shouldn't ever get here */ | 1251 | /* shouldn't ever get here */ |
| 1227 | printk(KERN_ERR "oops compute_mmcr failed\n"); | 1252 | printk(KERN_ERR "oops compute_mmcr failed\n"); |
| 1228 | goto out; | 1253 | goto out; |
| 1229 | } | 1254 | } |
| 1230 | 1255 | ||
| 1231 | /* | 1256 | if (!(ppmu->flags & PPMU_ARCH_207S)) { |
| 1232 | * Add in MMCR0 freeze bits corresponding to the | 1257 | /* |
| 1233 | * attr.exclude_* bits for the first event. | 1258 | * Add in MMCR0 freeze bits corresponding to the attr.exclude_* |
| 1234 | * We have already checked that all events have the | 1259 | * bits for the first event. We have already checked that all |
| 1235 | * same values for these bits as the first event. | 1260 | * events have the same value for these bits as the first event. |
| 1236 | */ | 1261 | */ |
| 1237 | event = cpuhw->event[0]; | 1262 | event = cpuhw->event[0]; |
| 1238 | if (event->attr.exclude_user) | 1263 | if (event->attr.exclude_user) |
| 1239 | cpuhw->mmcr[0] |= MMCR0_FCP; | 1264 | cpuhw->mmcr[0] |= MMCR0_FCP; |
| 1240 | if (event->attr.exclude_kernel) | 1265 | if (event->attr.exclude_kernel) |
| 1241 | cpuhw->mmcr[0] |= freeze_events_kernel; | 1266 | cpuhw->mmcr[0] |= freeze_events_kernel; |
| 1242 | if (event->attr.exclude_hv) | 1267 | if (event->attr.exclude_hv) |
| 1243 | cpuhw->mmcr[0] |= MMCR0_FCHV; | 1268 | cpuhw->mmcr[0] |= MMCR0_FCHV; |
| 1269 | } | ||
| 1244 | 1270 | ||
| 1245 | /* | 1271 | /* |
| 1246 | * Write the new configuration to MMCR* with the freeze | 1272 | * Write the new configuration to MMCR* with the freeze |
| @@ -1252,6 +1278,8 @@ static void power_pmu_enable(struct pmu *pmu) | |||
| 1252 | mtspr(SPRN_MMCR1, cpuhw->mmcr[1]); | 1278 | mtspr(SPRN_MMCR1, cpuhw->mmcr[1]); |
| 1253 | mtspr(SPRN_MMCR0, (cpuhw->mmcr[0] & ~(MMCR0_PMC1CE | MMCR0_PMCjCE)) | 1279 | mtspr(SPRN_MMCR0, (cpuhw->mmcr[0] & ~(MMCR0_PMC1CE | MMCR0_PMCjCE)) |
| 1254 | | MMCR0_FC); | 1280 | | MMCR0_FC); |
| 1281 | if (ppmu->flags & PPMU_ARCH_207S) | ||
| 1282 | mtspr(SPRN_MMCR2, cpuhw->mmcr[3]); | ||
| 1255 | 1283 | ||
| 1256 | /* | 1284 | /* |
| 1257 | * Read off any pre-existing events that need to move | 1285 | * Read off any pre-existing events that need to move |
| @@ -1307,10 +1335,7 @@ static void power_pmu_enable(struct pmu *pmu) | |||
| 1307 | out_enable: | 1335 | out_enable: |
| 1308 | pmao_restore_workaround(ebb); | 1336 | pmao_restore_workaround(ebb); |
| 1309 | 1337 | ||
| 1310 | if (ppmu->flags & PPMU_ARCH_207S) | 1338 | mmcr0 = ebb_switch_in(ebb, cpuhw); |
| 1311 | mtspr(SPRN_MMCR2, 0); | ||
| 1312 | |||
| 1313 | mmcr0 = ebb_switch_in(ebb, cpuhw->mmcr[0]); | ||
| 1314 | 1339 | ||
| 1315 | mb(); | 1340 | mb(); |
| 1316 | if (cpuhw->bhrb_users) | 1341 | if (cpuhw->bhrb_users) |
diff --git a/arch/powerpc/perf/mpc7450-pmu.c b/arch/powerpc/perf/mpc7450-pmu.c index fe21b515ca44..d115c5635bf3 100644 --- a/arch/powerpc/perf/mpc7450-pmu.c +++ b/arch/powerpc/perf/mpc7450-pmu.c | |||
| @@ -260,8 +260,9 @@ static const u32 pmcsel_mask[N_COUNTER] = { | |||
| 260 | /* | 260 | /* |
| 261 | * Compute MMCR0/1/2 values for a set of events. | 261 | * Compute MMCR0/1/2 values for a set of events. |
| 262 | */ | 262 | */ |
| 263 | static int mpc7450_compute_mmcr(u64 event[], int n_ev, | 263 | static int mpc7450_compute_mmcr(u64 event[], int n_ev, unsigned int hwc[], |
| 264 | unsigned int hwc[], unsigned long mmcr[]) | 264 | unsigned long mmcr[], |
| 265 | struct perf_event *pevents[]) | ||
| 265 | { | 266 | { |
| 266 | u8 event_index[N_CLASSES][N_COUNTER]; | 267 | u8 event_index[N_CLASSES][N_COUNTER]; |
| 267 | int n_classevent[N_CLASSES]; | 268 | int n_classevent[N_CLASSES]; |
diff --git a/arch/powerpc/perf/power4-pmu.c b/arch/powerpc/perf/power4-pmu.c index 9103a1de864d..ce6072fa481b 100644 --- a/arch/powerpc/perf/power4-pmu.c +++ b/arch/powerpc/perf/power4-pmu.c | |||
| @@ -356,7 +356,7 @@ static int p4_get_alternatives(u64 event, unsigned int flags, u64 alt[]) | |||
| 356 | } | 356 | } |
| 357 | 357 | ||
| 358 | static int p4_compute_mmcr(u64 event[], int n_ev, | 358 | static int p4_compute_mmcr(u64 event[], int n_ev, |
| 359 | unsigned int hwc[], unsigned long mmcr[]) | 359 | unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[]) |
| 360 | { | 360 | { |
| 361 | unsigned long mmcr0 = 0, mmcr1 = 0, mmcra = 0; | 361 | unsigned long mmcr0 = 0, mmcr1 = 0, mmcra = 0; |
| 362 | unsigned int pmc, unit, byte, psel, lower; | 362 | unsigned int pmc, unit, byte, psel, lower; |
diff --git a/arch/powerpc/perf/power5+-pmu.c b/arch/powerpc/perf/power5+-pmu.c index b03b6dc0172d..0526dac66007 100644 --- a/arch/powerpc/perf/power5+-pmu.c +++ b/arch/powerpc/perf/power5+-pmu.c | |||
| @@ -452,7 +452,7 @@ static int power5p_marked_instr_event(u64 event) | |||
| 452 | } | 452 | } |
| 453 | 453 | ||
| 454 | static int power5p_compute_mmcr(u64 event[], int n_ev, | 454 | static int power5p_compute_mmcr(u64 event[], int n_ev, |
| 455 | unsigned int hwc[], unsigned long mmcr[]) | 455 | unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[]) |
| 456 | { | 456 | { |
| 457 | unsigned long mmcr1 = 0; | 457 | unsigned long mmcr1 = 0; |
| 458 | unsigned long mmcra = 0; | 458 | unsigned long mmcra = 0; |
diff --git a/arch/powerpc/perf/power5-pmu.c b/arch/powerpc/perf/power5-pmu.c index 1e8ce423c3af..4dc99f9f7962 100644 --- a/arch/powerpc/perf/power5-pmu.c +++ b/arch/powerpc/perf/power5-pmu.c | |||
| @@ -383,7 +383,7 @@ static int power5_marked_instr_event(u64 event) | |||
| 383 | } | 383 | } |
| 384 | 384 | ||
| 385 | static int power5_compute_mmcr(u64 event[], int n_ev, | 385 | static int power5_compute_mmcr(u64 event[], int n_ev, |
| 386 | unsigned int hwc[], unsigned long mmcr[]) | 386 | unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[]) |
| 387 | { | 387 | { |
| 388 | unsigned long mmcr1 = 0; | 388 | unsigned long mmcr1 = 0; |
| 389 | unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS; | 389 | unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS; |
diff --git a/arch/powerpc/perf/power6-pmu.c b/arch/powerpc/perf/power6-pmu.c index 31128e086fed..9c9d646b68a1 100644 --- a/arch/powerpc/perf/power6-pmu.c +++ b/arch/powerpc/perf/power6-pmu.c | |||
| @@ -175,7 +175,7 @@ static int power6_marked_instr_event(u64 event) | |||
| 175 | * Assign PMC numbers and compute MMCR1 value for a set of events | 175 | * Assign PMC numbers and compute MMCR1 value for a set of events |
| 176 | */ | 176 | */ |
| 177 | static int p6_compute_mmcr(u64 event[], int n_ev, | 177 | static int p6_compute_mmcr(u64 event[], int n_ev, |
| 178 | unsigned int hwc[], unsigned long mmcr[]) | 178 | unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[]) |
| 179 | { | 179 | { |
| 180 | unsigned long mmcr1 = 0; | 180 | unsigned long mmcr1 = 0; |
| 181 | unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS; | 181 | unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS; |
diff --git a/arch/powerpc/perf/power7-pmu.c b/arch/powerpc/perf/power7-pmu.c index 56c67bca2f75..5b62f2389290 100644 --- a/arch/powerpc/perf/power7-pmu.c +++ b/arch/powerpc/perf/power7-pmu.c | |||
| @@ -245,7 +245,7 @@ static int power7_marked_instr_event(u64 event) | |||
| 245 | } | 245 | } |
| 246 | 246 | ||
| 247 | static int power7_compute_mmcr(u64 event[], int n_ev, | 247 | static int power7_compute_mmcr(u64 event[], int n_ev, |
| 248 | unsigned int hwc[], unsigned long mmcr[]) | 248 | unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[]) |
| 249 | { | 249 | { |
| 250 | unsigned long mmcr1 = 0; | 250 | unsigned long mmcr1 = 0; |
| 251 | unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS; | 251 | unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS; |
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c index 639cd9156585..396351db601b 100644 --- a/arch/powerpc/perf/power8-pmu.c +++ b/arch/powerpc/perf/power8-pmu.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
| 16 | #include <linux/perf_event.h> | 16 | #include <linux/perf_event.h> |
| 17 | #include <asm/firmware.h> | 17 | #include <asm/firmware.h> |
| 18 | #include <asm/cputable.h> | ||
| 18 | 19 | ||
| 19 | 20 | ||
| 20 | /* | 21 | /* |
| @@ -266,6 +267,11 @@ | |||
| 266 | #define MMCRA_SDAR_MODE_TLB (1ull << 42) | 267 | #define MMCRA_SDAR_MODE_TLB (1ull << 42) |
| 267 | #define MMCRA_IFM_SHIFT 30 | 268 | #define MMCRA_IFM_SHIFT 30 |
| 268 | 269 | ||
| 270 | /* Bits in MMCR2 for POWER8 */ | ||
| 271 | #define MMCR2_FCS(pmc) (1ull << (63 - (((pmc) - 1) * 9))) | ||
| 272 | #define MMCR2_FCP(pmc) (1ull << (62 - (((pmc) - 1) * 9))) | ||
| 273 | #define MMCR2_FCH(pmc) (1ull << (57 - (((pmc) - 1) * 9))) | ||
| 274 | |||
| 269 | 275 | ||
| 270 | static inline bool event_is_fab_match(u64 event) | 276 | static inline bool event_is_fab_match(u64 event) |
| 271 | { | 277 | { |
| @@ -393,9 +399,10 @@ static int power8_get_constraint(u64 event, unsigned long *maskp, unsigned long | |||
| 393 | } | 399 | } |
| 394 | 400 | ||
| 395 | static int power8_compute_mmcr(u64 event[], int n_ev, | 401 | static int power8_compute_mmcr(u64 event[], int n_ev, |
| 396 | unsigned int hwc[], unsigned long mmcr[]) | 402 | unsigned int hwc[], unsigned long mmcr[], |
| 403 | struct perf_event *pevents[]) | ||
| 397 | { | 404 | { |
| 398 | unsigned long mmcra, mmcr1, unit, combine, psel, cache, val; | 405 | unsigned long mmcra, mmcr1, mmcr2, unit, combine, psel, cache, val; |
| 399 | unsigned int pmc, pmc_inuse; | 406 | unsigned int pmc, pmc_inuse; |
| 400 | int i; | 407 | int i; |
| 401 | 408 | ||
| @@ -410,7 +417,7 @@ static int power8_compute_mmcr(u64 event[], int n_ev, | |||
| 410 | 417 | ||
| 411 | /* In continous sampling mode, update SDAR on TLB miss */ | 418 | /* In continous sampling mode, update SDAR on TLB miss */ |
| 412 | mmcra = MMCRA_SDAR_MODE_TLB; | 419 | mmcra = MMCRA_SDAR_MODE_TLB; |
| 413 | mmcr1 = 0; | 420 | mmcr1 = mmcr2 = 0; |
| 414 | 421 | ||
| 415 | /* Second pass: assign PMCs, set all MMCR1 fields */ | 422 | /* Second pass: assign PMCs, set all MMCR1 fields */ |
| 416 | for (i = 0; i < n_ev; ++i) { | 423 | for (i = 0; i < n_ev; ++i) { |
| @@ -472,6 +479,19 @@ static int power8_compute_mmcr(u64 event[], int n_ev, | |||
| 472 | mmcra |= val << MMCRA_IFM_SHIFT; | 479 | mmcra |= val << MMCRA_IFM_SHIFT; |
| 473 | } | 480 | } |
| 474 | 481 | ||
| 482 | if (pevents[i]->attr.exclude_user) | ||
| 483 | mmcr2 |= MMCR2_FCP(pmc); | ||
| 484 | |||
| 485 | if (pevents[i]->attr.exclude_hv) | ||
| 486 | mmcr2 |= MMCR2_FCH(pmc); | ||
| 487 | |||
| 488 | if (pevents[i]->attr.exclude_kernel) { | ||
| 489 | if (cpu_has_feature(CPU_FTR_HVMODE)) | ||
| 490 | mmcr2 |= MMCR2_FCH(pmc); | ||
| 491 | else | ||
| 492 | mmcr2 |= MMCR2_FCS(pmc); | ||
| 493 | } | ||
| 494 | |||
| 475 | hwc[i] = pmc - 1; | 495 | hwc[i] = pmc - 1; |
| 476 | } | 496 | } |
| 477 | 497 | ||
| @@ -491,6 +511,7 @@ static int power8_compute_mmcr(u64 event[], int n_ev, | |||
| 491 | 511 | ||
| 492 | mmcr[1] = mmcr1; | 512 | mmcr[1] = mmcr1; |
| 493 | mmcr[2] = mmcra; | 513 | mmcr[2] = mmcra; |
| 514 | mmcr[3] = mmcr2; | ||
| 494 | 515 | ||
| 495 | return 0; | 516 | return 0; |
| 496 | } | 517 | } |
diff --git a/arch/powerpc/perf/ppc970-pmu.c b/arch/powerpc/perf/ppc970-pmu.c index 20139ceeacf6..8b6a8a36fa38 100644 --- a/arch/powerpc/perf/ppc970-pmu.c +++ b/arch/powerpc/perf/ppc970-pmu.c | |||
| @@ -257,7 +257,7 @@ static int p970_get_alternatives(u64 event, unsigned int flags, u64 alt[]) | |||
| 257 | } | 257 | } |
| 258 | 258 | ||
| 259 | static int p970_compute_mmcr(u64 event[], int n_ev, | 259 | static int p970_compute_mmcr(u64 event[], int n_ev, |
| 260 | unsigned int hwc[], unsigned long mmcr[]) | 260 | unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[]) |
| 261 | { | 261 | { |
| 262 | unsigned long mmcr0 = 0, mmcr1 = 0, mmcra = 0; | 262 | unsigned long mmcr0 = 0, mmcr1 = 0, mmcra = 0; |
| 263 | unsigned int pmc, unit, byte, psel; | 263 | unsigned int pmc, unit, byte, psel; |
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index f442120e0033..0c1e6903597e 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig | |||
| @@ -274,7 +274,7 @@ config CORENET_GENERIC | |||
| 274 | For 32bit kernel, the following boards are supported: | 274 | For 32bit kernel, the following boards are supported: |
| 275 | P2041 RDB, P3041 DS, P4080 DS, kmcoge4, and OCA4080 | 275 | P2041 RDB, P3041 DS, P4080 DS, kmcoge4, and OCA4080 |
| 276 | For 64bit kernel, the following boards are supported: | 276 | For 64bit kernel, the following boards are supported: |
| 277 | T4240 QDS and B4 QDS | 277 | T208x QDS/RDB, T4240 QDS/RDB and B4 QDS |
| 278 | The following boards are supported for both 32bit and 64bit kernel: | 278 | The following boards are supported for both 32bit and 64bit kernel: |
| 279 | P5020 DS, P5040 DS and T104xQDS | 279 | P5020 DS, P5040 DS and T104xQDS |
| 280 | 280 | ||
diff --git a/arch/powerpc/platforms/85xx/corenet_generic.c b/arch/powerpc/platforms/85xx/corenet_generic.c index 5db1e117fdde..d22dd85e50bf 100644 --- a/arch/powerpc/platforms/85xx/corenet_generic.c +++ b/arch/powerpc/platforms/85xx/corenet_generic.c | |||
| @@ -119,7 +119,11 @@ static const char * const boards[] __initconst = { | |||
| 119 | "fsl,P4080DS", | 119 | "fsl,P4080DS", |
| 120 | "fsl,P5020DS", | 120 | "fsl,P5020DS", |
| 121 | "fsl,P5040DS", | 121 | "fsl,P5040DS", |
| 122 | "fsl,T2080QDS", | ||
| 123 | "fsl,T2080RDB", | ||
| 124 | "fsl,T2081QDS", | ||
| 122 | "fsl,T4240QDS", | 125 | "fsl,T4240QDS", |
| 126 | "fsl,T4240RDB", | ||
| 123 | "fsl,B4860QDS", | 127 | "fsl,B4860QDS", |
| 124 | "fsl,B4420QDS", | 128 | "fsl,B4420QDS", |
| 125 | "fsl,B4220QDS", | 129 | "fsl,B4220QDS", |
| @@ -129,28 +133,14 @@ static const char * const boards[] __initconst = { | |||
| 129 | NULL | 133 | NULL |
| 130 | }; | 134 | }; |
| 131 | 135 | ||
| 132 | static const char * const hv_boards[] __initconst = { | ||
| 133 | "fsl,P2041RDB-hv", | ||
| 134 | "fsl,P3041DS-hv", | ||
| 135 | "fsl,OCA4080-hv", | ||
| 136 | "fsl,P4080DS-hv", | ||
| 137 | "fsl,P5020DS-hv", | ||
| 138 | "fsl,P5040DS-hv", | ||
| 139 | "fsl,T4240QDS-hv", | ||
| 140 | "fsl,B4860QDS-hv", | ||
| 141 | "fsl,B4420QDS-hv", | ||
| 142 | "fsl,B4220QDS-hv", | ||
| 143 | "fsl,T1040QDS-hv", | ||
| 144 | "fsl,T1042QDS-hv", | ||
| 145 | NULL | ||
| 146 | }; | ||
| 147 | |||
| 148 | /* | 136 | /* |
| 149 | * Called very early, device-tree isn't unflattened | 137 | * Called very early, device-tree isn't unflattened |
| 150 | */ | 138 | */ |
| 151 | static int __init corenet_generic_probe(void) | 139 | static int __init corenet_generic_probe(void) |
| 152 | { | 140 | { |
| 153 | unsigned long root = of_get_flat_dt_root(); | 141 | unsigned long root = of_get_flat_dt_root(); |
| 142 | char hv_compat[24]; | ||
| 143 | int i; | ||
| 154 | #ifdef CONFIG_SMP | 144 | #ifdef CONFIG_SMP |
| 155 | extern struct smp_ops_t smp_85xx_ops; | 145 | extern struct smp_ops_t smp_85xx_ops; |
| 156 | #endif | 146 | #endif |
| @@ -159,21 +149,26 @@ static int __init corenet_generic_probe(void) | |||
| 159 | return 1; | 149 | return 1; |
| 160 | 150 | ||
| 161 | /* Check if we're running under the Freescale hypervisor */ | 151 | /* Check if we're running under the Freescale hypervisor */ |
| 162 | if (of_flat_dt_match(root, hv_boards)) { | 152 | for (i = 0; boards[i]; i++) { |
| 163 | ppc_md.init_IRQ = ehv_pic_init; | 153 | snprintf(hv_compat, sizeof(hv_compat), "%s-hv", boards[i]); |
| 164 | ppc_md.get_irq = ehv_pic_get_irq; | 154 | if (of_flat_dt_is_compatible(root, hv_compat)) { |
| 165 | ppc_md.restart = fsl_hv_restart; | 155 | ppc_md.init_IRQ = ehv_pic_init; |
| 166 | ppc_md.power_off = fsl_hv_halt; | 156 | |
| 167 | ppc_md.halt = fsl_hv_halt; | 157 | ppc_md.get_irq = ehv_pic_get_irq; |
| 158 | ppc_md.restart = fsl_hv_restart; | ||
| 159 | ppc_md.power_off = fsl_hv_halt; | ||
| 160 | ppc_md.halt = fsl_hv_halt; | ||
| 168 | #ifdef CONFIG_SMP | 161 | #ifdef CONFIG_SMP |
| 169 | /* | 162 | /* |
| 170 | * Disable the timebase sync operations because we can't write | 163 | * Disable the timebase sync operations because we |
| 171 | * to the timebase registers under the hypervisor. | 164 | * can't write to the timebase registers under the |
| 172 | */ | 165 | * hypervisor. |
| 173 | smp_85xx_ops.give_timebase = NULL; | 166 | */ |
| 174 | smp_85xx_ops.take_timebase = NULL; | 167 | smp_85xx_ops.give_timebase = NULL; |
| 168 | smp_85xx_ops.take_timebase = NULL; | ||
| 175 | #endif | 169 | #endif |
| 176 | return 1; | 170 | return 1; |
| 171 | } | ||
| 177 | } | 172 | } |
| 178 | 173 | ||
| 179 | return 0; | 174 | return 0; |
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index ba093f553678..d7c1e69f3070 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <asm/dbell.h> | 28 | #include <asm/dbell.h> |
| 29 | #include <asm/fsl_guts.h> | 29 | #include <asm/fsl_guts.h> |
| 30 | #include <asm/code-patching.h> | 30 | #include <asm/code-patching.h> |
| 31 | #include <asm/cputhreads.h> | ||
| 31 | 32 | ||
| 32 | #include <sysdev/fsl_soc.h> | 33 | #include <sysdev/fsl_soc.h> |
| 33 | #include <sysdev/mpic.h> | 34 | #include <sysdev/mpic.h> |
| @@ -168,6 +169,24 @@ static inline u32 read_spin_table_addr_l(void *spin_table) | |||
| 168 | return in_be32(&((struct epapr_spin_table *)spin_table)->addr_l); | 169 | return in_be32(&((struct epapr_spin_table *)spin_table)->addr_l); |
| 169 | } | 170 | } |
| 170 | 171 | ||
| 172 | #ifdef CONFIG_PPC64 | ||
| 173 | static void wake_hw_thread(void *info) | ||
| 174 | { | ||
| 175 | void fsl_secondary_thread_init(void); | ||
| 176 | unsigned long imsr1, inia1; | ||
| 177 | int nr = *(const int *)info; | ||
| 178 | |||
| 179 | imsr1 = MSR_KERNEL; | ||
| 180 | inia1 = *(unsigned long *)fsl_secondary_thread_init; | ||
| 181 | |||
| 182 | mttmr(TMRN_IMSR1, imsr1); | ||
| 183 | mttmr(TMRN_INIA1, inia1); | ||
| 184 | mtspr(SPRN_TENS, TEN_THREAD(1)); | ||
| 185 | |||
| 186 | smp_generic_kick_cpu(nr); | ||
| 187 | } | ||
| 188 | #endif | ||
| 189 | |||
| 171 | static int smp_85xx_kick_cpu(int nr) | 190 | static int smp_85xx_kick_cpu(int nr) |
| 172 | { | 191 | { |
| 173 | unsigned long flags; | 192 | unsigned long flags; |
| @@ -183,6 +202,31 @@ static int smp_85xx_kick_cpu(int nr) | |||
| 183 | 202 | ||
| 184 | pr_debug("smp_85xx_kick_cpu: kick CPU #%d\n", nr); | 203 | pr_debug("smp_85xx_kick_cpu: kick CPU #%d\n", nr); |
| 185 | 204 | ||
| 205 | #ifdef CONFIG_PPC64 | ||
| 206 | /* Threads don't use the spin table */ | ||
| 207 | if (cpu_thread_in_core(nr) != 0) { | ||
| 208 | int primary = cpu_first_thread_sibling(nr); | ||
| 209 | |||
| 210 | if (WARN_ON_ONCE(!cpu_has_feature(CPU_FTR_SMT))) | ||
| 211 | return -ENOENT; | ||
| 212 | |||
| 213 | if (cpu_thread_in_core(nr) != 1) { | ||
| 214 | pr_err("%s: cpu %d: invalid hw thread %d\n", | ||
| 215 | __func__, nr, cpu_thread_in_core(nr)); | ||
| 216 | return -ENOENT; | ||
| 217 | } | ||
| 218 | |||
| 219 | if (!cpu_online(primary)) { | ||
| 220 | pr_err("%s: cpu %d: primary %d not online\n", | ||
| 221 | __func__, nr, primary); | ||
| 222 | return -ENOENT; | ||
| 223 | } | ||
| 224 | |||
| 225 | smp_call_function_single(primary, wake_hw_thread, &nr, 0); | ||
| 226 | return 0; | ||
| 227 | } | ||
| 228 | #endif | ||
| 229 | |||
| 186 | np = of_get_cpu_node(nr, NULL); | 230 | np = of_get_cpu_node(nr, NULL); |
| 187 | cpu_rel_addr = of_get_property(np, "cpu-release-addr", NULL); | 231 | cpu_rel_addr = of_get_property(np, "cpu-release-addr", NULL); |
| 188 | 232 | ||
diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c index 587a2828b06c..d3037747031d 100644 --- a/arch/powerpc/platforms/8xx/m8xx_setup.c +++ b/arch/powerpc/platforms/8xx/m8xx_setup.c | |||
| @@ -18,7 +18,6 @@ | |||
| 18 | #include <linux/fsl_devices.h> | 18 | #include <linux/fsl_devices.h> |
| 19 | 19 | ||
| 20 | #include <asm/io.h> | 20 | #include <asm/io.h> |
| 21 | #include <asm/mpc8xx.h> | ||
| 22 | #include <asm/8xx_immap.h> | 21 | #include <asm/8xx_immap.h> |
| 23 | #include <asm/prom.h> | 22 | #include <asm/prom.h> |
| 24 | #include <asm/fs_pd.h> | 23 | #include <asm/fs_pd.h> |
| @@ -28,8 +27,6 @@ | |||
| 28 | 27 | ||
| 29 | #include "mpc8xx.h" | 28 | #include "mpc8xx.h" |
| 30 | 29 | ||
| 31 | struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops; | ||
| 32 | |||
| 33 | extern int cpm_pic_init(void); | 30 | extern int cpm_pic_init(void); |
| 34 | extern int cpm_get_irq(void); | 31 | extern int cpm_get_irq(void); |
| 35 | 32 | ||
diff --git a/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/arch/powerpc/platforms/8xx/mpc885ads_setup.c index c1262581b63c..5921dcb498fd 100644 --- a/arch/powerpc/platforms/8xx/mpc885ads_setup.c +++ b/arch/powerpc/platforms/8xx/mpc885ads_setup.c | |||
| @@ -35,7 +35,6 @@ | |||
| 35 | #include <asm/page.h> | 35 | #include <asm/page.h> |
| 36 | #include <asm/processor.h> | 36 | #include <asm/processor.h> |
| 37 | #include <asm/time.h> | 37 | #include <asm/time.h> |
| 38 | #include <asm/mpc8xx.h> | ||
| 39 | #include <asm/8xx_immap.h> | 38 | #include <asm/8xx_immap.h> |
| 40 | #include <asm/cpm1.h> | 39 | #include <asm/cpm1.h> |
| 41 | #include <asm/fs_pd.h> | 40 | #include <asm/fs_pd.h> |
| @@ -46,61 +45,6 @@ | |||
| 46 | 45 | ||
| 47 | static u32 __iomem *bcsr, *bcsr5; | 46 | static u32 __iomem *bcsr, *bcsr5; |
| 48 | 47 | ||
| 49 | #ifdef CONFIG_PCMCIA_M8XX | ||
| 50 | static void pcmcia_hw_setup(int slot, int enable) | ||
| 51 | { | ||
| 52 | if (enable) | ||
| 53 | clrbits32(&bcsr[1], BCSR1_PCCEN); | ||
| 54 | else | ||
| 55 | setbits32(&bcsr[1], BCSR1_PCCEN); | ||
| 56 | } | ||
| 57 | |||
| 58 | static int pcmcia_set_voltage(int slot, int vcc, int vpp) | ||
| 59 | { | ||
| 60 | u32 reg = 0; | ||
| 61 | |||
| 62 | switch (vcc) { | ||
| 63 | case 0: | ||
| 64 | break; | ||
| 65 | case 33: | ||
| 66 | reg |= BCSR1_PCCVCC0; | ||
| 67 | break; | ||
| 68 | case 50: | ||
| 69 | reg |= BCSR1_PCCVCC1; | ||
| 70 | break; | ||
| 71 | default: | ||
| 72 | return 1; | ||
| 73 | } | ||
| 74 | |||
| 75 | switch (vpp) { | ||
| 76 | case 0: | ||
| 77 | break; | ||
| 78 | case 33: | ||
| 79 | case 50: | ||
| 80 | if (vcc == vpp) | ||
| 81 | reg |= BCSR1_PCCVPP1; | ||
| 82 | else | ||
| 83 | return 1; | ||
| 84 | break; | ||
| 85 | case 120: | ||
| 86 | if ((vcc == 33) || (vcc == 50)) | ||
| 87 | reg |= BCSR1_PCCVPP0; | ||
| 88 | else | ||
| 89 | return 1; | ||
| 90 | default: | ||
| 91 | return 1; | ||
| 92 | } | ||
| 93 | |||
| 94 | /* first, turn off all power */ | ||
| 95 | clrbits32(&bcsr[1], 0x00610000); | ||
| 96 | |||
| 97 | /* enable new powersettings */ | ||
| 98 | setbits32(&bcsr[1], reg); | ||
| 99 | |||
| 100 | return 0; | ||
| 101 | } | ||
| 102 | #endif | ||
| 103 | |||
| 104 | struct cpm_pin { | 48 | struct cpm_pin { |
| 105 | int port, pin, flags; | 49 | int port, pin, flags; |
| 106 | }; | 50 | }; |
| @@ -245,12 +189,6 @@ static void __init mpc885ads_setup_arch(void) | |||
| 245 | of_detach_node(np); | 189 | of_detach_node(np); |
| 246 | of_node_put(np); | 190 | of_node_put(np); |
| 247 | } | 191 | } |
| 248 | |||
| 249 | #ifdef CONFIG_PCMCIA_M8XX | ||
| 250 | /* Set up board specific hook-ups.*/ | ||
| 251 | m8xx_pcmcia_ops.hw_ctrl = pcmcia_hw_setup; | ||
| 252 | m8xx_pcmcia_ops.voltage_set = pcmcia_set_voltage; | ||
| 253 | #endif | ||
| 254 | } | 192 | } |
| 255 | 193 | ||
| 256 | static int __init mpc885ads_probe(void) | 194 | static int __init mpc885ads_probe(void) |
diff --git a/arch/powerpc/platforms/8xx/tqm8xx_setup.c b/arch/powerpc/platforms/8xx/tqm8xx_setup.c index 251aba8759e4..dda607807def 100644 --- a/arch/powerpc/platforms/8xx/tqm8xx_setup.c +++ b/arch/powerpc/platforms/8xx/tqm8xx_setup.c | |||
| @@ -37,7 +37,6 @@ | |||
| 37 | #include <asm/page.h> | 37 | #include <asm/page.h> |
| 38 | #include <asm/processor.h> | 38 | #include <asm/processor.h> |
| 39 | #include <asm/time.h> | 39 | #include <asm/time.h> |
| 40 | #include <asm/mpc8xx.h> | ||
| 41 | #include <asm/8xx_immap.h> | 40 | #include <asm/8xx_immap.h> |
| 42 | #include <asm/cpm1.h> | 41 | #include <asm/cpm1.h> |
| 43 | #include <asm/fs_pd.h> | 42 | #include <asm/fs_pd.h> |
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index a41bd023647a..e8bc40869cbd 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype | |||
| @@ -61,7 +61,7 @@ choice | |||
| 61 | help | 61 | help |
| 62 | There are two families of 64 bit PowerPC chips supported. | 62 | There are two families of 64 bit PowerPC chips supported. |
| 63 | The most common ones are the desktop and server CPUs | 63 | The most common ones are the desktop and server CPUs |
| 64 | (POWER3, RS64, POWER4, POWER5, POWER5+, POWER6, ...) | 64 | (POWER4, POWER5, 970, POWER5+, POWER6, POWER7, POWER8 ...) |
| 65 | 65 | ||
| 66 | The other are the "embedded" processors compliant with the | 66 | The other are the "embedded" processors compliant with the |
| 67 | "Book 3E" variant of the architecture | 67 | "Book 3E" variant of the architecture |
| @@ -140,14 +140,6 @@ config 6xx | |||
| 140 | depends on PPC32 && PPC_BOOK3S | 140 | depends on PPC32 && PPC_BOOK3S |
| 141 | select PPC_HAVE_PMU_SUPPORT | 141 | select PPC_HAVE_PMU_SUPPORT |
| 142 | 142 | ||
| 143 | config POWER3 | ||
| 144 | depends on PPC64 && PPC_BOOK3S | ||
| 145 | def_bool y | ||
| 146 | |||
| 147 | config POWER4 | ||
| 148 | depends on PPC64 && PPC_BOOK3S | ||
| 149 | def_bool y | ||
| 150 | |||
| 151 | config TUNE_CELL | 143 | config TUNE_CELL |
| 152 | bool "Optimize for Cell Broadband Engine" | 144 | bool "Optimize for Cell Broadband Engine" |
| 153 | depends on PPC64 && PPC_BOOK3S | 145 | depends on PPC64 && PPC_BOOK3S |
| @@ -244,7 +236,7 @@ config PHYS_64BIT | |||
| 244 | 236 | ||
| 245 | config ALTIVEC | 237 | config ALTIVEC |
| 246 | bool "AltiVec Support" | 238 | bool "AltiVec Support" |
| 247 | depends on 6xx || POWER4 || (PPC_E500MC && PPC64) | 239 | depends on 6xx || PPC_BOOK3S_64 || (PPC_E500MC && PPC64) |
| 248 | ---help--- | 240 | ---help--- |
| 249 | This option enables kernel support for the Altivec extensions to the | 241 | This option enables kernel support for the Altivec extensions to the |
| 250 | PowerPC processor. The kernel currently supports saving and restoring | 242 | PowerPC processor. The kernel currently supports saving and restoring |
| @@ -260,7 +252,7 @@ config ALTIVEC | |||
| 260 | 252 | ||
| 261 | config VSX | 253 | config VSX |
| 262 | bool "VSX Support" | 254 | bool "VSX Support" |
| 263 | depends on POWER4 && ALTIVEC && PPC_FPU | 255 | depends on PPC_BOOK3S_64 && ALTIVEC && PPC_FPU |
| 264 | ---help--- | 256 | ---help--- |
| 265 | 257 | ||
| 266 | This option enables kernel support for the Vector Scaler extensions | 258 | This option enables kernel support for the Vector Scaler extensions |
| @@ -276,7 +268,7 @@ config VSX | |||
| 276 | 268 | ||
| 277 | config PPC_ICSWX | 269 | config PPC_ICSWX |
| 278 | bool "Support for PowerPC icswx coprocessor instruction" | 270 | bool "Support for PowerPC icswx coprocessor instruction" |
| 279 | depends on POWER4 | 271 | depends on PPC_BOOK3S_64 |
| 280 | default n | 272 | default n |
| 281 | ---help--- | 273 | ---help--- |
| 282 | 274 | ||
| @@ -294,7 +286,7 @@ config PPC_ICSWX | |||
| 294 | 286 | ||
| 295 | config PPC_ICSWX_PID | 287 | config PPC_ICSWX_PID |
| 296 | bool "icswx requires direct PID management" | 288 | bool "icswx requires direct PID management" |
| 297 | depends on PPC_ICSWX && POWER4 | 289 | depends on PPC_ICSWX |
| 298 | default y | 290 | default y |
| 299 | ---help--- | 291 | ---help--- |
| 300 | The PID register in server is used explicitly for ICSWX. In | 292 | The PID register in server is used explicitly for ICSWX. In |
diff --git a/arch/powerpc/platforms/powermac/Kconfig b/arch/powerpc/platforms/powermac/Kconfig index 1afd10f67858..607124bae2e7 100644 --- a/arch/powerpc/platforms/powermac/Kconfig +++ b/arch/powerpc/platforms/powermac/Kconfig | |||
| @@ -10,7 +10,7 @@ config PPC_PMAC | |||
| 10 | 10 | ||
| 11 | config PPC_PMAC64 | 11 | config PPC_PMAC64 |
| 12 | bool | 12 | bool |
| 13 | depends on PPC_PMAC && POWER4 | 13 | depends on PPC_PMAC && PPC64 |
| 14 | select MPIC | 14 | select MPIC |
| 15 | select U3_DART | 15 | select U3_DART |
| 16 | select MPIC_U3_HT_IRQS | 16 | select MPIC_U3_HT_IRQS |
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index 63d82bbc05e9..1413e72bc2e1 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c | |||
| @@ -158,7 +158,7 @@ static inline int simple_feature_tweak(struct device_node *node, int type, | |||
| 158 | return 0; | 158 | return 0; |
| 159 | } | 159 | } |
| 160 | 160 | ||
| 161 | #ifndef CONFIG_POWER4 | 161 | #ifndef CONFIG_PPC64 |
| 162 | 162 | ||
| 163 | static long ohare_htw_scc_enable(struct device_node *node, long param, | 163 | static long ohare_htw_scc_enable(struct device_node *node, long param, |
| 164 | long value) | 164 | long value) |
| @@ -1318,7 +1318,7 @@ intrepid_aack_delay_enable(struct device_node *node, long param, long value) | |||
| 1318 | } | 1318 | } |
| 1319 | 1319 | ||
| 1320 | 1320 | ||
| 1321 | #endif /* CONFIG_POWER4 */ | 1321 | #endif /* CONFIG_PPC64 */ |
| 1322 | 1322 | ||
| 1323 | static long | 1323 | static long |
| 1324 | core99_read_gpio(struct device_node *node, long param, long value) | 1324 | core99_read_gpio(struct device_node *node, long param, long value) |
| @@ -1338,7 +1338,7 @@ core99_write_gpio(struct device_node *node, long param, long value) | |||
| 1338 | return 0; | 1338 | return 0; |
| 1339 | } | 1339 | } |
| 1340 | 1340 | ||
| 1341 | #ifdef CONFIG_POWER4 | 1341 | #ifdef CONFIG_PPC64 |
| 1342 | static long g5_gmac_enable(struct device_node *node, long param, long value) | 1342 | static long g5_gmac_enable(struct device_node *node, long param, long value) |
| 1343 | { | 1343 | { |
| 1344 | struct macio_chip *macio = &macio_chips[0]; | 1344 | struct macio_chip *macio = &macio_chips[0]; |
| @@ -1550,9 +1550,9 @@ void g5_phy_disable_cpu1(void) | |||
| 1550 | if (uninorth_maj == 3) | 1550 | if (uninorth_maj == 3) |
| 1551 | UN_OUT(U3_API_PHY_CONFIG_1, 0); | 1551 | UN_OUT(U3_API_PHY_CONFIG_1, 0); |
| 1552 | } | 1552 | } |
| 1553 | #endif /* CONFIG_POWER4 */ | 1553 | #endif /* CONFIG_PPC64 */ |
| 1554 | 1554 | ||
| 1555 | #ifndef CONFIG_POWER4 | 1555 | #ifndef CONFIG_PPC64 |
| 1556 | 1556 | ||
| 1557 | 1557 | ||
| 1558 | #ifdef CONFIG_PM | 1558 | #ifdef CONFIG_PM |
| @@ -1864,7 +1864,7 @@ core99_sleep_state(struct device_node *node, long param, long value) | |||
| 1864 | return 0; | 1864 | return 0; |
| 1865 | } | 1865 | } |
| 1866 | 1866 | ||
| 1867 | #endif /* CONFIG_POWER4 */ | 1867 | #endif /* CONFIG_PPC64 */ |
| 1868 | 1868 | ||
| 1869 | static long | 1869 | static long |
| 1870 | generic_dev_can_wake(struct device_node *node, long param, long value) | 1870 | generic_dev_can_wake(struct device_node *node, long param, long value) |
| @@ -1906,7 +1906,7 @@ static struct feature_table_entry any_features[] = { | |||
| 1906 | { 0, NULL } | 1906 | { 0, NULL } |
| 1907 | }; | 1907 | }; |
| 1908 | 1908 | ||
| 1909 | #ifndef CONFIG_POWER4 | 1909 | #ifndef CONFIG_PPC64 |
| 1910 | 1910 | ||
| 1911 | /* OHare based motherboards. Currently, we only use these on the | 1911 | /* OHare based motherboards. Currently, we only use these on the |
| 1912 | * 2400,3400 and 3500 series powerbooks. Some older desktops seem | 1912 | * 2400,3400 and 3500 series powerbooks. Some older desktops seem |
| @@ -2056,7 +2056,7 @@ static struct feature_table_entry intrepid_features[] = { | |||
| 2056 | { 0, NULL } | 2056 | { 0, NULL } |
| 2057 | }; | 2057 | }; |
| 2058 | 2058 | ||
| 2059 | #else /* CONFIG_POWER4 */ | 2059 | #else /* CONFIG_PPC64 */ |
| 2060 | 2060 | ||
| 2061 | /* G5 features | 2061 | /* G5 features |
| 2062 | */ | 2062 | */ |
| @@ -2074,10 +2074,10 @@ static struct feature_table_entry g5_features[] = { | |||
| 2074 | { 0, NULL } | 2074 | { 0, NULL } |
| 2075 | }; | 2075 | }; |
| 2076 | 2076 | ||
| 2077 | #endif /* CONFIG_POWER4 */ | 2077 | #endif /* CONFIG_PPC64 */ |
| 2078 | 2078 | ||
| 2079 | static struct pmac_mb_def pmac_mb_defs[] = { | 2079 | static struct pmac_mb_def pmac_mb_defs[] = { |
| 2080 | #ifndef CONFIG_POWER4 | 2080 | #ifndef CONFIG_PPC64 |
| 2081 | /* | 2081 | /* |
| 2082 | * Desktops | 2082 | * Desktops |
| 2083 | */ | 2083 | */ |
| @@ -2342,7 +2342,7 @@ static struct pmac_mb_def pmac_mb_defs[] = { | |||
| 2342 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | 2342 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, |
| 2343 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | 2343 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, |
| 2344 | }, | 2344 | }, |
| 2345 | #else /* CONFIG_POWER4 */ | 2345 | #else /* CONFIG_PPC64 */ |
| 2346 | { "PowerMac7,2", "PowerMac G5", | 2346 | { "PowerMac7,2", "PowerMac G5", |
| 2347 | PMAC_TYPE_POWERMAC_G5, g5_features, | 2347 | PMAC_TYPE_POWERMAC_G5, g5_features, |
| 2348 | 0, | 2348 | 0, |
| @@ -2373,7 +2373,7 @@ static struct pmac_mb_def pmac_mb_defs[] = { | |||
| 2373 | 0, | 2373 | 0, |
| 2374 | }, | 2374 | }, |
| 2375 | #endif /* CONFIG_PPC64 */ | 2375 | #endif /* CONFIG_PPC64 */ |
| 2376 | #endif /* CONFIG_POWER4 */ | 2376 | #endif /* CONFIG_PPC64 */ |
| 2377 | }; | 2377 | }; |
| 2378 | 2378 | ||
| 2379 | /* | 2379 | /* |
| @@ -2441,7 +2441,7 @@ static int __init probe_motherboard(void) | |||
| 2441 | 2441 | ||
| 2442 | /* Fallback to selection depending on mac-io chip type */ | 2442 | /* Fallback to selection depending on mac-io chip type */ |
| 2443 | switch(macio->type) { | 2443 | switch(macio->type) { |
| 2444 | #ifndef CONFIG_POWER4 | 2444 | #ifndef CONFIG_PPC64 |
| 2445 | case macio_grand_central: | 2445 | case macio_grand_central: |
| 2446 | pmac_mb.model_id = PMAC_TYPE_PSURGE; | 2446 | pmac_mb.model_id = PMAC_TYPE_PSURGE; |
| 2447 | pmac_mb.model_name = "Unknown PowerSurge"; | 2447 | pmac_mb.model_name = "Unknown PowerSurge"; |
| @@ -2475,7 +2475,7 @@ static int __init probe_motherboard(void) | |||
| 2475 | pmac_mb.model_name = "Unknown Intrepid-based"; | 2475 | pmac_mb.model_name = "Unknown Intrepid-based"; |
| 2476 | pmac_mb.features = intrepid_features; | 2476 | pmac_mb.features = intrepid_features; |
| 2477 | break; | 2477 | break; |
| 2478 | #else /* CONFIG_POWER4 */ | 2478 | #else /* CONFIG_PPC64 */ |
| 2479 | case macio_keylargo2: | 2479 | case macio_keylargo2: |
| 2480 | pmac_mb.model_id = PMAC_TYPE_UNKNOWN_K2; | 2480 | pmac_mb.model_id = PMAC_TYPE_UNKNOWN_K2; |
| 2481 | pmac_mb.model_name = "Unknown K2-based"; | 2481 | pmac_mb.model_name = "Unknown K2-based"; |
| @@ -2486,13 +2486,13 @@ static int __init probe_motherboard(void) | |||
| 2486 | pmac_mb.model_name = "Unknown Shasta-based"; | 2486 | pmac_mb.model_name = "Unknown Shasta-based"; |
| 2487 | pmac_mb.features = g5_features; | 2487 | pmac_mb.features = g5_features; |
| 2488 | break; | 2488 | break; |
| 2489 | #endif /* CONFIG_POWER4 */ | 2489 | #endif /* CONFIG_PPC64 */ |
| 2490 | default: | 2490 | default: |
| 2491 | ret = -ENODEV; | 2491 | ret = -ENODEV; |
| 2492 | goto done; | 2492 | goto done; |
| 2493 | } | 2493 | } |
| 2494 | found: | 2494 | found: |
| 2495 | #ifndef CONFIG_POWER4 | 2495 | #ifndef CONFIG_PPC64 |
| 2496 | /* Fixup Hooper vs. Comet */ | 2496 | /* Fixup Hooper vs. Comet */ |
| 2497 | if (pmac_mb.model_id == PMAC_TYPE_HOOPER) { | 2497 | if (pmac_mb.model_id == PMAC_TYPE_HOOPER) { |
| 2498 | u32 __iomem * mach_id_ptr = ioremap(0xf3000034, 4); | 2498 | u32 __iomem * mach_id_ptr = ioremap(0xf3000034, 4); |
| @@ -2546,9 +2546,9 @@ found: | |||
| 2546 | */ | 2546 | */ |
| 2547 | powersave_lowspeed = 1; | 2547 | powersave_lowspeed = 1; |
| 2548 | 2548 | ||
| 2549 | #else /* CONFIG_POWER4 */ | 2549 | #else /* CONFIG_PPC64 */ |
| 2550 | powersave_nap = 1; | 2550 | powersave_nap = 1; |
| 2551 | #endif /* CONFIG_POWER4 */ | 2551 | #endif /* CONFIG_PPC64 */ |
| 2552 | 2552 | ||
| 2553 | /* Check for "mobile" machine */ | 2553 | /* Check for "mobile" machine */ |
| 2554 | if (model && (strncmp(model, "PowerBook", 9) == 0 | 2554 | if (model && (strncmp(model, "PowerBook", 9) == 0 |
| @@ -2786,7 +2786,7 @@ set_initial_features(void) | |||
| 2786 | MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); | 2786 | MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); |
| 2787 | } | 2787 | } |
| 2788 | 2788 | ||
| 2789 | #ifdef CONFIG_POWER4 | 2789 | #ifdef CONFIG_PPC64 |
| 2790 | if (macio_chips[0].type == macio_keylargo2 || | 2790 | if (macio_chips[0].type == macio_keylargo2 || |
| 2791 | macio_chips[0].type == macio_shasta) { | 2791 | macio_chips[0].type == macio_shasta) { |
| 2792 | #ifndef CONFIG_SMP | 2792 | #ifndef CONFIG_SMP |
| @@ -2826,7 +2826,7 @@ set_initial_features(void) | |||
| 2826 | np = of_find_node_by_name(np, "firewire"); | 2826 | np = of_find_node_by_name(np, "firewire"); |
| 2827 | } | 2827 | } |
| 2828 | } | 2828 | } |
| 2829 | #else /* CONFIG_POWER4 */ | 2829 | #else /* CONFIG_PPC64 */ |
| 2830 | 2830 | ||
| 2831 | if (macio_chips[0].type == macio_keylargo || | 2831 | if (macio_chips[0].type == macio_keylargo || |
| 2832 | macio_chips[0].type == macio_pangea || | 2832 | macio_chips[0].type == macio_pangea || |
| @@ -2895,7 +2895,7 @@ set_initial_features(void) | |||
| 2895 | MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N); | 2895 | MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N); |
| 2896 | } | 2896 | } |
| 2897 | 2897 | ||
| 2898 | #endif /* CONFIG_POWER4 */ | 2898 | #endif /* CONFIG_PPC64 */ |
| 2899 | 2899 | ||
| 2900 | /* On all machines, switch modem & serial ports off */ | 2900 | /* On all machines, switch modem & serial ports off */ |
| 2901 | for_each_node_by_name(np, "ch-a") | 2901 | for_each_node_by_name(np, "ch-a") |
diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile index 4ad227d04c1a..f241accc053d 100644 --- a/arch/powerpc/platforms/powernv/Makefile +++ b/arch/powerpc/platforms/powernv/Makefile | |||
| @@ -1,10 +1,11 @@ | |||
| 1 | obj-y += setup.o opal-wrappers.o opal.o opal-async.o | 1 | obj-y += setup.o opal-wrappers.o opal.o opal-async.o |
| 2 | obj-y += opal-rtc.o opal-nvram.o opal-lpc.o opal-flash.o | 2 | obj-y += opal-rtc.o opal-nvram.o opal-lpc.o opal-flash.o |
| 3 | obj-y += rng.o opal-elog.o opal-dump.o opal-sysparam.o opal-sensor.o | 3 | obj-y += rng.o opal-elog.o opal-dump.o opal-sysparam.o opal-sensor.o |
| 4 | obj-y += opal-msglog.o | 4 | obj-y += opal-msglog.o opal-hmi.o |
| 5 | 5 | ||
| 6 | obj-$(CONFIG_SMP) += smp.o subcore.o subcore-asm.o | 6 | obj-$(CONFIG_SMP) += smp.o subcore.o subcore-asm.o |
| 7 | obj-$(CONFIG_PCI) += pci.o pci-p5ioc2.o pci-ioda.o | 7 | obj-$(CONFIG_PCI) += pci.o pci-p5ioc2.o pci-ioda.o |
| 8 | obj-$(CONFIG_EEH) += eeh-ioda.o eeh-powernv.o | 8 | obj-$(CONFIG_EEH) += eeh-ioda.o eeh-powernv.o |
| 9 | obj-$(CONFIG_PPC_SCOM) += opal-xscom.o | 9 | obj-$(CONFIG_PPC_SCOM) += opal-xscom.o |
| 10 | obj-$(CONFIG_MEMORY_FAILURE) += opal-memory-errors.o | 10 | obj-$(CONFIG_MEMORY_FAILURE) += opal-memory-errors.o |
| 11 | obj-$(CONFIG_TRACEPOINTS) += opal-tracepoints.o | ||
diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c index 8ad0c5b891f4..c945bed4dc9e 100644 --- a/arch/powerpc/platforms/powernv/eeh-ioda.c +++ b/arch/powerpc/platforms/powernv/eeh-ioda.c | |||
| @@ -187,10 +187,10 @@ static int ioda_eeh_post_init(struct pci_controller *hose) | |||
| 187 | */ | 187 | */ |
| 188 | static int ioda_eeh_set_option(struct eeh_pe *pe, int option) | 188 | static int ioda_eeh_set_option(struct eeh_pe *pe, int option) |
| 189 | { | 189 | { |
| 190 | s64 ret; | ||
| 191 | u32 pe_no; | ||
| 192 | struct pci_controller *hose = pe->phb; | 190 | struct pci_controller *hose = pe->phb; |
| 193 | struct pnv_phb *phb = hose->private_data; | 191 | struct pnv_phb *phb = hose->private_data; |
| 192 | int enable, ret = 0; | ||
| 193 | s64 rc; | ||
| 194 | 194 | ||
| 195 | /* Check on PE number */ | 195 | /* Check on PE number */ |
| 196 | if (pe->addr < 0 || pe->addr >= phb->ioda.total_pe) { | 196 | if (pe->addr < 0 || pe->addr >= phb->ioda.total_pe) { |
| @@ -201,184 +201,214 @@ static int ioda_eeh_set_option(struct eeh_pe *pe, int option) | |||
| 201 | return -EINVAL; | 201 | return -EINVAL; |
| 202 | } | 202 | } |
| 203 | 203 | ||
| 204 | pe_no = pe->addr; | ||
| 205 | switch (option) { | 204 | switch (option) { |
| 206 | case EEH_OPT_DISABLE: | 205 | case EEH_OPT_DISABLE: |
| 207 | ret = -EEXIST; | 206 | return -EPERM; |
| 208 | break; | ||
| 209 | case EEH_OPT_ENABLE: | 207 | case EEH_OPT_ENABLE: |
| 210 | ret = 0; | 208 | return 0; |
| 211 | break; | ||
| 212 | case EEH_OPT_THAW_MMIO: | 209 | case EEH_OPT_THAW_MMIO: |
| 213 | ret = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no, | 210 | enable = OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO; |
| 214 | OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO); | ||
| 215 | if (ret) { | ||
| 216 | pr_warning("%s: Failed to enable MMIO for " | ||
| 217 | "PHB#%x-PE#%x, err=%lld\n", | ||
| 218 | __func__, hose->global_number, pe_no, ret); | ||
| 219 | return -EIO; | ||
| 220 | } | ||
| 221 | |||
| 222 | break; | 211 | break; |
| 223 | case EEH_OPT_THAW_DMA: | 212 | case EEH_OPT_THAW_DMA: |
| 224 | ret = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no, | 213 | enable = OPAL_EEH_ACTION_CLEAR_FREEZE_DMA; |
| 225 | OPAL_EEH_ACTION_CLEAR_FREEZE_DMA); | ||
| 226 | if (ret) { | ||
| 227 | pr_warning("%s: Failed to enable DMA for " | ||
| 228 | "PHB#%x-PE#%x, err=%lld\n", | ||
| 229 | __func__, hose->global_number, pe_no, ret); | ||
| 230 | return -EIO; | ||
| 231 | } | ||
| 232 | |||
| 233 | break; | 214 | break; |
| 234 | default: | 215 | default: |
| 235 | pr_warning("%s: Invalid option %d\n", __func__, option); | 216 | pr_warn("%s: Invalid option %d\n", |
| 217 | __func__, option); | ||
| 236 | return -EINVAL; | 218 | return -EINVAL; |
| 237 | } | 219 | } |
| 238 | 220 | ||
| 221 | /* If PHB supports compound PE, to handle it */ | ||
| 222 | if (phb->unfreeze_pe) { | ||
| 223 | ret = phb->unfreeze_pe(phb, pe->addr, enable); | ||
| 224 | } else { | ||
| 225 | rc = opal_pci_eeh_freeze_clear(phb->opal_id, | ||
| 226 | pe->addr, | ||
| 227 | enable); | ||
| 228 | if (rc != OPAL_SUCCESS) { | ||
| 229 | pr_warn("%s: Failure %lld enable %d for PHB#%x-PE#%x\n", | ||
| 230 | __func__, rc, option, phb->hose->global_number, | ||
| 231 | pe->addr); | ||
| 232 | ret = -EIO; | ||
| 233 | } | ||
| 234 | } | ||
| 235 | |||
| 239 | return ret; | 236 | return ret; |
| 240 | } | 237 | } |
| 241 | 238 | ||
| 242 | static void ioda_eeh_phb_diag(struct pci_controller *hose) | 239 | static void ioda_eeh_phb_diag(struct eeh_pe *pe) |
| 243 | { | 240 | { |
| 244 | struct pnv_phb *phb = hose->private_data; | 241 | struct pnv_phb *phb = pe->phb->private_data; |
| 245 | long rc; | 242 | long rc; |
| 246 | 243 | ||
| 247 | rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob, | 244 | rc = opal_pci_get_phb_diag_data2(phb->opal_id, pe->data, |
| 248 | PNV_PCI_DIAG_BUF_SIZE); | 245 | PNV_PCI_DIAG_BUF_SIZE); |
| 249 | if (rc != OPAL_SUCCESS) { | 246 | if (rc != OPAL_SUCCESS) |
| 250 | pr_warning("%s: Failed to get diag-data for PHB#%x (%ld)\n", | 247 | pr_warn("%s: Failed to get diag-data for PHB#%x (%ld)\n", |
| 251 | __func__, hose->global_number, rc); | 248 | __func__, pe->phb->global_number, rc); |
| 252 | return; | ||
| 253 | } | ||
| 254 | |||
| 255 | pnv_pci_dump_phb_diag_data(hose, phb->diag.blob); | ||
| 256 | } | 249 | } |
| 257 | 250 | ||
| 258 | /** | 251 | static int ioda_eeh_get_phb_state(struct eeh_pe *pe) |
| 259 | * ioda_eeh_get_state - Retrieve the state of PE | ||
| 260 | * @pe: EEH PE | ||
| 261 | * | ||
| 262 | * The PE's state should be retrieved from the PEEV, PEST | ||
| 263 | * IODA tables. Since the OPAL has exported the function | ||
| 264 | * to do it, it'd better to use that. | ||
| 265 | */ | ||
| 266 | static int ioda_eeh_get_state(struct eeh_pe *pe) | ||
| 267 | { | 252 | { |
| 268 | s64 ret = 0; | 253 | struct pnv_phb *phb = pe->phb->private_data; |
| 269 | u8 fstate; | 254 | u8 fstate; |
| 270 | __be16 pcierr; | 255 | __be16 pcierr; |
| 271 | u32 pe_no; | 256 | s64 rc; |
| 272 | int result; | 257 | int result = 0; |
| 273 | struct pci_controller *hose = pe->phb; | 258 | |
| 274 | struct pnv_phb *phb = hose->private_data; | 259 | rc = opal_pci_eeh_freeze_status(phb->opal_id, |
| 260 | pe->addr, | ||
| 261 | &fstate, | ||
| 262 | &pcierr, | ||
| 263 | NULL); | ||
| 264 | if (rc != OPAL_SUCCESS) { | ||
| 265 | pr_warn("%s: Failure %lld getting PHB#%x state\n", | ||
| 266 | __func__, rc, phb->hose->global_number); | ||
| 267 | return EEH_STATE_NOT_SUPPORT; | ||
| 268 | } | ||
| 275 | 269 | ||
| 276 | /* | 270 | /* |
| 277 | * Sanity check on PE address. The PHB PE address should | 271 | * Check PHB state. If the PHB is frozen for the |
| 278 | * be zero. | 272 | * first time, to dump the PHB diag-data. |
| 279 | */ | 273 | */ |
| 280 | if (pe->addr < 0 || pe->addr >= phb->ioda.total_pe) { | 274 | if (be16_to_cpu(pcierr) != OPAL_EEH_PHB_ERROR) { |
| 281 | pr_err("%s: PE address %x out of range [0, %x] " | 275 | result = (EEH_STATE_MMIO_ACTIVE | |
| 282 | "on PHB#%x\n", | 276 | EEH_STATE_DMA_ACTIVE | |
| 283 | __func__, pe->addr, phb->ioda.total_pe, | 277 | EEH_STATE_MMIO_ENABLED | |
| 284 | hose->global_number); | 278 | EEH_STATE_DMA_ENABLED); |
| 285 | return EEH_STATE_NOT_SUPPORT; | 279 | } else if (!(pe->state & EEH_PE_ISOLATED)) { |
| 280 | eeh_pe_state_mark(pe, EEH_PE_ISOLATED); | ||
| 281 | ioda_eeh_phb_diag(pe); | ||
| 286 | } | 282 | } |
| 287 | 283 | ||
| 284 | return result; | ||
| 285 | } | ||
| 286 | |||
| 287 | static int ioda_eeh_get_pe_state(struct eeh_pe *pe) | ||
| 288 | { | ||
| 289 | struct pnv_phb *phb = pe->phb->private_data; | ||
| 290 | u8 fstate; | ||
| 291 | __be16 pcierr; | ||
| 292 | s64 rc; | ||
| 293 | int result; | ||
| 294 | |||
| 288 | /* | 295 | /* |
| 289 | * If we're in middle of PE reset, return normal | 296 | * We don't clobber hardware frozen state until PE |
| 290 | * state to keep EEH core going. For PHB reset, we | 297 | * reset is completed. In order to keep EEH core |
| 291 | * still expect to have fenced PHB cleared with | 298 | * moving forward, we have to return operational |
| 292 | * PHB reset. | 299 | * state during PE reset. |
| 293 | */ | 300 | */ |
| 294 | if (!(pe->type & EEH_PE_PHB) && | 301 | if (pe->state & EEH_PE_RESET) { |
| 295 | (pe->state & EEH_PE_RESET)) { | 302 | result = (EEH_STATE_MMIO_ACTIVE | |
| 296 | result = (EEH_STATE_MMIO_ACTIVE | | 303 | EEH_STATE_DMA_ACTIVE | |
| 297 | EEH_STATE_DMA_ACTIVE | | ||
| 298 | EEH_STATE_MMIO_ENABLED | | 304 | EEH_STATE_MMIO_ENABLED | |
| 299 | EEH_STATE_DMA_ENABLED); | 305 | EEH_STATE_DMA_ENABLED); |
| 300 | return result; | 306 | return result; |
| 301 | } | 307 | } |
| 302 | 308 | ||
| 303 | /* Retrieve PE status through OPAL */ | 309 | /* |
| 304 | pe_no = pe->addr; | 310 | * Fetch PE state from hardware. If the PHB |
| 305 | ret = opal_pci_eeh_freeze_status(phb->opal_id, pe_no, | 311 | * supports compound PE, let it handle that. |
| 306 | &fstate, &pcierr, NULL); | 312 | */ |
| 307 | if (ret) { | 313 | if (phb->get_pe_state) { |
| 308 | pr_err("%s: Failed to get EEH status on " | 314 | fstate = phb->get_pe_state(phb, pe->addr); |
| 309 | "PHB#%x-PE#%x\n, err=%lld\n", | 315 | } else { |
| 310 | __func__, hose->global_number, pe_no, ret); | 316 | rc = opal_pci_eeh_freeze_status(phb->opal_id, |
| 311 | return EEH_STATE_NOT_SUPPORT; | 317 | pe->addr, |
| 312 | } | 318 | &fstate, |
| 313 | 319 | &pcierr, | |
| 314 | /* Check PHB status */ | 320 | NULL); |
| 315 | if (pe->type & EEH_PE_PHB) { | 321 | if (rc != OPAL_SUCCESS) { |
| 316 | result = 0; | 322 | pr_warn("%s: Failure %lld getting PHB#%x-PE%x state\n", |
| 317 | result &= ~EEH_STATE_RESET_ACTIVE; | 323 | __func__, rc, phb->hose->global_number, pe->addr); |
| 318 | 324 | return EEH_STATE_NOT_SUPPORT; | |
| 319 | if (be16_to_cpu(pcierr) != OPAL_EEH_PHB_ERROR) { | ||
| 320 | result |= EEH_STATE_MMIO_ACTIVE; | ||
| 321 | result |= EEH_STATE_DMA_ACTIVE; | ||
| 322 | result |= EEH_STATE_MMIO_ENABLED; | ||
| 323 | result |= EEH_STATE_DMA_ENABLED; | ||
| 324 | } else if (!(pe->state & EEH_PE_ISOLATED)) { | ||
| 325 | eeh_pe_state_mark(pe, EEH_PE_ISOLATED); | ||
| 326 | ioda_eeh_phb_diag(hose); | ||
| 327 | } | 325 | } |
| 328 | |||
| 329 | return result; | ||
| 330 | } | 326 | } |
| 331 | 327 | ||
| 332 | /* Parse result out */ | 328 | /* Figure out state */ |
| 333 | result = 0; | ||
| 334 | switch (fstate) { | 329 | switch (fstate) { |
| 335 | case OPAL_EEH_STOPPED_NOT_FROZEN: | 330 | case OPAL_EEH_STOPPED_NOT_FROZEN: |
| 336 | result &= ~EEH_STATE_RESET_ACTIVE; | 331 | result = (EEH_STATE_MMIO_ACTIVE | |
| 337 | result |= EEH_STATE_MMIO_ACTIVE; | 332 | EEH_STATE_DMA_ACTIVE | |
| 338 | result |= EEH_STATE_DMA_ACTIVE; | 333 | EEH_STATE_MMIO_ENABLED | |
| 339 | result |= EEH_STATE_MMIO_ENABLED; | 334 | EEH_STATE_DMA_ENABLED); |
| 340 | result |= EEH_STATE_DMA_ENABLED; | ||
| 341 | break; | 335 | break; |
| 342 | case OPAL_EEH_STOPPED_MMIO_FREEZE: | 336 | case OPAL_EEH_STOPPED_MMIO_FREEZE: |
| 343 | result &= ~EEH_STATE_RESET_ACTIVE; | 337 | result = (EEH_STATE_DMA_ACTIVE | |
| 344 | result |= EEH_STATE_DMA_ACTIVE; | 338 | EEH_STATE_DMA_ENABLED); |
| 345 | result |= EEH_STATE_DMA_ENABLED; | ||
| 346 | break; | 339 | break; |
| 347 | case OPAL_EEH_STOPPED_DMA_FREEZE: | 340 | case OPAL_EEH_STOPPED_DMA_FREEZE: |
| 348 | result &= ~EEH_STATE_RESET_ACTIVE; | 341 | result = (EEH_STATE_MMIO_ACTIVE | |
| 349 | result |= EEH_STATE_MMIO_ACTIVE; | 342 | EEH_STATE_MMIO_ENABLED); |
| 350 | result |= EEH_STATE_MMIO_ENABLED; | ||
| 351 | break; | 343 | break; |
| 352 | case OPAL_EEH_STOPPED_MMIO_DMA_FREEZE: | 344 | case OPAL_EEH_STOPPED_MMIO_DMA_FREEZE: |
| 353 | result &= ~EEH_STATE_RESET_ACTIVE; | 345 | result = 0; |
| 354 | break; | 346 | break; |
| 355 | case OPAL_EEH_STOPPED_RESET: | 347 | case OPAL_EEH_STOPPED_RESET: |
| 356 | result |= EEH_STATE_RESET_ACTIVE; | 348 | result = EEH_STATE_RESET_ACTIVE; |
| 357 | break; | 349 | break; |
| 358 | case OPAL_EEH_STOPPED_TEMP_UNAVAIL: | 350 | case OPAL_EEH_STOPPED_TEMP_UNAVAIL: |
| 359 | result |= EEH_STATE_UNAVAILABLE; | 351 | result = EEH_STATE_UNAVAILABLE; |
| 360 | break; | 352 | break; |
| 361 | case OPAL_EEH_STOPPED_PERM_UNAVAIL: | 353 | case OPAL_EEH_STOPPED_PERM_UNAVAIL: |
| 362 | result |= EEH_STATE_NOT_SUPPORT; | 354 | result = EEH_STATE_NOT_SUPPORT; |
| 363 | break; | 355 | break; |
| 364 | default: | 356 | default: |
| 365 | pr_warning("%s: Unexpected EEH status 0x%x " | 357 | result = EEH_STATE_NOT_SUPPORT; |
| 366 | "on PHB#%x-PE#%x\n", | 358 | pr_warn("%s: Invalid PHB#%x-PE#%x state %x\n", |
| 367 | __func__, fstate, hose->global_number, pe_no); | 359 | __func__, phb->hose->global_number, |
| 360 | pe->addr, fstate); | ||
| 368 | } | 361 | } |
| 369 | 362 | ||
| 370 | /* Dump PHB diag-data for frozen PE */ | 363 | /* |
| 371 | if (result != EEH_STATE_NOT_SUPPORT && | 364 | * If PHB supports compound PE, to freeze all |
| 372 | (result & (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) != | 365 | * slave PEs for consistency. |
| 373 | (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE) && | 366 | * |
| 367 | * If the PE is switching to frozen state for the | ||
| 368 | * first time, to dump the PHB diag-data. | ||
| 369 | */ | ||
| 370 | if (!(result & EEH_STATE_NOT_SUPPORT) && | ||
| 371 | !(result & EEH_STATE_UNAVAILABLE) && | ||
| 372 | !(result & EEH_STATE_MMIO_ACTIVE) && | ||
| 373 | !(result & EEH_STATE_DMA_ACTIVE) && | ||
| 374 | !(pe->state & EEH_PE_ISOLATED)) { | 374 | !(pe->state & EEH_PE_ISOLATED)) { |
| 375 | if (phb->freeze_pe) | ||
| 376 | phb->freeze_pe(phb, pe->addr); | ||
| 377 | |||
| 375 | eeh_pe_state_mark(pe, EEH_PE_ISOLATED); | 378 | eeh_pe_state_mark(pe, EEH_PE_ISOLATED); |
| 376 | ioda_eeh_phb_diag(hose); | 379 | ioda_eeh_phb_diag(pe); |
| 377 | } | 380 | } |
| 378 | 381 | ||
| 379 | return result; | 382 | return result; |
| 380 | } | 383 | } |
| 381 | 384 | ||
| 385 | /** | ||
| 386 | * ioda_eeh_get_state - Retrieve the state of PE | ||
| 387 | * @pe: EEH PE | ||
| 388 | * | ||
| 389 | * The PE's state should be retrieved from the PEEV, PEST | ||
| 390 | * IODA tables. Since the OPAL has exported the function | ||
| 391 | * to do it, it'd better to use that. | ||
| 392 | */ | ||
| 393 | static int ioda_eeh_get_state(struct eeh_pe *pe) | ||
| 394 | { | ||
| 395 | struct pnv_phb *phb = pe->phb->private_data; | ||
| 396 | |||
| 397 | /* Sanity check on PE number. PHB PE should have 0 */ | ||
| 398 | if (pe->addr < 0 || | ||
| 399 | pe->addr >= phb->ioda.total_pe) { | ||
| 400 | pr_warn("%s: PHB#%x-PE#%x out of range [0, %x]\n", | ||
| 401 | __func__, phb->hose->global_number, | ||
| 402 | pe->addr, phb->ioda.total_pe); | ||
| 403 | return EEH_STATE_NOT_SUPPORT; | ||
| 404 | } | ||
| 405 | |||
| 406 | if (pe->type & EEH_PE_PHB) | ||
| 407 | return ioda_eeh_get_phb_state(pe); | ||
| 408 | |||
| 409 | return ioda_eeh_get_pe_state(pe); | ||
| 410 | } | ||
| 411 | |||
| 382 | static s64 ioda_eeh_phb_poll(struct pnv_phb *phb) | 412 | static s64 ioda_eeh_phb_poll(struct pnv_phb *phb) |
| 383 | { | 413 | { |
| 384 | s64 rc = OPAL_HARDWARE; | 414 | s64 rc = OPAL_HARDWARE; |
| @@ -589,6 +619,24 @@ static int ioda_eeh_reset(struct eeh_pe *pe, int option) | |||
| 589 | } | 619 | } |
| 590 | 620 | ||
| 591 | /** | 621 | /** |
| 622 | * ioda_eeh_get_log - Retrieve error log | ||
| 623 | * @pe: frozen PE | ||
| 624 | * @severity: permanent or temporary error | ||
| 625 | * @drv_log: device driver log | ||
| 626 | * @len: length of device driver log | ||
| 627 | * | ||
| 628 | * Retrieve error log, which contains log from device driver | ||
| 629 | * and firmware. | ||
| 630 | */ | ||
| 631 | int ioda_eeh_get_log(struct eeh_pe *pe, int severity, | ||
| 632 | char *drv_log, unsigned long len) | ||
| 633 | { | ||
| 634 | pnv_pci_dump_phb_diag_data(pe->phb, pe->data); | ||
| 635 | |||
| 636 | return 0; | ||
| 637 | } | ||
| 638 | |||
| 639 | /** | ||
| 592 | * ioda_eeh_configure_bridge - Configure the PCI bridges for the indicated PE | 640 | * ioda_eeh_configure_bridge - Configure the PCI bridges for the indicated PE |
| 593 | * @pe: EEH PE | 641 | * @pe: EEH PE |
| 594 | * | 642 | * |
| @@ -605,18 +653,24 @@ static int ioda_eeh_configure_bridge(struct eeh_pe *pe) | |||
| 605 | static void ioda_eeh_hub_diag_common(struct OpalIoP7IOCErrorData *data) | 653 | static void ioda_eeh_hub_diag_common(struct OpalIoP7IOCErrorData *data) |
| 606 | { | 654 | { |
| 607 | /* GEM */ | 655 | /* GEM */ |
| 608 | pr_info(" GEM XFIR: %016llx\n", data->gemXfir); | 656 | if (data->gemXfir || data->gemRfir || |
| 609 | pr_info(" GEM RFIR: %016llx\n", data->gemRfir); | 657 | data->gemRirqfir || data->gemMask || data->gemRwof) |
| 610 | pr_info(" GEM RIRQFIR: %016llx\n", data->gemRirqfir); | 658 | pr_info(" GEM: %016llx %016llx %016llx %016llx %016llx\n", |
| 611 | pr_info(" GEM Mask: %016llx\n", data->gemMask); | 659 | be64_to_cpu(data->gemXfir), |
| 612 | pr_info(" GEM RWOF: %016llx\n", data->gemRwof); | 660 | be64_to_cpu(data->gemRfir), |
| 661 | be64_to_cpu(data->gemRirqfir), | ||
| 662 | be64_to_cpu(data->gemMask), | ||
| 663 | be64_to_cpu(data->gemRwof)); | ||
| 613 | 664 | ||
| 614 | /* LEM */ | 665 | /* LEM */ |
| 615 | pr_info(" LEM FIR: %016llx\n", data->lemFir); | 666 | if (data->lemFir || data->lemErrMask || |
| 616 | pr_info(" LEM Error Mask: %016llx\n", data->lemErrMask); | 667 | data->lemAction0 || data->lemAction1 || data->lemWof) |
| 617 | pr_info(" LEM Action 0: %016llx\n", data->lemAction0); | 668 | pr_info(" LEM: %016llx %016llx %016llx %016llx %016llx\n", |
| 618 | pr_info(" LEM Action 1: %016llx\n", data->lemAction1); | 669 | be64_to_cpu(data->lemFir), |
| 619 | pr_info(" LEM WOF: %016llx\n", data->lemWof); | 670 | be64_to_cpu(data->lemErrMask), |
| 671 | be64_to_cpu(data->lemAction0), | ||
| 672 | be64_to_cpu(data->lemAction1), | ||
| 673 | be64_to_cpu(data->lemWof)); | ||
| 620 | } | 674 | } |
| 621 | 675 | ||
| 622 | static void ioda_eeh_hub_diag(struct pci_controller *hose) | 676 | static void ioda_eeh_hub_diag(struct pci_controller *hose) |
| @@ -627,8 +681,8 @@ static void ioda_eeh_hub_diag(struct pci_controller *hose) | |||
| 627 | 681 | ||
| 628 | rc = opal_pci_get_hub_diag_data(phb->hub_id, data, sizeof(*data)); | 682 | rc = opal_pci_get_hub_diag_data(phb->hub_id, data, sizeof(*data)); |
| 629 | if (rc != OPAL_SUCCESS) { | 683 | if (rc != OPAL_SUCCESS) { |
| 630 | pr_warning("%s: Failed to get HUB#%llx diag-data (%ld)\n", | 684 | pr_warn("%s: Failed to get HUB#%llx diag-data (%ld)\n", |
| 631 | __func__, phb->hub_id, rc); | 685 | __func__, phb->hub_id, rc); |
| 632 | return; | 686 | return; |
| 633 | } | 687 | } |
| 634 | 688 | ||
| @@ -636,24 +690,31 @@ static void ioda_eeh_hub_diag(struct pci_controller *hose) | |||
| 636 | case OPAL_P7IOC_DIAG_TYPE_RGC: | 690 | case OPAL_P7IOC_DIAG_TYPE_RGC: |
| 637 | pr_info("P7IOC diag-data for RGC\n\n"); | 691 | pr_info("P7IOC diag-data for RGC\n\n"); |
| 638 | ioda_eeh_hub_diag_common(data); | 692 | ioda_eeh_hub_diag_common(data); |
| 639 | pr_info(" RGC Status: %016llx\n", data->rgc.rgcStatus); | 693 | if (data->rgc.rgcStatus || data->rgc.rgcLdcp) |
| 640 | pr_info(" RGC LDCP: %016llx\n", data->rgc.rgcLdcp); | 694 | pr_info(" RGC: %016llx %016llx\n", |
| 695 | be64_to_cpu(data->rgc.rgcStatus), | ||
| 696 | be64_to_cpu(data->rgc.rgcLdcp)); | ||
| 641 | break; | 697 | break; |
| 642 | case OPAL_P7IOC_DIAG_TYPE_BI: | 698 | case OPAL_P7IOC_DIAG_TYPE_BI: |
| 643 | pr_info("P7IOC diag-data for BI %s\n\n", | 699 | pr_info("P7IOC diag-data for BI %s\n\n", |
| 644 | data->bi.biDownbound ? "Downbound" : "Upbound"); | 700 | data->bi.biDownbound ? "Downbound" : "Upbound"); |
| 645 | ioda_eeh_hub_diag_common(data); | 701 | ioda_eeh_hub_diag_common(data); |
| 646 | pr_info(" BI LDCP 0: %016llx\n", data->bi.biLdcp0); | 702 | if (data->bi.biLdcp0 || data->bi.biLdcp1 || |
| 647 | pr_info(" BI LDCP 1: %016llx\n", data->bi.biLdcp1); | 703 | data->bi.biLdcp2 || data->bi.biFenceStatus) |
| 648 | pr_info(" BI LDCP 2: %016llx\n", data->bi.biLdcp2); | 704 | pr_info(" BI: %016llx %016llx %016llx %016llx\n", |
| 649 | pr_info(" BI Fence Status: %016llx\n", data->bi.biFenceStatus); | 705 | be64_to_cpu(data->bi.biLdcp0), |
| 706 | be64_to_cpu(data->bi.biLdcp1), | ||
| 707 | be64_to_cpu(data->bi.biLdcp2), | ||
| 708 | be64_to_cpu(data->bi.biFenceStatus)); | ||
| 650 | break; | 709 | break; |
| 651 | case OPAL_P7IOC_DIAG_TYPE_CI: | 710 | case OPAL_P7IOC_DIAG_TYPE_CI: |
| 652 | pr_info("P7IOC diag-data for CI Port %d\\nn", | 711 | pr_info("P7IOC diag-data for CI Port %d\n\n", |
| 653 | data->ci.ciPort); | 712 | data->ci.ciPort); |
| 654 | ioda_eeh_hub_diag_common(data); | 713 | ioda_eeh_hub_diag_common(data); |
| 655 | pr_info(" CI Port Status: %016llx\n", data->ci.ciPortStatus); | 714 | if (data->ci.ciPortStatus || data->ci.ciPortLdcp) |
| 656 | pr_info(" CI Port LDCP: %016llx\n", data->ci.ciPortLdcp); | 715 | pr_info(" CI: %016llx %016llx\n", |
| 716 | be64_to_cpu(data->ci.ciPortStatus), | ||
| 717 | be64_to_cpu(data->ci.ciPortLdcp)); | ||
| 657 | break; | 718 | break; |
| 658 | case OPAL_P7IOC_DIAG_TYPE_MISC: | 719 | case OPAL_P7IOC_DIAG_TYPE_MISC: |
| 659 | pr_info("P7IOC diag-data for MISC\n\n"); | 720 | pr_info("P7IOC diag-data for MISC\n\n"); |
| @@ -664,30 +725,51 @@ static void ioda_eeh_hub_diag(struct pci_controller *hose) | |||
| 664 | ioda_eeh_hub_diag_common(data); | 725 | ioda_eeh_hub_diag_common(data); |
| 665 | break; | 726 | break; |
| 666 | default: | 727 | default: |
| 667 | pr_warning("%s: Invalid type of HUB#%llx diag-data (%d)\n", | 728 | pr_warn("%s: Invalid type of HUB#%llx diag-data (%d)\n", |
| 668 | __func__, phb->hub_id, data->type); | 729 | __func__, phb->hub_id, data->type); |
| 669 | } | 730 | } |
| 670 | } | 731 | } |
| 671 | 732 | ||
| 672 | static int ioda_eeh_get_pe(struct pci_controller *hose, | 733 | static int ioda_eeh_get_pe(struct pci_controller *hose, |
| 673 | u16 pe_no, struct eeh_pe **pe) | 734 | u16 pe_no, struct eeh_pe **pe) |
| 674 | { | 735 | { |
| 675 | struct eeh_pe *phb_pe, *dev_pe; | 736 | struct pnv_phb *phb = hose->private_data; |
| 676 | struct eeh_dev dev; | 737 | struct pnv_ioda_pe *pnv_pe; |
| 738 | struct eeh_pe *dev_pe; | ||
| 739 | struct eeh_dev edev; | ||
| 677 | 740 | ||
| 678 | /* Find the PHB PE */ | 741 | /* |
| 679 | phb_pe = eeh_phb_pe_get(hose); | 742 | * If PHB supports compound PE, to fetch |
| 680 | if (!phb_pe) | 743 | * the master PE because slave PE is invisible |
| 681 | return -EEXIST; | 744 | * to EEH core. |
| 745 | */ | ||
| 746 | if (phb->get_pe_state) { | ||
| 747 | pnv_pe = &phb->ioda.pe_array[pe_no]; | ||
| 748 | if (pnv_pe->flags & PNV_IODA_PE_SLAVE) { | ||
| 749 | pnv_pe = pnv_pe->master; | ||
| 750 | WARN_ON(!pnv_pe || | ||
| 751 | !(pnv_pe->flags & PNV_IODA_PE_MASTER)); | ||
| 752 | pe_no = pnv_pe->pe_number; | ||
| 753 | } | ||
| 754 | } | ||
| 682 | 755 | ||
| 683 | /* Find the PE according to PE# */ | 756 | /* Find the PE according to PE# */ |
| 684 | memset(&dev, 0, sizeof(struct eeh_dev)); | 757 | memset(&edev, 0, sizeof(struct eeh_dev)); |
| 685 | dev.phb = hose; | 758 | edev.phb = hose; |
| 686 | dev.pe_config_addr = pe_no; | 759 | edev.pe_config_addr = pe_no; |
| 687 | dev_pe = eeh_pe_get(&dev); | 760 | dev_pe = eeh_pe_get(&edev); |
| 688 | if (!dev_pe) return -EEXIST; | 761 | if (!dev_pe) |
| 762 | return -EEXIST; | ||
| 689 | 763 | ||
| 764 | /* | ||
| 765 | * At this point, we're sure the compound PE should | ||
| 766 | * be put into frozen state. | ||
| 767 | */ | ||
| 690 | *pe = dev_pe; | 768 | *pe = dev_pe; |
| 769 | if (phb->freeze_pe && | ||
| 770 | !(dev_pe->state & EEH_PE_ISOLATED)) | ||
| 771 | phb->freeze_pe(phb, pe_no); | ||
| 772 | |||
| 691 | return 0; | 773 | return 0; |
| 692 | } | 774 | } |
| 693 | 775 | ||
| @@ -792,7 +874,8 @@ static int ioda_eeh_next_error(struct eeh_pe **pe) | |||
| 792 | "detected, location: %s\n", | 874 | "detected, location: %s\n", |
| 793 | hose->global_number, | 875 | hose->global_number, |
| 794 | eeh_pe_loc_get(phb_pe)); | 876 | eeh_pe_loc_get(phb_pe)); |
| 795 | ioda_eeh_phb_diag(hose); | 877 | ioda_eeh_phb_diag(phb_pe); |
| 878 | pnv_pci_dump_phb_diag_data(hose, phb_pe->data); | ||
| 796 | ret = EEH_NEXT_ERR_NONE; | 879 | ret = EEH_NEXT_ERR_NONE; |
| 797 | } | 880 | } |
| 798 | 881 | ||
| @@ -812,7 +895,8 @@ static int ioda_eeh_next_error(struct eeh_pe **pe) | |||
| 812 | opal_pci_eeh_freeze_clear(phb->opal_id, frozen_pe_no, | 895 | opal_pci_eeh_freeze_clear(phb->opal_id, frozen_pe_no, |
| 813 | OPAL_EEH_ACTION_CLEAR_FREEZE_ALL); | 896 | OPAL_EEH_ACTION_CLEAR_FREEZE_ALL); |
| 814 | ret = EEH_NEXT_ERR_NONE; | 897 | ret = EEH_NEXT_ERR_NONE; |
| 815 | } else if ((*pe)->state & EEH_PE_ISOLATED) { | 898 | } else if ((*pe)->state & EEH_PE_ISOLATED || |
| 899 | eeh_pe_passed(*pe)) { | ||
| 816 | ret = EEH_NEXT_ERR_NONE; | 900 | ret = EEH_NEXT_ERR_NONE; |
| 817 | } else { | 901 | } else { |
| 818 | pr_err("EEH: Frozen PE#%x on PHB#%x detected\n", | 902 | pr_err("EEH: Frozen PE#%x on PHB#%x detected\n", |
| @@ -839,7 +923,7 @@ static int ioda_eeh_next_error(struct eeh_pe **pe) | |||
| 839 | ret == EEH_NEXT_ERR_FENCED_PHB) && | 923 | ret == EEH_NEXT_ERR_FENCED_PHB) && |
| 840 | !((*pe)->state & EEH_PE_ISOLATED)) { | 924 | !((*pe)->state & EEH_PE_ISOLATED)) { |
| 841 | eeh_pe_state_mark(*pe, EEH_PE_ISOLATED); | 925 | eeh_pe_state_mark(*pe, EEH_PE_ISOLATED); |
| 842 | ioda_eeh_phb_diag(hose); | 926 | ioda_eeh_phb_diag(*pe); |
| 843 | } | 927 | } |
| 844 | 928 | ||
| 845 | /* | 929 | /* |
| @@ -885,6 +969,7 @@ struct pnv_eeh_ops ioda_eeh_ops = { | |||
| 885 | .set_option = ioda_eeh_set_option, | 969 | .set_option = ioda_eeh_set_option, |
| 886 | .get_state = ioda_eeh_get_state, | 970 | .get_state = ioda_eeh_get_state, |
| 887 | .reset = ioda_eeh_reset, | 971 | .reset = ioda_eeh_reset, |
| 972 | .get_log = ioda_eeh_get_log, | ||
| 888 | .configure_bridge = ioda_eeh_configure_bridge, | 973 | .configure_bridge = ioda_eeh_configure_bridge, |
| 889 | .next_error = ioda_eeh_next_error | 974 | .next_error = ioda_eeh_next_error |
| 890 | }; | 975 | }; |
diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index 56a206f32f77..fd7a16f855ed 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c | |||
| @@ -45,14 +45,31 @@ | |||
| 45 | */ | 45 | */ |
| 46 | static int powernv_eeh_init(void) | 46 | static int powernv_eeh_init(void) |
| 47 | { | 47 | { |
| 48 | struct pci_controller *hose; | ||
| 49 | struct pnv_phb *phb; | ||
| 50 | |||
| 48 | /* We require OPALv3 */ | 51 | /* We require OPALv3 */ |
| 49 | if (!firmware_has_feature(FW_FEATURE_OPALv3)) { | 52 | if (!firmware_has_feature(FW_FEATURE_OPALv3)) { |
| 50 | pr_warning("%s: OPALv3 is required !\n", __func__); | 53 | pr_warn("%s: OPALv3 is required !\n", |
| 54 | __func__); | ||
| 51 | return -EINVAL; | 55 | return -EINVAL; |
| 52 | } | 56 | } |
| 53 | 57 | ||
| 54 | /* Set EEH probe mode */ | 58 | /* Set probe mode */ |
| 55 | eeh_probe_mode_set(EEH_PROBE_MODE_DEV); | 59 | eeh_add_flag(EEH_PROBE_MODE_DEV); |
| 60 | |||
| 61 | /* | ||
| 62 | * P7IOC blocks PCI config access to frozen PE, but PHB3 | ||
| 63 | * doesn't do that. So we have to selectively enable I/O | ||
| 64 | * prior to collecting error log. | ||
| 65 | */ | ||
| 66 | list_for_each_entry(hose, &hose_list, list_node) { | ||
| 67 | phb = hose->private_data; | ||
| 68 | |||
| 69 | if (phb->model == PNV_PHB_MODEL_P7IOC) | ||
| 70 | eeh_add_flag(EEH_ENABLE_IO_FOR_LOG); | ||
| 71 | break; | ||
| 72 | } | ||
| 56 | 73 | ||
| 57 | return 0; | 74 | return 0; |
| 58 | } | 75 | } |
| @@ -107,6 +124,7 @@ static int powernv_eeh_dev_probe(struct pci_dev *dev, void *flag) | |||
| 107 | struct pnv_phb *phb = hose->private_data; | 124 | struct pnv_phb *phb = hose->private_data; |
| 108 | struct device_node *dn = pci_device_to_OF_node(dev); | 125 | struct device_node *dn = pci_device_to_OF_node(dev); |
| 109 | struct eeh_dev *edev = of_node_to_eeh_dev(dn); | 126 | struct eeh_dev *edev = of_node_to_eeh_dev(dn); |
| 127 | int ret; | ||
| 110 | 128 | ||
| 111 | /* | 129 | /* |
| 112 | * When probing the root bridge, which doesn't have any | 130 | * When probing the root bridge, which doesn't have any |
| @@ -143,13 +161,27 @@ static int powernv_eeh_dev_probe(struct pci_dev *dev, void *flag) | |||
| 143 | edev->pe_config_addr = phb->bdfn_to_pe(phb, dev->bus, dev->devfn & 0xff); | 161 | edev->pe_config_addr = phb->bdfn_to_pe(phb, dev->bus, dev->devfn & 0xff); |
| 144 | 162 | ||
| 145 | /* Create PE */ | 163 | /* Create PE */ |
| 146 | eeh_add_to_parent_pe(edev); | 164 | ret = eeh_add_to_parent_pe(edev); |
| 165 | if (ret) { | ||
| 166 | pr_warn("%s: Can't add PCI dev %s to parent PE (%d)\n", | ||
| 167 | __func__, pci_name(dev), ret); | ||
| 168 | return ret; | ||
| 169 | } | ||
| 170 | |||
| 171 | /* | ||
| 172 | * Cache the PE primary bus, which can't be fetched when | ||
| 173 | * full hotplug is in progress. In that case, all child | ||
| 174 | * PCI devices of the PE are expected to be removed prior | ||
| 175 | * to PE reset. | ||
| 176 | */ | ||
| 177 | if (!edev->pe->bus) | ||
| 178 | edev->pe->bus = dev->bus; | ||
| 147 | 179 | ||
| 148 | /* | 180 | /* |
| 149 | * Enable EEH explicitly so that we will do EEH check | 181 | * Enable EEH explicitly so that we will do EEH check |
| 150 | * while accessing I/O stuff | 182 | * while accessing I/O stuff |
| 151 | */ | 183 | */ |
| 152 | eeh_set_enable(true); | 184 | eeh_add_flag(EEH_ENABLED); |
| 153 | 185 | ||
| 154 | /* Save memory bars */ | 186 | /* Save memory bars */ |
| 155 | eeh_save_bars(edev); | 187 | eeh_save_bars(edev); |
| @@ -273,8 +305,8 @@ static int powernv_eeh_wait_state(struct eeh_pe *pe, int max_wait) | |||
| 273 | 305 | ||
| 274 | max_wait -= mwait; | 306 | max_wait -= mwait; |
| 275 | if (max_wait <= 0) { | 307 | if (max_wait <= 0) { |
| 276 | pr_warning("%s: Timeout getting PE#%x's state (%d)\n", | 308 | pr_warn("%s: Timeout getting PE#%x's state (%d)\n", |
| 277 | __func__, pe->addr, max_wait); | 309 | __func__, pe->addr, max_wait); |
| 278 | return EEH_STATE_NOT_SUPPORT; | 310 | return EEH_STATE_NOT_SUPPORT; |
| 279 | } | 311 | } |
| 280 | 312 | ||
| @@ -294,7 +326,7 @@ static int powernv_eeh_wait_state(struct eeh_pe *pe, int max_wait) | |||
| 294 | * Retrieve the temporary or permanent error from the PE. | 326 | * Retrieve the temporary or permanent error from the PE. |
| 295 | */ | 327 | */ |
| 296 | static int powernv_eeh_get_log(struct eeh_pe *pe, int severity, | 328 | static int powernv_eeh_get_log(struct eeh_pe *pe, int severity, |
| 297 | char *drv_log, unsigned long len) | 329 | char *drv_log, unsigned long len) |
| 298 | { | 330 | { |
| 299 | struct pci_controller *hose = pe->phb; | 331 | struct pci_controller *hose = pe->phb; |
| 300 | struct pnv_phb *phb = hose->private_data; | 332 | struct pnv_phb *phb = hose->private_data; |
| @@ -398,9 +430,7 @@ static int __init eeh_powernv_init(void) | |||
| 398 | { | 430 | { |
| 399 | int ret = -EINVAL; | 431 | int ret = -EINVAL; |
| 400 | 432 | ||
| 401 | if (!machine_is(powernv)) | 433 | eeh_set_pe_aux_size(PNV_PCI_DIAG_BUF_SIZE); |
| 402 | return ret; | ||
| 403 | |||
| 404 | ret = eeh_ops_register(&powernv_eeh_ops); | 434 | ret = eeh_ops_register(&powernv_eeh_ops); |
| 405 | if (!ret) | 435 | if (!ret) |
| 406 | pr_info("EEH: PowerNV platform initialized\n"); | 436 | pr_info("EEH: PowerNV platform initialized\n"); |
| @@ -409,5 +439,4 @@ static int __init eeh_powernv_init(void) | |||
| 409 | 439 | ||
| 410 | return ret; | 440 | return ret; |
| 411 | } | 441 | } |
| 412 | 442 | machine_early_initcall(powernv, eeh_powernv_init); | |
| 413 | early_initcall(eeh_powernv_init); | ||
diff --git a/arch/powerpc/platforms/powernv/opal-async.c b/arch/powerpc/platforms/powernv/opal-async.c index 32e2adfa5320..e462ab947d16 100644 --- a/arch/powerpc/platforms/powernv/opal-async.c +++ b/arch/powerpc/platforms/powernv/opal-async.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/wait.h> | 20 | #include <linux/wait.h> |
| 21 | #include <linux/gfp.h> | 21 | #include <linux/gfp.h> |
| 22 | #include <linux/of.h> | 22 | #include <linux/of.h> |
| 23 | #include <asm/machdep.h> | ||
| 23 | #include <asm/opal.h> | 24 | #include <asm/opal.h> |
| 24 | 25 | ||
| 25 | #define N_ASYNC_COMPLETIONS 64 | 26 | #define N_ASYNC_COMPLETIONS 64 |
| @@ -201,4 +202,4 @@ out_opal_node: | |||
| 201 | out: | 202 | out: |
| 202 | return err; | 203 | return err; |
| 203 | } | 204 | } |
| 204 | subsys_initcall(opal_async_comp_init); | 205 | machine_subsys_initcall(powernv, opal_async_comp_init); |
diff --git a/arch/powerpc/platforms/powernv/opal-hmi.c b/arch/powerpc/platforms/powernv/opal-hmi.c new file mode 100644 index 000000000000..97ac8dc33667 --- /dev/null +++ b/arch/powerpc/platforms/powernv/opal-hmi.c | |||
| @@ -0,0 +1,188 @@ | |||
| 1 | /* | ||
| 2 | * OPAL hypervisor Maintenance interrupt handling support in PowreNV. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License as published by | ||
| 6 | * the Free Software Foundation; either version 2 of the License, or | ||
| 7 | * (at your option) any later version. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License | ||
| 15 | * along with this program; If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | * | ||
| 17 | * Copyright 2014 IBM Corporation | ||
| 18 | * Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> | ||
| 19 | */ | ||
| 20 | |||
| 21 | #undef DEBUG | ||
| 22 | |||
| 23 | #include <linux/kernel.h> | ||
| 24 | #include <linux/init.h> | ||
| 25 | #include <linux/of.h> | ||
| 26 | #include <linux/mm.h> | ||
| 27 | #include <linux/slab.h> | ||
| 28 | |||
| 29 | #include <asm/opal.h> | ||
| 30 | #include <asm/cputable.h> | ||
| 31 | |||
| 32 | static int opal_hmi_handler_nb_init; | ||
| 33 | struct OpalHmiEvtNode { | ||
| 34 | struct list_head list; | ||
| 35 | struct OpalHMIEvent hmi_evt; | ||
| 36 | }; | ||
| 37 | static LIST_HEAD(opal_hmi_evt_list); | ||
| 38 | static DEFINE_SPINLOCK(opal_hmi_evt_lock); | ||
| 39 | |||
| 40 | static void print_hmi_event_info(struct OpalHMIEvent *hmi_evt) | ||
| 41 | { | ||
| 42 | const char *level, *sevstr, *error_info; | ||
| 43 | static const char *hmi_error_types[] = { | ||
| 44 | "Malfunction Alert", | ||
| 45 | "Processor Recovery done", | ||
| 46 | "Processor recovery occurred again", | ||
| 47 | "Processor recovery occurred for masked error", | ||
| 48 | "Timer facility experienced an error", | ||
| 49 | "TFMR SPR is corrupted", | ||
| 50 | "UPS (Uniterrupted Power System) Overflow indication", | ||
| 51 | "An XSCOM operation failure", | ||
| 52 | "An XSCOM operation completed", | ||
| 53 | "SCOM has set a reserved FIR bit to cause recovery", | ||
| 54 | "Debug trigger has set a reserved FIR bit to cause recovery", | ||
| 55 | "A hypervisor resource error occurred" | ||
| 56 | }; | ||
| 57 | |||
| 58 | /* Print things out */ | ||
| 59 | if (hmi_evt->version != OpalHMIEvt_V1) { | ||
| 60 | pr_err("HMI Interrupt, Unknown event version %d !\n", | ||
| 61 | hmi_evt->version); | ||
| 62 | return; | ||
| 63 | } | ||
| 64 | switch (hmi_evt->severity) { | ||
| 65 | case OpalHMI_SEV_NO_ERROR: | ||
| 66 | level = KERN_INFO; | ||
| 67 | sevstr = "Harmless"; | ||
| 68 | break; | ||
| 69 | case OpalHMI_SEV_WARNING: | ||
| 70 | level = KERN_WARNING; | ||
| 71 | sevstr = ""; | ||
| 72 | break; | ||
| 73 | case OpalHMI_SEV_ERROR_SYNC: | ||
| 74 | level = KERN_ERR; | ||
| 75 | sevstr = "Severe"; | ||
| 76 | break; | ||
| 77 | case OpalHMI_SEV_FATAL: | ||
| 78 | default: | ||
| 79 | level = KERN_ERR; | ||
| 80 | sevstr = "Fatal"; | ||
| 81 | break; | ||
| 82 | } | ||
| 83 | |||
| 84 | printk("%s%s Hypervisor Maintenance interrupt [%s]\n", | ||
| 85 | level, sevstr, | ||
| 86 | hmi_evt->disposition == OpalHMI_DISPOSITION_RECOVERED ? | ||
| 87 | "Recovered" : "Not recovered"); | ||
| 88 | error_info = hmi_evt->type < ARRAY_SIZE(hmi_error_types) ? | ||
| 89 | hmi_error_types[hmi_evt->type] | ||
| 90 | : "Unknown"; | ||
| 91 | printk("%s Error detail: %s\n", level, error_info); | ||
| 92 | printk("%s HMER: %016llx\n", level, be64_to_cpu(hmi_evt->hmer)); | ||
| 93 | if ((hmi_evt->type == OpalHMI_ERROR_TFAC) || | ||
| 94 | (hmi_evt->type == OpalHMI_ERROR_TFMR_PARITY)) | ||
| 95 | printk("%s TFMR: %016llx\n", level, | ||
| 96 | be64_to_cpu(hmi_evt->tfmr)); | ||
| 97 | } | ||
| 98 | |||
| 99 | static void hmi_event_handler(struct work_struct *work) | ||
| 100 | { | ||
| 101 | unsigned long flags; | ||
| 102 | struct OpalHMIEvent *hmi_evt; | ||
| 103 | struct OpalHmiEvtNode *msg_node; | ||
| 104 | uint8_t disposition; | ||
| 105 | |||
| 106 | spin_lock_irqsave(&opal_hmi_evt_lock, flags); | ||
| 107 | while (!list_empty(&opal_hmi_evt_list)) { | ||
| 108 | msg_node = list_entry(opal_hmi_evt_list.next, | ||
| 109 | struct OpalHmiEvtNode, list); | ||
| 110 | list_del(&msg_node->list); | ||
| 111 | spin_unlock_irqrestore(&opal_hmi_evt_lock, flags); | ||
| 112 | |||
| 113 | hmi_evt = (struct OpalHMIEvent *) &msg_node->hmi_evt; | ||
| 114 | print_hmi_event_info(hmi_evt); | ||
| 115 | disposition = hmi_evt->disposition; | ||
| 116 | kfree(msg_node); | ||
| 117 | |||
| 118 | /* | ||
| 119 | * Check if HMI event has been recovered or not. If not | ||
| 120 | * then we can't continue, invoke panic. | ||
| 121 | */ | ||
| 122 | if (disposition != OpalHMI_DISPOSITION_RECOVERED) | ||
| 123 | panic("Unrecoverable HMI exception"); | ||
| 124 | |||
| 125 | spin_lock_irqsave(&opal_hmi_evt_lock, flags); | ||
| 126 | } | ||
| 127 | spin_unlock_irqrestore(&opal_hmi_evt_lock, flags); | ||
| 128 | } | ||
| 129 | |||
| 130 | static DECLARE_WORK(hmi_event_work, hmi_event_handler); | ||
| 131 | /* | ||
| 132 | * opal_handle_hmi_event - notifier handler that queues up HMI events | ||
| 133 | * to be preocessed later. | ||
| 134 | */ | ||
| 135 | static int opal_handle_hmi_event(struct notifier_block *nb, | ||
| 136 | unsigned long msg_type, void *msg) | ||
| 137 | { | ||
| 138 | unsigned long flags; | ||
| 139 | struct OpalHMIEvent *hmi_evt; | ||
| 140 | struct opal_msg *hmi_msg = msg; | ||
| 141 | struct OpalHmiEvtNode *msg_node; | ||
| 142 | |||
| 143 | /* Sanity Checks */ | ||
| 144 | if (msg_type != OPAL_MSG_HMI_EVT) | ||
| 145 | return 0; | ||
| 146 | |||
| 147 | /* HMI event info starts from param[0] */ | ||
| 148 | hmi_evt = (struct OpalHMIEvent *)&hmi_msg->params[0]; | ||
| 149 | |||
| 150 | /* Delay the logging of HMI events to workqueue. */ | ||
| 151 | msg_node = kzalloc(sizeof(*msg_node), GFP_ATOMIC); | ||
| 152 | if (!msg_node) { | ||
| 153 | pr_err("HMI: out of memory, Opal message event not handled\n"); | ||
| 154 | return -ENOMEM; | ||
| 155 | } | ||
| 156 | memcpy(&msg_node->hmi_evt, hmi_evt, sizeof(struct OpalHMIEvent)); | ||
| 157 | |||
| 158 | spin_lock_irqsave(&opal_hmi_evt_lock, flags); | ||
| 159 | list_add(&msg_node->list, &opal_hmi_evt_list); | ||
| 160 | spin_unlock_irqrestore(&opal_hmi_evt_lock, flags); | ||
| 161 | |||
| 162 | schedule_work(&hmi_event_work); | ||
| 163 | return 0; | ||
| 164 | } | ||
| 165 | |||
| 166 | static struct notifier_block opal_hmi_handler_nb = { | ||
| 167 | .notifier_call = opal_handle_hmi_event, | ||
| 168 | .next = NULL, | ||
| 169 | .priority = 0, | ||
| 170 | }; | ||
| 171 | |||
| 172 | static int __init opal_hmi_handler_init(void) | ||
| 173 | { | ||
| 174 | int ret; | ||
| 175 | |||
| 176 | if (!opal_hmi_handler_nb_init) { | ||
| 177 | ret = opal_message_notifier_register( | ||
| 178 | OPAL_MSG_HMI_EVT, &opal_hmi_handler_nb); | ||
| 179 | if (ret) { | ||
| 180 | pr_err("%s: Can't register OPAL event notifier (%d)\n", | ||
| 181 | __func__, ret); | ||
| 182 | return ret; | ||
| 183 | } | ||
| 184 | opal_hmi_handler_nb_init = 1; | ||
| 185 | } | ||
| 186 | return 0; | ||
| 187 | } | ||
| 188 | subsys_initcall(opal_hmi_handler_init); | ||
diff --git a/arch/powerpc/platforms/powernv/opal-lpc.c b/arch/powerpc/platforms/powernv/opal-lpc.c index f04b4d8aca5a..ad4b31df779a 100644 --- a/arch/powerpc/platforms/powernv/opal-lpc.c +++ b/arch/powerpc/platforms/powernv/opal-lpc.c | |||
| @@ -324,7 +324,7 @@ static int opal_lpc_init_debugfs(void) | |||
| 324 | rc |= opal_lpc_debugfs_create_type(root, "fw", OPAL_LPC_FW); | 324 | rc |= opal_lpc_debugfs_create_type(root, "fw", OPAL_LPC_FW); |
| 325 | return rc; | 325 | return rc; |
| 326 | } | 326 | } |
| 327 | device_initcall(opal_lpc_init_debugfs); | 327 | machine_device_initcall(powernv, opal_lpc_init_debugfs); |
| 328 | #endif /* CONFIG_DEBUG_FS */ | 328 | #endif /* CONFIG_DEBUG_FS */ |
| 329 | 329 | ||
| 330 | void opal_lpc_init(void) | 330 | void opal_lpc_init(void) |
diff --git a/arch/powerpc/platforms/powernv/opal-memory-errors.c b/arch/powerpc/platforms/powernv/opal-memory-errors.c index b17a34b695ef..43db2136dbff 100644 --- a/arch/powerpc/platforms/powernv/opal-memory-errors.c +++ b/arch/powerpc/platforms/powernv/opal-memory-errors.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
| 28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
| 29 | 29 | ||
| 30 | #include <asm/machdep.h> | ||
| 30 | #include <asm/opal.h> | 31 | #include <asm/opal.h> |
| 31 | #include <asm/cputable.h> | 32 | #include <asm/cputable.h> |
| 32 | 33 | ||
| @@ -143,4 +144,4 @@ static int __init opal_mem_err_init(void) | |||
| 143 | } | 144 | } |
| 144 | return 0; | 145 | return 0; |
| 145 | } | 146 | } |
| 146 | subsys_initcall(opal_mem_err_init); | 147 | machine_subsys_initcall(powernv, opal_mem_err_init); |
diff --git a/arch/powerpc/platforms/powernv/opal-tracepoints.c b/arch/powerpc/platforms/powernv/opal-tracepoints.c new file mode 100644 index 000000000000..d8a000a9988b --- /dev/null +++ b/arch/powerpc/platforms/powernv/opal-tracepoints.c | |||
| @@ -0,0 +1,84 @@ | |||
| 1 | #include <linux/percpu.h> | ||
| 2 | #include <linux/jump_label.h> | ||
| 3 | #include <asm/trace.h> | ||
| 4 | |||
| 5 | #ifdef CONFIG_JUMP_LABEL | ||
| 6 | struct static_key opal_tracepoint_key = STATIC_KEY_INIT; | ||
| 7 | |||
| 8 | void opal_tracepoint_regfunc(void) | ||
| 9 | { | ||
| 10 | static_key_slow_inc(&opal_tracepoint_key); | ||
| 11 | } | ||
| 12 | |||
| 13 | void opal_tracepoint_unregfunc(void) | ||
| 14 | { | ||
| 15 | static_key_slow_dec(&opal_tracepoint_key); | ||
| 16 | } | ||
| 17 | #else | ||
| 18 | /* | ||
| 19 | * We optimise OPAL calls by placing opal_tracepoint_refcount | ||
| 20 | * directly in the TOC so we can check if the opal tracepoints are | ||
| 21 | * enabled via a single load. | ||
| 22 | */ | ||
| 23 | |||
| 24 | /* NB: reg/unreg are called while guarded with the tracepoints_mutex */ | ||
| 25 | extern long opal_tracepoint_refcount; | ||
| 26 | |||
| 27 | void opal_tracepoint_regfunc(void) | ||
| 28 | { | ||
| 29 | opal_tracepoint_refcount++; | ||
| 30 | } | ||
| 31 | |||
| 32 | void opal_tracepoint_unregfunc(void) | ||
| 33 | { | ||
| 34 | opal_tracepoint_refcount--; | ||
| 35 | } | ||
| 36 | #endif | ||
| 37 | |||
| 38 | /* | ||
| 39 | * Since the tracing code might execute OPAL calls we need to guard against | ||
| 40 | * recursion. | ||
| 41 | */ | ||
| 42 | static DEFINE_PER_CPU(unsigned int, opal_trace_depth); | ||
| 43 | |||
| 44 | void __trace_opal_entry(unsigned long opcode, unsigned long *args) | ||
| 45 | { | ||
| 46 | unsigned long flags; | ||
| 47 | unsigned int *depth; | ||
| 48 | |||
| 49 | local_irq_save(flags); | ||
| 50 | |||
| 51 | depth = &__get_cpu_var(opal_trace_depth); | ||
| 52 | |||
| 53 | if (*depth) | ||
| 54 | goto out; | ||
| 55 | |||
| 56 | (*depth)++; | ||
| 57 | preempt_disable(); | ||
| 58 | trace_opal_entry(opcode, args); | ||
| 59 | (*depth)--; | ||
| 60 | |||
| 61 | out: | ||
| 62 | local_irq_restore(flags); | ||
| 63 | } | ||
| 64 | |||
| 65 | void __trace_opal_exit(long opcode, unsigned long retval) | ||
| 66 | { | ||
| 67 | unsigned long flags; | ||
| 68 | unsigned int *depth; | ||
| 69 | |||
| 70 | local_irq_save(flags); | ||
| 71 | |||
| 72 | depth = &__get_cpu_var(opal_trace_depth); | ||
| 73 | |||
| 74 | if (*depth) | ||
| 75 | goto out; | ||
| 76 | |||
| 77 | (*depth)++; | ||
| 78 | trace_opal_exit(opcode, retval); | ||
| 79 | preempt_enable(); | ||
| 80 | (*depth)--; | ||
| 81 | |||
| 82 | out: | ||
| 83 | local_irq_restore(flags); | ||
| 84 | } | ||
diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S index 4abbff22a61f..a328be44880f 100644 --- a/arch/powerpc/platforms/powernv/opal-wrappers.S +++ b/arch/powerpc/platforms/powernv/opal-wrappers.S | |||
| @@ -13,30 +13,69 @@ | |||
| 13 | #include <asm/hvcall.h> | 13 | #include <asm/hvcall.h> |
| 14 | #include <asm/asm-offsets.h> | 14 | #include <asm/asm-offsets.h> |
| 15 | #include <asm/opal.h> | 15 | #include <asm/opal.h> |
| 16 | #include <asm/jump_label.h> | ||
| 17 | |||
| 18 | .section ".text" | ||
| 19 | |||
| 20 | #ifdef CONFIG_TRACEPOINTS | ||
| 21 | #ifdef CONFIG_JUMP_LABEL | ||
| 22 | #define OPAL_BRANCH(LABEL) \ | ||
| 23 | ARCH_STATIC_BRANCH(LABEL, opal_tracepoint_key) | ||
| 24 | #else | ||
| 25 | |||
| 26 | .section ".toc","aw" | ||
| 27 | |||
| 28 | .globl opal_tracepoint_refcount | ||
| 29 | opal_tracepoint_refcount: | ||
| 30 | .llong 0 | ||
| 31 | |||
| 32 | .section ".text" | ||
| 33 | |||
| 34 | /* | ||
| 35 | * We branch around this in early init by using an unconditional cpu | ||
| 36 | * feature. | ||
| 37 | */ | ||
| 38 | #define OPAL_BRANCH(LABEL) \ | ||
| 39 | BEGIN_FTR_SECTION; \ | ||
| 40 | b 1f; \ | ||
| 41 | END_FTR_SECTION(0, 1); \ | ||
| 42 | ld r12,opal_tracepoint_refcount@toc(r2); \ | ||
| 43 | std r12,32(r1); \ | ||
| 44 | cmpdi r12,0; \ | ||
| 45 | bne- LABEL; \ | ||
| 46 | 1: | ||
| 47 | |||
| 48 | #endif | ||
| 49 | |||
| 50 | #else | ||
| 51 | #define OPAL_BRANCH(LABEL) | ||
| 52 | #endif | ||
| 16 | 53 | ||
| 17 | /* TODO: | 54 | /* TODO: |
| 18 | * | 55 | * |
| 19 | * - Trace irqs in/off (needs saving/restoring all args, argh...) | 56 | * - Trace irqs in/off (needs saving/restoring all args, argh...) |
| 20 | * - Get r11 feed up by Dave so I can have better register usage | 57 | * - Get r11 feed up by Dave so I can have better register usage |
| 21 | */ | 58 | */ |
| 59 | |||
| 22 | #define OPAL_CALL(name, token) \ | 60 | #define OPAL_CALL(name, token) \ |
| 23 | _GLOBAL(name); \ | 61 | _GLOBAL(name); \ |
| 24 | mflr r0; \ | 62 | mflr r0; \ |
| 25 | mfcr r12; \ | ||
| 26 | std r0,16(r1); \ | 63 | std r0,16(r1); \ |
| 64 | li r0,token; \ | ||
| 65 | OPAL_BRANCH(opal_tracepoint_entry) \ | ||
| 66 | mfcr r12; \ | ||
| 27 | stw r12,8(r1); \ | 67 | stw r12,8(r1); \ |
| 28 | std r1,PACAR1(r13); \ | 68 | std r1,PACAR1(r13); \ |
| 29 | li r0,0; \ | 69 | li r11,0; \ |
| 30 | mfmsr r12; \ | 70 | mfmsr r12; \ |
| 31 | ori r0,r0,MSR_EE; \ | 71 | ori r11,r11,MSR_EE; \ |
| 32 | std r12,PACASAVEDMSR(r13); \ | 72 | std r12,PACASAVEDMSR(r13); \ |
| 33 | andc r12,r12,r0; \ | 73 | andc r12,r12,r11; \ |
| 34 | mtmsrd r12,1; \ | 74 | mtmsrd r12,1; \ |
| 35 | LOAD_REG_ADDR(r0,opal_return); \ | 75 | LOAD_REG_ADDR(r11,opal_return); \ |
| 36 | mtlr r0; \ | 76 | mtlr r11; \ |
| 37 | li r0,MSR_DR|MSR_IR|MSR_LE;\ | 77 | li r11,MSR_DR|MSR_IR|MSR_LE;\ |
| 38 | andc r12,r12,r0; \ | 78 | andc r12,r12,r11; \ |
| 39 | li r0,token; \ | ||
| 40 | mtspr SPRN_HSRR1,r12; \ | 79 | mtspr SPRN_HSRR1,r12; \ |
| 41 | LOAD_REG_ADDR(r11,opal); \ | 80 | LOAD_REG_ADDR(r11,opal); \ |
| 42 | ld r12,8(r11); \ | 81 | ld r12,8(r11); \ |
| @@ -61,6 +100,64 @@ opal_return: | |||
| 61 | mtcr r4; | 100 | mtcr r4; |
| 62 | rfid | 101 | rfid |
| 63 | 102 | ||
| 103 | #ifdef CONFIG_TRACEPOINTS | ||
| 104 | opal_tracepoint_entry: | ||
| 105 | stdu r1,-STACKFRAMESIZE(r1) | ||
| 106 | std r0,STK_REG(R23)(r1) | ||
| 107 | std r3,STK_REG(R24)(r1) | ||
| 108 | std r4,STK_REG(R25)(r1) | ||
| 109 | std r5,STK_REG(R26)(r1) | ||
| 110 | std r6,STK_REG(R27)(r1) | ||
| 111 | std r7,STK_REG(R28)(r1) | ||
| 112 | std r8,STK_REG(R29)(r1) | ||
| 113 | std r9,STK_REG(R30)(r1) | ||
| 114 | std r10,STK_REG(R31)(r1) | ||
| 115 | mr r3,r0 | ||
| 116 | addi r4,r1,STK_REG(R24) | ||
| 117 | bl __trace_opal_entry | ||
| 118 | ld r0,STK_REG(R23)(r1) | ||
| 119 | ld r3,STK_REG(R24)(r1) | ||
| 120 | ld r4,STK_REG(R25)(r1) | ||
| 121 | ld r5,STK_REG(R26)(r1) | ||
| 122 | ld r6,STK_REG(R27)(r1) | ||
| 123 | ld r7,STK_REG(R28)(r1) | ||
| 124 | ld r8,STK_REG(R29)(r1) | ||
| 125 | ld r9,STK_REG(R30)(r1) | ||
| 126 | ld r10,STK_REG(R31)(r1) | ||
| 127 | LOAD_REG_ADDR(r11,opal_tracepoint_return) | ||
| 128 | mfcr r12 | ||
| 129 | std r11,16(r1) | ||
| 130 | stw r12,8(r1) | ||
| 131 | std r1,PACAR1(r13) | ||
| 132 | li r11,0 | ||
| 133 | mfmsr r12 | ||
| 134 | ori r11,r11,MSR_EE | ||
| 135 | std r12,PACASAVEDMSR(r13) | ||
| 136 | andc r12,r12,r11 | ||
| 137 | mtmsrd r12,1 | ||
| 138 | LOAD_REG_ADDR(r11,opal_return) | ||
| 139 | mtlr r11 | ||
| 140 | li r11,MSR_DR|MSR_IR|MSR_LE | ||
| 141 | andc r12,r12,r11 | ||
| 142 | mtspr SPRN_HSRR1,r12 | ||
| 143 | LOAD_REG_ADDR(r11,opal) | ||
| 144 | ld r12,8(r11) | ||
| 145 | ld r2,0(r11) | ||
| 146 | mtspr SPRN_HSRR0,r12 | ||
| 147 | hrfid | ||
| 148 | |||
| 149 | opal_tracepoint_return: | ||
| 150 | std r3,STK_REG(R31)(r1) | ||
| 151 | mr r4,r3 | ||
| 152 | ld r0,STK_REG(R23)(r1) | ||
| 153 | bl __trace_opal_exit | ||
| 154 | ld r3,STK_REG(R31)(r1) | ||
| 155 | addi r1,r1,STACKFRAMESIZE | ||
| 156 | ld r0,16(r1) | ||
| 157 | mtlr r0 | ||
| 158 | blr | ||
| 159 | #endif | ||
| 160 | |||
| 64 | OPAL_CALL(opal_invalid_call, OPAL_INVALID_CALL); | 161 | OPAL_CALL(opal_invalid_call, OPAL_INVALID_CALL); |
| 65 | OPAL_CALL(opal_console_write, OPAL_CONSOLE_WRITE); | 162 | OPAL_CALL(opal_console_write, OPAL_CONSOLE_WRITE); |
| 66 | OPAL_CALL(opal_console_read, OPAL_CONSOLE_READ); | 163 | OPAL_CALL(opal_console_read, OPAL_CONSOLE_READ); |
| @@ -86,6 +183,7 @@ OPAL_CALL(opal_get_xive, OPAL_GET_XIVE); | |||
| 86 | OPAL_CALL(opal_register_exception_handler, OPAL_REGISTER_OPAL_EXCEPTION_HANDLER); | 183 | OPAL_CALL(opal_register_exception_handler, OPAL_REGISTER_OPAL_EXCEPTION_HANDLER); |
| 87 | OPAL_CALL(opal_pci_eeh_freeze_status, OPAL_PCI_EEH_FREEZE_STATUS); | 184 | OPAL_CALL(opal_pci_eeh_freeze_status, OPAL_PCI_EEH_FREEZE_STATUS); |
| 88 | OPAL_CALL(opal_pci_eeh_freeze_clear, OPAL_PCI_EEH_FREEZE_CLEAR); | 185 | OPAL_CALL(opal_pci_eeh_freeze_clear, OPAL_PCI_EEH_FREEZE_CLEAR); |
| 186 | OPAL_CALL(opal_pci_eeh_freeze_set, OPAL_PCI_EEH_FREEZE_SET); | ||
| 89 | OPAL_CALL(opal_pci_shpc, OPAL_PCI_SHPC); | 187 | OPAL_CALL(opal_pci_shpc, OPAL_PCI_SHPC); |
| 90 | OPAL_CALL(opal_pci_phb_mmio_enable, OPAL_PCI_PHB_MMIO_ENABLE); | 188 | OPAL_CALL(opal_pci_phb_mmio_enable, OPAL_PCI_PHB_MMIO_ENABLE); |
| 91 | OPAL_CALL(opal_pci_set_phb_mem_window, OPAL_PCI_SET_PHB_MEM_WINDOW); | 189 | OPAL_CALL(opal_pci_set_phb_mem_window, OPAL_PCI_SET_PHB_MEM_WINDOW); |
| @@ -146,3 +244,4 @@ OPAL_CALL(opal_sync_host_reboot, OPAL_SYNC_HOST_REBOOT); | |||
| 146 | OPAL_CALL(opal_sensor_read, OPAL_SENSOR_READ); | 244 | OPAL_CALL(opal_sensor_read, OPAL_SENSOR_READ); |
| 147 | OPAL_CALL(opal_get_param, OPAL_GET_PARAM); | 245 | OPAL_CALL(opal_get_param, OPAL_GET_PARAM); |
| 148 | OPAL_CALL(opal_set_param, OPAL_SET_PARAM); | 246 | OPAL_CALL(opal_set_param, OPAL_SET_PARAM); |
| 247 | OPAL_CALL(opal_handle_hmi, OPAL_HANDLE_HMI); | ||
diff --git a/arch/powerpc/platforms/powernv/opal-xscom.c b/arch/powerpc/platforms/powernv/opal-xscom.c index 4cd2ea6c0dbe..7634d1c62299 100644 --- a/arch/powerpc/platforms/powernv/opal-xscom.c +++ b/arch/powerpc/platforms/powernv/opal-xscom.c | |||
| @@ -130,4 +130,4 @@ static int opal_xscom_init(void) | |||
| 130 | scom_init(&opal_scom_controller); | 130 | scom_init(&opal_scom_controller); |
| 131 | return 0; | 131 | return 0; |
| 132 | } | 132 | } |
| 133 | arch_initcall(opal_xscom_init); | 133 | machine_arch_initcall(powernv, opal_xscom_init); |
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index 199975613fe9..f0a01a46a57d 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c | |||
| @@ -22,6 +22,8 @@ | |||
| 22 | #include <linux/kobject.h> | 22 | #include <linux/kobject.h> |
| 23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
| 24 | #include <linux/memblock.h> | 24 | #include <linux/memblock.h> |
| 25 | |||
| 26 | #include <asm/machdep.h> | ||
| 25 | #include <asm/opal.h> | 27 | #include <asm/opal.h> |
| 26 | #include <asm/firmware.h> | 28 | #include <asm/firmware.h> |
| 27 | #include <asm/mce.h> | 29 | #include <asm/mce.h> |
| @@ -192,16 +194,12 @@ static int __init opal_register_exception_handlers(void) | |||
| 192 | * fwnmi area at 0x7000 to provide the glue space to OPAL | 194 | * fwnmi area at 0x7000 to provide the glue space to OPAL |
| 193 | */ | 195 | */ |
| 194 | glue = 0x7000; | 196 | glue = 0x7000; |
| 195 | opal_register_exception_handler(OPAL_HYPERVISOR_MAINTENANCE_HANDLER, | ||
| 196 | 0, glue); | ||
| 197 | glue += 128; | ||
| 198 | opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue); | 197 | opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue); |
| 199 | #endif | 198 | #endif |
| 200 | 199 | ||
| 201 | return 0; | 200 | return 0; |
| 202 | } | 201 | } |
| 203 | 202 | machine_early_initcall(powernv, opal_register_exception_handlers); | |
| 204 | early_initcall(opal_register_exception_handlers); | ||
| 205 | 203 | ||
| 206 | int opal_notifier_register(struct notifier_block *nb) | 204 | int opal_notifier_register(struct notifier_block *nb) |
| 207 | { | 205 | { |
| @@ -368,7 +366,7 @@ static int __init opal_message_init(void) | |||
| 368 | } | 366 | } |
| 369 | return 0; | 367 | return 0; |
| 370 | } | 368 | } |
| 371 | early_initcall(opal_message_init); | 369 | machine_early_initcall(powernv, opal_message_init); |
| 372 | 370 | ||
| 373 | int opal_get_chars(uint32_t vtermno, char *buf, int count) | 371 | int opal_get_chars(uint32_t vtermno, char *buf, int count) |
| 374 | { | 372 | { |
| @@ -513,6 +511,46 @@ int opal_machine_check(struct pt_regs *regs) | |||
| 513 | return 0; | 511 | return 0; |
| 514 | } | 512 | } |
| 515 | 513 | ||
| 514 | /* Early hmi handler called in real mode. */ | ||
| 515 | int opal_hmi_exception_early(struct pt_regs *regs) | ||
| 516 | { | ||
| 517 | s64 rc; | ||
| 518 | |||
| 519 | /* | ||
| 520 | * call opal hmi handler. Pass paca address as token. | ||
| 521 | * The return value OPAL_SUCCESS is an indication that there is | ||
| 522 | * an HMI event generated waiting to pull by Linux. | ||
| 523 | */ | ||
| 524 | rc = opal_handle_hmi(); | ||
| 525 | if (rc == OPAL_SUCCESS) { | ||
| 526 | local_paca->hmi_event_available = 1; | ||
| 527 | return 1; | ||
| 528 | } | ||
| 529 | return 0; | ||
| 530 | } | ||
| 531 | |||
| 532 | /* HMI exception handler called in virtual mode during check_irq_replay. */ | ||
| 533 | int opal_handle_hmi_exception(struct pt_regs *regs) | ||
| 534 | { | ||
| 535 | s64 rc; | ||
| 536 | __be64 evt = 0; | ||
| 537 | |||
| 538 | /* | ||
| 539 | * Check if HMI event is available. | ||
| 540 | * if Yes, then call opal_poll_events to pull opal messages and | ||
| 541 | * process them. | ||
| 542 | */ | ||
| 543 | if (!local_paca->hmi_event_available) | ||
| 544 | return 0; | ||
| 545 | |||
| 546 | local_paca->hmi_event_available = 0; | ||
| 547 | rc = opal_poll_events(&evt); | ||
| 548 | if (rc == OPAL_SUCCESS && evt) | ||
| 549 | opal_do_notifier(be64_to_cpu(evt)); | ||
| 550 | |||
| 551 | return 1; | ||
| 552 | } | ||
| 553 | |||
| 516 | static uint64_t find_recovery_address(uint64_t nip) | 554 | static uint64_t find_recovery_address(uint64_t nip) |
| 517 | { | 555 | { |
| 518 | int i; | 556 | int i; |
| @@ -630,7 +668,7 @@ static int __init opal_init(void) | |||
| 630 | 668 | ||
| 631 | return 0; | 669 | return 0; |
| 632 | } | 670 | } |
| 633 | subsys_initcall(opal_init); | 671 | machine_subsys_initcall(powernv, opal_init); |
| 634 | 672 | ||
| 635 | void opal_shutdown(void) | 673 | void opal_shutdown(void) |
| 636 | { | 674 | { |
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index de19edeaa7a7..b136108ddc99 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include <asm/tce.h> | 36 | #include <asm/tce.h> |
| 37 | #include <asm/xics.h> | 37 | #include <asm/xics.h> |
| 38 | #include <asm/debug.h> | 38 | #include <asm/debug.h> |
| 39 | #include <asm/firmware.h> | ||
| 39 | 40 | ||
| 40 | #include "powernv.h" | 41 | #include "powernv.h" |
| 41 | #include "pci.h" | 42 | #include "pci.h" |
| @@ -82,6 +83,12 @@ static inline void __raw_rm_writeq(u64 val, volatile void __iomem *paddr) | |||
| 82 | : : "r" (val), "r" (paddr) : "memory"); | 83 | : : "r" (val), "r" (paddr) : "memory"); |
| 83 | } | 84 | } |
| 84 | 85 | ||
| 86 | static inline bool pnv_pci_is_mem_pref_64(unsigned long flags) | ||
| 87 | { | ||
| 88 | return ((flags & (IORESOURCE_MEM_64 | IORESOURCE_PREFETCH)) == | ||
| 89 | (IORESOURCE_MEM_64 | IORESOURCE_PREFETCH)); | ||
| 90 | } | ||
| 91 | |||
| 85 | static int pnv_ioda_alloc_pe(struct pnv_phb *phb) | 92 | static int pnv_ioda_alloc_pe(struct pnv_phb *phb) |
| 86 | { | 93 | { |
| 87 | unsigned long pe; | 94 | unsigned long pe; |
| @@ -106,6 +113,380 @@ static void pnv_ioda_free_pe(struct pnv_phb *phb, int pe) | |||
| 106 | clear_bit(pe, phb->ioda.pe_alloc); | 113 | clear_bit(pe, phb->ioda.pe_alloc); |
| 107 | } | 114 | } |
| 108 | 115 | ||
| 116 | /* The default M64 BAR is shared by all PEs */ | ||
| 117 | static int pnv_ioda2_init_m64(struct pnv_phb *phb) | ||
| 118 | { | ||
| 119 | const char *desc; | ||
| 120 | struct resource *r; | ||
| 121 | s64 rc; | ||
| 122 | |||
| 123 | /* Configure the default M64 BAR */ | ||
| 124 | rc = opal_pci_set_phb_mem_window(phb->opal_id, | ||
| 125 | OPAL_M64_WINDOW_TYPE, | ||
| 126 | phb->ioda.m64_bar_idx, | ||
| 127 | phb->ioda.m64_base, | ||
| 128 | 0, /* unused */ | ||
| 129 | phb->ioda.m64_size); | ||
| 130 | if (rc != OPAL_SUCCESS) { | ||
| 131 | desc = "configuring"; | ||
| 132 | goto fail; | ||
| 133 | } | ||
| 134 | |||
| 135 | /* Enable the default M64 BAR */ | ||
| 136 | rc = opal_pci_phb_mmio_enable(phb->opal_id, | ||
| 137 | OPAL_M64_WINDOW_TYPE, | ||
| 138 | phb->ioda.m64_bar_idx, | ||
| 139 | OPAL_ENABLE_M64_SPLIT); | ||
| 140 | if (rc != OPAL_SUCCESS) { | ||
| 141 | desc = "enabling"; | ||
| 142 | goto fail; | ||
| 143 | } | ||
| 144 | |||
| 145 | /* Mark the M64 BAR assigned */ | ||
| 146 | set_bit(phb->ioda.m64_bar_idx, &phb->ioda.m64_bar_alloc); | ||
| 147 | |||
| 148 | /* | ||
| 149 | * Strip off the segment used by the reserved PE, which is | ||
| 150 | * expected to be 0 or last one of PE capabicity. | ||
| 151 | */ | ||
| 152 | r = &phb->hose->mem_resources[1]; | ||
| 153 | if (phb->ioda.reserved_pe == 0) | ||
| 154 | r->start += phb->ioda.m64_segsize; | ||
| 155 | else if (phb->ioda.reserved_pe == (phb->ioda.total_pe - 1)) | ||
| 156 | r->end -= phb->ioda.m64_segsize; | ||
| 157 | else | ||
| 158 | pr_warn(" Cannot strip M64 segment for reserved PE#%d\n", | ||
| 159 | phb->ioda.reserved_pe); | ||
| 160 | |||
| 161 | return 0; | ||
| 162 | |||
| 163 | fail: | ||
| 164 | pr_warn(" Failure %lld %s M64 BAR#%d\n", | ||
| 165 | rc, desc, phb->ioda.m64_bar_idx); | ||
| 166 | opal_pci_phb_mmio_enable(phb->opal_id, | ||
| 167 | OPAL_M64_WINDOW_TYPE, | ||
| 168 | phb->ioda.m64_bar_idx, | ||
| 169 | OPAL_DISABLE_M64); | ||
| 170 | return -EIO; | ||
| 171 | } | ||
| 172 | |||
| 173 | static void pnv_ioda2_alloc_m64_pe(struct pnv_phb *phb) | ||
| 174 | { | ||
| 175 | resource_size_t sgsz = phb->ioda.m64_segsize; | ||
| 176 | struct pci_dev *pdev; | ||
| 177 | struct resource *r; | ||
| 178 | int base, step, i; | ||
| 179 | |||
| 180 | /* | ||
| 181 | * Root bus always has full M64 range and root port has | ||
| 182 | * M64 range used in reality. So we're checking root port | ||
| 183 | * instead of root bus. | ||
| 184 | */ | ||
| 185 | list_for_each_entry(pdev, &phb->hose->bus->devices, bus_list) { | ||
| 186 | for (i = PCI_BRIDGE_RESOURCES; | ||
| 187 | i <= PCI_BRIDGE_RESOURCE_END; i++) { | ||
| 188 | r = &pdev->resource[i]; | ||
| 189 | if (!r->parent || | ||
| 190 | !pnv_pci_is_mem_pref_64(r->flags)) | ||
| 191 | continue; | ||
| 192 | |||
| 193 | base = (r->start - phb->ioda.m64_base) / sgsz; | ||
| 194 | for (step = 0; step < resource_size(r) / sgsz; step++) | ||
| 195 | set_bit(base + step, phb->ioda.pe_alloc); | ||
| 196 | } | ||
| 197 | } | ||
| 198 | } | ||
| 199 | |||
| 200 | static int pnv_ioda2_pick_m64_pe(struct pnv_phb *phb, | ||
| 201 | struct pci_bus *bus, int all) | ||
| 202 | { | ||
| 203 | resource_size_t segsz = phb->ioda.m64_segsize; | ||
| 204 | struct pci_dev *pdev; | ||
| 205 | struct resource *r; | ||
| 206 | struct pnv_ioda_pe *master_pe, *pe; | ||
| 207 | unsigned long size, *pe_alloc; | ||
| 208 | bool found; | ||
| 209 | int start, i, j; | ||
| 210 | |||
| 211 | /* Root bus shouldn't use M64 */ | ||
| 212 | if (pci_is_root_bus(bus)) | ||
| 213 | return IODA_INVALID_PE; | ||
| 214 | |||
| 215 | /* We support only one M64 window on each bus */ | ||
| 216 | found = false; | ||
| 217 | pci_bus_for_each_resource(bus, r, i) { | ||
| 218 | if (r && r->parent && | ||
| 219 | pnv_pci_is_mem_pref_64(r->flags)) { | ||
| 220 | found = true; | ||
| 221 | break; | ||
| 222 | } | ||
| 223 | } | ||
| 224 | |||
| 225 | /* No M64 window found ? */ | ||
| 226 | if (!found) | ||
| 227 | return IODA_INVALID_PE; | ||
| 228 | |||
| 229 | /* Allocate bitmap */ | ||
| 230 | size = _ALIGN_UP(phb->ioda.total_pe / 8, sizeof(unsigned long)); | ||
| 231 | pe_alloc = kzalloc(size, GFP_KERNEL); | ||
| 232 | if (!pe_alloc) { | ||
| 233 | pr_warn("%s: Out of memory !\n", | ||
| 234 | __func__); | ||
| 235 | return IODA_INVALID_PE; | ||
| 236 | } | ||
| 237 | |||
| 238 | /* | ||
| 239 | * Figure out reserved PE numbers by the PE | ||
| 240 | * the its child PEs. | ||
| 241 | */ | ||
| 242 | start = (r->start - phb->ioda.m64_base) / segsz; | ||
| 243 | for (i = 0; i < resource_size(r) / segsz; i++) | ||
| 244 | set_bit(start + i, pe_alloc); | ||
| 245 | |||
| 246 | if (all) | ||
| 247 | goto done; | ||
| 248 | |||
| 249 | /* | ||
| 250 | * If the PE doesn't cover all subordinate buses, | ||
| 251 | * we need subtract from reserved PEs for children. | ||
| 252 | */ | ||
| 253 | list_for_each_entry(pdev, &bus->devices, bus_list) { | ||
| 254 | if (!pdev->subordinate) | ||
| 255 | continue; | ||
| 256 | |||
| 257 | pci_bus_for_each_resource(pdev->subordinate, r, i) { | ||
| 258 | if (!r || !r->parent || | ||
| 259 | !pnv_pci_is_mem_pref_64(r->flags)) | ||
| 260 | continue; | ||
| 261 | |||
| 262 | start = (r->start - phb->ioda.m64_base) / segsz; | ||
| 263 | for (j = 0; j < resource_size(r) / segsz ; j++) | ||
| 264 | clear_bit(start + j, pe_alloc); | ||
| 265 | } | ||
| 266 | } | ||
| 267 | |||
| 268 | /* | ||
| 269 | * the current bus might not own M64 window and that's all | ||
| 270 | * contributed by its child buses. For the case, we needn't | ||
| 271 | * pick M64 dependent PE#. | ||
| 272 | */ | ||
| 273 | if (bitmap_empty(pe_alloc, phb->ioda.total_pe)) { | ||
| 274 | kfree(pe_alloc); | ||
| 275 | return IODA_INVALID_PE; | ||
| 276 | } | ||
| 277 | |||
| 278 | /* | ||
| 279 | * Figure out the master PE and put all slave PEs to master | ||
| 280 | * PE's list to form compound PE. | ||
| 281 | */ | ||
| 282 | done: | ||
| 283 | master_pe = NULL; | ||
| 284 | i = -1; | ||
| 285 | while ((i = find_next_bit(pe_alloc, phb->ioda.total_pe, i + 1)) < | ||
| 286 | phb->ioda.total_pe) { | ||
| 287 | pe = &phb->ioda.pe_array[i]; | ||
| 288 | pe->phb = phb; | ||
| 289 | pe->pe_number = i; | ||
| 290 | |||
| 291 | if (!master_pe) { | ||
| 292 | pe->flags |= PNV_IODA_PE_MASTER; | ||
| 293 | INIT_LIST_HEAD(&pe->slaves); | ||
| 294 | master_pe = pe; | ||
| 295 | } else { | ||
| 296 | pe->flags |= PNV_IODA_PE_SLAVE; | ||
| 297 | pe->master = master_pe; | ||
| 298 | list_add_tail(&pe->list, &master_pe->slaves); | ||
| 299 | } | ||
| 300 | } | ||
| 301 | |||
| 302 | kfree(pe_alloc); | ||
| 303 | return master_pe->pe_number; | ||
| 304 | } | ||
| 305 | |||
| 306 | static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb) | ||
| 307 | { | ||
| 308 | struct pci_controller *hose = phb->hose; | ||
| 309 | struct device_node *dn = hose->dn; | ||
| 310 | struct resource *res; | ||
| 311 | const u32 *r; | ||
| 312 | u64 pci_addr; | ||
| 313 | |||
| 314 | if (!firmware_has_feature(FW_FEATURE_OPALv3)) { | ||
| 315 | pr_info(" Firmware too old to support M64 window\n"); | ||
| 316 | return; | ||
| 317 | } | ||
| 318 | |||
| 319 | r = of_get_property(dn, "ibm,opal-m64-window", NULL); | ||
| 320 | if (!r) { | ||
| 321 | pr_info(" No <ibm,opal-m64-window> on %s\n", | ||
| 322 | dn->full_name); | ||
| 323 | return; | ||
| 324 | } | ||
| 325 | |||
| 326 | /* FIXME: Support M64 for P7IOC */ | ||
| 327 | if (phb->type != PNV_PHB_IODA2) { | ||
| 328 | pr_info(" Not support M64 window\n"); | ||
| 329 | return; | ||
| 330 | } | ||
| 331 | |||
| 332 | res = &hose->mem_resources[1]; | ||
| 333 | res->start = of_translate_address(dn, r + 2); | ||
| 334 | res->end = res->start + of_read_number(r + 4, 2) - 1; | ||
| 335 | res->flags = (IORESOURCE_MEM | IORESOURCE_MEM_64 | IORESOURCE_PREFETCH); | ||
| 336 | pci_addr = of_read_number(r, 2); | ||
| 337 | hose->mem_offset[1] = res->start - pci_addr; | ||
| 338 | |||
| 339 | phb->ioda.m64_size = resource_size(res); | ||
| 340 | phb->ioda.m64_segsize = phb->ioda.m64_size / phb->ioda.total_pe; | ||
| 341 | phb->ioda.m64_base = pci_addr; | ||
| 342 | |||
| 343 | /* Use last M64 BAR to cover M64 window */ | ||
| 344 | phb->ioda.m64_bar_idx = 15; | ||
| 345 | phb->init_m64 = pnv_ioda2_init_m64; | ||
| 346 | phb->alloc_m64_pe = pnv_ioda2_alloc_m64_pe; | ||
| 347 | phb->pick_m64_pe = pnv_ioda2_pick_m64_pe; | ||
| 348 | } | ||
| 349 | |||
| 350 | static void pnv_ioda_freeze_pe(struct pnv_phb *phb, int pe_no) | ||
| 351 | { | ||
| 352 | struct pnv_ioda_pe *pe = &phb->ioda.pe_array[pe_no]; | ||
| 353 | struct pnv_ioda_pe *slave; | ||
| 354 | s64 rc; | ||
| 355 | |||
| 356 | /* Fetch master PE */ | ||
| 357 | if (pe->flags & PNV_IODA_PE_SLAVE) { | ||
| 358 | pe = pe->master; | ||
| 359 | WARN_ON(!pe || !(pe->flags & PNV_IODA_PE_MASTER)); | ||
| 360 | pe_no = pe->pe_number; | ||
| 361 | } | ||
| 362 | |||
| 363 | /* Freeze master PE */ | ||
| 364 | rc = opal_pci_eeh_freeze_set(phb->opal_id, | ||
| 365 | pe_no, | ||
| 366 | OPAL_EEH_ACTION_SET_FREEZE_ALL); | ||
| 367 | if (rc != OPAL_SUCCESS) { | ||
| 368 | pr_warn("%s: Failure %lld freezing PHB#%x-PE#%x\n", | ||
| 369 | __func__, rc, phb->hose->global_number, pe_no); | ||
| 370 | return; | ||
| 371 | } | ||
| 372 | |||
| 373 | /* Freeze slave PEs */ | ||
| 374 | if (!(pe->flags & PNV_IODA_PE_MASTER)) | ||
| 375 | return; | ||
| 376 | |||
| 377 | list_for_each_entry(slave, &pe->slaves, list) { | ||
| 378 | rc = opal_pci_eeh_freeze_set(phb->opal_id, | ||
| 379 | slave->pe_number, | ||
| 380 | OPAL_EEH_ACTION_SET_FREEZE_ALL); | ||
| 381 | if (rc != OPAL_SUCCESS) | ||
| 382 | pr_warn("%s: Failure %lld freezing PHB#%x-PE#%x\n", | ||
| 383 | __func__, rc, phb->hose->global_number, | ||
| 384 | slave->pe_number); | ||
| 385 | } | ||
| 386 | } | ||
| 387 | |||
| 388 | int pnv_ioda_unfreeze_pe(struct pnv_phb *phb, int pe_no, int opt) | ||
| 389 | { | ||
| 390 | struct pnv_ioda_pe *pe, *slave; | ||
| 391 | s64 rc; | ||
| 392 | |||
| 393 | /* Find master PE */ | ||
| 394 | pe = &phb->ioda.pe_array[pe_no]; | ||
| 395 | if (pe->flags & PNV_IODA_PE_SLAVE) { | ||
| 396 | pe = pe->master; | ||
| 397 | WARN_ON(!pe || !(pe->flags & PNV_IODA_PE_MASTER)); | ||
| 398 | pe_no = pe->pe_number; | ||
| 399 | } | ||
| 400 | |||
| 401 | /* Clear frozen state for master PE */ | ||
| 402 | rc = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no, opt); | ||
| 403 | if (rc != OPAL_SUCCESS) { | ||
| 404 | pr_warn("%s: Failure %lld clear %d on PHB#%x-PE#%x\n", | ||
| 405 | __func__, rc, opt, phb->hose->global_number, pe_no); | ||
| 406 | return -EIO; | ||
| 407 | } | ||
| 408 | |||
| 409 | if (!(pe->flags & PNV_IODA_PE_MASTER)) | ||
| 410 | return 0; | ||
| 411 | |||
| 412 | /* Clear frozen state for slave PEs */ | ||
| 413 | list_for_each_entry(slave, &pe->slaves, list) { | ||
| 414 | rc = opal_pci_eeh_freeze_clear(phb->opal_id, | ||
| 415 | slave->pe_number, | ||
| 416 | opt); | ||
| 417 | if (rc != OPAL_SUCCESS) { | ||
| 418 | pr_warn("%s: Failure %lld clear %d on PHB#%x-PE#%x\n", | ||
| 419 | __func__, rc, opt, phb->hose->global_number, | ||
| 420 | slave->pe_number); | ||
| 421 | return -EIO; | ||
| 422 | } | ||
| 423 | } | ||
| 424 | |||
| 425 | return 0; | ||
| 426 | } | ||
| 427 | |||
| 428 | static int pnv_ioda_get_pe_state(struct pnv_phb *phb, int pe_no) | ||
| 429 | { | ||
| 430 | struct pnv_ioda_pe *slave, *pe; | ||
| 431 | u8 fstate, state; | ||
| 432 | __be16 pcierr; | ||
| 433 | s64 rc; | ||
| 434 | |||
| 435 | /* Sanity check on PE number */ | ||
| 436 | if (pe_no < 0 || pe_no >= phb->ioda.total_pe) | ||
| 437 | return OPAL_EEH_STOPPED_PERM_UNAVAIL; | ||
| 438 | |||
| 439 | /* | ||
| 440 | * Fetch the master PE and the PE instance might be | ||
| 441 | * not initialized yet. | ||
| 442 | */ | ||
| 443 | pe = &phb->ioda.pe_array[pe_no]; | ||
| 444 | if (pe->flags & PNV_IODA_PE_SLAVE) { | ||
| 445 | pe = pe->master; | ||
| 446 | WARN_ON(!pe || !(pe->flags & PNV_IODA_PE_MASTER)); | ||
| 447 | pe_no = pe->pe_number; | ||
| 448 | } | ||
| 449 | |||
| 450 | /* Check the master PE */ | ||
| 451 | rc = opal_pci_eeh_freeze_status(phb->opal_id, pe_no, | ||
| 452 | &state, &pcierr, NULL); | ||
| 453 | if (rc != OPAL_SUCCESS) { | ||
| 454 | pr_warn("%s: Failure %lld getting " | ||
| 455 | "PHB#%x-PE#%x state\n", | ||
| 456 | __func__, rc, | ||
| 457 | phb->hose->global_number, pe_no); | ||
| 458 | return OPAL_EEH_STOPPED_TEMP_UNAVAIL; | ||
| 459 | } | ||
| 460 | |||
| 461 | /* Check the slave PE */ | ||
| 462 | if (!(pe->flags & PNV_IODA_PE_MASTER)) | ||
| 463 | return state; | ||
| 464 | |||
| 465 | list_for_each_entry(slave, &pe->slaves, list) { | ||
| 466 | rc = opal_pci_eeh_freeze_status(phb->opal_id, | ||
| 467 | slave->pe_number, | ||
| 468 | &fstate, | ||
| 469 | &pcierr, | ||
| 470 | NULL); | ||
| 471 | if (rc != OPAL_SUCCESS) { | ||
| 472 | pr_warn("%s: Failure %lld getting " | ||
| 473 | "PHB#%x-PE#%x state\n", | ||
| 474 | __func__, rc, | ||
| 475 | phb->hose->global_number, slave->pe_number); | ||
| 476 | return OPAL_EEH_STOPPED_TEMP_UNAVAIL; | ||
| 477 | } | ||
| 478 | |||
| 479 | /* | ||
| 480 | * Override the result based on the ascending | ||
| 481 | * priority. | ||
| 482 | */ | ||
| 483 | if (fstate > state) | ||
| 484 | state = fstate; | ||
| 485 | } | ||
| 486 | |||
| 487 | return state; | ||
| 488 | } | ||
| 489 | |||
| 109 | /* Currently those 2 are only used when MSIs are enabled, this will change | 490 | /* Currently those 2 are only used when MSIs are enabled, this will change |
| 110 | * but in the meantime, we need to protect them to avoid warnings | 491 | * but in the meantime, we need to protect them to avoid warnings |
| 111 | */ | 492 | */ |
| @@ -363,9 +744,16 @@ static void pnv_ioda_setup_bus_PE(struct pci_bus *bus, int all) | |||
| 363 | struct pci_controller *hose = pci_bus_to_host(bus); | 744 | struct pci_controller *hose = pci_bus_to_host(bus); |
| 364 | struct pnv_phb *phb = hose->private_data; | 745 | struct pnv_phb *phb = hose->private_data; |
| 365 | struct pnv_ioda_pe *pe; | 746 | struct pnv_ioda_pe *pe; |
| 366 | int pe_num; | 747 | int pe_num = IODA_INVALID_PE; |
| 748 | |||
| 749 | /* Check if PE is determined by M64 */ | ||
| 750 | if (phb->pick_m64_pe) | ||
| 751 | pe_num = phb->pick_m64_pe(phb, bus, all); | ||
| 752 | |||
| 753 | /* The PE number isn't pinned by M64 */ | ||
| 754 | if (pe_num == IODA_INVALID_PE) | ||
| 755 | pe_num = pnv_ioda_alloc_pe(phb); | ||
| 367 | 756 | ||
| 368 | pe_num = pnv_ioda_alloc_pe(phb); | ||
| 369 | if (pe_num == IODA_INVALID_PE) { | 757 | if (pe_num == IODA_INVALID_PE) { |
| 370 | pr_warning("%s: Not enough PE# available for PCI bus %04x:%02x\n", | 758 | pr_warning("%s: Not enough PE# available for PCI bus %04x:%02x\n", |
| 371 | __func__, pci_domain_nr(bus), bus->number); | 759 | __func__, pci_domain_nr(bus), bus->number); |
| @@ -373,7 +761,7 @@ static void pnv_ioda_setup_bus_PE(struct pci_bus *bus, int all) | |||
| 373 | } | 761 | } |
| 374 | 762 | ||
| 375 | pe = &phb->ioda.pe_array[pe_num]; | 763 | pe = &phb->ioda.pe_array[pe_num]; |
| 376 | pe->flags = (all ? PNV_IODA_PE_BUS_ALL : PNV_IODA_PE_BUS); | 764 | pe->flags |= (all ? PNV_IODA_PE_BUS_ALL : PNV_IODA_PE_BUS); |
| 377 | pe->pbus = bus; | 765 | pe->pbus = bus; |
| 378 | pe->pdev = NULL; | 766 | pe->pdev = NULL; |
| 379 | pe->tce32_seg = -1; | 767 | pe->tce32_seg = -1; |
| @@ -441,8 +829,15 @@ static void pnv_ioda_setup_PEs(struct pci_bus *bus) | |||
| 441 | static void pnv_pci_ioda_setup_PEs(void) | 829 | static void pnv_pci_ioda_setup_PEs(void) |
| 442 | { | 830 | { |
| 443 | struct pci_controller *hose, *tmp; | 831 | struct pci_controller *hose, *tmp; |
| 832 | struct pnv_phb *phb; | ||
| 444 | 833 | ||
| 445 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { | 834 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { |
| 835 | phb = hose->private_data; | ||
| 836 | |||
| 837 | /* M64 layout might affect PE allocation */ | ||
| 838 | if (phb->alloc_m64_pe) | ||
| 839 | phb->alloc_m64_pe(phb); | ||
| 840 | |||
| 446 | pnv_ioda_setup_PEs(hose->bus); | 841 | pnv_ioda_setup_PEs(hose->bus); |
| 447 | } | 842 | } |
| 448 | } | 843 | } |
| @@ -491,17 +886,26 @@ static int pnv_pci_ioda_dma_set_mask(struct pnv_phb *phb, | |||
| 491 | set_dma_ops(&pdev->dev, &dma_iommu_ops); | 886 | set_dma_ops(&pdev->dev, &dma_iommu_ops); |
| 492 | set_iommu_table_base(&pdev->dev, &pe->tce32_table); | 887 | set_iommu_table_base(&pdev->dev, &pe->tce32_table); |
| 493 | } | 888 | } |
| 889 | *pdev->dev.dma_mask = dma_mask; | ||
| 494 | return 0; | 890 | return 0; |
| 495 | } | 891 | } |
| 496 | 892 | ||
| 497 | static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, struct pci_bus *bus) | 893 | static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, |
| 894 | struct pci_bus *bus, | ||
| 895 | bool add_to_iommu_group) | ||
| 498 | { | 896 | { |
| 499 | struct pci_dev *dev; | 897 | struct pci_dev *dev; |
| 500 | 898 | ||
| 501 | list_for_each_entry(dev, &bus->devices, bus_list) { | 899 | list_for_each_entry(dev, &bus->devices, bus_list) { |
| 502 | set_iommu_table_base_and_group(&dev->dev, &pe->tce32_table); | 900 | if (add_to_iommu_group) |
| 901 | set_iommu_table_base_and_group(&dev->dev, | ||
| 902 | &pe->tce32_table); | ||
| 903 | else | ||
| 904 | set_iommu_table_base(&dev->dev, &pe->tce32_table); | ||
| 905 | |||
| 503 | if (dev->subordinate) | 906 | if (dev->subordinate) |
| 504 | pnv_ioda_setup_bus_dma(pe, dev->subordinate); | 907 | pnv_ioda_setup_bus_dma(pe, dev->subordinate, |
| 908 | add_to_iommu_group); | ||
| 505 | } | 909 | } |
| 506 | } | 910 | } |
| 507 | 911 | ||
| @@ -513,15 +917,16 @@ static void pnv_pci_ioda1_tce_invalidate(struct pnv_ioda_pe *pe, | |||
| 513 | (__be64 __iomem *)pe->tce_inval_reg_phys : | 917 | (__be64 __iomem *)pe->tce_inval_reg_phys : |
| 514 | (__be64 __iomem *)tbl->it_index; | 918 | (__be64 __iomem *)tbl->it_index; |
| 515 | unsigned long start, end, inc; | 919 | unsigned long start, end, inc; |
| 920 | const unsigned shift = tbl->it_page_shift; | ||
| 516 | 921 | ||
| 517 | start = __pa(startp); | 922 | start = __pa(startp); |
| 518 | end = __pa(endp); | 923 | end = __pa(endp); |
| 519 | 924 | ||
| 520 | /* BML uses this case for p6/p7/galaxy2: Shift addr and put in node */ | 925 | /* BML uses this case for p6/p7/galaxy2: Shift addr and put in node */ |
| 521 | if (tbl->it_busno) { | 926 | if (tbl->it_busno) { |
| 522 | start <<= 12; | 927 | start <<= shift; |
| 523 | end <<= 12; | 928 | end <<= shift; |
| 524 | inc = 128 << 12; | 929 | inc = 128ull << shift; |
| 525 | start |= tbl->it_busno; | 930 | start |= tbl->it_busno; |
| 526 | end |= tbl->it_busno; | 931 | end |= tbl->it_busno; |
| 527 | } else if (tbl->it_type & TCE_PCI_SWINV_PAIR) { | 932 | } else if (tbl->it_type & TCE_PCI_SWINV_PAIR) { |
| @@ -559,18 +964,19 @@ static void pnv_pci_ioda2_tce_invalidate(struct pnv_ioda_pe *pe, | |||
| 559 | __be64 __iomem *invalidate = rm ? | 964 | __be64 __iomem *invalidate = rm ? |
| 560 | (__be64 __iomem *)pe->tce_inval_reg_phys : | 965 | (__be64 __iomem *)pe->tce_inval_reg_phys : |
| 561 | (__be64 __iomem *)tbl->it_index; | 966 | (__be64 __iomem *)tbl->it_index; |
| 967 | const unsigned shift = tbl->it_page_shift; | ||
| 562 | 968 | ||
| 563 | /* We'll invalidate DMA address in PE scope */ | 969 | /* We'll invalidate DMA address in PE scope */ |
| 564 | start = 0x2ul << 60; | 970 | start = 0x2ull << 60; |
| 565 | start |= (pe->pe_number & 0xFF); | 971 | start |= (pe->pe_number & 0xFF); |
| 566 | end = start; | 972 | end = start; |
| 567 | 973 | ||
| 568 | /* Figure out the start, end and step */ | 974 | /* Figure out the start, end and step */ |
| 569 | inc = tbl->it_offset + (((u64)startp - tbl->it_base) / sizeof(u64)); | 975 | inc = tbl->it_offset + (((u64)startp - tbl->it_base) / sizeof(u64)); |
| 570 | start |= (inc << 12); | 976 | start |= (inc << shift); |
| 571 | inc = tbl->it_offset + (((u64)endp - tbl->it_base) / sizeof(u64)); | 977 | inc = tbl->it_offset + (((u64)endp - tbl->it_base) / sizeof(u64)); |
| 572 | end |= (inc << 12); | 978 | end |= (inc << shift); |
| 573 | inc = (0x1ul << 12); | 979 | inc = (0x1ull << shift); |
| 574 | mb(); | 980 | mb(); |
| 575 | 981 | ||
| 576 | while (start <= end) { | 982 | while (start <= end) { |
| @@ -654,7 +1060,7 @@ static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb, | |||
| 654 | /* Setup linux iommu table */ | 1060 | /* Setup linux iommu table */ |
| 655 | tbl = &pe->tce32_table; | 1061 | tbl = &pe->tce32_table; |
| 656 | pnv_pci_setup_iommu_table(tbl, addr, TCE32_TABLE_SIZE * segs, | 1062 | pnv_pci_setup_iommu_table(tbl, addr, TCE32_TABLE_SIZE * segs, |
| 657 | base << 28); | 1063 | base << 28, IOMMU_PAGE_SHIFT_4K); |
| 658 | 1064 | ||
| 659 | /* OPAL variant of P7IOC SW invalidated TCEs */ | 1065 | /* OPAL variant of P7IOC SW invalidated TCEs */ |
| 660 | swinvp = of_get_property(phb->hose->dn, "ibm,opal-tce-kill", NULL); | 1066 | swinvp = of_get_property(phb->hose->dn, "ibm,opal-tce-kill", NULL); |
| @@ -677,7 +1083,7 @@ static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb, | |||
| 677 | if (pe->pdev) | 1083 | if (pe->pdev) |
| 678 | set_iommu_table_base_and_group(&pe->pdev->dev, tbl); | 1084 | set_iommu_table_base_and_group(&pe->pdev->dev, tbl); |
| 679 | else | 1085 | else |
| 680 | pnv_ioda_setup_bus_dma(pe, pe->pbus); | 1086 | pnv_ioda_setup_bus_dma(pe, pe->pbus, true); |
| 681 | 1087 | ||
| 682 | return; | 1088 | return; |
| 683 | fail: | 1089 | fail: |
| @@ -713,11 +1119,15 @@ static void pnv_pci_ioda2_set_bypass(struct iommu_table *tbl, bool enable) | |||
| 713 | 0); | 1119 | 0); |
| 714 | 1120 | ||
| 715 | /* | 1121 | /* |
| 716 | * We might want to reset the DMA ops of all devices on | 1122 | * EEH needs the mapping between IOMMU table and group |
| 717 | * this PE. However in theory, that shouldn't be necessary | 1123 | * of those VFIO/KVM pass-through devices. We can postpone |
| 718 | * as this is used for VFIO/KVM pass-through and the device | 1124 | * resetting DMA ops until the DMA mask is configured in |
| 719 | * hasn't yet been returned to its kernel driver | 1125 | * host side. |
| 720 | */ | 1126 | */ |
| 1127 | if (pe->pdev) | ||
| 1128 | set_iommu_table_base(&pe->pdev->dev, tbl); | ||
| 1129 | else | ||
| 1130 | pnv_ioda_setup_bus_dma(pe, pe->pbus, false); | ||
| 721 | } | 1131 | } |
| 722 | if (rc) | 1132 | if (rc) |
| 723 | pe_err(pe, "OPAL error %lld configuring bypass window\n", rc); | 1133 | pe_err(pe, "OPAL error %lld configuring bypass window\n", rc); |
| @@ -784,7 +1194,8 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb, | |||
| 784 | 1194 | ||
| 785 | /* Setup linux iommu table */ | 1195 | /* Setup linux iommu table */ |
| 786 | tbl = &pe->tce32_table; | 1196 | tbl = &pe->tce32_table; |
| 787 | pnv_pci_setup_iommu_table(tbl, addr, tce_table_size, 0); | 1197 | pnv_pci_setup_iommu_table(tbl, addr, tce_table_size, 0, |
| 1198 | IOMMU_PAGE_SHIFT_4K); | ||
| 788 | 1199 | ||
| 789 | /* OPAL variant of PHB3 invalidated TCEs */ | 1200 | /* OPAL variant of PHB3 invalidated TCEs */ |
| 790 | swinvp = of_get_property(phb->hose->dn, "ibm,opal-tce-kill", NULL); | 1201 | swinvp = of_get_property(phb->hose->dn, "ibm,opal-tce-kill", NULL); |
| @@ -805,7 +1216,7 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb, | |||
| 805 | if (pe->pdev) | 1216 | if (pe->pdev) |
| 806 | set_iommu_table_base_and_group(&pe->pdev->dev, tbl); | 1217 | set_iommu_table_base_and_group(&pe->pdev->dev, tbl); |
| 807 | else | 1218 | else |
| 808 | pnv_ioda_setup_bus_dma(pe, pe->pbus); | 1219 | pnv_ioda_setup_bus_dma(pe, pe->pbus, true); |
| 809 | 1220 | ||
| 810 | /* Also create a bypass window */ | 1221 | /* Also create a bypass window */ |
| 811 | pnv_pci_ioda2_setup_bypass_pe(phb, pe); | 1222 | pnv_pci_ioda2_setup_bypass_pe(phb, pe); |
| @@ -1055,9 +1466,6 @@ static void pnv_ioda_setup_pe_seg(struct pci_controller *hose, | |||
| 1055 | index++; | 1466 | index++; |
| 1056 | } | 1467 | } |
| 1057 | } else if (res->flags & IORESOURCE_MEM) { | 1468 | } else if (res->flags & IORESOURCE_MEM) { |
| 1058 | /* WARNING: Assumes M32 is mem region 0 in PHB. We need to | ||
| 1059 | * harden that algorithm when we start supporting M64 | ||
| 1060 | */ | ||
| 1061 | region.start = res->start - | 1469 | region.start = res->start - |
| 1062 | hose->mem_offset[0] - | 1470 | hose->mem_offset[0] - |
| 1063 | phb->ioda.m32_pci_base; | 1471 | phb->ioda.m32_pci_base; |
| @@ -1141,9 +1549,8 @@ static void pnv_pci_ioda_fixup(void) | |||
| 1141 | pnv_pci_ioda_create_dbgfs(); | 1549 | pnv_pci_ioda_create_dbgfs(); |
| 1142 | 1550 | ||
| 1143 | #ifdef CONFIG_EEH | 1551 | #ifdef CONFIG_EEH |
| 1144 | eeh_probe_mode_set(EEH_PROBE_MODE_DEV); | ||
| 1145 | eeh_addr_cache_build(); | ||
| 1146 | eeh_init(); | 1552 | eeh_init(); |
| 1553 | eeh_addr_cache_build(); | ||
| 1147 | #endif | 1554 | #endif |
| 1148 | } | 1555 | } |
| 1149 | 1556 | ||
| @@ -1178,7 +1585,10 @@ static resource_size_t pnv_pci_window_alignment(struct pci_bus *bus, | |||
| 1178 | bridge = bridge->bus->self; | 1585 | bridge = bridge->bus->self; |
| 1179 | } | 1586 | } |
| 1180 | 1587 | ||
| 1181 | /* We need support prefetchable memory window later */ | 1588 | /* We fail back to M32 if M64 isn't supported */ |
| 1589 | if (phb->ioda.m64_segsize && | ||
| 1590 | pnv_pci_is_mem_pref_64(type)) | ||
| 1591 | return phb->ioda.m64_segsize; | ||
| 1182 | if (type & IORESOURCE_MEM) | 1592 | if (type & IORESOURCE_MEM) |
| 1183 | return phb->ioda.m32_segsize; | 1593 | return phb->ioda.m32_segsize; |
| 1184 | 1594 | ||
| @@ -1299,6 +1709,10 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, | |||
| 1299 | prop32 = of_get_property(np, "ibm,opal-reserved-pe", NULL); | 1709 | prop32 = of_get_property(np, "ibm,opal-reserved-pe", NULL); |
| 1300 | if (prop32) | 1710 | if (prop32) |
| 1301 | phb->ioda.reserved_pe = be32_to_cpup(prop32); | 1711 | phb->ioda.reserved_pe = be32_to_cpup(prop32); |
| 1712 | |||
| 1713 | /* Parse 64-bit MMIO range */ | ||
| 1714 | pnv_ioda_parse_m64_window(phb); | ||
| 1715 | |||
| 1302 | phb->ioda.m32_size = resource_size(&hose->mem_resources[0]); | 1716 | phb->ioda.m32_size = resource_size(&hose->mem_resources[0]); |
| 1303 | /* FW Has already off top 64k of M32 space (MSI space) */ | 1717 | /* FW Has already off top 64k of M32 space (MSI space) */ |
| 1304 | phb->ioda.m32_size += 0x10000; | 1718 | phb->ioda.m32_size += 0x10000; |
| @@ -1334,14 +1748,6 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, | |||
| 1334 | /* Calculate how many 32-bit TCE segments we have */ | 1748 | /* Calculate how many 32-bit TCE segments we have */ |
| 1335 | phb->ioda.tce32_count = phb->ioda.m32_pci_base >> 28; | 1749 | phb->ioda.tce32_count = phb->ioda.m32_pci_base >> 28; |
| 1336 | 1750 | ||
| 1337 | /* Clear unusable m64 */ | ||
| 1338 | hose->mem_resources[1].flags = 0; | ||
| 1339 | hose->mem_resources[1].start = 0; | ||
| 1340 | hose->mem_resources[1].end = 0; | ||
| 1341 | hose->mem_resources[2].flags = 0; | ||
| 1342 | hose->mem_resources[2].start = 0; | ||
| 1343 | hose->mem_resources[2].end = 0; | ||
| 1344 | |||
| 1345 | #if 0 /* We should really do that ... */ | 1751 | #if 0 /* We should really do that ... */ |
| 1346 | rc = opal_pci_set_phb_mem_window(opal->phb_id, | 1752 | rc = opal_pci_set_phb_mem_window(opal->phb_id, |
| 1347 | window_type, | 1753 | window_type, |
| @@ -1351,14 +1757,21 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, | |||
| 1351 | segment_size); | 1757 | segment_size); |
| 1352 | #endif | 1758 | #endif |
| 1353 | 1759 | ||
| 1354 | pr_info(" %d (%d) PE's M32: 0x%x [segment=0x%x]" | 1760 | pr_info(" %03d (%03d) PE's M32: 0x%x [segment=0x%x]\n", |
| 1355 | " IO: 0x%x [segment=0x%x]\n", | 1761 | phb->ioda.total_pe, phb->ioda.reserved_pe, |
| 1356 | phb->ioda.total_pe, | 1762 | phb->ioda.m32_size, phb->ioda.m32_segsize); |
| 1357 | phb->ioda.reserved_pe, | 1763 | if (phb->ioda.m64_size) |
| 1358 | phb->ioda.m32_size, phb->ioda.m32_segsize, | 1764 | pr_info(" M64: 0x%lx [segment=0x%lx]\n", |
| 1359 | phb->ioda.io_size, phb->ioda.io_segsize); | 1765 | phb->ioda.m64_size, phb->ioda.m64_segsize); |
| 1766 | if (phb->ioda.io_size) | ||
| 1767 | pr_info(" IO: 0x%x [segment=0x%x]\n", | ||
| 1768 | phb->ioda.io_size, phb->ioda.io_segsize); | ||
| 1769 | |||
| 1360 | 1770 | ||
| 1361 | phb->hose->ops = &pnv_pci_ops; | 1771 | phb->hose->ops = &pnv_pci_ops; |
| 1772 | phb->get_pe_state = pnv_ioda_get_pe_state; | ||
| 1773 | phb->freeze_pe = pnv_ioda_freeze_pe; | ||
| 1774 | phb->unfreeze_pe = pnv_ioda_unfreeze_pe; | ||
| 1362 | #ifdef CONFIG_EEH | 1775 | #ifdef CONFIG_EEH |
| 1363 | phb->eeh_ops = &ioda_eeh_ops; | 1776 | phb->eeh_ops = &ioda_eeh_ops; |
| 1364 | #endif | 1777 | #endif |
| @@ -1404,6 +1817,10 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, | |||
| 1404 | ioda_eeh_phb_reset(hose, EEH_RESET_FUNDAMENTAL); | 1817 | ioda_eeh_phb_reset(hose, EEH_RESET_FUNDAMENTAL); |
| 1405 | ioda_eeh_phb_reset(hose, OPAL_DEASSERT_RESET); | 1818 | ioda_eeh_phb_reset(hose, OPAL_DEASSERT_RESET); |
| 1406 | } | 1819 | } |
| 1820 | |||
| 1821 | /* Configure M64 window */ | ||
| 1822 | if (phb->init_m64 && phb->init_m64(phb)) | ||
| 1823 | hose->mem_resources[1].flags = 0; | ||
| 1407 | } | 1824 | } |
| 1408 | 1825 | ||
| 1409 | void __init pnv_pci_init_ioda2_phb(struct device_node *np) | 1826 | void __init pnv_pci_init_ioda2_phb(struct device_node *np) |
diff --git a/arch/powerpc/platforms/powernv/pci-p5ioc2.c b/arch/powerpc/platforms/powernv/pci-p5ioc2.c index e3807d69393e..94ce3481490b 100644 --- a/arch/powerpc/platforms/powernv/pci-p5ioc2.c +++ b/arch/powerpc/platforms/powernv/pci-p5ioc2.c | |||
| @@ -172,7 +172,8 @@ static void __init pnv_pci_init_p5ioc2_phb(struct device_node *np, u64 hub_id, | |||
| 172 | /* Setup TCEs */ | 172 | /* Setup TCEs */ |
| 173 | phb->dma_dev_setup = pnv_pci_p5ioc2_dma_dev_setup; | 173 | phb->dma_dev_setup = pnv_pci_p5ioc2_dma_dev_setup; |
| 174 | pnv_pci_setup_iommu_table(&phb->p5ioc2.iommu_table, | 174 | pnv_pci_setup_iommu_table(&phb->p5ioc2.iommu_table, |
| 175 | tce_mem, tce_size, 0); | 175 | tce_mem, tce_size, 0, |
| 176 | IOMMU_PAGE_SHIFT_4K); | ||
| 176 | } | 177 | } |
| 177 | 178 | ||
| 178 | void __init pnv_pci_init_p5ioc2_hub(struct device_node *np) | 179 | void __init pnv_pci_init_p5ioc2_hub(struct device_node *np) |
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index f91a4e5d872e..b854b57ed5e1 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c | |||
| @@ -132,61 +132,78 @@ static void pnv_pci_dump_p7ioc_diag_data(struct pci_controller *hose, | |||
| 132 | 132 | ||
| 133 | data = (struct OpalIoP7IOCPhbErrorData *)common; | 133 | data = (struct OpalIoP7IOCPhbErrorData *)common; |
| 134 | pr_info("P7IOC PHB#%d Diag-data (Version: %d)\n", | 134 | pr_info("P7IOC PHB#%d Diag-data (Version: %d)\n", |
| 135 | hose->global_number, common->version); | 135 | hose->global_number, be32_to_cpu(common->version)); |
| 136 | 136 | ||
| 137 | if (data->brdgCtl) | 137 | if (data->brdgCtl) |
| 138 | pr_info("brdgCtl: %08x\n", | 138 | pr_info("brdgCtl: %08x\n", |
| 139 | data->brdgCtl); | 139 | be32_to_cpu(data->brdgCtl)); |
| 140 | if (data->portStatusReg || data->rootCmplxStatus || | 140 | if (data->portStatusReg || data->rootCmplxStatus || |
| 141 | data->busAgentStatus) | 141 | data->busAgentStatus) |
| 142 | pr_info("UtlSts: %08x %08x %08x\n", | 142 | pr_info("UtlSts: %08x %08x %08x\n", |
| 143 | data->portStatusReg, data->rootCmplxStatus, | 143 | be32_to_cpu(data->portStatusReg), |
| 144 | data->busAgentStatus); | 144 | be32_to_cpu(data->rootCmplxStatus), |
| 145 | be32_to_cpu(data->busAgentStatus)); | ||
| 145 | if (data->deviceStatus || data->slotStatus || | 146 | if (data->deviceStatus || data->slotStatus || |
| 146 | data->linkStatus || data->devCmdStatus || | 147 | data->linkStatus || data->devCmdStatus || |
| 147 | data->devSecStatus) | 148 | data->devSecStatus) |
| 148 | pr_info("RootSts: %08x %08x %08x %08x %08x\n", | 149 | pr_info("RootSts: %08x %08x %08x %08x %08x\n", |
| 149 | data->deviceStatus, data->slotStatus, | 150 | be32_to_cpu(data->deviceStatus), |
| 150 | data->linkStatus, data->devCmdStatus, | 151 | be32_to_cpu(data->slotStatus), |
| 151 | data->devSecStatus); | 152 | be32_to_cpu(data->linkStatus), |
| 153 | be32_to_cpu(data->devCmdStatus), | ||
| 154 | be32_to_cpu(data->devSecStatus)); | ||
| 152 | if (data->rootErrorStatus || data->uncorrErrorStatus || | 155 | if (data->rootErrorStatus || data->uncorrErrorStatus || |
| 153 | data->corrErrorStatus) | 156 | data->corrErrorStatus) |
| 154 | pr_info("RootErrSts: %08x %08x %08x\n", | 157 | pr_info("RootErrSts: %08x %08x %08x\n", |
| 155 | data->rootErrorStatus, data->uncorrErrorStatus, | 158 | be32_to_cpu(data->rootErrorStatus), |
| 156 | data->corrErrorStatus); | 159 | be32_to_cpu(data->uncorrErrorStatus), |
| 160 | be32_to_cpu(data->corrErrorStatus)); | ||
| 157 | if (data->tlpHdr1 || data->tlpHdr2 || | 161 | if (data->tlpHdr1 || data->tlpHdr2 || |
| 158 | data->tlpHdr3 || data->tlpHdr4) | 162 | data->tlpHdr3 || data->tlpHdr4) |
| 159 | pr_info("RootErrLog: %08x %08x %08x %08x\n", | 163 | pr_info("RootErrLog: %08x %08x %08x %08x\n", |
| 160 | data->tlpHdr1, data->tlpHdr2, | 164 | be32_to_cpu(data->tlpHdr1), |
| 161 | data->tlpHdr3, data->tlpHdr4); | 165 | be32_to_cpu(data->tlpHdr2), |
| 166 | be32_to_cpu(data->tlpHdr3), | ||
| 167 | be32_to_cpu(data->tlpHdr4)); | ||
| 162 | if (data->sourceId || data->errorClass || | 168 | if (data->sourceId || data->errorClass || |
| 163 | data->correlator) | 169 | data->correlator) |
| 164 | pr_info("RootErrLog1: %08x %016llx %016llx\n", | 170 | pr_info("RootErrLog1: %08x %016llx %016llx\n", |
| 165 | data->sourceId, data->errorClass, | 171 | be32_to_cpu(data->sourceId), |
| 166 | data->correlator); | 172 | be64_to_cpu(data->errorClass), |
| 173 | be64_to_cpu(data->correlator)); | ||
| 167 | if (data->p7iocPlssr || data->p7iocCsr) | 174 | if (data->p7iocPlssr || data->p7iocCsr) |
| 168 | pr_info("PhbSts: %016llx %016llx\n", | 175 | pr_info("PhbSts: %016llx %016llx\n", |
| 169 | data->p7iocPlssr, data->p7iocCsr); | 176 | be64_to_cpu(data->p7iocPlssr), |
| 177 | be64_to_cpu(data->p7iocCsr)); | ||
| 170 | if (data->lemFir) | 178 | if (data->lemFir) |
| 171 | pr_info("Lem: %016llx %016llx %016llx\n", | 179 | pr_info("Lem: %016llx %016llx %016llx\n", |
| 172 | data->lemFir, data->lemErrorMask, | 180 | be64_to_cpu(data->lemFir), |
| 173 | data->lemWOF); | 181 | be64_to_cpu(data->lemErrorMask), |
| 182 | be64_to_cpu(data->lemWOF)); | ||
| 174 | if (data->phbErrorStatus) | 183 | if (data->phbErrorStatus) |
| 175 | pr_info("PhbErr: %016llx %016llx %016llx %016llx\n", | 184 | pr_info("PhbErr: %016llx %016llx %016llx %016llx\n", |
| 176 | data->phbErrorStatus, data->phbFirstErrorStatus, | 185 | be64_to_cpu(data->phbErrorStatus), |
| 177 | data->phbErrorLog0, data->phbErrorLog1); | 186 | be64_to_cpu(data->phbFirstErrorStatus), |
| 187 | be64_to_cpu(data->phbErrorLog0), | ||
| 188 | be64_to_cpu(data->phbErrorLog1)); | ||
| 178 | if (data->mmioErrorStatus) | 189 | if (data->mmioErrorStatus) |
| 179 | pr_info("OutErr: %016llx %016llx %016llx %016llx\n", | 190 | pr_info("OutErr: %016llx %016llx %016llx %016llx\n", |
| 180 | data->mmioErrorStatus, data->mmioFirstErrorStatus, | 191 | be64_to_cpu(data->mmioErrorStatus), |
| 181 | data->mmioErrorLog0, data->mmioErrorLog1); | 192 | be64_to_cpu(data->mmioFirstErrorStatus), |
| 193 | be64_to_cpu(data->mmioErrorLog0), | ||
| 194 | be64_to_cpu(data->mmioErrorLog1)); | ||
| 182 | if (data->dma0ErrorStatus) | 195 | if (data->dma0ErrorStatus) |
| 183 | pr_info("InAErr: %016llx %016llx %016llx %016llx\n", | 196 | pr_info("InAErr: %016llx %016llx %016llx %016llx\n", |
| 184 | data->dma0ErrorStatus, data->dma0FirstErrorStatus, | 197 | be64_to_cpu(data->dma0ErrorStatus), |
| 185 | data->dma0ErrorLog0, data->dma0ErrorLog1); | 198 | be64_to_cpu(data->dma0FirstErrorStatus), |
| 199 | be64_to_cpu(data->dma0ErrorLog0), | ||
| 200 | be64_to_cpu(data->dma0ErrorLog1)); | ||
| 186 | if (data->dma1ErrorStatus) | 201 | if (data->dma1ErrorStatus) |
| 187 | pr_info("InBErr: %016llx %016llx %016llx %016llx\n", | 202 | pr_info("InBErr: %016llx %016llx %016llx %016llx\n", |
| 188 | data->dma1ErrorStatus, data->dma1FirstErrorStatus, | 203 | be64_to_cpu(data->dma1ErrorStatus), |
| 189 | data->dma1ErrorLog0, data->dma1ErrorLog1); | 204 | be64_to_cpu(data->dma1FirstErrorStatus), |
| 205 | be64_to_cpu(data->dma1ErrorLog0), | ||
| 206 | be64_to_cpu(data->dma1ErrorLog1)); | ||
| 190 | 207 | ||
| 191 | for (i = 0; i < OPAL_P7IOC_NUM_PEST_REGS; i++) { | 208 | for (i = 0; i < OPAL_P7IOC_NUM_PEST_REGS; i++) { |
| 192 | if ((data->pestA[i] >> 63) == 0 && | 209 | if ((data->pestA[i] >> 63) == 0 && |
| @@ -194,7 +211,8 @@ static void pnv_pci_dump_p7ioc_diag_data(struct pci_controller *hose, | |||
| 194 | continue; | 211 | continue; |
| 195 | 212 | ||
| 196 | pr_info("PE[%3d] A/B: %016llx %016llx\n", | 213 | pr_info("PE[%3d] A/B: %016llx %016llx\n", |
| 197 | i, data->pestA[i], data->pestB[i]); | 214 | i, be64_to_cpu(data->pestA[i]), |
| 215 | be64_to_cpu(data->pestB[i])); | ||
| 198 | } | 216 | } |
| 199 | } | 217 | } |
| 200 | 218 | ||
| @@ -319,43 +337,52 @@ void pnv_pci_dump_phb_diag_data(struct pci_controller *hose, | |||
| 319 | static void pnv_pci_handle_eeh_config(struct pnv_phb *phb, u32 pe_no) | 337 | static void pnv_pci_handle_eeh_config(struct pnv_phb *phb, u32 pe_no) |
| 320 | { | 338 | { |
| 321 | unsigned long flags, rc; | 339 | unsigned long flags, rc; |
| 322 | int has_diag; | 340 | int has_diag, ret = 0; |
| 323 | 341 | ||
| 324 | spin_lock_irqsave(&phb->lock, flags); | 342 | spin_lock_irqsave(&phb->lock, flags); |
| 325 | 343 | ||
| 344 | /* Fetch PHB diag-data */ | ||
| 326 | rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob, | 345 | rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob, |
| 327 | PNV_PCI_DIAG_BUF_SIZE); | 346 | PNV_PCI_DIAG_BUF_SIZE); |
| 328 | has_diag = (rc == OPAL_SUCCESS); | 347 | has_diag = (rc == OPAL_SUCCESS); |
| 329 | 348 | ||
| 330 | rc = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no, | 349 | /* If PHB supports compound PE, to handle it */ |
| 350 | if (phb->unfreeze_pe) { | ||
| 351 | ret = phb->unfreeze_pe(phb, | ||
| 352 | pe_no, | ||
| 331 | OPAL_EEH_ACTION_CLEAR_FREEZE_ALL); | 353 | OPAL_EEH_ACTION_CLEAR_FREEZE_ALL); |
| 332 | if (rc) { | 354 | } else { |
| 333 | pr_warning("PCI %d: Failed to clear EEH freeze state" | 355 | rc = opal_pci_eeh_freeze_clear(phb->opal_id, |
| 334 | " for PE#%d, err %ld\n", | 356 | pe_no, |
| 335 | phb->hose->global_number, pe_no, rc); | 357 | OPAL_EEH_ACTION_CLEAR_FREEZE_ALL); |
| 336 | 358 | if (rc) { | |
| 337 | /* For now, let's only display the diag buffer when we fail to clear | 359 | pr_warn("%s: Failure %ld clearing frozen " |
| 338 | * the EEH status. We'll do more sensible things later when we have | 360 | "PHB#%x-PE#%x\n", |
| 339 | * proper EEH support. We need to make sure we don't pollute ourselves | 361 | __func__, rc, phb->hose->global_number, |
| 340 | * with the normal errors generated when probing empty slots | 362 | pe_no); |
| 341 | */ | 363 | ret = -EIO; |
| 342 | if (has_diag) | 364 | } |
| 343 | pnv_pci_dump_phb_diag_data(phb->hose, phb->diag.blob); | ||
| 344 | else | ||
| 345 | pr_warning("PCI %d: No diag data available\n", | ||
| 346 | phb->hose->global_number); | ||
| 347 | } | 365 | } |
| 348 | 366 | ||
| 367 | /* | ||
| 368 | * For now, let's only display the diag buffer when we fail to clear | ||
| 369 | * the EEH status. We'll do more sensible things later when we have | ||
| 370 | * proper EEH support. We need to make sure we don't pollute ourselves | ||
| 371 | * with the normal errors generated when probing empty slots | ||
| 372 | */ | ||
| 373 | if (has_diag && ret) | ||
| 374 | pnv_pci_dump_phb_diag_data(phb->hose, phb->diag.blob); | ||
| 375 | |||
| 349 | spin_unlock_irqrestore(&phb->lock, flags); | 376 | spin_unlock_irqrestore(&phb->lock, flags); |
| 350 | } | 377 | } |
| 351 | 378 | ||
| 352 | static void pnv_pci_config_check_eeh(struct pnv_phb *phb, | 379 | static void pnv_pci_config_check_eeh(struct pnv_phb *phb, |
| 353 | struct device_node *dn) | 380 | struct device_node *dn) |
| 354 | { | 381 | { |
| 355 | s64 rc; | ||
| 356 | u8 fstate; | 382 | u8 fstate; |
| 357 | __be16 pcierr; | 383 | __be16 pcierr; |
| 358 | u32 pe_no; | 384 | int pe_no; |
| 385 | s64 rc; | ||
| 359 | 386 | ||
| 360 | /* | 387 | /* |
| 361 | * Get the PE#. During the PCI probe stage, we might not | 388 | * Get the PE#. During the PCI probe stage, we might not |
| @@ -370,20 +397,42 @@ static void pnv_pci_config_check_eeh(struct pnv_phb *phb, | |||
| 370 | pe_no = phb->ioda.reserved_pe; | 397 | pe_no = phb->ioda.reserved_pe; |
| 371 | } | 398 | } |
| 372 | 399 | ||
| 373 | /* Read freeze status */ | 400 | /* |
| 374 | rc = opal_pci_eeh_freeze_status(phb->opal_id, pe_no, &fstate, &pcierr, | 401 | * Fetch frozen state. If the PHB support compound PE, |
| 375 | NULL); | 402 | * we need handle that case. |
| 376 | if (rc) { | 403 | */ |
| 377 | pr_warning("%s: Can't read EEH status (PE#%d) for " | 404 | if (phb->get_pe_state) { |
| 378 | "%s, err %lld\n", | 405 | fstate = phb->get_pe_state(phb, pe_no); |
| 379 | __func__, pe_no, dn->full_name, rc); | 406 | } else { |
| 380 | return; | 407 | rc = opal_pci_eeh_freeze_status(phb->opal_id, |
| 408 | pe_no, | ||
| 409 | &fstate, | ||
| 410 | &pcierr, | ||
| 411 | NULL); | ||
| 412 | if (rc) { | ||
| 413 | pr_warn("%s: Failure %lld getting PHB#%x-PE#%x state\n", | ||
| 414 | __func__, rc, phb->hose->global_number, pe_no); | ||
| 415 | return; | ||
| 416 | } | ||
| 381 | } | 417 | } |
| 418 | |||
| 382 | cfg_dbg(" -> EEH check, bdfn=%04x PE#%d fstate=%x\n", | 419 | cfg_dbg(" -> EEH check, bdfn=%04x PE#%d fstate=%x\n", |
| 383 | (PCI_DN(dn)->busno << 8) | (PCI_DN(dn)->devfn), | 420 | (PCI_DN(dn)->busno << 8) | (PCI_DN(dn)->devfn), |
| 384 | pe_no, fstate); | 421 | pe_no, fstate); |
| 385 | if (fstate != 0) | 422 | |
| 423 | /* Clear the frozen state if applicable */ | ||
| 424 | if (fstate == OPAL_EEH_STOPPED_MMIO_FREEZE || | ||
| 425 | fstate == OPAL_EEH_STOPPED_DMA_FREEZE || | ||
| 426 | fstate == OPAL_EEH_STOPPED_MMIO_DMA_FREEZE) { | ||
| 427 | /* | ||
| 428 | * If PHB supports compound PE, freeze it for | ||
| 429 | * consistency. | ||
| 430 | */ | ||
| 431 | if (phb->freeze_pe) | ||
| 432 | phb->freeze_pe(phb, pe_no); | ||
| 433 | |||
| 386 | pnv_pci_handle_eeh_config(phb, pe_no); | 434 | pnv_pci_handle_eeh_config(phb, pe_no); |
| 435 | } | ||
| 387 | } | 436 | } |
| 388 | 437 | ||
| 389 | int pnv_pci_cfg_read(struct device_node *dn, | 438 | int pnv_pci_cfg_read(struct device_node *dn, |
| @@ -564,10 +613,11 @@ static int pnv_tce_build(struct iommu_table *tbl, long index, long npages, | |||
| 564 | proto_tce |= TCE_PCI_WRITE; | 613 | proto_tce |= TCE_PCI_WRITE; |
| 565 | 614 | ||
| 566 | tces = tcep = ((__be64 *)tbl->it_base) + index - tbl->it_offset; | 615 | tces = tcep = ((__be64 *)tbl->it_base) + index - tbl->it_offset; |
| 567 | rpn = __pa(uaddr) >> TCE_SHIFT; | 616 | rpn = __pa(uaddr) >> tbl->it_page_shift; |
| 568 | 617 | ||
| 569 | while (npages--) | 618 | while (npages--) |
| 570 | *(tcep++) = cpu_to_be64(proto_tce | (rpn++ << TCE_RPN_SHIFT)); | 619 | *(tcep++) = cpu_to_be64(proto_tce | |
| 620 | (rpn++ << tbl->it_page_shift)); | ||
| 571 | 621 | ||
| 572 | /* Some implementations won't cache invalid TCEs and thus may not | 622 | /* Some implementations won't cache invalid TCEs and thus may not |
| 573 | * need that flush. We'll probably turn it_type into a bit mask | 623 | * need that flush. We'll probably turn it_type into a bit mask |
| @@ -627,11 +677,11 @@ static void pnv_tce_free_rm(struct iommu_table *tbl, long index, long npages) | |||
| 627 | 677 | ||
| 628 | void pnv_pci_setup_iommu_table(struct iommu_table *tbl, | 678 | void pnv_pci_setup_iommu_table(struct iommu_table *tbl, |
| 629 | void *tce_mem, u64 tce_size, | 679 | void *tce_mem, u64 tce_size, |
| 630 | u64 dma_offset) | 680 | u64 dma_offset, unsigned page_shift) |
| 631 | { | 681 | { |
| 632 | tbl->it_blocksize = 16; | 682 | tbl->it_blocksize = 16; |
| 633 | tbl->it_base = (unsigned long)tce_mem; | 683 | tbl->it_base = (unsigned long)tce_mem; |
| 634 | tbl->it_page_shift = IOMMU_PAGE_SHIFT_4K; | 684 | tbl->it_page_shift = page_shift; |
| 635 | tbl->it_offset = dma_offset >> tbl->it_page_shift; | 685 | tbl->it_offset = dma_offset >> tbl->it_page_shift; |
| 636 | tbl->it_index = 0; | 686 | tbl->it_index = 0; |
| 637 | tbl->it_size = tce_size >> 3; | 687 | tbl->it_size = tce_size >> 3; |
| @@ -656,7 +706,7 @@ static struct iommu_table *pnv_pci_setup_bml_iommu(struct pci_controller *hose) | |||
| 656 | if (WARN_ON(!tbl)) | 706 | if (WARN_ON(!tbl)) |
| 657 | return NULL; | 707 | return NULL; |
| 658 | pnv_pci_setup_iommu_table(tbl, __va(be64_to_cpup(basep)), | 708 | pnv_pci_setup_iommu_table(tbl, __va(be64_to_cpup(basep)), |
| 659 | be32_to_cpup(sizep), 0); | 709 | be32_to_cpup(sizep), 0, IOMMU_PAGE_SHIFT_4K); |
| 660 | iommu_init_table(tbl, hose->node); | 710 | iommu_init_table(tbl, hose->node); |
| 661 | iommu_register_group(tbl, pci_domain_nr(hose->bus), 0); | 711 | iommu_register_group(tbl, pci_domain_nr(hose->bus), 0); |
| 662 | 712 | ||
| @@ -842,5 +892,4 @@ static int __init tce_iommu_bus_notifier_init(void) | |||
| 842 | bus_register_notifier(&pci_bus_type, &tce_iommu_bus_nb); | 892 | bus_register_notifier(&pci_bus_type, &tce_iommu_bus_nb); |
| 843 | return 0; | 893 | return 0; |
| 844 | } | 894 | } |
| 845 | 895 | machine_subsys_initcall_sync(powernv, tce_iommu_bus_notifier_init); | |
| 846 | subsys_initcall_sync(tce_iommu_bus_notifier_init); | ||
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index 676232c34328..48494d4b6058 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h | |||
| @@ -21,6 +21,8 @@ enum pnv_phb_model { | |||
| 21 | #define PNV_IODA_PE_DEV (1 << 0) /* PE has single PCI device */ | 21 | #define PNV_IODA_PE_DEV (1 << 0) /* PE has single PCI device */ |
| 22 | #define PNV_IODA_PE_BUS (1 << 1) /* PE has primary PCI bus */ | 22 | #define PNV_IODA_PE_BUS (1 << 1) /* PE has primary PCI bus */ |
| 23 | #define PNV_IODA_PE_BUS_ALL (1 << 2) /* PE has subordinate buses */ | 23 | #define PNV_IODA_PE_BUS_ALL (1 << 2) /* PE has subordinate buses */ |
| 24 | #define PNV_IODA_PE_MASTER (1 << 3) /* Master PE in compound case */ | ||
| 25 | #define PNV_IODA_PE_SLAVE (1 << 4) /* Slave PE in compound case */ | ||
| 24 | 26 | ||
| 25 | /* Data associated with a PE, including IOMMU tracking etc.. */ | 27 | /* Data associated with a PE, including IOMMU tracking etc.. */ |
| 26 | struct pnv_phb; | 28 | struct pnv_phb; |
| @@ -64,6 +66,10 @@ struct pnv_ioda_pe { | |||
| 64 | */ | 66 | */ |
| 65 | int mve_number; | 67 | int mve_number; |
| 66 | 68 | ||
| 69 | /* PEs in compound case */ | ||
| 70 | struct pnv_ioda_pe *master; | ||
| 71 | struct list_head slaves; | ||
| 72 | |||
| 67 | /* Link in list of PE#s */ | 73 | /* Link in list of PE#s */ |
| 68 | struct list_head dma_link; | 74 | struct list_head dma_link; |
| 69 | struct list_head list; | 75 | struct list_head list; |
| @@ -119,6 +125,12 @@ struct pnv_phb { | |||
| 119 | void (*fixup_phb)(struct pci_controller *hose); | 125 | void (*fixup_phb)(struct pci_controller *hose); |
| 120 | u32 (*bdfn_to_pe)(struct pnv_phb *phb, struct pci_bus *bus, u32 devfn); | 126 | u32 (*bdfn_to_pe)(struct pnv_phb *phb, struct pci_bus *bus, u32 devfn); |
| 121 | void (*shutdown)(struct pnv_phb *phb); | 127 | void (*shutdown)(struct pnv_phb *phb); |
| 128 | int (*init_m64)(struct pnv_phb *phb); | ||
| 129 | void (*alloc_m64_pe)(struct pnv_phb *phb); | ||
| 130 | int (*pick_m64_pe)(struct pnv_phb *phb, struct pci_bus *bus, int all); | ||
| 131 | int (*get_pe_state)(struct pnv_phb *phb, int pe_no); | ||
| 132 | void (*freeze_pe)(struct pnv_phb *phb, int pe_no); | ||
| 133 | int (*unfreeze_pe)(struct pnv_phb *phb, int pe_no, int opt); | ||
| 122 | 134 | ||
| 123 | union { | 135 | union { |
| 124 | struct { | 136 | struct { |
| @@ -129,9 +141,20 @@ struct pnv_phb { | |||
| 129 | /* Global bridge info */ | 141 | /* Global bridge info */ |
| 130 | unsigned int total_pe; | 142 | unsigned int total_pe; |
| 131 | unsigned int reserved_pe; | 143 | unsigned int reserved_pe; |
| 144 | |||
| 145 | /* 32-bit MMIO window */ | ||
| 132 | unsigned int m32_size; | 146 | unsigned int m32_size; |
| 133 | unsigned int m32_segsize; | 147 | unsigned int m32_segsize; |
| 134 | unsigned int m32_pci_base; | 148 | unsigned int m32_pci_base; |
| 149 | |||
| 150 | /* 64-bit MMIO window */ | ||
| 151 | unsigned int m64_bar_idx; | ||
| 152 | unsigned long m64_size; | ||
| 153 | unsigned long m64_segsize; | ||
| 154 | unsigned long m64_base; | ||
| 155 | unsigned long m64_bar_alloc; | ||
| 156 | |||
| 157 | /* IO ports */ | ||
| 135 | unsigned int io_size; | 158 | unsigned int io_size; |
| 136 | unsigned int io_segsize; | 159 | unsigned int io_segsize; |
| 137 | unsigned int io_pci_base; | 160 | unsigned int io_pci_base; |
| @@ -198,7 +221,7 @@ int pnv_pci_cfg_write(struct device_node *dn, | |||
| 198 | int where, int size, u32 val); | 221 | int where, int size, u32 val); |
| 199 | extern void pnv_pci_setup_iommu_table(struct iommu_table *tbl, | 222 | extern void pnv_pci_setup_iommu_table(struct iommu_table *tbl, |
| 200 | void *tce_mem, u64 tce_size, | 223 | void *tce_mem, u64 tce_size, |
| 201 | u64 dma_offset); | 224 | u64 dma_offset, unsigned page_shift); |
| 202 | extern void pnv_pci_init_p5ioc2_hub(struct device_node *np); | 225 | extern void pnv_pci_init_p5ioc2_hub(struct device_node *np); |
| 203 | extern void pnv_pci_init_ioda_hub(struct device_node *np); | 226 | extern void pnv_pci_init_ioda_hub(struct device_node *np); |
| 204 | extern void pnv_pci_init_ioda2_phb(struct device_node *np); | 227 | extern void pnv_pci_init_ioda2_phb(struct device_node *np); |
diff --git a/arch/powerpc/platforms/powernv/rng.c b/arch/powerpc/platforms/powernv/rng.c index 1cb160dc1609..80db43944afe 100644 --- a/arch/powerpc/platforms/powernv/rng.c +++ b/arch/powerpc/platforms/powernv/rng.c | |||
| @@ -123,4 +123,4 @@ static __init int rng_init(void) | |||
| 123 | 123 | ||
| 124 | return 0; | 124 | return 0; |
| 125 | } | 125 | } |
| 126 | subsys_initcall(rng_init); | 126 | machine_subsys_initcall(powernv, rng_init); |
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c index d9b88fa7c5a3..5a0e2dc6de5f 100644 --- a/arch/powerpc/platforms/powernv/setup.c +++ b/arch/powerpc/platforms/powernv/setup.c | |||
| @@ -264,6 +264,8 @@ static void __init pnv_setup_machdep_opal(void) | |||
| 264 | ppc_md.halt = pnv_halt; | 264 | ppc_md.halt = pnv_halt; |
| 265 | ppc_md.machine_check_exception = opal_machine_check; | 265 | ppc_md.machine_check_exception = opal_machine_check; |
| 266 | ppc_md.mce_check_early_recovery = opal_mce_check_early_recovery; | 266 | ppc_md.mce_check_early_recovery = opal_mce_check_early_recovery; |
| 267 | ppc_md.hmi_exception_early = opal_hmi_exception_early; | ||
| 268 | ppc_md.handle_hmi_exception = opal_handle_hmi_exception; | ||
| 267 | } | 269 | } |
| 268 | 270 | ||
| 269 | #ifdef CONFIG_PPC_POWERNV_RTAS | 271 | #ifdef CONFIG_PPC_POWERNV_RTAS |
diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c index 7d61498e45c0..1062f71f5a85 100644 --- a/arch/powerpc/platforms/pseries/dtl.c +++ b/arch/powerpc/platforms/pseries/dtl.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <asm/lppaca.h> | 29 | #include <asm/lppaca.h> |
| 30 | #include <asm/debug.h> | 30 | #include <asm/debug.h> |
| 31 | #include <asm/plpar_wrappers.h> | 31 | #include <asm/plpar_wrappers.h> |
| 32 | #include <asm/machdep.h> | ||
| 32 | 33 | ||
| 33 | struct dtl { | 34 | struct dtl { |
| 34 | struct dtl_entry *buf; | 35 | struct dtl_entry *buf; |
| @@ -391,4 +392,4 @@ err_remove_dir: | |||
| 391 | err: | 392 | err: |
| 392 | return rc; | 393 | return rc; |
| 393 | } | 394 | } |
| 394 | arch_initcall(dtl_init); | 395 | machine_arch_initcall(pseries, dtl_init); |
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c index 0bec0c02c5e7..b08053819d99 100644 --- a/arch/powerpc/platforms/pseries/eeh_pseries.c +++ b/arch/powerpc/platforms/pseries/eeh_pseries.c | |||
| @@ -89,26 +89,26 @@ static int pseries_eeh_init(void) | |||
| 89 | * of domain/bus/slot/function for EEH RTAS operations. | 89 | * of domain/bus/slot/function for EEH RTAS operations. |
| 90 | */ | 90 | */ |
| 91 | if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE) { | 91 | if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE) { |
| 92 | pr_warning("%s: RTAS service <ibm,set-eeh-option> invalid\n", | 92 | pr_warn("%s: RTAS service <ibm,set-eeh-option> invalid\n", |
| 93 | __func__); | 93 | __func__); |
| 94 | return -EINVAL; | 94 | return -EINVAL; |
| 95 | } else if (ibm_set_slot_reset == RTAS_UNKNOWN_SERVICE) { | 95 | } else if (ibm_set_slot_reset == RTAS_UNKNOWN_SERVICE) { |
| 96 | pr_warning("%s: RTAS service <ibm,set-slot-reset> invalid\n", | 96 | pr_warn("%s: RTAS service <ibm,set-slot-reset> invalid\n", |
| 97 | __func__); | 97 | __func__); |
| 98 | return -EINVAL; | 98 | return -EINVAL; |
| 99 | } else if (ibm_read_slot_reset_state2 == RTAS_UNKNOWN_SERVICE && | 99 | } else if (ibm_read_slot_reset_state2 == RTAS_UNKNOWN_SERVICE && |
| 100 | ibm_read_slot_reset_state == RTAS_UNKNOWN_SERVICE) { | 100 | ibm_read_slot_reset_state == RTAS_UNKNOWN_SERVICE) { |
| 101 | pr_warning("%s: RTAS service <ibm,read-slot-reset-state2> and " | 101 | pr_warn("%s: RTAS service <ibm,read-slot-reset-state2> and " |
| 102 | "<ibm,read-slot-reset-state> invalid\n", | 102 | "<ibm,read-slot-reset-state> invalid\n", |
| 103 | __func__); | 103 | __func__); |
| 104 | return -EINVAL; | 104 | return -EINVAL; |
| 105 | } else if (ibm_slot_error_detail == RTAS_UNKNOWN_SERVICE) { | 105 | } else if (ibm_slot_error_detail == RTAS_UNKNOWN_SERVICE) { |
| 106 | pr_warning("%s: RTAS service <ibm,slot-error-detail> invalid\n", | 106 | pr_warn("%s: RTAS service <ibm,slot-error-detail> invalid\n", |
| 107 | __func__); | 107 | __func__); |
| 108 | return -EINVAL; | 108 | return -EINVAL; |
| 109 | } else if (ibm_configure_pe == RTAS_UNKNOWN_SERVICE && | 109 | } else if (ibm_configure_pe == RTAS_UNKNOWN_SERVICE && |
| 110 | ibm_configure_bridge == RTAS_UNKNOWN_SERVICE) { | 110 | ibm_configure_bridge == RTAS_UNKNOWN_SERVICE) { |
| 111 | pr_warning("%s: RTAS service <ibm,configure-pe> and " | 111 | pr_warn("%s: RTAS service <ibm,configure-pe> and " |
| 112 | "<ibm,configure-bridge> invalid\n", | 112 | "<ibm,configure-bridge> invalid\n", |
| 113 | __func__); | 113 | __func__); |
| 114 | return -EINVAL; | 114 | return -EINVAL; |
| @@ -118,17 +118,17 @@ static int pseries_eeh_init(void) | |||
| 118 | spin_lock_init(&slot_errbuf_lock); | 118 | spin_lock_init(&slot_errbuf_lock); |
| 119 | eeh_error_buf_size = rtas_token("rtas-error-log-max"); | 119 | eeh_error_buf_size = rtas_token("rtas-error-log-max"); |
| 120 | if (eeh_error_buf_size == RTAS_UNKNOWN_SERVICE) { | 120 | if (eeh_error_buf_size == RTAS_UNKNOWN_SERVICE) { |
| 121 | pr_warning("%s: unknown EEH error log size\n", | 121 | pr_warn("%s: unknown EEH error log size\n", |
| 122 | __func__); | 122 | __func__); |
| 123 | eeh_error_buf_size = 1024; | 123 | eeh_error_buf_size = 1024; |
| 124 | } else if (eeh_error_buf_size > RTAS_ERROR_LOG_MAX) { | 124 | } else if (eeh_error_buf_size > RTAS_ERROR_LOG_MAX) { |
| 125 | pr_warning("%s: EEH error log size %d exceeds the maximal %d\n", | 125 | pr_warn("%s: EEH error log size %d exceeds the maximal %d\n", |
| 126 | __func__, eeh_error_buf_size, RTAS_ERROR_LOG_MAX); | 126 | __func__, eeh_error_buf_size, RTAS_ERROR_LOG_MAX); |
| 127 | eeh_error_buf_size = RTAS_ERROR_LOG_MAX; | 127 | eeh_error_buf_size = RTAS_ERROR_LOG_MAX; |
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | /* Set EEH probe mode */ | 130 | /* Set EEH probe mode */ |
| 131 | eeh_probe_mode_set(EEH_PROBE_MODE_DEVTREE); | 131 | eeh_add_flag(EEH_PROBE_MODE_DEVTREE | EEH_ENABLE_IO_FOR_LOG); |
| 132 | 132 | ||
| 133 | return 0; | 133 | return 0; |
| 134 | } | 134 | } |
| @@ -270,7 +270,7 @@ static void *pseries_eeh_of_probe(struct device_node *dn, void *flag) | |||
| 270 | /* Retrieve the device address */ | 270 | /* Retrieve the device address */ |
| 271 | regs = of_get_property(dn, "reg", NULL); | 271 | regs = of_get_property(dn, "reg", NULL); |
| 272 | if (!regs) { | 272 | if (!regs) { |
| 273 | pr_warning("%s: OF node property %s::reg not found\n", | 273 | pr_warn("%s: OF node property %s::reg not found\n", |
| 274 | __func__, dn->full_name); | 274 | __func__, dn->full_name); |
| 275 | return NULL; | 275 | return NULL; |
| 276 | } | 276 | } |
| @@ -297,7 +297,7 @@ static void *pseries_eeh_of_probe(struct device_node *dn, void *flag) | |||
| 297 | enable = 1; | 297 | enable = 1; |
| 298 | 298 | ||
| 299 | if (enable) { | 299 | if (enable) { |
| 300 | eeh_set_enable(true); | 300 | eeh_add_flag(EEH_ENABLED); |
| 301 | eeh_add_to_parent_pe(edev); | 301 | eeh_add_to_parent_pe(edev); |
| 302 | 302 | ||
| 303 | pr_debug("%s: EEH enabled on %s PHB#%d-PE#%x, config addr#%x\n", | 303 | pr_debug("%s: EEH enabled on %s PHB#%d-PE#%x, config addr#%x\n", |
| @@ -398,7 +398,7 @@ static int pseries_eeh_get_pe_addr(struct eeh_pe *pe) | |||
| 398 | pe->config_addr, BUID_HI(pe->phb->buid), | 398 | pe->config_addr, BUID_HI(pe->phb->buid), |
| 399 | BUID_LO(pe->phb->buid), 0); | 399 | BUID_LO(pe->phb->buid), 0); |
| 400 | if (ret) { | 400 | if (ret) { |
| 401 | pr_warning("%s: Failed to get address for PHB#%d-PE#%x\n", | 401 | pr_warn("%s: Failed to get address for PHB#%d-PE#%x\n", |
| 402 | __func__, pe->phb->global_number, pe->config_addr); | 402 | __func__, pe->phb->global_number, pe->config_addr); |
| 403 | return 0; | 403 | return 0; |
| 404 | } | 404 | } |
| @@ -411,7 +411,7 @@ static int pseries_eeh_get_pe_addr(struct eeh_pe *pe) | |||
| 411 | pe->config_addr, BUID_HI(pe->phb->buid), | 411 | pe->config_addr, BUID_HI(pe->phb->buid), |
| 412 | BUID_LO(pe->phb->buid), 0); | 412 | BUID_LO(pe->phb->buid), 0); |
| 413 | if (ret) { | 413 | if (ret) { |
| 414 | pr_warning("%s: Failed to get address for PHB#%d-PE#%x\n", | 414 | pr_warn("%s: Failed to get address for PHB#%d-PE#%x\n", |
| 415 | __func__, pe->phb->global_number, pe->config_addr); | 415 | __func__, pe->phb->global_number, pe->config_addr); |
| 416 | return 0; | 416 | return 0; |
| 417 | } | 417 | } |
| @@ -584,17 +584,17 @@ static int pseries_eeh_wait_state(struct eeh_pe *pe, int max_wait) | |||
| 584 | return ret; | 584 | return ret; |
| 585 | 585 | ||
| 586 | if (max_wait <= 0) { | 586 | if (max_wait <= 0) { |
| 587 | pr_warning("%s: Timeout when getting PE's state (%d)\n", | 587 | pr_warn("%s: Timeout when getting PE's state (%d)\n", |
| 588 | __func__, max_wait); | 588 | __func__, max_wait); |
| 589 | return EEH_STATE_NOT_SUPPORT; | 589 | return EEH_STATE_NOT_SUPPORT; |
| 590 | } | 590 | } |
| 591 | 591 | ||
| 592 | if (mwait <= 0) { | 592 | if (mwait <= 0) { |
| 593 | pr_warning("%s: Firmware returned bad wait value %d\n", | 593 | pr_warn("%s: Firmware returned bad wait value %d\n", |
| 594 | __func__, mwait); | 594 | __func__, mwait); |
| 595 | mwait = EEH_STATE_MIN_WAIT_TIME; | 595 | mwait = EEH_STATE_MIN_WAIT_TIME; |
| 596 | } else if (mwait > EEH_STATE_MAX_WAIT_TIME) { | 596 | } else if (mwait > EEH_STATE_MAX_WAIT_TIME) { |
| 597 | pr_warning("%s: Firmware returned too long wait value %d\n", | 597 | pr_warn("%s: Firmware returned too long wait value %d\n", |
| 598 | __func__, mwait); | 598 | __func__, mwait); |
| 599 | mwait = EEH_STATE_MAX_WAIT_TIME; | 599 | mwait = EEH_STATE_MAX_WAIT_TIME; |
| 600 | } | 600 | } |
| @@ -675,7 +675,7 @@ static int pseries_eeh_configure_bridge(struct eeh_pe *pe) | |||
| 675 | } | 675 | } |
| 676 | 676 | ||
| 677 | if (ret) | 677 | if (ret) |
| 678 | pr_warning("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n", | 678 | pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n", |
| 679 | __func__, pe->phb->global_number, pe->addr, ret); | 679 | __func__, pe->phb->global_number, pe->addr, ret); |
| 680 | 680 | ||
| 681 | return ret; | 681 | return ret; |
| @@ -743,10 +743,7 @@ static struct eeh_ops pseries_eeh_ops = { | |||
| 743 | */ | 743 | */ |
| 744 | static int __init eeh_pseries_init(void) | 744 | static int __init eeh_pseries_init(void) |
| 745 | { | 745 | { |
| 746 | int ret = -EINVAL; | 746 | int ret; |
| 747 | |||
| 748 | if (!machine_is(pseries)) | ||
| 749 | return ret; | ||
| 750 | 747 | ||
| 751 | ret = eeh_ops_register(&pseries_eeh_ops); | 748 | ret = eeh_ops_register(&pseries_eeh_ops); |
| 752 | if (!ret) | 749 | if (!ret) |
| @@ -757,5 +754,4 @@ static int __init eeh_pseries_init(void) | |||
| 757 | 754 | ||
| 758 | return ret; | 755 | return ret; |
| 759 | } | 756 | } |
| 760 | 757 | machine_early_initcall(pseries, eeh_pseries_init); | |
| 761 | early_initcall(eeh_pseries_init); | ||
diff --git a/arch/powerpc/platforms/pseries/hvCall.S b/arch/powerpc/platforms/pseries/hvCall.S index 99ecf0a5a929..3fda3f17b84e 100644 --- a/arch/powerpc/platforms/pseries/hvCall.S +++ b/arch/powerpc/platforms/pseries/hvCall.S | |||
| @@ -12,9 +12,13 @@ | |||
| 12 | #include <asm/ppc_asm.h> | 12 | #include <asm/ppc_asm.h> |
| 13 | #include <asm/asm-offsets.h> | 13 | #include <asm/asm-offsets.h> |
| 14 | #include <asm/ptrace.h> | 14 | #include <asm/ptrace.h> |
| 15 | #include <asm/jump_label.h> | ||
| 16 | |||
| 17 | .section ".text" | ||
| 15 | 18 | ||
| 16 | #ifdef CONFIG_TRACEPOINTS | 19 | #ifdef CONFIG_TRACEPOINTS |
| 17 | 20 | ||
| 21 | #ifndef CONFIG_JUMP_LABEL | ||
| 18 | .section ".toc","aw" | 22 | .section ".toc","aw" |
| 19 | 23 | ||
| 20 | .globl hcall_tracepoint_refcount | 24 | .globl hcall_tracepoint_refcount |
| @@ -22,21 +26,13 @@ hcall_tracepoint_refcount: | |||
| 22 | .llong 0 | 26 | .llong 0 |
| 23 | 27 | ||
| 24 | .section ".text" | 28 | .section ".text" |
| 29 | #endif | ||
| 25 | 30 | ||
| 26 | /* | 31 | /* |
| 27 | * precall must preserve all registers. use unused STK_PARAM() | 32 | * precall must preserve all registers. use unused STK_PARAM() |
| 28 | * areas to save snapshots and opcode. We branch around this | 33 | * areas to save snapshots and opcode. |
| 29 | * in early init (eg when populating the MMU hashtable) by using an | ||
| 30 | * unconditional cpu feature. | ||
| 31 | */ | 34 | */ |
| 32 | #define HCALL_INST_PRECALL(FIRST_REG) \ | 35 | #define HCALL_INST_PRECALL(FIRST_REG) \ |
| 33 | BEGIN_FTR_SECTION; \ | ||
| 34 | b 1f; \ | ||
| 35 | END_FTR_SECTION(0, 1); \ | ||
| 36 | ld r12,hcall_tracepoint_refcount@toc(r2); \ | ||
| 37 | std r12,32(r1); \ | ||
| 38 | cmpdi r12,0; \ | ||
| 39 | beq+ 1f; \ | ||
| 40 | mflr r0; \ | 36 | mflr r0; \ |
| 41 | std r3,STK_PARAM(R3)(r1); \ | 37 | std r3,STK_PARAM(R3)(r1); \ |
| 42 | std r4,STK_PARAM(R4)(r1); \ | 38 | std r4,STK_PARAM(R4)(r1); \ |
| @@ -50,45 +46,29 @@ END_FTR_SECTION(0, 1); \ | |||
| 50 | addi r4,r1,STK_PARAM(FIRST_REG); \ | 46 | addi r4,r1,STK_PARAM(FIRST_REG); \ |
| 51 | stdu r1,-STACK_FRAME_OVERHEAD(r1); \ | 47 | stdu r1,-STACK_FRAME_OVERHEAD(r1); \ |
| 52 | bl __trace_hcall_entry; \ | 48 | bl __trace_hcall_entry; \ |
| 53 | addi r1,r1,STACK_FRAME_OVERHEAD; \ | 49 | ld r3,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1); \ |
| 54 | ld r0,16(r1); \ | 50 | ld r4,STACK_FRAME_OVERHEAD+STK_PARAM(R4)(r1); \ |
| 55 | ld r3,STK_PARAM(R3)(r1); \ | 51 | ld r5,STACK_FRAME_OVERHEAD+STK_PARAM(R5)(r1); \ |
| 56 | ld r4,STK_PARAM(R4)(r1); \ | 52 | ld r6,STACK_FRAME_OVERHEAD+STK_PARAM(R6)(r1); \ |
| 57 | ld r5,STK_PARAM(R5)(r1); \ | 53 | ld r7,STACK_FRAME_OVERHEAD+STK_PARAM(R7)(r1); \ |
| 58 | ld r6,STK_PARAM(R6)(r1); \ | 54 | ld r8,STACK_FRAME_OVERHEAD+STK_PARAM(R8)(r1); \ |
| 59 | ld r7,STK_PARAM(R7)(r1); \ | 55 | ld r9,STACK_FRAME_OVERHEAD+STK_PARAM(R9)(r1); \ |
| 60 | ld r8,STK_PARAM(R8)(r1); \ | 56 | ld r10,STACK_FRAME_OVERHEAD+STK_PARAM(R10)(r1) |
| 61 | ld r9,STK_PARAM(R9)(r1); \ | ||
| 62 | ld r10,STK_PARAM(R10)(r1); \ | ||
| 63 | mtlr r0; \ | ||
| 64 | 1: | ||
| 65 | 57 | ||
| 66 | /* | 58 | /* |
| 67 | * postcall is performed immediately before function return which | 59 | * postcall is performed immediately before function return which |
| 68 | * allows liberal use of volatile registers. We branch around this | 60 | * allows liberal use of volatile registers. |
| 69 | * in early init (eg when populating the MMU hashtable) by using an | ||
| 70 | * unconditional cpu feature. | ||
| 71 | */ | 61 | */ |
| 72 | #define __HCALL_INST_POSTCALL \ | 62 | #define __HCALL_INST_POSTCALL \ |
| 73 | BEGIN_FTR_SECTION; \ | 63 | ld r0,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1); \ |
| 74 | b 1f; \ | 64 | std r3,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1); \ |
| 75 | END_FTR_SECTION(0, 1); \ | ||
| 76 | ld r12,32(r1); \ | ||
| 77 | cmpdi r12,0; \ | ||
| 78 | beq+ 1f; \ | ||
| 79 | mflr r0; \ | ||
| 80 | ld r6,STK_PARAM(R3)(r1); \ | ||
| 81 | std r3,STK_PARAM(R3)(r1); \ | ||
| 82 | mr r4,r3; \ | 65 | mr r4,r3; \ |
| 83 | mr r3,r6; \ | 66 | mr r3,r0; \ |
| 84 | std r0,16(r1); \ | ||
| 85 | stdu r1,-STACK_FRAME_OVERHEAD(r1); \ | ||
| 86 | bl __trace_hcall_exit; \ | 67 | bl __trace_hcall_exit; \ |
| 68 | ld r0,STACK_FRAME_OVERHEAD+16(r1); \ | ||
| 87 | addi r1,r1,STACK_FRAME_OVERHEAD; \ | 69 | addi r1,r1,STACK_FRAME_OVERHEAD; \ |
| 88 | ld r0,16(r1); \ | ||
| 89 | ld r3,STK_PARAM(R3)(r1); \ | 70 | ld r3,STK_PARAM(R3)(r1); \ |
| 90 | mtlr r0; \ | 71 | mtlr r0 |
| 91 | 1: | ||
| 92 | 72 | ||
| 93 | #define HCALL_INST_POSTCALL_NORETS \ | 73 | #define HCALL_INST_POSTCALL_NORETS \ |
| 94 | li r5,0; \ | 74 | li r5,0; \ |
| @@ -98,37 +78,62 @@ END_FTR_SECTION(0, 1); \ | |||
| 98 | mr r5,BUFREG; \ | 78 | mr r5,BUFREG; \ |
| 99 | __HCALL_INST_POSTCALL | 79 | __HCALL_INST_POSTCALL |
| 100 | 80 | ||
| 81 | #ifdef CONFIG_JUMP_LABEL | ||
| 82 | #define HCALL_BRANCH(LABEL) \ | ||
| 83 | ARCH_STATIC_BRANCH(LABEL, hcall_tracepoint_key) | ||
| 84 | #else | ||
| 85 | |||
| 86 | /* | ||
| 87 | * We branch around this in early init (eg when populating the MMU | ||
| 88 | * hashtable) by using an unconditional cpu feature. | ||
| 89 | */ | ||
| 90 | #define HCALL_BRANCH(LABEL) \ | ||
| 91 | BEGIN_FTR_SECTION; \ | ||
| 92 | b 1f; \ | ||
| 93 | END_FTR_SECTION(0, 1); \ | ||
| 94 | ld r12,hcall_tracepoint_refcount@toc(r2); \ | ||
| 95 | std r12,32(r1); \ | ||
| 96 | cmpdi r12,0; \ | ||
| 97 | bne- LABEL; \ | ||
| 98 | 1: | ||
| 99 | #endif | ||
| 100 | |||
| 101 | #else | 101 | #else |
| 102 | #define HCALL_INST_PRECALL(FIRST_ARG) | 102 | #define HCALL_INST_PRECALL(FIRST_ARG) |
| 103 | #define HCALL_INST_POSTCALL_NORETS | 103 | #define HCALL_INST_POSTCALL_NORETS |
| 104 | #define HCALL_INST_POSTCALL(BUFREG) | 104 | #define HCALL_INST_POSTCALL(BUFREG) |
| 105 | #define HCALL_BRANCH(LABEL) | ||
| 105 | #endif | 106 | #endif |
| 106 | 107 | ||
| 107 | .text | ||
| 108 | |||
| 109 | _GLOBAL_TOC(plpar_hcall_norets) | 108 | _GLOBAL_TOC(plpar_hcall_norets) |
| 110 | HMT_MEDIUM | 109 | HMT_MEDIUM |
| 111 | 110 | ||
| 112 | mfcr r0 | 111 | mfcr r0 |
| 113 | stw r0,8(r1) | 112 | stw r0,8(r1) |
| 114 | 113 | HCALL_BRANCH(plpar_hcall_norets_trace) | |
| 115 | HCALL_INST_PRECALL(R4) | ||
| 116 | |||
| 117 | HVSC /* invoke the hypervisor */ | 114 | HVSC /* invoke the hypervisor */ |
| 118 | 115 | ||
| 119 | HCALL_INST_POSTCALL_NORETS | ||
| 120 | |||
| 121 | lwz r0,8(r1) | 116 | lwz r0,8(r1) |
| 122 | mtcrf 0xff,r0 | 117 | mtcrf 0xff,r0 |
| 123 | blr /* return r3 = status */ | 118 | blr /* return r3 = status */ |
| 124 | 119 | ||
| 120 | #ifdef CONFIG_TRACEPOINTS | ||
| 121 | plpar_hcall_norets_trace: | ||
| 122 | HCALL_INST_PRECALL(R4) | ||
| 123 | HVSC | ||
| 124 | HCALL_INST_POSTCALL_NORETS | ||
| 125 | lwz r0,8(r1) | ||
| 126 | mtcrf 0xff,r0 | ||
| 127 | blr | ||
| 128 | #endif | ||
| 129 | |||
| 125 | _GLOBAL_TOC(plpar_hcall) | 130 | _GLOBAL_TOC(plpar_hcall) |
| 126 | HMT_MEDIUM | 131 | HMT_MEDIUM |
| 127 | 132 | ||
| 128 | mfcr r0 | 133 | mfcr r0 |
| 129 | stw r0,8(r1) | 134 | stw r0,8(r1) |
| 130 | 135 | ||
| 131 | HCALL_INST_PRECALL(R5) | 136 | HCALL_BRANCH(plpar_hcall_trace) |
| 132 | 137 | ||
| 133 | std r4,STK_PARAM(R4)(r1) /* Save ret buffer */ | 138 | std r4,STK_PARAM(R4)(r1) /* Save ret buffer */ |
| 134 | 139 | ||
| @@ -147,12 +152,40 @@ _GLOBAL_TOC(plpar_hcall) | |||
| 147 | std r6, 16(r12) | 152 | std r6, 16(r12) |
| 148 | std r7, 24(r12) | 153 | std r7, 24(r12) |
| 149 | 154 | ||
| 155 | lwz r0,8(r1) | ||
| 156 | mtcrf 0xff,r0 | ||
| 157 | |||
| 158 | blr /* return r3 = status */ | ||
| 159 | |||
| 160 | #ifdef CONFIG_TRACEPOINTS | ||
| 161 | plpar_hcall_trace: | ||
| 162 | HCALL_INST_PRECALL(R5) | ||
| 163 | |||
| 164 | std r4,STK_PARAM(R4)(r1) | ||
| 165 | mr r0,r4 | ||
| 166 | |||
| 167 | mr r4,r5 | ||
| 168 | mr r5,r6 | ||
| 169 | mr r6,r7 | ||
| 170 | mr r7,r8 | ||
| 171 | mr r8,r9 | ||
| 172 | mr r9,r10 | ||
| 173 | |||
| 174 | HVSC | ||
| 175 | |||
| 176 | ld r12,STK_PARAM(R4)(r1) | ||
| 177 | std r4,0(r12) | ||
| 178 | std r5,8(r12) | ||
| 179 | std r6,16(r12) | ||
| 180 | std r7,24(r12) | ||
| 181 | |||
| 150 | HCALL_INST_POSTCALL(r12) | 182 | HCALL_INST_POSTCALL(r12) |
| 151 | 183 | ||
| 152 | lwz r0,8(r1) | 184 | lwz r0,8(r1) |
| 153 | mtcrf 0xff,r0 | 185 | mtcrf 0xff,r0 |
| 154 | 186 | ||
| 155 | blr /* return r3 = status */ | 187 | blr |
| 188 | #endif | ||
| 156 | 189 | ||
| 157 | /* | 190 | /* |
| 158 | * plpar_hcall_raw can be called in real mode. kexec/kdump need some | 191 | * plpar_hcall_raw can be called in real mode. kexec/kdump need some |
| @@ -194,7 +227,7 @@ _GLOBAL_TOC(plpar_hcall9) | |||
| 194 | mfcr r0 | 227 | mfcr r0 |
| 195 | stw r0,8(r1) | 228 | stw r0,8(r1) |
| 196 | 229 | ||
| 197 | HCALL_INST_PRECALL(R5) | 230 | HCALL_BRANCH(plpar_hcall9_trace) |
| 198 | 231 | ||
| 199 | std r4,STK_PARAM(R4)(r1) /* Save ret buffer */ | 232 | std r4,STK_PARAM(R4)(r1) /* Save ret buffer */ |
| 200 | 233 | ||
| @@ -222,12 +255,49 @@ _GLOBAL_TOC(plpar_hcall9) | |||
| 222 | std r11,56(r12) | 255 | std r11,56(r12) |
| 223 | std r0, 64(r12) | 256 | std r0, 64(r12) |
| 224 | 257 | ||
| 258 | lwz r0,8(r1) | ||
| 259 | mtcrf 0xff,r0 | ||
| 260 | |||
| 261 | blr /* return r3 = status */ | ||
| 262 | |||
| 263 | #ifdef CONFIG_TRACEPOINTS | ||
| 264 | plpar_hcall9_trace: | ||
| 265 | HCALL_INST_PRECALL(R5) | ||
| 266 | |||
| 267 | std r4,STK_PARAM(R4)(r1) | ||
| 268 | mr r0,r4 | ||
| 269 | |||
| 270 | mr r4,r5 | ||
| 271 | mr r5,r6 | ||
| 272 | mr r6,r7 | ||
| 273 | mr r7,r8 | ||
| 274 | mr r8,r9 | ||
| 275 | mr r9,r10 | ||
| 276 | ld r10,STACK_FRAME_OVERHEAD+STK_PARAM(R11)(r1) | ||
| 277 | ld r11,STACK_FRAME_OVERHEAD+STK_PARAM(R12)(r1) | ||
| 278 | ld r12,STACK_FRAME_OVERHEAD+STK_PARAM(R13)(r1) | ||
| 279 | |||
| 280 | HVSC | ||
| 281 | |||
| 282 | mr r0,r12 | ||
| 283 | ld r12,STACK_FRAME_OVERHEAD+STK_PARAM(R4)(r1) | ||
| 284 | std r4,0(r12) | ||
| 285 | std r5,8(r12) | ||
| 286 | std r6,16(r12) | ||
| 287 | std r7,24(r12) | ||
| 288 | std r8,32(r12) | ||
| 289 | std r9,40(r12) | ||
| 290 | std r10,48(r12) | ||
| 291 | std r11,56(r12) | ||
| 292 | std r0,64(r12) | ||
| 293 | |||
| 225 | HCALL_INST_POSTCALL(r12) | 294 | HCALL_INST_POSTCALL(r12) |
| 226 | 295 | ||
| 227 | lwz r0,8(r1) | 296 | lwz r0,8(r1) |
| 228 | mtcrf 0xff,r0 | 297 | mtcrf 0xff,r0 |
| 229 | 298 | ||
| 230 | blr /* return r3 = status */ | 299 | blr |
| 300 | #endif | ||
| 231 | 301 | ||
| 232 | /* See plpar_hcall_raw to see why this is needed */ | 302 | /* See plpar_hcall_raw to see why this is needed */ |
| 233 | _GLOBAL(plpar_hcall9_raw) | 303 | _GLOBAL(plpar_hcall9_raw) |
diff --git a/arch/powerpc/platforms/pseries/hvCall_inst.c b/arch/powerpc/platforms/pseries/hvCall_inst.c index cf4e7736e4f1..4575f0c9e521 100644 --- a/arch/powerpc/platforms/pseries/hvCall_inst.c +++ b/arch/powerpc/platforms/pseries/hvCall_inst.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <asm/firmware.h> | 27 | #include <asm/firmware.h> |
| 28 | #include <asm/cputable.h> | 28 | #include <asm/cputable.h> |
| 29 | #include <asm/trace.h> | 29 | #include <asm/trace.h> |
| 30 | #include <asm/machdep.h> | ||
| 30 | 31 | ||
| 31 | DEFINE_PER_CPU(struct hcall_stats[HCALL_STAT_ARRAY_SIZE], hcall_stats); | 32 | DEFINE_PER_CPU(struct hcall_stats[HCALL_STAT_ARRAY_SIZE], hcall_stats); |
| 32 | 33 | ||
| @@ -162,4 +163,4 @@ static int __init hcall_inst_init(void) | |||
| 162 | 163 | ||
| 163 | return 0; | 164 | return 0; |
| 164 | } | 165 | } |
| 165 | __initcall(hcall_inst_init); | 166 | machine_device_initcall(pseries, hcall_inst_init); |
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index b02af9ef3ff6..fbfcef514aa7 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/dma-mapping.h> | 26 | #include <linux/dma-mapping.h> |
| 27 | #include <linux/console.h> | 27 | #include <linux/console.h> |
| 28 | #include <linux/export.h> | 28 | #include <linux/export.h> |
| 29 | #include <linux/static_key.h> | ||
| 29 | #include <asm/processor.h> | 30 | #include <asm/processor.h> |
| 30 | #include <asm/mmu.h> | 31 | #include <asm/mmu.h> |
| 31 | #include <asm/page.h> | 32 | #include <asm/page.h> |
| @@ -649,6 +650,19 @@ EXPORT_SYMBOL(arch_free_page); | |||
| 649 | #endif | 650 | #endif |
| 650 | 651 | ||
| 651 | #ifdef CONFIG_TRACEPOINTS | 652 | #ifdef CONFIG_TRACEPOINTS |
| 653 | #ifdef CONFIG_JUMP_LABEL | ||
| 654 | struct static_key hcall_tracepoint_key = STATIC_KEY_INIT; | ||
| 655 | |||
| 656 | void hcall_tracepoint_regfunc(void) | ||
| 657 | { | ||
| 658 | static_key_slow_inc(&hcall_tracepoint_key); | ||
| 659 | } | ||
| 660 | |||
| 661 | void hcall_tracepoint_unregfunc(void) | ||
| 662 | { | ||
| 663 | static_key_slow_dec(&hcall_tracepoint_key); | ||
| 664 | } | ||
| 665 | #else | ||
| 652 | /* | 666 | /* |
| 653 | * We optimise our hcall path by placing hcall_tracepoint_refcount | 667 | * We optimise our hcall path by placing hcall_tracepoint_refcount |
| 654 | * directly in the TOC so we can check if the hcall tracepoints are | 668 | * directly in the TOC so we can check if the hcall tracepoints are |
| @@ -658,13 +672,6 @@ EXPORT_SYMBOL(arch_free_page); | |||
| 658 | /* NB: reg/unreg are called while guarded with the tracepoints_mutex */ | 672 | /* NB: reg/unreg are called while guarded with the tracepoints_mutex */ |
| 659 | extern long hcall_tracepoint_refcount; | 673 | extern long hcall_tracepoint_refcount; |
| 660 | 674 | ||
| 661 | /* | ||
| 662 | * Since the tracing code might execute hcalls we need to guard against | ||
| 663 | * recursion. One example of this are spinlocks calling H_YIELD on | ||
| 664 | * shared processor partitions. | ||
| 665 | */ | ||
| 666 | static DEFINE_PER_CPU(unsigned int, hcall_trace_depth); | ||
| 667 | |||
| 668 | void hcall_tracepoint_regfunc(void) | 675 | void hcall_tracepoint_regfunc(void) |
| 669 | { | 676 | { |
| 670 | hcall_tracepoint_refcount++; | 677 | hcall_tracepoint_refcount++; |
| @@ -674,6 +681,15 @@ void hcall_tracepoint_unregfunc(void) | |||
| 674 | { | 681 | { |
| 675 | hcall_tracepoint_refcount--; | 682 | hcall_tracepoint_refcount--; |
| 676 | } | 683 | } |
| 684 | #endif | ||
| 685 | |||
| 686 | /* | ||
| 687 | * Since the tracing code might execute hcalls we need to guard against | ||
| 688 | * recursion. One example of this are spinlocks calling H_YIELD on | ||
| 689 | * shared processor partitions. | ||
| 690 | */ | ||
| 691 | static DEFINE_PER_CPU(unsigned int, hcall_trace_depth); | ||
| 692 | |||
| 677 | 693 | ||
| 678 | void __trace_hcall_entry(unsigned long opcode, unsigned long *args) | 694 | void __trace_hcall_entry(unsigned long opcode, unsigned long *args) |
| 679 | { | 695 | { |
diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c index bde7ebad3949..d146fef038b8 100644 --- a/arch/powerpc/platforms/pseries/mobility.c +++ b/arch/powerpc/platforms/pseries/mobility.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
| 19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
| 20 | 20 | ||
| 21 | #include <asm/machdep.h> | ||
| 21 | #include <asm/rtas.h> | 22 | #include <asm/rtas.h> |
| 22 | #include "pseries.h" | 23 | #include "pseries.h" |
| 23 | 24 | ||
| @@ -362,4 +363,4 @@ static int __init mobility_sysfs_init(void) | |||
| 362 | 363 | ||
| 363 | return rc; | 364 | return rc; |
| 364 | } | 365 | } |
| 365 | device_initcall(mobility_sysfs_init); | 366 | machine_device_initcall(pseries, mobility_sysfs_init); |
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c index 0c882e83c4ce..18ff4626d74e 100644 --- a/arch/powerpc/platforms/pseries/msi.c +++ b/arch/powerpc/platforms/pseries/msi.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <asm/rtas.h> | 16 | #include <asm/rtas.h> |
| 17 | #include <asm/hw_irq.h> | 17 | #include <asm/hw_irq.h> |
| 18 | #include <asm/ppc-pci.h> | 18 | #include <asm/ppc-pci.h> |
| 19 | #include <asm/machdep.h> | ||
| 19 | 20 | ||
| 20 | static int query_token, change_token; | 21 | static int query_token, change_token; |
| 21 | 22 | ||
| @@ -532,5 +533,4 @@ static int rtas_msi_init(void) | |||
| 532 | 533 | ||
| 533 | return 0; | 534 | return 0; |
| 534 | } | 535 | } |
| 535 | arch_initcall(rtas_msi_init); | 536 | machine_arch_initcall(pseries, rtas_msi_init); |
| 536 | |||
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index 203cbf0dc101..89e23811199c 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c | |||
| @@ -118,10 +118,10 @@ int remove_phb_dynamic(struct pci_controller *phb) | |||
| 118 | } | 118 | } |
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | /* Unregister the bridge device from sysfs and remove the PCI bus */ | 121 | /* Remove the PCI bus and unregister the bridge device from sysfs */ |
| 122 | device_unregister(b->bridge); | ||
| 123 | phb->bus = NULL; | 122 | phb->bus = NULL; |
| 124 | pci_remove_bus(b); | 123 | pci_remove_bus(b); |
| 124 | device_unregister(b->bridge); | ||
| 125 | 125 | ||
| 126 | /* Now release the IO resource */ | 126 | /* Now release the IO resource */ |
| 127 | if (res->flags & IORESOURCE_IO) | 127 | if (res->flags & IORESOURCE_IO) |
diff --git a/arch/powerpc/platforms/pseries/power.c b/arch/powerpc/platforms/pseries/power.c index 6d6266236446..c26eadde434c 100644 --- a/arch/powerpc/platforms/pseries/power.c +++ b/arch/powerpc/platforms/pseries/power.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <linux/string.h> | 25 | #include <linux/string.h> |
| 26 | #include <linux/errno.h> | 26 | #include <linux/errno.h> |
| 27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
| 28 | #include <asm/machdep.h> | ||
| 28 | 29 | ||
| 29 | unsigned long rtas_poweron_auto; /* default and normal state is 0 */ | 30 | unsigned long rtas_poweron_auto; /* default and normal state is 0 */ |
| 30 | 31 | ||
| @@ -71,11 +72,11 @@ static int __init pm_init(void) | |||
| 71 | return -ENOMEM; | 72 | return -ENOMEM; |
| 72 | return sysfs_create_group(power_kobj, &attr_group); | 73 | return sysfs_create_group(power_kobj, &attr_group); |
| 73 | } | 74 | } |
| 74 | core_initcall(pm_init); | 75 | machine_core_initcall(pseries, pm_init); |
| 75 | #else | 76 | #else |
| 76 | static int __init apo_pm_init(void) | 77 | static int __init apo_pm_init(void) |
| 77 | { | 78 | { |
| 78 | return (sysfs_create_file(power_kobj, &auto_poweron_attr.attr)); | 79 | return (sysfs_create_file(power_kobj, &auto_poweron_attr.attr)); |
| 79 | } | 80 | } |
| 80 | __initcall(apo_pm_init); | 81 | machine_device_initcall(pseries, apo_pm_init); |
| 81 | #endif | 82 | #endif |
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c index 9c5778e6ed4b..dff05b9eb946 100644 --- a/arch/powerpc/platforms/pseries/ras.c +++ b/arch/powerpc/platforms/pseries/ras.c | |||
| @@ -71,7 +71,7 @@ static int __init init_ras_IRQ(void) | |||
| 71 | 71 | ||
| 72 | return 0; | 72 | return 0; |
| 73 | } | 73 | } |
| 74 | subsys_initcall(init_ras_IRQ); | 74 | machine_subsys_initcall(pseries, init_ras_IRQ); |
| 75 | 75 | ||
| 76 | #define EPOW_SHUTDOWN_NORMAL 1 | 76 | #define EPOW_SHUTDOWN_NORMAL 1 |
| 77 | #define EPOW_SHUTDOWN_ON_UPS 2 | 77 | #define EPOW_SHUTDOWN_ON_UPS 2 |
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 1c0a60d98867..0f319521e002 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c | |||
| @@ -446,13 +446,10 @@ static int proc_ppc64_create_ofdt(void) | |||
| 446 | { | 446 | { |
| 447 | struct proc_dir_entry *ent; | 447 | struct proc_dir_entry *ent; |
| 448 | 448 | ||
| 449 | if (!machine_is(pseries)) | ||
| 450 | return 0; | ||
| 451 | |||
| 452 | ent = proc_create("powerpc/ofdt", S_IWUSR, NULL, &ofdt_fops); | 449 | ent = proc_create("powerpc/ofdt", S_IWUSR, NULL, &ofdt_fops); |
| 453 | if (ent) | 450 | if (ent) |
| 454 | proc_set_size(ent, 0); | 451 | proc_set_size(ent, 0); |
| 455 | 452 | ||
| 456 | return 0; | 453 | return 0; |
| 457 | } | 454 | } |
| 458 | __initcall(proc_ppc64_create_ofdt); | 455 | machine_device_initcall(pseries, proc_ppc64_create_ofdt); |
diff --git a/arch/powerpc/platforms/pseries/rng.c b/arch/powerpc/platforms/pseries/rng.c index 72a102758d4e..e09608770909 100644 --- a/arch/powerpc/platforms/pseries/rng.c +++ b/arch/powerpc/platforms/pseries/rng.c | |||
| @@ -42,4 +42,4 @@ static __init int rng_init(void) | |||
| 42 | 42 | ||
| 43 | return 0; | 43 | return 0; |
| 44 | } | 44 | } |
| 45 | subsys_initcall(rng_init); | 45 | machine_subsys_initcall(pseries, rng_init); |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index f2f40e64658f..cfe8a6389a51 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
| @@ -351,7 +351,7 @@ static int alloc_dispatch_log_kmem_cache(void) | |||
| 351 | 351 | ||
| 352 | return alloc_dispatch_logs(); | 352 | return alloc_dispatch_logs(); |
| 353 | } | 353 | } |
| 354 | early_initcall(alloc_dispatch_log_kmem_cache); | 354 | machine_early_initcall(pseries, alloc_dispatch_log_kmem_cache); |
| 355 | 355 | ||
| 356 | static void pseries_lpar_idle(void) | 356 | static void pseries_lpar_idle(void) |
| 357 | { | 357 | { |
diff --git a/arch/powerpc/platforms/pseries/suspend.c b/arch/powerpc/platforms/pseries/suspend.c index b87b97849d4c..e76aefae2aa2 100644 --- a/arch/powerpc/platforms/pseries/suspend.c +++ b/arch/powerpc/platforms/pseries/suspend.c | |||
| @@ -265,7 +265,7 @@ static int __init pseries_suspend_init(void) | |||
| 265 | { | 265 | { |
| 266 | int rc; | 266 | int rc; |
| 267 | 267 | ||
| 268 | if (!machine_is(pseries) || !firmware_has_feature(FW_FEATURE_LPAR)) | 268 | if (!firmware_has_feature(FW_FEATURE_LPAR)) |
| 269 | return 0; | 269 | return 0; |
| 270 | 270 | ||
| 271 | suspend_data.token = rtas_token("ibm,suspend-me"); | 271 | suspend_data.token = rtas_token("ibm,suspend-me"); |
| @@ -280,5 +280,4 @@ static int __init pseries_suspend_init(void) | |||
| 280 | suspend_set_ops(&pseries_suspend_ops); | 280 | suspend_set_ops(&pseries_suspend_ops); |
| 281 | return 0; | 281 | return 0; |
| 282 | } | 282 | } |
| 283 | 283 | machine_device_initcall(pseries, pseries_suspend_init); | |
| 284 | __initcall(pseries_suspend_init); | ||
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 4bd091a05583..c5077673bd94 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c | |||
| @@ -853,8 +853,8 @@ u64 fsl_pci_immrbar_base(struct pci_controller *hose) | |||
| 853 | in = pcie->cfg_type0 + PEX_RC_INWIN_BASE; | 853 | in = pcie->cfg_type0 + PEX_RC_INWIN_BASE; |
| 854 | for (i = 0; i < 4; i++) { | 854 | for (i = 0; i < 4; i++) { |
| 855 | /* not enabled, skip */ | 855 | /* not enabled, skip */ |
| 856 | if (!in_le32(&in[i].ar) & PEX_RCIWARn_EN) | 856 | if (!(in_le32(&in[i].ar) & PEX_RCIWARn_EN)) |
| 857 | continue; | 857 | continue; |
| 858 | 858 | ||
| 859 | if (get_immrbase() == in_le32(&in[i].tar)) | 859 | if (get_immrbase() == in_le32(&in[i].tar)) |
| 860 | return (u64)in_le32(&in[i].barh) << 32 | | 860 | return (u64)in_le32(&in[i].barh) << 32 | |
diff --git a/arch/powerpc/sysdev/micropatch.c b/arch/powerpc/sysdev/micropatch.c index c0bb76ef7242..6727dc54d549 100644 --- a/arch/powerpc/sysdev/micropatch.c +++ b/arch/powerpc/sysdev/micropatch.c | |||
| @@ -13,7 +13,6 @@ | |||
| 13 | #include <linux/mm.h> | 13 | #include <linux/mm.h> |
| 14 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
| 15 | #include <asm/irq.h> | 15 | #include <asm/irq.h> |
| 16 | #include <asm/mpc8xx.h> | ||
| 17 | #include <asm/page.h> | 16 | #include <asm/page.h> |
| 18 | #include <asm/pgtable.h> | 17 | #include <asm/pgtable.h> |
| 19 | #include <asm/8xx_immap.h> | 18 | #include <asm/8xx_immap.h> |
diff --git a/arch/powerpc/sysdev/mpic_msgr.c b/arch/powerpc/sysdev/mpic_msgr.c index 2c9b52aa266c..7bdf3cc741e4 100644 --- a/arch/powerpc/sysdev/mpic_msgr.c +++ b/arch/powerpc/sysdev/mpic_msgr.c | |||
| @@ -184,7 +184,7 @@ static int mpic_msgr_probe(struct platform_device *dev) | |||
| 184 | dev_info(&dev->dev, "Found %d message registers\n", | 184 | dev_info(&dev->dev, "Found %d message registers\n", |
| 185 | mpic_msgr_count); | 185 | mpic_msgr_count); |
| 186 | 186 | ||
| 187 | mpic_msgrs = kzalloc(sizeof(struct mpic_msgr) * mpic_msgr_count, | 187 | mpic_msgrs = kcalloc(mpic_msgr_count, sizeof(*mpic_msgrs), |
| 188 | GFP_KERNEL); | 188 | GFP_KERNEL); |
| 189 | if (!mpic_msgrs) { | 189 | if (!mpic_msgrs) { |
| 190 | dev_err(&dev->dev, | 190 | dev_err(&dev->dev, |
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index d199bfa2f1fa..8d198b5e9e0a 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c | |||
| @@ -2058,10 +2058,6 @@ static void dump_one_paca(int cpu) | |||
| 2058 | DUMP(p, kernel_toc, "lx"); | 2058 | DUMP(p, kernel_toc, "lx"); |
| 2059 | DUMP(p, kernelbase, "lx"); | 2059 | DUMP(p, kernelbase, "lx"); |
| 2060 | DUMP(p, kernel_msr, "lx"); | 2060 | DUMP(p, kernel_msr, "lx"); |
| 2061 | #ifdef CONFIG_PPC_STD_MMU_64 | ||
| 2062 | DUMP(p, stab_real, "lx"); | ||
| 2063 | DUMP(p, stab_addr, "lx"); | ||
| 2064 | #endif | ||
| 2065 | DUMP(p, emergency_sp, "p"); | 2061 | DUMP(p, emergency_sp, "p"); |
| 2066 | #ifdef CONFIG_PPC_BOOK3S_64 | 2062 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 2067 | DUMP(p, mc_emergency_sp, "p"); | 2063 | DUMP(p, mc_emergency_sp, "p"); |
| @@ -2694,7 +2690,7 @@ static void xmon_print_symbol(unsigned long address, const char *mid, | |||
| 2694 | } | 2690 | } |
| 2695 | 2691 | ||
| 2696 | #ifdef CONFIG_PPC_BOOK3S_64 | 2692 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 2697 | static void dump_slb(void) | 2693 | void dump_segments(void) |
| 2698 | { | 2694 | { |
| 2699 | int i; | 2695 | int i; |
| 2700 | unsigned long esid,vsid,valid; | 2696 | unsigned long esid,vsid,valid; |
| @@ -2726,34 +2722,6 @@ static void dump_slb(void) | |||
| 2726 | } | 2722 | } |
| 2727 | } | 2723 | } |
| 2728 | } | 2724 | } |
| 2729 | |||
| 2730 | static void dump_stab(void) | ||
| 2731 | { | ||
| 2732 | int i; | ||
| 2733 | unsigned long *tmp = (unsigned long *)local_paca->stab_addr; | ||
| 2734 | |||
| 2735 | printf("Segment table contents of cpu 0x%x\n", smp_processor_id()); | ||
| 2736 | |||
| 2737 | for (i = 0; i < PAGE_SIZE/16; i++) { | ||
| 2738 | unsigned long a, b; | ||
| 2739 | |||
| 2740 | a = *tmp++; | ||
| 2741 | b = *tmp++; | ||
| 2742 | |||
| 2743 | if (a || b) { | ||
| 2744 | printf("%03d %016lx ", i, a); | ||
| 2745 | printf("%016lx\n", b); | ||
| 2746 | } | ||
| 2747 | } | ||
| 2748 | } | ||
| 2749 | |||
| 2750 | void dump_segments(void) | ||
| 2751 | { | ||
| 2752 | if (mmu_has_feature(MMU_FTR_SLB)) | ||
| 2753 | dump_slb(); | ||
| 2754 | else | ||
| 2755 | dump_stab(); | ||
| 2756 | } | ||
| 2757 | #endif | 2725 | #endif |
| 2758 | 2726 | ||
| 2759 | #ifdef CONFIG_PPC_STD_MMU_32 | 2727 | #ifdef CONFIG_PPC_STD_MMU_32 |
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index bb1d08dc8cc8..379c0837f5a9 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <linux/of.h> | 28 | #include <linux/of.h> |
| 29 | 29 | ||
| 30 | #include <asm/cputhreads.h> | 30 | #include <asm/cputhreads.h> |
| 31 | #include <asm/firmware.h> | ||
| 31 | #include <asm/reg.h> | 32 | #include <asm/reg.h> |
| 32 | #include <asm/smp.h> /* Required for cpu_sibling_mask() in UP configs */ | 33 | #include <asm/smp.h> /* Required for cpu_sibling_mask() in UP configs */ |
| 33 | 34 | ||
| @@ -98,7 +99,11 @@ static int init_powernv_pstates(void) | |||
| 98 | return -ENODEV; | 99 | return -ENODEV; |
| 99 | } | 100 | } |
| 100 | 101 | ||
| 101 | WARN_ON(len_ids != len_freqs); | 102 | if (len_ids != len_freqs) { |
| 103 | pr_warn("Entries in ibm,pstate-ids and " | ||
| 104 | "ibm,pstate-frequencies-mhz does not match\n"); | ||
| 105 | } | ||
| 106 | |||
| 102 | nr_pstates = min(len_ids, len_freqs) / sizeof(u32); | 107 | nr_pstates = min(len_ids, len_freqs) / sizeof(u32); |
| 103 | if (!nr_pstates) { | 108 | if (!nr_pstates) { |
| 104 | pr_warn("No PStates found\n"); | 109 | pr_warn("No PStates found\n"); |
| @@ -131,7 +136,12 @@ static unsigned int pstate_id_to_freq(int pstate_id) | |||
| 131 | int i; | 136 | int i; |
| 132 | 137 | ||
| 133 | i = powernv_pstate_info.max - pstate_id; | 138 | i = powernv_pstate_info.max - pstate_id; |
| 134 | BUG_ON(i >= powernv_pstate_info.nr_pstates || i < 0); | 139 | if (i >= powernv_pstate_info.nr_pstates || i < 0) { |
| 140 | pr_warn("PState id %d outside of PState table, " | ||
| 141 | "reporting nominal id %d instead\n", | ||
| 142 | pstate_id, powernv_pstate_info.nominal); | ||
| 143 | i = powernv_pstate_info.max - powernv_pstate_info.nominal; | ||
| 144 | } | ||
| 135 | 145 | ||
| 136 | return powernv_freqs[i].frequency; | 146 | return powernv_freqs[i].frequency; |
| 137 | } | 147 | } |
| @@ -321,6 +331,10 @@ static int __init powernv_cpufreq_init(void) | |||
| 321 | { | 331 | { |
| 322 | int rc = 0; | 332 | int rc = 0; |
| 323 | 333 | ||
| 334 | /* Don't probe on pseries (guest) platforms */ | ||
| 335 | if (!firmware_has_feature(FW_FEATURE_OPALv3)) | ||
| 336 | return -ENODEV; | ||
| 337 | |||
| 324 | /* Discover pstates from device tree and init */ | 338 | /* Discover pstates from device tree and init */ |
| 325 | rc = init_powernv_pstates(); | 339 | rc = init_powernv_pstates(); |
| 326 | if (rc) { | 340 | if (rc) { |
diff --git a/drivers/cpuidle/cpuidle-powernv.c b/drivers/cpuidle/cpuidle-powernv.c index 74f5788d50b1..a64be578dab2 100644 --- a/drivers/cpuidle/cpuidle-powernv.c +++ b/drivers/cpuidle/cpuidle-powernv.c | |||
| @@ -160,10 +160,10 @@ static int powernv_cpuidle_driver_init(void) | |||
| 160 | static int powernv_add_idle_states(void) | 160 | static int powernv_add_idle_states(void) |
| 161 | { | 161 | { |
| 162 | struct device_node *power_mgt; | 162 | struct device_node *power_mgt; |
| 163 | struct property *prop; | ||
| 164 | int nr_idle_states = 1; /* Snooze */ | 163 | int nr_idle_states = 1; /* Snooze */ |
| 165 | int dt_idle_states; | 164 | int dt_idle_states; |
| 166 | u32 *flags; | 165 | const __be32 *idle_state_flags; |
| 166 | u32 len_flags, flags; | ||
| 167 | int i; | 167 | int i; |
| 168 | 168 | ||
| 169 | /* Currently we have snooze statically defined */ | 169 | /* Currently we have snooze statically defined */ |
| @@ -174,18 +174,18 @@ static int powernv_add_idle_states(void) | |||
| 174 | return nr_idle_states; | 174 | return nr_idle_states; |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | prop = of_find_property(power_mgt, "ibm,cpu-idle-state-flags", NULL); | 177 | idle_state_flags = of_get_property(power_mgt, "ibm,cpu-idle-state-flags", &len_flags); |
| 178 | if (!prop) { | 178 | if (!idle_state_flags) { |
| 179 | pr_warn("DT-PowerMgmt: missing ibm,cpu-idle-state-flags\n"); | 179 | pr_warn("DT-PowerMgmt: missing ibm,cpu-idle-state-flags\n"); |
| 180 | return nr_idle_states; | 180 | return nr_idle_states; |
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | dt_idle_states = prop->length / sizeof(u32); | 183 | dt_idle_states = len_flags / sizeof(u32); |
| 184 | flags = (u32 *) prop->value; | ||
| 185 | 184 | ||
| 186 | for (i = 0; i < dt_idle_states; i++) { | 185 | for (i = 0; i < dt_idle_states; i++) { |
| 187 | 186 | ||
| 188 | if (flags[i] & IDLE_USE_INST_NAP) { | 187 | flags = be32_to_cpu(idle_state_flags[i]); |
| 188 | if (flags & IDLE_USE_INST_NAP) { | ||
| 189 | /* Add NAP state */ | 189 | /* Add NAP state */ |
| 190 | strcpy(powernv_states[nr_idle_states].name, "Nap"); | 190 | strcpy(powernv_states[nr_idle_states].name, "Nap"); |
| 191 | strcpy(powernv_states[nr_idle_states].desc, "Nap"); | 191 | strcpy(powernv_states[nr_idle_states].desc, "Nap"); |
| @@ -196,7 +196,7 @@ static int powernv_add_idle_states(void) | |||
| 196 | nr_idle_states++; | 196 | nr_idle_states++; |
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | if (flags[i] & IDLE_USE_INST_SLEEP) { | 199 | if (flags & IDLE_USE_INST_SLEEP) { |
| 200 | /* Add FASTSLEEP state */ | 200 | /* Add FASTSLEEP state */ |
| 201 | strcpy(powernv_states[nr_idle_states].name, "FastSleep"); | 201 | strcpy(powernv_states[nr_idle_states].name, "FastSleep"); |
| 202 | strcpy(powernv_states[nr_idle_states].desc, "FastSleep"); | 202 | strcpy(powernv_states[nr_idle_states].desc, "FastSleep"); |
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig index c59e9c96e86d..fab81a143bd7 100644 --- a/drivers/memory/Kconfig +++ b/drivers/memory/Kconfig | |||
| @@ -61,6 +61,16 @@ config TEGRA30_MC | |||
| 61 | analysis, especially for IOMMU/SMMU(System Memory Management | 61 | analysis, especially for IOMMU/SMMU(System Memory Management |
| 62 | Unit) module. | 62 | Unit) module. |
| 63 | 63 | ||
| 64 | config FSL_CORENET_CF | ||
| 65 | tristate "Freescale CoreNet Error Reporting" | ||
| 66 | depends on FSL_SOC_BOOKE | ||
| 67 | help | ||
| 68 | Say Y for reporting of errors from the Freescale CoreNet | ||
| 69 | Coherency Fabric. Errors reported include accesses to | ||
| 70 | physical addresses that mapped by no local access window | ||
| 71 | (LAW) or an invalid LAW, as well as bad cache state that | ||
| 72 | represents a coherency violation. | ||
| 73 | |||
| 64 | config FSL_IFC | 74 | config FSL_IFC |
| 65 | bool | 75 | bool |
| 66 | depends on FSL_SOC | 76 | depends on FSL_SOC |
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile index 71160a2b7313..4055c47f45ab 100644 --- a/drivers/memory/Makefile +++ b/drivers/memory/Makefile | |||
| @@ -7,6 +7,7 @@ obj-$(CONFIG_OF) += of_memory.o | |||
| 7 | endif | 7 | endif |
| 8 | obj-$(CONFIG_TI_AEMIF) += ti-aemif.o | 8 | obj-$(CONFIG_TI_AEMIF) += ti-aemif.o |
| 9 | obj-$(CONFIG_TI_EMIF) += emif.o | 9 | obj-$(CONFIG_TI_EMIF) += emif.o |
| 10 | obj-$(CONFIG_FSL_CORENET_CF) += fsl-corenet-cf.o | ||
| 10 | obj-$(CONFIG_FSL_IFC) += fsl_ifc.o | 11 | obj-$(CONFIG_FSL_IFC) += fsl_ifc.o |
| 11 | obj-$(CONFIG_MVEBU_DEVBUS) += mvebu-devbus.o | 12 | obj-$(CONFIG_MVEBU_DEVBUS) += mvebu-devbus.o |
| 12 | obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o | 13 | obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o |
diff --git a/drivers/memory/fsl-corenet-cf.c b/drivers/memory/fsl-corenet-cf.c new file mode 100644 index 000000000000..c9443fc136db --- /dev/null +++ b/drivers/memory/fsl-corenet-cf.c | |||
| @@ -0,0 +1,251 @@ | |||
| 1 | /* | ||
| 2 | * CoreNet Coherency Fabric error reporting | ||
| 3 | * | ||
| 4 | * Copyright 2014 Freescale Semiconductor Inc. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License as published by the | ||
| 8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 9 | * option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/interrupt.h> | ||
| 13 | #include <linux/io.h> | ||
| 14 | #include <linux/irq.h> | ||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/of.h> | ||
| 17 | #include <linux/of_address.h> | ||
| 18 | #include <linux/of_device.h> | ||
| 19 | #include <linux/of_irq.h> | ||
| 20 | #include <linux/platform_device.h> | ||
| 21 | |||
| 22 | enum ccf_version { | ||
| 23 | CCF1, | ||
| 24 | CCF2, | ||
| 25 | }; | ||
| 26 | |||
| 27 | struct ccf_info { | ||
| 28 | enum ccf_version version; | ||
| 29 | int err_reg_offs; | ||
| 30 | }; | ||
| 31 | |||
| 32 | static const struct ccf_info ccf1_info = { | ||
| 33 | .version = CCF1, | ||
| 34 | .err_reg_offs = 0xa00, | ||
| 35 | }; | ||
| 36 | |||
| 37 | static const struct ccf_info ccf2_info = { | ||
| 38 | .version = CCF2, | ||
| 39 | .err_reg_offs = 0xe40, | ||
| 40 | }; | ||
| 41 | |||
| 42 | static const struct of_device_id ccf_matches[] = { | ||
| 43 | { | ||
| 44 | .compatible = "fsl,corenet1-cf", | ||
| 45 | .data = &ccf1_info, | ||
| 46 | }, | ||
| 47 | { | ||
| 48 | .compatible = "fsl,corenet2-cf", | ||
| 49 | .data = &ccf2_info, | ||
| 50 | }, | ||
| 51 | {} | ||
| 52 | }; | ||
| 53 | |||
| 54 | struct ccf_err_regs { | ||
| 55 | u32 errdet; /* 0x00 Error Detect Register */ | ||
| 56 | /* 0x04 Error Enable (ccf1)/Disable (ccf2) Register */ | ||
| 57 | u32 errdis; | ||
| 58 | /* 0x08 Error Interrupt Enable Register (ccf2 only) */ | ||
| 59 | u32 errinten; | ||
| 60 | u32 cecar; /* 0x0c Error Capture Attribute Register */ | ||
| 61 | u32 cecaddrh; /* 0x10 Error Capture Address High */ | ||
| 62 | u32 cecaddrl; /* 0x14 Error Capture Address Low */ | ||
| 63 | u32 cecar2; /* 0x18 Error Capture Attribute Register 2 */ | ||
| 64 | }; | ||
| 65 | |||
| 66 | /* LAE/CV also valid for errdis and errinten */ | ||
| 67 | #define ERRDET_LAE (1 << 0) /* Local Access Error */ | ||
| 68 | #define ERRDET_CV (1 << 1) /* Coherency Violation */ | ||
| 69 | #define ERRDET_CTYPE_SHIFT 26 /* Capture Type (ccf2 only) */ | ||
| 70 | #define ERRDET_CTYPE_MASK (0x1f << ERRDET_CTYPE_SHIFT) | ||
| 71 | #define ERRDET_CAP (1 << 31) /* Capture Valid (ccf2 only) */ | ||
| 72 | |||
| 73 | #define CECAR_VAL (1 << 0) /* Valid (ccf1 only) */ | ||
| 74 | #define CECAR_UVT (1 << 15) /* Unavailable target ID (ccf1) */ | ||
| 75 | #define CECAR_SRCID_SHIFT_CCF1 24 | ||
| 76 | #define CECAR_SRCID_MASK_CCF1 (0xff << CECAR_SRCID_SHIFT_CCF1) | ||
| 77 | #define CECAR_SRCID_SHIFT_CCF2 18 | ||
| 78 | #define CECAR_SRCID_MASK_CCF2 (0xff << CECAR_SRCID_SHIFT_CCF2) | ||
| 79 | |||
| 80 | #define CECADDRH_ADDRH 0xff | ||
| 81 | |||
| 82 | struct ccf_private { | ||
| 83 | const struct ccf_info *info; | ||
| 84 | struct device *dev; | ||
| 85 | void __iomem *regs; | ||
| 86 | struct ccf_err_regs __iomem *err_regs; | ||
| 87 | }; | ||
| 88 | |||
| 89 | static irqreturn_t ccf_irq(int irq, void *dev_id) | ||
| 90 | { | ||
| 91 | struct ccf_private *ccf = dev_id; | ||
| 92 | static DEFINE_RATELIMIT_STATE(ratelimit, DEFAULT_RATELIMIT_INTERVAL, | ||
| 93 | DEFAULT_RATELIMIT_BURST); | ||
| 94 | u32 errdet, cecar, cecar2; | ||
| 95 | u64 addr; | ||
| 96 | u32 src_id; | ||
| 97 | bool uvt = false; | ||
| 98 | bool cap_valid = false; | ||
| 99 | |||
| 100 | errdet = ioread32be(&ccf->err_regs->errdet); | ||
| 101 | cecar = ioread32be(&ccf->err_regs->cecar); | ||
| 102 | cecar2 = ioread32be(&ccf->err_regs->cecar2); | ||
| 103 | addr = ioread32be(&ccf->err_regs->cecaddrl); | ||
| 104 | addr |= ((u64)(ioread32be(&ccf->err_regs->cecaddrh) & | ||
| 105 | CECADDRH_ADDRH)) << 32; | ||
| 106 | |||
| 107 | if (!__ratelimit(&ratelimit)) | ||
| 108 | goto out; | ||
| 109 | |||
| 110 | switch (ccf->info->version) { | ||
| 111 | case CCF1: | ||
| 112 | if (cecar & CECAR_VAL) { | ||
| 113 | if (cecar & CECAR_UVT) | ||
| 114 | uvt = true; | ||
| 115 | |||
| 116 | src_id = (cecar & CECAR_SRCID_MASK_CCF1) >> | ||
| 117 | CECAR_SRCID_SHIFT_CCF1; | ||
| 118 | cap_valid = true; | ||
| 119 | } | ||
| 120 | |||
| 121 | break; | ||
| 122 | case CCF2: | ||
| 123 | if (errdet & ERRDET_CAP) { | ||
| 124 | src_id = (cecar & CECAR_SRCID_MASK_CCF2) >> | ||
| 125 | CECAR_SRCID_SHIFT_CCF2; | ||
| 126 | cap_valid = true; | ||
| 127 | } | ||
| 128 | |||
| 129 | break; | ||
| 130 | } | ||
| 131 | |||
| 132 | dev_crit(ccf->dev, "errdet 0x%08x cecar 0x%08x cecar2 0x%08x\n", | ||
| 133 | errdet, cecar, cecar2); | ||
| 134 | |||
| 135 | if (errdet & ERRDET_LAE) { | ||
| 136 | if (uvt) | ||
| 137 | dev_crit(ccf->dev, "LAW Unavailable Target ID\n"); | ||
| 138 | else | ||
| 139 | dev_crit(ccf->dev, "Local Access Window Error\n"); | ||
| 140 | } | ||
| 141 | |||
| 142 | if (errdet & ERRDET_CV) | ||
| 143 | dev_crit(ccf->dev, "Coherency Violation\n"); | ||
| 144 | |||
| 145 | if (cap_valid) { | ||
| 146 | dev_crit(ccf->dev, "address 0x%09llx, src id 0x%x\n", | ||
| 147 | addr, src_id); | ||
| 148 | } | ||
| 149 | |||
| 150 | out: | ||
| 151 | iowrite32be(errdet, &ccf->err_regs->errdet); | ||
| 152 | return errdet ? IRQ_HANDLED : IRQ_NONE; | ||
| 153 | } | ||
| 154 | |||
| 155 | static int ccf_probe(struct platform_device *pdev) | ||
| 156 | { | ||
| 157 | struct ccf_private *ccf; | ||
| 158 | struct resource *r; | ||
| 159 | const struct of_device_id *match; | ||
| 160 | int ret, irq; | ||
| 161 | |||
| 162 | match = of_match_device(ccf_matches, &pdev->dev); | ||
| 163 | if (WARN_ON(!match)) | ||
| 164 | return -ENODEV; | ||
| 165 | |||
| 166 | ccf = devm_kzalloc(&pdev->dev, sizeof(*ccf), GFP_KERNEL); | ||
| 167 | if (!ccf) | ||
| 168 | return -ENOMEM; | ||
| 169 | |||
| 170 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 171 | if (!r) { | ||
| 172 | dev_err(&pdev->dev, "%s: no mem resource\n", __func__); | ||
| 173 | return -ENXIO; | ||
| 174 | } | ||
| 175 | |||
| 176 | ccf->regs = devm_ioremap_resource(&pdev->dev, r); | ||
| 177 | if (IS_ERR(ccf->regs)) { | ||
| 178 | dev_err(&pdev->dev, "%s: can't map mem resource\n", __func__); | ||
| 179 | return PTR_ERR(ccf->regs); | ||
| 180 | } | ||
| 181 | |||
| 182 | ccf->dev = &pdev->dev; | ||
| 183 | ccf->info = match->data; | ||
| 184 | ccf->err_regs = ccf->regs + ccf->info->err_reg_offs; | ||
| 185 | |||
| 186 | dev_set_drvdata(&pdev->dev, ccf); | ||
| 187 | |||
| 188 | irq = platform_get_irq(pdev, 0); | ||
| 189 | if (!irq) { | ||
| 190 | dev_err(&pdev->dev, "%s: no irq\n", __func__); | ||
| 191 | return -ENXIO; | ||
| 192 | } | ||
| 193 | |||
| 194 | ret = devm_request_irq(&pdev->dev, irq, ccf_irq, 0, pdev->name, ccf); | ||
| 195 | if (ret) { | ||
| 196 | dev_err(&pdev->dev, "%s: can't request irq\n", __func__); | ||
| 197 | return ret; | ||
| 198 | } | ||
| 199 | |||
| 200 | switch (ccf->info->version) { | ||
| 201 | case CCF1: | ||
| 202 | /* On CCF1 this register enables rather than disables. */ | ||
| 203 | iowrite32be(ERRDET_LAE | ERRDET_CV, &ccf->err_regs->errdis); | ||
| 204 | break; | ||
| 205 | |||
| 206 | case CCF2: | ||
| 207 | iowrite32be(0, &ccf->err_regs->errdis); | ||
| 208 | iowrite32be(ERRDET_LAE | ERRDET_CV, &ccf->err_regs->errinten); | ||
| 209 | break; | ||
| 210 | } | ||
| 211 | |||
| 212 | return 0; | ||
| 213 | } | ||
| 214 | |||
| 215 | static int ccf_remove(struct platform_device *pdev) | ||
| 216 | { | ||
| 217 | struct ccf_private *ccf = dev_get_drvdata(&pdev->dev); | ||
| 218 | |||
| 219 | switch (ccf->info->version) { | ||
| 220 | case CCF1: | ||
| 221 | iowrite32be(0, &ccf->err_regs->errdis); | ||
| 222 | break; | ||
| 223 | |||
| 224 | case CCF2: | ||
| 225 | /* | ||
| 226 | * We clear errdis on ccf1 because that's the only way to | ||
| 227 | * disable interrupts, but on ccf2 there's no need to disable | ||
| 228 | * detection. | ||
| 229 | */ | ||
| 230 | iowrite32be(0, &ccf->err_regs->errinten); | ||
| 231 | break; | ||
| 232 | } | ||
| 233 | |||
| 234 | return 0; | ||
| 235 | } | ||
| 236 | |||
| 237 | static struct platform_driver ccf_driver = { | ||
| 238 | .driver = { | ||
| 239 | .name = KBUILD_MODNAME, | ||
| 240 | .owner = THIS_MODULE, | ||
| 241 | .of_match_table = ccf_matches, | ||
| 242 | }, | ||
| 243 | .probe = ccf_probe, | ||
| 244 | .remove = ccf_remove, | ||
| 245 | }; | ||
| 246 | |||
| 247 | module_platform_driver(ccf_driver); | ||
| 248 | |||
| 249 | MODULE_LICENSE("GPL"); | ||
| 250 | MODULE_AUTHOR("Freescale Semiconductor"); | ||
| 251 | MODULE_DESCRIPTION("Freescale CoreNet Coherency Fabric error reporting"); | ||
diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-fec.c b/drivers/net/ethernet/freescale/fs_enet/mac-fec.c index fc5413488496..1eedfba2ad3c 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mac-fec.c +++ b/drivers/net/ethernet/freescale/fs_enet/mac-fec.c | |||
| @@ -41,7 +41,6 @@ | |||
| 41 | #ifdef CONFIG_8xx | 41 | #ifdef CONFIG_8xx |
| 42 | #include <asm/8xx_immap.h> | 42 | #include <asm/8xx_immap.h> |
| 43 | #include <asm/pgtable.h> | 43 | #include <asm/pgtable.h> |
| 44 | #include <asm/mpc8xx.h> | ||
| 45 | #include <asm/cpm1.h> | 44 | #include <asm/cpm1.h> |
| 46 | #endif | 45 | #endif |
| 47 | 46 | ||
diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-scc.c b/drivers/net/ethernet/freescale/fs_enet/mac-scc.c index b4bf02f57d43..90b3b19b7cd3 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mac-scc.c +++ b/drivers/net/ethernet/freescale/fs_enet/mac-scc.c | |||
| @@ -40,7 +40,6 @@ | |||
| 40 | #ifdef CONFIG_8xx | 40 | #ifdef CONFIG_8xx |
| 41 | #include <asm/8xx_immap.h> | 41 | #include <asm/8xx_immap.h> |
| 42 | #include <asm/pgtable.h> | 42 | #include <asm/pgtable.h> |
| 43 | #include <asm/mpc8xx.h> | ||
| 44 | #include <asm/cpm1.h> | 43 | #include <asm/cpm1.h> |
| 45 | #endif | 44 | #endif |
| 46 | 45 | ||
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index 51cf8083b299..b0ce7cdee0c2 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig | |||
| @@ -144,16 +144,6 @@ config TCIC | |||
| 144 | "Bridge" is the name used for the hardware inside your computer that | 144 | "Bridge" is the name used for the hardware inside your computer that |
| 145 | PCMCIA cards are plugged into. If unsure, say N. | 145 | PCMCIA cards are plugged into. If unsure, say N. |
| 146 | 146 | ||
| 147 | config PCMCIA_M8XX | ||
| 148 | tristate "MPC8xx PCMCIA support" | ||
| 149 | depends on PCCARD && PPC && 8xx | ||
| 150 | select PCCARD_IODYN if PCMCIA != n | ||
| 151 | help | ||
| 152 | Say Y here to include support for PowerPC 8xx series PCMCIA | ||
| 153 | controller. | ||
| 154 | |||
| 155 | This driver is also available as a module called m8xx_pcmcia. | ||
| 156 | |||
| 157 | config PCMCIA_ALCHEMY_DEVBOARD | 147 | config PCMCIA_ALCHEMY_DEVBOARD |
| 158 | tristate "Alchemy Db/Pb1xxx PCMCIA socket services" | 148 | tristate "Alchemy Db/Pb1xxx PCMCIA socket services" |
| 159 | depends on MIPS_ALCHEMY && PCMCIA | 149 | depends on MIPS_ALCHEMY && PCMCIA |
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index fd55a6951402..27e94b30cf96 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile | |||
| @@ -23,7 +23,6 @@ obj-$(CONFIG_PD6729) += pd6729.o | |||
| 23 | obj-$(CONFIG_I82365) += i82365.o | 23 | obj-$(CONFIG_I82365) += i82365.o |
| 24 | obj-$(CONFIG_I82092) += i82092.o | 24 | obj-$(CONFIG_I82092) += i82092.o |
| 25 | obj-$(CONFIG_TCIC) += tcic.o | 25 | obj-$(CONFIG_TCIC) += tcic.o |
| 26 | obj-$(CONFIG_PCMCIA_M8XX) += m8xx_pcmcia.o | ||
| 27 | obj-$(CONFIG_PCMCIA_SOC_COMMON) += soc_common.o | 26 | obj-$(CONFIG_PCMCIA_SOC_COMMON) += soc_common.o |
| 28 | obj-$(CONFIG_PCMCIA_SA11XX_BASE) += sa11xx_base.o | 27 | obj-$(CONFIG_PCMCIA_SA11XX_BASE) += sa11xx_base.o |
| 29 | obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o | 28 | obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o |
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c deleted file mode 100644 index 182034d2ef58..000000000000 --- a/drivers/pcmcia/m8xx_pcmcia.c +++ /dev/null | |||
| @@ -1,1168 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * m8xx_pcmcia.c - Linux PCMCIA socket driver for the mpc8xx series. | ||
| 3 | * | ||
| 4 | * (C) 1999-2000 Magnus Damm <damm@opensource.se> | ||
| 5 | * (C) 2001-2002 Montavista Software, Inc. | ||
| 6 | * <mlocke@mvista.com> | ||
| 7 | * | ||
| 8 | * Support for two slots by Cyclades Corporation | ||
| 9 | * <oliver.kurth@cyclades.de> | ||
| 10 | * Further fixes, v2.6 kernel port | ||
| 11 | * <marcelo.tosatti@cyclades.com> | ||
| 12 | * | ||
| 13 | * Some fixes, additions (C) 2005-2007 Montavista Software, Inc. | ||
| 14 | * <vbordug@ru.mvista.com> | ||
| 15 | * | ||
| 16 | * "The ExCA standard specifies that socket controllers should provide | ||
| 17 | * two IO and five memory windows per socket, which can be independently | ||
| 18 | * configured and positioned in the host address space and mapped to | ||
| 19 | * arbitrary segments of card address space. " - David A Hinds. 1999 | ||
| 20 | * | ||
| 21 | * This controller does _not_ meet the ExCA standard. | ||
| 22 | * | ||
| 23 | * m8xx pcmcia controller brief info: | ||
| 24 | * + 8 windows (attrib, mem, i/o) | ||
| 25 | * + up to two slots (SLOT_A and SLOT_B) | ||
| 26 | * + inputpins, outputpins, event and mask registers. | ||
| 27 | * - no offset register. sigh. | ||
| 28 | * | ||
| 29 | * Because of the lacking offset register we must map the whole card. | ||
| 30 | * We assign each memory window PCMCIA_MEM_WIN_SIZE address space. | ||
| 31 | * Make sure there is (PCMCIA_MEM_WIN_SIZE * PCMCIA_MEM_WIN_NO | ||
| 32 | * * PCMCIA_SOCKETS_NO) bytes at PCMCIA_MEM_WIN_BASE. | ||
| 33 | * The i/o windows are dynamically allocated at PCMCIA_IO_WIN_BASE. | ||
| 34 | * They are maximum 64KByte each... | ||
| 35 | */ | ||
| 36 | |||
| 37 | #include <linux/module.h> | ||
| 38 | #include <linux/init.h> | ||
| 39 | #include <linux/types.h> | ||
| 40 | #include <linux/fcntl.h> | ||
| 41 | #include <linux/string.h> | ||
| 42 | |||
| 43 | #include <linux/kernel.h> | ||
| 44 | #include <linux/errno.h> | ||
| 45 | #include <linux/timer.h> | ||
| 46 | #include <linux/ioport.h> | ||
| 47 | #include <linux/delay.h> | ||
| 48 | #include <linux/interrupt.h> | ||
| 49 | #include <linux/fsl_devices.h> | ||
| 50 | #include <linux/bitops.h> | ||
| 51 | #include <linux/of_address.h> | ||
| 52 | #include <linux/of_device.h> | ||
| 53 | #include <linux/of_irq.h> | ||
| 54 | #include <linux/of_platform.h> | ||
| 55 | |||
| 56 | #include <asm/io.h> | ||
| 57 | #include <asm/time.h> | ||
| 58 | #include <asm/mpc8xx.h> | ||
| 59 | #include <asm/8xx_immap.h> | ||
| 60 | #include <asm/irq.h> | ||
| 61 | #include <asm/fs_pd.h> | ||
| 62 | |||
| 63 | #include <pcmcia/ss.h> | ||
| 64 | |||
| 65 | #define pcmcia_info(args...) printk(KERN_INFO "m8xx_pcmcia: "args) | ||
| 66 | #define pcmcia_error(args...) printk(KERN_ERR "m8xx_pcmcia: "args) | ||
| 67 | |||
| 68 | static const char *version = "Version 0.06, Aug 2005"; | ||
| 69 | MODULE_LICENSE("Dual MPL/GPL"); | ||
| 70 | |||
| 71 | #if !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B) | ||
| 72 | |||
| 73 | /* The ADS board use SLOT_A */ | ||
| 74 | #ifdef CONFIG_ADS | ||
| 75 | #define CONFIG_PCMCIA_SLOT_A | ||
| 76 | #define CONFIG_BD_IS_MHZ | ||
| 77 | #endif | ||
| 78 | |||
| 79 | /* The FADS series are a mess */ | ||
| 80 | #ifdef CONFIG_FADS | ||
| 81 | #if defined(CONFIG_MPC860T) || defined(CONFIG_MPC860) || defined(CONFIG_MPC821) | ||
| 82 | #define CONFIG_PCMCIA_SLOT_A | ||
| 83 | #else | ||
| 84 | #define CONFIG_PCMCIA_SLOT_B | ||
| 85 | #endif | ||
| 86 | #endif | ||
| 87 | |||
| 88 | #if defined(CONFIG_MPC885ADS) | ||
| 89 | #define CONFIG_PCMCIA_SLOT_A | ||
| 90 | #define PCMCIA_GLITCHY_CD | ||
| 91 | #endif | ||
| 92 | |||
| 93 | /* Cyclades ACS uses both slots */ | ||
| 94 | #ifdef CONFIG_PRxK | ||
| 95 | #define CONFIG_PCMCIA_SLOT_A | ||
| 96 | #define CONFIG_PCMCIA_SLOT_B | ||
| 97 | #endif | ||
| 98 | |||
| 99 | #endif /* !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B) */ | ||
| 100 | |||
| 101 | #if defined(CONFIG_PCMCIA_SLOT_A) && defined(CONFIG_PCMCIA_SLOT_B) | ||
| 102 | |||
| 103 | #define PCMCIA_SOCKETS_NO 2 | ||
| 104 | /* We have only 8 windows, dualsocket support will be limited. */ | ||
| 105 | #define PCMCIA_MEM_WIN_NO 2 | ||
| 106 | #define PCMCIA_IO_WIN_NO 2 | ||
| 107 | #define PCMCIA_SLOT_MSG "SLOT_A and SLOT_B" | ||
| 108 | |||
| 109 | #elif defined(CONFIG_PCMCIA_SLOT_A) || defined(CONFIG_PCMCIA_SLOT_B) | ||
| 110 | |||
| 111 | #define PCMCIA_SOCKETS_NO 1 | ||
| 112 | /* full support for one slot */ | ||
| 113 | #define PCMCIA_MEM_WIN_NO 5 | ||
| 114 | #define PCMCIA_IO_WIN_NO 2 | ||
| 115 | |||
| 116 | /* define _slot_ to be able to optimize macros */ | ||
| 117 | |||
| 118 | #ifdef CONFIG_PCMCIA_SLOT_A | ||
| 119 | #define _slot_ 0 | ||
| 120 | #define PCMCIA_SLOT_MSG "SLOT_A" | ||
| 121 | #else | ||
| 122 | #define _slot_ 1 | ||
| 123 | #define PCMCIA_SLOT_MSG "SLOT_B" | ||
| 124 | #endif | ||
| 125 | |||
| 126 | #else | ||
| 127 | #error m8xx_pcmcia: Bad configuration! | ||
| 128 | #endif | ||
| 129 | |||
| 130 | /* ------------------------------------------------------------------------- */ | ||
| 131 | |||
| 132 | #define PCMCIA_MEM_WIN_BASE 0xe0000000 /* base address for memory window 0 */ | ||
| 133 | #define PCMCIA_MEM_WIN_SIZE 0x04000000 /* each memory window is 64 MByte */ | ||
| 134 | #define PCMCIA_IO_WIN_BASE _IO_BASE /* base address for io window 0 */ | ||
| 135 | /* ------------------------------------------------------------------------- */ | ||
| 136 | |||
| 137 | static int pcmcia_schlvl; | ||
| 138 | |||
| 139 | static DEFINE_SPINLOCK(events_lock); | ||
| 140 | |||
| 141 | #define PCMCIA_SOCKET_KEY_5V 1 | ||
| 142 | #define PCMCIA_SOCKET_KEY_LV 2 | ||
| 143 | |||
| 144 | /* look up table for pgcrx registers */ | ||
| 145 | static u32 *m8xx_pgcrx[2]; | ||
| 146 | |||
| 147 | /* | ||
| 148 | * This structure is used to address each window in the PCMCIA controller. | ||
| 149 | * | ||
| 150 | * Keep in mind that we assume that pcmcia_win[n+1] is mapped directly | ||
| 151 | * after pcmcia_win[n]... | ||
| 152 | */ | ||
| 153 | |||
| 154 | struct pcmcia_win { | ||
| 155 | u32 br; | ||
| 156 | u32 or; | ||
| 157 | }; | ||
| 158 | |||
| 159 | /* | ||
| 160 | * For some reason the hardware guys decided to make both slots share | ||
| 161 | * some registers. | ||
| 162 | * | ||
| 163 | * Could someone invent object oriented hardware ? | ||
| 164 | * | ||
| 165 | * The macros are used to get the right bit from the registers. | ||
| 166 | * SLOT_A : slot = 0 | ||
| 167 | * SLOT_B : slot = 1 | ||
| 168 | */ | ||
| 169 | |||
| 170 | #define M8XX_PCMCIA_VS1(slot) (0x80000000 >> (slot << 4)) | ||
| 171 | #define M8XX_PCMCIA_VS2(slot) (0x40000000 >> (slot << 4)) | ||
| 172 | #define M8XX_PCMCIA_VS_MASK(slot) (0xc0000000 >> (slot << 4)) | ||
| 173 | #define M8XX_PCMCIA_VS_SHIFT(slot) (30 - (slot << 4)) | ||
| 174 | |||
| 175 | #define M8XX_PCMCIA_WP(slot) (0x20000000 >> (slot << 4)) | ||
| 176 | #define M8XX_PCMCIA_CD2(slot) (0x10000000 >> (slot << 4)) | ||
| 177 | #define M8XX_PCMCIA_CD1(slot) (0x08000000 >> (slot << 4)) | ||
| 178 | #define M8XX_PCMCIA_BVD2(slot) (0x04000000 >> (slot << 4)) | ||
| 179 | #define M8XX_PCMCIA_BVD1(slot) (0x02000000 >> (slot << 4)) | ||
| 180 | #define M8XX_PCMCIA_RDY(slot) (0x01000000 >> (slot << 4)) | ||
| 181 | #define M8XX_PCMCIA_RDY_L(slot) (0x00800000 >> (slot << 4)) | ||
| 182 | #define M8XX_PCMCIA_RDY_H(slot) (0x00400000 >> (slot << 4)) | ||
| 183 | #define M8XX_PCMCIA_RDY_R(slot) (0x00200000 >> (slot << 4)) | ||
| 184 | #define M8XX_PCMCIA_RDY_F(slot) (0x00100000 >> (slot << 4)) | ||
| 185 | #define M8XX_PCMCIA_MASK(slot) (0xFFFF0000 >> (slot << 4)) | ||
| 186 | |||
| 187 | #define M8XX_PCMCIA_POR_VALID 0x00000001 | ||
| 188 | #define M8XX_PCMCIA_POR_WRPROT 0x00000002 | ||
| 189 | #define M8XX_PCMCIA_POR_ATTRMEM 0x00000010 | ||
| 190 | #define M8XX_PCMCIA_POR_IO 0x00000018 | ||
| 191 | #define M8XX_PCMCIA_POR_16BIT 0x00000040 | ||
| 192 | |||
| 193 | #define M8XX_PGCRX(slot) m8xx_pgcrx[slot] | ||
| 194 | |||
| 195 | #define M8XX_PGCRX_CXOE 0x00000080 | ||
| 196 | #define M8XX_PGCRX_CXRESET 0x00000040 | ||
| 197 | |||
| 198 | /* we keep one lookup table per socket to check flags */ | ||
| 199 | |||
| 200 | #define PCMCIA_EVENTS_MAX 5 /* 4 max at a time + termination */ | ||
| 201 | |||
| 202 | struct event_table { | ||
| 203 | u32 regbit; | ||
| 204 | u32 eventbit; | ||
| 205 | }; | ||
| 206 | |||
| 207 | static const char driver_name[] = "m8xx-pcmcia"; | ||
| 208 | |||
| 209 | struct socket_info { | ||
| 210 | void (*handler) (void *info, u32 events); | ||
| 211 | void *info; | ||
| 212 | |||
| 213 | u32 slot; | ||
| 214 | pcmconf8xx_t *pcmcia; | ||
| 215 | u32 bus_freq; | ||
| 216 | int hwirq; | ||
| 217 | |||
| 218 | socket_state_t state; | ||
| 219 | struct pccard_mem_map mem_win[PCMCIA_MEM_WIN_NO]; | ||
| 220 | struct pccard_io_map io_win[PCMCIA_IO_WIN_NO]; | ||
| 221 | struct event_table events[PCMCIA_EVENTS_MAX]; | ||
| 222 | struct pcmcia_socket socket; | ||
| 223 | }; | ||
| 224 | |||
| 225 | static struct socket_info socket[PCMCIA_SOCKETS_NO]; | ||
| 226 | |||
| 227 | /* | ||
| 228 | * Search this table to see if the windowsize is | ||
| 229 | * supported... | ||
| 230 | */ | ||
| 231 | |||
| 232 | #define M8XX_SIZES_NO 32 | ||
| 233 | |||
| 234 | static const u32 m8xx_size_to_gray[M8XX_SIZES_NO] = { | ||
| 235 | 0x00000001, 0x00000002, 0x00000008, 0x00000004, | ||
| 236 | 0x00000080, 0x00000040, 0x00000010, 0x00000020, | ||
| 237 | 0x00008000, 0x00004000, 0x00001000, 0x00002000, | ||
| 238 | 0x00000100, 0x00000200, 0x00000800, 0x00000400, | ||
| 239 | |||
| 240 | 0x0fffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
| 241 | 0x01000000, 0x02000000, 0xffffffff, 0x04000000, | ||
| 242 | 0x00010000, 0x00020000, 0x00080000, 0x00040000, | ||
| 243 | 0x00800000, 0x00400000, 0x00100000, 0x00200000 | ||
| 244 | }; | ||
| 245 | |||
| 246 | /* ------------------------------------------------------------------------- */ | ||
| 247 | |||
| 248 | static irqreturn_t m8xx_interrupt(int irq, void *dev); | ||
| 249 | |||
| 250 | #define PCMCIA_BMT_LIMIT (15*4) /* Bus Monitor Timeout value */ | ||
| 251 | |||
| 252 | /* FADS Boards from Motorola */ | ||
| 253 | |||
| 254 | #if defined(CONFIG_FADS) | ||
| 255 | |||
| 256 | #define PCMCIA_BOARD_MSG "FADS" | ||
| 257 | |||
| 258 | static int voltage_set(int slot, int vcc, int vpp) | ||
| 259 | { | ||
| 260 | u32 reg = 0; | ||
| 261 | |||
| 262 | switch (vcc) { | ||
| 263 | case 0: | ||
| 264 | break; | ||
| 265 | case 33: | ||
| 266 | reg |= BCSR1_PCCVCC0; | ||
| 267 | break; | ||
| 268 | case 50: | ||
| 269 | reg |= BCSR1_PCCVCC1; | ||
| 270 | break; | ||
| 271 | default: | ||
| 272 | return 1; | ||
| 273 | } | ||
| 274 | |||
| 275 | switch (vpp) { | ||
| 276 | case 0: | ||
| 277 | break; | ||
| 278 | case 33: | ||
| 279 | case 50: | ||
| 280 | if (vcc == vpp) | ||
| 281 | reg |= BCSR1_PCCVPP1; | ||
| 282 | else | ||
| 283 | return 1; | ||
| 284 | break; | ||
| 285 | case 120: | ||
| 286 | if ((vcc == 33) || (vcc == 50)) | ||
| 287 | reg |= BCSR1_PCCVPP0; | ||
| 288 | else | ||
| 289 | return 1; | ||
| 290 | default: | ||
| 291 | return 1; | ||
| 292 | } | ||
| 293 | |||
| 294 | /* first, turn off all power */ | ||
| 295 | out_be32((u32 *) BCSR1, | ||
| 296 | in_be32((u32 *) BCSR1) & ~(BCSR1_PCCVCC_MASK | | ||
| 297 | BCSR1_PCCVPP_MASK)); | ||
| 298 | |||
| 299 | /* enable new powersettings */ | ||
| 300 | out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) | reg); | ||
| 301 | |||
| 302 | return 0; | ||
| 303 | } | ||
| 304 | |||
| 305 | #define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V | ||
| 306 | |||
| 307 | static void hardware_enable(int slot) | ||
| 308 | { | ||
| 309 | out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) & ~BCSR1_PCCEN); | ||
| 310 | } | ||
| 311 | |||
| 312 | static void hardware_disable(int slot) | ||
| 313 | { | ||
| 314 | out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) | BCSR1_PCCEN); | ||
| 315 | } | ||
| 316 | |||
| 317 | #endif | ||
| 318 | |||
| 319 | /* MPC885ADS Boards */ | ||
| 320 | |||
| 321 | #if defined(CONFIG_MPC885ADS) | ||
| 322 | |||
| 323 | #define PCMCIA_BOARD_MSG "MPC885ADS" | ||
| 324 | #define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V | ||
| 325 | |||
| 326 | static inline void hardware_enable(int slot) | ||
| 327 | { | ||
| 328 | m8xx_pcmcia_ops.hw_ctrl(slot, 1); | ||
| 329 | } | ||
| 330 | |||
| 331 | static inline void hardware_disable(int slot) | ||
| 332 | { | ||
| 333 | m8xx_pcmcia_ops.hw_ctrl(slot, 0); | ||
| 334 | } | ||
| 335 | |||
| 336 | static inline int voltage_set(int slot, int vcc, int vpp) | ||
| 337 | { | ||
| 338 | return m8xx_pcmcia_ops.voltage_set(slot, vcc, vpp); | ||
| 339 | } | ||
| 340 | |||
| 341 | #endif | ||
| 342 | |||
| 343 | #if defined(CONFIG_PRxK) | ||
| 344 | #include <asm/cpld.h> | ||
| 345 | extern volatile fpga_pc_regs *fpga_pc; | ||
| 346 | |||
| 347 | #define PCMCIA_BOARD_MSG "MPC855T" | ||
| 348 | |||
| 349 | static int voltage_set(int slot, int vcc, int vpp) | ||
| 350 | { | ||
| 351 | u8 reg = 0; | ||
| 352 | u8 regread; | ||
| 353 | cpld_regs *ccpld = get_cpld(); | ||
| 354 | |||
| 355 | switch (vcc) { | ||
| 356 | case 0: | ||
| 357 | break; | ||
| 358 | case 33: | ||
| 359 | reg |= PCMCIA_VCC_33; | ||
| 360 | break; | ||
| 361 | case 50: | ||
| 362 | reg |= PCMCIA_VCC_50; | ||
| 363 | break; | ||
| 364 | default: | ||
| 365 | return 1; | ||
| 366 | } | ||
| 367 | |||
| 368 | switch (vpp) { | ||
| 369 | case 0: | ||
| 370 | break; | ||
| 371 | case 33: | ||
| 372 | case 50: | ||
| 373 | if (vcc == vpp) | ||
| 374 | reg |= PCMCIA_VPP_VCC; | ||
| 375 | else | ||
| 376 | return 1; | ||
| 377 | break; | ||
| 378 | case 120: | ||
| 379 | if ((vcc == 33) || (vcc == 50)) | ||
| 380 | reg |= PCMCIA_VPP_12; | ||
| 381 | else | ||
| 382 | return 1; | ||
| 383 | default: | ||
| 384 | return 1; | ||
| 385 | } | ||
| 386 | |||
| 387 | reg = reg >> (slot << 2); | ||
| 388 | regread = in_8(&ccpld->fpga_pc_ctl); | ||
| 389 | if (reg != | ||
| 390 | (regread & ((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >> (slot << 2)))) { | ||
| 391 | /* enable new powersettings */ | ||
| 392 | regread = | ||
| 393 | regread & ~((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >> | ||
| 394 | (slot << 2)); | ||
| 395 | out_8(&ccpld->fpga_pc_ctl, reg | regread); | ||
| 396 | msleep(100); | ||
| 397 | } | ||
| 398 | |||
| 399 | return 0; | ||
| 400 | } | ||
| 401 | |||
| 402 | #define socket_get(_slot_) PCMCIA_SOCKET_KEY_LV | ||
| 403 | #define hardware_enable(_slot_) /* No hardware to enable */ | ||
| 404 | #define hardware_disable(_slot_) /* No hardware to disable */ | ||
| 405 | |||
| 406 | #endif /* CONFIG_PRxK */ | ||
| 407 | |||
| 408 | static u32 pending_events[PCMCIA_SOCKETS_NO]; | ||
| 409 | static DEFINE_SPINLOCK(pending_event_lock); | ||
| 410 | |||
| 411 | static irqreturn_t m8xx_interrupt(int irq, void *dev) | ||
| 412 | { | ||
| 413 | struct socket_info *s; | ||
| 414 | struct event_table *e; | ||
| 415 | unsigned int i, events, pscr, pipr, per; | ||
| 416 | pcmconf8xx_t *pcmcia = socket[0].pcmcia; | ||
| 417 | |||
| 418 | pr_debug("m8xx_pcmcia: Interrupt!\n"); | ||
| 419 | /* get interrupt sources */ | ||
| 420 | |||
| 421 | pscr = in_be32(&pcmcia->pcmc_pscr); | ||
| 422 | pipr = in_be32(&pcmcia->pcmc_pipr); | ||
| 423 | per = in_be32(&pcmcia->pcmc_per); | ||
| 424 | |||
| 425 | for (i = 0; i < PCMCIA_SOCKETS_NO; i++) { | ||
| 426 | s = &socket[i]; | ||
| 427 | e = &s->events[0]; | ||
| 428 | events = 0; | ||
| 429 | |||
| 430 | while (e->regbit) { | ||
| 431 | if (pscr & e->regbit) | ||
| 432 | events |= e->eventbit; | ||
| 433 | |||
| 434 | e++; | ||
| 435 | } | ||
| 436 | |||
| 437 | /* | ||
| 438 | * report only if both card detect signals are the same | ||
| 439 | * not too nice done, | ||
| 440 | * we depend on that CD2 is the bit to the left of CD1... | ||
| 441 | */ | ||
| 442 | if (events & SS_DETECT) | ||
| 443 | if (((pipr & M8XX_PCMCIA_CD2(i)) >> 1) ^ | ||
| 444 | (pipr & M8XX_PCMCIA_CD1(i))) { | ||
| 445 | events &= ~SS_DETECT; | ||
| 446 | } | ||
| 447 | #ifdef PCMCIA_GLITCHY_CD | ||
| 448 | /* | ||
| 449 | * I've experienced CD problems with my ADS board. | ||
| 450 | * We make an extra check to see if there was a | ||
| 451 | * real change of Card detection. | ||
| 452 | */ | ||
| 453 | |||
| 454 | if ((events & SS_DETECT) && | ||
| 455 | ((pipr & | ||
| 456 | (M8XX_PCMCIA_CD2(i) | M8XX_PCMCIA_CD1(i))) == 0) && | ||
| 457 | (s->state.Vcc | s->state.Vpp)) { | ||
| 458 | events &= ~SS_DETECT; | ||
| 459 | /*printk( "CD glitch workaround - CD = 0x%08x!\n", | ||
| 460 | (pipr & (M8XX_PCMCIA_CD2(i) | ||
| 461 | | M8XX_PCMCIA_CD1(i)))); */ | ||
| 462 | } | ||
| 463 | #endif | ||
| 464 | |||
| 465 | /* call the handler */ | ||
| 466 | |||
| 467 | pr_debug("m8xx_pcmcia: slot %u: events = 0x%02x, pscr = 0x%08x, " | ||
| 468 | "pipr = 0x%08x\n", i, events, pscr, pipr); | ||
| 469 | |||
| 470 | if (events) { | ||
| 471 | spin_lock(&pending_event_lock); | ||
| 472 | pending_events[i] |= events; | ||
| 473 | spin_unlock(&pending_event_lock); | ||
| 474 | /* | ||
| 475 | * Turn off RDY_L bits in the PER mask on | ||
| 476 | * CD interrupt receival. | ||
| 477 | * | ||
| 478 | * They can generate bad interrupts on the | ||
| 479 | * ACS4,8,16,32. - marcelo | ||
| 480 | */ | ||
| 481 | per &= ~M8XX_PCMCIA_RDY_L(0); | ||
| 482 | per &= ~M8XX_PCMCIA_RDY_L(1); | ||
| 483 | |||
| 484 | out_be32(&pcmcia->pcmc_per, per); | ||
| 485 | |||
| 486 | if (events) | ||
| 487 | pcmcia_parse_events(&socket[i].socket, events); | ||
| 488 | } | ||
| 489 | } | ||
| 490 | |||
| 491 | /* clear the interrupt sources */ | ||
| 492 | out_be32(&pcmcia->pcmc_pscr, pscr); | ||
| 493 | |||
| 494 | pr_debug("m8xx_pcmcia: Interrupt done.\n"); | ||
| 495 | |||
| 496 | return IRQ_HANDLED; | ||
| 497 | } | ||
| 498 | |||
| 499 | static u32 m8xx_get_graycode(u32 size) | ||
| 500 | { | ||
| 501 | u32 k; | ||
| 502 | |||
| 503 | for (k = 0; k < M8XX_SIZES_NO; k++) | ||
| 504 | if (m8xx_size_to_gray[k] == size) | ||
| 505 | break; | ||
| 506 | |||
| 507 | if ((k == M8XX_SIZES_NO) || (m8xx_size_to_gray[k] == -1)) | ||
| 508 | k = -1; | ||
| 509 | |||
| 510 | return k; | ||
| 511 | } | ||
| 512 | |||
| 513 | static u32 m8xx_get_speed(u32 ns, u32 is_io, u32 bus_freq) | ||
| 514 | { | ||
| 515 | u32 reg, clocks, psst, psl, psht; | ||
| 516 | |||
| 517 | if (!ns) { | ||
| 518 | |||
| 519 | /* | ||
| 520 | * We get called with IO maps setup to 0ns | ||
| 521 | * if not specified by the user. | ||
| 522 | * They should be 255ns. | ||
| 523 | */ | ||
| 524 | |||
| 525 | if (is_io) | ||
| 526 | ns = 255; | ||
| 527 | else | ||
| 528 | ns = 100; /* fast memory if 0 */ | ||
| 529 | } | ||
| 530 | |||
| 531 | /* | ||
| 532 | * In PSST, PSL, PSHT fields we tell the controller | ||
| 533 | * timing parameters in CLKOUT clock cycles. | ||
| 534 | * CLKOUT is the same as GCLK2_50. | ||
| 535 | */ | ||
| 536 | |||
| 537 | /* how we want to adjust the timing - in percent */ | ||
| 538 | |||
| 539 | #define ADJ 180 /* 80 % longer accesstime - to be sure */ | ||
| 540 | |||
| 541 | clocks = ((bus_freq / 1000) * ns) / 1000; | ||
| 542 | clocks = (clocks * ADJ) / (100 * 1000); | ||
| 543 | if (clocks >= PCMCIA_BMT_LIMIT) { | ||
| 544 | printk("Max access time limit reached\n"); | ||
| 545 | clocks = PCMCIA_BMT_LIMIT - 1; | ||
| 546 | } | ||
| 547 | |||
| 548 | psst = clocks / 7; /* setup time */ | ||
| 549 | psht = clocks / 7; /* hold time */ | ||
| 550 | psl = (clocks * 5) / 7; /* strobe length */ | ||
| 551 | |||
| 552 | psst += clocks - (psst + psht + psl); | ||
| 553 | |||
| 554 | reg = psst << 12; | ||
| 555 | reg |= psl << 7; | ||
| 556 | reg |= psht << 16; | ||
| 557 | |||
| 558 | return reg; | ||
| 559 | } | ||
| 560 | |||
| 561 | static int m8xx_get_status(struct pcmcia_socket *sock, unsigned int *value) | ||
| 562 | { | ||
| 563 | int lsock = container_of(sock, struct socket_info, socket)->slot; | ||
| 564 | struct socket_info *s = &socket[lsock]; | ||
| 565 | unsigned int pipr, reg; | ||
| 566 | pcmconf8xx_t *pcmcia = s->pcmcia; | ||
| 567 | |||
| 568 | pipr = in_be32(&pcmcia->pcmc_pipr); | ||
| 569 | |||
| 570 | *value = ((pipr & (M8XX_PCMCIA_CD1(lsock) | ||
| 571 | | M8XX_PCMCIA_CD2(lsock))) == 0) ? SS_DETECT : 0; | ||
| 572 | *value |= (pipr & M8XX_PCMCIA_WP(lsock)) ? SS_WRPROT : 0; | ||
| 573 | |||
| 574 | if (s->state.flags & SS_IOCARD) | ||
| 575 | *value |= (pipr & M8XX_PCMCIA_BVD1(lsock)) ? SS_STSCHG : 0; | ||
| 576 | else { | ||
| 577 | *value |= (pipr & M8XX_PCMCIA_RDY(lsock)) ? SS_READY : 0; | ||
| 578 | *value |= (pipr & M8XX_PCMCIA_BVD1(lsock)) ? SS_BATDEAD : 0; | ||
| 579 | *value |= (pipr & M8XX_PCMCIA_BVD2(lsock)) ? SS_BATWARN : 0; | ||
| 580 | } | ||
| 581 | |||
| 582 | if (s->state.Vcc | s->state.Vpp) | ||
| 583 | *value |= SS_POWERON; | ||
| 584 | |||
| 585 | /* | ||
| 586 | * Voltage detection: | ||
| 587 | * This driver only supports 16-Bit pc-cards. | ||
| 588 | * Cardbus is not handled here. | ||
| 589 | * | ||
| 590 | * To determine what voltage to use we must read the VS1 and VS2 pin. | ||
| 591 | * Depending on what socket type is present, | ||
| 592 | * different combinations mean different things. | ||
| 593 | * | ||
| 594 | * Card Key Socket Key VS1 VS2 Card Vcc for CIS parse | ||
| 595 | * | ||
| 596 | * 5V 5V, LV* NC NC 5V only 5V (if available) | ||
| 597 | * | ||
| 598 | * 5V 5V, LV* GND NC 5 or 3.3V as low as possible | ||
| 599 | * | ||
| 600 | * 5V 5V, LV* GND GND 5, 3.3, x.xV as low as possible | ||
| 601 | * | ||
| 602 | * LV* 5V - - shall not fit into socket | ||
| 603 | * | ||
| 604 | * LV* LV* GND NC 3.3V only 3.3V | ||
| 605 | * | ||
| 606 | * LV* LV* NC GND x.xV x.xV (if avail.) | ||
| 607 | * | ||
| 608 | * LV* LV* GND GND 3.3 or x.xV as low as possible | ||
| 609 | * | ||
| 610 | * *LV means Low Voltage | ||
| 611 | * | ||
| 612 | * | ||
| 613 | * That gives us the following table: | ||
| 614 | * | ||
| 615 | * Socket VS1 VS2 Voltage | ||
| 616 | * | ||
| 617 | * 5V NC NC 5V | ||
| 618 | * 5V NC GND none (should not be possible) | ||
| 619 | * 5V GND NC >= 3.3V | ||
| 620 | * 5V GND GND >= x.xV | ||
| 621 | * | ||
| 622 | * LV NC NC 5V (if available) | ||
| 623 | * LV NC GND x.xV (if available) | ||
| 624 | * LV GND NC 3.3V | ||
| 625 | * LV GND GND >= x.xV | ||
| 626 | * | ||
| 627 | * So, how do I determine if I have a 5V or a LV | ||
| 628 | * socket on my board? Look at the socket! | ||
| 629 | * | ||
| 630 | * | ||
| 631 | * Socket with 5V key: | ||
| 632 | * ++--------------------------------------------+ | ||
| 633 | * || | | ||
| 634 | * || || | ||
| 635 | * || || | ||
| 636 | * | | | ||
| 637 | * +---------------------------------------------+ | ||
| 638 | * | ||
| 639 | * Socket with LV key: | ||
| 640 | * ++--------------------------------------------+ | ||
| 641 | * || | | ||
| 642 | * | || | ||
| 643 | * | || | ||
| 644 | * | | | ||
| 645 | * +---------------------------------------------+ | ||
| 646 | * | ||
| 647 | * | ||
| 648 | * With other words - LV only cards does not fit | ||
| 649 | * into the 5V socket! | ||
| 650 | */ | ||
| 651 | |||
| 652 | /* read out VS1 and VS2 */ | ||
| 653 | |||
| 654 | reg = (pipr & M8XX_PCMCIA_VS_MASK(lsock)) | ||
| 655 | >> M8XX_PCMCIA_VS_SHIFT(lsock); | ||
| 656 | |||
| 657 | if (socket_get(lsock) == PCMCIA_SOCKET_KEY_LV) { | ||
| 658 | switch (reg) { | ||
| 659 | case 1: | ||
| 660 | *value |= SS_3VCARD; | ||
| 661 | break; /* GND, NC - 3.3V only */ | ||
| 662 | case 2: | ||
| 663 | *value |= SS_XVCARD; | ||
| 664 | break; /* NC. GND - x.xV only */ | ||
| 665 | }; | ||
| 666 | } | ||
| 667 | |||
| 668 | pr_debug("m8xx_pcmcia: GetStatus(%d) = %#2.2x\n", lsock, *value); | ||
| 669 | return 0; | ||
| 670 | } | ||
| 671 | |||
| 672 | static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t * state) | ||
| 673 | { | ||
| 674 | int lsock = container_of(sock, struct socket_info, socket)->slot; | ||
| 675 | struct socket_info *s = &socket[lsock]; | ||
| 676 | struct event_table *e; | ||
| 677 | unsigned int reg; | ||
| 678 | unsigned long flags; | ||
| 679 | pcmconf8xx_t *pcmcia = socket[0].pcmcia; | ||
| 680 | |||
| 681 | pr_debug("m8xx_pcmcia: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, " | ||
| 682 | "io_irq %d, csc_mask %#2.2x)\n", lsock, state->flags, | ||
| 683 | state->Vcc, state->Vpp, state->io_irq, state->csc_mask); | ||
| 684 | |||
| 685 | /* First, set voltage - bail out if invalid */ | ||
| 686 | if (voltage_set(lsock, state->Vcc, state->Vpp)) | ||
| 687 | return -EINVAL; | ||
| 688 | |||
| 689 | /* Take care of reset... */ | ||
| 690 | if (state->flags & SS_RESET) | ||
| 691 | out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXRESET); /* active high */ | ||
| 692 | else | ||
| 693 | out_be32(M8XX_PGCRX(lsock), | ||
| 694 | in_be32(M8XX_PGCRX(lsock)) & ~M8XX_PGCRX_CXRESET); | ||
| 695 | |||
| 696 | /* ... and output enable. */ | ||
| 697 | |||
| 698 | /* The CxOE signal is connected to a 74541 on the ADS. | ||
| 699 | I guess most other boards used the ADS as a reference. | ||
| 700 | I tried to control the CxOE signal with SS_OUTPUT_ENA, | ||
| 701 | but the reset signal seems connected via the 541. | ||
| 702 | If the CxOE is left high are some signals tristated and | ||
| 703 | no pullups are present -> the cards act weird. | ||
| 704 | So right now the buffers are enabled if the power is on. */ | ||
| 705 | |||
| 706 | if (state->Vcc || state->Vpp) | ||
| 707 | out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) & ~M8XX_PGCRX_CXOE); /* active low */ | ||
| 708 | else | ||
| 709 | out_be32(M8XX_PGCRX(lsock), | ||
| 710 | in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXOE); | ||
| 711 | |||
| 712 | /* | ||
| 713 | * We'd better turn off interrupts before | ||
| 714 | * we mess with the events-table.. | ||
| 715 | */ | ||
| 716 | |||
| 717 | spin_lock_irqsave(&events_lock, flags); | ||
| 718 | |||
| 719 | /* | ||
| 720 | * Play around with the interrupt mask to be able to | ||
| 721 | * give the events the generic pcmcia driver wants us to. | ||
| 722 | */ | ||
| 723 | |||
| 724 | e = &s->events[0]; | ||
| 725 | reg = 0; | ||
| 726 | |||
| 727 | if (state->csc_mask & SS_DETECT) { | ||
| 728 | e->eventbit = SS_DETECT; | ||
| 729 | reg |= e->regbit = (M8XX_PCMCIA_CD2(lsock) | ||
| 730 | | M8XX_PCMCIA_CD1(lsock)); | ||
| 731 | e++; | ||
| 732 | } | ||
| 733 | if (state->flags & SS_IOCARD) { | ||
| 734 | /* | ||
| 735 | * I/O card | ||
| 736 | */ | ||
| 737 | if (state->csc_mask & SS_STSCHG) { | ||
| 738 | e->eventbit = SS_STSCHG; | ||
| 739 | reg |= e->regbit = M8XX_PCMCIA_BVD1(lsock); | ||
| 740 | e++; | ||
| 741 | } | ||
| 742 | /* | ||
| 743 | * If io_irq is non-zero we should enable irq. | ||
| 744 | */ | ||
| 745 | if (state->io_irq) { | ||
| 746 | out_be32(M8XX_PGCRX(lsock), | ||
| 747 | in_be32(M8XX_PGCRX(lsock)) | | ||
| 748 | mk_int_int_mask(s->hwirq) << 24); | ||
| 749 | /* | ||
| 750 | * Strange thing here: | ||
| 751 | * The manual does not tell us which interrupt | ||
| 752 | * the sources generate. | ||
| 753 | * Anyhow, I found out that RDY_L generates IREQLVL. | ||
| 754 | * | ||
| 755 | * We use level triggerd interrupts, and they don't | ||
| 756 | * have to be cleared in PSCR in the interrupt handler. | ||
| 757 | */ | ||
| 758 | reg |= M8XX_PCMCIA_RDY_L(lsock); | ||
| 759 | } else | ||
| 760 | out_be32(M8XX_PGCRX(lsock), | ||
| 761 | in_be32(M8XX_PGCRX(lsock)) & 0x00ffffff); | ||
| 762 | } else { | ||
| 763 | /* | ||
| 764 | * Memory card | ||
| 765 | */ | ||
| 766 | if (state->csc_mask & SS_BATDEAD) { | ||
| 767 | e->eventbit = SS_BATDEAD; | ||
| 768 | reg |= e->regbit = M8XX_PCMCIA_BVD1(lsock); | ||
| 769 | e++; | ||
| 770 | } | ||
| 771 | if (state->csc_mask & SS_BATWARN) { | ||
| 772 | e->eventbit = SS_BATWARN; | ||
| 773 | reg |= e->regbit = M8XX_PCMCIA_BVD2(lsock); | ||
| 774 | e++; | ||
| 775 | } | ||
| 776 | /* What should I trigger on - low/high,raise,fall? */ | ||
| 777 | if (state->csc_mask & SS_READY) { | ||
| 778 | e->eventbit = SS_READY; | ||
| 779 | reg |= e->regbit = 0; //?? | ||
| 780 | e++; | ||
| 781 | } | ||
| 782 | } | ||
| 783 | |||
| 784 | e->regbit = 0; /* terminate list */ | ||
| 785 | |||
| 786 | /* | ||
| 787 | * Clear the status changed . | ||
| 788 | * Port A and Port B share the same port. | ||
| 789 | * Writing ones will clear the bits. | ||
| 790 | */ | ||
| 791 | |||
| 792 | out_be32(&pcmcia->pcmc_pscr, reg); | ||
| 793 | |||
| 794 | /* | ||
| 795 | * Write the mask. | ||
| 796 | * Port A and Port B share the same port. | ||
| 797 | * Need for read-modify-write. | ||
| 798 | * Ones will enable the interrupt. | ||
| 799 | */ | ||
| 800 | |||
| 801 | reg |= | ||
| 802 | in_be32(&pcmcia-> | ||
| 803 | pcmc_per) & (M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1)); | ||
| 804 | out_be32(&pcmcia->pcmc_per, reg); | ||
| 805 | |||
| 806 | spin_unlock_irqrestore(&events_lock, flags); | ||
| 807 | |||
| 808 | /* copy the struct and modify the copy */ | ||
| 809 | |||
| 810 | s->state = *state; | ||
| 811 | |||
| 812 | return 0; | ||
| 813 | } | ||
| 814 | |||
| 815 | static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io) | ||
| 816 | { | ||
| 817 | int lsock = container_of(sock, struct socket_info, socket)->slot; | ||
| 818 | |||
| 819 | struct socket_info *s = &socket[lsock]; | ||
| 820 | struct pcmcia_win *w; | ||
| 821 | unsigned int reg, winnr; | ||
| 822 | pcmconf8xx_t *pcmcia = s->pcmcia; | ||
| 823 | |||
| 824 | #define M8XX_SIZE (io->stop - io->start + 1) | ||
| 825 | #define M8XX_BASE (PCMCIA_IO_WIN_BASE + io->start) | ||
| 826 | |||
| 827 | pr_debug("m8xx_pcmcia: SetIOMap(%d, %d, %#2.2x, %d ns, " | ||
| 828 | "%#4.4llx-%#4.4llx)\n", lsock, io->map, io->flags, | ||
| 829 | io->speed, (unsigned long long)io->start, | ||
| 830 | (unsigned long long)io->stop); | ||
| 831 | |||
| 832 | if ((io->map >= PCMCIA_IO_WIN_NO) || (io->start > 0xffff) | ||
| 833 | || (io->stop > 0xffff) || (io->stop < io->start)) | ||
| 834 | return -EINVAL; | ||
| 835 | |||
| 836 | if ((reg = m8xx_get_graycode(M8XX_SIZE)) == -1) | ||
| 837 | return -EINVAL; | ||
| 838 | |||
| 839 | if (io->flags & MAP_ACTIVE) { | ||
| 840 | |||
| 841 | pr_debug("m8xx_pcmcia: io->flags & MAP_ACTIVE\n"); | ||
| 842 | |||
| 843 | winnr = (PCMCIA_MEM_WIN_NO * PCMCIA_SOCKETS_NO) | ||
| 844 | + (lsock * PCMCIA_IO_WIN_NO) + io->map; | ||
| 845 | |||
| 846 | /* setup registers */ | ||
| 847 | |||
| 848 | w = (void *)&pcmcia->pcmc_pbr0; | ||
| 849 | w += winnr; | ||
| 850 | |||
| 851 | out_be32(&w->or, 0); /* turn off window first */ | ||
| 852 | out_be32(&w->br, M8XX_BASE); | ||
| 853 | |||
| 854 | reg <<= 27; | ||
| 855 | reg |= M8XX_PCMCIA_POR_IO | (lsock << 2); | ||
| 856 | |||
| 857 | reg |= m8xx_get_speed(io->speed, 1, s->bus_freq); | ||
| 858 | |||
| 859 | if (io->flags & MAP_WRPROT) | ||
| 860 | reg |= M8XX_PCMCIA_POR_WRPROT; | ||
| 861 | |||
| 862 | /*if(io->flags & (MAP_16BIT | MAP_AUTOSZ)) */ | ||
| 863 | if (io->flags & MAP_16BIT) | ||
| 864 | reg |= M8XX_PCMCIA_POR_16BIT; | ||
| 865 | |||
| 866 | if (io->flags & MAP_ACTIVE) | ||
| 867 | reg |= M8XX_PCMCIA_POR_VALID; | ||
| 868 | |||
| 869 | out_be32(&w->or, reg); | ||
| 870 | |||
| 871 | pr_debug("m8xx_pcmcia: Socket %u: Mapped io window %u at " | ||
| 872 | "%#8.8x, OR = %#8.8x.\n", lsock, io->map, w->br, w->or); | ||
| 873 | } else { | ||
| 874 | /* shutdown IO window */ | ||
| 875 | winnr = (PCMCIA_MEM_WIN_NO * PCMCIA_SOCKETS_NO) | ||
| 876 | + (lsock * PCMCIA_IO_WIN_NO) + io->map; | ||
| 877 | |||
| 878 | /* setup registers */ | ||
| 879 | |||
| 880 | w = (void *)&pcmcia->pcmc_pbr0; | ||
| 881 | w += winnr; | ||
| 882 | |||
| 883 | out_be32(&w->or, 0); /* turn off window */ | ||
| 884 | out_be32(&w->br, 0); /* turn off base address */ | ||
| 885 | |||
| 886 | pr_debug("m8xx_pcmcia: Socket %u: Unmapped io window %u at " | ||
| 887 | "%#8.8x, OR = %#8.8x.\n", lsock, io->map, w->br, w->or); | ||
| 888 | } | ||
| 889 | |||
| 890 | /* copy the struct and modify the copy */ | ||
| 891 | s->io_win[io->map] = *io; | ||
| 892 | s->io_win[io->map].flags &= (MAP_WRPROT | MAP_16BIT | MAP_ACTIVE); | ||
| 893 | pr_debug("m8xx_pcmcia: SetIOMap exit\n"); | ||
| 894 | |||
| 895 | return 0; | ||
| 896 | } | ||
| 897 | |||
| 898 | static int m8xx_set_mem_map(struct pcmcia_socket *sock, | ||
| 899 | struct pccard_mem_map *mem) | ||
| 900 | { | ||
| 901 | int lsock = container_of(sock, struct socket_info, socket)->slot; | ||
| 902 | struct socket_info *s = &socket[lsock]; | ||
| 903 | struct pcmcia_win *w; | ||
| 904 | struct pccard_mem_map *old; | ||
| 905 | unsigned int reg, winnr; | ||
| 906 | pcmconf8xx_t *pcmcia = s->pcmcia; | ||
| 907 | |||
| 908 | pr_debug("m8xx_pcmcia: SetMemMap(%d, %d, %#2.2x, %d ns, " | ||
| 909 | "%#5.5llx, %#5.5x)\n", lsock, mem->map, mem->flags, | ||
| 910 | mem->speed, (unsigned long long)mem->static_start, | ||
| 911 | mem->card_start); | ||
| 912 | |||
| 913 | if ((mem->map >= PCMCIA_MEM_WIN_NO) | ||
| 914 | // || ((mem->s) >= PCMCIA_MEM_WIN_SIZE) | ||
| 915 | || (mem->card_start >= 0x04000000) | ||
| 916 | || (mem->static_start & 0xfff) /* 4KByte resolution */ | ||
| 917 | ||(mem->card_start & 0xfff)) | ||
| 918 | return -EINVAL; | ||
| 919 | |||
| 920 | if ((reg = m8xx_get_graycode(PCMCIA_MEM_WIN_SIZE)) == -1) { | ||
| 921 | printk("Cannot set size to 0x%08x.\n", PCMCIA_MEM_WIN_SIZE); | ||
| 922 | return -EINVAL; | ||
| 923 | } | ||
| 924 | reg <<= 27; | ||
| 925 | |||
| 926 | winnr = (lsock * PCMCIA_MEM_WIN_NO) + mem->map; | ||
| 927 | |||
| 928 | /* Setup the window in the pcmcia controller */ | ||
| 929 | |||
| 930 | w = (void *)&pcmcia->pcmc_pbr0; | ||
| 931 | w += winnr; | ||
| 932 | |||
| 933 | reg |= lsock << 2; | ||
| 934 | |||
| 935 | reg |= m8xx_get_speed(mem->speed, 0, s->bus_freq); | ||
| 936 | |||
| 937 | if (mem->flags & MAP_ATTRIB) | ||
| 938 | reg |= M8XX_PCMCIA_POR_ATTRMEM; | ||
| 939 | |||
| 940 | if (mem->flags & MAP_WRPROT) | ||
| 941 | reg |= M8XX_PCMCIA_POR_WRPROT; | ||
| 942 | |||
| 943 | if (mem->flags & MAP_16BIT) | ||
| 944 | reg |= M8XX_PCMCIA_POR_16BIT; | ||
| 945 | |||
| 946 | if (mem->flags & MAP_ACTIVE) | ||
| 947 | reg |= M8XX_PCMCIA_POR_VALID; | ||
| 948 | |||
| 949 | out_be32(&w->or, reg); | ||
| 950 | |||
| 951 | pr_debug("m8xx_pcmcia: Socket %u: Mapped memory window %u at %#8.8x, " | ||
| 952 | "OR = %#8.8x.\n", lsock, mem->map, w->br, w->or); | ||
| 953 | |||
| 954 | if (mem->flags & MAP_ACTIVE) { | ||
| 955 | /* get the new base address */ | ||
| 956 | mem->static_start = PCMCIA_MEM_WIN_BASE + | ||
| 957 | (PCMCIA_MEM_WIN_SIZE * winnr) | ||
| 958 | + mem->card_start; | ||
| 959 | } | ||
| 960 | |||
| 961 | pr_debug("m8xx_pcmcia: SetMemMap(%d, %d, %#2.2x, %d ns, " | ||
| 962 | "%#5.5llx, %#5.5x)\n", lsock, mem->map, mem->flags, | ||
| 963 | mem->speed, (unsigned long long)mem->static_start, | ||
| 964 | mem->card_start); | ||
| 965 | |||
| 966 | /* copy the struct and modify the copy */ | ||
| 967 | |||
| 968 | old = &s->mem_win[mem->map]; | ||
| 969 | |||
| 970 | *old = *mem; | ||
| 971 | old->flags &= (MAP_ATTRIB | MAP_WRPROT | MAP_16BIT | MAP_ACTIVE); | ||
| 972 | |||
| 973 | return 0; | ||
| 974 | } | ||
| 975 | |||
| 976 | static int m8xx_sock_init(struct pcmcia_socket *sock) | ||
| 977 | { | ||
| 978 | int i; | ||
| 979 | pccard_io_map io = { 0, 0, 0, 0, 1 }; | ||
| 980 | pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 }; | ||
| 981 | |||
| 982 | pr_debug("m8xx_pcmcia: sock_init(%d)\n", s); | ||
| 983 | |||
| 984 | m8xx_set_socket(sock, &dead_socket); | ||
| 985 | for (i = 0; i < PCMCIA_IO_WIN_NO; i++) { | ||
| 986 | io.map = i; | ||
| 987 | m8xx_set_io_map(sock, &io); | ||
| 988 | } | ||
| 989 | for (i = 0; i < PCMCIA_MEM_WIN_NO; i++) { | ||
| 990 | mem.map = i; | ||
| 991 | m8xx_set_mem_map(sock, &mem); | ||
| 992 | } | ||
| 993 | |||
| 994 | return 0; | ||
| 995 | |||
| 996 | } | ||
| 997 | |||
| 998 | static int m8xx_sock_suspend(struct pcmcia_socket *sock) | ||
| 999 | { | ||
| 1000 | return m8xx_set_socket(sock, &dead_socket); | ||
| 1001 | } | ||
| 1002 | |||
| 1003 | static struct pccard_operations m8xx_services = { | ||
| 1004 | .init = m8xx_sock_init, | ||
| 1005 | .suspend = m8xx_sock_suspend, | ||
| 1006 | .get_status = m8xx_get_status, | ||
| 1007 | .set_socket = m8xx_set_socket, | ||
| 1008 | .set_io_map = m8xx_set_io_map, | ||
| 1009 | .set_mem_map = m8xx_set_mem_map, | ||
| 1010 | }; | ||
| 1011 | |||
| 1012 | static int __init m8xx_probe(struct platform_device *ofdev) | ||
| 1013 | { | ||
| 1014 | struct pcmcia_win *w; | ||
| 1015 | unsigned int i, m, hwirq; | ||
| 1016 | pcmconf8xx_t *pcmcia; | ||
| 1017 | int status; | ||
| 1018 | struct device_node *np = ofdev->dev.of_node; | ||
| 1019 | |||
| 1020 | pcmcia_info("%s\n", version); | ||
| 1021 | |||
| 1022 | pcmcia = of_iomap(np, 0); | ||
| 1023 | if (pcmcia == NULL) | ||
| 1024 | return -EINVAL; | ||
| 1025 | |||
| 1026 | pcmcia_schlvl = irq_of_parse_and_map(np, 0); | ||
| 1027 | hwirq = irq_map[pcmcia_schlvl].hwirq; | ||
| 1028 | if (pcmcia_schlvl < 0) { | ||
| 1029 | iounmap(pcmcia); | ||
| 1030 | return -EINVAL; | ||
| 1031 | } | ||
| 1032 | |||
| 1033 | m8xx_pgcrx[0] = &pcmcia->pcmc_pgcra; | ||
| 1034 | m8xx_pgcrx[1] = &pcmcia->pcmc_pgcrb; | ||
| 1035 | |||
| 1036 | pcmcia_info(PCMCIA_BOARD_MSG " using " PCMCIA_SLOT_MSG | ||
| 1037 | " with IRQ %u (%d). \n", pcmcia_schlvl, hwirq); | ||
| 1038 | |||
| 1039 | /* Configure Status change interrupt */ | ||
| 1040 | |||
| 1041 | if (request_irq(pcmcia_schlvl, m8xx_interrupt, IRQF_SHARED, | ||
| 1042 | driver_name, socket)) { | ||
| 1043 | pcmcia_error("Cannot allocate IRQ %u for SCHLVL!\n", | ||
| 1044 | pcmcia_schlvl); | ||
| 1045 | iounmap(pcmcia); | ||
| 1046 | return -1; | ||
| 1047 | } | ||
| 1048 | |||
| 1049 | w = (void *)&pcmcia->pcmc_pbr0; | ||
| 1050 | |||
| 1051 | out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1)); | ||
| 1052 | clrbits32(&pcmcia->pcmc_per, M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1)); | ||
| 1053 | |||
| 1054 | /* connect interrupt and disable CxOE */ | ||
| 1055 | |||
| 1056 | out_be32(M8XX_PGCRX(0), | ||
| 1057 | M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16)); | ||
| 1058 | out_be32(M8XX_PGCRX(1), | ||
| 1059 | M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16)); | ||
| 1060 | |||
| 1061 | /* initialize the fixed memory windows */ | ||
| 1062 | |||
| 1063 | for (i = 0; i < PCMCIA_SOCKETS_NO; i++) { | ||
| 1064 | for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) { | ||
| 1065 | out_be32(&w->br, PCMCIA_MEM_WIN_BASE + | ||
| 1066 | (PCMCIA_MEM_WIN_SIZE | ||
| 1067 | * (m + i * PCMCIA_MEM_WIN_NO))); | ||
| 1068 | |||
| 1069 | out_be32(&w->or, 0); /* set to not valid */ | ||
| 1070 | |||
| 1071 | w++; | ||
| 1072 | } | ||
| 1073 | } | ||
| 1074 | |||
| 1075 | /* turn off voltage */ | ||
| 1076 | voltage_set(0, 0, 0); | ||
| 1077 | voltage_set(1, 0, 0); | ||
| 1078 | |||
| 1079 | /* Enable external hardware */ | ||
| 1080 | hardware_enable(0); | ||
| 1081 | hardware_enable(1); | ||
| 1082 | |||
| 1083 | for (i = 0; i < PCMCIA_SOCKETS_NO; i++) { | ||
| 1084 | socket[i].slot = i; | ||
| 1085 | socket[i].socket.owner = THIS_MODULE; | ||
| 1086 | socket[i].socket.features = | ||
| 1087 | SS_CAP_PCCARD | SS_CAP_MEM_ALIGN | SS_CAP_STATIC_MAP; | ||
| 1088 | socket[i].socket.irq_mask = 0x000; | ||
| 1089 | socket[i].socket.map_size = 0x1000; | ||
| 1090 | socket[i].socket.io_offset = 0; | ||
| 1091 | socket[i].socket.pci_irq = pcmcia_schlvl; | ||
| 1092 | socket[i].socket.ops = &m8xx_services; | ||
| 1093 | socket[i].socket.resource_ops = &pccard_iodyn_ops; | ||
| 1094 | socket[i].socket.cb_dev = NULL; | ||
| 1095 | socket[i].socket.dev.parent = &ofdev->dev; | ||
| 1096 | socket[i].pcmcia = pcmcia; | ||
| 1097 | socket[i].bus_freq = ppc_proc_freq; | ||
| 1098 | socket[i].hwirq = hwirq; | ||
| 1099 | |||
| 1100 | } | ||
| 1101 | |||
| 1102 | for (i = 0; i < PCMCIA_SOCKETS_NO; i++) { | ||
| 1103 | status = pcmcia_register_socket(&socket[i].socket); | ||
| 1104 | if (status < 0) | ||
| 1105 | pcmcia_error("Socket register failed\n"); | ||
| 1106 | } | ||
| 1107 | |||
| 1108 | return 0; | ||
| 1109 | } | ||
| 1110 | |||
| 1111 | static int m8xx_remove(struct platform_device *ofdev) | ||
| 1112 | { | ||
| 1113 | u32 m, i; | ||
| 1114 | struct pcmcia_win *w; | ||
| 1115 | pcmconf8xx_t *pcmcia = socket[0].pcmcia; | ||
| 1116 | |||
| 1117 | for (i = 0; i < PCMCIA_SOCKETS_NO; i++) { | ||
| 1118 | w = (void *)&pcmcia->pcmc_pbr0; | ||
| 1119 | |||
| 1120 | out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(i)); | ||
| 1121 | out_be32(&pcmcia->pcmc_per, | ||
| 1122 | in_be32(&pcmcia->pcmc_per) & ~M8XX_PCMCIA_MASK(i)); | ||
| 1123 | |||
| 1124 | /* turn off interrupt and disable CxOE */ | ||
| 1125 | out_be32(M8XX_PGCRX(i), M8XX_PGCRX_CXOE); | ||
| 1126 | |||
| 1127 | /* turn off memory windows */ | ||
| 1128 | for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) { | ||
| 1129 | out_be32(&w->or, 0); /* set to not valid */ | ||
| 1130 | w++; | ||
| 1131 | } | ||
| 1132 | |||
| 1133 | /* turn off voltage */ | ||
| 1134 | voltage_set(i, 0, 0); | ||
| 1135 | |||
| 1136 | /* disable external hardware */ | ||
| 1137 | hardware_disable(i); | ||
| 1138 | } | ||
| 1139 | for (i = 0; i < PCMCIA_SOCKETS_NO; i++) | ||
| 1140 | pcmcia_unregister_socket(&socket[i].socket); | ||
| 1141 | iounmap(pcmcia); | ||
| 1142 | |||
| 1143 | free_irq(pcmcia_schlvl, NULL); | ||
| 1144 | |||
| 1145 | return 0; | ||
| 1146 | } | ||
| 1147 | |||
| 1148 | static const struct of_device_id m8xx_pcmcia_match[] = { | ||
| 1149 | { | ||
| 1150 | .type = "pcmcia", | ||
| 1151 | .compatible = "fsl,pq-pcmcia", | ||
| 1152 | }, | ||
| 1153 | {}, | ||
| 1154 | }; | ||
| 1155 | |||
| 1156 | MODULE_DEVICE_TABLE(of, m8xx_pcmcia_match); | ||
| 1157 | |||
| 1158 | static struct platform_driver m8xx_pcmcia_driver = { | ||
| 1159 | .driver = { | ||
| 1160 | .name = driver_name, | ||
| 1161 | .owner = THIS_MODULE, | ||
| 1162 | .of_match_table = m8xx_pcmcia_match, | ||
| 1163 | }, | ||
| 1164 | .probe = m8xx_probe, | ||
| 1165 | .remove = m8xx_remove, | ||
| 1166 | }; | ||
| 1167 | |||
| 1168 | module_platform_driver(m8xx_pcmcia_driver); | ||
diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile index 72bfabc8629e..50e30bc75e85 100644 --- a/drivers/vfio/Makefile +++ b/drivers/vfio/Makefile | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | obj-$(CONFIG_VFIO) += vfio.o | 1 | obj-$(CONFIG_VFIO) += vfio.o |
| 2 | obj-$(CONFIG_VFIO_IOMMU_TYPE1) += vfio_iommu_type1.o | 2 | obj-$(CONFIG_VFIO_IOMMU_TYPE1) += vfio_iommu_type1.o |
| 3 | obj-$(CONFIG_VFIO_IOMMU_SPAPR_TCE) += vfio_iommu_spapr_tce.o | 3 | obj-$(CONFIG_VFIO_IOMMU_SPAPR_TCE) += vfio_iommu_spapr_tce.o |
| 4 | obj-$(CONFIG_EEH) += vfio_spapr_eeh.o | ||
| 4 | obj-$(CONFIG_VFIO_PCI) += pci/ | 5 | obj-$(CONFIG_VFIO_PCI) += pci/ |
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index 010e0f8b8e4f..e2ee80f36e3e 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c | |||
| @@ -157,8 +157,10 @@ static void vfio_pci_release(void *device_data) | |||
| 157 | { | 157 | { |
| 158 | struct vfio_pci_device *vdev = device_data; | 158 | struct vfio_pci_device *vdev = device_data; |
| 159 | 159 | ||
| 160 | if (atomic_dec_and_test(&vdev->refcnt)) | 160 | if (atomic_dec_and_test(&vdev->refcnt)) { |
| 161 | vfio_spapr_pci_eeh_release(vdev->pdev); | ||
| 161 | vfio_pci_disable(vdev); | 162 | vfio_pci_disable(vdev); |
| 163 | } | ||
| 162 | 164 | ||
| 163 | module_put(THIS_MODULE); | 165 | module_put(THIS_MODULE); |
| 164 | } | 166 | } |
| @@ -166,19 +168,27 @@ static void vfio_pci_release(void *device_data) | |||
| 166 | static int vfio_pci_open(void *device_data) | 168 | static int vfio_pci_open(void *device_data) |
| 167 | { | 169 | { |
| 168 | struct vfio_pci_device *vdev = device_data; | 170 | struct vfio_pci_device *vdev = device_data; |
| 171 | int ret; | ||
| 169 | 172 | ||
| 170 | if (!try_module_get(THIS_MODULE)) | 173 | if (!try_module_get(THIS_MODULE)) |
| 171 | return -ENODEV; | 174 | return -ENODEV; |
| 172 | 175 | ||
| 173 | if (atomic_inc_return(&vdev->refcnt) == 1) { | 176 | if (atomic_inc_return(&vdev->refcnt) == 1) { |
| 174 | int ret = vfio_pci_enable(vdev); | 177 | ret = vfio_pci_enable(vdev); |
| 178 | if (ret) | ||
| 179 | goto error; | ||
| 180 | |||
| 181 | ret = vfio_spapr_pci_eeh_open(vdev->pdev); | ||
| 175 | if (ret) { | 182 | if (ret) { |
| 176 | module_put(THIS_MODULE); | 183 | vfio_pci_disable(vdev); |
| 177 | return ret; | 184 | goto error; |
| 178 | } | 185 | } |
| 179 | } | 186 | } |
| 180 | 187 | ||
| 181 | return 0; | 188 | return 0; |
| 189 | error: | ||
| 190 | module_put(THIS_MODULE); | ||
| 191 | return ret; | ||
| 182 | } | 192 | } |
| 183 | 193 | ||
| 184 | static int vfio_pci_get_irq_count(struct vfio_pci_device *vdev, int irq_type) | 194 | static int vfio_pci_get_irq_count(struct vfio_pci_device *vdev, int irq_type) |
diff --git a/drivers/vfio/vfio_iommu_spapr_tce.c b/drivers/vfio/vfio_iommu_spapr_tce.c index a84788ba662c..730b4ef3e0cc 100644 --- a/drivers/vfio/vfio_iommu_spapr_tce.c +++ b/drivers/vfio/vfio_iommu_spapr_tce.c | |||
| @@ -156,7 +156,16 @@ static long tce_iommu_ioctl(void *iommu_data, | |||
| 156 | 156 | ||
| 157 | switch (cmd) { | 157 | switch (cmd) { |
| 158 | case VFIO_CHECK_EXTENSION: | 158 | case VFIO_CHECK_EXTENSION: |
| 159 | return (arg == VFIO_SPAPR_TCE_IOMMU) ? 1 : 0; | 159 | switch (arg) { |
| 160 | case VFIO_SPAPR_TCE_IOMMU: | ||
| 161 | ret = 1; | ||
| 162 | break; | ||
| 163 | default: | ||
| 164 | ret = vfio_spapr_iommu_eeh_ioctl(NULL, cmd, arg); | ||
| 165 | break; | ||
| 166 | } | ||
| 167 | |||
| 168 | return (ret < 0) ? 0 : ret; | ||
| 160 | 169 | ||
| 161 | case VFIO_IOMMU_SPAPR_TCE_GET_INFO: { | 170 | case VFIO_IOMMU_SPAPR_TCE_GET_INFO: { |
| 162 | struct vfio_iommu_spapr_tce_info info; | 171 | struct vfio_iommu_spapr_tce_info info; |
| @@ -283,6 +292,12 @@ static long tce_iommu_ioctl(void *iommu_data, | |||
| 283 | tce_iommu_disable(container); | 292 | tce_iommu_disable(container); |
| 284 | mutex_unlock(&container->lock); | 293 | mutex_unlock(&container->lock); |
| 285 | return 0; | 294 | return 0; |
| 295 | case VFIO_EEH_PE_OP: | ||
| 296 | if (!container->tbl || !container->tbl->it_group) | ||
| 297 | return -ENODEV; | ||
| 298 | |||
| 299 | return vfio_spapr_iommu_eeh_ioctl(container->tbl->it_group, | ||
| 300 | cmd, arg); | ||
| 286 | } | 301 | } |
| 287 | 302 | ||
| 288 | return -ENOTTY; | 303 | return -ENOTTY; |
diff --git a/drivers/vfio/vfio_spapr_eeh.c b/drivers/vfio/vfio_spapr_eeh.c new file mode 100644 index 000000000000..f834b4ce1431 --- /dev/null +++ b/drivers/vfio/vfio_spapr_eeh.c | |||
| @@ -0,0 +1,87 @@ | |||
| 1 | /* | ||
| 2 | * EEH functionality support for VFIO devices. The feature is only | ||
| 3 | * available on sPAPR compatible platforms. | ||
| 4 | * | ||
| 5 | * Copyright Gavin Shan, IBM Corporation 2014. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/uaccess.h> | ||
| 13 | #include <linux/vfio.h> | ||
| 14 | #include <asm/eeh.h> | ||
| 15 | |||
| 16 | /* We might build address mapping here for "fast" path later */ | ||
| 17 | int vfio_spapr_pci_eeh_open(struct pci_dev *pdev) | ||
| 18 | { | ||
| 19 | return eeh_dev_open(pdev); | ||
| 20 | } | ||
| 21 | |||
| 22 | void vfio_spapr_pci_eeh_release(struct pci_dev *pdev) | ||
| 23 | { | ||
| 24 | eeh_dev_release(pdev); | ||
| 25 | } | ||
| 26 | |||
| 27 | long vfio_spapr_iommu_eeh_ioctl(struct iommu_group *group, | ||
| 28 | unsigned int cmd, unsigned long arg) | ||
| 29 | { | ||
| 30 | struct eeh_pe *pe; | ||
| 31 | struct vfio_eeh_pe_op op; | ||
| 32 | unsigned long minsz; | ||
| 33 | long ret = -EINVAL; | ||
| 34 | |||
| 35 | switch (cmd) { | ||
| 36 | case VFIO_CHECK_EXTENSION: | ||
| 37 | if (arg == VFIO_EEH) | ||
| 38 | ret = eeh_enabled() ? 1 : 0; | ||
| 39 | else | ||
| 40 | ret = 0; | ||
| 41 | break; | ||
| 42 | case VFIO_EEH_PE_OP: | ||
| 43 | pe = eeh_iommu_group_to_pe(group); | ||
| 44 | if (!pe) | ||
| 45 | return -ENODEV; | ||
| 46 | |||
| 47 | minsz = offsetofend(struct vfio_eeh_pe_op, op); | ||
| 48 | if (copy_from_user(&op, (void __user *)arg, minsz)) | ||
| 49 | return -EFAULT; | ||
| 50 | if (op.argsz < minsz || op.flags) | ||
| 51 | return -EINVAL; | ||
| 52 | |||
| 53 | switch (op.op) { | ||
| 54 | case VFIO_EEH_PE_DISABLE: | ||
| 55 | ret = eeh_pe_set_option(pe, EEH_OPT_DISABLE); | ||
| 56 | break; | ||
| 57 | case VFIO_EEH_PE_ENABLE: | ||
| 58 | ret = eeh_pe_set_option(pe, EEH_OPT_ENABLE); | ||
| 59 | break; | ||
| 60 | case VFIO_EEH_PE_UNFREEZE_IO: | ||
| 61 | ret = eeh_pe_set_option(pe, EEH_OPT_THAW_MMIO); | ||
| 62 | break; | ||
| 63 | case VFIO_EEH_PE_UNFREEZE_DMA: | ||
| 64 | ret = eeh_pe_set_option(pe, EEH_OPT_THAW_DMA); | ||
| 65 | break; | ||
| 66 | case VFIO_EEH_PE_GET_STATE: | ||
| 67 | ret = eeh_pe_get_state(pe); | ||
| 68 | break; | ||
| 69 | case VFIO_EEH_PE_RESET_DEACTIVATE: | ||
| 70 | ret = eeh_pe_reset(pe, EEH_RESET_DEACTIVATE); | ||
| 71 | break; | ||
| 72 | case VFIO_EEH_PE_RESET_HOT: | ||
| 73 | ret = eeh_pe_reset(pe, EEH_RESET_HOT); | ||
| 74 | break; | ||
| 75 | case VFIO_EEH_PE_RESET_FUNDAMENTAL: | ||
| 76 | ret = eeh_pe_reset(pe, EEH_RESET_FUNDAMENTAL); | ||
| 77 | break; | ||
| 78 | case VFIO_EEH_PE_CONFIGURE: | ||
| 79 | ret = eeh_pe_configure(pe); | ||
| 80 | break; | ||
| 81 | default: | ||
| 82 | ret = -EINVAL; | ||
| 83 | } | ||
| 84 | } | ||
| 85 | |||
| 86 | return ret; | ||
| 87 | } | ||
diff --git a/include/linux/vfio.h b/include/linux/vfio.h index 8ec980b5e3af..25a0fbd4b998 100644 --- a/include/linux/vfio.h +++ b/include/linux/vfio.h | |||
| @@ -98,4 +98,27 @@ extern int vfio_external_user_iommu_id(struct vfio_group *group); | |||
| 98 | extern long vfio_external_check_extension(struct vfio_group *group, | 98 | extern long vfio_external_check_extension(struct vfio_group *group, |
| 99 | unsigned long arg); | 99 | unsigned long arg); |
| 100 | 100 | ||
| 101 | #ifdef CONFIG_EEH | ||
| 102 | extern int vfio_spapr_pci_eeh_open(struct pci_dev *pdev); | ||
| 103 | extern void vfio_spapr_pci_eeh_release(struct pci_dev *pdev); | ||
| 104 | extern long vfio_spapr_iommu_eeh_ioctl(struct iommu_group *group, | ||
| 105 | unsigned int cmd, | ||
| 106 | unsigned long arg); | ||
| 107 | #else | ||
| 108 | static inline int vfio_spapr_pci_eeh_open(struct pci_dev *pdev) | ||
| 109 | { | ||
| 110 | return 0; | ||
| 111 | } | ||
| 112 | |||
| 113 | static inline void vfio_spapr_pci_eeh_release(struct pci_dev *pdev) | ||
| 114 | { | ||
| 115 | } | ||
| 116 | |||
| 117 | static inline long vfio_spapr_iommu_eeh_ioctl(struct iommu_group *group, | ||
| 118 | unsigned int cmd, | ||
| 119 | unsigned long arg) | ||
| 120 | { | ||
| 121 | return -ENOTTY; | ||
| 122 | } | ||
| 123 | #endif /* CONFIG_EEH */ | ||
| 101 | #endif /* VFIO_H */ | 124 | #endif /* VFIO_H */ |
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h index cb9023d4f063..6612974c64bf 100644 --- a/include/uapi/linux/vfio.h +++ b/include/uapi/linux/vfio.h | |||
| @@ -30,6 +30,9 @@ | |||
| 30 | */ | 30 | */ |
| 31 | #define VFIO_DMA_CC_IOMMU 4 | 31 | #define VFIO_DMA_CC_IOMMU 4 |
| 32 | 32 | ||
| 33 | /* Check if EEH is supported */ | ||
| 34 | #define VFIO_EEH 5 | ||
| 35 | |||
| 33 | /* | 36 | /* |
| 34 | * The IOCTL interface is designed for extensibility by embedding the | 37 | * The IOCTL interface is designed for extensibility by embedding the |
| 35 | * structure length (argsz) and flags into structures passed between | 38 | * structure length (argsz) and flags into structures passed between |
| @@ -455,6 +458,37 @@ struct vfio_iommu_spapr_tce_info { | |||
| 455 | 458 | ||
| 456 | #define VFIO_IOMMU_SPAPR_TCE_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 12) | 459 | #define VFIO_IOMMU_SPAPR_TCE_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 12) |
| 457 | 460 | ||
| 461 | /* | ||
| 462 | * EEH PE operation struct provides ways to: | ||
| 463 | * - enable/disable EEH functionality; | ||
| 464 | * - unfreeze IO/DMA for frozen PE; | ||
| 465 | * - read PE state; | ||
| 466 | * - reset PE; | ||
| 467 | * - configure PE. | ||
| 468 | */ | ||
| 469 | struct vfio_eeh_pe_op { | ||
| 470 | __u32 argsz; | ||
| 471 | __u32 flags; | ||
| 472 | __u32 op; | ||
| 473 | }; | ||
| 474 | |||
| 475 | #define VFIO_EEH_PE_DISABLE 0 /* Disable EEH functionality */ | ||
| 476 | #define VFIO_EEH_PE_ENABLE 1 /* Enable EEH functionality */ | ||
| 477 | #define VFIO_EEH_PE_UNFREEZE_IO 2 /* Enable IO for frozen PE */ | ||
| 478 | #define VFIO_EEH_PE_UNFREEZE_DMA 3 /* Enable DMA for frozen PE */ | ||
| 479 | #define VFIO_EEH_PE_GET_STATE 4 /* PE state retrieval */ | ||
| 480 | #define VFIO_EEH_PE_STATE_NORMAL 0 /* PE in functional state */ | ||
| 481 | #define VFIO_EEH_PE_STATE_RESET 1 /* PE reset in progress */ | ||
| 482 | #define VFIO_EEH_PE_STATE_STOPPED 2 /* Stopped DMA and IO */ | ||
| 483 | #define VFIO_EEH_PE_STATE_STOPPED_DMA 4 /* Stopped DMA only */ | ||
| 484 | #define VFIO_EEH_PE_STATE_UNAVAIL 5 /* State unavailable */ | ||
| 485 | #define VFIO_EEH_PE_RESET_DEACTIVATE 5 /* Deassert PE reset */ | ||
| 486 | #define VFIO_EEH_PE_RESET_HOT 6 /* Assert hot reset */ | ||
| 487 | #define VFIO_EEH_PE_RESET_FUNDAMENTAL 7 /* Assert fundamental reset */ | ||
| 488 | #define VFIO_EEH_PE_CONFIGURE 8 /* PE configuration */ | ||
| 489 | |||
| 490 | #define VFIO_EEH_PE_OP _IO(VFIO_TYPE, VFIO_BASE + 21) | ||
| 491 | |||
| 458 | /* ***************************************************************** */ | 492 | /* ***************************************************************** */ |
| 459 | 493 | ||
| 460 | #endif /* _UAPIVFIO_H */ | 494 | #endif /* _UAPIVFIO_H */ |
diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile index 54833a791a44..74a78cedce37 100644 --- a/tools/testing/selftests/powerpc/Makefile +++ b/tools/testing/selftests/powerpc/Makefile | |||
| @@ -17,10 +17,10 @@ TARGETS = pmu copyloops mm tm | |||
| 17 | 17 | ||
| 18 | endif | 18 | endif |
| 19 | 19 | ||
| 20 | all: | 20 | all: $(TARGETS) |
| 21 | @for TARGET in $(TARGETS); do \ | 21 | |
| 22 | $(MAKE) -C $$TARGET all; \ | 22 | $(TARGETS): |
| 23 | done; | 23 | $(MAKE) -k -C $@ all |
| 24 | 24 | ||
| 25 | run_tests: all | 25 | run_tests: all |
| 26 | @for TARGET in $(TARGETS); do \ | 26 | @for TARGET in $(TARGETS); do \ |
| @@ -36,4 +36,4 @@ clean: | |||
| 36 | tags: | 36 | tags: |
| 37 | find . -name '*.c' -o -name '*.h' | xargs ctags | 37 | find . -name '*.c' -o -name '*.h' | xargs ctags |
| 38 | 38 | ||
| 39 | .PHONY: all run_tests clean tags | 39 | .PHONY: all run_tests clean tags $(TARGETS) |
diff --git a/tools/testing/selftests/powerpc/pmu/Makefile b/tools/testing/selftests/powerpc/pmu/Makefile index b9ff0db42c79..c9f4263906a5 100644 --- a/tools/testing/selftests/powerpc/pmu/Makefile +++ b/tools/testing/selftests/powerpc/pmu/Makefile | |||
| @@ -1,10 +1,12 @@ | |||
| 1 | noarg: | 1 | noarg: |
| 2 | $(MAKE) -C ../ | 2 | $(MAKE) -C ../ |
| 3 | 3 | ||
| 4 | PROGS := count_instructions | 4 | PROGS := count_instructions l3_bank_test per_event_excludes |
| 5 | EXTRA_SOURCES := ../harness.c event.c | 5 | EXTRA_SOURCES := ../harness.c event.c lib.c |
| 6 | 6 | ||
| 7 | all: $(PROGS) sub_all | 7 | SUB_TARGETS = ebb |
| 8 | |||
| 9 | all: $(PROGS) $(SUB_TARGETS) | ||
| 8 | 10 | ||
| 9 | $(PROGS): $(EXTRA_SOURCES) | 11 | $(PROGS): $(EXTRA_SOURCES) |
| 10 | 12 | ||
| @@ -20,13 +22,8 @@ run_tests: all sub_run_tests | |||
| 20 | clean: sub_clean | 22 | clean: sub_clean |
| 21 | rm -f $(PROGS) loop.o | 23 | rm -f $(PROGS) loop.o |
| 22 | 24 | ||
| 23 | 25 | $(SUB_TARGETS): | |
| 24 | SUB_TARGETS = ebb | 26 | $(MAKE) -k -C $@ all |
| 25 | |||
| 26 | sub_all: | ||
| 27 | @for TARGET in $(SUB_TARGETS); do \ | ||
| 28 | $(MAKE) -C $$TARGET all; \ | ||
| 29 | done; | ||
| 30 | 27 | ||
| 31 | sub_run_tests: all | 28 | sub_run_tests: all |
| 32 | @for TARGET in $(SUB_TARGETS); do \ | 29 | @for TARGET in $(SUB_TARGETS); do \ |
| @@ -38,4 +35,4 @@ sub_clean: | |||
| 38 | $(MAKE) -C $$TARGET clean; \ | 35 | $(MAKE) -C $$TARGET clean; \ |
| 39 | done; | 36 | done; |
| 40 | 37 | ||
| 41 | .PHONY: all run_tests clean sub_all sub_run_tests sub_clean | 38 | .PHONY: all run_tests clean sub_run_tests sub_clean $(SUB_TARGETS) |
diff --git a/tools/testing/selftests/powerpc/pmu/count_instructions.c b/tools/testing/selftests/powerpc/pmu/count_instructions.c index 312b4f0fd27c..4622117b24c0 100644 --- a/tools/testing/selftests/powerpc/pmu/count_instructions.c +++ b/tools/testing/selftests/powerpc/pmu/count_instructions.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | #include "event.h" | 13 | #include "event.h" |
| 14 | #include "utils.h" | 14 | #include "utils.h" |
| 15 | #include "lib.h" | ||
| 15 | 16 | ||
| 16 | extern void thirty_two_instruction_loop(u64 loops); | 17 | extern void thirty_two_instruction_loop(u64 loops); |
| 17 | 18 | ||
| @@ -90,7 +91,7 @@ static u64 determine_overhead(struct event *events) | |||
| 90 | return overhead; | 91 | return overhead; |
| 91 | } | 92 | } |
| 92 | 93 | ||
| 93 | static int count_instructions(void) | 94 | static int test_body(void) |
| 94 | { | 95 | { |
| 95 | struct event events[2]; | 96 | struct event events[2]; |
| 96 | u64 overhead; | 97 | u64 overhead; |
| @@ -111,17 +112,23 @@ static int count_instructions(void) | |||
| 111 | overhead = determine_overhead(events); | 112 | overhead = determine_overhead(events); |
| 112 | printf("Overhead of null loop: %llu instructions\n", overhead); | 113 | printf("Overhead of null loop: %llu instructions\n", overhead); |
| 113 | 114 | ||
| 114 | /* Run for 1M instructions */ | 115 | /* Run for 1Mi instructions */ |
| 115 | FAIL_IF(do_count_loop(events, 0x100000, overhead, true)); | 116 | FAIL_IF(do_count_loop(events, 1000000, overhead, true)); |
| 117 | |||
| 118 | /* Run for 10Mi instructions */ | ||
| 119 | FAIL_IF(do_count_loop(events, 10000000, overhead, true)); | ||
| 120 | |||
| 121 | /* Run for 100Mi instructions */ | ||
| 122 | FAIL_IF(do_count_loop(events, 100000000, overhead, true)); | ||
| 116 | 123 | ||
| 117 | /* Run for 10M instructions */ | 124 | /* Run for 1Bi instructions */ |
| 118 | FAIL_IF(do_count_loop(events, 0xa00000, overhead, true)); | 125 | FAIL_IF(do_count_loop(events, 1000000000, overhead, true)); |
| 119 | 126 | ||
| 120 | /* Run for 100M instructions */ | 127 | /* Run for 16Bi instructions */ |
| 121 | FAIL_IF(do_count_loop(events, 0x6400000, overhead, true)); | 128 | FAIL_IF(do_count_loop(events, 16000000000, overhead, true)); |
| 122 | 129 | ||
| 123 | /* Run for 1G instructions */ | 130 | /* Run for 64Bi instructions */ |
| 124 | FAIL_IF(do_count_loop(events, 0x40000000, overhead, true)); | 131 | FAIL_IF(do_count_loop(events, 64000000000, overhead, true)); |
| 125 | 132 | ||
| 126 | event_close(&events[0]); | 133 | event_close(&events[0]); |
| 127 | event_close(&events[1]); | 134 | event_close(&events[1]); |
| @@ -129,6 +136,11 @@ static int count_instructions(void) | |||
| 129 | return 0; | 136 | return 0; |
| 130 | } | 137 | } |
| 131 | 138 | ||
| 139 | static int count_instructions(void) | ||
| 140 | { | ||
| 141 | return eat_cpu(test_body); | ||
| 142 | } | ||
| 143 | |||
| 132 | int main(void) | 144 | int main(void) |
| 133 | { | 145 | { |
| 134 | return test_harness(count_instructions, "count_instructions"); | 146 | return test_harness(count_instructions, "count_instructions"); |
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/Makefile b/tools/testing/selftests/powerpc/pmu/ebb/Makefile index edbba2affc2c..3dc4332698cb 100644 --- a/tools/testing/selftests/powerpc/pmu/ebb/Makefile +++ b/tools/testing/selftests/powerpc/pmu/ebb/Makefile | |||
| @@ -13,11 +13,12 @@ PROGS := reg_access_test event_attributes_test cycles_test \ | |||
| 13 | close_clears_pmcc_test instruction_count_test \ | 13 | close_clears_pmcc_test instruction_count_test \ |
| 14 | fork_cleanup_test ebb_on_child_test \ | 14 | fork_cleanup_test ebb_on_child_test \ |
| 15 | ebb_on_willing_child_test back_to_back_ebbs_test \ | 15 | ebb_on_willing_child_test back_to_back_ebbs_test \ |
| 16 | lost_exception_test no_handler_test | 16 | lost_exception_test no_handler_test \ |
| 17 | cycles_with_mmcr2_test | ||
| 17 | 18 | ||
| 18 | all: $(PROGS) | 19 | all: $(PROGS) |
| 19 | 20 | ||
| 20 | $(PROGS): ../../harness.c ../event.c ../lib.c ebb.c ebb_handler.S trace.c | 21 | $(PROGS): ../../harness.c ../event.c ../lib.c ebb.c ebb_handler.S trace.c busy_loop.S |
| 21 | 22 | ||
| 22 | instruction_count_test: ../loop.S | 23 | instruction_count_test: ../loop.S |
| 23 | 24 | ||
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/busy_loop.S b/tools/testing/selftests/powerpc/pmu/ebb/busy_loop.S new file mode 100644 index 000000000000..c7e4093f1cd3 --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/busy_loop.S | |||
| @@ -0,0 +1,271 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2014, Michael Ellerman, IBM Corp. | ||
| 3 | * Licensed under GPLv2. | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <ppc-asm.h> | ||
| 7 | |||
| 8 | .text | ||
| 9 | |||
| 10 | FUNC_START(core_busy_loop) | ||
| 11 | stdu %r1, -168(%r1) | ||
| 12 | std r14, 160(%r1) | ||
| 13 | std r15, 152(%r1) | ||
| 14 | std r16, 144(%r1) | ||
| 15 | std r17, 136(%r1) | ||
| 16 | std r18, 128(%r1) | ||
| 17 | std r19, 120(%r1) | ||
| 18 | std r20, 112(%r1) | ||
| 19 | std r21, 104(%r1) | ||
| 20 | std r22, 96(%r1) | ||
| 21 | std r23, 88(%r1) | ||
| 22 | std r24, 80(%r1) | ||
| 23 | std r25, 72(%r1) | ||
| 24 | std r26, 64(%r1) | ||
| 25 | std r27, 56(%r1) | ||
| 26 | std r28, 48(%r1) | ||
| 27 | std r29, 40(%r1) | ||
| 28 | std r30, 32(%r1) | ||
| 29 | std r31, 24(%r1) | ||
| 30 | |||
| 31 | li r3, 0x3030 | ||
| 32 | std r3, -96(%r1) | ||
| 33 | li r4, 0x4040 | ||
| 34 | std r4, -104(%r1) | ||
| 35 | li r5, 0x5050 | ||
| 36 | std r5, -112(%r1) | ||
| 37 | li r6, 0x6060 | ||
| 38 | std r6, -120(%r1) | ||
| 39 | li r7, 0x7070 | ||
| 40 | std r7, -128(%r1) | ||
| 41 | li r8, 0x0808 | ||
| 42 | std r8, -136(%r1) | ||
| 43 | li r9, 0x0909 | ||
| 44 | std r9, -144(%r1) | ||
| 45 | li r10, 0x1010 | ||
| 46 | std r10, -152(%r1) | ||
| 47 | li r11, 0x1111 | ||
| 48 | std r11, -160(%r1) | ||
| 49 | li r14, 0x1414 | ||
| 50 | std r14, -168(%r1) | ||
| 51 | li r15, 0x1515 | ||
| 52 | std r15, -176(%r1) | ||
| 53 | li r16, 0x1616 | ||
| 54 | std r16, -184(%r1) | ||
| 55 | li r17, 0x1717 | ||
| 56 | std r17, -192(%r1) | ||
| 57 | li r18, 0x1818 | ||
| 58 | std r18, -200(%r1) | ||
| 59 | li r19, 0x1919 | ||
| 60 | std r19, -208(%r1) | ||
| 61 | li r20, 0x2020 | ||
| 62 | std r20, -216(%r1) | ||
| 63 | li r21, 0x2121 | ||
| 64 | std r21, -224(%r1) | ||
| 65 | li r22, 0x2222 | ||
| 66 | std r22, -232(%r1) | ||
| 67 | li r23, 0x2323 | ||
| 68 | std r23, -240(%r1) | ||
| 69 | li r24, 0x2424 | ||
| 70 | std r24, -248(%r1) | ||
| 71 | li r25, 0x2525 | ||
| 72 | std r25, -256(%r1) | ||
| 73 | li r26, 0x2626 | ||
| 74 | std r26, -264(%r1) | ||
| 75 | li r27, 0x2727 | ||
| 76 | std r27, -272(%r1) | ||
| 77 | li r28, 0x2828 | ||
| 78 | std r28, -280(%r1) | ||
| 79 | li r29, 0x2929 | ||
| 80 | std r29, -288(%r1) | ||
| 81 | li r30, 0x3030 | ||
| 82 | li r31, 0x3131 | ||
| 83 | |||
| 84 | li r3, 0 | ||
| 85 | 0: addi r3, r3, 1 | ||
| 86 | cmpwi r3, 100 | ||
| 87 | blt 0b | ||
| 88 | |||
| 89 | /* Return 1 (fail) unless we get through all the checks */ | ||
| 90 | li r3, 1 | ||
| 91 | |||
| 92 | /* Check none of our registers have been corrupted */ | ||
| 93 | cmpwi r4, 0x4040 | ||
| 94 | bne 1f | ||
| 95 | cmpwi r5, 0x5050 | ||
| 96 | bne 1f | ||
| 97 | cmpwi r6, 0x6060 | ||
| 98 | bne 1f | ||
| 99 | cmpwi r7, 0x7070 | ||
| 100 | bne 1f | ||
| 101 | cmpwi r8, 0x0808 | ||
| 102 | bne 1f | ||
| 103 | cmpwi r9, 0x0909 | ||
| 104 | bne 1f | ||
| 105 | cmpwi r10, 0x1010 | ||
| 106 | bne 1f | ||
| 107 | cmpwi r11, 0x1111 | ||
| 108 | bne 1f | ||
| 109 | cmpwi r14, 0x1414 | ||
| 110 | bne 1f | ||
| 111 | cmpwi r15, 0x1515 | ||
| 112 | bne 1f | ||
| 113 | cmpwi r16, 0x1616 | ||
| 114 | bne 1f | ||
| 115 | cmpwi r17, 0x1717 | ||
| 116 | bne 1f | ||
| 117 | cmpwi r18, 0x1818 | ||
| 118 | bne 1f | ||
| 119 | cmpwi r19, 0x1919 | ||
| 120 | bne 1f | ||
| 121 | cmpwi r20, 0x2020 | ||
| 122 | bne 1f | ||
| 123 | cmpwi r21, 0x2121 | ||
| 124 | bne 1f | ||
| 125 | cmpwi r22, 0x2222 | ||
| 126 | bne 1f | ||
| 127 | cmpwi r23, 0x2323 | ||
| 128 | bne 1f | ||
| 129 | cmpwi r24, 0x2424 | ||
| 130 | bne 1f | ||
| 131 | cmpwi r25, 0x2525 | ||
| 132 | bne 1f | ||
| 133 | cmpwi r26, 0x2626 | ||
| 134 | bne 1f | ||
| 135 | cmpwi r27, 0x2727 | ||
| 136 | bne 1f | ||
| 137 | cmpwi r28, 0x2828 | ||
| 138 | bne 1f | ||
| 139 | cmpwi r29, 0x2929 | ||
| 140 | bne 1f | ||
| 141 | cmpwi r30, 0x3030 | ||
| 142 | bne 1f | ||
| 143 | cmpwi r31, 0x3131 | ||
| 144 | bne 1f | ||
| 145 | |||
| 146 | /* Load junk into all our registers before we reload them from the stack. */ | ||
| 147 | li r3, 0xde | ||
| 148 | li r4, 0xad | ||
| 149 | li r5, 0xbe | ||
| 150 | li r6, 0xef | ||
| 151 | li r7, 0xde | ||
| 152 | li r8, 0xad | ||
| 153 | li r9, 0xbe | ||
| 154 | li r10, 0xef | ||
| 155 | li r11, 0xde | ||
| 156 | li r14, 0xad | ||
| 157 | li r15, 0xbe | ||
| 158 | li r16, 0xef | ||
| 159 | li r17, 0xde | ||
| 160 | li r18, 0xad | ||
| 161 | li r19, 0xbe | ||
| 162 | li r20, 0xef | ||
| 163 | li r21, 0xde | ||
| 164 | li r22, 0xad | ||
| 165 | li r23, 0xbe | ||
| 166 | li r24, 0xef | ||
| 167 | li r25, 0xde | ||
| 168 | li r26, 0xad | ||
| 169 | li r27, 0xbe | ||
| 170 | li r28, 0xef | ||
| 171 | li r29, 0xdd | ||
| 172 | |||
| 173 | ld r3, -96(%r1) | ||
| 174 | cmpwi r3, 0x3030 | ||
| 175 | bne 1f | ||
| 176 | ld r4, -104(%r1) | ||
| 177 | cmpwi r4, 0x4040 | ||
| 178 | bne 1f | ||
| 179 | ld r5, -112(%r1) | ||
| 180 | cmpwi r5, 0x5050 | ||
| 181 | bne 1f | ||
| 182 | ld r6, -120(%r1) | ||
| 183 | cmpwi r6, 0x6060 | ||
| 184 | bne 1f | ||
| 185 | ld r7, -128(%r1) | ||
| 186 | cmpwi r7, 0x7070 | ||
| 187 | bne 1f | ||
| 188 | ld r8, -136(%r1) | ||
| 189 | cmpwi r8, 0x0808 | ||
| 190 | bne 1f | ||
| 191 | ld r9, -144(%r1) | ||
| 192 | cmpwi r9, 0x0909 | ||
| 193 | bne 1f | ||
| 194 | ld r10, -152(%r1) | ||
| 195 | cmpwi r10, 0x1010 | ||
| 196 | bne 1f | ||
| 197 | ld r11, -160(%r1) | ||
| 198 | cmpwi r11, 0x1111 | ||
| 199 | bne 1f | ||
| 200 | ld r14, -168(%r1) | ||
| 201 | cmpwi r14, 0x1414 | ||
| 202 | bne 1f | ||
| 203 | ld r15, -176(%r1) | ||
| 204 | cmpwi r15, 0x1515 | ||
| 205 | bne 1f | ||
| 206 | ld r16, -184(%r1) | ||
| 207 | cmpwi r16, 0x1616 | ||
| 208 | bne 1f | ||
| 209 | ld r17, -192(%r1) | ||
| 210 | cmpwi r17, 0x1717 | ||
| 211 | bne 1f | ||
| 212 | ld r18, -200(%r1) | ||
| 213 | cmpwi r18, 0x1818 | ||
| 214 | bne 1f | ||
| 215 | ld r19, -208(%r1) | ||
| 216 | cmpwi r19, 0x1919 | ||
| 217 | bne 1f | ||
| 218 | ld r20, -216(%r1) | ||
| 219 | cmpwi r20, 0x2020 | ||
| 220 | bne 1f | ||
| 221 | ld r21, -224(%r1) | ||
| 222 | cmpwi r21, 0x2121 | ||
| 223 | bne 1f | ||
| 224 | ld r22, -232(%r1) | ||
| 225 | cmpwi r22, 0x2222 | ||
| 226 | bne 1f | ||
| 227 | ld r23, -240(%r1) | ||
| 228 | cmpwi r23, 0x2323 | ||
| 229 | bne 1f | ||
| 230 | ld r24, -248(%r1) | ||
| 231 | cmpwi r24, 0x2424 | ||
| 232 | bne 1f | ||
| 233 | ld r25, -256(%r1) | ||
| 234 | cmpwi r25, 0x2525 | ||
| 235 | bne 1f | ||
| 236 | ld r26, -264(%r1) | ||
| 237 | cmpwi r26, 0x2626 | ||
| 238 | bne 1f | ||
| 239 | ld r27, -272(%r1) | ||
| 240 | cmpwi r27, 0x2727 | ||
| 241 | bne 1f | ||
| 242 | ld r28, -280(%r1) | ||
| 243 | cmpwi r28, 0x2828 | ||
| 244 | bne 1f | ||
| 245 | ld r29, -288(%r1) | ||
| 246 | cmpwi r29, 0x2929 | ||
| 247 | bne 1f | ||
| 248 | |||
| 249 | /* Load 0 (success) to return */ | ||
| 250 | li r3, 0 | ||
| 251 | |||
| 252 | 1: ld r14, 160(%r1) | ||
| 253 | ld r15, 152(%r1) | ||
| 254 | ld r16, 144(%r1) | ||
| 255 | ld r17, 136(%r1) | ||
| 256 | ld r18, 128(%r1) | ||
| 257 | ld r19, 120(%r1) | ||
| 258 | ld r20, 112(%r1) | ||
| 259 | ld r21, 104(%r1) | ||
| 260 | ld r22, 96(%r1) | ||
| 261 | ld r23, 88(%r1) | ||
| 262 | ld r24, 80(%r1) | ||
| 263 | ld r25, 72(%r1) | ||
| 264 | ld r26, 64(%r1) | ||
| 265 | ld r27, 56(%r1) | ||
| 266 | ld r28, 48(%r1) | ||
| 267 | ld r29, 40(%r1) | ||
| 268 | ld r30, 32(%r1) | ||
| 269 | ld r31, 24(%r1) | ||
| 270 | addi %r1, %r1, 168 | ||
| 271 | blr | ||
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/cycles_with_mmcr2_test.c b/tools/testing/selftests/powerpc/pmu/ebb/cycles_with_mmcr2_test.c new file mode 100644 index 000000000000..d43029b0800c --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/cycles_with_mmcr2_test.c | |||
| @@ -0,0 +1,91 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2014, Michael Ellerman, IBM Corp. | ||
| 3 | * Licensed under GPLv2. | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <stdio.h> | ||
| 7 | #include <stdlib.h> | ||
| 8 | #include <stdbool.h> | ||
| 9 | |||
| 10 | #include "ebb.h" | ||
| 11 | |||
| 12 | |||
| 13 | /* | ||
| 14 | * Test of counting cycles while manipulating the user accessible bits in MMCR2. | ||
| 15 | */ | ||
| 16 | |||
| 17 | /* We use two values because the first freezes PMC1 and so we would get no EBBs */ | ||
| 18 | #define MMCR2_EXPECTED_1 0x4020100804020000UL /* (FC1P|FC2P|FC3P|FC4P|FC5P|FC6P) */ | ||
| 19 | #define MMCR2_EXPECTED_2 0x0020100804020000UL /* ( FC2P|FC3P|FC4P|FC5P|FC6P) */ | ||
| 20 | |||
| 21 | |||
| 22 | int cycles_with_mmcr2(void) | ||
| 23 | { | ||
| 24 | struct event event; | ||
| 25 | uint64_t val, expected[2], actual; | ||
| 26 | int i; | ||
| 27 | bool bad_mmcr2; | ||
| 28 | |||
| 29 | event_init_named(&event, 0x1001e, "cycles"); | ||
| 30 | event_leader_ebb_init(&event); | ||
| 31 | |||
| 32 | event.attr.exclude_kernel = 1; | ||
| 33 | event.attr.exclude_hv = 1; | ||
| 34 | event.attr.exclude_idle = 1; | ||
| 35 | |||
| 36 | FAIL_IF(event_open(&event)); | ||
| 37 | |||
| 38 | ebb_enable_pmc_counting(1); | ||
| 39 | setup_ebb_handler(standard_ebb_callee); | ||
| 40 | ebb_global_enable(); | ||
| 41 | |||
| 42 | FAIL_IF(ebb_event_enable(&event)); | ||
| 43 | |||
| 44 | mtspr(SPRN_PMC1, pmc_sample_period(sample_period)); | ||
| 45 | |||
| 46 | /* XXX Set of MMCR2 must be after enable */ | ||
| 47 | expected[0] = MMCR2_EXPECTED_1; | ||
| 48 | expected[1] = MMCR2_EXPECTED_2; | ||
| 49 | i = 0; | ||
| 50 | bad_mmcr2 = false; | ||
| 51 | |||
| 52 | /* Make sure we loop until we take at least one EBB */ | ||
| 53 | while ((ebb_state.stats.ebb_count < 20 && !bad_mmcr2) || | ||
| 54 | ebb_state.stats.ebb_count < 1) | ||
| 55 | { | ||
| 56 | mtspr(SPRN_MMCR2, expected[i % 2]); | ||
| 57 | |||
| 58 | FAIL_IF(core_busy_loop()); | ||
| 59 | |||
| 60 | val = mfspr(SPRN_MMCR2); | ||
| 61 | if (val != expected[i % 2]) { | ||
| 62 | bad_mmcr2 = true; | ||
| 63 | actual = val; | ||
| 64 | } | ||
| 65 | |||
| 66 | i++; | ||
| 67 | } | ||
| 68 | |||
| 69 | ebb_global_disable(); | ||
| 70 | ebb_freeze_pmcs(); | ||
| 71 | |||
| 72 | count_pmc(1, sample_period); | ||
| 73 | |||
| 74 | dump_ebb_state(); | ||
| 75 | |||
| 76 | event_close(&event); | ||
| 77 | |||
| 78 | FAIL_IF(ebb_state.stats.ebb_count == 0); | ||
| 79 | |||
| 80 | if (bad_mmcr2) | ||
| 81 | printf("Bad MMCR2 value seen is 0x%lx\n", actual); | ||
| 82 | |||
| 83 | FAIL_IF(bad_mmcr2); | ||
| 84 | |||
| 85 | return 0; | ||
| 86 | } | ||
| 87 | |||
| 88 | int main(void) | ||
| 89 | { | ||
| 90 | return test_harness(cycles_with_mmcr2, "cycles_with_mmcr2"); | ||
| 91 | } | ||
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/ebb.c b/tools/testing/selftests/powerpc/pmu/ebb/ebb.c index 1b46be94b64c..d7a72ce696b5 100644 --- a/tools/testing/selftests/powerpc/pmu/ebb/ebb.c +++ b/tools/testing/selftests/powerpc/pmu/ebb/ebb.c | |||
| @@ -224,6 +224,7 @@ void dump_ebb_hw_state(void) | |||
| 224 | 224 | ||
| 225 | printf("HW state:\n" \ | 225 | printf("HW state:\n" \ |
| 226 | "MMCR0 0x%016x %s\n" \ | 226 | "MMCR0 0x%016x %s\n" \ |
| 227 | "MMCR2 0x%016lx\n" \ | ||
| 227 | "EBBHR 0x%016lx\n" \ | 228 | "EBBHR 0x%016lx\n" \ |
| 228 | "BESCR 0x%016llx %s\n" \ | 229 | "BESCR 0x%016llx %s\n" \ |
| 229 | "PMC1 0x%016lx\n" \ | 230 | "PMC1 0x%016lx\n" \ |
| @@ -233,10 +234,11 @@ void dump_ebb_hw_state(void) | |||
| 233 | "PMC5 0x%016lx\n" \ | 234 | "PMC5 0x%016lx\n" \ |
| 234 | "PMC6 0x%016lx\n" \ | 235 | "PMC6 0x%016lx\n" \ |
| 235 | "SIAR 0x%016lx\n", | 236 | "SIAR 0x%016lx\n", |
| 236 | mmcr0, decode_mmcr0(mmcr0), mfspr(SPRN_EBBHR), bescr, | 237 | mmcr0, decode_mmcr0(mmcr0), mfspr(SPRN_MMCR2), |
| 237 | decode_bescr(bescr), mfspr(SPRN_PMC1), mfspr(SPRN_PMC2), | 238 | mfspr(SPRN_EBBHR), bescr, decode_bescr(bescr), |
| 238 | mfspr(SPRN_PMC3), mfspr(SPRN_PMC4), mfspr(SPRN_PMC5), | 239 | mfspr(SPRN_PMC1), mfspr(SPRN_PMC2), mfspr(SPRN_PMC3), |
| 239 | mfspr(SPRN_PMC6), mfspr(SPRN_SIAR)); | 240 | mfspr(SPRN_PMC4), mfspr(SPRN_PMC5), mfspr(SPRN_PMC6), |
| 241 | mfspr(SPRN_SIAR)); | ||
| 240 | } | 242 | } |
| 241 | 243 | ||
| 242 | void dump_ebb_state(void) | 244 | void dump_ebb_state(void) |
| @@ -335,257 +337,6 @@ void event_leader_ebb_init(struct event *e) | |||
| 335 | e->attr.pinned = 1; | 337 | e->attr.pinned = 1; |
| 336 | } | 338 | } |
| 337 | 339 | ||
| 338 | int core_busy_loop(void) | ||
| 339 | { | ||
| 340 | int rc; | ||
| 341 | |||
| 342 | asm volatile ( | ||
| 343 | "li 3, 0x3030\n" | ||
| 344 | "std 3, -96(1)\n" | ||
| 345 | "li 4, 0x4040\n" | ||
| 346 | "std 4, -104(1)\n" | ||
| 347 | "li 5, 0x5050\n" | ||
| 348 | "std 5, -112(1)\n" | ||
| 349 | "li 6, 0x6060\n" | ||
| 350 | "std 6, -120(1)\n" | ||
| 351 | "li 7, 0x7070\n" | ||
| 352 | "std 7, -128(1)\n" | ||
| 353 | "li 8, 0x0808\n" | ||
| 354 | "std 8, -136(1)\n" | ||
| 355 | "li 9, 0x0909\n" | ||
| 356 | "std 9, -144(1)\n" | ||
| 357 | "li 10, 0x1010\n" | ||
| 358 | "std 10, -152(1)\n" | ||
| 359 | "li 11, 0x1111\n" | ||
| 360 | "std 11, -160(1)\n" | ||
| 361 | "li 14, 0x1414\n" | ||
| 362 | "std 14, -168(1)\n" | ||
| 363 | "li 15, 0x1515\n" | ||
| 364 | "std 15, -176(1)\n" | ||
| 365 | "li 16, 0x1616\n" | ||
| 366 | "std 16, -184(1)\n" | ||
| 367 | "li 17, 0x1717\n" | ||
| 368 | "std 17, -192(1)\n" | ||
| 369 | "li 18, 0x1818\n" | ||
| 370 | "std 18, -200(1)\n" | ||
| 371 | "li 19, 0x1919\n" | ||
| 372 | "std 19, -208(1)\n" | ||
| 373 | "li 20, 0x2020\n" | ||
| 374 | "std 20, -216(1)\n" | ||
| 375 | "li 21, 0x2121\n" | ||
| 376 | "std 21, -224(1)\n" | ||
| 377 | "li 22, 0x2222\n" | ||
| 378 | "std 22, -232(1)\n" | ||
| 379 | "li 23, 0x2323\n" | ||
| 380 | "std 23, -240(1)\n" | ||
| 381 | "li 24, 0x2424\n" | ||
| 382 | "std 24, -248(1)\n" | ||
| 383 | "li 25, 0x2525\n" | ||
| 384 | "std 25, -256(1)\n" | ||
| 385 | "li 26, 0x2626\n" | ||
| 386 | "std 26, -264(1)\n" | ||
| 387 | "li 27, 0x2727\n" | ||
| 388 | "std 27, -272(1)\n" | ||
| 389 | "li 28, 0x2828\n" | ||
| 390 | "std 28, -280(1)\n" | ||
| 391 | "li 29, 0x2929\n" | ||
| 392 | "std 29, -288(1)\n" | ||
| 393 | "li 30, 0x3030\n" | ||
| 394 | "li 31, 0x3131\n" | ||
| 395 | |||
| 396 | "li 3, 0\n" | ||
| 397 | "0: " | ||
| 398 | "addi 3, 3, 1\n" | ||
| 399 | "cmpwi 3, 100\n" | ||
| 400 | "blt 0b\n" | ||
| 401 | |||
| 402 | /* Return 1 (fail) unless we get through all the checks */ | ||
| 403 | "li 0, 1\n" | ||
| 404 | |||
| 405 | /* Check none of our registers have been corrupted */ | ||
| 406 | "cmpwi 4, 0x4040\n" | ||
| 407 | "bne 1f\n" | ||
| 408 | "cmpwi 5, 0x5050\n" | ||
| 409 | "bne 1f\n" | ||
| 410 | "cmpwi 6, 0x6060\n" | ||
| 411 | "bne 1f\n" | ||
| 412 | "cmpwi 7, 0x7070\n" | ||
| 413 | "bne 1f\n" | ||
| 414 | "cmpwi 8, 0x0808\n" | ||
| 415 | "bne 1f\n" | ||
| 416 | "cmpwi 9, 0x0909\n" | ||
| 417 | "bne 1f\n" | ||
| 418 | "cmpwi 10, 0x1010\n" | ||
| 419 | "bne 1f\n" | ||
| 420 | "cmpwi 11, 0x1111\n" | ||
| 421 | "bne 1f\n" | ||
| 422 | "cmpwi 14, 0x1414\n" | ||
| 423 | "bne 1f\n" | ||
| 424 | "cmpwi 15, 0x1515\n" | ||
| 425 | "bne 1f\n" | ||
| 426 | "cmpwi 16, 0x1616\n" | ||
| 427 | "bne 1f\n" | ||
| 428 | "cmpwi 17, 0x1717\n" | ||
| 429 | "bne 1f\n" | ||
| 430 | "cmpwi 18, 0x1818\n" | ||
| 431 | "bne 1f\n" | ||
| 432 | "cmpwi 19, 0x1919\n" | ||
| 433 | "bne 1f\n" | ||
| 434 | "cmpwi 20, 0x2020\n" | ||
| 435 | "bne 1f\n" | ||
| 436 | "cmpwi 21, 0x2121\n" | ||
| 437 | "bne 1f\n" | ||
| 438 | "cmpwi 22, 0x2222\n" | ||
| 439 | "bne 1f\n" | ||
| 440 | "cmpwi 23, 0x2323\n" | ||
| 441 | "bne 1f\n" | ||
| 442 | "cmpwi 24, 0x2424\n" | ||
| 443 | "bne 1f\n" | ||
| 444 | "cmpwi 25, 0x2525\n" | ||
| 445 | "bne 1f\n" | ||
| 446 | "cmpwi 26, 0x2626\n" | ||
| 447 | "bne 1f\n" | ||
| 448 | "cmpwi 27, 0x2727\n" | ||
| 449 | "bne 1f\n" | ||
| 450 | "cmpwi 28, 0x2828\n" | ||
| 451 | "bne 1f\n" | ||
| 452 | "cmpwi 29, 0x2929\n" | ||
| 453 | "bne 1f\n" | ||
| 454 | "cmpwi 30, 0x3030\n" | ||
| 455 | "bne 1f\n" | ||
| 456 | "cmpwi 31, 0x3131\n" | ||
| 457 | "bne 1f\n" | ||
| 458 | |||
| 459 | /* Load junk into all our registers before we reload them from the stack. */ | ||
| 460 | "li 3, 0xde\n" | ||
| 461 | "li 4, 0xad\n" | ||
| 462 | "li 5, 0xbe\n" | ||
| 463 | "li 6, 0xef\n" | ||
| 464 | "li 7, 0xde\n" | ||
| 465 | "li 8, 0xad\n" | ||
| 466 | "li 9, 0xbe\n" | ||
| 467 | "li 10, 0xef\n" | ||
| 468 | "li 11, 0xde\n" | ||
| 469 | "li 14, 0xad\n" | ||
| 470 | "li 15, 0xbe\n" | ||
| 471 | "li 16, 0xef\n" | ||
| 472 | "li 17, 0xde\n" | ||
| 473 | "li 18, 0xad\n" | ||
| 474 | "li 19, 0xbe\n" | ||
| 475 | "li 20, 0xef\n" | ||
| 476 | "li 21, 0xde\n" | ||
| 477 | "li 22, 0xad\n" | ||
| 478 | "li 23, 0xbe\n" | ||
| 479 | "li 24, 0xef\n" | ||
| 480 | "li 25, 0xde\n" | ||
| 481 | "li 26, 0xad\n" | ||
| 482 | "li 27, 0xbe\n" | ||
| 483 | "li 28, 0xef\n" | ||
| 484 | "li 29, 0xdd\n" | ||
| 485 | |||
| 486 | "ld 3, -96(1)\n" | ||
| 487 | "cmpwi 3, 0x3030\n" | ||
| 488 | "bne 1f\n" | ||
| 489 | "ld 4, -104(1)\n" | ||
| 490 | "cmpwi 4, 0x4040\n" | ||
| 491 | "bne 1f\n" | ||
| 492 | "ld 5, -112(1)\n" | ||
| 493 | "cmpwi 5, 0x5050\n" | ||
| 494 | "bne 1f\n" | ||
| 495 | "ld 6, -120(1)\n" | ||
| 496 | "cmpwi 6, 0x6060\n" | ||
| 497 | "bne 1f\n" | ||
| 498 | "ld 7, -128(1)\n" | ||
| 499 | "cmpwi 7, 0x7070\n" | ||
| 500 | "bne 1f\n" | ||
| 501 | "ld 8, -136(1)\n" | ||
| 502 | "cmpwi 8, 0x0808\n" | ||
| 503 | "bne 1f\n" | ||
| 504 | "ld 9, -144(1)\n" | ||
| 505 | "cmpwi 9, 0x0909\n" | ||
| 506 | "bne 1f\n" | ||
| 507 | "ld 10, -152(1)\n" | ||
| 508 | "cmpwi 10, 0x1010\n" | ||
| 509 | "bne 1f\n" | ||
| 510 | "ld 11, -160(1)\n" | ||
| 511 | "cmpwi 11, 0x1111\n" | ||
| 512 | "bne 1f\n" | ||
| 513 | "ld 14, -168(1)\n" | ||
| 514 | "cmpwi 14, 0x1414\n" | ||
| 515 | "bne 1f\n" | ||
| 516 | "ld 15, -176(1)\n" | ||
| 517 | "cmpwi 15, 0x1515\n" | ||
| 518 | "bne 1f\n" | ||
| 519 | "ld 16, -184(1)\n" | ||
| 520 | "cmpwi 16, 0x1616\n" | ||
| 521 | "bne 1f\n" | ||
| 522 | "ld 17, -192(1)\n" | ||
| 523 | "cmpwi 17, 0x1717\n" | ||
| 524 | "bne 1f\n" | ||
| 525 | "ld 18, -200(1)\n" | ||
| 526 | "cmpwi 18, 0x1818\n" | ||
| 527 | "bne 1f\n" | ||
| 528 | "ld 19, -208(1)\n" | ||
| 529 | "cmpwi 19, 0x1919\n" | ||
| 530 | "bne 1f\n" | ||
| 531 | "ld 20, -216(1)\n" | ||
| 532 | "cmpwi 20, 0x2020\n" | ||
| 533 | "bne 1f\n" | ||
| 534 | "ld 21, -224(1)\n" | ||
| 535 | "cmpwi 21, 0x2121\n" | ||
| 536 | "bne 1f\n" | ||
| 537 | "ld 22, -232(1)\n" | ||
| 538 | "cmpwi 22, 0x2222\n" | ||
| 539 | "bne 1f\n" | ||
| 540 | "ld 23, -240(1)\n" | ||
| 541 | "cmpwi 23, 0x2323\n" | ||
| 542 | "bne 1f\n" | ||
| 543 | "ld 24, -248(1)\n" | ||
| 544 | "cmpwi 24, 0x2424\n" | ||
| 545 | "bne 1f\n" | ||
| 546 | "ld 25, -256(1)\n" | ||
| 547 | "cmpwi 25, 0x2525\n" | ||
| 548 | "bne 1f\n" | ||
| 549 | "ld 26, -264(1)\n" | ||
| 550 | "cmpwi 26, 0x2626\n" | ||
| 551 | "bne 1f\n" | ||
| 552 | "ld 27, -272(1)\n" | ||
| 553 | "cmpwi 27, 0x2727\n" | ||
| 554 | "bne 1f\n" | ||
| 555 | "ld 28, -280(1)\n" | ||
| 556 | "cmpwi 28, 0x2828\n" | ||
| 557 | "bne 1f\n" | ||
| 558 | "ld 29, -288(1)\n" | ||
| 559 | "cmpwi 29, 0x2929\n" | ||
| 560 | "bne 1f\n" | ||
| 561 | |||
| 562 | /* Load 0 (success) to return */ | ||
| 563 | "li 0, 0\n" | ||
| 564 | |||
| 565 | "1: mr %0, 0\n" | ||
| 566 | |||
| 567 | : "=r" (rc) | ||
| 568 | : /* no inputs */ | ||
| 569 | : "3", "4", "5", "6", "7", "8", "9", "10", "11", "14", | ||
| 570 | "15", "16", "17", "18", "19", "20", "21", "22", "23", | ||
| 571 | "24", "25", "26", "27", "28", "29", "30", "31", | ||
| 572 | "memory" | ||
| 573 | ); | ||
| 574 | |||
| 575 | return rc; | ||
| 576 | } | ||
| 577 | |||
| 578 | int core_busy_loop_with_freeze(void) | ||
| 579 | { | ||
| 580 | int rc; | ||
| 581 | |||
| 582 | mtspr(SPRN_MMCR0, mfspr(SPRN_MMCR0) & ~MMCR0_FC); | ||
| 583 | rc = core_busy_loop(); | ||
| 584 | mtspr(SPRN_MMCR0, mfspr(SPRN_MMCR0) | MMCR0_FC); | ||
| 585 | |||
| 586 | return rc; | ||
| 587 | } | ||
| 588 | |||
| 589 | int ebb_child(union pipe read_pipe, union pipe write_pipe) | 340 | int ebb_child(union pipe read_pipe, union pipe write_pipe) |
| 590 | { | 341 | { |
| 591 | struct event event; | 342 | struct event event; |
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/ebb.h b/tools/testing/selftests/powerpc/pmu/ebb/ebb.h index e62bde05bf78..e44eee5d97ca 100644 --- a/tools/testing/selftests/powerpc/pmu/ebb/ebb.h +++ b/tools/testing/selftests/powerpc/pmu/ebb/ebb.h | |||
| @@ -70,7 +70,6 @@ int ebb_check_mmcr0(void); | |||
| 70 | extern u64 sample_period; | 70 | extern u64 sample_period; |
| 71 | 71 | ||
| 72 | int core_busy_loop(void); | 72 | int core_busy_loop(void); |
| 73 | int core_busy_loop_with_freeze(void); | ||
| 74 | int ebb_child(union pipe read_pipe, union pipe write_pipe); | 73 | int ebb_child(union pipe read_pipe, union pipe write_pipe); |
| 75 | int catch_sigill(void (*func)(void)); | 74 | int catch_sigill(void (*func)(void)); |
| 76 | void write_pmc1(void); | 75 | void write_pmc1(void); |
diff --git a/tools/testing/selftests/powerpc/pmu/l3_bank_test.c b/tools/testing/selftests/powerpc/pmu/l3_bank_test.c new file mode 100644 index 000000000000..77472f31441e --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/l3_bank_test.c | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2014, Michael Ellerman, IBM Corp. | ||
| 3 | * Licensed under GPLv2. | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <stdio.h> | ||
| 7 | #include <stdlib.h> | ||
| 8 | |||
| 9 | #include "event.h" | ||
| 10 | #include "utils.h" | ||
| 11 | |||
| 12 | #define MALLOC_SIZE (0x10000 * 10) /* Ought to be enough .. */ | ||
| 13 | |||
| 14 | /* | ||
| 15 | * Tests that the L3 bank handling is correct. We fixed it in commit e9aaac1. | ||
| 16 | */ | ||
| 17 | static int l3_bank_test(void) | ||
| 18 | { | ||
| 19 | struct event event; | ||
| 20 | char *p; | ||
| 21 | int i; | ||
| 22 | |||
| 23 | p = malloc(MALLOC_SIZE); | ||
| 24 | FAIL_IF(!p); | ||
| 25 | |||
| 26 | event_init(&event, 0x84918F); | ||
| 27 | |||
| 28 | FAIL_IF(event_open(&event)); | ||
| 29 | |||
| 30 | for (i = 0; i < MALLOC_SIZE; i += 0x10000) | ||
| 31 | p[i] = i; | ||
| 32 | |||
| 33 | event_read(&event); | ||
| 34 | event_report(&event); | ||
| 35 | |||
| 36 | FAIL_IF(event.result.running == 0); | ||
| 37 | FAIL_IF(event.result.enabled == 0); | ||
| 38 | |||
| 39 | event_close(&event); | ||
| 40 | free(p); | ||
| 41 | |||
| 42 | return 0; | ||
| 43 | } | ||
| 44 | |||
| 45 | int main(void) | ||
| 46 | { | ||
| 47 | return test_harness(l3_bank_test, "l3_bank_test"); | ||
| 48 | } | ||
diff --git a/tools/testing/selftests/powerpc/pmu/lib.c b/tools/testing/selftests/powerpc/pmu/lib.c index 0f6a4731d546..9768dea37bf3 100644 --- a/tools/testing/selftests/powerpc/pmu/lib.c +++ b/tools/testing/selftests/powerpc/pmu/lib.c | |||
| @@ -5,10 +5,15 @@ | |||
| 5 | 5 | ||
| 6 | #define _GNU_SOURCE /* For CPU_ZERO etc. */ | 6 | #define _GNU_SOURCE /* For CPU_ZERO etc. */ |
| 7 | 7 | ||
| 8 | #include <elf.h> | ||
| 8 | #include <errno.h> | 9 | #include <errno.h> |
| 10 | #include <fcntl.h> | ||
| 11 | #include <link.h> | ||
| 9 | #include <sched.h> | 12 | #include <sched.h> |
| 10 | #include <setjmp.h> | 13 | #include <setjmp.h> |
| 11 | #include <stdlib.h> | 14 | #include <stdlib.h> |
| 15 | #include <sys/stat.h> | ||
| 16 | #include <sys/types.h> | ||
| 12 | #include <sys/wait.h> | 17 | #include <sys/wait.h> |
| 13 | 18 | ||
| 14 | #include "utils.h" | 19 | #include "utils.h" |
| @@ -177,8 +182,8 @@ struct addr_range libc, vdso; | |||
| 177 | 182 | ||
| 178 | int parse_proc_maps(void) | 183 | int parse_proc_maps(void) |
| 179 | { | 184 | { |
| 185 | unsigned long start, end; | ||
| 180 | char execute, name[128]; | 186 | char execute, name[128]; |
| 181 | uint64_t start, end; | ||
| 182 | FILE *f; | 187 | FILE *f; |
| 183 | int rc; | 188 | int rc; |
| 184 | 189 | ||
| @@ -250,3 +255,46 @@ out_close: | |||
| 250 | out: | 255 | out: |
| 251 | return rc; | 256 | return rc; |
| 252 | } | 257 | } |
| 258 | |||
| 259 | static char auxv[4096]; | ||
| 260 | |||
| 261 | void *get_auxv_entry(int type) | ||
| 262 | { | ||
| 263 | ElfW(auxv_t) *p; | ||
| 264 | void *result; | ||
| 265 | ssize_t num; | ||
| 266 | int fd; | ||
| 267 | |||
| 268 | fd = open("/proc/self/auxv", O_RDONLY); | ||
| 269 | if (fd == -1) { | ||
| 270 | perror("open"); | ||
| 271 | return NULL; | ||
| 272 | } | ||
| 273 | |||
| 274 | result = NULL; | ||
| 275 | |||
| 276 | num = read(fd, auxv, sizeof(auxv)); | ||
| 277 | if (num < 0) { | ||
| 278 | perror("read"); | ||
| 279 | goto out; | ||
| 280 | } | ||
| 281 | |||
| 282 | if (num > sizeof(auxv)) { | ||
| 283 | printf("Overflowed auxv buffer\n"); | ||
| 284 | goto out; | ||
| 285 | } | ||
| 286 | |||
| 287 | p = (ElfW(auxv_t) *)auxv; | ||
| 288 | |||
| 289 | while (p->a_type != AT_NULL) { | ||
| 290 | if (p->a_type == type) { | ||
| 291 | result = (void *)p->a_un.a_val; | ||
| 292 | break; | ||
| 293 | } | ||
| 294 | |||
| 295 | p++; | ||
| 296 | } | ||
| 297 | out: | ||
| 298 | close(fd); | ||
| 299 | return result; | ||
| 300 | } | ||
diff --git a/tools/testing/selftests/powerpc/pmu/lib.h b/tools/testing/selftests/powerpc/pmu/lib.h index ca5d72ae3be6..0f0339c8a6f6 100644 --- a/tools/testing/selftests/powerpc/pmu/lib.h +++ b/tools/testing/selftests/powerpc/pmu/lib.h | |||
| @@ -29,6 +29,7 @@ extern int notify_parent(union pipe write_pipe); | |||
| 29 | extern int notify_parent_of_error(union pipe write_pipe); | 29 | extern int notify_parent_of_error(union pipe write_pipe); |
| 30 | extern pid_t eat_cpu(int (test_function)(void)); | 30 | extern pid_t eat_cpu(int (test_function)(void)); |
| 31 | extern bool require_paranoia_below(int level); | 31 | extern bool require_paranoia_below(int level); |
| 32 | extern void *get_auxv_entry(int type); | ||
| 32 | 33 | ||
| 33 | struct addr_range { | 34 | struct addr_range { |
| 34 | uint64_t first, last; | 35 | uint64_t first, last; |
diff --git a/tools/testing/selftests/powerpc/pmu/per_event_excludes.c b/tools/testing/selftests/powerpc/pmu/per_event_excludes.c new file mode 100644 index 000000000000..fddbbc9cae2f --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/per_event_excludes.c | |||
| @@ -0,0 +1,114 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2014, Michael Ellerman, IBM Corp. | ||
| 3 | * Licensed under GPLv2. | ||
| 4 | */ | ||
| 5 | |||
| 6 | #define _GNU_SOURCE | ||
| 7 | |||
| 8 | #include <elf.h> | ||
| 9 | #include <limits.h> | ||
| 10 | #include <stdio.h> | ||
| 11 | #include <stdbool.h> | ||
| 12 | #include <string.h> | ||
| 13 | #include <sys/prctl.h> | ||
| 14 | |||
| 15 | #include "event.h" | ||
| 16 | #include "lib.h" | ||
| 17 | #include "utils.h" | ||
| 18 | |||
| 19 | /* | ||
| 20 | * Test that per-event excludes work. | ||
| 21 | */ | ||
| 22 | |||
| 23 | static int per_event_excludes(void) | ||
| 24 | { | ||
| 25 | struct event *e, events[4]; | ||
| 26 | char *platform; | ||
| 27 | int i; | ||
| 28 | |||
| 29 | platform = (char *)get_auxv_entry(AT_BASE_PLATFORM); | ||
| 30 | FAIL_IF(!platform); | ||
| 31 | SKIP_IF(strcmp(platform, "power8") != 0); | ||
| 32 | |||
| 33 | /* | ||
| 34 | * We need to create the events disabled, otherwise the running/enabled | ||
| 35 | * counts don't match up. | ||
| 36 | */ | ||
| 37 | e = &events[0]; | ||
| 38 | event_init_opts(e, PERF_COUNT_HW_INSTRUCTIONS, | ||
| 39 | PERF_TYPE_HARDWARE, "instructions"); | ||
| 40 | e->attr.disabled = 1; | ||
| 41 | |||
| 42 | e = &events[1]; | ||
| 43 | event_init_opts(e, PERF_COUNT_HW_INSTRUCTIONS, | ||
| 44 | PERF_TYPE_HARDWARE, "instructions(k)"); | ||
| 45 | e->attr.disabled = 1; | ||
| 46 | e->attr.exclude_user = 1; | ||
| 47 | e->attr.exclude_hv = 1; | ||
| 48 | |||
| 49 | e = &events[2]; | ||
| 50 | event_init_opts(e, PERF_COUNT_HW_INSTRUCTIONS, | ||
| 51 | PERF_TYPE_HARDWARE, "instructions(h)"); | ||
| 52 | e->attr.disabled = 1; | ||
| 53 | e->attr.exclude_user = 1; | ||
| 54 | e->attr.exclude_kernel = 1; | ||
| 55 | |||
| 56 | e = &events[3]; | ||
| 57 | event_init_opts(e, PERF_COUNT_HW_INSTRUCTIONS, | ||
| 58 | PERF_TYPE_HARDWARE, "instructions(u)"); | ||
| 59 | e->attr.disabled = 1; | ||
| 60 | e->attr.exclude_hv = 1; | ||
| 61 | e->attr.exclude_kernel = 1; | ||
| 62 | |||
| 63 | FAIL_IF(event_open(&events[0])); | ||
| 64 | |||
| 65 | /* | ||
| 66 | * The open here will fail if we don't have per event exclude support, | ||
| 67 | * because the second event has an incompatible set of exclude settings | ||
| 68 | * and we're asking for the events to be in a group. | ||
| 69 | */ | ||
| 70 | for (i = 1; i < 4; i++) | ||
| 71 | FAIL_IF(event_open_with_group(&events[i], events[0].fd)); | ||
| 72 | |||
| 73 | /* | ||
| 74 | * Even though the above will fail without per-event excludes we keep | ||
| 75 | * testing in order to be thorough. | ||
| 76 | */ | ||
| 77 | prctl(PR_TASK_PERF_EVENTS_ENABLE); | ||
| 78 | |||
| 79 | /* Spin for a while */ | ||
| 80 | for (i = 0; i < INT_MAX; i++) | ||
| 81 | asm volatile("" : : : "memory"); | ||
| 82 | |||
| 83 | prctl(PR_TASK_PERF_EVENTS_DISABLE); | ||
| 84 | |||
| 85 | for (i = 0; i < 4; i++) { | ||
| 86 | FAIL_IF(event_read(&events[i])); | ||
| 87 | event_report(&events[i]); | ||
| 88 | } | ||
| 89 | |||
| 90 | /* | ||
| 91 | * We should see that all events have enabled == running. That | ||
| 92 | * shows that they were all on the PMU at once. | ||
| 93 | */ | ||
| 94 | for (i = 0; i < 4; i++) | ||
| 95 | FAIL_IF(events[i].result.running != events[i].result.enabled); | ||
| 96 | |||
| 97 | /* | ||
| 98 | * We can also check that the result for instructions is >= all the | ||
| 99 | * other counts. That's because it is counting all instructions while | ||
| 100 | * the others are counting a subset. | ||
| 101 | */ | ||
| 102 | for (i = 1; i < 4; i++) | ||
| 103 | FAIL_IF(events[0].result.value < events[i].result.value); | ||
| 104 | |||
| 105 | for (i = 0; i < 4; i++) | ||
| 106 | event_close(&events[i]); | ||
| 107 | |||
| 108 | return 0; | ||
| 109 | } | ||
| 110 | |||
| 111 | int main(void) | ||
| 112 | { | ||
| 113 | return test_harness(per_event_excludes, "per_event_excludes"); | ||
| 114 | } | ||
