diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-07 11:50:34 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-07 11:50:34 -0400 |
commit | f536b3cae84eb7c9f3495285ad048d13a397ed0b (patch) | |
tree | b53eee1c45eb080168786e2f103e76d6706cbbb0 | |
parent | e669830526a0abaf301bf408df69cde33901ac63 (diff) | |
parent | 537e5400a0a05c4efe70e7b372c19cfcd0179362 (diff) |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
Pull powerpc updates from Ben Herrenschmidt:
"This is the powerpc new goodies for 3.17. The short story:
The biggest bit is Michael removing all of pre-POWER4 processor
support from the 64-bit kernel. POWER3 and rs64. This gets rid of a
ton of old cruft that has been bitrotting in a long while. It was
broken for quite a few versions already and nobody noticed. Nobody
uses those machines anymore. While at it, he cleaned up a bunch of
old dusty cabinets, getting rid of a skeletton or two.
Then, we have some base VFIO support for KVM, which allows assigning
of PCI devices to KVM guests, support for large 64-bit BARs on
"powernv" platforms, support for HMI (Hardware Management Interrupts)
on those same platforms, some sparse-vmemmap improvements (for memory
hotplug),
There is the usual batch of Freescale embedded updates (summary in the
merge commit) and fixes here or there, I think that's it for the
highlights"
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (102 commits)
powerpc/eeh: Export eeh_iommu_group_to_pe()
powerpc/eeh: Add missing #ifdef CONFIG_IOMMU_API
powerpc: Reduce scariness of interrupt frames in stack traces
powerpc: start loop at section start of start in vmemmap_populated()
powerpc: implement vmemmap_free()
powerpc: implement vmemmap_remove_mapping() for BOOK3S
powerpc: implement vmemmap_list_free()
powerpc: Fail remap_4k_pfn() if PFN doesn't fit inside PTE
powerpc/book3s: Fix endianess issue for HMI handling on napping cpus.
powerpc/book3s: handle HMIs for cpus in nap mode.
powerpc/powernv: Invoke opal call to handle hmi.
powerpc/book3s: Add basic infrastructure to handle HMI in Linux.
powerpc/iommu: Fix comments with it_page_shift
powerpc/powernv: Handle compound PE in config accessors
powerpc/powernv: Handle compound PE for EEH
powerpc/powernv: Handle compound PE
powerpc/powernv: Split ioda_eeh_get_state()
powerpc/powernv: Allow to freeze PE
powerpc/powernv: Enable M64 aperatus for PHB3
powerpc/eeh: Aux PE data for error log
...
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 | } | ||