aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-06-12 18:05:02 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-06-12 18:05:02 -0400
commit38da0d6888a6bccd3ae93227aa9f29537f8bd5f9 (patch)
tree64c7c1d008460f05b579110a7e40b6c796fb1578
parent19785cf93b6c4252981894394f2dbd35c5e5d1ec (diff)
parentce4c7b241227ed49c0b6f0f1867653e1ee0007ef (diff)
Merge tag 'pci-v4.18-changes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull more PCI updates from Bjorn Helgaas: - squash AER directory into drivers/pci/pcie/aer.c (Bjorn Helgaas) - collect all native hardware drivers under drivers/pci/controller/ (Shawn Lin) * tag 'pci-v4.18-changes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: PCI/AER: Use "PCI Express" consistently in Kconfig text PCI/AER: Hoist aerdrv.c, aer_inject.c up to drivers/pci/pcie/ PCI/AER: Squash Kconfig.debug into Kconfig PCI/AER: Move private AER things to aerdrv.c PCI/AER: Move aer_irq() declaration to portdrv.h PCI/AER: Move pcie_aer_get_firmware_first() to portdrv.h PCI/AER: Remove duplicate pcie_port_bus_type declaration PCI/AER: Squash ecrc.c into aerdrv.c PCI/AER: Squash aerdrv_acpi.c into aerdrv.c PCI/AER: Squash aerdrv_errprint.c into aerdrv.c PCI/AER: Squash aerdrv_core.c into aerdrv.c PCI/AER: Reorder code to group probe/remove stuff together PCI/AER: Remove forward declarations PCI: Collect all native drivers under drivers/pci/controller/
-rw-r--r--MAINTAINERS70
-rw-r--r--drivers/pci/Kconfig4
-rw-r--r--drivers/pci/Makefile6
-rw-r--r--drivers/pci/cadence/Kconfig27
-rw-r--r--drivers/pci/cadence/Makefile4
-rw-r--r--drivers/pci/controller/Kconfig (renamed from drivers/pci/host/Kconfig)31
-rw-r--r--drivers/pci/controller/Makefile (renamed from drivers/pci/host/Makefile)6
-rw-r--r--drivers/pci/controller/dwc/Kconfig (renamed from drivers/pci/dwc/Kconfig)0
-rw-r--r--drivers/pci/controller/dwc/Makefile (renamed from drivers/pci/dwc/Makefile)0
-rw-r--r--drivers/pci/controller/dwc/pci-dra7xx.c (renamed from drivers/pci/dwc/pci-dra7xx.c)2
-rw-r--r--drivers/pci/controller/dwc/pci-exynos.c (renamed from drivers/pci/dwc/pci-exynos.c)0
-rw-r--r--drivers/pci/controller/dwc/pci-imx6.c (renamed from drivers/pci/dwc/pci-imx6.c)0
-rw-r--r--drivers/pci/controller/dwc/pci-keystone-dw.c (renamed from drivers/pci/dwc/pci-keystone-dw.c)0
-rw-r--r--drivers/pci/controller/dwc/pci-keystone.c (renamed from drivers/pci/dwc/pci-keystone.c)0
-rw-r--r--drivers/pci/controller/dwc/pci-keystone.h (renamed from drivers/pci/dwc/pci-keystone.h)0
-rw-r--r--drivers/pci/controller/dwc/pci-layerscape.c (renamed from drivers/pci/dwc/pci-layerscape.c)0
-rw-r--r--drivers/pci/controller/dwc/pcie-armada8k.c (renamed from drivers/pci/dwc/pcie-armada8k.c)0
-rw-r--r--drivers/pci/controller/dwc/pcie-artpec6.c (renamed from drivers/pci/dwc/pcie-artpec6.c)0
-rw-r--r--drivers/pci/controller/dwc/pcie-designware-ep.c (renamed from drivers/pci/dwc/pcie-designware-ep.c)0
-rw-r--r--drivers/pci/controller/dwc/pcie-designware-host.c (renamed from drivers/pci/dwc/pcie-designware-host.c)2
-rw-r--r--drivers/pci/controller/dwc/pcie-designware-plat.c (renamed from drivers/pci/dwc/pcie-designware-plat.c)0
-rw-r--r--drivers/pci/controller/dwc/pcie-designware.c (renamed from drivers/pci/dwc/pcie-designware.c)0
-rw-r--r--drivers/pci/controller/dwc/pcie-designware.h (renamed from drivers/pci/dwc/pcie-designware.h)0
-rw-r--r--drivers/pci/controller/dwc/pcie-hisi.c (renamed from drivers/pci/dwc/pcie-hisi.c)2
-rw-r--r--drivers/pci/controller/dwc/pcie-histb.c (renamed from drivers/pci/dwc/pcie-histb.c)0
-rw-r--r--drivers/pci/controller/dwc/pcie-kirin.c (renamed from drivers/pci/dwc/pcie-kirin.c)0
-rw-r--r--drivers/pci/controller/dwc/pcie-qcom.c (renamed from drivers/pci/dwc/pcie-qcom.c)0
-rw-r--r--drivers/pci/controller/dwc/pcie-spear13xx.c (renamed from drivers/pci/dwc/pcie-spear13xx.c)0
-rw-r--r--drivers/pci/controller/pci-aardvark.c (renamed from drivers/pci/host/pci-aardvark.c)0
-rw-r--r--drivers/pci/controller/pci-ftpci100.c (renamed from drivers/pci/host/pci-ftpci100.c)0
-rw-r--r--drivers/pci/controller/pci-host-common.c (renamed from drivers/pci/host/pci-host-common.c)0
-rw-r--r--drivers/pci/controller/pci-host-generic.c (renamed from drivers/pci/host/pci-host-generic.c)0
-rw-r--r--drivers/pci/controller/pci-hyperv.c (renamed from drivers/pci/host/pci-hyperv.c)0
-rw-r--r--drivers/pci/controller/pci-mvebu.c (renamed from drivers/pci/host/pci-mvebu.c)0
-rw-r--r--drivers/pci/controller/pci-rcar-gen2.c (renamed from drivers/pci/host/pci-rcar-gen2.c)0
-rw-r--r--drivers/pci/controller/pci-tegra.c (renamed from drivers/pci/host/pci-tegra.c)0
-rw-r--r--drivers/pci/controller/pci-thunder-ecam.c (renamed from drivers/pci/host/pci-thunder-ecam.c)0
-rw-r--r--drivers/pci/controller/pci-thunder-pem.c (renamed from drivers/pci/host/pci-thunder-pem.c)0
-rw-r--r--drivers/pci/controller/pci-v3-semi.c (renamed from drivers/pci/host/pci-v3-semi.c)0
-rw-r--r--drivers/pci/controller/pci-versatile.c (renamed from drivers/pci/host/pci-versatile.c)0
-rw-r--r--drivers/pci/controller/pci-xgene-msi.c (renamed from drivers/pci/host/pci-xgene-msi.c)0
-rw-r--r--drivers/pci/controller/pci-xgene.c (renamed from drivers/pci/host/pci-xgene.c)0
-rw-r--r--drivers/pci/controller/pcie-altera-msi.c (renamed from drivers/pci/host/pcie-altera-msi.c)0
-rw-r--r--drivers/pci/controller/pcie-altera.c (renamed from drivers/pci/host/pcie-altera.c)0
-rw-r--r--drivers/pci/controller/pcie-cadence-ep.c (renamed from drivers/pci/cadence/pcie-cadence-ep.c)0
-rw-r--r--drivers/pci/controller/pcie-cadence-host.c (renamed from drivers/pci/cadence/pcie-cadence-host.c)0
-rw-r--r--drivers/pci/controller/pcie-cadence.c (renamed from drivers/pci/cadence/pcie-cadence.c)0
-rw-r--r--drivers/pci/controller/pcie-cadence.h (renamed from drivers/pci/cadence/pcie-cadence.h)0
-rw-r--r--drivers/pci/controller/pcie-iproc-bcma.c (renamed from drivers/pci/host/pcie-iproc-bcma.c)0
-rw-r--r--drivers/pci/controller/pcie-iproc-msi.c (renamed from drivers/pci/host/pcie-iproc-msi.c)0
-rw-r--r--drivers/pci/controller/pcie-iproc-platform.c (renamed from drivers/pci/host/pcie-iproc-platform.c)0
-rw-r--r--drivers/pci/controller/pcie-iproc.c (renamed from drivers/pci/host/pcie-iproc.c)0
-rw-r--r--drivers/pci/controller/pcie-iproc.h (renamed from drivers/pci/host/pcie-iproc.h)0
-rw-r--r--drivers/pci/controller/pcie-mediatek.c (renamed from drivers/pci/host/pcie-mediatek.c)0
-rw-r--r--drivers/pci/controller/pcie-mobiveil.c (renamed from drivers/pci/host/pcie-mobiveil.c)0
-rw-r--r--drivers/pci/controller/pcie-rcar.c (renamed from drivers/pci/host/pcie-rcar.c)0
-rw-r--r--drivers/pci/controller/pcie-rockchip-ep.c (renamed from drivers/pci/host/pcie-rockchip-ep.c)0
-rw-r--r--drivers/pci/controller/pcie-rockchip-host.c (renamed from drivers/pci/host/pcie-rockchip-host.c)0
-rw-r--r--drivers/pci/controller/pcie-rockchip.c (renamed from drivers/pci/host/pcie-rockchip.c)0
-rw-r--r--drivers/pci/controller/pcie-rockchip.h (renamed from drivers/pci/host/pcie-rockchip.h)0
-rw-r--r--drivers/pci/controller/pcie-tango.c (renamed from drivers/pci/host/pcie-tango.c)0
-rw-r--r--drivers/pci/controller/pcie-xilinx-nwl.c (renamed from drivers/pci/host/pcie-xilinx-nwl.c)0
-rw-r--r--drivers/pci/controller/pcie-xilinx.c (renamed from drivers/pci/host/pcie-xilinx.c)0
-rw-r--r--drivers/pci/controller/vmd.c (renamed from drivers/pci/host/vmd.c)0
-rw-r--r--drivers/pci/pcie/Kconfig41
-rw-r--r--drivers/pci/pcie/Makefile3
-rw-r--r--drivers/pci/pcie/aer.c1377
-rw-r--r--drivers/pci/pcie/aer/Kconfig29
-rw-r--r--drivers/pci/pcie/aer/Kconfig.debug19
-rw-r--r--drivers/pci/pcie/aer/Makefile13
-rw-r--r--drivers/pci/pcie/aer/aerdrv.c371
-rw-r--r--drivers/pci/pcie/aer/aerdrv.h95
-rw-r--r--drivers/pci/pcie/aer/aerdrv_acpi.c141
-rw-r--r--drivers/pci/pcie/aer/aerdrv_core.c496
-rw-r--r--drivers/pci/pcie/aer/aerdrv_errprint.c260
-rw-r--r--drivers/pci/pcie/aer/ecrc.c117
-rw-r--r--drivers/pci/pcie/aer_inject.c (renamed from drivers/pci/pcie/aer/aer_inject.c)3
-rw-r--r--drivers/pci/pcie/dpc.c1
-rw-r--r--drivers/pci/pcie/portdrv.h15
79 files changed, 1509 insertions, 1626 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index def2850a1b19..c13b9fb3be0b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6620,7 +6620,7 @@ F: arch/x86/hyperv
6620F: drivers/hid/hid-hyperv.c 6620F: drivers/hid/hid-hyperv.c
6621F: drivers/hv/ 6621F: drivers/hv/
6622F: drivers/input/serio/hyperv-keyboard.c 6622F: drivers/input/serio/hyperv-keyboard.c
6623F: drivers/pci/host/pci-hyperv.c 6623F: drivers/pci/controller/pci-hyperv.c
6624F: drivers/net/hyperv/ 6624F: drivers/net/hyperv/
6625F: drivers/scsi/storvsc_drv.c 6625F: drivers/scsi/storvsc_drv.c
6626F: drivers/uio/uio_hv_generic.c 6626F: drivers/uio/uio_hv_generic.c
@@ -9524,7 +9524,7 @@ M: Subrahmanya Lingappa <l.subrahmanya@mobiveil.co.in>
9524L: linux-pci@vger.kernel.org 9524L: linux-pci@vger.kernel.org
9525S: Supported 9525S: Supported
9526F: Documentation/devicetree/bindings/pci/mobiveil-pcie.txt 9526F: Documentation/devicetree/bindings/pci/mobiveil-pcie.txt
9527F: drivers/pci/host/pcie-mobiveil.c 9527F: drivers/pci/controller/pcie-mobiveil.c
9528 9528
9529MODULE SUPPORT 9529MODULE SUPPORT
9530M: Jessica Yu <jeyu@kernel.org> 9530M: Jessica Yu <jeyu@kernel.org>
@@ -10829,7 +10829,7 @@ L: linux-pci@vger.kernel.org
10829L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) 10829L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
10830S: Maintained 10830S: Maintained
10831F: Documentation/devicetree/bindings/pci/aardvark-pci.txt 10831F: Documentation/devicetree/bindings/pci/aardvark-pci.txt
10832F: drivers/pci/host/pci-aardvark.c 10832F: drivers/pci/controller/pci-aardvark.c
10833 10833
10834PCI DRIVER FOR ALTERA PCIE IP 10834PCI DRIVER FOR ALTERA PCIE IP
10835M: Ley Foon Tan <lftan@altera.com> 10835M: Ley Foon Tan <lftan@altera.com>
@@ -10837,7 +10837,7 @@ L: rfi@lists.rocketboards.org (moderated for non-subscribers)
10837L: linux-pci@vger.kernel.org 10837L: linux-pci@vger.kernel.org
10838S: Supported 10838S: Supported
10839F: Documentation/devicetree/bindings/pci/altera-pcie.txt 10839F: Documentation/devicetree/bindings/pci/altera-pcie.txt
10840F: drivers/pci/host/pcie-altera.c 10840F: drivers/pci/controller/pcie-altera.c
10841 10841
10842PCI DRIVER FOR APPLIEDMICRO XGENE 10842PCI DRIVER FOR APPLIEDMICRO XGENE
10843M: Tanmay Inamdar <tinamdar@apm.com> 10843M: Tanmay Inamdar <tinamdar@apm.com>
@@ -10845,7 +10845,7 @@ L: linux-pci@vger.kernel.org
10845L: linux-arm-kernel@lists.infradead.org 10845L: linux-arm-kernel@lists.infradead.org
10846S: Maintained 10846S: Maintained
10847F: Documentation/devicetree/bindings/pci/xgene-pci.txt 10847F: Documentation/devicetree/bindings/pci/xgene-pci.txt
10848F: drivers/pci/host/pci-xgene.c 10848F: drivers/pci/controller/pci-xgene.c
10849 10849
10850PCI DRIVER FOR ARM VERSATILE PLATFORM 10850PCI DRIVER FOR ARM VERSATILE PLATFORM
10851M: Rob Herring <robh@kernel.org> 10851M: Rob Herring <robh@kernel.org>
@@ -10853,7 +10853,7 @@ L: linux-pci@vger.kernel.org
10853L: linux-arm-kernel@lists.infradead.org 10853L: linux-arm-kernel@lists.infradead.org
10854S: Maintained 10854S: Maintained
10855F: Documentation/devicetree/bindings/pci/versatile.txt 10855F: Documentation/devicetree/bindings/pci/versatile.txt
10856F: drivers/pci/host/pci-versatile.c 10856F: drivers/pci/controller/pci-versatile.c
10857 10857
10858PCI DRIVER FOR ARMADA 8K 10858PCI DRIVER FOR ARMADA 8K
10859M: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> 10859M: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
@@ -10861,14 +10861,14 @@ L: linux-pci@vger.kernel.org
10861L: linux-arm-kernel@lists.infradead.org 10861L: linux-arm-kernel@lists.infradead.org
10862S: Maintained 10862S: Maintained
10863F: Documentation/devicetree/bindings/pci/pci-armada8k.txt 10863F: Documentation/devicetree/bindings/pci/pci-armada8k.txt
10864F: drivers/pci/dwc/pcie-armada8k.c 10864F: drivers/pci/controller/dwc/pcie-armada8k.c
10865 10865
10866PCI DRIVER FOR CADENCE PCIE IP 10866PCI DRIVER FOR CADENCE PCIE IP
10867M: Alan Douglas <adouglas@cadence.com> 10867M: Alan Douglas <adouglas@cadence.com>
10868L: linux-pci@vger.kernel.org 10868L: linux-pci@vger.kernel.org
10869S: Maintained 10869S: Maintained
10870F: Documentation/devicetree/bindings/pci/cdns,*.txt 10870F: Documentation/devicetree/bindings/pci/cdns,*.txt
10871F: drivers/pci/cadence/pcie-cadence* 10871F: drivers/pci/controller/pcie-cadence*
10872 10872
10873PCI DRIVER FOR FREESCALE LAYERSCAPE 10873PCI DRIVER FOR FREESCALE LAYERSCAPE
10874M: Minghuan Lian <minghuan.Lian@nxp.com> 10874M: Minghuan Lian <minghuan.Lian@nxp.com>
@@ -10878,16 +10878,16 @@ L: linuxppc-dev@lists.ozlabs.org
10878L: linux-pci@vger.kernel.org 10878L: linux-pci@vger.kernel.org
10879L: linux-arm-kernel@lists.infradead.org 10879L: linux-arm-kernel@lists.infradead.org
10880S: Maintained 10880S: Maintained
10881F: drivers/pci/dwc/*layerscape* 10881F: drivers/pci/controller/dwc/*layerscape*
10882 10882
10883PCI DRIVER FOR GENERIC OF HOSTS 10883PCI DRIVER FOR GENERIC OF HOSTS
10884M: Will Deacon <will.deacon@arm.com> 10884M: Will Deacon <will.deacon@arm.com>
10885L: linux-pci@vger.kernel.org 10885L: linux-pci@vger.kernel.org
10886L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) 10886L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
10887S: Maintained 10887S: Maintained
10888F: Documentation/devicetree/bindings/pci/host-generic-pci.txt 10888F: Documentation/devicetree/bindings/pci/controller-generic-pci.txt
10889F: drivers/pci/host/pci-host-common.c 10889F: drivers/pci/controller/pci-host-common.c
10890F: drivers/pci/host/pci-host-generic.c 10890F: drivers/pci/controller/pci-host-generic.c
10891 10891
10892PCI DRIVER FOR IMX6 10892PCI DRIVER FOR IMX6
10893M: Richard Zhu <hongxing.zhu@nxp.com> 10893M: Richard Zhu <hongxing.zhu@nxp.com>
@@ -10896,14 +10896,14 @@ L: linux-pci@vger.kernel.org
10896L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) 10896L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
10897S: Maintained 10897S: Maintained
10898F: Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt 10898F: Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt
10899F: drivers/pci/dwc/*imx6* 10899F: drivers/pci/controller/dwc/*imx6*
10900 10900
10901PCI DRIVER FOR INTEL VOLUME MANAGEMENT DEVICE (VMD) 10901PCI DRIVER FOR INTEL VOLUME MANAGEMENT DEVICE (VMD)
10902M: Keith Busch <keith.busch@intel.com> 10902M: Keith Busch <keith.busch@intel.com>
10903M: Jonathan Derrick <jonathan.derrick@intel.com> 10903M: Jonathan Derrick <jonathan.derrick@intel.com>
10904L: linux-pci@vger.kernel.org 10904L: linux-pci@vger.kernel.org
10905S: Supported 10905S: Supported
10906F: drivers/pci/host/vmd.c 10906F: drivers/pci/controller/vmd.c
10907 10907
10908PCI DRIVER FOR MICROSEMI SWITCHTEC 10908PCI DRIVER FOR MICROSEMI SWITCHTEC
10909M: Kurt Schwemmer <kurt.schwemmer@microsemi.com> 10909M: Kurt Schwemmer <kurt.schwemmer@microsemi.com>
@@ -10923,7 +10923,7 @@ M: Jason Cooper <jason@lakedaemon.net>
10923L: linux-pci@vger.kernel.org 10923L: linux-pci@vger.kernel.org
10924L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) 10924L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
10925S: Maintained 10925S: Maintained
10926F: drivers/pci/host/*mvebu* 10926F: drivers/pci/controller/*mvebu*
10927 10927
10928PCI DRIVER FOR NVIDIA TEGRA 10928PCI DRIVER FOR NVIDIA TEGRA
10929M: Thierry Reding <thierry.reding@gmail.com> 10929M: Thierry Reding <thierry.reding@gmail.com>
@@ -10931,14 +10931,14 @@ L: linux-tegra@vger.kernel.org
10931L: linux-pci@vger.kernel.org 10931L: linux-pci@vger.kernel.org
10932S: Supported 10932S: Supported
10933F: Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt 10933F: Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt
10934F: drivers/pci/host/pci-tegra.c 10934F: drivers/pci/controller/pci-tegra.c
10935 10935
10936PCI DRIVER FOR RENESAS R-CAR 10936PCI DRIVER FOR RENESAS R-CAR
10937M: Simon Horman <horms@verge.net.au> 10937M: Simon Horman <horms@verge.net.au>
10938L: linux-pci@vger.kernel.org 10938L: linux-pci@vger.kernel.org
10939L: linux-renesas-soc@vger.kernel.org 10939L: linux-renesas-soc@vger.kernel.org
10940S: Maintained 10940S: Maintained
10941F: drivers/pci/host/*rcar* 10941F: drivers/pci/controller/*rcar*
10942 10942
10943PCI DRIVER FOR SAMSUNG EXYNOS 10943PCI DRIVER FOR SAMSUNG EXYNOS
10944M: Jingoo Han <jingoohan1@gmail.com> 10944M: Jingoo Han <jingoohan1@gmail.com>
@@ -10946,7 +10946,7 @@ L: linux-pci@vger.kernel.org
10946L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) 10946L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
10947L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers) 10947L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
10948S: Maintained 10948S: Maintained
10949F: drivers/pci/dwc/pci-exynos.c 10949F: drivers/pci/controller/dwc/pci-exynos.c
10950 10950
10951PCI DRIVER FOR SYNOPSYS DESIGNWARE 10951PCI DRIVER FOR SYNOPSYS DESIGNWARE
10952M: Jingoo Han <jingoohan1@gmail.com> 10952M: Jingoo Han <jingoohan1@gmail.com>
@@ -10954,7 +10954,7 @@ M: Joao Pinto <Joao.Pinto@synopsys.com>
10954L: linux-pci@vger.kernel.org 10954L: linux-pci@vger.kernel.org
10955S: Maintained 10955S: Maintained
10956F: Documentation/devicetree/bindings/pci/designware-pcie.txt 10956F: Documentation/devicetree/bindings/pci/designware-pcie.txt
10957F: drivers/pci/dwc/*designware* 10957F: drivers/pci/controller/dwc/*designware*
10958 10958
10959PCI DRIVER FOR TI DRA7XX 10959PCI DRIVER FOR TI DRA7XX
10960M: Kishon Vijay Abraham I <kishon@ti.com> 10960M: Kishon Vijay Abraham I <kishon@ti.com>
@@ -10962,14 +10962,14 @@ L: linux-omap@vger.kernel.org
10962L: linux-pci@vger.kernel.org 10962L: linux-pci@vger.kernel.org
10963S: Supported 10963S: Supported
10964F: Documentation/devicetree/bindings/pci/ti-pci.txt 10964F: Documentation/devicetree/bindings/pci/ti-pci.txt
10965F: drivers/pci/dwc/pci-dra7xx.c 10965F: drivers/pci/controller/dwc/pci-dra7xx.c
10966 10966
10967PCI DRIVER FOR TI KEYSTONE 10967PCI DRIVER FOR TI KEYSTONE
10968M: Murali Karicheri <m-karicheri2@ti.com> 10968M: Murali Karicheri <m-karicheri2@ti.com>
10969L: linux-pci@vger.kernel.org 10969L: linux-pci@vger.kernel.org
10970L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) 10970L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
10971S: Maintained 10971S: Maintained
10972F: drivers/pci/dwc/*keystone* 10972F: drivers/pci/controller/dwc/*keystone*
10973 10973
10974PCI ENDPOINT SUBSYSTEM 10974PCI ENDPOINT SUBSYSTEM
10975M: Kishon Vijay Abraham I <kishon@ti.com> 10975M: Kishon Vijay Abraham I <kishon@ti.com>
@@ -11002,7 +11002,7 @@ L: rfi@lists.rocketboards.org (moderated for non-subscribers)
11002L: linux-pci@vger.kernel.org 11002L: linux-pci@vger.kernel.org
11003S: Supported 11003S: Supported
11004F: Documentation/devicetree/bindings/pci/altera-pcie-msi.txt 11004F: Documentation/devicetree/bindings/pci/altera-pcie-msi.txt
11005F: drivers/pci/host/pcie-altera-msi.c 11005F: drivers/pci/controller/pcie-altera-msi.c
11006 11006
11007PCI MSI DRIVER FOR APPLIEDMICRO XGENE 11007PCI MSI DRIVER FOR APPLIEDMICRO XGENE
11008M: Duc Dang <dhdang@apm.com> 11008M: Duc Dang <dhdang@apm.com>
@@ -11010,7 +11010,7 @@ L: linux-pci@vger.kernel.org
11010L: linux-arm-kernel@lists.infradead.org 11010L: linux-arm-kernel@lists.infradead.org
11011S: Maintained 11011S: Maintained
11012F: Documentation/devicetree/bindings/pci/xgene-pci-msi.txt 11012F: Documentation/devicetree/bindings/pci/xgene-pci-msi.txt
11013F: drivers/pci/host/pci-xgene-msi.c 11013F: drivers/pci/controller/pci-xgene-msi.c
11014 11014
11015PCI SUBSYSTEM 11015PCI SUBSYSTEM
11016M: Bjorn Helgaas <bhelgaas@google.com> 11016M: Bjorn Helgaas <bhelgaas@google.com>
@@ -11036,9 +11036,7 @@ L: linux-pci@vger.kernel.org
11036Q: http://patchwork.ozlabs.org/project/linux-pci/list/ 11036Q: http://patchwork.ozlabs.org/project/linux-pci/list/
11037T: git git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/pci.git/ 11037T: git git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/pci.git/
11038S: Supported 11038S: Supported
11039F: drivers/pci/cadence/ 11039F: drivers/pci/controller/
11040F: drivers/pci/host/
11041F: drivers/pci/dwc/
11042 11040
11043PCIE DRIVER FOR AXIS ARTPEC 11041PCIE DRIVER FOR AXIS ARTPEC
11044M: Jesper Nilsson <jesper.nilsson@axis.com> 11042M: Jesper Nilsson <jesper.nilsson@axis.com>
@@ -11046,7 +11044,7 @@ L: linux-arm-kernel@axis.com
11046L: linux-pci@vger.kernel.org 11044L: linux-pci@vger.kernel.org
11047S: Maintained 11045S: Maintained
11048F: Documentation/devicetree/bindings/pci/axis,artpec* 11046F: Documentation/devicetree/bindings/pci/axis,artpec*
11049F: drivers/pci/dwc/*artpec* 11047F: drivers/pci/controller/dwc/*artpec*
11050 11048
11051PCIE DRIVER FOR CAVIUM THUNDERX 11049PCIE DRIVER FOR CAVIUM THUNDERX
11052M: David Daney <david.daney@cavium.com> 11050M: David Daney <david.daney@cavium.com>
@@ -11054,14 +11052,14 @@ L: linux-pci@vger.kernel.org
11054L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) 11052L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
11055S: Supported 11053S: Supported
11056F: Documentation/devicetree/bindings/pci/pci-thunder-* 11054F: Documentation/devicetree/bindings/pci/pci-thunder-*
11057F: drivers/pci/host/pci-thunder-* 11055F: drivers/pci/controller/pci-thunder-*
11058 11056
11059PCIE DRIVER FOR HISILICON 11057PCIE DRIVER FOR HISILICON
11060M: Zhou Wang <wangzhou1@hisilicon.com> 11058M: Zhou Wang <wangzhou1@hisilicon.com>
11061L: linux-pci@vger.kernel.org 11059L: linux-pci@vger.kernel.org
11062S: Maintained 11060S: Maintained
11063F: Documentation/devicetree/bindings/pci/hisilicon-pcie.txt 11061F: Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
11064F: drivers/pci/dwc/pcie-hisi.c 11062F: drivers/pci/controller/dwc/pcie-hisi.c
11065 11063
11066PCIE DRIVER FOR HISILICON KIRIN 11064PCIE DRIVER FOR HISILICON KIRIN
11067M: Xiaowei Song <songxiaowei@hisilicon.com> 11065M: Xiaowei Song <songxiaowei@hisilicon.com>
@@ -11069,7 +11067,7 @@ M: Binghui Wang <wangbinghui@hisilicon.com>
11069L: linux-pci@vger.kernel.org 11067L: linux-pci@vger.kernel.org
11070S: Maintained 11068S: Maintained
11071F: Documentation/devicetree/bindings/pci/pcie-kirin.txt 11069F: Documentation/devicetree/bindings/pci/pcie-kirin.txt
11072F: drivers/pci/dwc/pcie-kirin.c 11070F: drivers/pci/controller/dwc/pcie-kirin.c
11073 11071
11074PCIE DRIVER FOR HISILICON STB 11072PCIE DRIVER FOR HISILICON STB
11075M: Jianguo Sun <sunjianguo1@huawei.com> 11073M: Jianguo Sun <sunjianguo1@huawei.com>
@@ -11077,7 +11075,7 @@ M: Shawn Guo <shawn.guo@linaro.org>
11077L: linux-pci@vger.kernel.org 11075L: linux-pci@vger.kernel.org
11078S: Maintained 11076S: Maintained
11079F: Documentation/devicetree/bindings/pci/hisilicon-histb-pcie.txt 11077F: Documentation/devicetree/bindings/pci/hisilicon-histb-pcie.txt
11080F: drivers/pci/dwc/pcie-histb.c 11078F: drivers/pci/controller/dwc/pcie-histb.c
11081 11079
11082PCIE DRIVER FOR MEDIATEK 11080PCIE DRIVER FOR MEDIATEK
11083M: Ryder Lee <ryder.lee@mediatek.com> 11081M: Ryder Lee <ryder.lee@mediatek.com>
@@ -11085,14 +11083,14 @@ L: linux-pci@vger.kernel.org
11085L: linux-mediatek@lists.infradead.org 11083L: linux-mediatek@lists.infradead.org
11086S: Supported 11084S: Supported
11087F: Documentation/devicetree/bindings/pci/mediatek* 11085F: Documentation/devicetree/bindings/pci/mediatek*
11088F: drivers/pci/host/*mediatek* 11086F: drivers/pci/controller/*mediatek*
11089 11087
11090PCIE DRIVER FOR QUALCOMM MSM 11088PCIE DRIVER FOR QUALCOMM MSM
11091M: Stanimir Varbanov <svarbanov@mm-sol.com> 11089M: Stanimir Varbanov <svarbanov@mm-sol.com>
11092L: linux-pci@vger.kernel.org 11090L: linux-pci@vger.kernel.org
11093L: linux-arm-msm@vger.kernel.org 11091L: linux-arm-msm@vger.kernel.org
11094S: Maintained 11092S: Maintained
11095F: drivers/pci/dwc/*qcom* 11093F: drivers/pci/controller/dwc/*qcom*
11096 11094
11097PCIE DRIVER FOR ROCKCHIP 11095PCIE DRIVER FOR ROCKCHIP
11098M: Shawn Lin <shawn.lin@rock-chips.com> 11096M: Shawn Lin <shawn.lin@rock-chips.com>
@@ -11100,20 +11098,20 @@ L: linux-pci@vger.kernel.org
11100L: linux-rockchip@lists.infradead.org 11098L: linux-rockchip@lists.infradead.org
11101S: Maintained 11099S: Maintained
11102F: Documentation/devicetree/bindings/pci/rockchip-pcie* 11100F: Documentation/devicetree/bindings/pci/rockchip-pcie*
11103F: drivers/pci/host/pcie-rockchip* 11101F: drivers/pci/controller/pcie-rockchip*
11104 11102
11105PCI DRIVER FOR V3 SEMICONDUCTOR V360EPC 11103PCI DRIVER FOR V3 SEMICONDUCTOR V360EPC
11106M: Linus Walleij <linus.walleij@linaro.org> 11104M: Linus Walleij <linus.walleij@linaro.org>
11107L: linux-pci@vger.kernel.org 11105L: linux-pci@vger.kernel.org
11108S: Maintained 11106S: Maintained
11109F: Documentation/devicetree/bindings/pci/v3-v360epc-pci.txt 11107F: Documentation/devicetree/bindings/pci/v3-v360epc-pci.txt
11110F: drivers/pci/host/pci-v3-semi.c 11108F: drivers/pci/controller/pci-v3-semi.c
11111 11109
11112PCIE DRIVER FOR ST SPEAR13XX 11110PCIE DRIVER FOR ST SPEAR13XX
11113M: Pratyush Anand <pratyush.anand@gmail.com> 11111M: Pratyush Anand <pratyush.anand@gmail.com>
11114L: linux-pci@vger.kernel.org 11112L: linux-pci@vger.kernel.org
11115S: Maintained 11113S: Maintained
11116F: drivers/pci/dwc/*spear* 11114F: drivers/pci/controller/dwc/*spear*
11117 11115
11118PCMCIA SUBSYSTEM 11116PCMCIA SUBSYSTEM
11119M: Dominik Brodowski <linux@dominikbrodowski.net> 11117M: Dominik Brodowski <linux@dominikbrodowski.net>
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index b2f07635e94d..56ff8f6d31fc 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -145,8 +145,6 @@ config PCI_HYPERV
145 PCI devices from a PCI backend to support PCI driver domains. 145 PCI devices from a PCI backend to support PCI driver domains.
146 146
147source "drivers/pci/hotplug/Kconfig" 147source "drivers/pci/hotplug/Kconfig"
148source "drivers/pci/cadence/Kconfig" 148source "drivers/pci/controller/Kconfig"
149source "drivers/pci/dwc/Kconfig"
150source "drivers/pci/host/Kconfig"
151source "drivers/pci/endpoint/Kconfig" 149source "drivers/pci/endpoint/Kconfig"
152source "drivers/pci/switch/Kconfig" 150source "drivers/pci/switch/Kconfig"
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 84c9eef6b1c3..535201984b8b 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -28,14 +28,10 @@ obj-$(CONFIG_PCI_PF_STUB) += pci-pf-stub.o
28obj-$(CONFIG_PCI_ECAM) += ecam.o 28obj-$(CONFIG_PCI_ECAM) += ecam.o
29obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o 29obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o
30 30
31obj-y += host/ 31obj-y += controller/
32obj-y += switch/ 32obj-y += switch/
33 33
34# Endpoint library must be initialized before its users 34# Endpoint library must be initialized before its users
35obj-$(CONFIG_PCI_ENDPOINT) += endpoint/ 35obj-$(CONFIG_PCI_ENDPOINT) += endpoint/
36 36
37obj-$(CONFIG_PCIE_CADENCE) += cadence/
38# pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
39obj-y += dwc/
40
41ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG 37ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG
diff --git a/drivers/pci/cadence/Kconfig b/drivers/pci/cadence/Kconfig
deleted file mode 100644
index e6824cb56c16..000000000000
--- a/drivers/pci/cadence/Kconfig
+++ /dev/null
@@ -1,27 +0,0 @@
1menu "Cadence PCIe controllers support"
2
3config PCIE_CADENCE
4 bool
5
6config PCIE_CADENCE_HOST
7 bool "Cadence PCIe host controller"
8 depends on OF
9 depends on PCI
10 select IRQ_DOMAIN
11 select PCIE_CADENCE
12 help
13 Say Y here if you want to support the Cadence PCIe controller in host
14 mode. This PCIe controller may be embedded into many different vendors
15 SoCs.
16
17config PCIE_CADENCE_EP
18 bool "Cadence PCIe endpoint controller"
19 depends on OF
20 depends on PCI_ENDPOINT
21 select PCIE_CADENCE
22 help
23 Say Y here if you want to support the Cadence PCIe controller in
24 endpoint mode. This PCIe controller may be embedded into many
25 different vendors SoCs.
26
27endmenu
diff --git a/drivers/pci/cadence/Makefile b/drivers/pci/cadence/Makefile
deleted file mode 100644
index 719392b97998..000000000000
--- a/drivers/pci/cadence/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
1# SPDX-License-Identifier: GPL-2.0
2obj-$(CONFIG_PCIE_CADENCE) += pcie-cadence.o
3obj-$(CONFIG_PCIE_CADENCE_HOST) += pcie-cadence-host.o
4obj-$(CONFIG_PCIE_CADENCE_EP) += pcie-cadence-ep.o
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/controller/Kconfig
index a96e23bda664..18fa09b3ac8f 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/controller/Kconfig
@@ -1,6 +1,6 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
2 2
3menu "PCI host controller drivers" 3menu "PCI controller drivers"
4 depends on PCI 4 depends on PCI
5 5
6config PCI_MVEBU 6config PCI_MVEBU
@@ -20,6 +20,34 @@ config PCI_AARDVARK
20 controller is part of the South Bridge of the Marvel Armada 20 controller is part of the South Bridge of the Marvel Armada
21 3700 SoC. 21 3700 SoC.
22 22
23menu "Cadence PCIe controllers support"
24
25config PCIE_CADENCE
26 bool
27
28config PCIE_CADENCE_HOST
29 bool "Cadence PCIe host controller"
30 depends on OF
31 depends on PCI
32 select IRQ_DOMAIN
33 select PCIE_CADENCE
34 help
35 Say Y here if you want to support the Cadence PCIe controller in host
36 mode. This PCIe controller may be embedded into many different vendors
37 SoCs.
38
39config PCIE_CADENCE_EP
40 bool "Cadence PCIe endpoint controller"
41 depends on OF
42 depends on PCI_ENDPOINT
43 select PCIE_CADENCE
44 help
45 Say Y here if you want to support the Cadence PCIe controller in
46 endpoint mode. This PCIe controller may be embedded into many
47 different vendors SoCs.
48
49endmenu
50
23config PCIE_XILINX_NWL 51config PCIE_XILINX_NWL
24 bool "NWL PCIe Core" 52 bool "NWL PCIe Core"
25 depends on ARCH_ZYNQMP || COMPILE_TEST 53 depends on ARCH_ZYNQMP || COMPILE_TEST
@@ -243,4 +271,5 @@ config VMD
243 To compile this driver as a module, choose M here: the 271 To compile this driver as a module, choose M here: the
244 module will be called vmd. 272 module will be called vmd.
245 273
274source "drivers/pci/controller/dwc/Kconfig"
246endmenu 275endmenu
diff --git a/drivers/pci/host/Makefile b/drivers/pci/controller/Makefile
index 11d21b026d37..24322b92f200 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/controller/Makefile
@@ -1,4 +1,7 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
2obj-$(CONFIG_PCIE_CADENCE) += pcie-cadence.o
3obj-$(CONFIG_PCIE_CADENCE_HOST) += pcie-cadence-host.o
4obj-$(CONFIG_PCIE_CADENCE_EP) += pcie-cadence-ep.o
2obj-$(CONFIG_PCI_FTPCI100) += pci-ftpci100.o 5obj-$(CONFIG_PCI_FTPCI100) += pci-ftpci100.o
3obj-$(CONFIG_PCI_HYPERV) += pci-hyperv.o 6obj-$(CONFIG_PCI_HYPERV) += pci-hyperv.o
4obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o 7obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
@@ -25,6 +28,9 @@ obj-$(CONFIG_PCIE_ROCKCHIP_HOST) += pcie-rockchip-host.o
25obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o 28obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o
26obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o 29obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o
27obj-$(CONFIG_VMD) += vmd.o 30obj-$(CONFIG_VMD) += vmd.o
31# pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
32obj-y += dwc/
33
28 34
29# The following drivers are for devices that use the generic ACPI 35# The following drivers are for devices that use the generic ACPI
30# pci_root.c driver but don't support standard ECAM config access. 36# pci_root.c driver but don't support standard ECAM config access.
diff --git a/drivers/pci/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
index 16f52c626b4b..16f52c626b4b 100644
--- a/drivers/pci/dwc/Kconfig
+++ b/drivers/pci/controller/dwc/Kconfig
diff --git a/drivers/pci/dwc/Makefile b/drivers/pci/controller/dwc/Makefile
index 5d2ce72c7a52..5d2ce72c7a52 100644
--- a/drivers/pci/dwc/Makefile
+++ b/drivers/pci/controller/dwc/Makefile
diff --git a/drivers/pci/dwc/pci-dra7xx.c b/drivers/pci/controller/dwc/pci-dra7xx.c
index f688204e50c5..cfaeef81d868 100644
--- a/drivers/pci/dwc/pci-dra7xx.c
+++ b/drivers/pci/controller/dwc/pci-dra7xx.c
@@ -27,7 +27,7 @@
27#include <linux/mfd/syscon.h> 27#include <linux/mfd/syscon.h>
28#include <linux/regmap.h> 28#include <linux/regmap.h>
29 29
30#include "../pci.h" 30#include "../../pci.h"
31#include "pcie-designware.h" 31#include "pcie-designware.h"
32 32
33/* PCIe controller wrapper DRA7XX configuration registers */ 33/* PCIe controller wrapper DRA7XX configuration registers */
diff --git a/drivers/pci/dwc/pci-exynos.c b/drivers/pci/controller/dwc/pci-exynos.c
index 4cc1e5df8c79..4cc1e5df8c79 100644
--- a/drivers/pci/dwc/pci-exynos.c
+++ b/drivers/pci/controller/dwc/pci-exynos.c
diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index 80f604602783..80f604602783 100644
--- a/drivers/pci/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
diff --git a/drivers/pci/dwc/pci-keystone-dw.c b/drivers/pci/controller/dwc/pci-keystone-dw.c
index 0682213328e9..0682213328e9 100644
--- a/drivers/pci/dwc/pci-keystone-dw.c
+++ b/drivers/pci/controller/dwc/pci-keystone-dw.c
diff --git a/drivers/pci/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index 3722a5f31e5e..3722a5f31e5e 100644
--- a/drivers/pci/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
diff --git a/drivers/pci/dwc/pci-keystone.h b/drivers/pci/controller/dwc/pci-keystone.h
index 8a13da391543..8a13da391543 100644
--- a/drivers/pci/dwc/pci-keystone.h
+++ b/drivers/pci/controller/dwc/pci-keystone.h
diff --git a/drivers/pci/dwc/pci-layerscape.c b/drivers/pci/controller/dwc/pci-layerscape.c
index 3724d3ef7008..3724d3ef7008 100644
--- a/drivers/pci/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
diff --git a/drivers/pci/dwc/pcie-armada8k.c b/drivers/pci/controller/dwc/pcie-armada8k.c
index 072fd7ecc29f..072fd7ecc29f 100644
--- a/drivers/pci/dwc/pcie-armada8k.c
+++ b/drivers/pci/controller/dwc/pcie-armada8k.c
diff --git a/drivers/pci/dwc/pcie-artpec6.c b/drivers/pci/controller/dwc/pcie-artpec6.c
index 321b56cfd5d0..321b56cfd5d0 100644
--- a/drivers/pci/dwc/pcie-artpec6.c
+++ b/drivers/pci/controller/dwc/pcie-artpec6.c
diff --git a/drivers/pci/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 1eec4415a77f..1eec4415a77f 100644
--- a/drivers/pci/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
diff --git a/drivers/pci/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index cba1432e395d..781aa03aeede 100644
--- a/drivers/pci/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -15,7 +15,7 @@
15#include <linux/pci_regs.h> 15#include <linux/pci_regs.h>
16#include <linux/platform_device.h> 16#include <linux/platform_device.h>
17 17
18#include "../pci.h" 18#include "../../pci.h"
19#include "pcie-designware.h" 19#include "pcie-designware.h"
20 20
21static struct pci_ops dw_pcie_ops; 21static struct pci_ops dw_pcie_ops;
diff --git a/drivers/pci/dwc/pcie-designware-plat.c b/drivers/pci/controller/dwc/pcie-designware-plat.c
index 5937fed4c938..5937fed4c938 100644
--- a/drivers/pci/dwc/pcie-designware-plat.c
+++ b/drivers/pci/controller/dwc/pcie-designware-plat.c
diff --git a/drivers/pci/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index 778c4f76a884..778c4f76a884 100644
--- a/drivers/pci/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
diff --git a/drivers/pci/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index bee4e2535a61..bee4e2535a61 100644
--- a/drivers/pci/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
diff --git a/drivers/pci/dwc/pcie-hisi.c b/drivers/pci/controller/dwc/pcie-hisi.c
index 2658aaebb993..6d9e1b2b8f7b 100644
--- a/drivers/pci/dwc/pcie-hisi.c
+++ b/drivers/pci/controller/dwc/pcie-hisi.c
@@ -19,7 +19,7 @@
19#include <linux/pci-acpi.h> 19#include <linux/pci-acpi.h>
20#include <linux/pci-ecam.h> 20#include <linux/pci-ecam.h>
21#include <linux/regmap.h> 21#include <linux/regmap.h>
22#include "../pci.h" 22#include "../../pci.h"
23 23
24#if defined(CONFIG_PCI_HISI) || (defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)) 24#if defined(CONFIG_PCI_HISI) || (defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS))
25 25
diff --git a/drivers/pci/dwc/pcie-histb.c b/drivers/pci/controller/dwc/pcie-histb.c
index 3611d6ce9a92..3611d6ce9a92 100644
--- a/drivers/pci/dwc/pcie-histb.c
+++ b/drivers/pci/controller/dwc/pcie-histb.c
diff --git a/drivers/pci/dwc/pcie-kirin.c b/drivers/pci/controller/dwc/pcie-kirin.c
index d2970a009eb5..d2970a009eb5 100644
--- a/drivers/pci/dwc/pcie-kirin.c
+++ b/drivers/pci/controller/dwc/pcie-kirin.c
diff --git a/drivers/pci/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
index a1d0198081a6..a1d0198081a6 100644
--- a/drivers/pci/dwc/pcie-qcom.c
+++ b/drivers/pci/controller/dwc/pcie-qcom.c
diff --git a/drivers/pci/dwc/pcie-spear13xx.c b/drivers/pci/controller/dwc/pcie-spear13xx.c
index ecb58f7b7566..ecb58f7b7566 100644
--- a/drivers/pci/dwc/pcie-spear13xx.c
+++ b/drivers/pci/controller/dwc/pcie-spear13xx.c
diff --git a/drivers/pci/host/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
index d3172d5d3d35..d3172d5d3d35 100644
--- a/drivers/pci/host/pci-aardvark.c
+++ b/drivers/pci/controller/pci-aardvark.c
diff --git a/drivers/pci/host/pci-ftpci100.c b/drivers/pci/controller/pci-ftpci100.c
index a1ebe9ed441f..a1ebe9ed441f 100644
--- a/drivers/pci/host/pci-ftpci100.c
+++ b/drivers/pci/controller/pci-ftpci100.c
diff --git a/drivers/pci/host/pci-host-common.c b/drivers/pci/controller/pci-host-common.c
index d8f10451f273..d8f10451f273 100644
--- a/drivers/pci/host/pci-host-common.c
+++ b/drivers/pci/controller/pci-host-common.c
diff --git a/drivers/pci/host/pci-host-generic.c b/drivers/pci/controller/pci-host-generic.c
index dea3ec7592a2..dea3ec7592a2 100644
--- a/drivers/pci/host/pci-host-generic.c
+++ b/drivers/pci/controller/pci-host-generic.c
diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
index 6cc5036ac83c..6cc5036ac83c 100644
--- a/drivers/pci/host/pci-hyperv.c
+++ b/drivers/pci/controller/pci-hyperv.c
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index 23e270839e6a..23e270839e6a 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
diff --git a/drivers/pci/host/pci-rcar-gen2.c b/drivers/pci/controller/pci-rcar-gen2.c
index 326171cb1a97..326171cb1a97 100644
--- a/drivers/pci/host/pci-rcar-gen2.c
+++ b/drivers/pci/controller/pci-rcar-gen2.c
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/controller/pci-tegra.c
index f4f53d092e00..f4f53d092e00 100644
--- a/drivers/pci/host/pci-tegra.c
+++ b/drivers/pci/controller/pci-tegra.c
diff --git a/drivers/pci/host/pci-thunder-ecam.c b/drivers/pci/controller/pci-thunder-ecam.c
index 32d1d7b81ef4..32d1d7b81ef4 100644
--- a/drivers/pci/host/pci-thunder-ecam.c
+++ b/drivers/pci/controller/pci-thunder-ecam.c
diff --git a/drivers/pci/host/pci-thunder-pem.c b/drivers/pci/controller/pci-thunder-pem.c
index f127ce8bd4ef..f127ce8bd4ef 100644
--- a/drivers/pci/host/pci-thunder-pem.c
+++ b/drivers/pci/controller/pci-thunder-pem.c
diff --git a/drivers/pci/host/pci-v3-semi.c b/drivers/pci/controller/pci-v3-semi.c
index 68b8bfbdb867..68b8bfbdb867 100644
--- a/drivers/pci/host/pci-v3-semi.c
+++ b/drivers/pci/controller/pci-v3-semi.c
diff --git a/drivers/pci/host/pci-versatile.c b/drivers/pci/controller/pci-versatile.c
index 994f32061b32..994f32061b32 100644
--- a/drivers/pci/host/pci-versatile.c
+++ b/drivers/pci/controller/pci-versatile.c
diff --git a/drivers/pci/host/pci-xgene-msi.c b/drivers/pci/controller/pci-xgene-msi.c
index f4c02da84e59..f4c02da84e59 100644
--- a/drivers/pci/host/pci-xgene-msi.c
+++ b/drivers/pci/controller/pci-xgene-msi.c
diff --git a/drivers/pci/host/pci-xgene.c b/drivers/pci/controller/pci-xgene.c
index d854d67e873c..d854d67e873c 100644
--- a/drivers/pci/host/pci-xgene.c
+++ b/drivers/pci/controller/pci-xgene.c
diff --git a/drivers/pci/host/pcie-altera-msi.c b/drivers/pci/controller/pcie-altera-msi.c
index 025ef7d9a046..025ef7d9a046 100644
--- a/drivers/pci/host/pcie-altera-msi.c
+++ b/drivers/pci/controller/pcie-altera-msi.c
diff --git a/drivers/pci/host/pcie-altera.c b/drivers/pci/controller/pcie-altera.c
index 7d05e51205b3..7d05e51205b3 100644
--- a/drivers/pci/host/pcie-altera.c
+++ b/drivers/pci/controller/pcie-altera.c
diff --git a/drivers/pci/cadence/pcie-cadence-ep.c b/drivers/pci/controller/pcie-cadence-ep.c
index 3d8283e450a9..3d8283e450a9 100644
--- a/drivers/pci/cadence/pcie-cadence-ep.c
+++ b/drivers/pci/controller/pcie-cadence-ep.c
diff --git a/drivers/pci/cadence/pcie-cadence-host.c b/drivers/pci/controller/pcie-cadence-host.c
index a4ebbd37b553..a4ebbd37b553 100644
--- a/drivers/pci/cadence/pcie-cadence-host.c
+++ b/drivers/pci/controller/pcie-cadence-host.c
diff --git a/drivers/pci/cadence/pcie-cadence.c b/drivers/pci/controller/pcie-cadence.c
index 138d113eb45d..138d113eb45d 100644
--- a/drivers/pci/cadence/pcie-cadence.c
+++ b/drivers/pci/controller/pcie-cadence.c
diff --git a/drivers/pci/cadence/pcie-cadence.h b/drivers/pci/controller/pcie-cadence.h
index 4bb27333b05c..4bb27333b05c 100644
--- a/drivers/pci/cadence/pcie-cadence.h
+++ b/drivers/pci/controller/pcie-cadence.h
diff --git a/drivers/pci/host/pcie-iproc-bcma.c b/drivers/pci/controller/pcie-iproc-bcma.c
index aa55b064f64d..aa55b064f64d 100644
--- a/drivers/pci/host/pcie-iproc-bcma.c
+++ b/drivers/pci/controller/pcie-iproc-bcma.c
diff --git a/drivers/pci/host/pcie-iproc-msi.c b/drivers/pci/controller/pcie-iproc-msi.c
index 9deb56989d72..9deb56989d72 100644
--- a/drivers/pci/host/pcie-iproc-msi.c
+++ b/drivers/pci/controller/pcie-iproc-msi.c
diff --git a/drivers/pci/host/pcie-iproc-platform.c b/drivers/pci/controller/pcie-iproc-platform.c
index f30f5f3fb5c1..f30f5f3fb5c1 100644
--- a/drivers/pci/host/pcie-iproc-platform.c
+++ b/drivers/pci/controller/pcie-iproc-platform.c
diff --git a/drivers/pci/host/pcie-iproc.c b/drivers/pci/controller/pcie-iproc.c
index 3c76c5fa4f32..3c76c5fa4f32 100644
--- a/drivers/pci/host/pcie-iproc.c
+++ b/drivers/pci/controller/pcie-iproc.c
diff --git a/drivers/pci/host/pcie-iproc.h b/drivers/pci/controller/pcie-iproc.h
index 814b600b383a..814b600b383a 100644
--- a/drivers/pci/host/pcie-iproc.h
+++ b/drivers/pci/controller/pcie-iproc.h
diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/controller/pcie-mediatek.c
index 0baabe30858f..0baabe30858f 100644
--- a/drivers/pci/host/pcie-mediatek.c
+++ b/drivers/pci/controller/pcie-mediatek.c
diff --git a/drivers/pci/host/pcie-mobiveil.c b/drivers/pci/controller/pcie-mobiveil.c
index 4d6c20e47bed..4d6c20e47bed 100644
--- a/drivers/pci/host/pcie-mobiveil.c
+++ b/drivers/pci/controller/pcie-mobiveil.c
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/controller/pcie-rcar.c
index 874d75c9ee4a..874d75c9ee4a 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/controller/pcie-rcar.c
diff --git a/drivers/pci/host/pcie-rockchip-ep.c b/drivers/pci/controller/pcie-rockchip-ep.c
index fc267a49a932..fc267a49a932 100644
--- a/drivers/pci/host/pcie-rockchip-ep.c
+++ b/drivers/pci/controller/pcie-rockchip-ep.c
diff --git a/drivers/pci/host/pcie-rockchip-host.c b/drivers/pci/controller/pcie-rockchip-host.c
index 1372d270764f..1372d270764f 100644
--- a/drivers/pci/host/pcie-rockchip-host.c
+++ b/drivers/pci/controller/pcie-rockchip-host.c
diff --git a/drivers/pci/host/pcie-rockchip.c b/drivers/pci/controller/pcie-rockchip.c
index c53d1322a3d6..c53d1322a3d6 100644
--- a/drivers/pci/host/pcie-rockchip.c
+++ b/drivers/pci/controller/pcie-rockchip.c
diff --git a/drivers/pci/host/pcie-rockchip.h b/drivers/pci/controller/pcie-rockchip.h
index 8e87a059ce73..8e87a059ce73 100644
--- a/drivers/pci/host/pcie-rockchip.h
+++ b/drivers/pci/controller/pcie-rockchip.h
diff --git a/drivers/pci/host/pcie-tango.c b/drivers/pci/controller/pcie-tango.c
index 21a208da3f59..21a208da3f59 100644
--- a/drivers/pci/host/pcie-tango.c
+++ b/drivers/pci/controller/pcie-tango.c
diff --git a/drivers/pci/host/pcie-xilinx-nwl.c b/drivers/pci/controller/pcie-xilinx-nwl.c
index 6a4bbb5b3de0..6a4bbb5b3de0 100644
--- a/drivers/pci/host/pcie-xilinx-nwl.c
+++ b/drivers/pci/controller/pcie-xilinx-nwl.c
diff --git a/drivers/pci/host/pcie-xilinx.c b/drivers/pci/controller/pcie-xilinx.c
index b110a3a814e3..b110a3a814e3 100644
--- a/drivers/pci/host/pcie-xilinx.c
+++ b/drivers/pci/controller/pcie-xilinx.c
diff --git a/drivers/pci/host/vmd.c b/drivers/pci/controller/vmd.c
index 942b64fc7f1f..942b64fc7f1f 100644
--- a/drivers/pci/host/vmd.c
+++ b/drivers/pci/controller/vmd.c
diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig
index b12e28b3d8f9..0a1e9d379bc5 100644
--- a/drivers/pci/pcie/Kconfig
+++ b/drivers/pci/pcie/Kconfig
@@ -23,7 +23,42 @@ config HOTPLUG_PCI_PCIE
23 23
24 When in doubt, say N. 24 When in doubt, say N.
25 25
26source "drivers/pci/pcie/aer/Kconfig" 26config PCIEAER
27 bool "PCI Express Advanced Error Reporting support"
28 depends on PCIEPORTBUS
29 select RAS
30 default y
31 help
32 This enables PCI Express Root Port Advanced Error Reporting
33 (AER) driver support. Error reporting messages sent to Root
34 Port will be handled by PCI Express AER driver.
35
36config PCIEAER_INJECT
37 tristate "PCI Express error injection support"
38 depends on PCIEAER
39 default n
40 help
41 This enables PCI Express Root Port Advanced Error Reporting
42 (AER) software error injector.
43
44 Debugging AER code is quite difficult because it is hard
45 to trigger various real hardware errors. Software-based
46 error injection can fake almost all kinds of errors with the
47 help of a user space helper tool aer-inject, which can be
48 gotten from:
49 http://www.kernel.org/pub/linux/utils/pci/aer-inject/
50
51#
52# PCI Express ECRC
53#
54config PCIE_ECRC
55 bool "PCI Express ECRC settings control"
56 depends on PCIEAER
57 help
58 Used to override firmware/bios settings for PCI Express ECRC
59 (transaction layer end-to-end CRC checking).
60
61 When in doubt, say N.
27 62
28# 63#
29# PCI Express ASPM 64# PCI Express ASPM
@@ -92,7 +127,7 @@ config PCIE_PME
92 depends on PCIEPORTBUS && PM 127 depends on PCIEPORTBUS && PM
93 128
94config PCIE_DPC 129config PCIE_DPC
95 bool "PCIe Downstream Port Containment support" 130 bool "PCI Express Downstream Port Containment support"
96 depends on PCIEPORTBUS && PCIEAER 131 depends on PCIEPORTBUS && PCIEAER
97 default n 132 default n
98 help 133 help
@@ -103,7 +138,7 @@ config PCIE_DPC
103 it is safe to answer N. 138 it is safe to answer N.
104 139
105config PCIE_PTM 140config PCIE_PTM
106 bool "PCIe Precision Time Measurement support" 141 bool "PCI Express Precision Time Measurement support"
107 default n 142 default n
108 depends on PCIEPORTBUS 143 depends on PCIEPORTBUS
109 help 144 help
diff --git a/drivers/pci/pcie/Makefile b/drivers/pci/pcie/Makefile
index 03f4e0b3a140..ab514083d5d4 100644
--- a/drivers/pci/pcie/Makefile
+++ b/drivers/pci/pcie/Makefile
@@ -7,7 +7,8 @@ pcieportdrv-y := portdrv_core.o portdrv_pci.o err.o
7obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o 7obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o
8 8
9obj-$(CONFIG_PCIEASPM) += aspm.o 9obj-$(CONFIG_PCIEASPM) += aspm.o
10obj-$(CONFIG_PCIEAER) += aer/ 10obj-$(CONFIG_PCIEAER) += aer.o
11obj-$(CONFIG_PCIEAER_INJECT) += aer_inject.o
11obj-$(CONFIG_PCIE_PME) += pme.o 12obj-$(CONFIG_PCIE_PME) += pme.o
12obj-$(CONFIG_PCIE_DPC) += dpc.o 13obj-$(CONFIG_PCIE_DPC) += dpc.o
13obj-$(CONFIG_PCIE_PTM) += ptm.o 14obj-$(CONFIG_PCIE_PTM) += ptm.o
diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
new file mode 100644
index 000000000000..a2e88386af28
--- /dev/null
+++ b/drivers/pci/pcie/aer.c
@@ -0,0 +1,1377 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Implement the AER root port service driver. The driver registers an IRQ
4 * handler. When a root port triggers an AER interrupt, the IRQ handler
5 * collects root port status and schedules work.
6 *
7 * Copyright (C) 2006 Intel Corp.
8 * Tom Long Nguyen (tom.l.nguyen@intel.com)
9 * Zhang Yanmin (yanmin.zhang@intel.com)
10 *
11 * (C) Copyright 2009 Hewlett-Packard Development Company, L.P.
12 * Andrew Patterson <andrew.patterson@hp.com>
13 */
14
15#include <linux/cper.h>
16#include <linux/pci.h>
17#include <linux/pci-acpi.h>
18#include <linux/sched.h>
19#include <linux/kernel.h>
20#include <linux/errno.h>
21#include <linux/pm.h>
22#include <linux/init.h>
23#include <linux/interrupt.h>
24#include <linux/delay.h>
25#include <linux/kfifo.h>
26#include <linux/slab.h>
27#include <acpi/apei.h>
28#include <ras/ras_event.h>
29
30#include "../pci.h"
31#include "portdrv.h"
32
33#define AER_ERROR_SOURCES_MAX 100
34#define AER_MAX_MULTI_ERR_DEVICES 5 /* Not likely to have more */
35
36struct aer_err_info {
37 struct pci_dev *dev[AER_MAX_MULTI_ERR_DEVICES];
38 int error_dev_num;
39
40 unsigned int id:16;
41
42 unsigned int severity:2; /* 0:NONFATAL | 1:FATAL | 2:COR */
43 unsigned int __pad1:5;
44 unsigned int multi_error_valid:1;
45
46 unsigned int first_error:5;
47 unsigned int __pad2:2;
48 unsigned int tlp_header_valid:1;
49
50 unsigned int status; /* COR/UNCOR Error Status */
51 unsigned int mask; /* COR/UNCOR Error Mask */
52 struct aer_header_log_regs tlp; /* TLP Header */
53};
54
55struct aer_err_source {
56 unsigned int status;
57 unsigned int id;
58};
59
60struct aer_rpc {
61 struct pci_dev *rpd; /* Root Port device */
62 struct work_struct dpc_handler;
63 struct aer_err_source e_sources[AER_ERROR_SOURCES_MAX];
64 struct aer_err_info e_info;
65 unsigned short prod_idx; /* Error Producer Index */
66 unsigned short cons_idx; /* Error Consumer Index */
67 int isr;
68 spinlock_t e_lock; /*
69 * Lock access to Error Status/ID Regs
70 * and error producer/consumer index
71 */
72 struct mutex rpc_mutex; /*
73 * only one thread could do
74 * recovery on the same
75 * root port hierarchy
76 */
77};
78
79#define AER_LOG_TLP_MASKS (PCI_ERR_UNC_POISON_TLP| \
80 PCI_ERR_UNC_ECRC| \
81 PCI_ERR_UNC_UNSUP| \
82 PCI_ERR_UNC_COMP_ABORT| \
83 PCI_ERR_UNC_UNX_COMP| \
84 PCI_ERR_UNC_MALF_TLP)
85
86#define SYSTEM_ERROR_INTR_ON_MESG_MASK (PCI_EXP_RTCTL_SECEE| \
87 PCI_EXP_RTCTL_SENFEE| \
88 PCI_EXP_RTCTL_SEFEE)
89#define ROOT_PORT_INTR_ON_MESG_MASK (PCI_ERR_ROOT_CMD_COR_EN| \
90 PCI_ERR_ROOT_CMD_NONFATAL_EN| \
91 PCI_ERR_ROOT_CMD_FATAL_EN)
92#define ERR_COR_ID(d) (d & 0xffff)
93#define ERR_UNCOR_ID(d) (d >> 16)
94
95static int pcie_aer_disable;
96
97void pci_no_aer(void)
98{
99 pcie_aer_disable = 1;
100}
101
102bool pci_aer_available(void)
103{
104 return !pcie_aer_disable && pci_msi_enabled();
105}
106
107#ifdef CONFIG_PCIE_ECRC
108
109#define ECRC_POLICY_DEFAULT 0 /* ECRC set by BIOS */
110#define ECRC_POLICY_OFF 1 /* ECRC off for performance */
111#define ECRC_POLICY_ON 2 /* ECRC on for data integrity */
112
113static int ecrc_policy = ECRC_POLICY_DEFAULT;
114
115static const char *ecrc_policy_str[] = {
116 [ECRC_POLICY_DEFAULT] = "bios",
117 [ECRC_POLICY_OFF] = "off",
118 [ECRC_POLICY_ON] = "on"
119};
120
121/**
122 * enable_ercr_checking - enable PCIe ECRC checking for a device
123 * @dev: the PCI device
124 *
125 * Returns 0 on success, or negative on failure.
126 */
127static int enable_ecrc_checking(struct pci_dev *dev)
128{
129 int pos;
130 u32 reg32;
131
132 if (!pci_is_pcie(dev))
133 return -ENODEV;
134
135 pos = dev->aer_cap;
136 if (!pos)
137 return -ENODEV;
138
139 pci_read_config_dword(dev, pos + PCI_ERR_CAP, &reg32);
140 if (reg32 & PCI_ERR_CAP_ECRC_GENC)
141 reg32 |= PCI_ERR_CAP_ECRC_GENE;
142 if (reg32 & PCI_ERR_CAP_ECRC_CHKC)
143 reg32 |= PCI_ERR_CAP_ECRC_CHKE;
144 pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32);
145
146 return 0;
147}
148
149/**
150 * disable_ercr_checking - disables PCIe ECRC checking for a device
151 * @dev: the PCI device
152 *
153 * Returns 0 on success, or negative on failure.
154 */
155static int disable_ecrc_checking(struct pci_dev *dev)
156{
157 int pos;
158 u32 reg32;
159
160 if (!pci_is_pcie(dev))
161 return -ENODEV;
162
163 pos = dev->aer_cap;
164 if (!pos)
165 return -ENODEV;
166
167 pci_read_config_dword(dev, pos + PCI_ERR_CAP, &reg32);
168 reg32 &= ~(PCI_ERR_CAP_ECRC_GENE | PCI_ERR_CAP_ECRC_CHKE);
169 pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32);
170
171 return 0;
172}
173
174/**
175 * pcie_set_ecrc_checking - set/unset PCIe ECRC checking for a device based on global policy
176 * @dev: the PCI device
177 */
178void pcie_set_ecrc_checking(struct pci_dev *dev)
179{
180 switch (ecrc_policy) {
181 case ECRC_POLICY_DEFAULT:
182 return;
183 case ECRC_POLICY_OFF:
184 disable_ecrc_checking(dev);
185 break;
186 case ECRC_POLICY_ON:
187 enable_ecrc_checking(dev);
188 break;
189 default:
190 return;
191 }
192}
193
194/**
195 * pcie_ecrc_get_policy - parse kernel command-line ecrc option
196 */
197void pcie_ecrc_get_policy(char *str)
198{
199 int i;
200
201 for (i = 0; i < ARRAY_SIZE(ecrc_policy_str); i++)
202 if (!strncmp(str, ecrc_policy_str[i],
203 strlen(ecrc_policy_str[i])))
204 break;
205 if (i >= ARRAY_SIZE(ecrc_policy_str))
206 return;
207
208 ecrc_policy = i;
209}
210#endif /* CONFIG_PCIE_ECRC */
211
212#ifdef CONFIG_ACPI_APEI
213static inline int hest_match_pci(struct acpi_hest_aer_common *p,
214 struct pci_dev *pci)
215{
216 return ACPI_HEST_SEGMENT(p->bus) == pci_domain_nr(pci->bus) &&
217 ACPI_HEST_BUS(p->bus) == pci->bus->number &&
218 p->device == PCI_SLOT(pci->devfn) &&
219 p->function == PCI_FUNC(pci->devfn);
220}
221
222static inline bool hest_match_type(struct acpi_hest_header *hest_hdr,
223 struct pci_dev *dev)
224{
225 u16 hest_type = hest_hdr->type;
226 u8 pcie_type = pci_pcie_type(dev);
227
228 if ((hest_type == ACPI_HEST_TYPE_AER_ROOT_PORT &&
229 pcie_type == PCI_EXP_TYPE_ROOT_PORT) ||
230 (hest_type == ACPI_HEST_TYPE_AER_ENDPOINT &&
231 pcie_type == PCI_EXP_TYPE_ENDPOINT) ||
232 (hest_type == ACPI_HEST_TYPE_AER_BRIDGE &&
233 (dev->class >> 16) == PCI_BASE_CLASS_BRIDGE))
234 return true;
235 return false;
236}
237
238struct aer_hest_parse_info {
239 struct pci_dev *pci_dev;
240 int firmware_first;
241};
242
243static int hest_source_is_pcie_aer(struct acpi_hest_header *hest_hdr)
244{
245 if (hest_hdr->type == ACPI_HEST_TYPE_AER_ROOT_PORT ||
246 hest_hdr->type == ACPI_HEST_TYPE_AER_ENDPOINT ||
247 hest_hdr->type == ACPI_HEST_TYPE_AER_BRIDGE)
248 return 1;
249 return 0;
250}
251
252static int aer_hest_parse(struct acpi_hest_header *hest_hdr, void *data)
253{
254 struct aer_hest_parse_info *info = data;
255 struct acpi_hest_aer_common *p;
256 int ff;
257
258 if (!hest_source_is_pcie_aer(hest_hdr))
259 return 0;
260
261 p = (struct acpi_hest_aer_common *)(hest_hdr + 1);
262 ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
263
264 /*
265 * If no specific device is supplied, determine whether
266 * FIRMWARE_FIRST is set for *any* PCIe device.
267 */
268 if (!info->pci_dev) {
269 info->firmware_first |= ff;
270 return 0;
271 }
272
273 /* Otherwise, check the specific device */
274 if (p->flags & ACPI_HEST_GLOBAL) {
275 if (hest_match_type(hest_hdr, info->pci_dev))
276 info->firmware_first = ff;
277 } else
278 if (hest_match_pci(p, info->pci_dev))
279 info->firmware_first = ff;
280
281 return 0;
282}
283
284static void aer_set_firmware_first(struct pci_dev *pci_dev)
285{
286 int rc;
287 struct aer_hest_parse_info info = {
288 .pci_dev = pci_dev,
289 .firmware_first = 0,
290 };
291
292 rc = apei_hest_parse(aer_hest_parse, &info);
293
294 if (rc)
295 pci_dev->__aer_firmware_first = 0;
296 else
297 pci_dev->__aer_firmware_first = info.firmware_first;
298 pci_dev->__aer_firmware_first_valid = 1;
299}
300
301int pcie_aer_get_firmware_first(struct pci_dev *dev)
302{
303 if (!pci_is_pcie(dev))
304 return 0;
305
306 if (!dev->__aer_firmware_first_valid)
307 aer_set_firmware_first(dev);
308 return dev->__aer_firmware_first;
309}
310#define PCI_EXP_AER_FLAGS (PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | \
311 PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE)
312
313static bool aer_firmware_first;
314
315/**
316 * aer_acpi_firmware_first - Check if APEI should control AER.
317 */
318bool aer_acpi_firmware_first(void)
319{
320 static bool parsed = false;
321 struct aer_hest_parse_info info = {
322 .pci_dev = NULL, /* Check all PCIe devices */
323 .firmware_first = 0,
324 };
325
326 if (!parsed) {
327 apei_hest_parse(aer_hest_parse, &info);
328 aer_firmware_first = info.firmware_first;
329 parsed = true;
330 }
331 return aer_firmware_first;
332}
333#endif
334
335#define PCI_EXP_AER_FLAGS (PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | \
336 PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE)
337
338int pci_enable_pcie_error_reporting(struct pci_dev *dev)
339{
340 if (pcie_aer_get_firmware_first(dev))
341 return -EIO;
342
343 if (!dev->aer_cap)
344 return -EIO;
345
346 return pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_AER_FLAGS);
347}
348EXPORT_SYMBOL_GPL(pci_enable_pcie_error_reporting);
349
350int pci_disable_pcie_error_reporting(struct pci_dev *dev)
351{
352 if (pcie_aer_get_firmware_first(dev))
353 return -EIO;
354
355 return pcie_capability_clear_word(dev, PCI_EXP_DEVCTL,
356 PCI_EXP_AER_FLAGS);
357}
358EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting);
359
360int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
361{
362 int pos;
363 u32 status;
364
365 pos = dev->aer_cap;
366 if (!pos)
367 return -EIO;
368
369 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
370 if (status)
371 pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
372
373 return 0;
374}
375EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status);
376
377int pci_cleanup_aer_error_status_regs(struct pci_dev *dev)
378{
379 int pos;
380 u32 status;
381 int port_type;
382
383 if (!pci_is_pcie(dev))
384 return -ENODEV;
385
386 pos = dev->aer_cap;
387 if (!pos)
388 return -EIO;
389
390 port_type = pci_pcie_type(dev);
391 if (port_type == PCI_EXP_TYPE_ROOT_PORT) {
392 pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &status);
393 pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, status);
394 }
395
396 pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &status);
397 pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, status);
398
399 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
400 pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
401
402 return 0;
403}
404
405int pci_aer_init(struct pci_dev *dev)
406{
407 dev->aer_cap = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
408 return pci_cleanup_aer_error_status_regs(dev);
409}
410
411#define AER_AGENT_RECEIVER 0
412#define AER_AGENT_REQUESTER 1
413#define AER_AGENT_COMPLETER 2
414#define AER_AGENT_TRANSMITTER 3
415
416#define AER_AGENT_REQUESTER_MASK(t) ((t == AER_CORRECTABLE) ? \
417 0 : (PCI_ERR_UNC_COMP_TIME|PCI_ERR_UNC_UNSUP))
418#define AER_AGENT_COMPLETER_MASK(t) ((t == AER_CORRECTABLE) ? \
419 0 : PCI_ERR_UNC_COMP_ABORT)
420#define AER_AGENT_TRANSMITTER_MASK(t) ((t == AER_CORRECTABLE) ? \
421 (PCI_ERR_COR_REP_ROLL|PCI_ERR_COR_REP_TIMER) : 0)
422
423#define AER_GET_AGENT(t, e) \
424 ((e & AER_AGENT_COMPLETER_MASK(t)) ? AER_AGENT_COMPLETER : \
425 (e & AER_AGENT_REQUESTER_MASK(t)) ? AER_AGENT_REQUESTER : \
426 (e & AER_AGENT_TRANSMITTER_MASK(t)) ? AER_AGENT_TRANSMITTER : \
427 AER_AGENT_RECEIVER)
428
429#define AER_PHYSICAL_LAYER_ERROR 0
430#define AER_DATA_LINK_LAYER_ERROR 1
431#define AER_TRANSACTION_LAYER_ERROR 2
432
433#define AER_PHYSICAL_LAYER_ERROR_MASK(t) ((t == AER_CORRECTABLE) ? \
434 PCI_ERR_COR_RCVR : 0)
435#define AER_DATA_LINK_LAYER_ERROR_MASK(t) ((t == AER_CORRECTABLE) ? \
436 (PCI_ERR_COR_BAD_TLP| \
437 PCI_ERR_COR_BAD_DLLP| \
438 PCI_ERR_COR_REP_ROLL| \
439 PCI_ERR_COR_REP_TIMER) : PCI_ERR_UNC_DLP)
440
441#define AER_GET_LAYER_ERROR(t, e) \
442 ((e & AER_PHYSICAL_LAYER_ERROR_MASK(t)) ? AER_PHYSICAL_LAYER_ERROR : \
443 (e & AER_DATA_LINK_LAYER_ERROR_MASK(t)) ? AER_DATA_LINK_LAYER_ERROR : \
444 AER_TRANSACTION_LAYER_ERROR)
445
446/*
447 * AER error strings
448 */
449static const char *aer_error_severity_string[] = {
450 "Uncorrected (Non-Fatal)",
451 "Uncorrected (Fatal)",
452 "Corrected"
453};
454
455static const char *aer_error_layer[] = {
456 "Physical Layer",
457 "Data Link Layer",
458 "Transaction Layer"
459};
460
461static const char *aer_correctable_error_string[] = {
462 "Receiver Error", /* Bit Position 0 */
463 NULL,
464 NULL,
465 NULL,
466 NULL,
467 NULL,
468 "Bad TLP", /* Bit Position 6 */
469 "Bad DLLP", /* Bit Position 7 */
470 "RELAY_NUM Rollover", /* Bit Position 8 */
471 NULL,
472 NULL,
473 NULL,
474 "Replay Timer Timeout", /* Bit Position 12 */
475 "Advisory Non-Fatal", /* Bit Position 13 */
476 "Corrected Internal Error", /* Bit Position 14 */
477 "Header Log Overflow", /* Bit Position 15 */
478};
479
480static const char *aer_uncorrectable_error_string[] = {
481 "Undefined", /* Bit Position 0 */
482 NULL,
483 NULL,
484 NULL,
485 "Data Link Protocol", /* Bit Position 4 */
486 "Surprise Down Error", /* Bit Position 5 */
487 NULL,
488 NULL,
489 NULL,
490 NULL,
491 NULL,
492 NULL,
493 "Poisoned TLP", /* Bit Position 12 */
494 "Flow Control Protocol", /* Bit Position 13 */
495 "Completion Timeout", /* Bit Position 14 */
496 "Completer Abort", /* Bit Position 15 */
497 "Unexpected Completion", /* Bit Position 16 */
498 "Receiver Overflow", /* Bit Position 17 */
499 "Malformed TLP", /* Bit Position 18 */
500 "ECRC", /* Bit Position 19 */
501 "Unsupported Request", /* Bit Position 20 */
502 "ACS Violation", /* Bit Position 21 */
503 "Uncorrectable Internal Error", /* Bit Position 22 */
504 "MC Blocked TLP", /* Bit Position 23 */
505 "AtomicOp Egress Blocked", /* Bit Position 24 */
506 "TLP Prefix Blocked Error", /* Bit Position 25 */
507};
508
509static const char *aer_agent_string[] = {
510 "Receiver ID",
511 "Requester ID",
512 "Completer ID",
513 "Transmitter ID"
514};
515
516static void __print_tlp_header(struct pci_dev *dev,
517 struct aer_header_log_regs *t)
518{
519 pci_err(dev, " TLP Header: %08x %08x %08x %08x\n",
520 t->dw0, t->dw1, t->dw2, t->dw3);
521}
522
523static void __aer_print_error(struct pci_dev *dev,
524 struct aer_err_info *info)
525{
526 int i, status;
527 const char *errmsg = NULL;
528 status = (info->status & ~info->mask);
529
530 for (i = 0; i < 32; i++) {
531 if (!(status & (1 << i)))
532 continue;
533
534 if (info->severity == AER_CORRECTABLE)
535 errmsg = i < ARRAY_SIZE(aer_correctable_error_string) ?
536 aer_correctable_error_string[i] : NULL;
537 else
538 errmsg = i < ARRAY_SIZE(aer_uncorrectable_error_string) ?
539 aer_uncorrectable_error_string[i] : NULL;
540
541 if (errmsg)
542 pci_err(dev, " [%2d] %-22s%s\n", i, errmsg,
543 info->first_error == i ? " (First)" : "");
544 else
545 pci_err(dev, " [%2d] Unknown Error Bit%s\n",
546 i, info->first_error == i ? " (First)" : "");
547 }
548}
549
550static void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
551{
552 int layer, agent;
553 int id = ((dev->bus->number << 8) | dev->devfn);
554
555 if (!info->status) {
556 pci_err(dev, "PCIe Bus Error: severity=%s, type=Inaccessible, (Unregistered Agent ID)\n",
557 aer_error_severity_string[info->severity]);
558 goto out;
559 }
560
561 layer = AER_GET_LAYER_ERROR(info->severity, info->status);
562 agent = AER_GET_AGENT(info->severity, info->status);
563
564 pci_err(dev, "PCIe Bus Error: severity=%s, type=%s, (%s)\n",
565 aer_error_severity_string[info->severity],
566 aer_error_layer[layer], aer_agent_string[agent]);
567
568 pci_err(dev, " device [%04x:%04x] error status/mask=%08x/%08x\n",
569 dev->vendor, dev->device,
570 info->status, info->mask);
571
572 __aer_print_error(dev, info);
573
574 if (info->tlp_header_valid)
575 __print_tlp_header(dev, &info->tlp);
576
577out:
578 if (info->id && info->error_dev_num > 1 && info->id == id)
579 pci_err(dev, " Error of this Agent is reported first\n");
580
581 trace_aer_event(dev_name(&dev->dev), (info->status & ~info->mask),
582 info->severity, info->tlp_header_valid, &info->tlp);
583}
584
585static void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info)
586{
587 u8 bus = info->id >> 8;
588 u8 devfn = info->id & 0xff;
589
590 pci_info(dev, "AER: %s%s error received: %04x:%02x:%02x.%d\n",
591 info->multi_error_valid ? "Multiple " : "",
592 aer_error_severity_string[info->severity],
593 pci_domain_nr(dev->bus), bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
594}
595
596#ifdef CONFIG_ACPI_APEI_PCIEAER
597int cper_severity_to_aer(int cper_severity)
598{
599 switch (cper_severity) {
600 case CPER_SEV_RECOVERABLE:
601 return AER_NONFATAL;
602 case CPER_SEV_FATAL:
603 return AER_FATAL;
604 default:
605 return AER_CORRECTABLE;
606 }
607}
608EXPORT_SYMBOL_GPL(cper_severity_to_aer);
609
610void cper_print_aer(struct pci_dev *dev, int aer_severity,
611 struct aer_capability_regs *aer)
612{
613 int layer, agent, tlp_header_valid = 0;
614 u32 status, mask;
615 struct aer_err_info info;
616
617 if (aer_severity == AER_CORRECTABLE) {
618 status = aer->cor_status;
619 mask = aer->cor_mask;
620 } else {
621 status = aer->uncor_status;
622 mask = aer->uncor_mask;
623 tlp_header_valid = status & AER_LOG_TLP_MASKS;
624 }
625
626 layer = AER_GET_LAYER_ERROR(aer_severity, status);
627 agent = AER_GET_AGENT(aer_severity, status);
628
629 memset(&info, 0, sizeof(info));
630 info.severity = aer_severity;
631 info.status = status;
632 info.mask = mask;
633 info.first_error = PCI_ERR_CAP_FEP(aer->cap_control);
634
635 pci_err(dev, "aer_status: 0x%08x, aer_mask: 0x%08x\n", status, mask);
636 __aer_print_error(dev, &info);
637 pci_err(dev, "aer_layer=%s, aer_agent=%s\n",
638 aer_error_layer[layer], aer_agent_string[agent]);
639
640 if (aer_severity != AER_CORRECTABLE)
641 pci_err(dev, "aer_uncor_severity: 0x%08x\n",
642 aer->uncor_severity);
643
644 if (tlp_header_valid)
645 __print_tlp_header(dev, &aer->header_log);
646
647 trace_aer_event(dev_name(&dev->dev), (status & ~mask),
648 aer_severity, tlp_header_valid, &aer->header_log);
649}
650#endif
651
652/**
653 * add_error_device - list device to be handled
654 * @e_info: pointer to error info
655 * @dev: pointer to pci_dev to be added
656 */
657static int add_error_device(struct aer_err_info *e_info, struct pci_dev *dev)
658{
659 if (e_info->error_dev_num < AER_MAX_MULTI_ERR_DEVICES) {
660 e_info->dev[e_info->error_dev_num] = dev;
661 e_info->error_dev_num++;
662 return 0;
663 }
664 return -ENOSPC;
665}
666
667/**
668 * is_error_source - check whether the device is source of reported error
669 * @dev: pointer to pci_dev to be checked
670 * @e_info: pointer to reported error info
671 */
672static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info)
673{
674 int pos;
675 u32 status, mask;
676 u16 reg16;
677
678 /*
679 * When bus id is equal to 0, it might be a bad id
680 * reported by root port.
681 */
682 if ((PCI_BUS_NUM(e_info->id) != 0) &&
683 !(dev->bus->bus_flags & PCI_BUS_FLAGS_NO_AERSID)) {
684 /* Device ID match? */
685 if (e_info->id == ((dev->bus->number << 8) | dev->devfn))
686 return true;
687
688 /* Continue id comparing if there is no multiple error */
689 if (!e_info->multi_error_valid)
690 return false;
691 }
692
693 /*
694 * When either
695 * 1) bus id is equal to 0. Some ports might lose the bus
696 * id of error source id;
697 * 2) bus flag PCI_BUS_FLAGS_NO_AERSID is set
698 * 3) There are multiple errors and prior ID comparing fails;
699 * We check AER status registers to find possible reporter.
700 */
701 if (atomic_read(&dev->enable_cnt) == 0)
702 return false;
703
704 /* Check if AER is enabled */
705 pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &reg16);
706 if (!(reg16 & PCI_EXP_AER_FLAGS))
707 return false;
708
709 pos = dev->aer_cap;
710 if (!pos)
711 return false;
712
713 /* Check if error is recorded */
714 if (e_info->severity == AER_CORRECTABLE) {
715 pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &status);
716 pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &mask);
717 } else {
718 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
719 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, &mask);
720 }
721 if (status & ~mask)
722 return true;
723
724 return false;
725}
726
727static int find_device_iter(struct pci_dev *dev, void *data)
728{
729 struct aer_err_info *e_info = (struct aer_err_info *)data;
730
731 if (is_error_source(dev, e_info)) {
732 /* List this device */
733 if (add_error_device(e_info, dev)) {
734 /* We cannot handle more... Stop iteration */
735 /* TODO: Should print error message here? */
736 return 1;
737 }
738
739 /* If there is only a single error, stop iteration */
740 if (!e_info->multi_error_valid)
741 return 1;
742 }
743 return 0;
744}
745
746/**
747 * find_source_device - search through device hierarchy for source device
748 * @parent: pointer to Root Port pci_dev data structure
749 * @e_info: including detailed error information such like id
750 *
751 * Return true if found.
752 *
753 * Invoked by DPC when error is detected at the Root Port.
754 * Caller of this function must set id, severity, and multi_error_valid of
755 * struct aer_err_info pointed by @e_info properly. This function must fill
756 * e_info->error_dev_num and e_info->dev[], based on the given information.
757 */
758static bool find_source_device(struct pci_dev *parent,
759 struct aer_err_info *e_info)
760{
761 struct pci_dev *dev = parent;
762 int result;
763
764 /* Must reset in this function */
765 e_info->error_dev_num = 0;
766
767 /* Is Root Port an agent that sends error message? */
768 result = find_device_iter(dev, e_info);
769 if (result)
770 return true;
771
772 pci_walk_bus(parent->subordinate, find_device_iter, e_info);
773
774 if (!e_info->error_dev_num) {
775 pci_printk(KERN_DEBUG, parent, "can't find device of ID%04x\n",
776 e_info->id);
777 return false;
778 }
779 return true;
780}
781
782/**
783 * handle_error_source - handle logging error into an event log
784 * @dev: pointer to pci_dev data structure of error source device
785 * @info: comprehensive error information
786 *
787 * Invoked when an error being detected by Root Port.
788 */
789static void handle_error_source(struct pci_dev *dev, struct aer_err_info *info)
790{
791 int pos;
792
793 if (info->severity == AER_CORRECTABLE) {
794 /*
795 * Correctable error does not need software intervention.
796 * No need to go through error recovery process.
797 */
798 pos = dev->aer_cap;
799 if (pos)
800 pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS,
801 info->status);
802 } else if (info->severity == AER_NONFATAL)
803 pcie_do_nonfatal_recovery(dev);
804 else if (info->severity == AER_FATAL)
805 pcie_do_fatal_recovery(dev, PCIE_PORT_SERVICE_AER);
806}
807
808#ifdef CONFIG_ACPI_APEI_PCIEAER
809
810#define AER_RECOVER_RING_ORDER 4
811#define AER_RECOVER_RING_SIZE (1 << AER_RECOVER_RING_ORDER)
812
813struct aer_recover_entry {
814 u8 bus;
815 u8 devfn;
816 u16 domain;
817 int severity;
818 struct aer_capability_regs *regs;
819};
820
821static DEFINE_KFIFO(aer_recover_ring, struct aer_recover_entry,
822 AER_RECOVER_RING_SIZE);
823
824static void aer_recover_work_func(struct work_struct *work)
825{
826 struct aer_recover_entry entry;
827 struct pci_dev *pdev;
828
829 while (kfifo_get(&aer_recover_ring, &entry)) {
830 pdev = pci_get_domain_bus_and_slot(entry.domain, entry.bus,
831 entry.devfn);
832 if (!pdev) {
833 pr_err("AER recover: Can not find pci_dev for %04x:%02x:%02x:%x\n",
834 entry.domain, entry.bus,
835 PCI_SLOT(entry.devfn), PCI_FUNC(entry.devfn));
836 continue;
837 }
838 cper_print_aer(pdev, entry.severity, entry.regs);
839 if (entry.severity == AER_NONFATAL)
840 pcie_do_nonfatal_recovery(pdev);
841 else if (entry.severity == AER_FATAL)
842 pcie_do_fatal_recovery(pdev, PCIE_PORT_SERVICE_AER);
843 pci_dev_put(pdev);
844 }
845}
846
847/*
848 * Mutual exclusion for writers of aer_recover_ring, reader side don't
849 * need lock, because there is only one reader and lock is not needed
850 * between reader and writer.
851 */
852static DEFINE_SPINLOCK(aer_recover_ring_lock);
853static DECLARE_WORK(aer_recover_work, aer_recover_work_func);
854
855void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
856 int severity, struct aer_capability_regs *aer_regs)
857{
858 unsigned long flags;
859 struct aer_recover_entry entry = {
860 .bus = bus,
861 .devfn = devfn,
862 .domain = domain,
863 .severity = severity,
864 .regs = aer_regs,
865 };
866
867 spin_lock_irqsave(&aer_recover_ring_lock, flags);
868 if (kfifo_put(&aer_recover_ring, entry))
869 schedule_work(&aer_recover_work);
870 else
871 pr_err("AER recover: Buffer overflow when recovering AER for %04x:%02x:%02x:%x\n",
872 domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
873 spin_unlock_irqrestore(&aer_recover_ring_lock, flags);
874}
875EXPORT_SYMBOL_GPL(aer_recover_queue);
876#endif
877
878/**
879 * get_device_error_info - read error status from dev and store it to info
880 * @dev: pointer to the device expected to have a error record
881 * @info: pointer to structure to store the error record
882 *
883 * Return 1 on success, 0 on error.
884 *
885 * Note that @info is reused among all error devices. Clear fields properly.
886 */
887static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info)
888{
889 int pos, temp;
890
891 /* Must reset in this function */
892 info->status = 0;
893 info->tlp_header_valid = 0;
894
895 pos = dev->aer_cap;
896
897 /* The device might not support AER */
898 if (!pos)
899 return 0;
900
901 if (info->severity == AER_CORRECTABLE) {
902 pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS,
903 &info->status);
904 pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK,
905 &info->mask);
906 if (!(info->status & ~info->mask))
907 return 0;
908 } else if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
909 info->severity == AER_NONFATAL) {
910
911 /* Link is still healthy for IO reads */
912 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS,
913 &info->status);
914 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK,
915 &info->mask);
916 if (!(info->status & ~info->mask))
917 return 0;
918
919 /* Get First Error Pointer */
920 pci_read_config_dword(dev, pos + PCI_ERR_CAP, &temp);
921 info->first_error = PCI_ERR_CAP_FEP(temp);
922
923 if (info->status & AER_LOG_TLP_MASKS) {
924 info->tlp_header_valid = 1;
925 pci_read_config_dword(dev,
926 pos + PCI_ERR_HEADER_LOG, &info->tlp.dw0);
927 pci_read_config_dword(dev,
928 pos + PCI_ERR_HEADER_LOG + 4, &info->tlp.dw1);
929 pci_read_config_dword(dev,
930 pos + PCI_ERR_HEADER_LOG + 8, &info->tlp.dw2);
931 pci_read_config_dword(dev,
932 pos + PCI_ERR_HEADER_LOG + 12, &info->tlp.dw3);
933 }
934 }
935
936 return 1;
937}
938
939static inline void aer_process_err_devices(struct aer_err_info *e_info)
940{
941 int i;
942
943 /* Report all before handle them, not to lost records by reset etc. */
944 for (i = 0; i < e_info->error_dev_num && e_info->dev[i]; i++) {
945 if (get_device_error_info(e_info->dev[i], e_info))
946 aer_print_error(e_info->dev[i], e_info);
947 }
948 for (i = 0; i < e_info->error_dev_num && e_info->dev[i]; i++) {
949 if (get_device_error_info(e_info->dev[i], e_info))
950 handle_error_source(e_info->dev[i], e_info);
951 }
952}
953
954/**
955 * aer_isr_one_error - consume an error detected by root port
956 * @rpc: pointer to the root port which holds an error
957 * @e_src: pointer to an error source
958 */
959static void aer_isr_one_error(struct aer_rpc *rpc,
960 struct aer_err_source *e_src)
961{
962 struct pci_dev *pdev = rpc->rpd;
963 struct aer_err_info *e_info = &rpc->e_info;
964
965 /*
966 * There is a possibility that both correctable error and
967 * uncorrectable error being logged. Report correctable error first.
968 */
969 if (e_src->status & PCI_ERR_ROOT_COR_RCV) {
970 e_info->id = ERR_COR_ID(e_src->id);
971 e_info->severity = AER_CORRECTABLE;
972
973 if (e_src->status & PCI_ERR_ROOT_MULTI_COR_RCV)
974 e_info->multi_error_valid = 1;
975 else
976 e_info->multi_error_valid = 0;
977 aer_print_port_info(pdev, e_info);
978
979 if (find_source_device(pdev, e_info))
980 aer_process_err_devices(e_info);
981 }
982
983 if (e_src->status & PCI_ERR_ROOT_UNCOR_RCV) {
984 e_info->id = ERR_UNCOR_ID(e_src->id);
985
986 if (e_src->status & PCI_ERR_ROOT_FATAL_RCV)
987 e_info->severity = AER_FATAL;
988 else
989 e_info->severity = AER_NONFATAL;
990
991 if (e_src->status & PCI_ERR_ROOT_MULTI_UNCOR_RCV)
992 e_info->multi_error_valid = 1;
993 else
994 e_info->multi_error_valid = 0;
995
996 aer_print_port_info(pdev, e_info);
997
998 if (find_source_device(pdev, e_info))
999 aer_process_err_devices(e_info);
1000 }
1001}
1002
1003/**
1004 * get_e_source - retrieve an error source
1005 * @rpc: pointer to the root port which holds an error
1006 * @e_src: pointer to store retrieved error source
1007 *
1008 * Return 1 if an error source is retrieved, otherwise 0.
1009 *
1010 * Invoked by DPC handler to consume an error.
1011 */
1012static int get_e_source(struct aer_rpc *rpc, struct aer_err_source *e_src)
1013{
1014 unsigned long flags;
1015
1016 /* Lock access to Root error producer/consumer index */
1017 spin_lock_irqsave(&rpc->e_lock, flags);
1018 if (rpc->prod_idx == rpc->cons_idx) {
1019 spin_unlock_irqrestore(&rpc->e_lock, flags);
1020 return 0;
1021 }
1022
1023 *e_src = rpc->e_sources[rpc->cons_idx];
1024 rpc->cons_idx++;
1025 if (rpc->cons_idx == AER_ERROR_SOURCES_MAX)
1026 rpc->cons_idx = 0;
1027 spin_unlock_irqrestore(&rpc->e_lock, flags);
1028
1029 return 1;
1030}
1031
1032/**
1033 * aer_isr - consume errors detected by root port
1034 * @work: definition of this work item
1035 *
1036 * Invoked, as DPC, when root port records new detected error
1037 */
1038static void aer_isr(struct work_struct *work)
1039{
1040 struct aer_rpc *rpc = container_of(work, struct aer_rpc, dpc_handler);
1041 struct aer_err_source uninitialized_var(e_src);
1042
1043 mutex_lock(&rpc->rpc_mutex);
1044 while (get_e_source(rpc, &e_src))
1045 aer_isr_one_error(rpc, &e_src);
1046 mutex_unlock(&rpc->rpc_mutex);
1047}
1048
1049/**
1050 * aer_irq - Root Port's ISR
1051 * @irq: IRQ assigned to Root Port
1052 * @context: pointer to Root Port data structure
1053 *
1054 * Invoked when Root Port detects AER messages.
1055 */
1056irqreturn_t aer_irq(int irq, void *context)
1057{
1058 unsigned int status, id;
1059 struct pcie_device *pdev = (struct pcie_device *)context;
1060 struct aer_rpc *rpc = get_service_data(pdev);
1061 int next_prod_idx;
1062 unsigned long flags;
1063 int pos;
1064
1065 pos = pdev->port->aer_cap;
1066 /*
1067 * Must lock access to Root Error Status Reg, Root Error ID Reg,
1068 * and Root error producer/consumer index
1069 */
1070 spin_lock_irqsave(&rpc->e_lock, flags);
1071
1072 /* Read error status */
1073 pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, &status);
1074 if (!(status & (PCI_ERR_ROOT_UNCOR_RCV|PCI_ERR_ROOT_COR_RCV))) {
1075 spin_unlock_irqrestore(&rpc->e_lock, flags);
1076 return IRQ_NONE;
1077 }
1078
1079 /* Read error source and clear error status */
1080 pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_ERR_SRC, &id);
1081 pci_write_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, status);
1082
1083 /* Store error source for later DPC handler */
1084 next_prod_idx = rpc->prod_idx + 1;
1085 if (next_prod_idx == AER_ERROR_SOURCES_MAX)
1086 next_prod_idx = 0;
1087 if (next_prod_idx == rpc->cons_idx) {
1088 /*
1089 * Error Storm Condition - possibly the same error occurred.
1090 * Drop the error.
1091 */
1092 spin_unlock_irqrestore(&rpc->e_lock, flags);
1093 return IRQ_HANDLED;
1094 }
1095 rpc->e_sources[rpc->prod_idx].status = status;
1096 rpc->e_sources[rpc->prod_idx].id = id;
1097 rpc->prod_idx = next_prod_idx;
1098 spin_unlock_irqrestore(&rpc->e_lock, flags);
1099
1100 /* Invoke DPC handler */
1101 schedule_work(&rpc->dpc_handler);
1102
1103 return IRQ_HANDLED;
1104}
1105EXPORT_SYMBOL_GPL(aer_irq);
1106
1107static int set_device_error_reporting(struct pci_dev *dev, void *data)
1108{
1109 bool enable = *((bool *)data);
1110 int type = pci_pcie_type(dev);
1111
1112 if ((type == PCI_EXP_TYPE_ROOT_PORT) ||
1113 (type == PCI_EXP_TYPE_UPSTREAM) ||
1114 (type == PCI_EXP_TYPE_DOWNSTREAM)) {
1115 if (enable)
1116 pci_enable_pcie_error_reporting(dev);
1117 else
1118 pci_disable_pcie_error_reporting(dev);
1119 }
1120
1121 if (enable)
1122 pcie_set_ecrc_checking(dev);
1123
1124 return 0;
1125}
1126
1127/**
1128 * set_downstream_devices_error_reporting - enable/disable the error reporting bits on the root port and its downstream ports.
1129 * @dev: pointer to root port's pci_dev data structure
1130 * @enable: true = enable error reporting, false = disable error reporting.
1131 */
1132static void set_downstream_devices_error_reporting(struct pci_dev *dev,
1133 bool enable)
1134{
1135 set_device_error_reporting(dev, &enable);
1136
1137 if (!dev->subordinate)
1138 return;
1139 pci_walk_bus(dev->subordinate, set_device_error_reporting, &enable);
1140}
1141
1142/**
1143 * aer_enable_rootport - enable Root Port's interrupts when receiving messages
1144 * @rpc: pointer to a Root Port data structure
1145 *
1146 * Invoked when PCIe bus loads AER service driver.
1147 */
1148static void aer_enable_rootport(struct aer_rpc *rpc)
1149{
1150 struct pci_dev *pdev = rpc->rpd;
1151 int aer_pos;
1152 u16 reg16;
1153 u32 reg32;
1154
1155 /* Clear PCIe Capability's Device Status */
1156 pcie_capability_read_word(pdev, PCI_EXP_DEVSTA, &reg16);
1157 pcie_capability_write_word(pdev, PCI_EXP_DEVSTA, reg16);
1158
1159 /* Disable system error generation in response to error messages */
1160 pcie_capability_clear_word(pdev, PCI_EXP_RTCTL,
1161 SYSTEM_ERROR_INTR_ON_MESG_MASK);
1162
1163 aer_pos = pdev->aer_cap;
1164 /* Clear error status */
1165 pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, &reg32);
1166 pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32);
1167 pci_read_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, &reg32);
1168 pci_write_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, reg32);
1169 pci_read_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, &reg32);
1170 pci_write_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, reg32);
1171
1172 /*
1173 * Enable error reporting for the root port device and downstream port
1174 * devices.
1175 */
1176 set_downstream_devices_error_reporting(pdev, true);
1177
1178 /* Enable Root Port's interrupt in response to error messages */
1179 pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_COMMAND, &reg32);
1180 reg32 |= ROOT_PORT_INTR_ON_MESG_MASK;
1181 pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_COMMAND, reg32);
1182}
1183
1184/**
1185 * aer_disable_rootport - disable Root Port's interrupts when receiving messages
1186 * @rpc: pointer to a Root Port data structure
1187 *
1188 * Invoked when PCIe bus unloads AER service driver.
1189 */
1190static void aer_disable_rootport(struct aer_rpc *rpc)
1191{
1192 struct pci_dev *pdev = rpc->rpd;
1193 u32 reg32;
1194 int pos;
1195
1196 /*
1197 * Disable error reporting for the root port device and downstream port
1198 * devices.
1199 */
1200 set_downstream_devices_error_reporting(pdev, false);
1201
1202 pos = pdev->aer_cap;
1203 /* Disable Root's interrupt in response to error messages */
1204 pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
1205 reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK;
1206 pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, reg32);
1207
1208 /* Clear Root's error status reg */
1209 pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, &reg32);
1210 pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, reg32);
1211}
1212
1213/**
1214 * aer_alloc_rpc - allocate Root Port data structure
1215 * @dev: pointer to the pcie_dev data structure
1216 *
1217 * Invoked when Root Port's AER service is loaded.
1218 */
1219static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev)
1220{
1221 struct aer_rpc *rpc;
1222
1223 rpc = kzalloc(sizeof(struct aer_rpc), GFP_KERNEL);
1224 if (!rpc)
1225 return NULL;
1226
1227 /* Initialize Root lock access, e_lock, to Root Error Status Reg */
1228 spin_lock_init(&rpc->e_lock);
1229
1230 rpc->rpd = dev->port;
1231 INIT_WORK(&rpc->dpc_handler, aer_isr);
1232 mutex_init(&rpc->rpc_mutex);
1233
1234 /* Use PCIe bus function to store rpc into PCIe device */
1235 set_service_data(dev, rpc);
1236
1237 return rpc;
1238}
1239
1240/**
1241 * aer_remove - clean up resources
1242 * @dev: pointer to the pcie_dev data structure
1243 *
1244 * Invoked when PCI Express bus unloads or AER probe fails.
1245 */
1246static void aer_remove(struct pcie_device *dev)
1247{
1248 struct aer_rpc *rpc = get_service_data(dev);
1249
1250 if (rpc) {
1251 /* If register interrupt service, it must be free. */
1252 if (rpc->isr)
1253 free_irq(dev->irq, dev);
1254
1255 flush_work(&rpc->dpc_handler);
1256 aer_disable_rootport(rpc);
1257 kfree(rpc);
1258 set_service_data(dev, NULL);
1259 }
1260}
1261
1262/**
1263 * aer_probe - initialize resources
1264 * @dev: pointer to the pcie_dev data structure
1265 *
1266 * Invoked when PCI Express bus loads AER service driver.
1267 */
1268static int aer_probe(struct pcie_device *dev)
1269{
1270 int status;
1271 struct aer_rpc *rpc;
1272 struct device *device = &dev->port->dev;
1273
1274 /* Alloc rpc data structure */
1275 rpc = aer_alloc_rpc(dev);
1276 if (!rpc) {
1277 dev_printk(KERN_DEBUG, device, "alloc AER rpc failed\n");
1278 aer_remove(dev);
1279 return -ENOMEM;
1280 }
1281
1282 /* Request IRQ ISR */
1283 status = request_irq(dev->irq, aer_irq, IRQF_SHARED, "aerdrv", dev);
1284 if (status) {
1285 dev_printk(KERN_DEBUG, device, "request AER IRQ %d failed\n",
1286 dev->irq);
1287 aer_remove(dev);
1288 return status;
1289 }
1290
1291 rpc->isr = 1;
1292
1293 aer_enable_rootport(rpc);
1294 dev_info(device, "AER enabled with IRQ %d\n", dev->irq);
1295 return 0;
1296}
1297
1298/**
1299 * aer_root_reset - reset link on Root Port
1300 * @dev: pointer to Root Port's pci_dev data structure
1301 *
1302 * Invoked by Port Bus driver when performing link reset at Root Port.
1303 */
1304static pci_ers_result_t aer_root_reset(struct pci_dev *dev)
1305{
1306 u32 reg32;
1307 int pos;
1308
1309 pos = dev->aer_cap;
1310
1311 /* Disable Root's interrupt in response to error messages */
1312 pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
1313 reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK;
1314 pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32);
1315
1316 pci_reset_bridge_secondary_bus(dev);
1317 pci_printk(KERN_DEBUG, dev, "Root Port link has been reset\n");
1318
1319 /* Clear Root Error Status */
1320 pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &reg32);
1321 pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, reg32);
1322
1323 /* Enable Root Port's interrupt in response to error messages */
1324 pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
1325 reg32 |= ROOT_PORT_INTR_ON_MESG_MASK;
1326 pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32);
1327
1328 return PCI_ERS_RESULT_RECOVERED;
1329}
1330
1331/**
1332 * aer_error_resume - clean up corresponding error status bits
1333 * @dev: pointer to Root Port's pci_dev data structure
1334 *
1335 * Invoked by Port Bus driver during nonfatal recovery.
1336 */
1337static void aer_error_resume(struct pci_dev *dev)
1338{
1339 int pos;
1340 u32 status, mask;
1341 u16 reg16;
1342
1343 /* Clean up Root device status */
1344 pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &reg16);
1345 pcie_capability_write_word(dev, PCI_EXP_DEVSTA, reg16);
1346
1347 /* Clean AER Root Error Status */
1348 pos = dev->aer_cap;
1349 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
1350 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask);
1351 status &= ~mask; /* Clear corresponding nonfatal bits */
1352 pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
1353}
1354
1355static struct pcie_port_service_driver aerdriver = {
1356 .name = "aer",
1357 .port_type = PCI_EXP_TYPE_ROOT_PORT,
1358 .service = PCIE_PORT_SERVICE_AER,
1359
1360 .probe = aer_probe,
1361 .remove = aer_remove,
1362 .error_resume = aer_error_resume,
1363 .reset_link = aer_root_reset,
1364};
1365
1366/**
1367 * aer_service_init - register AER root service driver
1368 *
1369 * Invoked when AER root service driver is loaded.
1370 */
1371static int __init aer_service_init(void)
1372{
1373 if (!pci_aer_available() || aer_acpi_firmware_first())
1374 return -ENXIO;
1375 return pcie_port_service_register(&aerdriver);
1376}
1377device_initcall(aer_service_init);
diff --git a/drivers/pci/pcie/aer/Kconfig b/drivers/pci/pcie/aer/Kconfig
deleted file mode 100644
index 5a64eb3d6c7a..000000000000
--- a/drivers/pci/pcie/aer/Kconfig
+++ /dev/null
@@ -1,29 +0,0 @@
1# SPDX-License-Identifier: GPL-2.0
2#
3# PCI Express Root Port Device AER Configuration
4#
5
6config PCIEAER
7 bool "Root Port Advanced Error Reporting support"
8 depends on PCIEPORTBUS
9 select RAS
10 default y
11 help
12 This enables PCI Express Root Port Advanced Error Reporting
13 (AER) driver support. Error reporting messages sent to Root
14 Port will be handled by PCI Express AER driver.
15
16
17#
18# PCI Express ECRC
19#
20config PCIE_ECRC
21 bool "PCI Express ECRC settings control"
22 depends on PCIEAER
23 help
24 Used to override firmware/bios settings for PCI Express ECRC
25 (transaction layer end-to-end CRC checking).
26
27 When in doubt, say N.
28
29source "drivers/pci/pcie/aer/Kconfig.debug"
diff --git a/drivers/pci/pcie/aer/Kconfig.debug b/drivers/pci/pcie/aer/Kconfig.debug
deleted file mode 100644
index 67e02174b65b..000000000000
--- a/drivers/pci/pcie/aer/Kconfig.debug
+++ /dev/null
@@ -1,19 +0,0 @@
1# SPDX-License-Identifier: GPL-2.0
2#
3# PCI Express Root Port Device AER Debug Configuration
4#
5
6config PCIEAER_INJECT
7 tristate "PCIe AER error injector support"
8 depends on PCIEAER
9 default n
10 help
11 This enables PCI Express Root Port Advanced Error Reporting
12 (AER) software error injector.
13
14 Debugging PCIe AER code is quite difficult because it is hard
15 to trigger various real hardware errors. Software based
16 error injection can fake almost all kinds of errors with the
17 help of a user space helper tool aer-inject, which can be
18 gotten from:
19 http://www.kernel.org/pub/linux/utils/pci/aer-inject/
diff --git a/drivers/pci/pcie/aer/Makefile b/drivers/pci/pcie/aer/Makefile
deleted file mode 100644
index 09bd890875a3..000000000000
--- a/drivers/pci/pcie/aer/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
1# SPDX-License-Identifier: GPL-2.0
2#
3# Makefile for PCI-Express Root Port Advanced Error Reporting Driver
4#
5
6obj-$(CONFIG_PCIEAER) += aerdriver.o
7
8obj-$(CONFIG_PCIE_ECRC) += ecrc.o
9
10aerdriver-objs := aerdrv_errprint.o aerdrv_core.o aerdrv.o
11aerdriver-$(CONFIG_ACPI) += aerdrv_acpi.o
12
13obj-$(CONFIG_PCIEAER_INJECT) += aer_inject.o
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
deleted file mode 100644
index 9735c19bf39c..000000000000
--- a/drivers/pci/pcie/aer/aerdrv.c
+++ /dev/null
@@ -1,371 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Implement the AER root port service driver. The driver registers an IRQ
4 * handler. When a root port triggers an AER interrupt, the IRQ handler
5 * collects root port status and schedules work.
6 *
7 * Copyright (C) 2006 Intel Corp.
8 * Tom Long Nguyen (tom.l.nguyen@intel.com)
9 * Zhang Yanmin (yanmin.zhang@intel.com)
10 */
11
12#include <linux/pci.h>
13#include <linux/pci-acpi.h>
14#include <linux/sched.h>
15#include <linux/kernel.h>
16#include <linux/errno.h>
17#include <linux/pm.h>
18#include <linux/init.h>
19#include <linux/interrupt.h>
20#include <linux/delay.h>
21#include <linux/slab.h>
22
23#include "aerdrv.h"
24#include "../../pci.h"
25
26static int aer_probe(struct pcie_device *dev);
27static void aer_remove(struct pcie_device *dev);
28static void aer_error_resume(struct pci_dev *dev);
29static pci_ers_result_t aer_root_reset(struct pci_dev *dev);
30
31static struct pcie_port_service_driver aerdriver = {
32 .name = "aer",
33 .port_type = PCI_EXP_TYPE_ROOT_PORT,
34 .service = PCIE_PORT_SERVICE_AER,
35
36 .probe = aer_probe,
37 .remove = aer_remove,
38 .error_resume = aer_error_resume,
39 .reset_link = aer_root_reset,
40};
41
42static int pcie_aer_disable;
43
44void pci_no_aer(void)
45{
46 pcie_aer_disable = 1;
47}
48
49bool pci_aer_available(void)
50{
51 return !pcie_aer_disable && pci_msi_enabled();
52}
53
54static int set_device_error_reporting(struct pci_dev *dev, void *data)
55{
56 bool enable = *((bool *)data);
57 int type = pci_pcie_type(dev);
58
59 if ((type == PCI_EXP_TYPE_ROOT_PORT) ||
60 (type == PCI_EXP_TYPE_UPSTREAM) ||
61 (type == PCI_EXP_TYPE_DOWNSTREAM)) {
62 if (enable)
63 pci_enable_pcie_error_reporting(dev);
64 else
65 pci_disable_pcie_error_reporting(dev);
66 }
67
68 if (enable)
69 pcie_set_ecrc_checking(dev);
70
71 return 0;
72}
73
74/**
75 * set_downstream_devices_error_reporting - enable/disable the error reporting bits on the root port and its downstream ports.
76 * @dev: pointer to root port's pci_dev data structure
77 * @enable: true = enable error reporting, false = disable error reporting.
78 */
79static void set_downstream_devices_error_reporting(struct pci_dev *dev,
80 bool enable)
81{
82 set_device_error_reporting(dev, &enable);
83
84 if (!dev->subordinate)
85 return;
86 pci_walk_bus(dev->subordinate, set_device_error_reporting, &enable);
87}
88
89/**
90 * aer_enable_rootport - enable Root Port's interrupts when receiving messages
91 * @rpc: pointer to a Root Port data structure
92 *
93 * Invoked when PCIe bus loads AER service driver.
94 */
95static void aer_enable_rootport(struct aer_rpc *rpc)
96{
97 struct pci_dev *pdev = rpc->rpd;
98 int aer_pos;
99 u16 reg16;
100 u32 reg32;
101
102 /* Clear PCIe Capability's Device Status */
103 pcie_capability_read_word(pdev, PCI_EXP_DEVSTA, &reg16);
104 pcie_capability_write_word(pdev, PCI_EXP_DEVSTA, reg16);
105
106 /* Disable system error generation in response to error messages */
107 pcie_capability_clear_word(pdev, PCI_EXP_RTCTL,
108 SYSTEM_ERROR_INTR_ON_MESG_MASK);
109
110 aer_pos = pdev->aer_cap;
111 /* Clear error status */
112 pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, &reg32);
113 pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32);
114 pci_read_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, &reg32);
115 pci_write_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, reg32);
116 pci_read_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, &reg32);
117 pci_write_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, reg32);
118
119 /*
120 * Enable error reporting for the root port device and downstream port
121 * devices.
122 */
123 set_downstream_devices_error_reporting(pdev, true);
124
125 /* Enable Root Port's interrupt in response to error messages */
126 pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_COMMAND, &reg32);
127 reg32 |= ROOT_PORT_INTR_ON_MESG_MASK;
128 pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_COMMAND, reg32);
129}
130
131/**
132 * aer_disable_rootport - disable Root Port's interrupts when receiving messages
133 * @rpc: pointer to a Root Port data structure
134 *
135 * Invoked when PCIe bus unloads AER service driver.
136 */
137static void aer_disable_rootport(struct aer_rpc *rpc)
138{
139 struct pci_dev *pdev = rpc->rpd;
140 u32 reg32;
141 int pos;
142
143 /*
144 * Disable error reporting for the root port device and downstream port
145 * devices.
146 */
147 set_downstream_devices_error_reporting(pdev, false);
148
149 pos = pdev->aer_cap;
150 /* Disable Root's interrupt in response to error messages */
151 pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
152 reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK;
153 pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, reg32);
154
155 /* Clear Root's error status reg */
156 pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, &reg32);
157 pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, reg32);
158}
159
160/**
161 * aer_irq - Root Port's ISR
162 * @irq: IRQ assigned to Root Port
163 * @context: pointer to Root Port data structure
164 *
165 * Invoked when Root Port detects AER messages.
166 */
167irqreturn_t aer_irq(int irq, void *context)
168{
169 unsigned int status, id;
170 struct pcie_device *pdev = (struct pcie_device *)context;
171 struct aer_rpc *rpc = get_service_data(pdev);
172 int next_prod_idx;
173 unsigned long flags;
174 int pos;
175
176 pos = pdev->port->aer_cap;
177 /*
178 * Must lock access to Root Error Status Reg, Root Error ID Reg,
179 * and Root error producer/consumer index
180 */
181 spin_lock_irqsave(&rpc->e_lock, flags);
182
183 /* Read error status */
184 pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, &status);
185 if (!(status & (PCI_ERR_ROOT_UNCOR_RCV|PCI_ERR_ROOT_COR_RCV))) {
186 spin_unlock_irqrestore(&rpc->e_lock, flags);
187 return IRQ_NONE;
188 }
189
190 /* Read error source and clear error status */
191 pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_ERR_SRC, &id);
192 pci_write_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, status);
193
194 /* Store error source for later DPC handler */
195 next_prod_idx = rpc->prod_idx + 1;
196 if (next_prod_idx == AER_ERROR_SOURCES_MAX)
197 next_prod_idx = 0;
198 if (next_prod_idx == rpc->cons_idx) {
199 /*
200 * Error Storm Condition - possibly the same error occurred.
201 * Drop the error.
202 */
203 spin_unlock_irqrestore(&rpc->e_lock, flags);
204 return IRQ_HANDLED;
205 }
206 rpc->e_sources[rpc->prod_idx].status = status;
207 rpc->e_sources[rpc->prod_idx].id = id;
208 rpc->prod_idx = next_prod_idx;
209 spin_unlock_irqrestore(&rpc->e_lock, flags);
210
211 /* Invoke DPC handler */
212 schedule_work(&rpc->dpc_handler);
213
214 return IRQ_HANDLED;
215}
216EXPORT_SYMBOL_GPL(aer_irq);
217
218/**
219 * aer_alloc_rpc - allocate Root Port data structure
220 * @dev: pointer to the pcie_dev data structure
221 *
222 * Invoked when Root Port's AER service is loaded.
223 */
224static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev)
225{
226 struct aer_rpc *rpc;
227
228 rpc = kzalloc(sizeof(struct aer_rpc), GFP_KERNEL);
229 if (!rpc)
230 return NULL;
231
232 /* Initialize Root lock access, e_lock, to Root Error Status Reg */
233 spin_lock_init(&rpc->e_lock);
234
235 rpc->rpd = dev->port;
236 INIT_WORK(&rpc->dpc_handler, aer_isr);
237 mutex_init(&rpc->rpc_mutex);
238
239 /* Use PCIe bus function to store rpc into PCIe device */
240 set_service_data(dev, rpc);
241
242 return rpc;
243}
244
245/**
246 * aer_remove - clean up resources
247 * @dev: pointer to the pcie_dev data structure
248 *
249 * Invoked when PCI Express bus unloads or AER probe fails.
250 */
251static void aer_remove(struct pcie_device *dev)
252{
253 struct aer_rpc *rpc = get_service_data(dev);
254
255 if (rpc) {
256 /* If register interrupt service, it must be free. */
257 if (rpc->isr)
258 free_irq(dev->irq, dev);
259
260 flush_work(&rpc->dpc_handler);
261 aer_disable_rootport(rpc);
262 kfree(rpc);
263 set_service_data(dev, NULL);
264 }
265}
266
267/**
268 * aer_probe - initialize resources
269 * @dev: pointer to the pcie_dev data structure
270 *
271 * Invoked when PCI Express bus loads AER service driver.
272 */
273static int aer_probe(struct pcie_device *dev)
274{
275 int status;
276 struct aer_rpc *rpc;
277 struct device *device = &dev->port->dev;
278
279 /* Alloc rpc data structure */
280 rpc = aer_alloc_rpc(dev);
281 if (!rpc) {
282 dev_printk(KERN_DEBUG, device, "alloc AER rpc failed\n");
283 aer_remove(dev);
284 return -ENOMEM;
285 }
286
287 /* Request IRQ ISR */
288 status = request_irq(dev->irq, aer_irq, IRQF_SHARED, "aerdrv", dev);
289 if (status) {
290 dev_printk(KERN_DEBUG, device, "request AER IRQ %d failed\n",
291 dev->irq);
292 aer_remove(dev);
293 return status;
294 }
295
296 rpc->isr = 1;
297
298 aer_enable_rootport(rpc);
299 dev_info(device, "AER enabled with IRQ %d\n", dev->irq);
300 return 0;
301}
302
303/**
304 * aer_root_reset - reset link on Root Port
305 * @dev: pointer to Root Port's pci_dev data structure
306 *
307 * Invoked by Port Bus driver when performing link reset at Root Port.
308 */
309static pci_ers_result_t aer_root_reset(struct pci_dev *dev)
310{
311 u32 reg32;
312 int pos;
313
314 pos = dev->aer_cap;
315
316 /* Disable Root's interrupt in response to error messages */
317 pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
318 reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK;
319 pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32);
320
321 pci_reset_bridge_secondary_bus(dev);
322 pci_printk(KERN_DEBUG, dev, "Root Port link has been reset\n");
323
324 /* Clear Root Error Status */
325 pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &reg32);
326 pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, reg32);
327
328 /* Enable Root Port's interrupt in response to error messages */
329 pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
330 reg32 |= ROOT_PORT_INTR_ON_MESG_MASK;
331 pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32);
332
333 return PCI_ERS_RESULT_RECOVERED;
334}
335
336/**
337 * aer_error_resume - clean up corresponding error status bits
338 * @dev: pointer to Root Port's pci_dev data structure
339 *
340 * Invoked by Port Bus driver during nonfatal recovery.
341 */
342static void aer_error_resume(struct pci_dev *dev)
343{
344 int pos;
345 u32 status, mask;
346 u16 reg16;
347
348 /* Clean up Root device status */
349 pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &reg16);
350 pcie_capability_write_word(dev, PCI_EXP_DEVSTA, reg16);
351
352 /* Clean AER Root Error Status */
353 pos = dev->aer_cap;
354 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
355 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask);
356 status &= ~mask; /* Clear corresponding nonfatal bits */
357 pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
358}
359
360/**
361 * aer_service_init - register AER root service driver
362 *
363 * Invoked when AER root service driver is loaded.
364 */
365static int __init aer_service_init(void)
366{
367 if (!pci_aer_available() || aer_acpi_firmware_first())
368 return -ENXIO;
369 return pcie_port_service_register(&aerdriver);
370}
371device_initcall(aer_service_init);
diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h
deleted file mode 100644
index 6e0ad9a68fd9..000000000000
--- a/drivers/pci/pcie/aer/aerdrv.h
+++ /dev/null
@@ -1,95 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (C) 2006 Intel Corp.
4 * Tom Long Nguyen (tom.l.nguyen@intel.com)
5 * Zhang Yanmin (yanmin.zhang@intel.com)
6 */
7
8#ifndef _AERDRV_H_
9#define _AERDRV_H_
10
11#include <linux/workqueue.h>
12#include <linux/aer.h>
13#include <linux/interrupt.h>
14
15#include "../portdrv.h"
16
17#define SYSTEM_ERROR_INTR_ON_MESG_MASK (PCI_EXP_RTCTL_SECEE| \
18 PCI_EXP_RTCTL_SENFEE| \
19 PCI_EXP_RTCTL_SEFEE)
20#define ROOT_PORT_INTR_ON_MESG_MASK (PCI_ERR_ROOT_CMD_COR_EN| \
21 PCI_ERR_ROOT_CMD_NONFATAL_EN| \
22 PCI_ERR_ROOT_CMD_FATAL_EN)
23#define ERR_COR_ID(d) (d & 0xffff)
24#define ERR_UNCOR_ID(d) (d >> 16)
25
26#define AER_ERROR_SOURCES_MAX 100
27
28#define AER_LOG_TLP_MASKS (PCI_ERR_UNC_POISON_TLP| \
29 PCI_ERR_UNC_ECRC| \
30 PCI_ERR_UNC_UNSUP| \
31 PCI_ERR_UNC_COMP_ABORT| \
32 PCI_ERR_UNC_UNX_COMP| \
33 PCI_ERR_UNC_MALF_TLP)
34
35#define AER_MAX_MULTI_ERR_DEVICES 5 /* Not likely to have more */
36struct aer_err_info {
37 struct pci_dev *dev[AER_MAX_MULTI_ERR_DEVICES];
38 int error_dev_num;
39
40 unsigned int id:16;
41
42 unsigned int severity:2; /* 0:NONFATAL | 1:FATAL | 2:COR */
43 unsigned int __pad1:5;
44 unsigned int multi_error_valid:1;
45
46 unsigned int first_error:5;
47 unsigned int __pad2:2;
48 unsigned int tlp_header_valid:1;
49
50 unsigned int status; /* COR/UNCOR Error Status */
51 unsigned int mask; /* COR/UNCOR Error Mask */
52 struct aer_header_log_regs tlp; /* TLP Header */
53};
54
55struct aer_err_source {
56 unsigned int status;
57 unsigned int id;
58};
59
60struct aer_rpc {
61 struct pci_dev *rpd; /* Root Port device */
62 struct work_struct dpc_handler;
63 struct aer_err_source e_sources[AER_ERROR_SOURCES_MAX];
64 struct aer_err_info e_info;
65 unsigned short prod_idx; /* Error Producer Index */
66 unsigned short cons_idx; /* Error Consumer Index */
67 int isr;
68 spinlock_t e_lock; /*
69 * Lock access to Error Status/ID Regs
70 * and error producer/consumer index
71 */
72 struct mutex rpc_mutex; /*
73 * only one thread could do
74 * recovery on the same
75 * root port hierarchy
76 */
77};
78
79extern struct bus_type pcie_port_bus_type;
80void aer_isr(struct work_struct *work);
81void aer_print_error(struct pci_dev *dev, struct aer_err_info *info);
82void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info);
83irqreturn_t aer_irq(int irq, void *context);
84
85#ifdef CONFIG_ACPI_APEI
86int pcie_aer_get_firmware_first(struct pci_dev *pci_dev);
87#else
88static inline int pcie_aer_get_firmware_first(struct pci_dev *pci_dev)
89{
90 if (pci_dev->__aer_firmware_first_valid)
91 return pci_dev->__aer_firmware_first;
92 return 0;
93}
94#endif
95#endif /* _AERDRV_H_ */
diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c
deleted file mode 100644
index 08c87de13cb8..000000000000
--- a/drivers/pci/pcie/aer/aerdrv_acpi.c
+++ /dev/null
@@ -1,141 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Access ACPI _OSC method
4 *
5 * Copyright (C) 2006 Intel Corp.
6 * Tom Long Nguyen (tom.l.nguyen@intel.com)
7 * Zhang Yanmin (yanmin.zhang@intel.com)
8 */
9
10#include <linux/module.h>
11#include <linux/pci.h>
12#include <linux/kernel.h>
13#include <linux/errno.h>
14#include <linux/pm.h>
15#include <linux/suspend.h>
16#include <linux/acpi.h>
17#include <linux/pci-acpi.h>
18#include <linux/delay.h>
19#include <acpi/apei.h>
20#include "aerdrv.h"
21
22#ifdef CONFIG_ACPI_APEI
23static inline int hest_match_pci(struct acpi_hest_aer_common *p,
24 struct pci_dev *pci)
25{
26 return ACPI_HEST_SEGMENT(p->bus) == pci_domain_nr(pci->bus) &&
27 ACPI_HEST_BUS(p->bus) == pci->bus->number &&
28 p->device == PCI_SLOT(pci->devfn) &&
29 p->function == PCI_FUNC(pci->devfn);
30}
31
32static inline bool hest_match_type(struct acpi_hest_header *hest_hdr,
33 struct pci_dev *dev)
34{
35 u16 hest_type = hest_hdr->type;
36 u8 pcie_type = pci_pcie_type(dev);
37
38 if ((hest_type == ACPI_HEST_TYPE_AER_ROOT_PORT &&
39 pcie_type == PCI_EXP_TYPE_ROOT_PORT) ||
40 (hest_type == ACPI_HEST_TYPE_AER_ENDPOINT &&
41 pcie_type == PCI_EXP_TYPE_ENDPOINT) ||
42 (hest_type == ACPI_HEST_TYPE_AER_BRIDGE &&
43 (dev->class >> 16) == PCI_BASE_CLASS_BRIDGE))
44 return true;
45 return false;
46}
47
48struct aer_hest_parse_info {
49 struct pci_dev *pci_dev;
50 int firmware_first;
51};
52
53static int hest_source_is_pcie_aer(struct acpi_hest_header *hest_hdr)
54{
55 if (hest_hdr->type == ACPI_HEST_TYPE_AER_ROOT_PORT ||
56 hest_hdr->type == ACPI_HEST_TYPE_AER_ENDPOINT ||
57 hest_hdr->type == ACPI_HEST_TYPE_AER_BRIDGE)
58 return 1;
59 return 0;
60}
61
62static int aer_hest_parse(struct acpi_hest_header *hest_hdr, void *data)
63{
64 struct aer_hest_parse_info *info = data;
65 struct acpi_hest_aer_common *p;
66 int ff;
67
68 if (!hest_source_is_pcie_aer(hest_hdr))
69 return 0;
70
71 p = (struct acpi_hest_aer_common *)(hest_hdr + 1);
72 ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
73
74 /*
75 * If no specific device is supplied, determine whether
76 * FIRMWARE_FIRST is set for *any* PCIe device.
77 */
78 if (!info->pci_dev) {
79 info->firmware_first |= ff;
80 return 0;
81 }
82
83 /* Otherwise, check the specific device */
84 if (p->flags & ACPI_HEST_GLOBAL) {
85 if (hest_match_type(hest_hdr, info->pci_dev))
86 info->firmware_first = ff;
87 } else
88 if (hest_match_pci(p, info->pci_dev))
89 info->firmware_first = ff;
90
91 return 0;
92}
93
94static void aer_set_firmware_first(struct pci_dev *pci_dev)
95{
96 int rc;
97 struct aer_hest_parse_info info = {
98 .pci_dev = pci_dev,
99 .firmware_first = 0,
100 };
101
102 rc = apei_hest_parse(aer_hest_parse, &info);
103
104 if (rc)
105 pci_dev->__aer_firmware_first = 0;
106 else
107 pci_dev->__aer_firmware_first = info.firmware_first;
108 pci_dev->__aer_firmware_first_valid = 1;
109}
110
111int pcie_aer_get_firmware_first(struct pci_dev *dev)
112{
113 if (!pci_is_pcie(dev))
114 return 0;
115
116 if (!dev->__aer_firmware_first_valid)
117 aer_set_firmware_first(dev);
118 return dev->__aer_firmware_first;
119}
120
121static bool aer_firmware_first;
122
123/**
124 * aer_acpi_firmware_first - Check if APEI should control AER.
125 */
126bool aer_acpi_firmware_first(void)
127{
128 static bool parsed = false;
129 struct aer_hest_parse_info info = {
130 .pci_dev = NULL, /* Check all PCIe devices */
131 .firmware_first = 0,
132 };
133
134 if (!parsed) {
135 apei_hest_parse(aer_hest_parse, &info);
136 aer_firmware_first = info.firmware_first;
137 parsed = true;
138 }
139 return aer_firmware_first;
140}
141#endif
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
deleted file mode 100644
index 42d4f3f32282..000000000000
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ /dev/null
@@ -1,496 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Implement the core part of PCIe AER. When a PCIe error is delivered, an
4 * error message will be collected and printed to console, then an error
5 * recovery procedure will be executed by following the PCI error recovery
6 * rules.
7 *
8 * Copyright (C) 2006 Intel Corp.
9 * Tom Long Nguyen (tom.l.nguyen@intel.com)
10 * Zhang Yanmin (yanmin.zhang@intel.com)
11 */
12
13#include <linux/module.h>
14#include <linux/pci.h>
15#include <linux/kernel.h>
16#include <linux/errno.h>
17#include <linux/pm.h>
18#include <linux/suspend.h>
19#include <linux/delay.h>
20#include <linux/slab.h>
21#include <linux/kfifo.h>
22#include "aerdrv.h"
23#include "../../pci.h"
24
25#define PCI_EXP_AER_FLAGS (PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | \
26 PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE)
27
28int pci_enable_pcie_error_reporting(struct pci_dev *dev)
29{
30 if (pcie_aer_get_firmware_first(dev))
31 return -EIO;
32
33 if (!dev->aer_cap)
34 return -EIO;
35
36 return pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_AER_FLAGS);
37}
38EXPORT_SYMBOL_GPL(pci_enable_pcie_error_reporting);
39
40int pci_disable_pcie_error_reporting(struct pci_dev *dev)
41{
42 if (pcie_aer_get_firmware_first(dev))
43 return -EIO;
44
45 return pcie_capability_clear_word(dev, PCI_EXP_DEVCTL,
46 PCI_EXP_AER_FLAGS);
47}
48EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting);
49
50int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
51{
52 int pos;
53 u32 status;
54
55 pos = dev->aer_cap;
56 if (!pos)
57 return -EIO;
58
59 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
60 if (status)
61 pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
62
63 return 0;
64}
65EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status);
66
67int pci_cleanup_aer_error_status_regs(struct pci_dev *dev)
68{
69 int pos;
70 u32 status;
71 int port_type;
72
73 if (!pci_is_pcie(dev))
74 return -ENODEV;
75
76 pos = dev->aer_cap;
77 if (!pos)
78 return -EIO;
79
80 port_type = pci_pcie_type(dev);
81 if (port_type == PCI_EXP_TYPE_ROOT_PORT) {
82 pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &status);
83 pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, status);
84 }
85
86 pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &status);
87 pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, status);
88
89 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
90 pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
91
92 return 0;
93}
94
95int pci_aer_init(struct pci_dev *dev)
96{
97 dev->aer_cap = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
98 return pci_cleanup_aer_error_status_regs(dev);
99}
100
101/**
102 * add_error_device - list device to be handled
103 * @e_info: pointer to error info
104 * @dev: pointer to pci_dev to be added
105 */
106static int add_error_device(struct aer_err_info *e_info, struct pci_dev *dev)
107{
108 if (e_info->error_dev_num < AER_MAX_MULTI_ERR_DEVICES) {
109 e_info->dev[e_info->error_dev_num] = dev;
110 e_info->error_dev_num++;
111 return 0;
112 }
113 return -ENOSPC;
114}
115
116/**
117 * is_error_source - check whether the device is source of reported error
118 * @dev: pointer to pci_dev to be checked
119 * @e_info: pointer to reported error info
120 */
121static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info)
122{
123 int pos;
124 u32 status, mask;
125 u16 reg16;
126
127 /*
128 * When bus id is equal to 0, it might be a bad id
129 * reported by root port.
130 */
131 if ((PCI_BUS_NUM(e_info->id) != 0) &&
132 !(dev->bus->bus_flags & PCI_BUS_FLAGS_NO_AERSID)) {
133 /* Device ID match? */
134 if (e_info->id == ((dev->bus->number << 8) | dev->devfn))
135 return true;
136
137 /* Continue id comparing if there is no multiple error */
138 if (!e_info->multi_error_valid)
139 return false;
140 }
141
142 /*
143 * When either
144 * 1) bus id is equal to 0. Some ports might lose the bus
145 * id of error source id;
146 * 2) bus flag PCI_BUS_FLAGS_NO_AERSID is set
147 * 3) There are multiple errors and prior ID comparing fails;
148 * We check AER status registers to find possible reporter.
149 */
150 if (atomic_read(&dev->enable_cnt) == 0)
151 return false;
152
153 /* Check if AER is enabled */
154 pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &reg16);
155 if (!(reg16 & PCI_EXP_AER_FLAGS))
156 return false;
157
158 pos = dev->aer_cap;
159 if (!pos)
160 return false;
161
162 /* Check if error is recorded */
163 if (e_info->severity == AER_CORRECTABLE) {
164 pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &status);
165 pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &mask);
166 } else {
167 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
168 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, &mask);
169 }
170 if (status & ~mask)
171 return true;
172
173 return false;
174}
175
176static int find_device_iter(struct pci_dev *dev, void *data)
177{
178 struct aer_err_info *e_info = (struct aer_err_info *)data;
179
180 if (is_error_source(dev, e_info)) {
181 /* List this device */
182 if (add_error_device(e_info, dev)) {
183 /* We cannot handle more... Stop iteration */
184 /* TODO: Should print error message here? */
185 return 1;
186 }
187
188 /* If there is only a single error, stop iteration */
189 if (!e_info->multi_error_valid)
190 return 1;
191 }
192 return 0;
193}
194
195/**
196 * find_source_device - search through device hierarchy for source device
197 * @parent: pointer to Root Port pci_dev data structure
198 * @e_info: including detailed error information such like id
199 *
200 * Return true if found.
201 *
202 * Invoked by DPC when error is detected at the Root Port.
203 * Caller of this function must set id, severity, and multi_error_valid of
204 * struct aer_err_info pointed by @e_info properly. This function must fill
205 * e_info->error_dev_num and e_info->dev[], based on the given information.
206 */
207static bool find_source_device(struct pci_dev *parent,
208 struct aer_err_info *e_info)
209{
210 struct pci_dev *dev = parent;
211 int result;
212
213 /* Must reset in this function */
214 e_info->error_dev_num = 0;
215
216 /* Is Root Port an agent that sends error message? */
217 result = find_device_iter(dev, e_info);
218 if (result)
219 return true;
220
221 pci_walk_bus(parent->subordinate, find_device_iter, e_info);
222
223 if (!e_info->error_dev_num) {
224 pci_printk(KERN_DEBUG, parent, "can't find device of ID%04x\n",
225 e_info->id);
226 return false;
227 }
228 return true;
229}
230
231/**
232 * handle_error_source - handle logging error into an event log
233 * @dev: pointer to pci_dev data structure of error source device
234 * @info: comprehensive error information
235 *
236 * Invoked when an error being detected by Root Port.
237 */
238static void handle_error_source(struct pci_dev *dev, struct aer_err_info *info)
239{
240 int pos;
241
242 if (info->severity == AER_CORRECTABLE) {
243 /*
244 * Correctable error does not need software intervention.
245 * No need to go through error recovery process.
246 */
247 pos = dev->aer_cap;
248 if (pos)
249 pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS,
250 info->status);
251 } else if (info->severity == AER_NONFATAL)
252 pcie_do_nonfatal_recovery(dev);
253 else if (info->severity == AER_FATAL)
254 pcie_do_fatal_recovery(dev, PCIE_PORT_SERVICE_AER);
255}
256
257#ifdef CONFIG_ACPI_APEI_PCIEAER
258
259#define AER_RECOVER_RING_ORDER 4
260#define AER_RECOVER_RING_SIZE (1 << AER_RECOVER_RING_ORDER)
261
262struct aer_recover_entry {
263 u8 bus;
264 u8 devfn;
265 u16 domain;
266 int severity;
267 struct aer_capability_regs *regs;
268};
269
270static DEFINE_KFIFO(aer_recover_ring, struct aer_recover_entry,
271 AER_RECOVER_RING_SIZE);
272
273static void aer_recover_work_func(struct work_struct *work)
274{
275 struct aer_recover_entry entry;
276 struct pci_dev *pdev;
277
278 while (kfifo_get(&aer_recover_ring, &entry)) {
279 pdev = pci_get_domain_bus_and_slot(entry.domain, entry.bus,
280 entry.devfn);
281 if (!pdev) {
282 pr_err("AER recover: Can not find pci_dev for %04x:%02x:%02x:%x\n",
283 entry.domain, entry.bus,
284 PCI_SLOT(entry.devfn), PCI_FUNC(entry.devfn));
285 continue;
286 }
287 cper_print_aer(pdev, entry.severity, entry.regs);
288 if (entry.severity == AER_NONFATAL)
289 pcie_do_nonfatal_recovery(pdev);
290 else if (entry.severity == AER_FATAL)
291 pcie_do_fatal_recovery(pdev, PCIE_PORT_SERVICE_AER);
292 pci_dev_put(pdev);
293 }
294}
295
296/*
297 * Mutual exclusion for writers of aer_recover_ring, reader side don't
298 * need lock, because there is only one reader and lock is not needed
299 * between reader and writer.
300 */
301static DEFINE_SPINLOCK(aer_recover_ring_lock);
302static DECLARE_WORK(aer_recover_work, aer_recover_work_func);
303
304void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
305 int severity, struct aer_capability_regs *aer_regs)
306{
307 unsigned long flags;
308 struct aer_recover_entry entry = {
309 .bus = bus,
310 .devfn = devfn,
311 .domain = domain,
312 .severity = severity,
313 .regs = aer_regs,
314 };
315
316 spin_lock_irqsave(&aer_recover_ring_lock, flags);
317 if (kfifo_put(&aer_recover_ring, entry))
318 schedule_work(&aer_recover_work);
319 else
320 pr_err("AER recover: Buffer overflow when recovering AER for %04x:%02x:%02x:%x\n",
321 domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
322 spin_unlock_irqrestore(&aer_recover_ring_lock, flags);
323}
324EXPORT_SYMBOL_GPL(aer_recover_queue);
325#endif
326
327/**
328 * get_device_error_info - read error status from dev and store it to info
329 * @dev: pointer to the device expected to have a error record
330 * @info: pointer to structure to store the error record
331 *
332 * Return 1 on success, 0 on error.
333 *
334 * Note that @info is reused among all error devices. Clear fields properly.
335 */
336static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info)
337{
338 int pos, temp;
339
340 /* Must reset in this function */
341 info->status = 0;
342 info->tlp_header_valid = 0;
343
344 pos = dev->aer_cap;
345
346 /* The device might not support AER */
347 if (!pos)
348 return 0;
349
350 if (info->severity == AER_CORRECTABLE) {
351 pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS,
352 &info->status);
353 pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK,
354 &info->mask);
355 if (!(info->status & ~info->mask))
356 return 0;
357 } else if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
358 info->severity == AER_NONFATAL) {
359
360 /* Link is still healthy for IO reads */
361 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS,
362 &info->status);
363 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK,
364 &info->mask);
365 if (!(info->status & ~info->mask))
366 return 0;
367
368 /* Get First Error Pointer */
369 pci_read_config_dword(dev, pos + PCI_ERR_CAP, &temp);
370 info->first_error = PCI_ERR_CAP_FEP(temp);
371
372 if (info->status & AER_LOG_TLP_MASKS) {
373 info->tlp_header_valid = 1;
374 pci_read_config_dword(dev,
375 pos + PCI_ERR_HEADER_LOG, &info->tlp.dw0);
376 pci_read_config_dword(dev,
377 pos + PCI_ERR_HEADER_LOG + 4, &info->tlp.dw1);
378 pci_read_config_dword(dev,
379 pos + PCI_ERR_HEADER_LOG + 8, &info->tlp.dw2);
380 pci_read_config_dword(dev,
381 pos + PCI_ERR_HEADER_LOG + 12, &info->tlp.dw3);
382 }
383 }
384
385 return 1;
386}
387
388static inline void aer_process_err_devices(struct aer_err_info *e_info)
389{
390 int i;
391
392 /* Report all before handle them, not to lost records by reset etc. */
393 for (i = 0; i < e_info->error_dev_num && e_info->dev[i]; i++) {
394 if (get_device_error_info(e_info->dev[i], e_info))
395 aer_print_error(e_info->dev[i], e_info);
396 }
397 for (i = 0; i < e_info->error_dev_num && e_info->dev[i]; i++) {
398 if (get_device_error_info(e_info->dev[i], e_info))
399 handle_error_source(e_info->dev[i], e_info);
400 }
401}
402
403/**
404 * aer_isr_one_error - consume an error detected by root port
405 * @rpc: pointer to the root port which holds an error
406 * @e_src: pointer to an error source
407 */
408static void aer_isr_one_error(struct aer_rpc *rpc,
409 struct aer_err_source *e_src)
410{
411 struct pci_dev *pdev = rpc->rpd;
412 struct aer_err_info *e_info = &rpc->e_info;
413
414 /*
415 * There is a possibility that both correctable error and
416 * uncorrectable error being logged. Report correctable error first.
417 */
418 if (e_src->status & PCI_ERR_ROOT_COR_RCV) {
419 e_info->id = ERR_COR_ID(e_src->id);
420 e_info->severity = AER_CORRECTABLE;
421
422 if (e_src->status & PCI_ERR_ROOT_MULTI_COR_RCV)
423 e_info->multi_error_valid = 1;
424 else
425 e_info->multi_error_valid = 0;
426 aer_print_port_info(pdev, e_info);
427
428 if (find_source_device(pdev, e_info))
429 aer_process_err_devices(e_info);
430 }
431
432 if (e_src->status & PCI_ERR_ROOT_UNCOR_RCV) {
433 e_info->id = ERR_UNCOR_ID(e_src->id);
434
435 if (e_src->status & PCI_ERR_ROOT_FATAL_RCV)
436 e_info->severity = AER_FATAL;
437 else
438 e_info->severity = AER_NONFATAL;
439
440 if (e_src->status & PCI_ERR_ROOT_MULTI_UNCOR_RCV)
441 e_info->multi_error_valid = 1;
442 else
443 e_info->multi_error_valid = 0;
444
445 aer_print_port_info(pdev, e_info);
446
447 if (find_source_device(pdev, e_info))
448 aer_process_err_devices(e_info);
449 }
450}
451
452/**
453 * get_e_source - retrieve an error source
454 * @rpc: pointer to the root port which holds an error
455 * @e_src: pointer to store retrieved error source
456 *
457 * Return 1 if an error source is retrieved, otherwise 0.
458 *
459 * Invoked by DPC handler to consume an error.
460 */
461static int get_e_source(struct aer_rpc *rpc, struct aer_err_source *e_src)
462{
463 unsigned long flags;
464
465 /* Lock access to Root error producer/consumer index */
466 spin_lock_irqsave(&rpc->e_lock, flags);
467 if (rpc->prod_idx == rpc->cons_idx) {
468 spin_unlock_irqrestore(&rpc->e_lock, flags);
469 return 0;
470 }
471
472 *e_src = rpc->e_sources[rpc->cons_idx];
473 rpc->cons_idx++;
474 if (rpc->cons_idx == AER_ERROR_SOURCES_MAX)
475 rpc->cons_idx = 0;
476 spin_unlock_irqrestore(&rpc->e_lock, flags);
477
478 return 1;
479}
480
481/**
482 * aer_isr - consume errors detected by root port
483 * @work: definition of this work item
484 *
485 * Invoked, as DPC, when root port records new detected error
486 */
487void aer_isr(struct work_struct *work)
488{
489 struct aer_rpc *rpc = container_of(work, struct aer_rpc, dpc_handler);
490 struct aer_err_source uninitialized_var(e_src);
491
492 mutex_lock(&rpc->rpc_mutex);
493 while (get_e_source(rpc, &e_src))
494 aer_isr_one_error(rpc, &e_src);
495 mutex_unlock(&rpc->rpc_mutex);
496}
diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c
deleted file mode 100644
index 4985bdf64c2e..000000000000
--- a/drivers/pci/pcie/aer/aerdrv_errprint.c
+++ /dev/null
@@ -1,260 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Format error messages and print them to console.
4 *
5 * Copyright (C) 2006 Intel Corp.
6 * Tom Long Nguyen (tom.l.nguyen@intel.com)
7 * Zhang Yanmin (yanmin.zhang@intel.com)
8 */
9
10#include <linux/module.h>
11#include <linux/pci.h>
12#include <linux/kernel.h>
13#include <linux/errno.h>
14#include <linux/pm.h>
15#include <linux/suspend.h>
16#include <linux/cper.h>
17
18#include "aerdrv.h"
19#include <ras/ras_event.h>
20
21#define AER_AGENT_RECEIVER 0
22#define AER_AGENT_REQUESTER 1
23#define AER_AGENT_COMPLETER 2
24#define AER_AGENT_TRANSMITTER 3
25
26#define AER_AGENT_REQUESTER_MASK(t) ((t == AER_CORRECTABLE) ? \
27 0 : (PCI_ERR_UNC_COMP_TIME|PCI_ERR_UNC_UNSUP))
28#define AER_AGENT_COMPLETER_MASK(t) ((t == AER_CORRECTABLE) ? \
29 0 : PCI_ERR_UNC_COMP_ABORT)
30#define AER_AGENT_TRANSMITTER_MASK(t) ((t == AER_CORRECTABLE) ? \
31 (PCI_ERR_COR_REP_ROLL|PCI_ERR_COR_REP_TIMER) : 0)
32
33#define AER_GET_AGENT(t, e) \
34 ((e & AER_AGENT_COMPLETER_MASK(t)) ? AER_AGENT_COMPLETER : \
35 (e & AER_AGENT_REQUESTER_MASK(t)) ? AER_AGENT_REQUESTER : \
36 (e & AER_AGENT_TRANSMITTER_MASK(t)) ? AER_AGENT_TRANSMITTER : \
37 AER_AGENT_RECEIVER)
38
39#define AER_PHYSICAL_LAYER_ERROR 0
40#define AER_DATA_LINK_LAYER_ERROR 1
41#define AER_TRANSACTION_LAYER_ERROR 2
42
43#define AER_PHYSICAL_LAYER_ERROR_MASK(t) ((t == AER_CORRECTABLE) ? \
44 PCI_ERR_COR_RCVR : 0)
45#define AER_DATA_LINK_LAYER_ERROR_MASK(t) ((t == AER_CORRECTABLE) ? \
46 (PCI_ERR_COR_BAD_TLP| \
47 PCI_ERR_COR_BAD_DLLP| \
48 PCI_ERR_COR_REP_ROLL| \
49 PCI_ERR_COR_REP_TIMER) : PCI_ERR_UNC_DLP)
50
51#define AER_GET_LAYER_ERROR(t, e) \
52 ((e & AER_PHYSICAL_LAYER_ERROR_MASK(t)) ? AER_PHYSICAL_LAYER_ERROR : \
53 (e & AER_DATA_LINK_LAYER_ERROR_MASK(t)) ? AER_DATA_LINK_LAYER_ERROR : \
54 AER_TRANSACTION_LAYER_ERROR)
55
56/*
57 * AER error strings
58 */
59static const char *aer_error_severity_string[] = {
60 "Uncorrected (Non-Fatal)",
61 "Uncorrected (Fatal)",
62 "Corrected"
63};
64
65static const char *aer_error_layer[] = {
66 "Physical Layer",
67 "Data Link Layer",
68 "Transaction Layer"
69};
70
71static const char *aer_correctable_error_string[] = {
72 "Receiver Error", /* Bit Position 0 */
73 NULL,
74 NULL,
75 NULL,
76 NULL,
77 NULL,
78 "Bad TLP", /* Bit Position 6 */
79 "Bad DLLP", /* Bit Position 7 */
80 "RELAY_NUM Rollover", /* Bit Position 8 */
81 NULL,
82 NULL,
83 NULL,
84 "Replay Timer Timeout", /* Bit Position 12 */
85 "Advisory Non-Fatal", /* Bit Position 13 */
86 "Corrected Internal Error", /* Bit Position 14 */
87 "Header Log Overflow", /* Bit Position 15 */
88};
89
90static const char *aer_uncorrectable_error_string[] = {
91 "Undefined", /* Bit Position 0 */
92 NULL,
93 NULL,
94 NULL,
95 "Data Link Protocol", /* Bit Position 4 */
96 "Surprise Down Error", /* Bit Position 5 */
97 NULL,
98 NULL,
99 NULL,
100 NULL,
101 NULL,
102 NULL,
103 "Poisoned TLP", /* Bit Position 12 */
104 "Flow Control Protocol", /* Bit Position 13 */
105 "Completion Timeout", /* Bit Position 14 */
106 "Completer Abort", /* Bit Position 15 */
107 "Unexpected Completion", /* Bit Position 16 */
108 "Receiver Overflow", /* Bit Position 17 */
109 "Malformed TLP", /* Bit Position 18 */
110 "ECRC", /* Bit Position 19 */
111 "Unsupported Request", /* Bit Position 20 */
112 "ACS Violation", /* Bit Position 21 */
113 "Uncorrectable Internal Error", /* Bit Position 22 */
114 "MC Blocked TLP", /* Bit Position 23 */
115 "AtomicOp Egress Blocked", /* Bit Position 24 */
116 "TLP Prefix Blocked Error", /* Bit Position 25 */
117};
118
119static const char *aer_agent_string[] = {
120 "Receiver ID",
121 "Requester ID",
122 "Completer ID",
123 "Transmitter ID"
124};
125
126static void __print_tlp_header(struct pci_dev *dev,
127 struct aer_header_log_regs *t)
128{
129 pci_err(dev, " TLP Header: %08x %08x %08x %08x\n",
130 t->dw0, t->dw1, t->dw2, t->dw3);
131}
132
133static void __aer_print_error(struct pci_dev *dev,
134 struct aer_err_info *info)
135{
136 int i, status;
137 const char *errmsg = NULL;
138 status = (info->status & ~info->mask);
139
140 for (i = 0; i < 32; i++) {
141 if (!(status & (1 << i)))
142 continue;
143
144 if (info->severity == AER_CORRECTABLE)
145 errmsg = i < ARRAY_SIZE(aer_correctable_error_string) ?
146 aer_correctable_error_string[i] : NULL;
147 else
148 errmsg = i < ARRAY_SIZE(aer_uncorrectable_error_string) ?
149 aer_uncorrectable_error_string[i] : NULL;
150
151 if (errmsg)
152 pci_err(dev, " [%2d] %-22s%s\n", i, errmsg,
153 info->first_error == i ? " (First)" : "");
154 else
155 pci_err(dev, " [%2d] Unknown Error Bit%s\n",
156 i, info->first_error == i ? " (First)" : "");
157 }
158}
159
160void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
161{
162 int layer, agent;
163 int id = ((dev->bus->number << 8) | dev->devfn);
164
165 if (!info->status) {
166 pci_err(dev, "PCIe Bus Error: severity=%s, type=Inaccessible, (Unregistered Agent ID)\n",
167 aer_error_severity_string[info->severity]);
168 goto out;
169 }
170
171 layer = AER_GET_LAYER_ERROR(info->severity, info->status);
172 agent = AER_GET_AGENT(info->severity, info->status);
173
174 pci_err(dev, "PCIe Bus Error: severity=%s, type=%s, (%s)\n",
175 aer_error_severity_string[info->severity],
176 aer_error_layer[layer], aer_agent_string[agent]);
177
178 pci_err(dev, " device [%04x:%04x] error status/mask=%08x/%08x\n",
179 dev->vendor, dev->device,
180 info->status, info->mask);
181
182 __aer_print_error(dev, info);
183
184 if (info->tlp_header_valid)
185 __print_tlp_header(dev, &info->tlp);
186
187out:
188 if (info->id && info->error_dev_num > 1 && info->id == id)
189 pci_err(dev, " Error of this Agent is reported first\n");
190
191 trace_aer_event(dev_name(&dev->dev), (info->status & ~info->mask),
192 info->severity, info->tlp_header_valid, &info->tlp);
193}
194
195void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info)
196{
197 u8 bus = info->id >> 8;
198 u8 devfn = info->id & 0xff;
199
200 pci_info(dev, "AER: %s%s error received: %04x:%02x:%02x.%d\n",
201 info->multi_error_valid ? "Multiple " : "",
202 aer_error_severity_string[info->severity],
203 pci_domain_nr(dev->bus), bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
204}
205
206#ifdef CONFIG_ACPI_APEI_PCIEAER
207int cper_severity_to_aer(int cper_severity)
208{
209 switch (cper_severity) {
210 case CPER_SEV_RECOVERABLE:
211 return AER_NONFATAL;
212 case CPER_SEV_FATAL:
213 return AER_FATAL;
214 default:
215 return AER_CORRECTABLE;
216 }
217}
218EXPORT_SYMBOL_GPL(cper_severity_to_aer);
219
220void cper_print_aer(struct pci_dev *dev, int aer_severity,
221 struct aer_capability_regs *aer)
222{
223 int layer, agent, tlp_header_valid = 0;
224 u32 status, mask;
225 struct aer_err_info info;
226
227 if (aer_severity == AER_CORRECTABLE) {
228 status = aer->cor_status;
229 mask = aer->cor_mask;
230 } else {
231 status = aer->uncor_status;
232 mask = aer->uncor_mask;
233 tlp_header_valid = status & AER_LOG_TLP_MASKS;
234 }
235
236 layer = AER_GET_LAYER_ERROR(aer_severity, status);
237 agent = AER_GET_AGENT(aer_severity, status);
238
239 memset(&info, 0, sizeof(info));
240 info.severity = aer_severity;
241 info.status = status;
242 info.mask = mask;
243 info.first_error = PCI_ERR_CAP_FEP(aer->cap_control);
244
245 pci_err(dev, "aer_status: 0x%08x, aer_mask: 0x%08x\n", status, mask);
246 __aer_print_error(dev, &info);
247 pci_err(dev, "aer_layer=%s, aer_agent=%s\n",
248 aer_error_layer[layer], aer_agent_string[agent]);
249
250 if (aer_severity != AER_CORRECTABLE)
251 pci_err(dev, "aer_uncor_severity: 0x%08x\n",
252 aer->uncor_severity);
253
254 if (tlp_header_valid)
255 __print_tlp_header(dev, &aer->header_log);
256
257 trace_aer_event(dev_name(&dev->dev), (status & ~mask),
258 aer_severity, tlp_header_valid, &aer->header_log);
259}
260#endif
diff --git a/drivers/pci/pcie/aer/ecrc.c b/drivers/pci/pcie/aer/ecrc.c
deleted file mode 100644
index 039efb606e31..000000000000
--- a/drivers/pci/pcie/aer/ecrc.c
+++ /dev/null
@@ -1,117 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Enable/disable PCIe ECRC checking
4 *
5 * (C) Copyright 2009 Hewlett-Packard Development Company, L.P.
6 * Andrew Patterson <andrew.patterson@hp.com>
7 */
8
9#include <linux/kernel.h>
10#include <linux/module.h>
11#include <linux/moduleparam.h>
12#include <linux/pci.h>
13#include <linux/pci_regs.h>
14#include <linux/errno.h>
15#include "../../pci.h"
16
17#define ECRC_POLICY_DEFAULT 0 /* ECRC set by BIOS */
18#define ECRC_POLICY_OFF 1 /* ECRC off for performance */
19#define ECRC_POLICY_ON 2 /* ECRC on for data integrity */
20
21static int ecrc_policy = ECRC_POLICY_DEFAULT;
22
23static const char *ecrc_policy_str[] = {
24 [ECRC_POLICY_DEFAULT] = "bios",
25 [ECRC_POLICY_OFF] = "off",
26 [ECRC_POLICY_ON] = "on"
27};
28
29/**
30 * enable_ercr_checking - enable PCIe ECRC checking for a device
31 * @dev: the PCI device
32 *
33 * Returns 0 on success, or negative on failure.
34 */
35static int enable_ecrc_checking(struct pci_dev *dev)
36{
37 int pos;
38 u32 reg32;
39
40 if (!pci_is_pcie(dev))
41 return -ENODEV;
42
43 pos = dev->aer_cap;
44 if (!pos)
45 return -ENODEV;
46
47 pci_read_config_dword(dev, pos + PCI_ERR_CAP, &reg32);
48 if (reg32 & PCI_ERR_CAP_ECRC_GENC)
49 reg32 |= PCI_ERR_CAP_ECRC_GENE;
50 if (reg32 & PCI_ERR_CAP_ECRC_CHKC)
51 reg32 |= PCI_ERR_CAP_ECRC_CHKE;
52 pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32);
53
54 return 0;
55}
56
57/**
58 * disable_ercr_checking - disables PCIe ECRC checking for a device
59 * @dev: the PCI device
60 *
61 * Returns 0 on success, or negative on failure.
62 */
63static int disable_ecrc_checking(struct pci_dev *dev)
64{
65 int pos;
66 u32 reg32;
67
68 if (!pci_is_pcie(dev))
69 return -ENODEV;
70
71 pos = dev->aer_cap;
72 if (!pos)
73 return -ENODEV;
74
75 pci_read_config_dword(dev, pos + PCI_ERR_CAP, &reg32);
76 reg32 &= ~(PCI_ERR_CAP_ECRC_GENE | PCI_ERR_CAP_ECRC_CHKE);
77 pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32);
78
79 return 0;
80}
81
82/**
83 * pcie_set_ecrc_checking - set/unset PCIe ECRC checking for a device based on global policy
84 * @dev: the PCI device
85 */
86void pcie_set_ecrc_checking(struct pci_dev *dev)
87{
88 switch (ecrc_policy) {
89 case ECRC_POLICY_DEFAULT:
90 return;
91 case ECRC_POLICY_OFF:
92 disable_ecrc_checking(dev);
93 break;
94 case ECRC_POLICY_ON:
95 enable_ecrc_checking(dev);
96 break;
97 default:
98 return;
99 }
100}
101
102/**
103 * pcie_ecrc_get_policy - parse kernel command-line ecrc option
104 */
105void pcie_ecrc_get_policy(char *str)
106{
107 int i;
108
109 for (i = 0; i < ARRAY_SIZE(ecrc_policy_str); i++)
110 if (!strncmp(str, ecrc_policy_str[i],
111 strlen(ecrc_policy_str[i])))
112 break;
113 if (i >= ARRAY_SIZE(ecrc_policy_str))
114 return;
115
116 ecrc_policy = i;
117}
diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer_inject.c
index a49090935303..0eb24346cad3 100644
--- a/drivers/pci/pcie/aer/aer_inject.c
+++ b/drivers/pci/pcie/aer_inject.c
@@ -21,7 +21,8 @@
21#include <linux/uaccess.h> 21#include <linux/uaccess.h>
22#include <linux/stddef.h> 22#include <linux/stddef.h>
23#include <linux/device.h> 23#include <linux/device.h>
24#include "aerdrv.h" 24
25#include "portdrv.h"
25 26
26/* Override the existing corrected and uncorrected error masks */ 27/* Override the existing corrected and uncorrected error masks */
27static bool aer_mask_override; 28static bool aer_mask_override;
diff --git a/drivers/pci/pcie/dpc.c b/drivers/pci/pcie/dpc.c
index d6436681c535..921ed979109d 100644
--- a/drivers/pci/pcie/dpc.c
+++ b/drivers/pci/pcie/dpc.c
@@ -13,7 +13,6 @@
13 13
14#include "portdrv.h" 14#include "portdrv.h"
15#include "../pci.h" 15#include "../pci.h"
16#include "aer/aerdrv.h"
17 16
18struct dpc_dev { 17struct dpc_dev {
19 struct pcie_device *dev; 18 struct pcie_device *dev;
diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h
index 2bb5db7b53e6..6ffc797a0dc1 100644
--- a/drivers/pci/pcie/portdrv.h
+++ b/drivers/pci/pcie/portdrv.h
@@ -110,6 +110,21 @@ static inline bool pcie_pme_no_msi(void) { return false; }
110static inline void pcie_pme_interrupt_enable(struct pci_dev *dev, bool en) {} 110static inline void pcie_pme_interrupt_enable(struct pci_dev *dev, bool en) {}
111#endif /* !CONFIG_PCIE_PME */ 111#endif /* !CONFIG_PCIE_PME */
112 112
113#ifdef CONFIG_ACPI_APEI
114int pcie_aer_get_firmware_first(struct pci_dev *pci_dev);
115#else
116static inline int pcie_aer_get_firmware_first(struct pci_dev *pci_dev)
117{
118 if (pci_dev->__aer_firmware_first_valid)
119 return pci_dev->__aer_firmware_first;
120 return 0;
121}
122#endif
123
124#ifdef CONFIG_PCIEAER
125irqreturn_t aer_irq(int irq, void *context);
126#endif
127
113struct pcie_port_service_driver *pcie_port_find_service(struct pci_dev *dev, 128struct pcie_port_service_driver *pcie_port_find_service(struct pci_dev *dev,
114 u32 service); 129 u32 service);
115struct device *pcie_port_find_device(struct pci_dev *dev, u32 service); 130struct device *pcie_port_find_device(struct pci_dev *dev, u32 service);