Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'pci-v6.17-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci

Pull PCI updates from Bjorn Helgaas:
"Enumeration:

- Allow built-in drivers, not just modular drivers, to use async
initial probing (Lukas Wunner)

- Support Immediate Readiness even on devices with no PM Capability
(Sean Christopherson)

- Consolidate definition of PCIE_RESET_CONFIG_WAIT_MS (100ms), the
required delay between a reset and sending config requests to a
device (Niklas Cassel)

- Add pci_is_display() to check for "Display" base class and use it
in ALSA hda, vfio, vga_switcheroo, vt-d (Mario Limonciello)

- Allow 'isolated PCI functions' (multi-function devices without a
function 0) for LoongArch, similar to s390 and jailhouse (Huacai
Chen)

Power control:

- Add ability to enable optional slot clock for cases where the PCIe
host controller and the slot are supplied by different clocks
(Marek Vasut)

PCIe native device hotplug:

- Fix runtime PM ref imbalance on Hot-Plug Capable ports caused by
misinterpreting a config read failure after a device has been
removed (Lukas Wunner)

- Avoid creating a useless PCIe port service device for pciehp if the
slot is handled by the ACPI hotplug driver (Lukas Wunner)

- Ignore ACPI hotplug slots when calculating depth of pciehp hotplug
ports (Lukas Wunner)

Virtualization:

- Save VF resizable BAR state and restore it after reset (Michał
Winiarski)

- Allow IOV resources (VF BARs) to be resized (Michał Winiarski)

- Add pci_iov_vf_bar_set_size() so drivers can control VF BAR size
(Michał Winiarski)

Endpoint framework:

- Add RC-to-EP doorbell support using platform MSI controller,
including a test case (Frank Li)

- Allow BAR assignment via configfs so platforms have flexibility in
determining BAR usage (Jerome Brunet)

Native PCIe controller drivers:

- Convert amazon,al-alpine-v[23]-pcie, apm,xgene-pcie,
axis,artpec6-pcie, marvell,armada-3700-pcie, st,spear1340-pcie to
DT schema format (Rob Herring)

- Use dev_fwnode() instead of of_fwnode_handle() to remove OF
dependency in altera (fixes an unused variable), designware-host,
mediatek, mediatek-gen3, mobiveil, plda, xilinx, xilinx-dma,
xilinx-nwl (Jiri Slaby, Arnd Bergmann)

- Convert aardvark, altera, brcmstb, designware-host, iproc,
mediatek, mediatek-gen3, mobiveil, plda, rcar-host, vmd, xilinx,
xilinx-dma, xilinx-nwl from using pci_msi_create_irq_domain() to
using msi_create_parent_irq_domain() instead; this makes the
interrupt controller per-PCI device, allows dynamic allocation of
vectors after initialization, and allows support of IMS (Nam Cao)

APM X-Gene PCIe controller driver:

- Rewrite MSI handling to MSI CPU affinity, drop useless CPU hotplug
bits, use device-managed memory allocations, and clean things up
(Marc Zyngier)

- Probe xgene-msi as a standard platform driver rather than a
subsys_initcall (Marc Zyngier)

Broadcom STB PCIe controller driver:

- Add optional DT 'num-lanes' property and if present, use it to
override the Maximum Link Width advertised in Link Capabilities
(Jim Quinlan)

Cadence PCIe controller driver:

- Use PCIe Message routing types from the PCI core rather than
defining private ones (Hans Zhang)

Freescale i.MX6 PCIe controller driver:

- Add IMX8MQ_EP third 64-bit BAR in epc_features (Richard Zhu)

- Add IMX8MM_EP and IMX8MP_EP fixed 256-byte BAR 4 in epc_features
(Richard Zhu)

- Configure LUT for MSI/IOMMU in Endpoint mode so Root Complex can
trigger doorbel on Endpoint (Frank Li)

- Remove apps_reset (LTSSM_EN) from
imx_pcie_{assert,deassert}_core_reset(), which fixes a hotplug
regression on i.MX8MM (Richard Zhu)

- Delay Endpoint link start until configfs 'start' written (Richard
Zhu)

Intel VMD host bridge driver:

- Add Intel Panther Lake (PTL)-H/P/U Vendor ID (George D Sworo)

Qualcomm PCIe controller driver:

- Add DT binding and driver support for SA8255p, which supports ECAM
for Configuration Space access (Mayank Rana)

- Update DT binding and driver to describe PHYs and per-Root Port
resets in a Root Port stanza and deprecate describing them in the
host bridge; this makes it possible to support multiple Root Ports
in the future (Krishna Chaitanya Chundru)

- Add Qualcomm QCS615 to SM8150 DT binding (Ziyue Zhang)

- Add Qualcomm QCS8300 to SA8775p DT binding (Ziyue Zhang)

- Drop TBU and ref clocks from Qualcomm SM8150 and SC8180x DT
bindings (Konrad Dybcio)

- Document 'link_down' reset in Qualcomm SA8775P DT binding (Ziyue
Zhang)

- Add required PCIE_RESET_CONFIG_WAIT_MS delay after Link up IRQ
(Niklas Cassel)

Rockchip PCIe controller driver:

- Drop unused PCIe Message routing and code definitions (Hans Zhang)

- Remove several unused header includes (Hans Zhang)

- Use standard PCIe config register definitions instead of
rockchip-specific redefinitions (Geraldo Nascimento)

- Set Target Link Speed to 5.0 GT/s before retraining so we have a
chance to train at a higher speed (Geraldo Nascimento)

Rockchip DesignWare PCIe controller driver:

- Prevent race between link training and register update via DBI by
inhibiting link training after hot reset and link down (Wilfred
Mallawa)

- Add required PCIE_RESET_CONFIG_WAIT_MS delay after Link up IRQ
(Niklas Cassel)

Sophgo PCIe controller driver:

- Add DT binding and driver for Sophgo SG2044 PCIe controller driver
in Root Complex mode (Inochi Amaoto)

Synopsys DesignWare PCIe controller driver:

- Add required PCIE_RESET_CONFIG_WAIT_MS after waiting for Link up on
Ports that support > 5.0 GT/s. Slower Ports still rely on the
not-quite-correct PCIE_LINK_WAIT_SLEEP_MS 90ms default delay while
waiting for the Link (Niklas Cassel)"

* tag 'pci-v6.17-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci: (116 commits)
dt-bindings: PCI: qcom,pcie-sa8775p: Document 'link_down' reset
dt-bindings: PCI: Remove 83xx-512x-pci.txt
dt-bindings: PCI: Convert amazon,al-alpine-v[23]-pcie to DT schema
dt-bindings: PCI: Convert marvell,armada-3700-pcie to DT schema
dt-bindings: PCI: Convert apm,xgene-pcie to DT schema
dt-bindings: PCI: Convert axis,artpec6-pcie to DT schema
dt-bindings: PCI: Convert st,spear1340-pcie to DT schema
PCI: Move is_pciehp check out of pciehp_is_native()
PCI: pciehp: Use is_pciehp instead of is_hotplug_bridge
PCI/portdrv: Use is_pciehp instead of is_hotplug_bridge
PCI/ACPI: Fix runtime PM ref imbalance on Hot-Plug Capable ports
selftests: pci_endpoint: Add doorbell test case
misc: pci_endpoint_test: Add doorbell test case
PCI: endpoint: pci-epf-test: Add doorbell test support
PCI: endpoint: Add pci_epf_align_inbound_addr() helper for inbound address alignment
PCI: endpoint: pci-ep-msi: Add checks for MSI parent and mutability
PCI: endpoint: Add RC-to-EP doorbell support using platform MSI controller
PCI: dwc: Add Sophgo SG2044 PCIe controller driver in Root Complex mode
PCI: vmd: Switch to msi_create_parent_irq_domain()
PCI: vmd: Convert to lock guards
...

+2996 -1375
+15
Documentation/PCI/endpoint/pci-test-howto.rst
··· 203 203 command:: 204 204 205 205 # pci_endpoint_test -f pci_ep_bar -f pci_ep_basic -v memcpy -T COPY_TEST -v dma 206 + 207 + Kselftest EP Doorbell 208 + ~~~~~~~~~~~~~~~~~~~~~ 209 + 210 + If the Endpoint MSI controller is used for the doorbell usecase, run below 211 + command for testing it: 212 + 213 + # pci_endpoint_test -f pcie_ep_doorbell 214 + 215 + # Starting 1 tests from 1 test cases. 216 + # RUN pcie_ep_doorbell.DOORBELL_TEST ... 217 + # OK pcie_ep_doorbell.DOORBELL_TEST 218 + ok 1 pcie_ep_doorbell.DOORBELL_TEST 219 + # PASSED: 1 / 1 tests passed. 220 + # Totals: pass:1 fail:0 xfail:0 xpass:0 skip:0 error:0
-39
Documentation/devicetree/bindings/pci/83xx-512x-pci.txt
··· 1 - * Freescale 83xx and 512x PCI bridges 2 - 3 - Freescale 83xx and 512x SOCs include the same PCI bridge core. 4 - 5 - 83xx/512x specific notes: 6 - - reg: should contain two address length tuples 7 - The first is for the internal PCI bridge registers 8 - The second is for the PCI config space access registers 9 - 10 - Example (MPC8313ERDB) 11 - pci0: pci@e0008500 { 12 - interrupt-map-mask = <0xf800 0x0 0x0 0x7>; 13 - interrupt-map = < 14 - /* IDSEL 0x0E -mini PCI */ 15 - 0x7000 0x0 0x0 0x1 &ipic 18 0x8 16 - 0x7000 0x0 0x0 0x2 &ipic 18 0x8 17 - 0x7000 0x0 0x0 0x3 &ipic 18 0x8 18 - 0x7000 0x0 0x0 0x4 &ipic 18 0x8 19 - 20 - /* IDSEL 0x0F - PCI slot */ 21 - 0x7800 0x0 0x0 0x1 &ipic 17 0x8 22 - 0x7800 0x0 0x0 0x2 &ipic 18 0x8 23 - 0x7800 0x0 0x0 0x3 &ipic 17 0x8 24 - 0x7800 0x0 0x0 0x4 &ipic 18 0x8>; 25 - interrupt-parent = <&ipic>; 26 - interrupts = <66 0x8>; 27 - bus-range = <0x0 0x0>; 28 - ranges = <0x02000000 0x0 0x90000000 0x90000000 0x0 0x10000000 29 - 0x42000000 0x0 0x80000000 0x80000000 0x0 0x10000000 30 - 0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>; 31 - clock-frequency = <66666666>; 32 - #interrupt-cells = <1>; 33 - #size-cells = <2>; 34 - #address-cells = <3>; 35 - reg = <0xe0008500 0x100 /* internal registers */ 36 - 0xe0008300 0x8>; /* config space access registers */ 37 - compatible = "fsl,mpc8349-pci"; 38 - device_type = "pci"; 39 - };
-59
Documentation/devicetree/bindings/pci/aardvark-pci.txt
··· 1 - Aardvark PCIe controller 2 - 3 - This PCIe controller is used on the Marvell Armada 3700 ARM64 SoC. 4 - 5 - The Device Tree node describing an Aardvark PCIe controller must 6 - contain the following properties: 7 - 8 - - compatible: Should be "marvell,armada-3700-pcie" 9 - - reg: range of registers for the PCIe controller 10 - - interrupts: the interrupt line of the PCIe controller 11 - - #address-cells: set to <3> 12 - - #size-cells: set to <2> 13 - - device_type: set to "pci" 14 - - ranges: ranges for the PCI memory and I/O regions 15 - - #interrupt-cells: set to <1> 16 - - msi-controller: indicates that the PCIe controller can itself 17 - handle MSI interrupts 18 - - msi-parent: pointer to the MSI controller to be used 19 - - interrupt-map-mask and interrupt-map: standard PCI properties to 20 - define the mapping of the PCIe interface to interrupt numbers. 21 - - bus-range: PCI bus numbers covered 22 - - phys: the PCIe PHY handle 23 - - max-link-speed: see pci.txt 24 - - reset-gpios: see pci.txt 25 - 26 - In addition, the Device Tree describing an Aardvark PCIe controller 27 - must include a sub-node that describes the legacy interrupt controller 28 - built into the PCIe controller. This sub-node must have the following 29 - properties: 30 - 31 - - interrupt-controller 32 - - #interrupt-cells: set to <1> 33 - 34 - Example: 35 - 36 - pcie0: pcie@d0070000 { 37 - compatible = "marvell,armada-3700-pcie"; 38 - device_type = "pci"; 39 - reg = <0 0xd0070000 0 0x20000>; 40 - #address-cells = <3>; 41 - #size-cells = <2>; 42 - bus-range = <0x00 0xff>; 43 - interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>; 44 - #interrupt-cells = <1>; 45 - msi-controller; 46 - msi-parent = <&pcie0>; 47 - ranges = <0x82000000 0 0xe8000000 0 0xe8000000 0 0x1000000 /* Port 0 MEM */ 48 - 0x81000000 0 0xe9000000 0 0xe9000000 0 0x10000>; /* Port 0 IO*/ 49 - interrupt-map-mask = <0 0 0 7>; 50 - interrupt-map = <0 0 0 1 &pcie_intc 0>, 51 - <0 0 0 2 &pcie_intc 1>, 52 - <0 0 0 3 &pcie_intc 2>, 53 - <0 0 0 4 &pcie_intc 3>; 54 - phys = <&comphy1 0>; 55 - pcie_intc: interrupt-controller { 56 - interrupt-controller; 57 - #interrupt-cells = <1>; 58 - }; 59 - };
+71
Documentation/devicetree/bindings/pci/amazon,al-alpine-v3-pcie.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/pci/amazon,al-alpine-v3-pcie.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Amazon Annapurna Labs Alpine v3 PCIe Host Bridge 8 + 9 + maintainers: 10 + - Jonathan Chocron <jonnyc@amazon.com> 11 + 12 + description: 13 + Amazon's Annapurna Labs PCIe Host Controller is based on the Synopsys 14 + DesignWare PCI controller. 15 + 16 + allOf: 17 + - $ref: snps,dw-pcie.yaml# 18 + 19 + properties: 20 + compatible: 21 + enum: 22 + - amazon,al-alpine-v2-pcie 23 + - amazon,al-alpine-v3-pcie 24 + 25 + reg: 26 + items: 27 + - description: PCIe ECAM space 28 + - description: AL proprietary registers 29 + - description: Designware PCIe registers 30 + 31 + reg-names: 32 + items: 33 + - const: config 34 + - const: controller 35 + - const: dbi 36 + 37 + interrupts: 38 + maxItems: 1 39 + 40 + unevaluatedProperties: false 41 + 42 + required: 43 + - compatible 44 + - reg 45 + - reg-names 46 + 47 + examples: 48 + - | 49 + #include <dt-bindings/interrupt-controller/arm-gic.h> 50 + 51 + bus { 52 + #address-cells = <2>; 53 + #size-cells = <2>; 54 + 55 + pcie@fb600000 { 56 + compatible = "amazon,al-alpine-v3-pcie"; 57 + reg = <0x0 0xfb600000 0x0 0x00100000 58 + 0x0 0xfd800000 0x0 0x00010000 59 + 0x0 0xfd810000 0x0 0x00001000>; 60 + reg-names = "config", "controller", "dbi"; 61 + bus-range = <0 255>; 62 + device_type = "pci"; 63 + #address-cells = <3>; 64 + #size-cells = <2>; 65 + #interrupt-cells = <1>; 66 + interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>; 67 + interrupt-map-mask = <0x00 0 0 7>; 68 + interrupt-map = <0x0000 0 0 1 &gic GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>; /* INTa */ 69 + ranges = <0x02000000 0x0 0xc0010000 0x0 0xc0010000 0x0 0x07ff0000>; 70 + }; 71 + };
+84
Documentation/devicetree/bindings/pci/apm,xgene-pcie.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/pci/apm,xgene-pcie.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: AppliedMicro X-Gene PCIe interface 8 + 9 + maintainers: 10 + - Toan Le <toan@os.amperecomputing.com> 11 + 12 + allOf: 13 + - $ref: /schemas/pci/pci-host-bridge.yaml# 14 + 15 + properties: 16 + compatible: 17 + oneOf: 18 + - items: 19 + - const: apm,xgene-storm-pcie 20 + - const: apm,xgene-pcie 21 + - items: 22 + - const: apm,xgene-pcie 23 + 24 + reg: 25 + items: 26 + - description: Controller configuration registers 27 + - description: PCI configuration space registers 28 + 29 + reg-names: 30 + items: 31 + - const: csr 32 + - const: cfg 33 + 34 + clocks: 35 + maxItems: 1 36 + 37 + clock-names: 38 + items: 39 + - const: pcie 40 + 41 + dma-coherent: true 42 + 43 + msi-parent: 44 + maxItems: 1 45 + 46 + required: 47 + - compatible 48 + - reg 49 + - reg-names 50 + - '#interrupt-cells' 51 + - interrupt-map-mask 52 + - interrupt-map 53 + - clocks 54 + 55 + unevaluatedProperties: false 56 + 57 + examples: 58 + - | 59 + bus { 60 + #address-cells = <2>; 61 + #size-cells = <2>; 62 + 63 + pcie@1f2b0000 { 64 + compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie"; 65 + device_type = "pci"; 66 + #interrupt-cells = <1>; 67 + #size-cells = <2>; 68 + #address-cells = <3>; 69 + reg = <0x00 0x1f2b0000 0x0 0x00010000>, /* Controller registers */ 70 + <0xe0 0xd0000000 0x0 0x00040000>; /* PCI config space */ 71 + reg-names = "csr", "cfg"; 72 + ranges = <0x01000000 0x00 0x00000000 0xe0 0x10000000 0x00 0x00010000>, /* io */ 73 + <0x02000000 0x00 0x80000000 0xe1 0x80000000 0x00 0x80000000>; /* mem */ 74 + dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000>, 75 + <0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>; 76 + interrupt-map-mask = <0x0 0x0 0x0 0x7>; 77 + interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xc2 0x1>, 78 + <0x0 0x0 0x0 0x2 &gic 0x0 0xc3 0x1>, 79 + <0x0 0x0 0x0 0x3 &gic 0x0 0xc4 0x1>, 80 + <0x0 0x0 0x0 0x4 &gic 0x0 0xc5 0x1>; 81 + dma-coherent; 82 + clocks = <&pcie0clk 0>; 83 + }; 84 + };
-50
Documentation/devicetree/bindings/pci/axis,artpec6-pcie.txt
··· 1 - * Axis ARTPEC-6 PCIe interface 2 - 3 - This PCIe host controller is based on the Synopsys DesignWare PCIe IP 4 - and thus inherits all the common properties defined in snps,dw-pcie.yaml. 5 - 6 - Required properties: 7 - - compatible: "axis,artpec6-pcie", "snps,dw-pcie" for ARTPEC-6 in RC mode; 8 - "axis,artpec6-pcie-ep", "snps,dw-pcie" for ARTPEC-6 in EP mode; 9 - "axis,artpec7-pcie", "snps,dw-pcie" for ARTPEC-7 in RC mode; 10 - "axis,artpec7-pcie-ep", "snps,dw-pcie" for ARTPEC-7 in EP mode; 11 - - reg: base addresses and lengths of the PCIe controller (DBI), 12 - the PHY controller, and configuration address space. 13 - - reg-names: Must include the following entries: 14 - - "dbi" 15 - - "phy" 16 - - "config" 17 - - interrupts: A list of interrupt outputs of the controller. Must contain an 18 - entry for each entry in the interrupt-names property. 19 - - interrupt-names: Must include the following entries: 20 - - "msi": The interrupt that is asserted when an MSI is received 21 - - axis,syscon-pcie: A phandle pointing to the ARTPEC-6 system controller, 22 - used to enable and control the Synopsys IP. 23 - 24 - Example: 25 - 26 - pcie@f8050000 { 27 - compatible = "axis,artpec6-pcie", "snps,dw-pcie"; 28 - reg = <0xf8050000 0x2000 29 - 0xf8040000 0x1000 30 - 0xc0000000 0x2000>; 31 - reg-names = "dbi", "phy", "config"; 32 - #address-cells = <3>; 33 - #size-cells = <2>; 34 - device_type = "pci"; 35 - /* downstream I/O */ 36 - ranges = <0x81000000 0 0 0xc0002000 0 0x00010000 37 - /* non-prefetchable memory */ 38 - 0x82000000 0 0xc0012000 0xc0012000 0 0x1ffee000>; 39 - num-lanes = <2>; 40 - bus-range = <0x00 0xff>; 41 - interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>; 42 - interrupt-names = "msi"; 43 - #interrupt-cells = <1>; 44 - interrupt-map-mask = <0 0 0 0x7>; 45 - interrupt-map = <0 0 0 1 &intc GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>, 46 - <0 0 0 2 &intc GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>, 47 - <0 0 0 3 &intc GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>, 48 - <0 0 0 4 &intc GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>; 49 - axis,syscon-pcie = <&syscon>; 50 - };
+118
Documentation/devicetree/bindings/pci/axis,artpec6-pcie.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + # Copyright 2025 Axis AB 3 + %YAML 1.2 4 + --- 5 + $id: http://devicetree.org/schemas/pci/axis,artpec6-pcie.yaml# 6 + $schema: http://devicetree.org/meta-schemas/core.yaml# 7 + 8 + title: Axis ARTPEC-6 PCIe host controller 9 + 10 + maintainers: 11 + - Jesper Nilsson <jesper.nilsson@axis.com> 12 + 13 + description: 14 + This PCIe host controller is based on the Synopsys DesignWare PCIe IP. 15 + 16 + select: 17 + properties: 18 + compatible: 19 + contains: 20 + enum: 21 + - axis,artpec6-pcie 22 + - axis,artpec6-pcie-ep 23 + - axis,artpec7-pcie 24 + - axis,artpec7-pcie-ep 25 + required: 26 + - compatible 27 + 28 + properties: 29 + compatible: 30 + items: 31 + - enum: 32 + - axis,artpec6-pcie 33 + - axis,artpec6-pcie-ep 34 + - axis,artpec7-pcie 35 + - axis,artpec7-pcie-ep 36 + - const: snps,dw-pcie 37 + 38 + reg: 39 + minItems: 3 40 + maxItems: 4 41 + 42 + reg-names: 43 + minItems: 3 44 + maxItems: 4 45 + 46 + interrupts: 47 + maxItems: 1 48 + 49 + interrupt-names: 50 + items: 51 + - const: msi 52 + 53 + axis,syscon-pcie: 54 + $ref: /schemas/types.yaml#/definitions/phandle 55 + description: 56 + System controller phandle used to enable and control the Synopsys IP. 57 + 58 + required: 59 + - compatible 60 + - reg 61 + - reg-names 62 + - interrupts 63 + - interrupt-names 64 + - axis,syscon-pcie 65 + 66 + oneOf: 67 + - $ref: snps,dw-pcie.yaml# 68 + properties: 69 + reg: 70 + maxItems: 3 71 + 72 + reg-names: 73 + items: 74 + - const: dbi 75 + - const: phy 76 + - const: config 77 + 78 + - $ref: snps,dw-pcie-ep.yaml# 79 + properties: 80 + reg: 81 + minItems: 4 82 + 83 + reg-names: 84 + items: 85 + - const: dbi 86 + - const: dbi2 87 + - const: phy 88 + - const: addr_space 89 + 90 + unevaluatedProperties: false 91 + 92 + examples: 93 + - | 94 + #include <dt-bindings/interrupt-controller/arm-gic.h> 95 + 96 + pcie@f8050000 { 97 + compatible = "axis,artpec6-pcie", "snps,dw-pcie"; 98 + device_type = "pci"; 99 + reg = <0xf8050000 0x2000 100 + 0xf8040000 0x1000 101 + 0xc0000000 0x2000>; 102 + reg-names = "dbi", "phy", "config"; 103 + #address-cells = <3>; 104 + #size-cells = <2>; 105 + ranges = <0x81000000 0 0 0xc0002000 0 0x00010000>, 106 + <0x82000000 0 0xc0012000 0xc0012000 0 0x1ffee000>; 107 + num-lanes = <2>; 108 + bus-range = <0x00 0xff>; 109 + interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>; 110 + interrupt-names = "msi"; 111 + #interrupt-cells = <1>; 112 + interrupt-map-mask = <0 0 0 0x7>; 113 + interrupt-map = <0 0 0 1 &intc GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>, 114 + <0 0 0 2 &intc GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>, 115 + <0 0 0 3 &intc GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>, 116 + <0 0 0 4 &intc GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>; 117 + axis,syscon-pcie = <&syscon>; 118 + };
+4
Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml
··· 107 107 - const: bridge 108 108 - const: swinit 109 109 110 + num-lanes: 111 + default: 1 112 + maximum: 4 113 + 110 114 required: 111 115 - compatible 112 116 - reg
+99
Documentation/devicetree/bindings/pci/marvell,armada-3700-pcie.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/pci/marvell,armada-3700-pcie.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Marvell Armada 3700 (Aardvark) PCIe Controller 8 + 9 + maintainers: 10 + - Thomas Petazzoni <thomas.petazzoni@bootlin.com> 11 + - Pali Rohár <pali@kernel.org> 12 + 13 + allOf: 14 + - $ref: /schemas/pci/pci-host-bridge.yaml# 15 + 16 + properties: 17 + compatible: 18 + const: marvell,armada-3700-pcie 19 + 20 + reg: 21 + maxItems: 1 22 + 23 + clocks: 24 + maxItems: 1 25 + 26 + interrupts: 27 + maxItems: 1 28 + 29 + msi-controller: true 30 + 31 + msi-parent: 32 + maxItems: 1 33 + 34 + phys: 35 + maxItems: 1 36 + 37 + reset-gpios: 38 + description: PCIe reset GPIO signals. 39 + 40 + interrupt-controller: 41 + type: object 42 + additionalProperties: false 43 + 44 + properties: 45 + interrupt-controller: true 46 + 47 + '#interrupt-cells': 48 + const: 1 49 + 50 + required: 51 + - interrupt-controller 52 + - '#interrupt-cells' 53 + 54 + required: 55 + - compatible 56 + - reg 57 + - interrupts 58 + - '#interrupt-cells' 59 + 60 + unevaluatedProperties: false 61 + 62 + examples: 63 + - | 64 + #include <dt-bindings/interrupt-controller/arm-gic.h> 65 + #include <dt-bindings/gpio/gpio.h> 66 + 67 + bus { 68 + #address-cells = <2>; 69 + #size-cells = <2>; 70 + 71 + pcie@d0070000 { 72 + compatible = "marvell,armada-3700-pcie"; 73 + device_type = "pci"; 74 + reg = <0 0xd0070000 0 0x20000>; 75 + #address-cells = <3>; 76 + #size-cells = <2>; 77 + bus-range = <0x00 0xff>; 78 + interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>; 79 + msi-controller; 80 + msi-parent = <&pcie0>; 81 + ranges = <0x82000000 0 0xe8000000 0 0xe8000000 0 0x1000000>, 82 + <0x81000000 0 0xe9000000 0 0xe9000000 0 0x10000>; 83 + 84 + #interrupt-cells = <1>; 85 + interrupt-map-mask = <0 0 0 7>; 86 + interrupt-map = <0 0 0 1 &pcie_intc 0>, 87 + <0 0 0 2 &pcie_intc 1>, 88 + <0 0 0 3 &pcie_intc 2>, 89 + <0 0 0 4 &pcie_intc 3>; 90 + phys = <&comphy1 0>; 91 + max-link-speed = <2>; 92 + reset-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>; 93 + 94 + pcie_intc: interrupt-controller { 95 + interrupt-controller; 96 + #interrupt-cells = <1>; 97 + }; 98 + }; 99 + };
+1 -1
Documentation/devicetree/bindings/pci/pci-ep.yaml
··· 51 51 52 52 max-link-speed: 53 53 $ref: /schemas/types.yaml#/definitions/uint32 54 - enum: [ 1, 2, 3, 4 ] 54 + enum: [ 1, 2, 3, 4, 5, 6 ] 55 55 56 56 msi-map: 57 57 description: |
-46
Documentation/devicetree/bindings/pci/pcie-al.txt
··· 1 - * Amazon Annapurna Labs PCIe host bridge 2 - 3 - Amazon's Annapurna Labs PCIe Host Controller is based on the Synopsys DesignWare 4 - PCI core. It inherits common properties defined in 5 - Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml. 6 - 7 - Properties of the host controller node that differ from it are: 8 - 9 - - compatible: 10 - Usage: required 11 - Value type: <stringlist> 12 - Definition: Value should contain 13 - - "amazon,al-alpine-v2-pcie" for alpine_v2 14 - - "amazon,al-alpine-v3-pcie" for alpine_v3 15 - 16 - - reg: 17 - Usage: required 18 - Value type: <prop-encoded-array> 19 - Definition: Register ranges as listed in the reg-names property 20 - 21 - - reg-names: 22 - Usage: required 23 - Value type: <stringlist> 24 - Definition: Must include the following entries 25 - - "config" PCIe ECAM space 26 - - "controller" AL proprietary registers 27 - - "dbi" Designware PCIe registers 28 - 29 - Example: 30 - 31 - pcie-external0: pcie@fb600000 { 32 - compatible = "amazon,al-alpine-v3-pcie"; 33 - reg = <0x0 0xfb600000 0x0 0x00100000 34 - 0x0 0xfd800000 0x0 0x00010000 35 - 0x0 0xfd810000 0x0 0x00001000>; 36 - reg-names = "config", "controller", "dbi"; 37 - bus-range = <0 255>; 38 - device_type = "pci"; 39 - #address-cells = <3>; 40 - #size-cells = <2>; 41 - #interrupt-cells = <1>; 42 - interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>; 43 - interrupt-map-mask = <0x00 0 0 7>; 44 - interrupt-map = <0x0000 0 0 1 &gic GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>; /* INTa */ 45 - ranges = <0x02000000 0x0 0xc0010000 0x0 0xc0010000 0x0 0x07ff0000>; 46 - };
+30 -2
Documentation/devicetree/bindings/pci/qcom,pcie-common.yaml
··· 51 51 52 52 phys: 53 53 maxItems: 1 54 + deprecated: true 55 + description: 56 + This property is deprecated, instead of referencing this property from 57 + the host bridge node, use the property from the PCIe root port node. 54 58 55 59 phy-names: 56 60 items: 57 61 - const: pciephy 62 + deprecated: true 63 + description: 64 + Phandle to the register map node. This property is deprecated, and not 65 + required to add in the root port also, as the root port has only one phy. 58 66 59 67 power-domains: 60 68 maxItems: 1 ··· 79 71 maxItems: 12 80 72 81 73 perst-gpios: 82 - description: GPIO controlled connection to PERST# signal 74 + description: GPIO controlled connection to PERST# signal. This property is 75 + deprecated, instead of referencing this property from the host bridge node, 76 + use the reset-gpios property from the root port node. 83 77 maxItems: 1 78 + deprecated: true 84 79 85 80 wake-gpios: 86 - description: GPIO controlled connection to WAKE# signal 81 + description: GPIO controlled connection to WAKE# signal. This property is 82 + deprecated, instead of referencing this property from the host bridge node, 83 + use the property from the PCIe root port node. 87 84 maxItems: 1 85 + deprecated: true 88 86 89 87 vddpe-3v3-supply: 90 88 description: PCIe endpoint power supply ··· 98 84 operating-points-v2: true 99 85 opp-table: 100 86 type: object 87 + 88 + patternProperties: 89 + "^pcie@": 90 + type: object 91 + $ref: /schemas/pci/pci-pci-bridge.yaml# 92 + 93 + properties: 94 + reg: 95 + maxItems: 1 96 + 97 + phys: 98 + maxItems: 1 99 + 100 + unevaluatedProperties: false 101 101 102 102 required: 103 103 - reg
+122
Documentation/devicetree/bindings/pci/qcom,pcie-sa8255p.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/pci/qcom,pcie-sa8255p.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Qualcomm SA8255p based firmware managed and ECAM compliant PCIe Root Complex 8 + 9 + maintainers: 10 + - Bjorn Andersson <andersson@kernel.org> 11 + - Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> 12 + 13 + description: 14 + Qualcomm SA8255p SoC PCIe root complex controller is based on the Synopsys 15 + DesignWare PCIe IP which is managed by firmware, and configured in ECAM mode. 16 + 17 + properties: 18 + compatible: 19 + const: qcom,pcie-sa8255p 20 + 21 + reg: 22 + description: 23 + The base address and size of the ECAM area for accessing PCI 24 + Configuration Space, as accessed from the parent bus. The base 25 + address corresponds to the first bus in the "bus-range" property. If 26 + no "bus-range" is specified, this will be bus 0 (the default). 27 + maxItems: 1 28 + 29 + ranges: 30 + description: 31 + As described in IEEE Std 1275-1994, but must provide at least a 32 + definition of non-prefetchable memory. One or both of prefetchable Memory 33 + may also be provided. 34 + minItems: 1 35 + maxItems: 2 36 + 37 + interrupts: 38 + minItems: 8 39 + maxItems: 8 40 + 41 + interrupt-names: 42 + items: 43 + - const: msi0 44 + - const: msi1 45 + - const: msi2 46 + - const: msi3 47 + - const: msi4 48 + - const: msi5 49 + - const: msi6 50 + - const: msi7 51 + 52 + power-domains: 53 + maxItems: 1 54 + 55 + dma-coherent: true 56 + iommu-map: true 57 + 58 + required: 59 + - compatible 60 + - reg 61 + - ranges 62 + - power-domains 63 + - interrupts 64 + - interrupt-names 65 + 66 + allOf: 67 + - $ref: /schemas/pci/pci-host-bridge.yaml# 68 + 69 + unevaluatedProperties: false 70 + 71 + examples: 72 + - | 73 + #include <dt-bindings/interrupt-controller/arm-gic.h> 74 + 75 + soc { 76 + #address-cells = <2>; 77 + #size-cells = <2>; 78 + 79 + pci@1c00000 { 80 + compatible = "qcom,pcie-sa8255p"; 81 + reg = <0x4 0x00000000 0 0x10000000>; 82 + device_type = "pci"; 83 + #address-cells = <3>; 84 + #size-cells = <2>; 85 + ranges = <0x02000000 0x0 0x40100000 0x0 0x40100000 0x0 0x1ff00000>, 86 + <0x43000000 0x4 0x10100000 0x4 0x10100000 0x0 0x40000000>; 87 + bus-range = <0x00 0xff>; 88 + dma-coherent; 89 + linux,pci-domain = <0>; 90 + power-domains = <&scmi5_pd 0>; 91 + iommu-map = <0x0 &pcie_smmu 0x0000 0x1>, 92 + <0x100 &pcie_smmu 0x0001 0x1>; 93 + interrupt-parent = <&intc>; 94 + interrupts = <GIC_SPI 307 IRQ_TYPE_LEVEL_HIGH>, 95 + <GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH>, 96 + <GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH>, 97 + <GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH>, 98 + <GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH>, 99 + <GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH>, 100 + <GIC_SPI 374 IRQ_TYPE_LEVEL_HIGH>, 101 + <GIC_SPI 375 IRQ_TYPE_LEVEL_HIGH>; 102 + interrupt-names = "msi0", "msi1", "msi2", "msi3", 103 + "msi4", "msi5", "msi6", "msi7"; 104 + 105 + #interrupt-cells = <1>; 106 + interrupt-map-mask = <0 0 0 0x7>; 107 + interrupt-map = <0 0 0 1 &intc GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>, 108 + <0 0 0 2 &intc GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>, 109 + <0 0 0 3 &intc GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>, 110 + <0 0 0 4 &intc GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>; 111 + 112 + pcie@0 { 113 + device_type = "pci"; 114 + reg = <0x0 0x0 0x0 0x0 0x0>; 115 + bus-range = <0x01 0xff>; 116 + 117 + #address-cells = <3>; 118 + #size-cells = <2>; 119 + ranges; 120 + }; 121 + }; 122 + };
+14 -4
Documentation/devicetree/bindings/pci/qcom,pcie-sa8775p.yaml
··· 16 16 17 17 properties: 18 18 compatible: 19 - const: qcom,pcie-sa8775p 19 + oneOf: 20 + - const: qcom,pcie-sa8775p 21 + - items: 22 + - enum: 23 + - qcom,pcie-qcs8300 24 + - const: qcom,pcie-sa8775p 20 25 21 26 reg: 22 27 minItems: 6 ··· 66 61 - const: global 67 62 68 63 resets: 69 - maxItems: 1 64 + items: 65 + - description: PCIe controller reset 66 + - description: PCIe link down reset 70 67 71 68 reset-names: 72 69 items: 73 70 - const: pci 71 + - const: link_down 74 72 75 73 required: 76 74 - interconnects ··· 169 161 170 162 power-domains = <&gcc PCIE_0_GDSC>; 171 163 172 - resets = <&gcc GCC_PCIE_0_BCR>; 173 - reset-names = "pci"; 164 + resets = <&gcc GCC_PCIE_0_BCR>, 165 + <&gcc GCC_PCIE_0_LINK_DOWN_BCR>; 166 + reset-names = "pci", 167 + "link_down"; 174 168 175 169 perst-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>; 176 170 wake-gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>;
+12 -4
Documentation/devicetree/bindings/pci/qcom,pcie-sc7280.yaml
··· 165 165 iommu-map = <0x0 &apps_smmu 0x1c80 0x1>, 166 166 <0x100 &apps_smmu 0x1c81 0x1>; 167 167 168 - phys = <&pcie1_phy>; 169 - phy-names = "pciephy"; 170 - 171 168 pinctrl-names = "default"; 172 169 pinctrl-0 = <&pcie1_clkreq_n>; 173 170 ··· 173 176 resets = <&gcc GCC_PCIE_1_BCR>; 174 177 reset-names = "pci"; 175 178 176 - perst-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>; 177 179 vddpe-3v3-supply = <&pp3300_ssd>; 180 + pcie1_port0: pcie@0 { 181 + device_type = "pci"; 182 + reg = <0x0 0x0 0x0 0x0 0x0>; 183 + bus-range = <0x01 0xff>; 184 + 185 + #address-cells = <3>; 186 + #size-cells = <2>; 187 + ranges; 188 + phys = <&pcie1_phy>; 189 + 190 + reset-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>; 191 + }; 178 192 }; 179 193 };
+4 -10
Documentation/devicetree/bindings/pci/qcom,pcie-sc8180x.yaml
··· 33 33 - const: mhi # MHI registers 34 34 35 35 clocks: 36 - minItems: 8 37 - maxItems: 8 36 + minItems: 6 37 + maxItems: 6 38 38 39 39 clock-names: 40 40 items: ··· 44 44 - const: bus_master # Master AXI clock 45 45 - const: bus_slave # Slave AXI clock 46 46 - const: slave_q2a # Slave Q2A clock 47 - - const: ref # REFERENCE clock 48 - - const: tbu # PCIe TBU clock 49 47 50 48 interrupts: 51 49 minItems: 8 ··· 115 117 <&gcc GCC_PCIE_0_CFG_AHB_CLK>, 116 118 <&gcc GCC_PCIE_0_MSTR_AXI_CLK>, 117 119 <&gcc GCC_PCIE_0_SLV_AXI_CLK>, 118 - <&gcc GCC_PCIE_0_SLV_Q2A_AXI_CLK>, 119 - <&gcc GCC_PCIE_0_CLKREF_CLK>, 120 - <&gcc GCC_AGGRE_NOC_PCIE_TBU_CLK>; 120 + <&gcc GCC_PCIE_0_SLV_Q2A_AXI_CLK>; 121 121 clock-names = "pipe", 122 122 "aux", 123 123 "cfg", 124 124 "bus_master", 125 125 "bus_slave", 126 - "slave_q2a", 127 - "ref", 128 - "tbu"; 126 + "slave_q2a"; 129 127 130 128 dma-coherent; 131 129
+10 -11
Documentation/devicetree/bindings/pci/qcom,pcie-sm8150.yaml
··· 16 16 17 17 properties: 18 18 compatible: 19 - const: qcom,pcie-sm8150 19 + oneOf: 20 + - const: qcom,pcie-sm8150 21 + - items: 22 + - enum: 23 + - qcom,pcie-qcs615 24 + - const: qcom,pcie-sm8150 20 25 21 26 reg: 22 27 minItems: 5 ··· 38 33 - const: mhi # MHI registers 39 34 40 35 clocks: 41 - minItems: 8 42 - maxItems: 8 36 + minItems: 6 37 + maxItems: 6 43 38 44 39 clock-names: 45 40 items: ··· 49 44 - const: bus_master # Master AXI clock 50 45 - const: bus_slave # Slave AXI clock 51 46 - const: slave_q2a # Slave Q2A clock 52 - - const: tbu # PCIe TBU clock 53 - - const: ref # REFERENCE clock 54 47 55 48 interrupts: 56 49 minItems: 8 ··· 114 111 <&gcc GCC_PCIE_0_CFG_AHB_CLK>, 115 112 <&gcc GCC_PCIE_0_MSTR_AXI_CLK>, 116 113 <&gcc GCC_PCIE_0_SLV_AXI_CLK>, 117 - <&gcc GCC_PCIE_0_SLV_Q2A_AXI_CLK>, 118 - <&gcc GCC_AGGRE_NOC_PCIE_TBU_CLK>, 119 - <&rpmhcc RPMH_CXO_CLK>; 114 + <&gcc GCC_PCIE_0_SLV_Q2A_AXI_CLK>; 120 115 clock-names = "pipe", 121 116 "aux", 122 117 "cfg", 123 118 "bus_master", 124 119 "bus_slave", 125 - "slave_q2a", 126 - "tbu", 127 - "ref"; 120 + "slave_q2a"; 128 121 129 122 interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>, 130 123 <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+1 -1
Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
··· 108 108 - description: See native 'dbi' CSR region for details. 109 109 enum: [ ctrl ] 110 110 - description: See native 'elbi/app' CSR region for details. 111 - enum: [ apb, mgmt, link, ulreg, appl ] 111 + enum: [ apb, mgmt, link, ulreg, appl, controller ] 112 112 - description: See native 'atu' CSR region for details. 113 113 enum: [ atu_dma ] 114 114 - description: Syscon-related CSR regions.
+122
Documentation/devicetree/bindings/pci/sophgo,sg2044-pcie.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/pci/sophgo,sg2044-pcie.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: DesignWare based PCIe Root Complex controller on Sophgo SoCs 8 + 9 + maintainers: 10 + - Inochi Amaoto <inochiama@gmail.com> 11 + 12 + description: 13 + SG2044 SoC PCIe Root Complex controller is based on the Synopsys DesignWare 14 + PCIe IP and thus inherits all the common properties defined in 15 + snps,dw-pcie.yaml. 16 + 17 + allOf: 18 + - $ref: /schemas/pci/pci-host-bridge.yaml# 19 + - $ref: /schemas/pci/snps,dw-pcie.yaml# 20 + 21 + properties: 22 + compatible: 23 + const: sophgo,sg2044-pcie 24 + 25 + reg: 26 + items: 27 + - description: Data Bus Interface (DBI) registers 28 + - description: iATU registers 29 + - description: Config registers 30 + - description: Sophgo designed configuration registers 31 + 32 + reg-names: 33 + items: 34 + - const: dbi 35 + - const: atu 36 + - const: config 37 + - const: app 38 + 39 + clocks: 40 + items: 41 + - description: core clk 42 + 43 + clock-names: 44 + items: 45 + - const: core 46 + 47 + interrupt-controller: 48 + description: Interrupt controller node for handling legacy PCI interrupts. 49 + type: object 50 + 51 + properties: 52 + "#address-cells": 53 + const: 0 54 + 55 + "#interrupt-cells": 56 + const: 1 57 + 58 + interrupt-controller: true 59 + 60 + interrupts: 61 + items: 62 + - description: combined legacy interrupt 63 + 64 + required: 65 + - "#address-cells" 66 + - "#interrupt-cells" 67 + - interrupt-controller 68 + - interrupts 69 + 70 + additionalProperties: false 71 + 72 + msi-parent: true 73 + 74 + ranges: 75 + maxItems: 5 76 + 77 + required: 78 + - compatible 79 + - reg 80 + - clocks 81 + 82 + unevaluatedProperties: false 83 + 84 + examples: 85 + - | 86 + #include <dt-bindings/interrupt-controller/irq.h> 87 + 88 + soc { 89 + #address-cells = <2>; 90 + #size-cells = <2>; 91 + 92 + pcie@6c00400000 { 93 + compatible = "sophgo,sg2044-pcie"; 94 + reg = <0x6c 0x00400000 0x0 0x00001000>, 95 + <0x6c 0x00700000 0x0 0x00004000>, 96 + <0x40 0x00000000 0x0 0x00001000>, 97 + <0x6c 0x00780c00 0x0 0x00000400>; 98 + reg-names = "dbi", "atu", "config", "app"; 99 + #address-cells = <3>; 100 + #size-cells = <2>; 101 + bus-range = <0x00 0xff>; 102 + clocks = <&clk 0>; 103 + clock-names = "core"; 104 + device_type = "pci"; 105 + linux,pci-domain = <0>; 106 + msi-parent = <&msi>; 107 + ranges = <0x01000000 0x0 0x00000000 0x40 0x10000000 0x0 0x00200000>, 108 + <0x42000000 0x0 0x00000000 0x0 0x00000000 0x0 0x04000000>, 109 + <0x02000000 0x0 0x04000000 0x0 0x04000000 0x0 0x04000000>, 110 + <0x43000000 0x42 0x00000000 0x42 0x00000000 0x2 0x00000000>, 111 + <0x03000000 0x41 0x00000000 0x41 0x00000000 0x1 0x00000000>; 112 + 113 + interrupt-controller { 114 + #address-cells = <0>; 115 + #interrupt-cells = <1>; 116 + interrupt-controller; 117 + interrupt-parent = <&intc>; 118 + interrupts = <64 IRQ_TYPE_LEVEL_HIGH>; 119 + }; 120 + }; 121 + }; 122 + ...
-14
Documentation/devicetree/bindings/pci/spear13xx-pcie.txt
··· 1 - SPEAr13XX PCIe DT detail: 2 - ================================ 3 - 4 - SPEAr13XX uses the Synopsys DesignWare PCIe controller and ST MiPHY as PHY 5 - controller. 6 - 7 - Required properties: 8 - - compatible : should be "st,spear1340-pcie", "snps,dw-pcie". 9 - - phys : phandle to PHY node associated with PCIe controller 10 - - phy-names : must be "pcie-phy" 11 - - All other definitions as per generic PCI bindings 12 - 13 - Optional properties: 14 - - st,pcie-is-gen1 indicates that forced gen1 initialization is needed.
+45
Documentation/devicetree/bindings/pci/st,spear1340-pcie.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/pci/st,spear1340-pcie.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: ST SPEAr1340 PCIe controller 8 + 9 + maintainers: 10 + - Pratyush Anand <pratyush.anand@gmail.com> 11 + 12 + description: 13 + SPEAr13XX uses the Synopsys DesignWare PCIe controller and ST MiPHY as PHY 14 + controller. 15 + 16 + select: 17 + properties: 18 + compatible: 19 + contains: 20 + const: st,spear1340-pcie 21 + required: 22 + - compatible 23 + 24 + properties: 25 + compatible: 26 + items: 27 + - const: st,spear1340-pcie 28 + - const: snps,dw-pcie 29 + 30 + phys: 31 + maxItems: 1 32 + 33 + st,pcie-is-gen1: 34 + type: boolean 35 + description: Indicates forced gen1 initialization is needed. 36 + 37 + required: 38 + - compatible 39 + - phys 40 + - phy-names 41 + 42 + allOf: 43 + - $ref: snps,dw-pcie.yaml# 44 + 45 + unevaluatedProperties: false
-50
Documentation/devicetree/bindings/pci/xgene-pci.txt
··· 1 - * AppliedMicro X-Gene PCIe interface 2 - 3 - Required properties: 4 - - device_type: set to "pci" 5 - - compatible: should contain "apm,xgene-pcie" to identify the core. 6 - - reg: A list of physical base address and length for each set of controller 7 - registers. Must contain an entry for each entry in the reg-names 8 - property. 9 - - reg-names: Must include the following entries: 10 - "csr": controller configuration registers. 11 - "cfg": PCIe configuration space registers. 12 - - #address-cells: set to <3> 13 - - #size-cells: set to <2> 14 - - ranges: ranges for the outbound memory, I/O regions. 15 - - dma-ranges: ranges for the inbound memory regions. 16 - - #interrupt-cells: set to <1> 17 - - interrupt-map-mask and interrupt-map: standard PCI properties 18 - to define the mapping of the PCIe interface to interrupt 19 - numbers. 20 - - clocks: from common clock binding: handle to pci clock. 21 - 22 - Optional properties: 23 - - status: Either "ok" or "disabled". 24 - - dma-coherent: Present if DMA operations are coherent 25 - 26 - Example: 27 - 28 - pcie0: pcie@1f2b0000 { 29 - status = "disabled"; 30 - device_type = "pci"; 31 - compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie"; 32 - #interrupt-cells = <1>; 33 - #size-cells = <2>; 34 - #address-cells = <3>; 35 - reg = < 0x00 0x1f2b0000 0x0 0x00010000 /* Controller registers */ 36 - 0xe0 0xd0000000 0x0 0x00040000>; /* PCI config space */ 37 - reg-names = "csr", "cfg"; 38 - ranges = <0x01000000 0x00 0x00000000 0xe0 0x10000000 0x00 0x00010000 /* io */ 39 - 0x02000000 0x00 0x80000000 0xe1 0x80000000 0x00 0x80000000>; /* mem */ 40 - dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000 41 - 0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>; 42 - interrupt-map-mask = <0x0 0x0 0x0 0x7>; 43 - interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xc2 0x1 44 - 0x0 0x0 0x0 0x2 &gic 0x0 0xc3 0x1 45 - 0x0 0x0 0x0 0x3 &gic 0x0 0xc4 0x1 46 - 0x0 0x0 0x0 0x4 &gic 0x0 0xc5 0x1>; 47 - dma-coherent; 48 - clocks = <&pcie0clk 0>; 49 - }; 50 -
+3 -4
MAINTAINERS
··· 5189 5189 5190 5190 BROADCOM STB PCIE DRIVER 5191 5191 M: Jim Quinlan <jim2101024@gmail.com> 5192 - M: Nicolas Saenz Julienne <nsaenz@kernel.org> 5193 5192 M: Florian Fainelli <florian.fainelli@broadcom.com> 5194 5193 R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com> 5195 5194 L: linux-pci@vger.kernel.org ··· 19207 19208 L: linux-pci@vger.kernel.org 19208 19209 L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) 19209 19210 S: Maintained 19210 - F: Documentation/devicetree/bindings/pci/aardvark-pci.txt 19211 + F: Documentation/devicetree/bindings/pci/marvell,armada-3700-pcie.yaml 19211 19212 F: drivers/pci/controller/pci-aardvark.c 19212 19213 19213 19214 PCI DRIVER FOR ALTERA PCIE IP ··· 19222 19223 L: linux-pci@vger.kernel.org 19223 19224 L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) 19224 19225 S: Maintained 19225 - F: Documentation/devicetree/bindings/pci/xgene-pci.txt 19226 + F: Documentation/devicetree/bindings/pci/apm,xgene-pcie.yaml 19226 19227 F: drivers/pci/controller/pci-xgene.c 19227 19228 19228 19229 PCI DRIVER FOR ARM VERSATILE PLATFORM ··· 19541 19542 M: Jonathan Chocron <jonnyc@amazon.com> 19542 19543 L: linux-pci@vger.kernel.org 19543 19544 S: Maintained 19544 - F: Documentation/devicetree/bindings/pci/pcie-al.txt 19545 + F: Documentation/devicetree/bindings/pci/amazon,al-alpine-v3-pcie.yaml 19545 19546 F: drivers/pci/controller/dwc/pcie-al.c 19546 19547 19547 19548 PCIE DRIVER FOR AMLOGIC MESON
+1 -1
drivers/gpu/vga/vga_switcheroo.c
··· 437 437 */ 438 438 bool vga_switcheroo_client_probe_defer(struct pci_dev *pdev) 439 439 { 440 - if ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { 440 + if (pci_is_display(pdev)) { 441 441 /* 442 442 * apple-gmux is needed on pre-retina MacBook Pro 443 443 * to probe the panel if pdev is the inactive GPU.
+1 -1
drivers/iommu/intel/iommu.c
··· 34 34 #define ROOT_SIZE VTD_PAGE_SIZE 35 35 #define CONTEXT_SIZE VTD_PAGE_SIZE 36 36 37 - #define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) 37 + #define IS_GFX_DEVICE(pdev) pci_is_display(pdev) 38 38 #define IS_USB_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_SERIAL_USB) 39 39 #define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA) 40 40 #define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e)
+83
drivers/misc/pci_endpoint_test.c
··· 37 37 #define COMMAND_READ BIT(3) 38 38 #define COMMAND_WRITE BIT(4) 39 39 #define COMMAND_COPY BIT(5) 40 + #define COMMAND_ENABLE_DOORBELL BIT(6) 41 + #define COMMAND_DISABLE_DOORBELL BIT(7) 40 42 41 43 #define PCI_ENDPOINT_TEST_STATUS 0x8 42 44 #define STATUS_READ_SUCCESS BIT(0) ··· 50 48 #define STATUS_IRQ_RAISED BIT(6) 51 49 #define STATUS_SRC_ADDR_INVALID BIT(7) 52 50 #define STATUS_DST_ADDR_INVALID BIT(8) 51 + #define STATUS_DOORBELL_SUCCESS BIT(9) 52 + #define STATUS_DOORBELL_ENABLE_SUCCESS BIT(10) 53 + #define STATUS_DOORBELL_ENABLE_FAIL BIT(11) 54 + #define STATUS_DOORBELL_DISABLE_SUCCESS BIT(12) 55 + #define STATUS_DOORBELL_DISABLE_FAIL BIT(13) 53 56 54 57 #define PCI_ENDPOINT_TEST_LOWER_SRC_ADDR 0x0c 55 58 #define PCI_ENDPOINT_TEST_UPPER_SRC_ADDR 0x10 ··· 69 62 #define PCI_ENDPOINT_TEST_IRQ_NUMBER 0x28 70 63 71 64 #define PCI_ENDPOINT_TEST_FLAGS 0x2c 65 + 72 66 #define FLAG_USE_DMA BIT(0) 73 67 74 68 #define PCI_ENDPOINT_TEST_CAPS 0x30 ··· 77 69 #define CAP_MSI BIT(1) 78 70 #define CAP_MSIX BIT(2) 79 71 #define CAP_INTX BIT(3) 72 + 73 + #define PCI_ENDPOINT_TEST_DB_BAR 0x34 74 + #define PCI_ENDPOINT_TEST_DB_OFFSET 0x38 75 + #define PCI_ENDPOINT_TEST_DB_DATA 0x3c 80 76 81 77 #define PCI_DEVICE_ID_TI_AM654 0xb00c 82 78 #define PCI_DEVICE_ID_TI_J7200 0xb00f ··· 112 100 BAR_3, 113 101 BAR_4, 114 102 BAR_5, 103 + NO_BAR = -1, 115 104 }; 116 105 117 106 struct pci_endpoint_test { ··· 854 841 return 0; 855 842 } 856 843 844 + static int pci_endpoint_test_doorbell(struct pci_endpoint_test *test) 845 + { 846 + struct pci_dev *pdev = test->pdev; 847 + struct device *dev = &pdev->dev; 848 + int irq_type = test->irq_type; 849 + enum pci_barno bar; 850 + u32 data, status; 851 + u32 addr; 852 + int left; 853 + 854 + if (irq_type < PCITEST_IRQ_TYPE_INTX || 855 + irq_type > PCITEST_IRQ_TYPE_MSIX) { 856 + dev_err(dev, "Invalid IRQ type\n"); 857 + return -EINVAL; 858 + } 859 + 860 + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type); 861 + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1); 862 + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, 863 + COMMAND_ENABLE_DOORBELL); 864 + 865 + left = wait_for_completion_timeout(&test->irq_raised, msecs_to_jiffies(1000)); 866 + 867 + status = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS); 868 + if (!left || (status & STATUS_DOORBELL_ENABLE_FAIL)) { 869 + dev_err(dev, "Failed to enable doorbell\n"); 870 + return -EINVAL; 871 + } 872 + 873 + data = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_DB_DATA); 874 + addr = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_DB_OFFSET); 875 + bar = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_DB_BAR); 876 + 877 + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type); 878 + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1); 879 + 880 + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_STATUS, 0); 881 + 882 + bar = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_DB_BAR); 883 + 884 + writel(data, test->bar[bar] + addr); 885 + 886 + left = wait_for_completion_timeout(&test->irq_raised, msecs_to_jiffies(1000)); 887 + 888 + status = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS); 889 + 890 + if (!left || !(status & STATUS_DOORBELL_SUCCESS)) 891 + dev_err(dev, "Failed to trigger doorbell in endpoint\n"); 892 + 893 + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, 894 + COMMAND_DISABLE_DOORBELL); 895 + 896 + wait_for_completion_timeout(&test->irq_raised, msecs_to_jiffies(1000)); 897 + 898 + status |= pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS); 899 + 900 + if (status & STATUS_DOORBELL_DISABLE_FAIL) { 901 + dev_err(dev, "Failed to disable doorbell\n"); 902 + return -EINVAL; 903 + } 904 + 905 + if (!(status & STATUS_DOORBELL_SUCCESS)) 906 + return -EINVAL; 907 + 908 + return 0; 909 + } 910 + 857 911 static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd, 858 912 unsigned long arg) 859 913 { ··· 970 890 break; 971 891 case PCITEST_CLEAR_IRQ: 972 892 ret = pci_endpoint_test_clear_irq(test); 893 + break; 894 + case PCITEST_DOORBELL: 895 + ret = pci_endpoint_test_doorbell(test); 973 896 break; 974 897 } 975 898
+1 -4
drivers/pci/bus.c
··· 341 341 { 342 342 struct device_node *dn = dev->dev.of_node; 343 343 struct platform_device *pdev; 344 - int retval; 345 344 346 345 /* 347 346 * Can not put in pci_device_add yet because resources ··· 371 372 if (!dn || of_device_is_available(dn)) 372 373 pci_dev_allow_binding(dev); 373 374 374 - retval = device_attach(&dev->dev); 375 - if (retval < 0 && retval != -EPROBE_DEFER) 376 - pci_warn(dev, "device attach failed (%d)\n", retval); 375 + device_initial_probe(&dev->dev); 377 376 378 377 pci_dev_assign_added(dev); 379 378 }
+11
drivers/pci/controller/Kconfig
··· 13 13 depends on OF 14 14 depends on PCI_MSI 15 15 select PCI_BRIDGE_EMUL 16 + select IRQ_MSI_LIB 16 17 help 17 18 Add support for Aardvark 64bit PCIe Host Controller. This 18 19 controller is part of the South Bridge of the Marvel Armada ··· 30 29 tristate "Altera PCIe MSI feature" 31 30 depends on PCIE_ALTERA 32 31 depends on PCI_MSI 32 + select IRQ_MSI_LIB 33 33 help 34 34 Say Y here if you want PCIe MSI support for the Altera FPGA. 35 35 This MSI driver supports Altera MSI to GIC controller IP. ··· 64 62 BMIPS_GENERIC || COMPILE_TEST 65 63 depends on OF 66 64 depends on PCI_MSI 65 + select IRQ_MSI_LIB 67 66 default ARCH_BRCMSTB || BMIPS_GENERIC 68 67 help 69 68 Say Y here to enable PCIe host controller support for ··· 101 98 bool "Broadcom iProc PCIe MSI support" 102 99 depends on PCIE_IPROC_PLATFORM || PCIE_IPROC_BCMA 103 100 depends on PCI_MSI 101 + select IRQ_MSI_LIB 104 102 default ARCH_BCM_IPROC 105 103 help 106 104 Say Y here if you want to enable MSI support for Broadcom's iProc ··· 156 152 config VMD 157 153 depends on PCI_MSI && X86_64 && !UML 158 154 tristate "Intel Volume Management Device Driver" 155 + select IRQ_MSI_LIB 159 156 help 160 157 Adds support for the Intel Volume Management Device (VMD). VMD is a 161 158 secondary PCI host bridge that allows PCI Express root ports, ··· 196 191 depends on ARCH_AIROHA || ARCH_MEDIATEK || COMPILE_TEST 197 192 depends on OF 198 193 depends on PCI_MSI 194 + select IRQ_MSI_LIB 199 195 help 200 196 Say Y here if you want to enable PCIe controller support on 201 197 MediaTek SoCs. ··· 205 199 tristate "MediaTek Gen3 PCIe controller" 206 200 depends on ARCH_AIROHA || ARCH_MEDIATEK || COMPILE_TEST 207 201 depends on PCI_MSI 202 + select IRQ_MSI_LIB 208 203 help 209 204 Adds support for PCIe Gen3 MAC controller for MediaTek SoCs. 210 205 This PCIe controller is compatible with Gen3, Gen2 and Gen1 speed, ··· 244 237 bool "Renesas R-Car PCIe controller (host mode)" 245 238 depends on ARCH_RENESAS || COMPILE_TEST 246 239 depends on PCI_MSI 240 + select IRQ_MSI_LIB 247 241 help 248 242 Say Y here if you want PCIe controller support on R-Car SoCs in host 249 243 mode. ··· 323 315 bool "Xilinx AXI PCIe controller" 324 316 depends on OF 325 317 depends on PCI_MSI 318 + select IRQ_MSI_LIB 326 319 help 327 320 Say 'Y' here if you want kernel to support the Xilinx AXI PCIe 328 321 Host Bridge driver. ··· 333 324 depends on ARCH_ZYNQMP || COMPILE_TEST 334 325 depends on PCI_MSI 335 326 select PCI_HOST_COMMON 327 + select IRQ_MSI_LIB 336 328 help 337 329 Say 'Y' here if you want kernel support for the Xilinx PL DMA 338 330 PCIe host bridge. The controller is a Soft IP which can act as ··· 344 334 bool "Xilinx NWL PCIe controller" 345 335 depends on ARCH_ZYNQMP || COMPILE_TEST 346 336 depends on PCI_MSI 337 + select IRQ_MSI_LIB 347 338 help 348 339 Say 'Y' here if you want kernel support for Xilinx 349 340 NWL PCIe controller. The controller can act as Root Port
+1 -1
drivers/pci/controller/cadence/pcie-cadence-ep.c
··· 353 353 } 354 354 spin_unlock_irqrestore(&ep->lock, flags); 355 355 356 - offset = CDNS_PCIE_NORMAL_MSG_ROUTING(MSG_ROUTING_LOCAL) | 356 + offset = CDNS_PCIE_NORMAL_MSG_ROUTING(PCIE_MSG_TYPE_R_LOCAL) | 357 357 CDNS_PCIE_NORMAL_MSG_CODE(msg_code); 358 358 writel(0, ep->irq_cpu_addr + offset); 359 359 }
-20
drivers/pci/controller/cadence/pcie-cadence.h
··· 250 250 251 251 struct cdns_pcie; 252 252 253 - enum cdns_pcie_msg_routing { 254 - /* Route to Root Complex */ 255 - MSG_ROUTING_TO_RC, 256 - 257 - /* Use Address Routing */ 258 - MSG_ROUTING_BY_ADDR, 259 - 260 - /* Use ID Routing */ 261 - MSG_ROUTING_BY_ID, 262 - 263 - /* Route as Broadcast Message from Root Complex */ 264 - MSG_ROUTING_BCAST, 265 - 266 - /* Local message; terminate at receiver (INTx messages) */ 267 - MSG_ROUTING_LOCAL, 268 - 269 - /* Gather & route to Root Complex (PME_TO_Ack message) */ 270 - MSG_ROUTING_GATHER, 271 - }; 272 - 273 253 struct cdns_pcie_ops { 274 254 int (*start_link)(struct cdns_pcie *pcie); 275 255 void (*stop_link)(struct cdns_pcie *pcie);
+12
drivers/pci/controller/dwc/Kconfig
··· 19 19 config PCIE_DW_HOST 20 20 bool 21 21 select PCIE_DW 22 + select IRQ_MSI_LIB 22 23 23 24 config PCIE_DW_EP 24 25 bool ··· 297 296 select PCIE_DW_HOST 298 297 select CRC8 299 298 select PCIE_QCOM_COMMON 299 + select PCI_HOST_COMMON 300 300 help 301 301 Say Y here to enable PCIe controller support on Qualcomm SoCs. The 302 302 PCIe controller uses the DesignWare core plus Qualcomm-specific ··· 403 401 help 404 402 Say Y here if you want PCIe endpoint controller support on 405 403 UniPhier SoCs. This driver supports Pro5 SoC. 404 + 405 + config PCIE_SOPHGO_DW 406 + bool "Sophgo DesignWare PCIe controller (host mode)" 407 + depends on ARCH_SOPHGO || COMPILE_TEST 408 + depends on PCI_MSI 409 + depends on OF 410 + select PCIE_DW_HOST 411 + help 412 + Say Y here if you want PCIe host controller support on 413 + Sophgo SoCs. 406 414 407 415 config PCIE_SPEAR13XX 408 416 bool "STMicroelectronics SPEAr PCIe controller"
+1
drivers/pci/controller/dwc/Makefile
··· 20 20 obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o 21 21 obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o 22 22 obj-$(CONFIG_PCIE_ROCKCHIP_DW) += pcie-dw-rockchip.o 23 + obj-$(CONFIG_PCIE_SOPHGO_DW) += pcie-sophgo.o 23 24 obj-$(CONFIG_PCIE_INTEL_GW) += pcie-intel-gw.o 24 25 obj-$(CONFIG_PCIE_KEEMBAY) += pcie-keembay.o 25 26 obj-$(CONFIG_PCIE_KIRIN) += pcie-kirin.o
+26 -14
drivers/pci/controller/dwc/pci-imx6.c
··· 860 860 static void imx_pcie_assert_core_reset(struct imx_pcie *imx_pcie) 861 861 { 862 862 reset_control_assert(imx_pcie->pciephy_reset); 863 - reset_control_assert(imx_pcie->apps_reset); 864 863 865 864 if (imx_pcie->drvdata->core_reset) 866 865 imx_pcie->drvdata->core_reset(imx_pcie, true); ··· 871 872 static int imx_pcie_deassert_core_reset(struct imx_pcie *imx_pcie) 872 873 { 873 874 reset_control_deassert(imx_pcie->pciephy_reset); 874 - reset_control_deassert(imx_pcie->apps_reset); 875 875 876 876 if (imx_pcie->drvdata->core_reset) 877 877 imx_pcie->drvdata->core_reset(imx_pcie, false); ··· 1061 1063 data1 |= IMX95_PE0_LUT_VLD; 1062 1064 regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA1, data1); 1063 1065 1064 - data2 = IMX95_PE0_LUT_MASK; /* Match all bits of RID */ 1066 + if (imx_pcie->drvdata->mode == DW_PCIE_EP_TYPE) 1067 + data2 = 0x7; /* In the EP mode, only 'Device ID' is required */ 1068 + else 1069 + data2 = IMX95_PE0_LUT_MASK; /* Match all bits of RID */ 1065 1070 data2 |= FIELD_PREP(IMX95_PE0_LUT_REQID, rid); 1066 1071 regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA2, data2); 1067 1072 ··· 1097 1096 } 1098 1097 } 1099 1098 1100 - static int imx_pcie_enable_device(struct pci_host_bridge *bridge, 1101 - struct pci_dev *pdev) 1099 + static int imx_pcie_add_lut_by_rid(struct imx_pcie *imx_pcie, u32 rid) 1102 1100 { 1103 - struct imx_pcie *imx_pcie = to_imx_pcie(to_dw_pcie_from_pp(bridge->sysdata)); 1104 - u32 sid_i, sid_m, rid = pci_dev_id(pdev); 1101 + struct device *dev = imx_pcie->pci->dev; 1105 1102 struct device_node *target; 1106 - struct device *dev; 1103 + u32 sid_i, sid_m; 1107 1104 int err_i, err_m; 1108 1105 u32 sid = 0; 1109 - 1110 - dev = imx_pcie->pci->dev; 1111 1106 1112 1107 target = NULL; 1113 1108 err_i = of_map_id(dev->of_node, rid, "iommu-map", "iommu-map-mask", ··· 1179 1182 return imx_pcie_add_lut(imx_pcie, rid, sid); 1180 1183 } 1181 1184 1185 + static int imx_pcie_enable_device(struct pci_host_bridge *bridge, struct pci_dev *pdev) 1186 + { 1187 + struct imx_pcie *imx_pcie = to_imx_pcie(to_dw_pcie_from_pp(bridge->sysdata)); 1188 + 1189 + return imx_pcie_add_lut_by_rid(imx_pcie, pci_dev_id(pdev)); 1190 + } 1191 + 1182 1192 static void imx_pcie_disable_device(struct pci_host_bridge *bridge, 1183 1193 struct pci_dev *pdev) 1184 1194 { ··· 1250 1246 goto err_phy_exit; 1251 1247 } 1252 1248 } 1249 + 1250 + /* Make sure that PCIe LTSSM is cleared */ 1251 + imx_pcie_ltssm_disable(dev); 1253 1252 1254 1253 ret = imx_pcie_deassert_core_reset(imx_pcie); 1255 1254 if (ret < 0) { ··· 1392 1385 .msix_capable = false, 1393 1386 .bar[BAR_1] = { .type = BAR_RESERVED, }, 1394 1387 .bar[BAR_3] = { .type = BAR_RESERVED, }, 1388 + .bar[BAR_4] = { .type = BAR_FIXED, .fixed_size = SZ_256, }, 1389 + .bar[BAR_5] = { .type = BAR_RESERVED, }, 1395 1390 .align = SZ_64K, 1396 1391 }; 1397 1392 ··· 1473 1464 } 1474 1465 1475 1466 pci_epc_init_notify(ep->epc); 1476 - 1477 - /* Start LTSSM. */ 1478 - imx_pcie_ltssm_enable(dev); 1479 1467 1480 1468 return 0; 1481 1469 } ··· 1770 1764 ret = imx_add_pcie_ep(imx_pcie, pdev); 1771 1765 if (ret < 0) 1772 1766 return ret; 1767 + 1768 + /* 1769 + * FIXME: Only single Device (EPF) is supported due to the 1770 + * Endpoint framework limitation. 1771 + */ 1772 + imx_pcie_add_lut_by_rid(imx_pcie, 0); 1773 1773 } else { 1774 1774 pci->pp.use_atu_msg = true; 1775 1775 ret = dw_pcie_host_init(&pci->pp); ··· 1924 1912 .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, 1925 1913 .mode_off[1] = IOMUXC_GPR12, 1926 1914 .mode_mask[1] = IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE, 1927 - .epc_features = &imx8m_pcie_epc_features, 1915 + .epc_features = &imx8q_pcie_epc_features, 1928 1916 .init_phy = imx8mq_pcie_init_phy, 1929 1917 .enable_ref_clk = imx8mm_pcie_enable_ref_clk, 1930 1918 },
+8 -8
drivers/pci/controller/dwc/pcie-designware-debugfs.c
··· 814 814 { 815 815 struct dw_pcie *pci = drvdata; 816 816 817 - return (pci->mode == DW_PCIE_EP_TYPE) ? true : false; 817 + return pci->mode == DW_PCIE_EP_TYPE; 818 818 } 819 819 820 820 static bool dw_pcie_ptm_context_valid_visible(void *drvdata) 821 821 { 822 822 struct dw_pcie *pci = drvdata; 823 823 824 - return (pci->mode == DW_PCIE_RC_TYPE) ? true : false; 824 + return pci->mode == DW_PCIE_RC_TYPE; 825 825 } 826 826 827 827 static bool dw_pcie_ptm_local_clock_visible(void *drvdata) ··· 834 834 { 835 835 struct dw_pcie *pci = drvdata; 836 836 837 - return (pci->mode == DW_PCIE_EP_TYPE) ? true : false; 837 + return pci->mode == DW_PCIE_EP_TYPE; 838 838 } 839 839 840 840 static bool dw_pcie_ptm_t1_visible(void *drvdata) 841 841 { 842 842 struct dw_pcie *pci = drvdata; 843 843 844 - return (pci->mode == DW_PCIE_EP_TYPE) ? true : false; 844 + return pci->mode == DW_PCIE_EP_TYPE; 845 845 } 846 846 847 847 static bool dw_pcie_ptm_t2_visible(void *drvdata) 848 848 { 849 849 struct dw_pcie *pci = drvdata; 850 850 851 - return (pci->mode == DW_PCIE_RC_TYPE) ? true : false; 851 + return pci->mode == DW_PCIE_RC_TYPE; 852 852 } 853 853 854 854 static bool dw_pcie_ptm_t3_visible(void *drvdata) 855 855 { 856 856 struct dw_pcie *pci = drvdata; 857 857 858 - return (pci->mode == DW_PCIE_RC_TYPE) ? true : false; 858 + return pci->mode == DW_PCIE_RC_TYPE; 859 859 } 860 860 861 861 static bool dw_pcie_ptm_t4_visible(void *drvdata) 862 862 { 863 863 struct dw_pcie *pci = drvdata; 864 864 865 - return (pci->mode == DW_PCIE_EP_TYPE) ? true : false; 865 + return pci->mode == DW_PCIE_EP_TYPE; 866 866 } 867 867 868 - const struct pcie_ptm_ops dw_pcie_ptm_ops = { 868 + static const struct pcie_ptm_ops dw_pcie_ptm_ops = { 869 869 .check_capability = dw_pcie_ptm_check_capability, 870 870 .context_update_write = dw_pcie_ptm_context_update_write, 871 871 .context_update_read = dw_pcie_ptm_context_update_read,
+42 -61
drivers/pci/controller/dwc/pcie-designware-host.c
··· 10 10 11 11 #include <linux/iopoll.h> 12 12 #include <linux/irqchip/chained_irq.h> 13 + #include <linux/irqchip/irq-msi-lib.h> 13 14 #include <linux/irqdomain.h> 14 15 #include <linux/msi.h> 15 16 #include <linux/of_address.h> ··· 24 23 static struct pci_ops dw_pcie_ops; 25 24 static struct pci_ops dw_child_pcie_ops; 26 25 27 - static void dw_msi_ack_irq(struct irq_data *d) 28 - { 29 - irq_chip_ack_parent(d); 30 - } 26 + #define DW_PCIE_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ 27 + MSI_FLAG_USE_DEF_CHIP_OPS | \ 28 + MSI_FLAG_NO_AFFINITY | \ 29 + MSI_FLAG_PCI_MSI_MASK_PARENT) 30 + #define DW_PCIE_MSI_FLAGS_SUPPORTED (MSI_FLAG_MULTI_PCI_MSI | \ 31 + MSI_FLAG_PCI_MSIX | \ 32 + MSI_GENERIC_FLAGS_MASK) 31 33 32 - static void dw_msi_mask_irq(struct irq_data *d) 33 - { 34 - pci_msi_mask_irq(d); 35 - irq_chip_mask_parent(d); 36 - } 37 - 38 - static void dw_msi_unmask_irq(struct irq_data *d) 39 - { 40 - pci_msi_unmask_irq(d); 41 - irq_chip_unmask_parent(d); 42 - } 43 - 44 - static struct irq_chip dw_pcie_msi_irq_chip = { 45 - .name = "PCI-MSI", 46 - .irq_ack = dw_msi_ack_irq, 47 - .irq_mask = dw_msi_mask_irq, 48 - .irq_unmask = dw_msi_unmask_irq, 49 - }; 50 - 51 - static struct msi_domain_info dw_pcie_msi_domain_info = { 52 - .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | 53 - MSI_FLAG_NO_AFFINITY | MSI_FLAG_PCI_MSIX | 54 - MSI_FLAG_MULTI_PCI_MSI, 55 - .chip = &dw_pcie_msi_irq_chip, 34 + static const struct msi_parent_ops dw_pcie_msi_parent_ops = { 35 + .required_flags = DW_PCIE_MSI_FLAGS_REQUIRED, 36 + .supported_flags = DW_PCIE_MSI_FLAGS_SUPPORTED, 37 + .bus_select_token = DOMAIN_BUS_PCI_MSI, 38 + .chip_flags = MSI_CHIP_FLAG_SET_ACK, 39 + .prefix = "DW-", 40 + .init_dev_msi_info = msi_lib_init_dev_msi_info, 56 41 }; 57 42 58 43 /* MSI int handler */ ··· 214 227 int dw_pcie_allocate_domains(struct dw_pcie_rp *pp) 215 228 { 216 229 struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 217 - struct fwnode_handle *fwnode = of_fwnode_handle(pci->dev->of_node); 230 + struct irq_domain_info info = { 231 + .fwnode = dev_fwnode(pci->dev), 232 + .ops = &dw_pcie_msi_domain_ops, 233 + .size = pp->num_vectors, 234 + .host_data = pp, 235 + }; 218 236 219 - pp->irq_domain = irq_domain_create_linear(fwnode, pp->num_vectors, 220 - &dw_pcie_msi_domain_ops, pp); 237 + pp->irq_domain = msi_create_parent_irq_domain(&info, &dw_pcie_msi_parent_ops); 221 238 if (!pp->irq_domain) { 222 239 dev_err(pci->dev, "Failed to create IRQ domain\n"); 223 - return -ENOMEM; 224 - } 225 - 226 - irq_domain_update_bus_token(pp->irq_domain, DOMAIN_BUS_NEXUS); 227 - 228 - pp->msi_domain = pci_msi_create_irq_domain(fwnode, 229 - &dw_pcie_msi_domain_info, 230 - pp->irq_domain); 231 - if (!pp->msi_domain) { 232 - dev_err(pci->dev, "Failed to create MSI domain\n"); 233 - irq_domain_remove(pp->irq_domain); 234 240 return -ENOMEM; 235 241 } 236 242 237 243 return 0; 238 244 } 239 245 240 - static void dw_pcie_free_msi(struct dw_pcie_rp *pp) 246 + void dw_pcie_free_msi(struct dw_pcie_rp *pp) 241 247 { 242 248 u32 ctrl; 243 249 ··· 240 260 NULL, NULL); 241 261 } 242 262 243 - irq_domain_remove(pp->msi_domain); 244 263 irq_domain_remove(pp->irq_domain); 245 264 } 265 + EXPORT_SYMBOL_GPL(dw_pcie_free_msi); 246 266 247 - static void dw_pcie_msi_init(struct dw_pcie_rp *pp) 267 + void dw_pcie_msi_init(struct dw_pcie_rp *pp) 248 268 { 249 269 struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 250 270 u64 msi_target = (u64)pp->msi_data; 271 + u32 ctrl, num_ctrls; 251 272 252 273 if (!pci_msi_enabled() || !pp->has_msi_ctrl) 253 274 return; 275 + 276 + num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL; 277 + 278 + /* Initialize IRQ Status array */ 279 + for (ctrl = 0; ctrl < num_ctrls; ctrl++) { 280 + dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK + 281 + (ctrl * MSI_REG_CTRL_BLOCK_SIZE), 282 + pp->irq_mask[ctrl]); 283 + dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_ENABLE + 284 + (ctrl * MSI_REG_CTRL_BLOCK_SIZE), 285 + ~0); 286 + } 254 287 255 288 /* Program the msi_data */ 256 289 dw_pcie_writel_dbi(pci, PCIE_MSI_ADDR_LO, lower_32_bits(msi_target)); 257 290 dw_pcie_writel_dbi(pci, PCIE_MSI_ADDR_HI, upper_32_bits(msi_target)); 258 291 } 292 + EXPORT_SYMBOL_GPL(dw_pcie_msi_init); 259 293 260 294 static int dw_pcie_parse_split_msi_irq(struct dw_pcie_rp *pp) 261 295 { ··· 311 317 return 0; 312 318 } 313 319 314 - static int dw_pcie_msi_host_init(struct dw_pcie_rp *pp) 320 + int dw_pcie_msi_host_init(struct dw_pcie_rp *pp) 315 321 { 316 322 struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 317 323 struct device *dev = pci->dev; ··· 385 391 386 392 return 0; 387 393 } 394 + EXPORT_SYMBOL_GPL(dw_pcie_msi_host_init); 388 395 389 396 static void dw_pcie_host_request_msg_tlp_res(struct dw_pcie_rp *pp) 390 397 { ··· 904 909 int dw_pcie_setup_rc(struct dw_pcie_rp *pp) 905 910 { 906 911 struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 907 - u32 val, ctrl, num_ctrls; 912 + u32 val; 908 913 int ret; 909 914 910 915 /* ··· 914 919 dw_pcie_dbi_ro_wr_en(pci); 915 920 916 921 dw_pcie_setup(pci); 917 - 918 - if (pp->has_msi_ctrl) { 919 - num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL; 920 - 921 - /* Initialize IRQ Status array */ 922 - for (ctrl = 0; ctrl < num_ctrls; ctrl++) { 923 - dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK + 924 - (ctrl * MSI_REG_CTRL_BLOCK_SIZE), 925 - pp->irq_mask[ctrl]); 926 - dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_ENABLE + 927 - (ctrl * MSI_REG_CTRL_BLOCK_SIZE), 928 - ~0); 929 - } 930 - } 931 922 932 923 dw_pcie_msi_init(pp); 933 924
+11 -3
drivers/pci/controller/dwc/pcie-designware.c
··· 702 702 int retries; 703 703 704 704 /* Check if the link is up or not */ 705 - for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) { 705 + for (retries = 0; retries < PCIE_LINK_WAIT_MAX_RETRIES; retries++) { 706 706 if (dw_pcie_link_up(pci)) 707 707 break; 708 708 709 - msleep(LINK_WAIT_SLEEP_MS); 709 + msleep(PCIE_LINK_WAIT_SLEEP_MS); 710 710 } 711 711 712 - if (retries >= LINK_WAIT_MAX_RETRIES) { 712 + if (retries >= PCIE_LINK_WAIT_MAX_RETRIES) { 713 713 dev_info(pci->dev, "Phy link never came up\n"); 714 714 return -ETIMEDOUT; 715 715 } 716 + 717 + /* 718 + * As per PCIe r6.0, sec 6.6.1, a Downstream Port that supports Link 719 + * speeds greater than 5.0 GT/s, software must wait a minimum of 100 ms 720 + * after Link training completes before sending a Configuration Request. 721 + */ 722 + if (pci->max_link_speed > 2) 723 + msleep(PCIE_RESET_CONFIG_WAIT_MS); 716 724 717 725 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); 718 726 val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA);
+14 -5
drivers/pci/controller/dwc/pcie-designware.h
··· 62 62 #define dw_pcie_cap_set(_pci, _cap) \ 63 63 set_bit(DW_PCIE_CAP_ ## _cap, &(_pci)->caps) 64 64 65 - /* Parameters for the waiting for link up routine */ 66 - #define LINK_WAIT_MAX_RETRIES 10 67 - #define LINK_WAIT_SLEEP_MS 90 68 - 69 65 /* Parameters for the waiting for iATU enabled routine */ 70 66 #define LINK_WAIT_MAX_IATU_RETRIES 5 71 67 #define LINK_WAIT_IATU 9 ··· 413 417 const struct dw_pcie_host_ops *ops; 414 418 int msi_irq[MAX_MSI_CTRLS]; 415 419 struct irq_domain *irq_domain; 416 - struct irq_domain *msi_domain; 417 420 dma_addr_t msi_data; 418 421 struct irq_chip *msi_irq_chip; 419 422 u32 num_vectors; ··· 754 759 int dw_pcie_suspend_noirq(struct dw_pcie *pci); 755 760 int dw_pcie_resume_noirq(struct dw_pcie *pci); 756 761 irqreturn_t dw_handle_msi_irq(struct dw_pcie_rp *pp); 762 + void dw_pcie_msi_init(struct dw_pcie_rp *pp); 763 + int dw_pcie_msi_host_init(struct dw_pcie_rp *pp); 764 + void dw_pcie_free_msi(struct dw_pcie_rp *pp); 757 765 int dw_pcie_setup_rc(struct dw_pcie_rp *pp); 758 766 int dw_pcie_host_init(struct dw_pcie_rp *pp); 759 767 void dw_pcie_host_deinit(struct dw_pcie_rp *pp); ··· 778 780 { 779 781 return IRQ_NONE; 780 782 } 783 + 784 + static inline void dw_pcie_msi_init(struct dw_pcie_rp *pp) 785 + { } 786 + 787 + static inline int dw_pcie_msi_host_init(struct dw_pcie_rp *pp) 788 + { 789 + return -ENODEV; 790 + } 791 + 792 + static inline void dw_pcie_free_msi(struct dw_pcie_rp *pp) 793 + { } 781 794 782 795 static inline int dw_pcie_setup_rc(struct dw_pcie_rp *pp) 783 796 {
+13 -3
drivers/pci/controller/dwc/pcie-dw-rockchip.c
··· 58 58 59 59 /* Hot Reset Control Register */ 60 60 #define PCIE_CLIENT_HOT_RESET_CTRL 0x180 61 + #define PCIE_LTSSM_APP_DLY2_EN BIT(1) 62 + #define PCIE_LTSSM_APP_DLY2_DONE BIT(3) 61 63 #define PCIE_LTSSM_ENABLE_ENHANCE BIT(4) 62 64 63 65 /* LTSSM Status Register */ ··· 460 458 461 459 if (reg & PCIE_RDLH_LINK_UP_CHGED) { 462 460 if (rockchip_pcie_link_up(pci)) { 461 + msleep(PCIE_RESET_CONFIG_WAIT_MS); 463 462 dev_dbg(dev, "Received Link up event. Starting enumeration!\n"); 464 463 /* Rescan the bus to enumerate endpoint devices */ 465 464 pci_lock_rescan_remove(); ··· 477 474 struct rockchip_pcie *rockchip = arg; 478 475 struct dw_pcie *pci = &rockchip->pci; 479 476 struct device *dev = pci->dev; 480 - u32 reg; 477 + u32 reg, val; 481 478 482 479 reg = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_INTR_STATUS_MISC); 483 480 rockchip_pcie_writel_apb(rockchip, reg, PCIE_CLIENT_INTR_STATUS_MISC); ··· 488 485 if (reg & PCIE_LINK_REQ_RST_NOT_INT) { 489 486 dev_dbg(dev, "hot reset or link-down reset\n"); 490 487 dw_pcie_ep_linkdown(&pci->ep); 488 + /* Stop delaying link training. */ 489 + val = HIWORD_UPDATE_BIT(PCIE_LTSSM_APP_DLY2_DONE); 490 + rockchip_pcie_writel_apb(rockchip, val, 491 + PCIE_CLIENT_HOT_RESET_CTRL); 491 492 } 492 493 493 494 if (reg & PCIE_RDLH_LINK_UP_CHGED) { ··· 573 566 return ret; 574 567 } 575 568 576 - /* LTSSM enable control mode */ 577 - val = HIWORD_UPDATE_BIT(PCIE_LTSSM_ENABLE_ENHANCE); 569 + /* 570 + * LTSSM enable control mode, and automatically delay link training on 571 + * hot reset/link-down reset. 572 + */ 573 + val = HIWORD_UPDATE_BIT(PCIE_LTSSM_ENABLE_ENHANCE | PCIE_LTSSM_APP_DLY2_EN); 578 574 rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_HOT_RESET_CTRL); 579 575 580 576 rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_EP_MODE,
+288 -39
drivers/pci/controller/dwc/pcie-qcom.c
··· 21 21 #include <linux/limits.h> 22 22 #include <linux/init.h> 23 23 #include <linux/of.h> 24 + #include <linux/of_pci.h> 24 25 #include <linux/pci.h> 26 + #include <linux/pci-ecam.h> 25 27 #include <linux/pm_opp.h> 26 28 #include <linux/pm_runtime.h> 27 29 #include <linux/platform_device.h> ··· 36 34 #include <linux/units.h> 37 35 38 36 #include "../../pci.h" 37 + #include "../pci-host-common.h" 39 38 #include "pcie-designware.h" 40 39 #include "pcie-qcom-common.h" 41 40 ··· 258 255 * @ops: qcom PCIe ops structure 259 256 * @override_no_snoop: Override NO_SNOOP attribute in TLP to enable cache 260 257 * snooping 258 + * @firmware_managed: Set if the Root Complex is firmware managed 261 259 */ 262 260 struct qcom_pcie_cfg { 263 261 const struct qcom_pcie_ops *ops; 264 262 bool override_no_snoop; 263 + bool firmware_managed; 265 264 bool no_l0s; 265 + }; 266 + 267 + struct qcom_pcie_port { 268 + struct list_head list; 269 + struct gpio_desc *reset; 270 + struct phy *phy; 266 271 }; 267 272 268 273 struct qcom_pcie { ··· 285 274 struct icc_path *icc_cpu; 286 275 const struct qcom_pcie_cfg *cfg; 287 276 struct dentry *debugfs; 277 + struct list_head ports; 288 278 bool suspended; 289 279 bool use_pm_opp; 290 280 }; 291 281 292 282 #define to_qcom_pcie(x) dev_get_drvdata((x)->dev) 293 283 284 + static void qcom_perst_assert(struct qcom_pcie *pcie, bool assert) 285 + { 286 + struct qcom_pcie_port *port; 287 + int val = assert ? 1 : 0; 288 + 289 + if (list_empty(&pcie->ports)) 290 + gpiod_set_value_cansleep(pcie->reset, val); 291 + else 292 + list_for_each_entry(port, &pcie->ports, list) 293 + gpiod_set_value_cansleep(port->reset, val); 294 + 295 + usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500); 296 + } 297 + 294 298 static void qcom_ep_reset_assert(struct qcom_pcie *pcie) 295 299 { 296 - gpiod_set_value_cansleep(pcie->reset, 1); 297 - usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500); 300 + qcom_perst_assert(pcie, true); 298 301 } 299 302 300 303 static void qcom_ep_reset_deassert(struct qcom_pcie *pcie) 301 304 { 302 305 /* Ensure that PERST has been asserted for at least 100 ms */ 303 306 msleep(PCIE_T_PVPERL_MS); 304 - gpiod_set_value_cansleep(pcie->reset, 0); 305 - usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500); 307 + qcom_perst_assert(pcie, false); 306 308 } 307 309 308 310 static int qcom_pcie_start_link(struct dw_pcie *pci) ··· 1253 1229 return val & PCI_EXP_LNKSTA_DLLLA; 1254 1230 } 1255 1231 1232 + static void qcom_pcie_phy_exit(struct qcom_pcie *pcie) 1233 + { 1234 + struct qcom_pcie_port *port; 1235 + 1236 + if (list_empty(&pcie->ports)) 1237 + phy_exit(pcie->phy); 1238 + else 1239 + list_for_each_entry(port, &pcie->ports, list) 1240 + phy_exit(port->phy); 1241 + } 1242 + 1243 + static void qcom_pcie_phy_power_off(struct qcom_pcie *pcie) 1244 + { 1245 + struct qcom_pcie_port *port; 1246 + 1247 + if (list_empty(&pcie->ports)) { 1248 + phy_power_off(pcie->phy); 1249 + } else { 1250 + list_for_each_entry(port, &pcie->ports, list) 1251 + phy_power_off(port->phy); 1252 + } 1253 + } 1254 + 1255 + static int qcom_pcie_phy_power_on(struct qcom_pcie *pcie) 1256 + { 1257 + struct qcom_pcie_port *port; 1258 + int ret = 0; 1259 + 1260 + if (list_empty(&pcie->ports)) { 1261 + ret = phy_set_mode_ext(pcie->phy, PHY_MODE_PCIE, PHY_MODE_PCIE_RC); 1262 + if (ret) 1263 + return ret; 1264 + 1265 + ret = phy_power_on(pcie->phy); 1266 + if (ret) 1267 + return ret; 1268 + } else { 1269 + list_for_each_entry(port, &pcie->ports, list) { 1270 + ret = phy_set_mode_ext(port->phy, PHY_MODE_PCIE, PHY_MODE_PCIE_RC); 1271 + if (ret) 1272 + return ret; 1273 + 1274 + ret = phy_power_on(port->phy); 1275 + if (ret) { 1276 + qcom_pcie_phy_power_off(pcie); 1277 + return ret; 1278 + } 1279 + } 1280 + } 1281 + 1282 + return ret; 1283 + } 1284 + 1256 1285 static int qcom_pcie_host_init(struct dw_pcie_rp *pp) 1257 1286 { 1258 1287 struct dw_pcie *pci = to_dw_pcie_from_pp(pp); ··· 1318 1241 if (ret) 1319 1242 return ret; 1320 1243 1321 - ret = phy_set_mode_ext(pcie->phy, PHY_MODE_PCIE, PHY_MODE_PCIE_RC); 1322 - if (ret) 1323 - goto err_deinit; 1324 - 1325 - ret = phy_power_on(pcie->phy); 1244 + ret = qcom_pcie_phy_power_on(pcie); 1326 1245 if (ret) 1327 1246 goto err_deinit; 1328 1247 ··· 1341 1268 err_assert_reset: 1342 1269 qcom_ep_reset_assert(pcie); 1343 1270 err_disable_phy: 1344 - phy_power_off(pcie->phy); 1271 + qcom_pcie_phy_power_off(pcie); 1345 1272 err_deinit: 1346 1273 pcie->cfg->ops->deinit(pcie); 1347 1274 ··· 1354 1281 struct qcom_pcie *pcie = to_qcom_pcie(pci); 1355 1282 1356 1283 qcom_ep_reset_assert(pcie); 1357 - phy_power_off(pcie->phy); 1284 + qcom_pcie_phy_power_off(pcie); 1358 1285 pcie->cfg->ops->deinit(pcie); 1359 1286 } 1360 1287 ··· 1499 1426 .no_l0s = true, 1500 1427 }; 1501 1428 1429 + static const struct qcom_pcie_cfg cfg_fw_managed = { 1430 + .firmware_managed = true, 1431 + }; 1432 + 1502 1433 static const struct dw_pcie_ops dw_pcie_ops = { 1503 1434 .link_up = qcom_pcie_link_up, 1504 1435 .start_link = qcom_pcie_start_link, ··· 1641 1564 writel_relaxed(status, pcie->parf + PARF_INT_ALL_CLEAR); 1642 1565 1643 1566 if (FIELD_GET(PARF_INT_ALL_LINK_UP, status)) { 1567 + msleep(PCIE_RESET_CONFIG_WAIT_MS); 1644 1568 dev_dbg(dev, "Received Link up event. Starting enumeration!\n"); 1645 1569 /* Rescan the bus to enumerate endpoint devices */ 1646 1570 pci_lock_rescan_remove(); ··· 1657 1579 return IRQ_HANDLED; 1658 1580 } 1659 1581 1582 + static void qcom_pci_free_msi(void *ptr) 1583 + { 1584 + struct dw_pcie_rp *pp = (struct dw_pcie_rp *)ptr; 1585 + 1586 + if (pp && pp->has_msi_ctrl) 1587 + dw_pcie_free_msi(pp); 1588 + } 1589 + 1590 + static int qcom_pcie_ecam_host_init(struct pci_config_window *cfg) 1591 + { 1592 + struct device *dev = cfg->parent; 1593 + struct dw_pcie_rp *pp; 1594 + struct dw_pcie *pci; 1595 + int ret; 1596 + 1597 + pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); 1598 + if (!pci) 1599 + return -ENOMEM; 1600 + 1601 + pci->dev = dev; 1602 + pp = &pci->pp; 1603 + pci->dbi_base = cfg->win; 1604 + pp->num_vectors = MSI_DEF_NUM_VECTORS; 1605 + 1606 + ret = dw_pcie_msi_host_init(pp); 1607 + if (ret) 1608 + return ret; 1609 + 1610 + pp->has_msi_ctrl = true; 1611 + dw_pcie_msi_init(pp); 1612 + 1613 + return devm_add_action_or_reset(dev, qcom_pci_free_msi, pp); 1614 + } 1615 + 1616 + static const struct pci_ecam_ops pci_qcom_ecam_ops = { 1617 + .init = qcom_pcie_ecam_host_init, 1618 + .pci_ops = { 1619 + .map_bus = pci_ecam_map_bus, 1620 + .read = pci_generic_config_read, 1621 + .write = pci_generic_config_write, 1622 + } 1623 + }; 1624 + 1625 + static int qcom_pcie_parse_port(struct qcom_pcie *pcie, struct device_node *node) 1626 + { 1627 + struct device *dev = pcie->pci->dev; 1628 + struct qcom_pcie_port *port; 1629 + struct gpio_desc *reset; 1630 + struct phy *phy; 1631 + int ret; 1632 + 1633 + reset = devm_fwnode_gpiod_get(dev, of_fwnode_handle(node), 1634 + "reset", GPIOD_OUT_HIGH, "PERST#"); 1635 + if (IS_ERR(reset)) 1636 + return PTR_ERR(reset); 1637 + 1638 + phy = devm_of_phy_get(dev, node, NULL); 1639 + if (IS_ERR(phy)) 1640 + return PTR_ERR(phy); 1641 + 1642 + port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); 1643 + if (!port) 1644 + return -ENOMEM; 1645 + 1646 + ret = phy_init(phy); 1647 + if (ret) 1648 + return ret; 1649 + 1650 + port->reset = reset; 1651 + port->phy = phy; 1652 + INIT_LIST_HEAD(&port->list); 1653 + list_add_tail(&port->list, &pcie->ports); 1654 + 1655 + return 0; 1656 + } 1657 + 1658 + static int qcom_pcie_parse_ports(struct qcom_pcie *pcie) 1659 + { 1660 + struct device *dev = pcie->pci->dev; 1661 + struct qcom_pcie_port *port, *tmp; 1662 + int ret = -ENOENT; 1663 + 1664 + for_each_available_child_of_node_scoped(dev->of_node, of_port) { 1665 + ret = qcom_pcie_parse_port(pcie, of_port); 1666 + if (ret) 1667 + goto err_port_del; 1668 + } 1669 + 1670 + return ret; 1671 + 1672 + err_port_del: 1673 + list_for_each_entry_safe(port, tmp, &pcie->ports, list) 1674 + list_del(&port->list); 1675 + 1676 + return ret; 1677 + } 1678 + 1679 + static int qcom_pcie_parse_legacy_binding(struct qcom_pcie *pcie) 1680 + { 1681 + struct device *dev = pcie->pci->dev; 1682 + int ret; 1683 + 1684 + pcie->phy = devm_phy_optional_get(dev, "pciephy"); 1685 + if (IS_ERR(pcie->phy)) 1686 + return PTR_ERR(pcie->phy); 1687 + 1688 + pcie->reset = devm_gpiod_get_optional(dev, "perst", GPIOD_OUT_HIGH); 1689 + if (IS_ERR(pcie->reset)) 1690 + return PTR_ERR(pcie->reset); 1691 + 1692 + ret = phy_init(pcie->phy); 1693 + if (ret) 1694 + return ret; 1695 + 1696 + return 0; 1697 + } 1698 + 1660 1699 static int qcom_pcie_probe(struct platform_device *pdev) 1661 1700 { 1662 1701 const struct qcom_pcie_cfg *pcie_cfg; 1663 1702 unsigned long max_freq = ULONG_MAX; 1703 + struct qcom_pcie_port *port, *tmp; 1664 1704 struct device *dev = &pdev->dev; 1665 1705 struct dev_pm_opp *opp; 1666 1706 struct qcom_pcie *pcie; ··· 1789 1593 char *name; 1790 1594 1791 1595 pcie_cfg = of_device_get_match_data(dev); 1792 - if (!pcie_cfg || !pcie_cfg->ops) { 1793 - dev_err(dev, "Invalid platform data\n"); 1794 - return -EINVAL; 1596 + if (!pcie_cfg) { 1597 + dev_err(dev, "No platform data\n"); 1598 + return -ENODATA; 1795 1599 } 1796 1600 1797 - pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); 1798 - if (!pcie) 1799 - return -ENOMEM; 1800 - 1801 - pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); 1802 - if (!pci) 1803 - return -ENOMEM; 1601 + if (!pcie_cfg->firmware_managed && !pcie_cfg->ops) { 1602 + dev_err(dev, "No platform ops\n"); 1603 + return -ENODATA; 1604 + } 1804 1605 1805 1606 pm_runtime_enable(dev); 1806 1607 ret = pm_runtime_get_sync(dev); 1807 1608 if (ret < 0) 1808 1609 goto err_pm_runtime_put; 1610 + 1611 + if (pcie_cfg->firmware_managed) { 1612 + struct pci_host_bridge *bridge; 1613 + struct pci_config_window *cfg; 1614 + 1615 + bridge = devm_pci_alloc_host_bridge(dev, 0); 1616 + if (!bridge) { 1617 + ret = -ENOMEM; 1618 + goto err_pm_runtime_put; 1619 + } 1620 + 1621 + /* Parse and map our ECAM configuration space area */ 1622 + cfg = pci_host_common_ecam_create(dev, bridge, 1623 + &pci_qcom_ecam_ops); 1624 + if (IS_ERR(cfg)) { 1625 + ret = PTR_ERR(cfg); 1626 + goto err_pm_runtime_put; 1627 + } 1628 + 1629 + bridge->sysdata = cfg; 1630 + bridge->ops = (struct pci_ops *)&pci_qcom_ecam_ops.pci_ops; 1631 + bridge->msi_domain = true; 1632 + 1633 + ret = pci_host_probe(bridge); 1634 + if (ret) 1635 + goto err_pm_runtime_put; 1636 + 1637 + return 0; 1638 + } 1639 + 1640 + pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); 1641 + if (!pcie) { 1642 + ret = -ENOMEM; 1643 + goto err_pm_runtime_put; 1644 + } 1645 + 1646 + pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); 1647 + if (!pci) { 1648 + ret = -ENOMEM; 1649 + goto err_pm_runtime_put; 1650 + } 1651 + 1652 + INIT_LIST_HEAD(&pcie->ports); 1809 1653 1810 1654 pci->dev = dev; 1811 1655 pci->ops = &dw_pcie_ops; ··· 1854 1618 pcie->pci = pci; 1855 1619 1856 1620 pcie->cfg = pcie_cfg; 1857 - 1858 - pcie->reset = devm_gpiod_get_optional(dev, "perst", GPIOD_OUT_HIGH); 1859 - if (IS_ERR(pcie->reset)) { 1860 - ret = PTR_ERR(pcie->reset); 1861 - goto err_pm_runtime_put; 1862 - } 1863 1621 1864 1622 pcie->parf = devm_platform_ioremap_resource_byname(pdev, "parf"); 1865 1623 if (IS_ERR(pcie->parf)) { ··· 1875 1645 ret = PTR_ERR(pcie->mhi); 1876 1646 goto err_pm_runtime_put; 1877 1647 } 1878 - } 1879 - 1880 - pcie->phy = devm_phy_optional_get(dev, "pciephy"); 1881 - if (IS_ERR(pcie->phy)) { 1882 - ret = PTR_ERR(pcie->phy); 1883 - goto err_pm_runtime_put; 1884 1648 } 1885 1649 1886 1650 /* OPP table is optional */ ··· 1923 1699 1924 1700 pp->ops = &qcom_pcie_dw_ops; 1925 1701 1926 - ret = phy_init(pcie->phy); 1927 - if (ret) 1928 - goto err_pm_runtime_put; 1702 + ret = qcom_pcie_parse_ports(pcie); 1703 + if (ret) { 1704 + if (ret != -ENOENT) { 1705 + dev_err_probe(pci->dev, ret, 1706 + "Failed to parse Root Port: %d\n", ret); 1707 + goto err_pm_runtime_put; 1708 + } 1709 + 1710 + /* 1711 + * In the case of properties not populated in Root Port node, 1712 + * fallback to the legacy method of parsing the Host Bridge 1713 + * node. This is to maintain DT backwards compatibility. 1714 + */ 1715 + ret = qcom_pcie_parse_legacy_binding(pcie); 1716 + if (ret) 1717 + goto err_pm_runtime_put; 1718 + } 1929 1719 1930 1720 platform_set_drvdata(pdev, pcie); 1931 1721 ··· 1984 1746 err_host_deinit: 1985 1747 dw_pcie_host_deinit(pp); 1986 1748 err_phy_exit: 1987 - phy_exit(pcie->phy); 1749 + qcom_pcie_phy_exit(pcie); 1750 + list_for_each_entry_safe(port, tmp, &pcie->ports, list) 1751 + list_del(&port->list); 1988 1752 err_pm_runtime_put: 1989 1753 pm_runtime_put(dev); 1990 1754 pm_runtime_disable(dev); ··· 1996 1756 1997 1757 static int qcom_pcie_suspend_noirq(struct device *dev) 1998 1758 { 1999 - struct qcom_pcie *pcie = dev_get_drvdata(dev); 1759 + struct qcom_pcie *pcie; 2000 1760 int ret = 0; 1761 + 1762 + pcie = dev_get_drvdata(dev); 1763 + if (!pcie) 1764 + return 0; 2001 1765 2002 1766 /* 2003 1767 * Set minimum bandwidth required to keep data path functional during ··· 2056 1812 2057 1813 static int qcom_pcie_resume_noirq(struct device *dev) 2058 1814 { 2059 - struct qcom_pcie *pcie = dev_get_drvdata(dev); 1815 + struct qcom_pcie *pcie; 2060 1816 int ret; 1817 + 1818 + pcie = dev_get_drvdata(dev); 1819 + if (!pcie) 1820 + return 0; 2061 1821 2062 1822 if (pm_suspend_target_state != PM_SUSPEND_MEM) { 2063 1823 ret = icc_enable(pcie->icc_cpu); ··· 2097 1849 { .compatible = "qcom,pcie-ipq9574", .data = &cfg_2_9_0 }, 2098 1850 { .compatible = "qcom,pcie-msm8996", .data = &cfg_2_3_2 }, 2099 1851 { .compatible = "qcom,pcie-qcs404", .data = &cfg_2_4_0 }, 1852 + { .compatible = "qcom,pcie-sa8255p", .data = &cfg_fw_managed }, 2100 1853 { .compatible = "qcom,pcie-sa8540p", .data = &cfg_sc8280xp }, 2101 1854 { .compatible = "qcom,pcie-sa8775p", .data = &cfg_1_34_0}, 2102 1855 { .compatible = "qcom,pcie-sc7280", .data = &cfg_1_9_0 },
+257
drivers/pci/controller/dwc/pcie-sophgo.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Sophgo DesignWare based PCIe host controller driver 4 + */ 5 + 6 + #include <linux/bits.h> 7 + #include <linux/clk.h> 8 + #include <linux/irqchip/chained_irq.h> 9 + #include <linux/irqdomain.h> 10 + #include <linux/module.h> 11 + #include <linux/property.h> 12 + #include <linux/platform_device.h> 13 + 14 + #include "pcie-designware.h" 15 + 16 + #define to_sophgo_pcie(x) dev_get_drvdata((x)->dev) 17 + 18 + #define PCIE_INT_SIGNAL 0xc48 19 + #define PCIE_INT_EN 0xca0 20 + 21 + #define PCIE_INT_SIGNAL_INTX GENMASK(8, 5) 22 + 23 + #define PCIE_INT_EN_INTX GENMASK(4, 1) 24 + #define PCIE_INT_EN_INT_MSI BIT(5) 25 + 26 + struct sophgo_pcie { 27 + struct dw_pcie pci; 28 + void __iomem *app_base; 29 + struct clk_bulk_data *clks; 30 + unsigned int clk_cnt; 31 + struct irq_domain *irq_domain; 32 + }; 33 + 34 + static int sophgo_pcie_readl_app(struct sophgo_pcie *sophgo, u32 reg) 35 + { 36 + return readl_relaxed(sophgo->app_base + reg); 37 + } 38 + 39 + static void sophgo_pcie_writel_app(struct sophgo_pcie *sophgo, u32 val, u32 reg) 40 + { 41 + writel_relaxed(val, sophgo->app_base + reg); 42 + } 43 + 44 + static void sophgo_pcie_intx_handler(struct irq_desc *desc) 45 + { 46 + struct dw_pcie_rp *pp = irq_desc_get_handler_data(desc); 47 + struct irq_chip *chip = irq_desc_get_chip(desc); 48 + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 49 + struct sophgo_pcie *sophgo = to_sophgo_pcie(pci); 50 + unsigned long hwirq, reg; 51 + 52 + chained_irq_enter(chip, desc); 53 + 54 + reg = sophgo_pcie_readl_app(sophgo, PCIE_INT_SIGNAL); 55 + reg = FIELD_GET(PCIE_INT_SIGNAL_INTX, reg); 56 + 57 + for_each_set_bit(hwirq, &reg, PCI_NUM_INTX) 58 + generic_handle_domain_irq(sophgo->irq_domain, hwirq); 59 + 60 + chained_irq_exit(chip, desc); 61 + } 62 + 63 + static void sophgo_intx_irq_mask(struct irq_data *d) 64 + { 65 + struct dw_pcie_rp *pp = irq_data_get_irq_chip_data(d); 66 + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 67 + struct sophgo_pcie *sophgo = to_sophgo_pcie(pci); 68 + unsigned long flags; 69 + u32 val; 70 + 71 + raw_spin_lock_irqsave(&pp->lock, flags); 72 + 73 + val = sophgo_pcie_readl_app(sophgo, PCIE_INT_EN); 74 + val &= ~FIELD_PREP(PCIE_INT_EN_INTX, BIT(d->hwirq)); 75 + sophgo_pcie_writel_app(sophgo, val, PCIE_INT_EN); 76 + 77 + raw_spin_unlock_irqrestore(&pp->lock, flags); 78 + }; 79 + 80 + static void sophgo_intx_irq_unmask(struct irq_data *d) 81 + { 82 + struct dw_pcie_rp *pp = irq_data_get_irq_chip_data(d); 83 + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 84 + struct sophgo_pcie *sophgo = to_sophgo_pcie(pci); 85 + unsigned long flags; 86 + u32 val; 87 + 88 + raw_spin_lock_irqsave(&pp->lock, flags); 89 + 90 + val = sophgo_pcie_readl_app(sophgo, PCIE_INT_EN); 91 + val |= FIELD_PREP(PCIE_INT_EN_INTX, BIT(d->hwirq)); 92 + sophgo_pcie_writel_app(sophgo, val, PCIE_INT_EN); 93 + 94 + raw_spin_unlock_irqrestore(&pp->lock, flags); 95 + }; 96 + 97 + static struct irq_chip sophgo_intx_irq_chip = { 98 + .name = "INTx", 99 + .irq_mask = sophgo_intx_irq_mask, 100 + .irq_unmask = sophgo_intx_irq_unmask, 101 + }; 102 + 103 + static int sophgo_pcie_intx_map(struct irq_domain *domain, unsigned int irq, 104 + irq_hw_number_t hwirq) 105 + { 106 + irq_set_chip_and_handler(irq, &sophgo_intx_irq_chip, handle_level_irq); 107 + irq_set_chip_data(irq, domain->host_data); 108 + 109 + return 0; 110 + } 111 + 112 + static const struct irq_domain_ops intx_domain_ops = { 113 + .map = sophgo_pcie_intx_map, 114 + }; 115 + 116 + static int sophgo_pcie_init_irq_domain(struct dw_pcie_rp *pp) 117 + { 118 + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 119 + struct sophgo_pcie *sophgo = to_sophgo_pcie(pci); 120 + struct device *dev = sophgo->pci.dev; 121 + struct fwnode_handle *intc; 122 + int irq; 123 + 124 + intc = device_get_named_child_node(dev, "interrupt-controller"); 125 + if (!intc) { 126 + dev_err(dev, "missing child interrupt-controller node\n"); 127 + return -ENODEV; 128 + } 129 + 130 + irq = fwnode_irq_get(intc, 0); 131 + if (irq < 0) { 132 + dev_err(dev, "failed to get INTx irq number\n"); 133 + fwnode_handle_put(intc); 134 + return irq; 135 + } 136 + 137 + sophgo->irq_domain = irq_domain_create_linear(intc, PCI_NUM_INTX, 138 + &intx_domain_ops, pp); 139 + fwnode_handle_put(intc); 140 + if (!sophgo->irq_domain) { 141 + dev_err(dev, "failed to get a INTx irq domain\n"); 142 + return -EINVAL; 143 + } 144 + 145 + return irq; 146 + } 147 + 148 + static void sophgo_pcie_msi_enable(struct dw_pcie_rp *pp) 149 + { 150 + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 151 + struct sophgo_pcie *sophgo = to_sophgo_pcie(pci); 152 + unsigned long flags; 153 + u32 val; 154 + 155 + raw_spin_lock_irqsave(&pp->lock, flags); 156 + 157 + val = sophgo_pcie_readl_app(sophgo, PCIE_INT_EN); 158 + val |= PCIE_INT_EN_INT_MSI; 159 + sophgo_pcie_writel_app(sophgo, val, PCIE_INT_EN); 160 + 161 + raw_spin_unlock_irqrestore(&pp->lock, flags); 162 + } 163 + 164 + static int sophgo_pcie_host_init(struct dw_pcie_rp *pp) 165 + { 166 + int irq; 167 + 168 + irq = sophgo_pcie_init_irq_domain(pp); 169 + if (irq < 0) 170 + return irq; 171 + 172 + irq_set_chained_handler_and_data(irq, sophgo_pcie_intx_handler, pp); 173 + 174 + sophgo_pcie_msi_enable(pp); 175 + 176 + return 0; 177 + } 178 + 179 + static const struct dw_pcie_host_ops sophgo_pcie_host_ops = { 180 + .init = sophgo_pcie_host_init, 181 + }; 182 + 183 + static int sophgo_pcie_clk_init(struct sophgo_pcie *sophgo) 184 + { 185 + struct device *dev = sophgo->pci.dev; 186 + int ret; 187 + 188 + ret = devm_clk_bulk_get_all_enabled(dev, &sophgo->clks); 189 + if (ret < 0) 190 + return dev_err_probe(dev, ret, "failed to get clocks\n"); 191 + 192 + sophgo->clk_cnt = ret; 193 + 194 + return 0; 195 + } 196 + 197 + static int sophgo_pcie_resource_get(struct platform_device *pdev, 198 + struct sophgo_pcie *sophgo) 199 + { 200 + sophgo->app_base = devm_platform_ioremap_resource_byname(pdev, "app"); 201 + if (IS_ERR(sophgo->app_base)) 202 + return dev_err_probe(&pdev->dev, PTR_ERR(sophgo->app_base), 203 + "failed to map app registers\n"); 204 + 205 + return 0; 206 + } 207 + 208 + static int sophgo_pcie_configure_rc(struct sophgo_pcie *sophgo) 209 + { 210 + struct dw_pcie_rp *pp; 211 + 212 + pp = &sophgo->pci.pp; 213 + pp->ops = &sophgo_pcie_host_ops; 214 + 215 + return dw_pcie_host_init(pp); 216 + } 217 + 218 + static int sophgo_pcie_probe(struct platform_device *pdev) 219 + { 220 + struct device *dev = &pdev->dev; 221 + struct sophgo_pcie *sophgo; 222 + int ret; 223 + 224 + sophgo = devm_kzalloc(dev, sizeof(*sophgo), GFP_KERNEL); 225 + if (!sophgo) 226 + return -ENOMEM; 227 + 228 + platform_set_drvdata(pdev, sophgo); 229 + 230 + sophgo->pci.dev = dev; 231 + 232 + ret = sophgo_pcie_resource_get(pdev, sophgo); 233 + if (ret) 234 + return ret; 235 + 236 + ret = sophgo_pcie_clk_init(sophgo); 237 + if (ret) 238 + return ret; 239 + 240 + return sophgo_pcie_configure_rc(sophgo); 241 + } 242 + 243 + static const struct of_device_id sophgo_pcie_of_match[] = { 244 + { .compatible = "sophgo,sg2044-pcie" }, 245 + { } 246 + }; 247 + MODULE_DEVICE_TABLE(of, sophgo_pcie_of_match); 248 + 249 + static struct platform_driver sophgo_pcie_driver = { 250 + .driver = { 251 + .name = "sophgo-pcie", 252 + .of_match_table = sophgo_pcie_of_match, 253 + .suppress_bind_attrs = true, 254 + }, 255 + .probe = sophgo_pcie_probe, 256 + }; 257 + builtin_platform_driver(sophgo_pcie_driver);
+1
drivers/pci/controller/mobiveil/Kconfig
··· 9 9 config PCIE_MOBIVEIL_HOST 10 10 bool 11 11 depends on PCI_MSI 12 + select IRQ_MSI_LIB 12 13 select PCIE_MOBIVEIL 13 14 14 15 config PCIE_LAYERSCAPE_GEN4
+24 -24
drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
··· 12 12 #include <linux/init.h> 13 13 #include <linux/interrupt.h> 14 14 #include <linux/irq.h> 15 + #include <linux/irqchip/irq-msi-lib.h> 15 16 #include <linux/irqchip/chained_irq.h> 16 17 #include <linux/irqdomain.h> 17 18 #include <linux/kernel.h> ··· 354 353 .map = mobiveil_pcie_intx_map, 355 354 }; 356 355 357 - static struct irq_chip mobiveil_msi_irq_chip = { 358 - .name = "Mobiveil PCIe MSI", 359 - .irq_mask = pci_msi_mask_irq, 360 - .irq_unmask = pci_msi_unmask_irq, 361 - }; 356 + #define MOBIVEIL_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ 357 + MSI_FLAG_USE_DEF_CHIP_OPS | \ 358 + MSI_FLAG_NO_AFFINITY) 362 359 363 - static struct msi_domain_info mobiveil_msi_domain_info = { 364 - .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | 365 - MSI_FLAG_NO_AFFINITY | MSI_FLAG_PCI_MSIX, 366 - .chip = &mobiveil_msi_irq_chip, 360 + #define MOBIVEIL_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \ 361 + MSI_FLAG_PCI_MSIX) 362 + 363 + static const struct msi_parent_ops mobiveil_msi_parent_ops = { 364 + .required_flags = MOBIVEIL_MSI_FLAGS_REQUIRED, 365 + .supported_flags = MOBIVEIL_MSI_FLAGS_SUPPORTED, 366 + .bus_select_token = DOMAIN_BUS_PCI_MSI, 367 + .prefix = "Mobiveil-", 368 + .init_dev_msi_info = msi_lib_init_dev_msi_info, 367 369 }; 368 370 369 371 static void mobiveil_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) ··· 439 435 static int mobiveil_allocate_msi_domains(struct mobiveil_pcie *pcie) 440 436 { 441 437 struct device *dev = &pcie->pdev->dev; 442 - struct fwnode_handle *fwnode = of_fwnode_handle(dev->of_node); 443 438 struct mobiveil_msi *msi = &pcie->rp.msi; 444 439 445 440 mutex_init(&msi->lock); 446 - msi->dev_domain = irq_domain_create_linear(NULL, msi->num_of_vectors, 447 - &msi_domain_ops, pcie); 448 - if (!msi->dev_domain) { 449 - dev_err(dev, "failed to create IRQ domain\n"); 450 - return -ENOMEM; 451 - } 452 441 453 - msi->msi_domain = pci_msi_create_irq_domain(fwnode, 454 - &mobiveil_msi_domain_info, 455 - msi->dev_domain); 456 - if (!msi->msi_domain) { 442 + struct irq_domain_info info = { 443 + .fwnode = dev_fwnode(dev), 444 + .ops = &msi_domain_ops, 445 + .host_data = pcie, 446 + .size = msi->num_of_vectors, 447 + }; 448 + 449 + msi->dev_domain = msi_create_parent_irq_domain(&info, &mobiveil_msi_parent_ops); 450 + if (!msi->dev_domain) { 457 451 dev_err(dev, "failed to create MSI domain\n"); 458 - irq_domain_remove(msi->dev_domain); 459 452 return -ENOMEM; 460 453 } 461 454 ··· 465 464 struct mobiveil_root_port *rp = &pcie->rp; 466 465 467 466 /* setup INTx */ 468 - rp->intx_domain = irq_domain_create_linear(of_fwnode_handle(dev->of_node), PCI_NUM_INTX, 469 - &intx_domain_ops, pcie); 470 - 467 + rp->intx_domain = irq_domain_create_linear(dev_fwnode(dev), PCI_NUM_INTX, &intx_domain_ops, 468 + pcie); 471 469 if (!rp->intx_domain) { 472 470 dev_err(dev, "Failed to get a INTx IRQ domain\n"); 473 471 return -ENOMEM;
-1
drivers/pci/controller/mobiveil/pcie-mobiveil.h
··· 135 135 136 136 struct mobiveil_msi { /* MSI information */ 137 137 struct mutex lock; /* protect bitmap variable */ 138 - struct irq_domain *msi_domain; 139 138 struct irq_domain *dev_domain; 140 139 phys_addr_t msi_pages_phys; 141 140 int num_of_vectors;
+22 -35
drivers/pci/controller/pci-aardvark.c
··· 13 13 #include <linux/gpio/consumer.h> 14 14 #include <linux/interrupt.h> 15 15 #include <linux/irq.h> 16 + #include <linux/irqchip/irq-msi-lib.h> 16 17 #include <linux/irqdomain.h> 17 18 #include <linux/kernel.h> 18 19 #include <linux/module.h> ··· 279 278 struct irq_domain *irq_domain; 280 279 struct irq_chip irq_chip; 281 280 raw_spinlock_t irq_lock; 282 - struct irq_domain *msi_domain; 283 281 struct irq_domain *msi_inner_domain; 284 282 raw_spinlock_t msi_irq_lock; 285 283 DECLARE_BITMAP(msi_used, MSI_IRQ_NUM); ··· 1332 1332 raw_spin_unlock_irqrestore(&pcie->msi_irq_lock, flags); 1333 1333 } 1334 1334 1335 - static void advk_msi_top_irq_mask(struct irq_data *d) 1336 - { 1337 - pci_msi_mask_irq(d); 1338 - irq_chip_mask_parent(d); 1339 - } 1340 - 1341 - static void advk_msi_top_irq_unmask(struct irq_data *d) 1342 - { 1343 - pci_msi_unmask_irq(d); 1344 - irq_chip_unmask_parent(d); 1345 - } 1346 - 1347 1335 static struct irq_chip advk_msi_bottom_irq_chip = { 1348 1336 .name = "MSI", 1349 1337 .irq_compose_msi_msg = advk_msi_irq_compose_msi_msg, ··· 1424 1436 .xlate = irq_domain_xlate_onecell, 1425 1437 }; 1426 1438 1427 - static struct irq_chip advk_msi_irq_chip = { 1428 - .name = "advk-MSI", 1429 - .irq_mask = advk_msi_top_irq_mask, 1430 - .irq_unmask = advk_msi_top_irq_unmask, 1431 - }; 1439 + #define ADVK_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ 1440 + MSI_FLAG_USE_DEF_CHIP_OPS | \ 1441 + MSI_FLAG_PCI_MSI_MASK_PARENT | \ 1442 + MSI_FLAG_NO_AFFINITY) 1443 + #define ADVK_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \ 1444 + MSI_FLAG_PCI_MSIX | \ 1445 + MSI_FLAG_MULTI_PCI_MSI) 1432 1446 1433 - static struct msi_domain_info advk_msi_domain_info = { 1434 - .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | 1435 - MSI_FLAG_NO_AFFINITY | MSI_FLAG_MULTI_PCI_MSI | 1436 - MSI_FLAG_PCI_MSIX, 1437 - .chip = &advk_msi_irq_chip, 1447 + static const struct msi_parent_ops advk_msi_parent_ops = { 1448 + .required_flags = ADVK_MSI_FLAGS_REQUIRED, 1449 + .supported_flags = ADVK_MSI_FLAGS_SUPPORTED, 1450 + .bus_select_token = DOMAIN_BUS_PCI_MSI, 1451 + .prefix = "advk-", 1452 + .init_dev_msi_info = msi_lib_init_dev_msi_info, 1438 1453 }; 1439 1454 1440 1455 static int advk_pcie_init_msi_irq_domain(struct advk_pcie *pcie) ··· 1447 1456 raw_spin_lock_init(&pcie->msi_irq_lock); 1448 1457 mutex_init(&pcie->msi_used_lock); 1449 1458 1450 - pcie->msi_inner_domain = irq_domain_create_linear(NULL, MSI_IRQ_NUM, 1451 - &advk_msi_domain_ops, pcie); 1459 + struct irq_domain_info info = { 1460 + .fwnode = dev_fwnode(dev), 1461 + .ops = &advk_msi_domain_ops, 1462 + .host_data = pcie, 1463 + .size = MSI_IRQ_NUM, 1464 + }; 1465 + 1466 + pcie->msi_inner_domain = msi_create_parent_irq_domain(&info, &advk_msi_parent_ops); 1452 1467 if (!pcie->msi_inner_domain) 1453 1468 return -ENOMEM; 1454 - 1455 - pcie->msi_domain = 1456 - pci_msi_create_irq_domain(dev_fwnode(dev), 1457 - &advk_msi_domain_info, 1458 - pcie->msi_inner_domain); 1459 - if (!pcie->msi_domain) { 1460 - irq_domain_remove(pcie->msi_inner_domain); 1461 - return -ENOMEM; 1462 - } 1463 1469 1464 1470 return 0; 1465 1471 } 1466 1472 1467 1473 static void advk_pcie_remove_msi_irq_domain(struct advk_pcie *pcie) 1468 1474 { 1469 - irq_domain_remove(pcie->msi_domain); 1470 1475 irq_domain_remove(pcie->msi_inner_domain); 1471 1476 } 1472 1477
+3 -2
drivers/pci/controller/pci-host-common.c
··· 22 22 pci_ecam_free((struct pci_config_window *)ptr); 23 23 } 24 24 25 - static struct pci_config_window *gen_pci_init(struct device *dev, 25 + struct pci_config_window *pci_host_common_ecam_create(struct device *dev, 26 26 struct pci_host_bridge *bridge, const struct pci_ecam_ops *ops) 27 27 { 28 28 int err; ··· 50 50 51 51 return cfg; 52 52 } 53 + EXPORT_SYMBOL_GPL(pci_host_common_ecam_create); 53 54 54 55 int pci_host_common_init(struct platform_device *pdev, 55 56 const struct pci_ecam_ops *ops) ··· 68 67 platform_set_drvdata(pdev, bridge); 69 68 70 69 /* Parse and map our Configuration Space windows */ 71 - cfg = gen_pci_init(dev, bridge, ops); 70 + cfg = pci_host_common_ecam_create(dev, bridge, ops); 72 71 if (IS_ERR(cfg)) 73 72 return PTR_ERR(cfg); 74 73
+2
drivers/pci/controller/pci-host-common.h
··· 17 17 const struct pci_ecam_ops *ops); 18 18 void pci_host_common_remove(struct platform_device *pdev); 19 19 20 + struct pci_config_window *pci_host_common_ecam_create(struct device *dev, 21 + struct pci_host_bridge *bridge, const struct pci_ecam_ops *ops); 20 22 #endif
+2 -4
drivers/pci/controller/pci-mvebu.c
··· 1353 1353 goto skip; 1354 1354 } 1355 1355 1356 - ret = devm_add_action(dev, mvebu_pcie_port_clk_put, port); 1357 - if (ret < 0) { 1358 - clk_put(port->clk); 1356 + ret = devm_add_action_or_reset(dev, mvebu_pcie_port_clk_put, port); 1357 + if (ret < 0) 1359 1358 goto err; 1360 - } 1361 1359 1362 1360 return 1; 1363 1361
+155 -271
drivers/pci/controller/pci-xgene-msi.c
··· 6 6 * Author: Tanmay Inamdar <tinamdar@apm.com> 7 7 * Duc Dang <dhdang@apm.com> 8 8 */ 9 + #include <linux/bitfield.h> 9 10 #include <linux/cpu.h> 10 11 #include <linux/interrupt.h> 11 12 #include <linux/irqdomain.h> ··· 23 22 #define IDX_PER_GROUP 8 24 23 #define IRQS_PER_IDX 16 25 24 #define NR_HW_IRQS 16 26 - #define NR_MSI_VEC (IDX_PER_GROUP * IRQS_PER_IDX * NR_HW_IRQS) 25 + #define NR_MSI_BITS (IDX_PER_GROUP * IRQS_PER_IDX * NR_HW_IRQS) 26 + #define NR_MSI_VEC (NR_MSI_BITS / num_possible_cpus()) 27 27 28 - struct xgene_msi_group { 29 - struct xgene_msi *msi; 30 - int gic_irq; 31 - u32 msi_grp; 32 - }; 28 + #define MSI_GROUP_MASK GENMASK(22, 19) 29 + #define MSI_INDEX_MASK GENMASK(18, 16) 30 + #define MSI_INTR_MASK GENMASK(19, 16) 31 + 32 + #define MSInRx_HWIRQ_MASK GENMASK(6, 4) 33 + #define DATA_HWIRQ_MASK GENMASK(3, 0) 33 34 34 35 struct xgene_msi { 35 - struct device_node *node; 36 36 struct irq_domain *inner_domain; 37 37 u64 msi_addr; 38 38 void __iomem *msi_regs; 39 39 unsigned long *bitmap; 40 40 struct mutex bitmap_lock; 41 - struct xgene_msi_group *msi_groups; 42 - int num_cpus; 41 + unsigned int gic_irq[NR_HW_IRQS]; 43 42 }; 44 43 45 44 /* Global data */ 46 - static struct xgene_msi xgene_msi_ctrl; 45 + static struct xgene_msi *xgene_msi_ctrl; 47 46 48 47 /* 49 - * X-Gene v1 has 16 groups of MSI termination registers MSInIRx, where 50 - * n is group number (0..F), x is index of registers in each group (0..7) 48 + * X-Gene v1 has 16 frames of MSI termination registers MSInIRx, where n is 49 + * frame number (0..15), x is index of registers in each frame (0..7). Each 50 + * 32b register is at the beginning of a 64kB region, each frame occupying 51 + * 512kB (and the whole thing 8MB of PA space). 52 + * 53 + * Each register supports 16 MSI vectors (0..15) to generate interrupts. A 54 + * write to the MSInIRx from the PCI side generates an interrupt. A read 55 + * from the MSInRx on the CPU side returns a bitmap of the pending MSIs in 56 + * the lower 16 bits. A side effect of this read is that all pending 57 + * interrupts are acknowledged and cleared). 58 + * 59 + * Additionally, each MSI termination frame has 1 MSIINTn register (n is 60 + * 0..15) to indicate the MSI pending status caused by any of its 8 61 + * termination registers, reported as a bitmap in the lower 8 bits. Each 32b 62 + * register is at the beginning of a 64kB region (and overall occupying an 63 + * extra 1MB). 64 + * 65 + * There is one GIC IRQ assigned for each MSI termination frame, 16 in 66 + * total. 67 + * 51 68 * The register layout is as follows: 52 69 * MSI0IR0 base_addr 53 70 * MSI0IR1 base_addr + 0x10000 ··· 86 67 * MSIINT1 base_addr + 0x810000 87 68 * ... ... 88 69 * MSIINTF base_addr + 0x8F0000 89 - * 90 - * Each index register supports 16 MSI vectors (0..15) to generate interrupt. 91 - * There are total 16 GIC IRQs assigned for these 16 groups of MSI termination 92 - * registers. 93 - * 94 - * Each MSI termination group has 1 MSIINTn register (n is 0..15) to indicate 95 - * the MSI pending status caused by 1 of its 8 index registers. 96 70 */ 97 71 98 72 /* MSInIRx read helper */ 99 - static u32 xgene_msi_ir_read(struct xgene_msi *msi, 100 - u32 msi_grp, u32 msir_idx) 73 + static u32 xgene_msi_ir_read(struct xgene_msi *msi, u32 msi_grp, u32 msir_idx) 101 74 { 102 75 return readl_relaxed(msi->msi_regs + MSI_IR0 + 103 - (msi_grp << 19) + (msir_idx << 16)); 76 + (FIELD_PREP(MSI_GROUP_MASK, msi_grp) | 77 + FIELD_PREP(MSI_INDEX_MASK, msir_idx))); 104 78 } 105 79 106 80 /* MSIINTn read helper */ 107 81 static u32 xgene_msi_int_read(struct xgene_msi *msi, u32 msi_grp) 108 82 { 109 - return readl_relaxed(msi->msi_regs + MSI_INT0 + (msi_grp << 16)); 83 + return readl_relaxed(msi->msi_regs + MSI_INT0 + 84 + FIELD_PREP(MSI_INTR_MASK, msi_grp)); 110 85 } 111 86 112 87 /* 113 - * With 2048 MSI vectors supported, the MSI message can be constructed using 114 - * following scheme: 115 - * - Divide into 8 256-vector groups 116 - * Group 0: 0-255 117 - * Group 1: 256-511 118 - * Group 2: 512-767 119 - * ... 120 - * Group 7: 1792-2047 121 - * - Each 256-vector group is divided into 16 16-vector groups 122 - * As an example: 16 16-vector groups for 256-vector group 0-255 is 123 - * Group 0: 0-15 124 - * Group 1: 16-32 125 - * ... 126 - * Group 15: 240-255 127 - * - The termination address of MSI vector in 256-vector group n and 16-vector 128 - * group x is the address of MSIxIRn 129 - * - The data for MSI vector in 16-vector group x is x 88 + * In order to allow an MSI to be moved from one CPU to another without 89 + * having to repaint both the address and the data (which cannot be done 90 + * atomically), we statically partitions the MSI frames between CPUs. Given 91 + * that XGene-1 has 8 CPUs, each CPU gets two frames assigned to it 92 + * 93 + * We adopt the convention that when an MSI is moved, it is configured to 94 + * target the same register number in the congruent frame assigned to the 95 + * new target CPU. This reserves a given MSI across all CPUs, and reduces 96 + * the MSI capacity from 2048 to 256. 97 + * 98 + * Effectively, this amounts to: 99 + * - hwirq[7]::cpu[2:0] is the target frame number (n in MSInIRx) 100 + * - hwirq[6:4] is the register index in any given frame (x in MSInIRx) 101 + * - hwirq[3:0] is the MSI data 130 102 */ 131 - static u32 hwirq_to_reg_set(unsigned long hwirq) 103 + static irq_hw_number_t compute_hwirq(u8 frame, u8 index, u8 data) 132 104 { 133 - return (hwirq / (NR_HW_IRQS * IRQS_PER_IDX)); 134 - } 135 - 136 - static u32 hwirq_to_group(unsigned long hwirq) 137 - { 138 - return (hwirq % NR_HW_IRQS); 139 - } 140 - 141 - static u32 hwirq_to_msi_data(unsigned long hwirq) 142 - { 143 - return ((hwirq / NR_HW_IRQS) % IRQS_PER_IDX); 105 + return (FIELD_PREP(BIT(7), FIELD_GET(BIT(3), frame)) | 106 + FIELD_PREP(MSInRx_HWIRQ_MASK, index) | 107 + FIELD_PREP(DATA_HWIRQ_MASK, data)); 144 108 } 145 109 146 110 static void xgene_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) 147 111 { 148 112 struct xgene_msi *msi = irq_data_get_irq_chip_data(data); 149 - u32 reg_set = hwirq_to_reg_set(data->hwirq); 150 - u32 group = hwirq_to_group(data->hwirq); 151 - u64 target_addr = msi->msi_addr + (((8 * group) + reg_set) << 16); 113 + u64 target_addr; 114 + u32 frame, msir; 115 + int cpu; 116 + 117 + cpu = cpumask_first(irq_data_get_effective_affinity_mask(data)); 118 + msir = FIELD_GET(MSInRx_HWIRQ_MASK, data->hwirq); 119 + frame = FIELD_PREP(BIT(3), FIELD_GET(BIT(7), data->hwirq)) | cpu; 120 + 121 + target_addr = msi->msi_addr; 122 + target_addr += (FIELD_PREP(MSI_GROUP_MASK, frame) | 123 + FIELD_PREP(MSI_INTR_MASK, msir)); 152 124 153 125 msg->address_hi = upper_32_bits(target_addr); 154 126 msg->address_lo = lower_32_bits(target_addr); 155 - msg->data = hwirq_to_msi_data(data->hwirq); 156 - } 157 - 158 - /* 159 - * X-Gene v1 only has 16 MSI GIC IRQs for 2048 MSI vectors. To maintain 160 - * the expected behaviour of .set_affinity for each MSI interrupt, the 16 161 - * MSI GIC IRQs are statically allocated to 8 X-Gene v1 cores (2 GIC IRQs 162 - * for each core). The MSI vector is moved from 1 MSI GIC IRQ to another 163 - * MSI GIC IRQ to steer its MSI interrupt to correct X-Gene v1 core. As a 164 - * consequence, the total MSI vectors that X-Gene v1 supports will be 165 - * reduced to 256 (2048/8) vectors. 166 - */ 167 - static int hwirq_to_cpu(unsigned long hwirq) 168 - { 169 - return (hwirq % xgene_msi_ctrl.num_cpus); 170 - } 171 - 172 - static unsigned long hwirq_to_canonical_hwirq(unsigned long hwirq) 173 - { 174 - return (hwirq - hwirq_to_cpu(hwirq)); 127 + msg->data = FIELD_GET(DATA_HWIRQ_MASK, data->hwirq); 175 128 } 176 129 177 130 static int xgene_msi_set_affinity(struct irq_data *irqdata, 178 131 const struct cpumask *mask, bool force) 179 132 { 180 133 int target_cpu = cpumask_first(mask); 181 - int curr_cpu; 182 134 183 - curr_cpu = hwirq_to_cpu(irqdata->hwirq); 184 - if (curr_cpu == target_cpu) 185 - return IRQ_SET_MASK_OK_DONE; 135 + irq_data_update_effective_affinity(irqdata, cpumask_of(target_cpu)); 186 136 187 - /* Update MSI number to target the new CPU */ 188 - irqdata->hwirq = hwirq_to_canonical_hwirq(irqdata->hwirq) + target_cpu; 189 - 137 + /* Force the core code to regenerate the message */ 190 138 return IRQ_SET_MASK_OK; 191 139 } 192 140 ··· 167 181 unsigned int nr_irqs, void *args) 168 182 { 169 183 struct xgene_msi *msi = domain->host_data; 170 - int msi_irq; 184 + irq_hw_number_t hwirq; 171 185 172 186 mutex_lock(&msi->bitmap_lock); 173 187 174 - msi_irq = bitmap_find_next_zero_area(msi->bitmap, NR_MSI_VEC, 0, 175 - msi->num_cpus, 0); 176 - if (msi_irq < NR_MSI_VEC) 177 - bitmap_set(msi->bitmap, msi_irq, msi->num_cpus); 178 - else 179 - msi_irq = -ENOSPC; 188 + hwirq = find_first_zero_bit(msi->bitmap, NR_MSI_VEC); 189 + if (hwirq < NR_MSI_VEC) 190 + set_bit(hwirq, msi->bitmap); 180 191 181 192 mutex_unlock(&msi->bitmap_lock); 182 193 183 - if (msi_irq < 0) 184 - return msi_irq; 194 + if (hwirq >= NR_MSI_VEC) 195 + return -ENOSPC; 185 196 186 - irq_domain_set_info(domain, virq, msi_irq, 197 + irq_domain_set_info(domain, virq, hwirq, 187 198 &xgene_msi_bottom_irq_chip, domain->host_data, 188 199 handle_simple_irq, NULL, NULL); 200 + irqd_set_resend_when_in_progress(irq_get_irq_data(virq)); 189 201 190 202 return 0; 191 203 } ··· 193 209 { 194 210 struct irq_data *d = irq_domain_get_irq_data(domain, virq); 195 211 struct xgene_msi *msi = irq_data_get_irq_chip_data(d); 196 - u32 hwirq; 197 212 198 213 mutex_lock(&msi->bitmap_lock); 199 214 200 - hwirq = hwirq_to_canonical_hwirq(d->hwirq); 201 - bitmap_clear(msi->bitmap, hwirq, msi->num_cpus); 215 + clear_bit(d->hwirq, msi->bitmap); 202 216 203 217 mutex_unlock(&msi->bitmap_lock); 204 218 ··· 217 235 .init_dev_msi_info = msi_lib_init_dev_msi_info, 218 236 }; 219 237 220 - static int xgene_allocate_domains(struct xgene_msi *msi) 238 + static int xgene_allocate_domains(struct device_node *node, 239 + struct xgene_msi *msi) 221 240 { 222 241 struct irq_domain_info info = { 223 - .fwnode = of_fwnode_handle(msi->node), 242 + .fwnode = of_fwnode_handle(node), 224 243 .ops = &xgene_msi_domain_ops, 225 244 .size = NR_MSI_VEC, 226 245 .host_data = msi, ··· 231 248 return msi->inner_domain ? 0 : -ENOMEM; 232 249 } 233 250 234 - static void xgene_free_domains(struct xgene_msi *msi) 251 + static int xgene_msi_init_allocator(struct device *dev) 235 252 { 236 - if (msi->inner_domain) 237 - irq_domain_remove(msi->inner_domain); 238 - } 239 - 240 - static int xgene_msi_init_allocator(struct xgene_msi *xgene_msi) 241 - { 242 - xgene_msi->bitmap = bitmap_zalloc(NR_MSI_VEC, GFP_KERNEL); 243 - if (!xgene_msi->bitmap) 253 + xgene_msi_ctrl->bitmap = devm_bitmap_zalloc(dev, NR_MSI_VEC, GFP_KERNEL); 254 + if (!xgene_msi_ctrl->bitmap) 244 255 return -ENOMEM; 245 256 246 - mutex_init(&xgene_msi->bitmap_lock); 247 - 248 - xgene_msi->msi_groups = kcalloc(NR_HW_IRQS, 249 - sizeof(struct xgene_msi_group), 250 - GFP_KERNEL); 251 - if (!xgene_msi->msi_groups) 252 - return -ENOMEM; 257 + mutex_init(&xgene_msi_ctrl->bitmap_lock); 253 258 254 259 return 0; 255 260 } 256 261 257 262 static void xgene_msi_isr(struct irq_desc *desc) 258 263 { 264 + unsigned int *irqp = irq_desc_get_handler_data(desc); 259 265 struct irq_chip *chip = irq_desc_get_chip(desc); 260 - struct xgene_msi_group *msi_groups; 261 - struct xgene_msi *xgene_msi; 262 - int msir_index, msir_val, hw_irq, ret; 263 - u32 intr_index, grp_select, msi_grp; 266 + struct xgene_msi *xgene_msi = xgene_msi_ctrl; 267 + unsigned long grp_pending; 268 + int msir_idx; 269 + u32 msi_grp; 264 270 265 271 chained_irq_enter(chip, desc); 266 272 267 - msi_groups = irq_desc_get_handler_data(desc); 268 - xgene_msi = msi_groups->msi; 269 - msi_grp = msi_groups->msi_grp; 273 + msi_grp = irqp - xgene_msi->gic_irq; 270 274 271 - /* 272 - * MSIINTn (n is 0..F) indicates if there is a pending MSI interrupt 273 - * If bit x of this register is set (x is 0..7), one or more interrupts 274 - * corresponding to MSInIRx is set. 275 - */ 276 - grp_select = xgene_msi_int_read(xgene_msi, msi_grp); 277 - while (grp_select) { 278 - msir_index = ffs(grp_select) - 1; 279 - /* 280 - * Calculate MSInIRx address to read to check for interrupts 281 - * (refer to termination address and data assignment 282 - * described in xgene_compose_msi_msg() ) 283 - */ 284 - msir_val = xgene_msi_ir_read(xgene_msi, msi_grp, msir_index); 285 - while (msir_val) { 286 - intr_index = ffs(msir_val) - 1; 287 - /* 288 - * Calculate MSI vector number (refer to the termination 289 - * address and data assignment described in 290 - * xgene_compose_msi_msg function) 291 - */ 292 - hw_irq = (((msir_index * IRQS_PER_IDX) + intr_index) * 293 - NR_HW_IRQS) + msi_grp; 294 - /* 295 - * As we have multiple hw_irq that maps to single MSI, 296 - * always look up the virq using the hw_irq as seen from 297 - * CPU0 298 - */ 299 - hw_irq = hwirq_to_canonical_hwirq(hw_irq); 300 - ret = generic_handle_domain_irq(xgene_msi->inner_domain, hw_irq); 275 + grp_pending = xgene_msi_int_read(xgene_msi, msi_grp); 276 + 277 + for_each_set_bit(msir_idx, &grp_pending, IDX_PER_GROUP) { 278 + unsigned long msir; 279 + int intr_idx; 280 + 281 + msir = xgene_msi_ir_read(xgene_msi, msi_grp, msir_idx); 282 + 283 + for_each_set_bit(intr_idx, &msir, IRQS_PER_IDX) { 284 + irq_hw_number_t hwirq; 285 + int ret; 286 + 287 + hwirq = compute_hwirq(msi_grp, msir_idx, intr_idx); 288 + ret = generic_handle_domain_irq(xgene_msi->inner_domain, 289 + hwirq); 301 290 WARN_ON_ONCE(ret); 302 - msir_val &= ~(1 << intr_index); 303 - } 304 - grp_select &= ~(1 << msir_index); 305 - 306 - if (!grp_select) { 307 - /* 308 - * We handled all interrupts happened in this group, 309 - * resample this group MSI_INTx register in case 310 - * something else has been made pending in the meantime 311 - */ 312 - grp_select = xgene_msi_int_read(xgene_msi, msi_grp); 313 291 } 314 292 } 315 293 316 294 chained_irq_exit(chip, desc); 317 295 } 318 296 319 - static enum cpuhp_state pci_xgene_online; 320 - 321 297 static void xgene_msi_remove(struct platform_device *pdev) 322 298 { 323 - struct xgene_msi *msi = platform_get_drvdata(pdev); 299 + for (int i = 0; i < NR_HW_IRQS; i++) { 300 + unsigned int irq = xgene_msi_ctrl->gic_irq[i]; 301 + if (!irq) 302 + continue; 303 + irq_set_chained_handler_and_data(irq, NULL, NULL); 304 + } 324 305 325 - if (pci_xgene_online) 326 - cpuhp_remove_state(pci_xgene_online); 327 - cpuhp_remove_state(CPUHP_PCI_XGENE_DEAD); 328 - 329 - kfree(msi->msi_groups); 330 - 331 - bitmap_free(msi->bitmap); 332 - msi->bitmap = NULL; 333 - 334 - xgene_free_domains(msi); 306 + if (xgene_msi_ctrl->inner_domain) 307 + irq_domain_remove(xgene_msi_ctrl->inner_domain); 335 308 } 336 309 337 - static int xgene_msi_hwirq_alloc(unsigned int cpu) 310 + static int xgene_msi_handler_setup(struct platform_device *pdev) 338 311 { 339 - struct xgene_msi *msi = &xgene_msi_ctrl; 340 - struct xgene_msi_group *msi_group; 341 - cpumask_var_t mask; 312 + struct xgene_msi *xgene_msi = xgene_msi_ctrl; 342 313 int i; 343 - int err; 344 314 345 - for (i = cpu; i < NR_HW_IRQS; i += msi->num_cpus) { 346 - msi_group = &msi->msi_groups[i]; 347 - if (!msi_group->gic_irq) 348 - continue; 315 + for (i = 0; i < NR_HW_IRQS; i++) { 316 + u32 msi_val; 317 + int irq, err; 349 318 350 - irq_set_chained_handler_and_data(msi_group->gic_irq, 351 - xgene_msi_isr, msi_group); 319 + /* 320 + * MSInIRx registers are read-to-clear; before registering 321 + * interrupt handlers, read all of them to clear spurious 322 + * interrupts that may occur before the driver is probed. 323 + */ 324 + for (int msi_idx = 0; msi_idx < IDX_PER_GROUP; msi_idx++) 325 + xgene_msi_ir_read(xgene_msi, i, msi_idx); 326 + 327 + /* Read MSIINTn to confirm */ 328 + msi_val = xgene_msi_int_read(xgene_msi, i); 329 + if (msi_val) { 330 + dev_err(&pdev->dev, "Failed to clear spurious IRQ\n"); 331 + return EINVAL; 332 + } 333 + 334 + irq = platform_get_irq(pdev, i); 335 + if (irq < 0) 336 + return irq; 337 + 338 + xgene_msi->gic_irq[i] = irq; 352 339 353 340 /* 354 341 * Statically allocate MSI GIC IRQs to each CPU core. 355 342 * With 8-core X-Gene v1, 2 MSI GIC IRQs are allocated 356 343 * to each core. 357 344 */ 358 - if (alloc_cpumask_var(&mask, GFP_KERNEL)) { 359 - cpumask_clear(mask); 360 - cpumask_set_cpu(cpu, mask); 361 - err = irq_set_affinity(msi_group->gic_irq, mask); 362 - if (err) 363 - pr_err("failed to set affinity for GIC IRQ"); 364 - free_cpumask_var(mask); 365 - } else { 366 - pr_err("failed to alloc CPU mask for affinity\n"); 367 - err = -EINVAL; 368 - } 369 - 345 + irq_set_status_flags(irq, IRQ_NO_BALANCING); 346 + err = irq_set_affinity(irq, cpumask_of(i % num_possible_cpus())); 370 347 if (err) { 371 - irq_set_chained_handler_and_data(msi_group->gic_irq, 372 - NULL, NULL); 348 + pr_err("failed to set affinity for GIC IRQ"); 373 349 return err; 374 350 } 351 + 352 + irq_set_chained_handler_and_data(irq, xgene_msi_isr, 353 + &xgene_msi_ctrl->gic_irq[i]); 375 354 } 376 355 377 - return 0; 378 - } 379 - 380 - static int xgene_msi_hwirq_free(unsigned int cpu) 381 - { 382 - struct xgene_msi *msi = &xgene_msi_ctrl; 383 - struct xgene_msi_group *msi_group; 384 - int i; 385 - 386 - for (i = cpu; i < NR_HW_IRQS; i += msi->num_cpus) { 387 - msi_group = &msi->msi_groups[i]; 388 - if (!msi_group->gic_irq) 389 - continue; 390 - 391 - irq_set_chained_handler_and_data(msi_group->gic_irq, NULL, 392 - NULL); 393 - } 394 356 return 0; 395 357 } 396 358 ··· 347 419 static int xgene_msi_probe(struct platform_device *pdev) 348 420 { 349 421 struct resource *res; 350 - int rc, irq_index; 351 422 struct xgene_msi *xgene_msi; 352 - int virt_msir; 353 - u32 msi_val, msi_idx; 423 + int rc; 354 424 355 - xgene_msi = &xgene_msi_ctrl; 425 + xgene_msi_ctrl = devm_kzalloc(&pdev->dev, sizeof(*xgene_msi_ctrl), 426 + GFP_KERNEL); 427 + if (!xgene_msi_ctrl) 428 + return -ENOMEM; 356 429 357 - platform_set_drvdata(pdev, xgene_msi); 430 + xgene_msi = xgene_msi_ctrl; 358 431 359 432 xgene_msi->msi_regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 360 433 if (IS_ERR(xgene_msi->msi_regs)) { ··· 363 434 goto error; 364 435 } 365 436 xgene_msi->msi_addr = res->start; 366 - xgene_msi->node = pdev->dev.of_node; 367 - xgene_msi->num_cpus = num_possible_cpus(); 368 437 369 - rc = xgene_msi_init_allocator(xgene_msi); 438 + rc = xgene_msi_init_allocator(&pdev->dev); 370 439 if (rc) { 371 440 dev_err(&pdev->dev, "Error allocating MSI bitmap\n"); 372 441 goto error; 373 442 } 374 443 375 - rc = xgene_allocate_domains(xgene_msi); 444 + rc = xgene_allocate_domains(dev_of_node(&pdev->dev), xgene_msi); 376 445 if (rc) { 377 446 dev_err(&pdev->dev, "Failed to allocate MSI domain\n"); 378 447 goto error; 379 448 } 380 449 381 - for (irq_index = 0; irq_index < NR_HW_IRQS; irq_index++) { 382 - virt_msir = platform_get_irq(pdev, irq_index); 383 - if (virt_msir < 0) { 384 - rc = virt_msir; 385 - goto error; 386 - } 387 - xgene_msi->msi_groups[irq_index].gic_irq = virt_msir; 388 - xgene_msi->msi_groups[irq_index].msi_grp = irq_index; 389 - xgene_msi->msi_groups[irq_index].msi = xgene_msi; 390 - } 391 - 392 - /* 393 - * MSInIRx registers are read-to-clear; before registering 394 - * interrupt handlers, read all of them to clear spurious 395 - * interrupts that may occur before the driver is probed. 396 - */ 397 - for (irq_index = 0; irq_index < NR_HW_IRQS; irq_index++) { 398 - for (msi_idx = 0; msi_idx < IDX_PER_GROUP; msi_idx++) 399 - xgene_msi_ir_read(xgene_msi, irq_index, msi_idx); 400 - 401 - /* Read MSIINTn to confirm */ 402 - msi_val = xgene_msi_int_read(xgene_msi, irq_index); 403 - if (msi_val) { 404 - dev_err(&pdev->dev, "Failed to clear spurious IRQ\n"); 405 - rc = -EINVAL; 406 - goto error; 407 - } 408 - } 409 - 410 - rc = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "pci/xgene:online", 411 - xgene_msi_hwirq_alloc, NULL); 412 - if (rc < 0) 413 - goto err_cpuhp; 414 - pci_xgene_online = rc; 415 - rc = cpuhp_setup_state(CPUHP_PCI_XGENE_DEAD, "pci/xgene:dead", NULL, 416 - xgene_msi_hwirq_free); 450 + rc = xgene_msi_handler_setup(pdev); 417 451 if (rc) 418 - goto err_cpuhp; 452 + goto error; 419 453 420 454 dev_info(&pdev->dev, "APM X-Gene PCIe MSI driver loaded\n"); 421 455 422 456 return 0; 423 - 424 - err_cpuhp: 425 - dev_err(&pdev->dev, "failed to add CPU MSI notifier\n"); 426 457 error: 427 458 xgene_msi_remove(pdev); 428 459 return rc; ··· 396 507 .probe = xgene_msi_probe, 397 508 .remove = xgene_msi_remove, 398 509 }; 399 - 400 - static int __init xgene_pcie_msi_init(void) 401 - { 402 - return platform_driver_register(&xgene_msi_driver); 403 - } 404 - subsys_initcall(xgene_pcie_msi_init); 510 + builtin_platform_driver(xgene_msi_driver);
+24 -9
drivers/pci/controller/pci-xgene.c
··· 12 12 #include <linux/jiffies.h> 13 13 #include <linux/memblock.h> 14 14 #include <linux/init.h> 15 + #include <linux/irqdomain.h> 15 16 #include <linux/of.h> 16 17 #include <linux/of_address.h> 17 18 #include <linux/of_pci.h> ··· 54 53 #define XGENE_V1_PCI_EXP_CAP 0x40 55 54 56 55 /* PCIe IP version */ 57 - #define XGENE_PCIE_IP_VER_UNKN 0 58 56 #define XGENE_PCIE_IP_VER_1 1 59 57 #define XGENE_PCIE_IP_VER_2 2 60 58 61 - #if defined(CONFIG_PCI_XGENE) || (defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)) 62 59 struct xgene_pcie { 63 60 struct device_node *node; 64 61 struct device *dev; ··· 187 188 188 189 return PCIBIOS_SUCCESSFUL; 189 190 } 190 - #endif 191 191 192 192 #if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS) 193 193 static int xgene_get_csr_resource(struct acpi_device *adev, ··· 277 279 }; 278 280 #endif 279 281 280 - #if defined(CONFIG_PCI_XGENE) 281 282 static u64 xgene_pcie_set_ib_mask(struct xgene_pcie *port, u32 addr, 282 283 u32 flags, u64 size) 283 284 { ··· 591 594 .write = pci_generic_config_write32, 592 595 }; 593 596 597 + static bool xgene_check_pcie_msi_ready(void) 598 + { 599 + struct device_node *np; 600 + struct irq_domain *d; 601 + 602 + if (!IS_ENABLED(CONFIG_PCI_XGENE_MSI)) 603 + return true; 604 + 605 + np = of_find_compatible_node(NULL, NULL, "apm,xgene1-msi"); 606 + if (!np) 607 + return true; 608 + 609 + d = irq_find_matching_host(np, DOMAIN_BUS_PCI_MSI); 610 + of_node_put(np); 611 + 612 + return d && irq_domain_is_msi_parent(d); 613 + } 614 + 594 615 static int xgene_pcie_probe(struct platform_device *pdev) 595 616 { 596 617 struct device *dev = &pdev->dev; ··· 616 601 struct xgene_pcie *port; 617 602 struct pci_host_bridge *bridge; 618 603 int ret; 604 + 605 + if (!xgene_check_pcie_msi_ready()) 606 + return dev_err_probe(&pdev->dev, -EPROBE_DEFER, 607 + "MSI driver not ready\n"); 619 608 620 609 bridge = devm_pci_alloc_host_bridge(dev, sizeof(*port)); 621 610 if (!bridge) ··· 629 610 630 611 port->node = of_node_get(dn); 631 612 port->dev = dev; 632 - 633 - port->version = XGENE_PCIE_IP_VER_UNKN; 634 - if (of_device_is_compatible(port->node, "apm,xgene-pcie")) 635 - port->version = XGENE_PCIE_IP_VER_1; 613 + port->version = XGENE_PCIE_IP_VER_1; 636 614 637 615 ret = xgene_pcie_map_reg(port, pdev); 638 616 if (ret) ··· 663 647 .probe = xgene_pcie_probe, 664 648 }; 665 649 builtin_platform_driver(xgene_pcie_driver); 666 - #endif
+20 -23
drivers/pci/controller/pcie-altera-msi.c
··· 9 9 10 10 #include <linux/interrupt.h> 11 11 #include <linux/irqchip/chained_irq.h> 12 + #include <linux/irqchip/irq-msi-lib.h> 12 13 #include <linux/irqdomain.h> 13 14 #include <linux/init.h> 14 15 #include <linux/module.h> ··· 30 29 DECLARE_BITMAP(used, MAX_MSI_VECTORS); 31 30 struct mutex lock; /* protect "used" bitmap */ 32 31 struct platform_device *pdev; 33 - struct irq_domain *msi_domain; 34 32 struct irq_domain *inner_domain; 35 33 void __iomem *csr_base; 36 34 void __iomem *vector_base; ··· 74 74 chained_irq_exit(chip, desc); 75 75 } 76 76 77 - static struct irq_chip altera_msi_irq_chip = { 78 - .name = "Altera PCIe MSI", 79 - .irq_mask = pci_msi_mask_irq, 80 - .irq_unmask = pci_msi_unmask_irq, 81 - }; 77 + #define ALTERA_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ 78 + MSI_FLAG_USE_DEF_CHIP_OPS | \ 79 + MSI_FLAG_NO_AFFINITY) 82 80 83 - static struct msi_domain_info altera_msi_domain_info = { 84 - .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | 85 - MSI_FLAG_NO_AFFINITY | MSI_FLAG_PCI_MSIX, 86 - .chip = &altera_msi_irq_chip, 87 - }; 81 + #define ALTERA_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \ 82 + MSI_FLAG_PCI_MSIX) 88 83 84 + static const struct msi_parent_ops altera_msi_parent_ops = { 85 + .required_flags = ALTERA_MSI_FLAGS_REQUIRED, 86 + .supported_flags = ALTERA_MSI_FLAGS_SUPPORTED, 87 + .bus_select_token = DOMAIN_BUS_PCI_MSI, 88 + .prefix = "Altera-", 89 + .init_dev_msi_info = msi_lib_init_dev_msi_info, 90 + }; 89 91 static void altera_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) 90 92 { 91 93 struct altera_msi *msi = irq_data_get_irq_chip_data(data); ··· 166 164 167 165 static int altera_allocate_domains(struct altera_msi *msi) 168 166 { 169 - struct fwnode_handle *fwnode = of_fwnode_handle(msi->pdev->dev.of_node); 167 + struct irq_domain_info info = { 168 + .fwnode = dev_fwnode(&msi->pdev->dev), 169 + .ops = &msi_domain_ops, 170 + .host_data = msi, 171 + .size = msi->num_of_vectors, 172 + }; 170 173 171 - msi->inner_domain = irq_domain_create_linear(NULL, msi->num_of_vectors, 172 - &msi_domain_ops, msi); 174 + msi->inner_domain = msi_create_parent_irq_domain(&info, &altera_msi_parent_ops); 173 175 if (!msi->inner_domain) { 174 - dev_err(&msi->pdev->dev, "failed to create IRQ domain\n"); 175 - return -ENOMEM; 176 - } 177 - 178 - msi->msi_domain = pci_msi_create_irq_domain(fwnode, 179 - &altera_msi_domain_info, msi->inner_domain); 180 - if (!msi->msi_domain) { 181 176 dev_err(&msi->pdev->dev, "failed to create MSI domain\n"); 182 - irq_domain_remove(msi->inner_domain); 183 177 return -ENOMEM; 184 178 } 185 179 ··· 184 186 185 187 static void altera_free_domains(struct altera_msi *msi) 186 188 { 187 - irq_domain_remove(msi->msi_domain); 188 189 irq_domain_remove(msi->inner_domain); 189 190 } 190 191
+1 -2
drivers/pci/controller/pcie-altera.c
··· 852 852 static int altera_pcie_init_irq_domain(struct altera_pcie *pcie) 853 853 { 854 854 struct device *dev = &pcie->pdev->dev; 855 - struct device_node *node = dev->of_node; 856 855 857 856 /* Setup INTx */ 858 - pcie->irq_domain = irq_domain_create_linear(of_fwnode_handle(node), PCI_NUM_INTX, 857 + pcie->irq_domain = irq_domain_create_linear(dev_fwnode(dev), PCI_NUM_INTX, 859 858 &intx_domain_ops, pcie); 860 859 if (!pcie->irq_domain) { 861 860 dev_err(dev, "Failed to get a INTx IRQ domain\n");
+50 -30
drivers/pci/controller/pcie-brcmstb.c
··· 12 12 #include <linux/iopoll.h> 13 13 #include <linux/ioport.h> 14 14 #include <linux/irqchip/chained_irq.h> 15 + #include <linux/irqchip/irq-msi-lib.h> 15 16 #include <linux/irqdomain.h> 16 17 #include <linux/kernel.h> 17 18 #include <linux/list.h> ··· 47 46 #define PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK 0xffffff 48 47 49 48 #define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY 0x04dc 49 + #define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_MAX_LINK_WIDTH_MASK 0x1f0 50 50 #define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK 0xc00 51 51 52 52 #define PCIE_RC_CFG_PRIV1_ROOT_CAP 0x4f8 ··· 56 54 #define PCIE_RC_DL_MDIO_ADDR 0x1100 57 55 #define PCIE_RC_DL_MDIO_WR_DATA 0x1104 58 56 #define PCIE_RC_DL_MDIO_RD_DATA 0x1108 57 + 58 + #define PCIE_RC_PL_REG_PHY_CTL_1 0x1804 59 + #define PCIE_RC_PL_REG_PHY_CTL_1_REG_P2_POWERDOWN_ENA_NOSYNC_MASK 0x8 59 60 60 61 #define PCIE_RC_PL_PHY_CTL_15 0x184c 61 62 #define PCIE_RC_PL_PHY_CTL_15_DIS_PLL_PD_MASK 0x400000 ··· 270 265 struct device *dev; 271 266 void __iomem *base; 272 267 struct device_node *np; 273 - struct irq_domain *msi_domain; 274 268 struct irq_domain *inner_domain; 275 269 struct mutex lock; /* guards the alloc/free operations */ 276 270 u64 target_addr; ··· 469 465 writel(tmp, pcie->base + PCIE_MEM_WIN0_LIMIT_HI(win)); 470 466 } 471 467 472 - static struct irq_chip brcm_msi_irq_chip = { 473 - .name = "BRCM STB PCIe MSI", 474 - .irq_ack = irq_chip_ack_parent, 475 - .irq_mask = pci_msi_mask_irq, 476 - .irq_unmask = pci_msi_unmask_irq, 477 - }; 468 + #define BRCM_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ 469 + MSI_FLAG_USE_DEF_CHIP_OPS | \ 470 + MSI_FLAG_NO_AFFINITY) 478 471 479 - static struct msi_domain_info brcm_msi_domain_info = { 480 - .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | 481 - MSI_FLAG_NO_AFFINITY | MSI_FLAG_MULTI_PCI_MSI, 482 - .chip = &brcm_msi_irq_chip, 472 + #define BRCM_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \ 473 + MSI_FLAG_MULTI_PCI_MSI) 474 + 475 + static const struct msi_parent_ops brcm_msi_parent_ops = { 476 + .required_flags = BRCM_MSI_FLAGS_REQUIRED, 477 + .supported_flags = BRCM_MSI_FLAGS_SUPPORTED, 478 + .bus_select_token = DOMAIN_BUS_PCI_MSI, 479 + .chip_flags = MSI_CHIP_FLAG_SET_ACK, 480 + .prefix = "BRCM-", 481 + .init_dev_msi_info = msi_lib_init_dev_msi_info, 483 482 }; 484 483 485 484 static void brcm_pcie_msi_isr(struct irq_desc *desc) ··· 588 581 589 582 static int brcm_allocate_domains(struct brcm_msi *msi) 590 583 { 591 - struct fwnode_handle *fwnode = of_fwnode_handle(msi->np); 592 584 struct device *dev = msi->dev; 593 585 594 - msi->inner_domain = irq_domain_create_linear(NULL, msi->nr, &msi_domain_ops, msi); 595 - if (!msi->inner_domain) { 596 - dev_err(dev, "failed to create IRQ domain\n"); 597 - return -ENOMEM; 598 - } 586 + struct irq_domain_info info = { 587 + .fwnode = of_fwnode_handle(msi->np), 588 + .ops = &msi_domain_ops, 589 + .host_data = msi, 590 + .size = msi->nr, 591 + }; 599 592 600 - msi->msi_domain = pci_msi_create_irq_domain(fwnode, 601 - &brcm_msi_domain_info, 602 - msi->inner_domain); 603 - if (!msi->msi_domain) { 593 + msi->inner_domain = msi_create_parent_irq_domain(&info, &brcm_msi_parent_ops); 594 + if (!msi->inner_domain) { 604 595 dev_err(dev, "failed to create MSI domain\n"); 605 - irq_domain_remove(msi->inner_domain); 606 596 return -ENOMEM; 607 597 } 608 598 ··· 608 604 609 605 static void brcm_free_domains(struct brcm_msi *msi) 610 606 { 611 - irq_domain_remove(msi->msi_domain); 612 607 irq_domain_remove(msi->inner_domain); 613 608 } 614 609 ··· 973 970 * 974 971 * The PCIe host controller by design must set the inbound viewport to 975 972 * be a contiguous arrangement of all of the system's memory. In 976 - * addition, its size mut be a power of two. To further complicate 973 + * addition, its size must be a power of two. To further complicate 977 974 * matters, the viewport must start on a pcie-address that is aligned 978 975 * on a multiple of its size. If a portion of the viewport does not 979 976 * represent system memory -- e.g. 3GB of memory requires a 4GB ··· 1075 1072 void __iomem *base = pcie->base; 1076 1073 struct pci_host_bridge *bridge; 1077 1074 struct resource_entry *entry; 1078 - u32 tmp, burst, aspm_support; 1075 + u32 tmp, burst, aspm_support, num_lanes, num_lanes_cap; 1079 1076 u8 num_out_wins = 0; 1080 1077 int num_inbound_wins = 0; 1081 1078 int memc, ret; ··· 1182 1179 u32p_replace_bits(&tmp, aspm_support, 1183 1180 PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK); 1184 1181 writel(tmp, base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY); 1182 + 1183 + /* 'tmp' still holds the contents of PRIV1_LINK_CAPABILITY */ 1184 + num_lanes_cap = u32_get_bits(tmp, PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_MAX_LINK_WIDTH_MASK); 1185 + num_lanes = 0; 1186 + 1187 + /* 1188 + * Use hardware negotiated Max Link Width value by default. If the 1189 + * "num-lanes" DT property is present, assume that the chip's default 1190 + * link width capability information is incorrect/undesired and use the 1191 + * specified value instead. 1192 + */ 1193 + if (!of_property_read_u32(pcie->np, "num-lanes", &num_lanes) && 1194 + num_lanes && num_lanes <= 4 && num_lanes_cap != num_lanes) { 1195 + u32p_replace_bits(&tmp, num_lanes, 1196 + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_MAX_LINK_WIDTH_MASK); 1197 + writel(tmp, base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY); 1198 + tmp = readl(base + PCIE_RC_PL_REG_PHY_CTL_1); 1199 + u32p_replace_bits(&tmp, 1, 1200 + PCIE_RC_PL_REG_PHY_CTL_1_REG_P2_POWERDOWN_ENA_NOSYNC_MASK); 1201 + writel(tmp, base + PCIE_RC_PL_REG_PHY_CTL_1); 1202 + } 1185 1203 1186 1204 /* 1187 1205 * For config space accesses on the RC, show the right class for ··· 1357 1333 if (ret) 1358 1334 return ret; 1359 1335 1360 - /* 1361 - * Wait for 100ms after PERST# deassertion; see PCIe CEM specification 1362 - * sections 2.2, PCIe r5.0, 6.6.1. 1363 - */ 1364 - msleep(100); 1336 + msleep(PCIE_RESET_CONFIG_WAIT_MS); 1365 1337 1366 1338 /* 1367 1339 * Give the RC/EP even more time to wake up, before trying to
+20 -24
drivers/pci/controller/pcie-iproc-msi.c
··· 5 5 6 6 #include <linux/interrupt.h> 7 7 #include <linux/irqchip/chained_irq.h> 8 + #include <linux/irqchip/irq-msi-lib.h> 8 9 #include <linux/irqdomain.h> 9 10 #include <linux/msi.h> 10 11 #include <linux/of_irq.h> ··· 82 81 * @bitmap_lock: lock to protect access to the MSI bitmap 83 82 * @nr_msi_vecs: total number of MSI vectors 84 83 * @inner_domain: inner IRQ domain 85 - * @msi_domain: MSI IRQ domain 86 84 * @nr_eq_region: required number of 4K aligned memory region for MSI event 87 85 * queues 88 86 * @nr_msi_region: required number of 4K aligned address region for MSI posted ··· 101 101 struct mutex bitmap_lock; 102 102 unsigned int nr_msi_vecs; 103 103 struct irq_domain *inner_domain; 104 - struct irq_domain *msi_domain; 105 104 unsigned int nr_eq_region; 106 105 unsigned int nr_msi_region; 107 106 void *eq_cpu; ··· 164 165 return eq * EQ_LEN * sizeof(u32); 165 166 } 166 167 167 - static struct irq_chip iproc_msi_irq_chip = { 168 - .name = "iProc-MSI", 169 - }; 168 + #define IPROC_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ 169 + MSI_FLAG_USE_DEF_CHIP_OPS) 170 + #define IPROC_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \ 171 + MSI_FLAG_PCI_MSIX) 170 172 171 - static struct msi_domain_info iproc_msi_domain_info = { 172 - .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | 173 - MSI_FLAG_PCI_MSIX, 174 - .chip = &iproc_msi_irq_chip, 173 + static struct msi_parent_ops iproc_msi_parent_ops = { 174 + .required_flags = IPROC_MSI_FLAGS_REQUIRED, 175 + .supported_flags = IPROC_MSI_FLAGS_SUPPORTED, 176 + .bus_select_token = DOMAIN_BUS_PCI_MSI, 177 + .prefix = "iProc-", 178 + .init_dev_msi_info = msi_lib_init_dev_msi_info, 175 179 }; 176 - 177 180 /* 178 181 * In iProc PCIe core, each MSI group is serviced by a GIC interrupt and a 179 182 * dedicated event queue. Each MSI group can support up to 64 MSI vectors. ··· 447 446 static int iproc_msi_alloc_domains(struct device_node *node, 448 447 struct iproc_msi *msi) 449 448 { 450 - msi->inner_domain = irq_domain_create_linear(NULL, msi->nr_msi_vecs, 451 - &msi_domain_ops, msi); 449 + struct irq_domain_info info = { 450 + .fwnode = of_fwnode_handle(node), 451 + .ops = &msi_domain_ops, 452 + .host_data = msi, 453 + .size = msi->nr_msi_vecs, 454 + }; 455 + 456 + msi->inner_domain = msi_create_parent_irq_domain(&info, &iproc_msi_parent_ops); 452 457 if (!msi->inner_domain) 453 458 return -ENOMEM; 454 - 455 - msi->msi_domain = pci_msi_create_irq_domain(of_fwnode_handle(node), 456 - &iproc_msi_domain_info, 457 - msi->inner_domain); 458 - if (!msi->msi_domain) { 459 - irq_domain_remove(msi->inner_domain); 460 - return -ENOMEM; 461 - } 462 459 463 460 return 0; 464 461 } 465 462 466 463 static void iproc_msi_free_domains(struct iproc_msi *msi) 467 464 { 468 - if (msi->msi_domain) 469 - irq_domain_remove(msi->msi_domain); 470 - 471 465 if (msi->inner_domain) 472 466 irq_domain_remove(msi->inner_domain); 473 467 } ··· 538 542 msi->nr_cpus = num_possible_cpus(); 539 543 540 544 if (msi->nr_cpus == 1) 541 - iproc_msi_domain_info.flags |= MSI_FLAG_MULTI_PCI_MSI; 545 + iproc_msi_parent_ops.supported_flags |= MSI_FLAG_MULTI_PCI_MSI; 542 546 543 547 msi->nr_irqs = of_irq_count(node); 544 548 if (!msi->nr_irqs) {
+23 -41
drivers/pci/controller/pcie-mediatek-gen3.c
··· 12 12 #include <linux/delay.h> 13 13 #include <linux/iopoll.h> 14 14 #include <linux/irq.h> 15 + #include <linux/irqchip/irq-msi-lib.h> 15 16 #include <linux/irqchip/chained_irq.h> 16 17 #include <linux/irqdomain.h> 17 18 #include <linux/kernel.h> ··· 188 187 * @saved_irq_state: IRQ enable state saved at suspend time 189 188 * @irq_lock: lock protecting IRQ register access 190 189 * @intx_domain: legacy INTx IRQ domain 191 - * @msi_domain: MSI IRQ domain 192 190 * @msi_bottom_domain: MSI IRQ bottom domain 193 191 * @msi_sets: MSI sets information 194 192 * @lock: lock protecting IRQ bit map ··· 210 210 u32 saved_irq_state; 211 211 raw_spinlock_t irq_lock; 212 212 struct irq_domain *intx_domain; 213 - struct irq_domain *msi_domain; 214 213 struct irq_domain *msi_bottom_domain; 215 214 struct mtk_msi_set msi_sets[PCIE_MSI_SET_NUM]; 216 215 struct mutex lock; ··· 525 526 return 0; 526 527 } 527 528 528 - static void mtk_pcie_msi_irq_mask(struct irq_data *data) 529 - { 530 - pci_msi_mask_irq(data); 531 - irq_chip_mask_parent(data); 532 - } 529 + #define MTK_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ 530 + MSI_FLAG_USE_DEF_CHIP_OPS | \ 531 + MSI_FLAG_NO_AFFINITY | \ 532 + MSI_FLAG_PCI_MSI_MASK_PARENT) 533 533 534 - static void mtk_pcie_msi_irq_unmask(struct irq_data *data) 535 - { 536 - pci_msi_unmask_irq(data); 537 - irq_chip_unmask_parent(data); 538 - } 534 + #define MTK_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \ 535 + MSI_FLAG_PCI_MSIX | \ 536 + MSI_FLAG_MULTI_PCI_MSI) 539 537 540 - static struct irq_chip mtk_msi_irq_chip = { 541 - .irq_ack = irq_chip_ack_parent, 542 - .irq_mask = mtk_pcie_msi_irq_mask, 543 - .irq_unmask = mtk_pcie_msi_irq_unmask, 544 - .name = "MSI", 545 - }; 546 - 547 - static struct msi_domain_info mtk_msi_domain_info = { 548 - .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | 549 - MSI_FLAG_NO_AFFINITY | MSI_FLAG_PCI_MSIX | 550 - MSI_FLAG_MULTI_PCI_MSI, 551 - .chip = &mtk_msi_irq_chip, 538 + static const struct msi_parent_ops mtk_msi_parent_ops = { 539 + .required_flags = MTK_MSI_FLAGS_REQUIRED, 540 + .supported_flags = MTK_MSI_FLAGS_SUPPORTED, 541 + .bus_select_token = DOMAIN_BUS_PCI_MSI, 542 + .chip_flags = MSI_CHIP_FLAG_SET_ACK, 543 + .prefix = "MTK3-", 544 + .init_dev_msi_info = msi_lib_init_dev_msi_info, 552 545 }; 553 546 554 547 static void mtk_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) ··· 747 756 /* Setup MSI */ 748 757 mutex_init(&pcie->lock); 749 758 750 - pcie->msi_bottom_domain = irq_domain_create_linear(of_fwnode_handle(node), 751 - PCIE_MSI_IRQS_NUM, 752 - &mtk_msi_bottom_domain_ops, pcie); 759 + struct irq_domain_info info = { 760 + .fwnode = dev_fwnode(dev), 761 + .ops = &mtk_msi_bottom_domain_ops, 762 + .host_data = pcie, 763 + .size = PCIE_MSI_IRQS_NUM, 764 + }; 765 + 766 + pcie->msi_bottom_domain = msi_create_parent_irq_domain(&info, &mtk_msi_parent_ops); 753 767 if (!pcie->msi_bottom_domain) { 754 768 dev_err(dev, "failed to create MSI bottom domain\n"); 755 769 ret = -ENODEV; 756 770 goto err_msi_bottom_domain; 757 771 } 758 772 759 - pcie->msi_domain = pci_msi_create_irq_domain(dev->fwnode, 760 - &mtk_msi_domain_info, 761 - pcie->msi_bottom_domain); 762 - if (!pcie->msi_domain) { 763 - dev_err(dev, "failed to create MSI domain\n"); 764 - ret = -ENODEV; 765 - goto err_msi_domain; 766 - } 767 - 768 773 of_node_put(intc_node); 769 774 return 0; 770 775 771 - err_msi_domain: 772 - irq_domain_remove(pcie->msi_bottom_domain); 773 776 err_msi_bottom_domain: 774 777 irq_domain_remove(pcie->intx_domain); 775 778 out_put_node: ··· 777 792 778 793 if (pcie->intx_domain) 779 794 irq_domain_remove(pcie->intx_domain); 780 - 781 - if (pcie->msi_domain) 782 - irq_domain_remove(pcie->msi_domain); 783 795 784 796 if (pcie->msi_bottom_domain) 785 797 irq_domain_remove(pcie->msi_bottom_domain);
+22 -26
drivers/pci/controller/pcie-mediatek.c
··· 12 12 #include <linux/iopoll.h> 13 13 #include <linux/irq.h> 14 14 #include <linux/irqchip/chained_irq.h> 15 + #include <linux/irqchip/irq-msi-lib.h> 15 16 #include <linux/irqdomain.h> 16 17 #include <linux/kernel.h> 17 18 #include <linux/mfd/syscon.h> ··· 181 180 * @irq: GIC irq 182 181 * @irq_domain: legacy INTx IRQ domain 183 182 * @inner_domain: inner IRQ domain 184 - * @msi_domain: MSI IRQ domain 185 183 * @lock: protect the msi_irq_in_use bitmap 186 184 * @msi_irq_in_use: bit map for assigned MSI IRQ 187 185 */ ··· 200 200 int irq; 201 201 struct irq_domain *irq_domain; 202 202 struct irq_domain *inner_domain; 203 - struct irq_domain *msi_domain; 204 203 struct mutex lock; 205 204 DECLARE_BITMAP(msi_irq_in_use, MTK_MSI_IRQS_NUM); 206 205 }; ··· 469 470 .free = mtk_pcie_irq_domain_free, 470 471 }; 471 472 472 - static struct irq_chip mtk_msi_irq_chip = { 473 - .name = "MTK PCIe MSI", 474 - .irq_ack = irq_chip_ack_parent, 475 - .irq_mask = pci_msi_mask_irq, 476 - .irq_unmask = pci_msi_unmask_irq, 477 - }; 473 + #define MTK_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ 474 + MSI_FLAG_USE_DEF_CHIP_OPS | \ 475 + MSI_FLAG_NO_AFFINITY) 478 476 479 - static struct msi_domain_info mtk_msi_domain_info = { 480 - .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | 481 - MSI_FLAG_NO_AFFINITY | MSI_FLAG_PCI_MSIX, 482 - .chip = &mtk_msi_irq_chip, 477 + #define MTK_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \ 478 + MSI_FLAG_PCI_MSIX) 479 + 480 + static const struct msi_parent_ops mtk_msi_parent_ops = { 481 + .required_flags = MTK_MSI_FLAGS_REQUIRED, 482 + .supported_flags = MTK_MSI_FLAGS_SUPPORTED, 483 + .bus_select_token = DOMAIN_BUS_PCI_MSI, 484 + .chip_flags = MSI_CHIP_FLAG_SET_ACK, 485 + .prefix = "MTK-", 486 + .init_dev_msi_info = msi_lib_init_dev_msi_info, 483 487 }; 484 488 485 489 static int mtk_pcie_allocate_msi_domains(struct mtk_pcie_port *port) 486 490 { 487 - struct fwnode_handle *fwnode = of_fwnode_handle(port->pcie->dev->of_node); 488 - 489 491 mutex_init(&port->lock); 490 492 491 - port->inner_domain = irq_domain_create_linear(fwnode, MTK_MSI_IRQS_NUM, 492 - &msi_domain_ops, port); 493 + struct irq_domain_info info = { 494 + .fwnode = dev_fwnode(port->pcie->dev), 495 + .ops = &msi_domain_ops, 496 + .host_data = port, 497 + .size = MTK_MSI_IRQS_NUM, 498 + }; 499 + 500 + port->inner_domain = msi_create_parent_irq_domain(&info, &mtk_msi_parent_ops); 493 501 if (!port->inner_domain) { 494 502 dev_err(port->pcie->dev, "failed to create IRQ domain\n"); 495 - return -ENOMEM; 496 - } 497 - 498 - port->msi_domain = pci_msi_create_irq_domain(fwnode, &mtk_msi_domain_info, 499 - port->inner_domain); 500 - if (!port->msi_domain) { 501 - dev_err(port->pcie->dev, "failed to create MSI domain\n"); 502 - irq_domain_remove(port->inner_domain); 503 503 return -ENOMEM; 504 504 } 505 505 ··· 530 532 irq_domain_remove(port->irq_domain); 531 533 532 534 if (IS_ENABLED(CONFIG_PCI_MSI)) { 533 - if (port->msi_domain) 534 - irq_domain_remove(port->msi_domain); 535 535 if (port->inner_domain) 536 536 irq_domain_remove(port->inner_domain); 537 537 }
+24 -44
drivers/pci/controller/pcie-rcar-host.c
··· 17 17 #include <linux/delay.h> 18 18 #include <linux/interrupt.h> 19 19 #include <linux/irq.h> 20 + #include <linux/irqchip/irq-msi-lib.h> 20 21 #include <linux/irqdomain.h> 21 22 #include <linux/kernel.h> 22 23 #include <linux/init.h> ··· 598 597 return IRQ_HANDLED; 599 598 } 600 599 601 - static void rcar_msi_top_irq_ack(struct irq_data *d) 602 - { 603 - irq_chip_ack_parent(d); 604 - } 605 - 606 - static void rcar_msi_top_irq_mask(struct irq_data *d) 607 - { 608 - pci_msi_mask_irq(d); 609 - irq_chip_mask_parent(d); 610 - } 611 - 612 - static void rcar_msi_top_irq_unmask(struct irq_data *d) 613 - { 614 - pci_msi_unmask_irq(d); 615 - irq_chip_unmask_parent(d); 616 - } 617 - 618 - static struct irq_chip rcar_msi_top_chip = { 619 - .name = "PCIe MSI", 620 - .irq_ack = rcar_msi_top_irq_ack, 621 - .irq_mask = rcar_msi_top_irq_mask, 622 - .irq_unmask = rcar_msi_top_irq_unmask, 623 - }; 624 - 625 600 static void rcar_msi_irq_ack(struct irq_data *d) 626 601 { 627 602 struct rcar_msi *msi = irq_data_get_irq_chip_data(d); ··· 695 718 .free = rcar_msi_domain_free, 696 719 }; 697 720 698 - static struct msi_domain_info rcar_msi_info = { 699 - .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | 700 - MSI_FLAG_NO_AFFINITY | MSI_FLAG_MULTI_PCI_MSI, 701 - .chip = &rcar_msi_top_chip, 721 + #define RCAR_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ 722 + MSI_FLAG_USE_DEF_CHIP_OPS | \ 723 + MSI_FLAG_PCI_MSI_MASK_PARENT | \ 724 + MSI_FLAG_NO_AFFINITY) 725 + 726 + #define RCAR_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \ 727 + MSI_FLAG_MULTI_PCI_MSI) 728 + 729 + static const struct msi_parent_ops rcar_msi_parent_ops = { 730 + .required_flags = RCAR_MSI_FLAGS_REQUIRED, 731 + .supported_flags = RCAR_MSI_FLAGS_SUPPORTED, 732 + .bus_select_token = DOMAIN_BUS_PCI_MSI, 733 + .chip_flags = MSI_CHIP_FLAG_SET_ACK, 734 + .prefix = "RCAR-", 735 + .init_dev_msi_info = msi_lib_init_dev_msi_info, 702 736 }; 703 737 704 738 static int rcar_allocate_domains(struct rcar_msi *msi) 705 739 { 706 740 struct rcar_pcie *pcie = &msi_to_host(msi)->pcie; 707 - struct fwnode_handle *fwnode = dev_fwnode(pcie->dev); 708 - struct irq_domain *parent; 741 + struct irq_domain_info info = { 742 + .fwnode = dev_fwnode(pcie->dev), 743 + .ops = &rcar_msi_domain_ops, 744 + .host_data = msi, 745 + .size = INT_PCI_MSI_NR, 746 + }; 709 747 710 - parent = irq_domain_create_linear(fwnode, INT_PCI_MSI_NR, 711 - &rcar_msi_domain_ops, msi); 712 - if (!parent) { 713 - dev_err(pcie->dev, "failed to create IRQ domain\n"); 714 - return -ENOMEM; 715 - } 716 - irq_domain_update_bus_token(parent, DOMAIN_BUS_NEXUS); 717 - 718 - msi->domain = pci_msi_create_irq_domain(fwnode, &rcar_msi_info, parent); 748 + msi->domain = msi_create_parent_irq_domain(&info, &rcar_msi_parent_ops); 719 749 if (!msi->domain) { 720 - dev_err(pcie->dev, "failed to create MSI domain\n"); 721 - irq_domain_remove(parent); 750 + dev_err(pcie->dev, "failed to create IRQ domain\n"); 722 751 return -ENOMEM; 723 752 } 724 753 ··· 733 750 734 751 static void rcar_free_domains(struct rcar_msi *msi) 735 752 { 736 - struct irq_domain *parent = msi->domain->parent; 737 - 738 753 irq_domain_remove(msi->domain); 739 - irq_domain_remove(parent); 740 754 } 741 755 742 756 static int rcar_pcie_enable_msi(struct rcar_pcie_host *host)
+2 -2
drivers/pci/controller/pcie-rockchip-ep.c
··· 518 518 { 519 519 u32 status; 520 520 521 - status = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_LCS); 521 + status = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_BASE + PCI_EXP_LNKCTL); 522 522 status |= PCI_EXP_LNKCTL_RL; 523 - rockchip_pcie_write(rockchip, status, PCIE_EP_CONFIG_LCS); 523 + rockchip_pcie_write(rockchip, status, PCIE_EP_CONFIG_BASE + PCI_EXP_LNKCTL); 524 524 } 525 525 526 526 static bool rockchip_pcie_ep_link_up(struct rockchip_pcie *rockchip)
+30 -34
drivers/pci/controller/pcie-rockchip-host.c
··· 11 11 * ARM PCI Host generic driver. 12 12 */ 13 13 14 + #include <linux/bitfield.h> 14 15 #include <linux/bitrev.h> 15 - #include <linux/clk.h> 16 - #include <linux/delay.h> 17 16 #include <linux/gpio/consumer.h> 18 - #include <linux/init.h> 19 17 #include <linux/interrupt.h> 20 18 #include <linux/iopoll.h> 21 19 #include <linux/irq.h> 22 20 #include <linux/irqchip/chained_irq.h> 23 21 #include <linux/irqdomain.h> 24 - #include <linux/kernel.h> 25 - #include <linux/mfd/syscon.h> 26 22 #include <linux/module.h> 27 23 #include <linux/of.h> 28 24 #include <linux/of_pci.h> 29 - #include <linux/pci.h> 30 - #include <linux/pci_ids.h> 31 25 #include <linux/phy/phy.h> 32 26 #include <linux/platform_device.h> 33 - #include <linux/reset.h> 34 - #include <linux/regmap.h> 35 27 36 28 #include "../pci.h" 37 29 #include "pcie-rockchip.h" ··· 32 40 { 33 41 u32 status; 34 42 35 - status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS); 43 + status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); 36 44 status |= (PCI_EXP_LNKCTL_LBMIE | PCI_EXP_LNKCTL_LABIE); 37 - rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS); 45 + rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); 38 46 } 39 47 40 48 static void rockchip_pcie_clr_bw_int(struct rockchip_pcie *rockchip) 41 49 { 42 50 u32 status; 43 51 44 - status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS); 52 + status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); 45 53 status |= (PCI_EXP_LNKSTA_LBMS | PCI_EXP_LNKSTA_LABS) << 16; 46 - rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS); 54 + rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); 47 55 } 48 56 49 57 static void rockchip_pcie_update_txcredit_mui(struct rockchip_pcie *rockchip) ··· 261 269 scale = 3; /* 0.001x */ 262 270 curr = curr / 1000; /* convert to mA */ 263 271 power = (curr * 3300) / 1000; /* milliwatt */ 264 - while (power > PCIE_RC_CONFIG_DCR_CSPL_LIMIT) { 272 + while (power > FIELD_MAX(PCI_EXP_DEVCAP_PWR_VAL)) { 265 273 if (!scale) { 266 274 dev_warn(rockchip->dev, "invalid power supply\n"); 267 275 return; ··· 270 278 power = power / 10; 271 279 } 272 280 273 - status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_DCR); 274 - status |= (power << PCIE_RC_CONFIG_DCR_CSPL_SHIFT) | 275 - (scale << PCIE_RC_CONFIG_DCR_CPLS_SHIFT); 276 - rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_DCR); 281 + status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_DEVCAP); 282 + status |= FIELD_PREP(PCI_EXP_DEVCAP_PWR_VAL, power); 283 + status |= FIELD_PREP(PCI_EXP_DEVCAP_PWR_SCL, scale); 284 + rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_DEVCAP); 277 285 } 278 286 279 287 /** ··· 301 309 rockchip_pcie_set_power_limit(rockchip); 302 310 303 311 /* Set RC's clock architecture as common clock */ 304 - status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS); 312 + status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); 305 313 status |= PCI_EXP_LNKSTA_SLC << 16; 306 - rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS); 314 + rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); 307 315 308 316 /* Set RC's RCB to 128 */ 309 - status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS); 317 + status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); 310 318 status |= PCI_EXP_LNKCTL_RCB; 311 - rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS); 319 + rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); 312 320 313 321 /* Enable Gen1 training */ 314 322 rockchip_pcie_write(rockchip, PCIE_CLIENT_LINK_TRAIN_ENABLE, ··· 317 325 msleep(PCIE_T_PVPERL_MS); 318 326 gpiod_set_value_cansleep(rockchip->perst_gpio, 1); 319 327 320 - msleep(PCIE_T_RRS_READY_MS); 328 + msleep(PCIE_RESET_CONFIG_WAIT_MS); 321 329 322 330 /* 500ms timeout value should be enough for Gen1/2 training */ 323 331 err = readl_poll_timeout(rockchip->apb_base + PCIE_CLIENT_BASIC_STATUS1, ··· 333 341 * Enable retrain for gen2. This should be configured only after 334 342 * gen1 finished. 335 343 */ 336 - status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS); 344 + status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL2); 345 + status &= ~PCI_EXP_LNKCTL2_TLS; 346 + status |= PCI_EXP_LNKCTL2_TLS_5_0GT; 347 + rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL2); 348 + status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); 337 349 status |= PCI_EXP_LNKCTL_RL; 338 - rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS); 350 + rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); 339 351 340 352 err = readl_poll_timeout(rockchip->apb_base + PCIE_CORE_CTRL, 341 353 status, PCIE_LINK_IS_GEN2(status), 20, ··· 376 380 377 381 /* Clear L0s from RC's link cap */ 378 382 if (of_property_read_bool(dev->of_node, "aspm-no-l0s")) { 379 - status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LINK_CAP); 380 - status &= ~PCIE_RC_CONFIG_LINK_CAP_L0S; 381 - rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LINK_CAP); 383 + status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCAP); 384 + status &= ~PCI_EXP_LNKCAP_ASPM_L0S; 385 + rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCAP); 382 386 } 383 387 384 - status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_DCSR); 385 - status &= ~PCIE_RC_CONFIG_DCSR_MPS_MASK; 386 - status |= PCIE_RC_CONFIG_DCSR_MPS_256; 387 - rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_DCSR); 388 + status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_DEVCTL); 389 + status &= ~PCI_EXP_DEVCTL_PAYLOAD; 390 + status |= PCI_EXP_DEVCTL_PAYLOAD_256B; 391 + rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_DEVCTL); 388 392 389 393 return 0; 390 394 err_power_off_phy: ··· 435 439 dev_dbg(dev, "malformed TLP received from the link\n"); 436 440 437 441 if (sub_reg & PCIE_CORE_INT_UCR) 438 - dev_dbg(dev, "malformed TLP received from the link\n"); 442 + dev_dbg(dev, "Unexpected Completion received from the link\n"); 439 443 440 444 if (sub_reg & PCIE_CORE_INT_FCE) 441 445 dev_dbg(dev, "an error was observed in the flow control advertisements from the other side\n"); ··· 485 489 dev_dbg(dev, "fatal error interrupt received\n"); 486 490 487 491 if (reg & PCIE_CLIENT_INT_NFATAL_ERR) 488 - dev_dbg(dev, "no fatal error interrupt received\n"); 492 + dev_dbg(dev, "non fatal error interrupt received\n"); 489 493 490 494 if (reg & PCIE_CLIENT_INT_CORR_ERR) 491 495 dev_dbg(dev, "correctable error interrupt received\n");
+1 -25
drivers/pci/controller/pcie-rockchip.h
··· 155 155 #define PCIE_EP_CONFIG_DID_VID (PCIE_EP_CONFIG_BASE + 0x00) 156 156 #define PCIE_EP_CONFIG_LCS (PCIE_EP_CONFIG_BASE + 0xd0) 157 157 #define PCIE_RC_CONFIG_RID_CCR (PCIE_RC_CONFIG_BASE + 0x08) 158 - #define PCIE_RC_CONFIG_DCR (PCIE_RC_CONFIG_BASE + 0xc4) 159 - #define PCIE_RC_CONFIG_DCR_CSPL_SHIFT 18 160 - #define PCIE_RC_CONFIG_DCR_CSPL_LIMIT 0xff 161 - #define PCIE_RC_CONFIG_DCR_CPLS_SHIFT 26 162 - #define PCIE_RC_CONFIG_DCSR (PCIE_RC_CONFIG_BASE + 0xc8) 163 - #define PCIE_RC_CONFIG_DCSR_MPS_MASK GENMASK(7, 5) 164 - #define PCIE_RC_CONFIG_DCSR_MPS_256 (0x1 << 5) 165 - #define PCIE_RC_CONFIG_LINK_CAP (PCIE_RC_CONFIG_BASE + 0xcc) 166 - #define PCIE_RC_CONFIG_LINK_CAP_L0S BIT(10) 167 - #define PCIE_RC_CONFIG_LCS (PCIE_RC_CONFIG_BASE + 0xd0) 168 - #define PCIE_EP_CONFIG_LCS (PCIE_EP_CONFIG_BASE + 0xd0) 158 + #define PCIE_RC_CONFIG_CR (PCIE_RC_CONFIG_BASE + 0xc0) 169 159 #define PCIE_RC_CONFIG_L1_SUBSTATE_CTRL2 (PCIE_RC_CONFIG_BASE + 0x90c) 170 160 #define PCIE_RC_CONFIG_THP_CAP (PCIE_RC_CONFIG_BASE + 0x274) 171 161 #define PCIE_RC_CONFIG_THP_CAP_NEXT_MASK GENMASK(31, 20) ··· 205 215 #define RC_REGION_0_TYPE_MASK GENMASK(3, 0) 206 216 #define MAX_AXI_WRAPPER_REGION_NUM 33 207 217 208 - #define ROCKCHIP_PCIE_MSG_ROUTING_TO_RC 0x0 209 - #define ROCKCHIP_PCIE_MSG_ROUTING_VIA_ADDR 0x1 210 - #define ROCKCHIP_PCIE_MSG_ROUTING_VIA_ID 0x2 211 - #define ROCKCHIP_PCIE_MSG_ROUTING_BROADCAST 0x3 212 - #define ROCKCHIP_PCIE_MSG_ROUTING_LOCAL_INTX 0x4 213 - #define ROCKCHIP_PCIE_MSG_ROUTING_PME_ACK 0x5 214 - #define ROCKCHIP_PCIE_MSG_CODE_ASSERT_INTA 0x20 215 - #define ROCKCHIP_PCIE_MSG_CODE_ASSERT_INTB 0x21 216 - #define ROCKCHIP_PCIE_MSG_CODE_ASSERT_INTC 0x22 217 - #define ROCKCHIP_PCIE_MSG_CODE_ASSERT_INTD 0x23 218 - #define ROCKCHIP_PCIE_MSG_CODE_DEASSERT_INTA 0x24 219 - #define ROCKCHIP_PCIE_MSG_CODE_DEASSERT_INTB 0x25 220 - #define ROCKCHIP_PCIE_MSG_CODE_DEASSERT_INTC 0x26 221 - #define ROCKCHIP_PCIE_MSG_CODE_DEASSERT_INTD 0x27 222 218 #define ROCKCHIP_PCIE_MSG_ROUTING_MASK GENMASK(7, 5) 223 219 #define ROCKCHIP_PCIE_MSG_ROUTING(route) \ 224 220 (((route) << 5) & ROCKCHIP_PCIE_MSG_ROUTING_MASK)
+20 -27
drivers/pci/controller/pcie-xilinx-dma-pl.c
··· 7 7 #include <linux/bitfield.h> 8 8 #include <linux/interrupt.h> 9 9 #include <linux/irq.h> 10 + #include <linux/irqchip/irq-msi-lib.h> 10 11 #include <linux/irqdomain.h> 11 12 #include <linux/kernel.h> 12 13 #include <linux/module.h> ··· 91 90 }; 92 91 93 92 struct xilinx_msi { 94 - struct irq_domain *msi_domain; 95 93 unsigned long *bitmap; 96 94 struct irq_domain *dev_domain; 97 95 struct mutex lock; /* Protect bitmap variable */ ··· 373 373 return IRQ_HANDLED; 374 374 } 375 375 376 - static struct irq_chip xilinx_msi_irq_chip = { 377 - .name = "pl_dma:PCIe MSI", 378 - .irq_enable = pci_msi_unmask_irq, 379 - .irq_disable = pci_msi_mask_irq, 380 - .irq_mask = pci_msi_mask_irq, 381 - .irq_unmask = pci_msi_unmask_irq, 382 - }; 376 + #define XILINX_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ 377 + MSI_FLAG_USE_DEF_CHIP_OPS | \ 378 + MSI_FLAG_NO_AFFINITY) 383 379 384 - static struct msi_domain_info xilinx_msi_domain_info = { 385 - .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | 386 - MSI_FLAG_NO_AFFINITY | MSI_FLAG_MULTI_PCI_MSI, 387 - .chip = &xilinx_msi_irq_chip, 388 - }; 380 + #define XILINX_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \ 381 + MSI_FLAG_MULTI_PCI_MSI) 389 382 383 + static const struct msi_parent_ops xilinx_msi_parent_ops = { 384 + .required_flags = XILINX_MSI_FLAGS_REQUIRED, 385 + .supported_flags = XILINX_MSI_FLAGS_SUPPORTED, 386 + .bus_select_token = DOMAIN_BUS_PCI_MSI, 387 + .prefix = "pl_dma-", 388 + .init_dev_msi_info = msi_lib_init_dev_msi_info, 389 + }; 390 390 static void xilinx_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) 391 391 { 392 392 struct pl_dma_pcie *pcie = irq_data_get_irq_chip_data(data); ··· 458 458 irq_domain_remove(msi->dev_domain); 459 459 msi->dev_domain = NULL; 460 460 } 461 - 462 - if (msi->msi_domain) { 463 - irq_domain_remove(msi->msi_domain); 464 - msi->msi_domain = NULL; 465 - } 466 461 } 467 462 468 463 static int xilinx_pl_dma_pcie_init_msi_irq_domain(struct pl_dma_pcie *port) ··· 465 470 struct device *dev = port->dev; 466 471 struct xilinx_msi *msi = &port->msi; 467 472 int size = BITS_TO_LONGS(XILINX_NUM_MSI_IRQS) * sizeof(long); 468 - struct fwnode_handle *fwnode = of_fwnode_handle(port->dev->of_node); 473 + struct irq_domain_info info = { 474 + .fwnode = dev_fwnode(port->dev), 475 + .ops = &dev_msi_domain_ops, 476 + .host_data = port, 477 + .size = XILINX_NUM_MSI_IRQS, 478 + }; 469 479 470 - msi->dev_domain = irq_domain_create_linear(NULL, XILINX_NUM_MSI_IRQS, 471 - &dev_msi_domain_ops, port); 480 + msi->dev_domain = msi_create_parent_irq_domain(&info, &xilinx_msi_parent_ops); 472 481 if (!msi->dev_domain) 473 - goto out; 474 - 475 - msi->msi_domain = pci_msi_create_irq_domain(fwnode, 476 - &xilinx_msi_domain_info, 477 - msi->dev_domain); 478 - if (!msi->msi_domain) 479 482 goto out; 480 483 481 484 mutex_init(&msi->lock);
+22 -22
drivers/pci/controller/pcie-xilinx-nwl.c
··· 10 10 #include <linux/delay.h> 11 11 #include <linux/interrupt.h> 12 12 #include <linux/irq.h> 13 + #include <linux/irqchip/irq-msi-lib.h> 13 14 #include <linux/irqdomain.h> 14 15 #include <linux/kernel.h> 15 16 #include <linux/init.h> ··· 146 145 #define LINK_WAIT_USLEEP_MAX 100000 147 146 148 147 struct nwl_msi { /* MSI information */ 149 - struct irq_domain *msi_domain; 150 148 DECLARE_BITMAP(bitmap, INT_PCI_MSI_NR); 151 149 struct irq_domain *dev_domain; 152 150 struct mutex lock; /* protect bitmap variable */ ··· 418 418 }; 419 419 420 420 #ifdef CONFIG_PCI_MSI 421 - static struct irq_chip nwl_msi_irq_chip = { 422 - .name = "nwl_pcie:msi", 423 - .irq_enable = pci_msi_unmask_irq, 424 - .irq_disable = pci_msi_mask_irq, 425 - .irq_mask = pci_msi_mask_irq, 426 - .irq_unmask = pci_msi_unmask_irq, 421 + 422 + #define NWL_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ 423 + MSI_FLAG_USE_DEF_CHIP_OPS | \ 424 + MSI_FLAG_NO_AFFINITY) 425 + 426 + #define NWL_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \ 427 + MSI_FLAG_MULTI_PCI_MSI) 428 + 429 + static const struct msi_parent_ops nwl_msi_parent_ops = { 430 + .required_flags = NWL_MSI_FLAGS_REQUIRED, 431 + .supported_flags = NWL_MSI_FLAGS_SUPPORTED, 432 + .bus_select_token = DOMAIN_BUS_PCI_MSI, 433 + .prefix = "nwl-", 434 + .init_dev_msi_info = msi_lib_init_dev_msi_info, 427 435 }; 428 436 429 - static struct msi_domain_info nwl_msi_domain_info = { 430 - .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | 431 - MSI_FLAG_NO_AFFINITY | MSI_FLAG_MULTI_PCI_MSI, 432 - .chip = &nwl_msi_irq_chip, 433 - }; 434 437 #endif 435 438 436 439 static void nwl_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) ··· 498 495 { 499 496 #ifdef CONFIG_PCI_MSI 500 497 struct device *dev = pcie->dev; 501 - struct fwnode_handle *fwnode = of_fwnode_handle(dev->of_node); 502 498 struct nwl_msi *msi = &pcie->msi; 499 + struct irq_domain_info info = { 500 + .fwnode = dev_fwnode(dev), 501 + .ops = &dev_msi_domain_ops, 502 + .host_data = pcie, 503 + .size = INT_PCI_MSI_NR, 504 + }; 503 505 504 - msi->dev_domain = irq_domain_create_linear(NULL, INT_PCI_MSI_NR, &dev_msi_domain_ops, pcie); 506 + msi->dev_domain = msi_create_parent_irq_domain(&info, &nwl_msi_parent_ops); 505 507 if (!msi->dev_domain) { 506 508 dev_err(dev, "failed to create dev IRQ domain\n"); 507 - return -ENOMEM; 508 - } 509 - msi->msi_domain = pci_msi_create_irq_domain(fwnode, 510 - &nwl_msi_domain_info, 511 - msi->dev_domain); 512 - if (!msi->msi_domain) { 513 - dev_err(dev, "failed to create msi IRQ domain\n"); 514 - irq_domain_remove(msi->dev_domain); 515 509 return -ENOMEM; 516 510 } 517 511 #endif
+30 -24
drivers/pci/controller/pcie-xilinx.c
··· 12 12 13 13 #include <linux/interrupt.h> 14 14 #include <linux/irq.h> 15 + #include <linux/irqchip/irq-msi-lib.h> 15 16 #include <linux/irqdomain.h> 16 17 #include <linux/kernel.h> 17 18 #include <linux/init.h> ··· 204 203 */ 205 204 } 206 205 207 - static struct irq_chip xilinx_msi_top_chip = { 208 - .name = "PCIe MSI", 209 - .irq_ack = xilinx_msi_top_irq_ack, 210 - }; 211 - 212 206 static void xilinx_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) 213 207 { 214 208 struct xilinx_pcie *pcie = irq_data_get_irq_chip_data(data); ··· 260 264 .free = xilinx_msi_domain_free, 261 265 }; 262 266 263 - static struct msi_domain_info xilinx_msi_info = { 264 - .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | 265 - MSI_FLAG_NO_AFFINITY, 266 - .chip = &xilinx_msi_top_chip, 267 + static bool xilinx_init_dev_msi_info(struct device *dev, struct irq_domain *domain, 268 + struct irq_domain *real_parent, struct msi_domain_info *info) 269 + { 270 + struct irq_chip *chip = info->chip; 271 + 272 + if (!msi_lib_init_dev_msi_info(dev, domain, real_parent, info)) 273 + return false; 274 + 275 + chip->irq_ack = xilinx_msi_top_irq_ack; 276 + return true; 277 + } 278 + 279 + #define XILINX_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ 280 + MSI_FLAG_USE_DEF_CHIP_OPS | \ 281 + MSI_FLAG_NO_AFFINITY) 282 + 283 + static const struct msi_parent_ops xilinx_msi_parent_ops = { 284 + .required_flags = XILINX_MSI_FLAGS_REQUIRED, 285 + .supported_flags = MSI_GENERIC_FLAGS_MASK, 286 + .bus_select_token = DOMAIN_BUS_PCI_MSI, 287 + .prefix = "xilinx-", 288 + .init_dev_msi_info = xilinx_init_dev_msi_info, 267 289 }; 268 290 269 291 static int xilinx_allocate_msi_domains(struct xilinx_pcie *pcie) 270 292 { 271 - struct fwnode_handle *fwnode = dev_fwnode(pcie->dev); 272 - struct irq_domain *parent; 293 + struct irq_domain_info info = { 294 + .fwnode = dev_fwnode(pcie->dev), 295 + .ops = &xilinx_msi_domain_ops, 296 + .host_data = pcie, 297 + .size = XILINX_NUM_MSI_IRQS, 298 + }; 273 299 274 - parent = irq_domain_create_linear(fwnode, XILINX_NUM_MSI_IRQS, 275 - &xilinx_msi_domain_ops, pcie); 276 - if (!parent) { 277 - dev_err(pcie->dev, "failed to create IRQ domain\n"); 278 - return -ENOMEM; 279 - } 280 - irq_domain_update_bus_token(parent, DOMAIN_BUS_NEXUS); 281 - 282 - pcie->msi_domain = pci_msi_create_irq_domain(fwnode, &xilinx_msi_info, parent); 300 + pcie->msi_domain = msi_create_parent_irq_domain(&info, &xilinx_msi_parent_ops); 283 301 if (!pcie->msi_domain) { 284 302 dev_err(pcie->dev, "failed to create MSI domain\n"); 285 - irq_domain_remove(parent); 286 303 return -ENOMEM; 287 304 } 288 305 ··· 304 295 305 296 static void xilinx_free_msi_domains(struct xilinx_pcie *pcie) 306 297 { 307 - struct irq_domain *parent = pcie->msi_domain->parent; 308 - 309 298 irq_domain_remove(pcie->msi_domain); 310 - irq_domain_remove(parent); 311 299 } 312 300 313 301 /* INTx Functions */
+1
drivers/pci/controller/plda/Kconfig
··· 5 5 6 6 config PCIE_PLDA_HOST 7 7 bool 8 + select IRQ_MSI_LIB 8 9 9 10 config PCIE_MICROCHIP_HOST 10 11 tristate "Microchip AXI PCIe controller"
+21 -22
drivers/pci/controller/plda/pcie-plda-host.c
··· 11 11 #include <linux/align.h> 12 12 #include <linux/bitfield.h> 13 13 #include <linux/irqchip/chained_irq.h> 14 + #include <linux/irqchip/irq-msi-lib.h> 14 15 #include <linux/irqdomain.h> 15 16 #include <linux/msi.h> 16 17 #include <linux/pci_regs.h> ··· 135 134 .free = plda_irq_msi_domain_free, 136 135 }; 137 136 138 - static struct irq_chip plda_msi_irq_chip = { 139 - .name = "PLDA PCIe MSI", 140 - .irq_ack = irq_chip_ack_parent, 141 - .irq_mask = pci_msi_mask_irq, 142 - .irq_unmask = pci_msi_unmask_irq, 143 - }; 137 + #define PLDA_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ 138 + MSI_FLAG_USE_DEF_CHIP_OPS | \ 139 + MSI_FLAG_NO_AFFINITY) 140 + #define PLDA_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \ 141 + MSI_FLAG_PCI_MSIX) 144 142 145 - static struct msi_domain_info plda_msi_domain_info = { 146 - .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | 147 - MSI_FLAG_NO_AFFINITY | MSI_FLAG_PCI_MSIX, 148 - .chip = &plda_msi_irq_chip, 143 + static const struct msi_parent_ops plda_msi_parent_ops = { 144 + .required_flags = PLDA_MSI_FLAGS_REQUIRED, 145 + .supported_flags = PLDA_MSI_FLAGS_SUPPORTED, 146 + .chip_flags = MSI_CHIP_FLAG_SET_ACK, 147 + .bus_select_token = DOMAIN_BUS_PCI_MSI, 148 + .prefix = "PLDA-", 149 + .init_dev_msi_info = msi_lib_init_dev_msi_info, 149 150 }; 150 151 151 152 static int plda_allocate_msi_domains(struct plda_pcie_rp *port) 152 153 { 153 154 struct device *dev = port->dev; 154 - struct fwnode_handle *fwnode = of_fwnode_handle(dev->of_node); 155 155 struct plda_msi *msi = &port->msi; 156 156 157 157 mutex_init(&port->msi.lock); 158 158 159 - msi->dev_domain = irq_domain_create_linear(NULL, msi->num_vectors, &msi_domain_ops, port); 159 + struct irq_domain_info info = { 160 + .fwnode = dev_fwnode(dev), 161 + .ops = &msi_domain_ops, 162 + .host_data = port, 163 + .size = msi->num_vectors, 164 + }; 165 + 166 + msi->dev_domain = msi_create_parent_irq_domain(&info, &plda_msi_parent_ops); 160 167 if (!msi->dev_domain) { 161 168 dev_err(dev, "failed to create IRQ domain\n"); 162 - return -ENOMEM; 163 - } 164 - 165 - msi->msi_domain = pci_msi_create_irq_domain(fwnode, 166 - &plda_msi_domain_info, 167 - msi->dev_domain); 168 - if (!msi->msi_domain) { 169 - dev_err(dev, "failed to create MSI domain\n"); 170 - irq_domain_remove(msi->dev_domain); 171 169 return -ENOMEM; 172 170 } 173 171 ··· 563 563 irq_set_chained_handler_and_data(pcie->msi_irq, NULL, NULL); 564 564 irq_set_chained_handler_and_data(pcie->intx_irq, NULL, NULL); 565 565 566 - irq_domain_remove(pcie->msi.msi_domain); 567 566 irq_domain_remove(pcie->msi.dev_domain); 568 567 569 568 irq_domain_remove(pcie->intx_domain);
-1
drivers/pci/controller/plda/pcie-plda.h
··· 164 164 165 165 struct plda_msi { 166 166 struct mutex lock; /* Protect used bitmap */ 167 - struct irq_domain *msi_domain; 168 167 struct irq_domain *dev_domain; 169 168 u32 num_vectors; 170 169 u64 vector_phy;
+1 -1
drivers/pci/controller/plda/pcie-starfive.c
··· 368 368 * of 100ms following exit from a conventional reset before 369 369 * sending a configuration request to the device. 370 370 */ 371 - msleep(PCIE_RESET_CONFIG_DEVICE_WAIT_MS); 371 + msleep(PCIE_RESET_CONFIG_WAIT_MS); 372 372 373 373 if (starfive_pcie_host_wait_for_link(pcie)) 374 374 dev_info(dev, "port link down\n");
+123 -126
drivers/pci/controller/vmd.c
··· 7 7 #include <linux/device.h> 8 8 #include <linux/interrupt.h> 9 9 #include <linux/irq.h> 10 + #include <linux/irqchip/irq-msi-lib.h> 10 11 #include <linux/kernel.h> 11 12 #include <linux/module.h> 12 13 #include <linux/msi.h> ··· 175 174 msg->arch_addr_lo.destid_0_7 = index_from_irqs(vmd, irq); 176 175 } 177 176 178 - /* 179 - * We rely on MSI_FLAG_USE_DEF_CHIP_OPS to set the IRQ mask/unmask ops. 180 - */ 181 177 static void vmd_irq_enable(struct irq_data *data) 182 178 { 183 179 struct vmd_irq *vmdirq = data->chip_data; 184 - unsigned long flags; 185 180 186 - raw_spin_lock_irqsave(&list_lock, flags); 187 - WARN_ON(vmdirq->enabled); 188 - list_add_tail_rcu(&vmdirq->node, &vmdirq->irq->irq_list); 189 - vmdirq->enabled = true; 190 - raw_spin_unlock_irqrestore(&list_lock, flags); 181 + scoped_guard(raw_spinlock_irqsave, &list_lock) { 182 + WARN_ON(vmdirq->enabled); 183 + list_add_tail_rcu(&vmdirq->node, &vmdirq->irq->irq_list); 184 + vmdirq->enabled = true; 185 + } 186 + } 191 187 188 + static void vmd_pci_msi_enable(struct irq_data *data) 189 + { 190 + vmd_irq_enable(data->parent_data); 192 191 data->chip->irq_unmask(data); 193 192 } 194 193 195 194 static void vmd_irq_disable(struct irq_data *data) 196 195 { 197 196 struct vmd_irq *vmdirq = data->chip_data; 198 - unsigned long flags; 199 197 200 - data->chip->irq_mask(data); 201 - 202 - raw_spin_lock_irqsave(&list_lock, flags); 203 - if (vmdirq->enabled) { 204 - list_del_rcu(&vmdirq->node); 205 - vmdirq->enabled = false; 198 + scoped_guard(raw_spinlock_irqsave, &list_lock) { 199 + if (vmdirq->enabled) { 200 + list_del_rcu(&vmdirq->node); 201 + vmdirq->enabled = false; 202 + } 206 203 } 207 - raw_spin_unlock_irqrestore(&list_lock, flags); 204 + } 205 + 206 + static void vmd_pci_msi_disable(struct irq_data *data) 207 + { 208 + data->chip->irq_mask(data); 209 + vmd_irq_disable(data->parent_data); 208 210 } 209 211 210 212 static struct irq_chip vmd_msi_controller = { 211 213 .name = "VMD-MSI", 212 - .irq_enable = vmd_irq_enable, 213 - .irq_disable = vmd_irq_disable, 214 214 .irq_compose_msi_msg = vmd_compose_msi_msg, 215 215 }; 216 - 217 - static irq_hw_number_t vmd_get_hwirq(struct msi_domain_info *info, 218 - msi_alloc_info_t *arg) 219 - { 220 - return 0; 221 - } 222 216 223 217 /* 224 218 * XXX: We can be even smarter selecting the best IRQ once we solve the ··· 221 225 */ 222 226 static struct vmd_irq_list *vmd_next_irq(struct vmd_dev *vmd, struct msi_desc *desc) 223 227 { 224 - unsigned long flags; 225 228 int i, best; 226 229 227 230 if (vmd->msix_count == 1 + vmd->first_vec) ··· 237 242 return &vmd->irqs[vmd->first_vec]; 238 243 } 239 244 240 - raw_spin_lock_irqsave(&list_lock, flags); 241 - best = vmd->first_vec + 1; 242 - for (i = best; i < vmd->msix_count; i++) 243 - if (vmd->irqs[i].count < vmd->irqs[best].count) 244 - best = i; 245 - vmd->irqs[best].count++; 246 - raw_spin_unlock_irqrestore(&list_lock, flags); 245 + scoped_guard(raw_spinlock_irq, &list_lock) { 246 + best = vmd->first_vec + 1; 247 + for (i = best; i < vmd->msix_count; i++) 248 + if (vmd->irqs[i].count < vmd->irqs[best].count) 249 + best = i; 250 + vmd->irqs[best].count++; 251 + } 247 252 248 253 return &vmd->irqs[best]; 249 254 } 250 255 251 - static int vmd_msi_init(struct irq_domain *domain, struct msi_domain_info *info, 252 - unsigned int virq, irq_hw_number_t hwirq, 253 - msi_alloc_info_t *arg) 256 + static void vmd_msi_free(struct irq_domain *domain, unsigned int virq, 257 + unsigned int nr_irqs); 258 + 259 + static int vmd_msi_alloc(struct irq_domain *domain, unsigned int virq, 260 + unsigned int nr_irqs, void *arg) 254 261 { 255 - struct msi_desc *desc = arg->desc; 256 - struct vmd_dev *vmd = vmd_from_bus(msi_desc_to_pci_dev(desc)->bus); 257 - struct vmd_irq *vmdirq = kzalloc(sizeof(*vmdirq), GFP_KERNEL); 262 + struct msi_desc *desc = ((msi_alloc_info_t *)arg)->desc; 263 + struct vmd_dev *vmd = domain->host_data; 264 + struct vmd_irq *vmdirq; 258 265 259 - if (!vmdirq) 260 - return -ENOMEM; 266 + for (int i = 0; i < nr_irqs; ++i) { 267 + vmdirq = kzalloc(sizeof(*vmdirq), GFP_KERNEL); 268 + if (!vmdirq) { 269 + vmd_msi_free(domain, virq, i); 270 + return -ENOMEM; 271 + } 261 272 262 - INIT_LIST_HEAD(&vmdirq->node); 263 - vmdirq->irq = vmd_next_irq(vmd, desc); 264 - vmdirq->virq = virq; 273 + INIT_LIST_HEAD(&vmdirq->node); 274 + vmdirq->irq = vmd_next_irq(vmd, desc); 275 + vmdirq->virq = virq + i; 265 276 266 - irq_domain_set_info(domain, virq, vmdirq->irq->virq, info->chip, vmdirq, 267 - handle_untracked_irq, vmd, NULL); 277 + irq_domain_set_info(domain, virq + i, vmdirq->irq->virq, 278 + &vmd_msi_controller, vmdirq, 279 + handle_untracked_irq, vmd, NULL); 280 + } 281 + 268 282 return 0; 269 283 } 270 284 271 - static void vmd_msi_free(struct irq_domain *domain, 272 - struct msi_domain_info *info, unsigned int virq) 285 + static void vmd_msi_free(struct irq_domain *domain, unsigned int virq, 286 + unsigned int nr_irqs) 273 287 { 274 - struct vmd_irq *vmdirq = irq_get_chip_data(virq); 275 - unsigned long flags; 288 + struct vmd_irq *vmdirq; 276 289 277 - synchronize_srcu(&vmdirq->irq->srcu); 290 + for (int i = 0; i < nr_irqs; ++i) { 291 + vmdirq = irq_get_chip_data(virq + i); 278 292 279 - /* XXX: Potential optimization to rebalance */ 280 - raw_spin_lock_irqsave(&list_lock, flags); 281 - vmdirq->irq->count--; 282 - raw_spin_unlock_irqrestore(&list_lock, flags); 293 + synchronize_srcu(&vmdirq->irq->srcu); 283 294 284 - kfree(vmdirq); 295 + /* XXX: Potential optimization to rebalance */ 296 + scoped_guard(raw_spinlock_irq, &list_lock) 297 + vmdirq->irq->count--; 298 + 299 + kfree(vmdirq); 300 + } 285 301 } 286 302 287 - static int vmd_msi_prepare(struct irq_domain *domain, struct device *dev, 288 - int nvec, msi_alloc_info_t *arg) 303 + static const struct irq_domain_ops vmd_msi_domain_ops = { 304 + .alloc = vmd_msi_alloc, 305 + .free = vmd_msi_free, 306 + }; 307 + 308 + static bool vmd_init_dev_msi_info(struct device *dev, struct irq_domain *domain, 309 + struct irq_domain *real_parent, 310 + struct msi_domain_info *info) 289 311 { 290 - struct pci_dev *pdev = to_pci_dev(dev); 291 - struct vmd_dev *vmd = vmd_from_bus(pdev->bus); 312 + if (WARN_ON_ONCE(info->bus_token != DOMAIN_BUS_PCI_DEVICE_MSIX)) 313 + return false; 292 314 293 - if (nvec > vmd->msix_count) 294 - return vmd->msix_count; 315 + if (!msi_lib_init_dev_msi_info(dev, domain, real_parent, info)) 316 + return false; 295 317 296 - memset(arg, 0, sizeof(*arg)); 318 + info->chip->irq_enable = vmd_pci_msi_enable; 319 + info->chip->irq_disable = vmd_pci_msi_disable; 320 + return true; 321 + } 322 + 323 + #define VMD_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | MSI_FLAG_PCI_MSIX) 324 + #define VMD_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_NO_AFFINITY) 325 + 326 + static const struct msi_parent_ops vmd_msi_parent_ops = { 327 + .supported_flags = VMD_MSI_FLAGS_SUPPORTED, 328 + .required_flags = VMD_MSI_FLAGS_REQUIRED, 329 + .bus_select_token = DOMAIN_BUS_VMD_MSI, 330 + .bus_select_mask = MATCH_PCI_MSI, 331 + .prefix = "VMD-", 332 + .init_dev_msi_info = vmd_init_dev_msi_info, 333 + }; 334 + 335 + static int vmd_create_irq_domain(struct vmd_dev *vmd) 336 + { 337 + struct irq_domain_info info = { 338 + .size = vmd->msix_count, 339 + .ops = &vmd_msi_domain_ops, 340 + .host_data = vmd, 341 + }; 342 + 343 + info.fwnode = irq_domain_alloc_named_id_fwnode("VMD-MSI", 344 + vmd->sysdata.domain); 345 + if (!info.fwnode) 346 + return -ENODEV; 347 + 348 + vmd->irq_domain = msi_create_parent_irq_domain(&info, 349 + &vmd_msi_parent_ops); 350 + if (!vmd->irq_domain) { 351 + irq_domain_free_fwnode(info.fwnode); 352 + return -ENODEV; 353 + } 354 + 297 355 return 0; 298 356 } 299 - 300 - static void vmd_set_desc(msi_alloc_info_t *arg, struct msi_desc *desc) 301 - { 302 - arg->desc = desc; 303 - } 304 - 305 - static struct msi_domain_ops vmd_msi_domain_ops = { 306 - .get_hwirq = vmd_get_hwirq, 307 - .msi_init = vmd_msi_init, 308 - .msi_free = vmd_msi_free, 309 - .msi_prepare = vmd_msi_prepare, 310 - .set_desc = vmd_set_desc, 311 - }; 312 - 313 - static struct msi_domain_info vmd_msi_domain_info = { 314 - .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | 315 - MSI_FLAG_NO_AFFINITY | MSI_FLAG_PCI_MSIX, 316 - .ops = &vmd_msi_domain_ops, 317 - .chip = &vmd_msi_controller, 318 - }; 319 357 320 358 static void vmd_set_msi_remapping(struct vmd_dev *vmd, bool enable) 321 359 { ··· 358 330 reg = enable ? (reg & ~VMCONFIG_MSI_REMAP) : 359 331 (reg | VMCONFIG_MSI_REMAP); 360 332 pci_write_config_word(vmd->dev, PCI_REG_VMCONFIG, reg); 361 - } 362 - 363 - static int vmd_create_irq_domain(struct vmd_dev *vmd) 364 - { 365 - struct fwnode_handle *fn; 366 - 367 - fn = irq_domain_alloc_named_id_fwnode("VMD-MSI", vmd->sysdata.domain); 368 - if (!fn) 369 - return -ENODEV; 370 - 371 - vmd->irq_domain = pci_msi_create_irq_domain(fn, &vmd_msi_domain_info, NULL); 372 - if (!vmd->irq_domain) { 373 - irq_domain_free_fwnode(fn); 374 - return -ENODEV; 375 - } 376 - 377 - return 0; 378 333 } 379 334 380 335 static void vmd_remove_irq_domain(struct vmd_dev *vmd) ··· 398 387 { 399 388 struct vmd_dev *vmd = vmd_from_bus(bus); 400 389 void __iomem *addr = vmd_cfg_addr(vmd, bus, devfn, reg, len); 401 - unsigned long flags; 402 - int ret = 0; 403 390 404 391 if (!addr) 405 392 return -EFAULT; 406 393 407 - raw_spin_lock_irqsave(&vmd->cfg_lock, flags); 394 + guard(raw_spinlock_irqsave)(&vmd->cfg_lock); 408 395 switch (len) { 409 396 case 1: 410 397 *value = readb(addr); 411 - break; 398 + return 0; 412 399 case 2: 413 400 *value = readw(addr); 414 - break; 401 + return 0; 415 402 case 4: 416 403 *value = readl(addr); 417 - break; 404 + return 0; 418 405 default: 419 - ret = -EINVAL; 420 - break; 406 + return -EINVAL; 421 407 } 422 - raw_spin_unlock_irqrestore(&vmd->cfg_lock, flags); 423 - return ret; 424 408 } 425 409 426 410 /* ··· 428 422 { 429 423 struct vmd_dev *vmd = vmd_from_bus(bus); 430 424 void __iomem *addr = vmd_cfg_addr(vmd, bus, devfn, reg, len); 431 - unsigned long flags; 432 - int ret = 0; 433 425 434 426 if (!addr) 435 427 return -EFAULT; 436 428 437 - raw_spin_lock_irqsave(&vmd->cfg_lock, flags); 429 + guard(raw_spinlock_irqsave)(&vmd->cfg_lock); 438 430 switch (len) { 439 431 case 1: 440 432 writeb(value, addr); 441 433 readb(addr); 442 - break; 434 + return 0; 443 435 case 2: 444 436 writew(value, addr); 445 437 readw(addr); 446 - break; 438 + return 0; 447 439 case 4: 448 440 writel(value, addr); 449 441 readl(addr); 450 - break; 442 + return 0; 451 443 default: 452 - ret = -EINVAL; 453 - break; 444 + return -EINVAL; 454 445 } 455 - raw_spin_unlock_irqrestore(&vmd->cfg_lock, flags); 456 - return ret; 457 446 } 458 447 459 448 static struct pci_ops vmd_ops = { ··· 890 889 ret = vmd_create_irq_domain(vmd); 891 890 if (ret) 892 891 return ret; 893 - 894 - /* 895 - * Override the IRQ domain bus token so the domain can be 896 - * distinguished from a regular PCI/MSI domain. 897 - */ 898 - irq_domain_update_bus_token(vmd->irq_domain, DOMAIN_BUS_VMD_MSI); 899 892 } else { 900 893 vmd_set_msi_remapping(vmd, false); 901 894 } ··· 1123 1128 {PCI_VDEVICE(INTEL, 0xb60b), 1124 1129 .driver_data = VMD_FEATS_CLIENT,}, 1125 1130 {PCI_VDEVICE(INTEL, 0xb06f), 1131 + .driver_data = VMD_FEATS_CLIENT,}, 1132 + {PCI_VDEVICE(INTEL, 0xb07f), 1126 1133 .driver_data = VMD_FEATS_CLIENT,}, 1127 1134 {0,} 1128 1135 };
+8
drivers/pci/endpoint/Kconfig
··· 28 28 configure the endpoint function and used to bind the 29 29 function with an endpoint controller. 30 30 31 + config PCI_ENDPOINT_MSI_DOORBELL 32 + bool "PCI Endpoint MSI Doorbell Support" 33 + depends on PCI_ENDPOINT && GENERIC_MSI_IRQ 34 + help 35 + This enables the EP's MSI interrupt controller to function as a 36 + doorbell. The RC can trigger doorbell in EP by writing data to a 37 + dedicated BAR, which the EP maps to the controller's message address. 38 + 31 39 source "drivers/pci/endpoint/functions/Kconfig" 32 40 33 41 endmenu
+1
drivers/pci/endpoint/Makefile
··· 6 6 obj-$(CONFIG_PCI_ENDPOINT_CONFIGFS) += pci-ep-cfs.o 7 7 obj-$(CONFIG_PCI_ENDPOINT) += pci-epc-core.o pci-epf-core.o\ 8 8 pci-epc-mem.o functions/ 9 + obj-$(CONFIG_PCI_ENDPOINT_MSI_DOORBELL) += pci-ep-msi.o
+130
drivers/pci/endpoint/functions/pci-epf-test.c
··· 11 11 #include <linux/dmaengine.h> 12 12 #include <linux/io.h> 13 13 #include <linux/module.h> 14 + #include <linux/msi.h> 14 15 #include <linux/slab.h> 15 16 #include <linux/pci_ids.h> 16 17 #include <linux/random.h> 17 18 18 19 #include <linux/pci-epc.h> 19 20 #include <linux/pci-epf.h> 21 + #include <linux/pci-ep-msi.h> 20 22 #include <linux/pci_regs.h> 21 23 22 24 #define IRQ_TYPE_INTX 0 ··· 31 29 #define COMMAND_READ BIT(3) 32 30 #define COMMAND_WRITE BIT(4) 33 31 #define COMMAND_COPY BIT(5) 32 + #define COMMAND_ENABLE_DOORBELL BIT(6) 33 + #define COMMAND_DISABLE_DOORBELL BIT(7) 34 34 35 35 #define STATUS_READ_SUCCESS BIT(0) 36 36 #define STATUS_READ_FAIL BIT(1) ··· 43 39 #define STATUS_IRQ_RAISED BIT(6) 44 40 #define STATUS_SRC_ADDR_INVALID BIT(7) 45 41 #define STATUS_DST_ADDR_INVALID BIT(8) 42 + #define STATUS_DOORBELL_SUCCESS BIT(9) 43 + #define STATUS_DOORBELL_ENABLE_SUCCESS BIT(10) 44 + #define STATUS_DOORBELL_ENABLE_FAIL BIT(11) 45 + #define STATUS_DOORBELL_DISABLE_SUCCESS BIT(12) 46 + #define STATUS_DOORBELL_DISABLE_FAIL BIT(13) 46 47 47 48 #define FLAG_USE_DMA BIT(0) 48 49 ··· 75 66 bool dma_supported; 76 67 bool dma_private; 77 68 const struct pci_epc_features *epc_features; 69 + struct pci_epf_bar db_bar; 78 70 }; 79 71 80 72 struct pci_epf_test_reg { ··· 90 80 __le32 irq_number; 91 81 __le32 flags; 92 82 __le32 caps; 83 + __le32 doorbell_bar; 84 + __le32 doorbell_offset; 85 + __le32 doorbell_data; 93 86 } __packed; 94 87 95 88 static struct pci_epf_header test_header = { ··· 680 667 } 681 668 } 682 669 670 + static irqreturn_t pci_epf_test_doorbell_handler(int irq, void *data) 671 + { 672 + struct pci_epf_test *epf_test = data; 673 + enum pci_barno test_reg_bar = epf_test->test_reg_bar; 674 + struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar]; 675 + u32 status = le32_to_cpu(reg->status); 676 + 677 + status |= STATUS_DOORBELL_SUCCESS; 678 + reg->status = cpu_to_le32(status); 679 + pci_epf_test_raise_irq(epf_test, reg); 680 + 681 + return IRQ_HANDLED; 682 + } 683 + 684 + static void pci_epf_test_doorbell_cleanup(struct pci_epf_test *epf_test) 685 + { 686 + struct pci_epf_test_reg *reg = epf_test->reg[epf_test->test_reg_bar]; 687 + struct pci_epf *epf = epf_test->epf; 688 + 689 + free_irq(epf->db_msg[0].virq, epf_test); 690 + reg->doorbell_bar = cpu_to_le32(NO_BAR); 691 + 692 + pci_epf_free_doorbell(epf); 693 + } 694 + 695 + static void pci_epf_test_enable_doorbell(struct pci_epf_test *epf_test, 696 + struct pci_epf_test_reg *reg) 697 + { 698 + u32 status = le32_to_cpu(reg->status); 699 + struct pci_epf *epf = epf_test->epf; 700 + struct pci_epc *epc = epf->epc; 701 + struct msi_msg *msg; 702 + enum pci_barno bar; 703 + size_t offset; 704 + int ret; 705 + 706 + ret = pci_epf_alloc_doorbell(epf, 1); 707 + if (ret) 708 + goto set_status_err; 709 + 710 + msg = &epf->db_msg[0].msg; 711 + bar = pci_epc_get_next_free_bar(epf_test->epc_features, epf_test->test_reg_bar + 1); 712 + if (bar < BAR_0) 713 + goto err_doorbell_cleanup; 714 + 715 + ret = request_irq(epf->db_msg[0].virq, pci_epf_test_doorbell_handler, 0, 716 + "pci-ep-test-doorbell", epf_test); 717 + if (ret) { 718 + dev_err(&epf->dev, 719 + "Failed to request doorbell IRQ: %d\n", 720 + epf->db_msg[0].virq); 721 + goto err_doorbell_cleanup; 722 + } 723 + 724 + reg->doorbell_data = cpu_to_le32(msg->data); 725 + reg->doorbell_bar = cpu_to_le32(bar); 726 + 727 + msg = &epf->db_msg[0].msg; 728 + ret = pci_epf_align_inbound_addr(epf, bar, ((u64)msg->address_hi << 32) | msg->address_lo, 729 + &epf_test->db_bar.phys_addr, &offset); 730 + 731 + if (ret) 732 + goto err_doorbell_cleanup; 733 + 734 + reg->doorbell_offset = cpu_to_le32(offset); 735 + 736 + epf_test->db_bar.barno = bar; 737 + epf_test->db_bar.size = epf->bar[bar].size; 738 + epf_test->db_bar.flags = epf->bar[bar].flags; 739 + 740 + ret = pci_epc_set_bar(epc, epf->func_no, epf->vfunc_no, &epf_test->db_bar); 741 + if (ret) 742 + goto err_doorbell_cleanup; 743 + 744 + status |= STATUS_DOORBELL_ENABLE_SUCCESS; 745 + reg->status = cpu_to_le32(status); 746 + return; 747 + 748 + err_doorbell_cleanup: 749 + pci_epf_test_doorbell_cleanup(epf_test); 750 + set_status_err: 751 + status |= STATUS_DOORBELL_ENABLE_FAIL; 752 + reg->status = cpu_to_le32(status); 753 + } 754 + 755 + static void pci_epf_test_disable_doorbell(struct pci_epf_test *epf_test, 756 + struct pci_epf_test_reg *reg) 757 + { 758 + enum pci_barno bar = le32_to_cpu(reg->doorbell_bar); 759 + u32 status = le32_to_cpu(reg->status); 760 + struct pci_epf *epf = epf_test->epf; 761 + struct pci_epc *epc = epf->epc; 762 + 763 + if (bar < BAR_0) 764 + goto set_status_err; 765 + 766 + pci_epf_test_doorbell_cleanup(epf_test); 767 + pci_epc_clear_bar(epc, epf->func_no, epf->vfunc_no, &epf_test->db_bar); 768 + 769 + status |= STATUS_DOORBELL_DISABLE_SUCCESS; 770 + reg->status = cpu_to_le32(status); 771 + 772 + return; 773 + 774 + set_status_err: 775 + status |= STATUS_DOORBELL_DISABLE_FAIL; 776 + reg->status = cpu_to_le32(status); 777 + } 778 + 683 779 static void pci_epf_test_cmd_handler(struct work_struct *work) 684 780 { 685 781 u32 command; ··· 834 712 break; 835 713 case COMMAND_COPY: 836 714 pci_epf_test_copy(epf_test, reg); 715 + pci_epf_test_raise_irq(epf_test, reg); 716 + break; 717 + case COMMAND_ENABLE_DOORBELL: 718 + pci_epf_test_enable_doorbell(epf_test, reg); 719 + pci_epf_test_raise_irq(epf_test, reg); 720 + break; 721 + case COMMAND_DISABLE_DOORBELL: 722 + pci_epf_test_disable_doorbell(epf_test, reg); 837 723 pci_epf_test_raise_irq(epf_test, reg); 838 724 break; 839 725 default:
+131 -13
drivers/pci/endpoint/functions/pci-epf-vntb.c
··· 70 70 enum epf_ntb_bar { 71 71 BAR_CONFIG, 72 72 BAR_DB, 73 - BAR_MW0, 74 73 BAR_MW1, 75 74 BAR_MW2, 75 + BAR_MW3, 76 + BAR_MW4, 77 + VNTB_BAR_NUM, 76 78 }; 77 79 78 80 /* ··· 134 132 bool linkup; 135 133 u32 spad_size; 136 134 137 - enum pci_barno epf_ntb_bar[6]; 135 + enum pci_barno epf_ntb_bar[VNTB_BAR_NUM]; 138 136 139 137 struct epf_ntb_ctrl *reg; 140 138 ··· 512 510 struct device *dev = &ntb->epf->dev; 513 511 int ret; 514 512 struct pci_epf_bar *epf_bar; 515 - void __iomem *mw_addr; 513 + void *mw_addr; 516 514 enum pci_barno barno; 517 515 size_t size = sizeof(u32) * ntb->db_count; 518 516 ··· 578 576 579 577 for (i = 0; i < ntb->num_mws; i++) { 580 578 size = ntb->mws_size[i]; 581 - barno = ntb->epf_ntb_bar[BAR_MW0 + i]; 579 + barno = ntb->epf_ntb_bar[BAR_MW1 + i]; 582 580 583 581 ntb->epf->bar[barno].barno = barno; 584 582 ntb->epf->bar[barno].size = size; ··· 631 629 int i; 632 630 633 631 for (i = 0; i < num_mws; i++) { 634 - barno = ntb->epf_ntb_bar[BAR_MW0 + i]; 632 + barno = ntb->epf_ntb_bar[BAR_MW1 + i]; 635 633 pci_epc_clear_bar(ntb->epf->epc, 636 634 ntb->epf->func_no, 637 635 ntb->epf->vfunc_no, ··· 656 654 pci_epc_put(ntb->epf->epc); 657 655 } 658 656 657 + 658 + /** 659 + * epf_ntb_is_bar_used() - Check if a bar is used in the ntb configuration 660 + * @ntb: NTB device that facilitates communication between HOST and VHOST 661 + * @barno: Checked bar number 662 + * 663 + * Returns: true if used, false if free. 664 + */ 665 + static bool epf_ntb_is_bar_used(struct epf_ntb *ntb, 666 + enum pci_barno barno) 667 + { 668 + int i; 669 + 670 + for (i = 0; i < VNTB_BAR_NUM; i++) { 671 + if (ntb->epf_ntb_bar[i] == barno) 672 + return true; 673 + } 674 + 675 + return false; 676 + } 677 + 678 + /** 679 + * epf_ntb_find_bar() - Assign BAR number when no configuration is provided 680 + * @ntb: NTB device that facilitates communication between HOST and VHOST 681 + * @epc_features: The features provided by the EPC specific to this EPF 682 + * @bar: NTB BAR index 683 + * @barno: Bar start index 684 + * 685 + * When the BAR configuration was not provided through the userspace 686 + * configuration, automatically assign BAR as it has been historically 687 + * done by this endpoint function. 688 + * 689 + * Returns: the BAR number found, if any. -1 otherwise 690 + */ 691 + static int epf_ntb_find_bar(struct epf_ntb *ntb, 692 + const struct pci_epc_features *epc_features, 693 + enum epf_ntb_bar bar, 694 + enum pci_barno barno) 695 + { 696 + while (ntb->epf_ntb_bar[bar] < 0) { 697 + barno = pci_epc_get_next_free_bar(epc_features, barno); 698 + if (barno < 0) 699 + break; /* No more BAR available */ 700 + 701 + /* 702 + * Verify if the BAR found is not already assigned 703 + * through the provided configuration 704 + */ 705 + if (!epf_ntb_is_bar_used(ntb, barno)) 706 + ntb->epf_ntb_bar[bar] = barno; 707 + 708 + barno += 1; 709 + } 710 + 711 + return barno; 712 + } 713 + 659 714 /** 660 715 * epf_ntb_init_epc_bar() - Identify BARs to be used for each of the NTB 661 716 * constructs (scratchpad region, doorbell, memorywindow) ··· 735 676 epc_features = pci_epc_get_features(ntb->epf->epc, ntb->epf->func_no, ntb->epf->vfunc_no); 736 677 737 678 /* These are required BARs which are mandatory for NTB functionality */ 738 - for (bar = BAR_CONFIG; bar <= BAR_MW0; bar++, barno++) { 739 - barno = pci_epc_get_next_free_bar(epc_features, barno); 679 + for (bar = BAR_CONFIG; bar <= BAR_MW1; bar++) { 680 + barno = epf_ntb_find_bar(ntb, epc_features, bar, barno); 740 681 if (barno < 0) { 741 682 dev_err(dev, "Fail to get NTB function BAR\n"); 742 - return barno; 683 + return -ENOENT; 743 684 } 744 - ntb->epf_ntb_bar[bar] = barno; 745 685 } 746 686 747 687 /* These are optional BARs which don't impact NTB functionality */ 748 - for (bar = BAR_MW1, i = 1; i < num_mws; bar++, barno++, i++) { 749 - barno = pci_epc_get_next_free_bar(epc_features, barno); 688 + for (bar = BAR_MW1, i = 1; i < num_mws; bar++, i++) { 689 + barno = epf_ntb_find_bar(ntb, epc_features, bar, barno); 750 690 if (barno < 0) { 751 691 ntb->num_mws = i; 752 692 dev_dbg(dev, "BAR not available for > MW%d\n", i + 1); 753 693 } 754 - ntb->epf_ntb_bar[bar] = barno; 755 694 } 756 695 757 696 return 0; ··· 917 860 return len; \ 918 861 } 919 862 863 + #define EPF_NTB_BAR_R(_name, _id) \ 864 + static ssize_t epf_ntb_##_name##_show(struct config_item *item, \ 865 + char *page) \ 866 + { \ 867 + struct config_group *group = to_config_group(item); \ 868 + struct epf_ntb *ntb = to_epf_ntb(group); \ 869 + \ 870 + return sprintf(page, "%d\n", ntb->epf_ntb_bar[_id]); \ 871 + } 872 + 873 + #define EPF_NTB_BAR_W(_name, _id) \ 874 + static ssize_t epf_ntb_##_name##_store(struct config_item *item, \ 875 + const char *page, size_t len) \ 876 + { \ 877 + struct config_group *group = to_config_group(item); \ 878 + struct epf_ntb *ntb = to_epf_ntb(group); \ 879 + int val; \ 880 + int ret; \ 881 + \ 882 + ret = kstrtoint(page, 0, &val); \ 883 + if (ret) \ 884 + return ret; \ 885 + \ 886 + if (val < NO_BAR || val > BAR_5) \ 887 + return -EINVAL; \ 888 + \ 889 + ntb->epf_ntb_bar[_id] = val; \ 890 + \ 891 + return len; \ 892 + } 893 + 920 894 static ssize_t epf_ntb_num_mws_store(struct config_item *item, 921 895 const char *page, size_t len) 922 896 { ··· 987 899 EPF_NTB_MW_W(mw3) 988 900 EPF_NTB_MW_R(mw4) 989 901 EPF_NTB_MW_W(mw4) 902 + EPF_NTB_BAR_R(ctrl_bar, BAR_CONFIG) 903 + EPF_NTB_BAR_W(ctrl_bar, BAR_CONFIG) 904 + EPF_NTB_BAR_R(db_bar, BAR_DB) 905 + EPF_NTB_BAR_W(db_bar, BAR_DB) 906 + EPF_NTB_BAR_R(mw1_bar, BAR_MW1) 907 + EPF_NTB_BAR_W(mw1_bar, BAR_MW1) 908 + EPF_NTB_BAR_R(mw2_bar, BAR_MW2) 909 + EPF_NTB_BAR_W(mw2_bar, BAR_MW2) 910 + EPF_NTB_BAR_R(mw3_bar, BAR_MW3) 911 + EPF_NTB_BAR_W(mw3_bar, BAR_MW3) 912 + EPF_NTB_BAR_R(mw4_bar, BAR_MW4) 913 + EPF_NTB_BAR_W(mw4_bar, BAR_MW4) 990 914 991 915 CONFIGFS_ATTR(epf_ntb_, spad_count); 992 916 CONFIGFS_ATTR(epf_ntb_, db_count); ··· 1010 910 CONFIGFS_ATTR(epf_ntb_, vbus_number); 1011 911 CONFIGFS_ATTR(epf_ntb_, vntb_pid); 1012 912 CONFIGFS_ATTR(epf_ntb_, vntb_vid); 913 + CONFIGFS_ATTR(epf_ntb_, ctrl_bar); 914 + CONFIGFS_ATTR(epf_ntb_, db_bar); 915 + CONFIGFS_ATTR(epf_ntb_, mw1_bar); 916 + CONFIGFS_ATTR(epf_ntb_, mw2_bar); 917 + CONFIGFS_ATTR(epf_ntb_, mw3_bar); 918 + CONFIGFS_ATTR(epf_ntb_, mw4_bar); 1013 919 1014 920 static struct configfs_attribute *epf_ntb_attrs[] = { 1015 921 &epf_ntb_attr_spad_count, ··· 1028 922 &epf_ntb_attr_vbus_number, 1029 923 &epf_ntb_attr_vntb_pid, 1030 924 &epf_ntb_attr_vntb_vid, 925 + &epf_ntb_attr_ctrl_bar, 926 + &epf_ntb_attr_db_bar, 927 + &epf_ntb_attr_mw1_bar, 928 + &epf_ntb_attr_mw2_bar, 929 + &epf_ntb_attr_mw3_bar, 930 + &epf_ntb_attr_mw4_bar, 1031 931 NULL, 1032 932 }; 1033 933 ··· 1160 1048 struct device *dev; 1161 1049 1162 1050 dev = &ntb->ntb.dev; 1163 - barno = ntb->epf_ntb_bar[BAR_MW0 + idx]; 1051 + barno = ntb->epf_ntb_bar[BAR_MW1 + idx]; 1164 1052 epf_bar = &ntb->epf->bar[barno]; 1165 1053 epf_bar->phys_addr = addr; 1166 1054 epf_bar->barno = barno; ··· 1491 1379 { 1492 1380 struct epf_ntb *ntb; 1493 1381 struct device *dev; 1382 + int i; 1494 1383 1495 1384 dev = &epf->dev; 1496 1385 ··· 1502 1389 epf->header = &epf_ntb_header; 1503 1390 ntb->epf = epf; 1504 1391 ntb->vbus_number = 0xff; 1392 + 1393 + /* Initially, no bar is assigned */ 1394 + for (i = 0; i < VNTB_BAR_NUM; i++) 1395 + ntb->epf_ntb_bar[i] = NO_BAR; 1396 + 1505 1397 epf_set_drvdata(epf, ntb); 1506 1398 1507 1399 dev_info(dev, "pci-ep epf driver loaded\n");
+1
drivers/pci/endpoint/pci-ep-cfs.c
··· 691 691 if (IS_ERR_OR_NULL(group)) 692 692 return; 693 693 694 + list_del(&group->group_entry); 694 695 configfs_unregister_default_group(group); 695 696 } 696 697 EXPORT_SYMBOL(pci_ep_cfs_remove_epf_group);
+100
drivers/pci/endpoint/pci-ep-msi.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * PCI Endpoint *Controller* (EPC) MSI library 4 + * 5 + * Copyright (C) 2025 NXP 6 + * Author: Frank Li <Frank.Li@nxp.com> 7 + */ 8 + 9 + #include <linux/device.h> 10 + #include <linux/export.h> 11 + #include <linux/irqdomain.h> 12 + #include <linux/module.h> 13 + #include <linux/msi.h> 14 + #include <linux/of_irq.h> 15 + #include <linux/pci-epc.h> 16 + #include <linux/pci-epf.h> 17 + #include <linux/pci-ep-cfs.h> 18 + #include <linux/pci-ep-msi.h> 19 + #include <linux/slab.h> 20 + 21 + static void pci_epf_write_msi_msg(struct msi_desc *desc, struct msi_msg *msg) 22 + { 23 + struct pci_epc *epc; 24 + struct pci_epf *epf; 25 + 26 + epc = pci_epc_get(dev_name(msi_desc_to_dev(desc))); 27 + if (!epc) 28 + return; 29 + 30 + epf = list_first_entry_or_null(&epc->pci_epf, struct pci_epf, list); 31 + 32 + if (epf && epf->db_msg && desc->msi_index < epf->num_db) 33 + memcpy(&epf->db_msg[desc->msi_index].msg, msg, sizeof(*msg)); 34 + 35 + pci_epc_put(epc); 36 + } 37 + 38 + int pci_epf_alloc_doorbell(struct pci_epf *epf, u16 num_db) 39 + { 40 + struct pci_epc *epc = epf->epc; 41 + struct device *dev = &epf->dev; 42 + struct irq_domain *domain; 43 + void *msg; 44 + int ret; 45 + int i; 46 + 47 + /* TODO: Multi-EPF support */ 48 + if (list_first_entry_or_null(&epc->pci_epf, struct pci_epf, list) != epf) { 49 + dev_err(dev, "MSI doorbell doesn't support multiple EPF\n"); 50 + return -EINVAL; 51 + } 52 + 53 + domain = of_msi_map_get_device_domain(epc->dev.parent, 0, 54 + DOMAIN_BUS_PLATFORM_MSI); 55 + if (!domain) { 56 + dev_err(dev, "Can't find MSI domain for EPC\n"); 57 + return -ENODEV; 58 + } 59 + 60 + if (!irq_domain_is_msi_parent(domain)) 61 + return -ENODEV; 62 + 63 + if (!irq_domain_is_msi_immutable(domain)) { 64 + dev_err(dev, "Mutable MSI controller not supported\n"); 65 + return -ENODEV; 66 + } 67 + 68 + dev_set_msi_domain(epc->dev.parent, domain); 69 + 70 + msg = kcalloc(num_db, sizeof(struct pci_epf_doorbell_msg), GFP_KERNEL); 71 + if (!msg) 72 + return -ENOMEM; 73 + 74 + epf->num_db = num_db; 75 + epf->db_msg = msg; 76 + 77 + ret = platform_device_msi_init_and_alloc_irqs(epc->dev.parent, num_db, 78 + pci_epf_write_msi_msg); 79 + if (ret) { 80 + dev_err(dev, "Failed to allocate MSI\n"); 81 + kfree(msg); 82 + return ret; 83 + } 84 + 85 + for (i = 0; i < num_db; i++) 86 + epf->db_msg[i].virq = msi_get_virq(epc->dev.parent, i); 87 + 88 + return ret; 89 + } 90 + EXPORT_SYMBOL_GPL(pci_epf_alloc_doorbell); 91 + 92 + void pci_epf_free_doorbell(struct pci_epf *epf) 93 + { 94 + platform_device_msi_free_irqs_all(epf->epc->dev.parent); 95 + 96 + kfree(epf->db_msg); 97 + epf->db_msg = NULL; 98 + epf->num_db = 0; 99 + } 100 + EXPORT_SYMBOL_GPL(pci_epf_free_doorbell);
+39 -1
drivers/pci/endpoint/pci-epf-core.c
··· 338 338 mutex_lock(&pci_epf_mutex); 339 339 list_for_each_entry_safe(group, tmp, &driver->epf_group, group_entry) 340 340 pci_ep_cfs_remove_epf_group(group); 341 - list_del(&driver->epf_group); 341 + WARN_ON(!list_empty(&driver->epf_group)); 342 342 mutex_unlock(&pci_epf_mutex); 343 343 } 344 344 ··· 476 476 return epf; 477 477 } 478 478 EXPORT_SYMBOL_GPL(pci_epf_create); 479 + 480 + /** 481 + * pci_epf_align_inbound_addr() - Align the given address based on the BAR 482 + * alignment requirement 483 + * @epf: the EPF device 484 + * @addr: inbound address to be aligned 485 + * @bar: the BAR number corresponding to the given addr 486 + * @base: base address matching the @bar alignment requirement 487 + * @off: offset to be added to the @base address 488 + * 489 + * Helper function to align input @addr based on BAR's alignment requirement. 490 + * The aligned base address and offset are returned via @base and @off. 491 + * 492 + * NOTE: The pci_epf_alloc_space() function already accounts for alignment. 493 + * This API is primarily intended for use with other memory regions not 494 + * allocated by pci_epf_alloc_space(), such as peripheral register spaces or 495 + * the message address of a platform MSI controller. 496 + * 497 + * Return: 0 on success, errno otherwise. 498 + */ 499 + int pci_epf_align_inbound_addr(struct pci_epf *epf, enum pci_barno bar, 500 + u64 addr, dma_addr_t *base, size_t *off) 501 + { 502 + /* 503 + * Most EP controllers require the BAR start address to be aligned to 504 + * the BAR size, because they mask off the lower bits. 505 + * 506 + * Alignment to BAR size also works for controllers that support 507 + * unaligned addresses. 508 + */ 509 + u64 align = epf->bar[bar].size; 510 + 511 + *base = round_down(addr, align); 512 + *off = addr & (align - 1); 513 + 514 + return 0; 515 + } 516 + EXPORT_SYMBOL_GPL(pci_epf_align_inbound_addr); 479 517 480 518 static void pci_epf_dev_release(struct device *dev) 481 519 {
-4
drivers/pci/hotplug/TODO
··· 2 2 3 3 cpcihp: 4 4 5 - * There are no implementations of the ->hardware_test, ->get_power and 6 - ->set_power callbacks in struct cpci_hp_controller_ops. Why were they 7 - introduced? Can they be removed from the struct? 8 - 9 5 * Returned code from pci_hp_add_bridge() is not checked. 10 6 11 7 cpqphp:
+1 -1
drivers/pci/hotplug/pciehp_hpc.c
··· 995 995 996 996 while (bus->parent) { 997 997 bus = bus->parent; 998 - if (bus->self && bus->self->is_hotplug_bridge) 998 + if (bus->self && bus->self->is_pciehp) 999 999 depth++; 1000 1000 } 1001 1001
+142 -11
drivers/pci/iov.c
··· 7 7 * Copyright (C) 2009 Intel Corporation, Yu Zhao <yu.zhao@intel.com> 8 8 */ 9 9 10 + #include <linux/bitfield.h> 11 + #include <linux/bits.h> 12 + #include <linux/log2.h> 10 13 #include <linux/pci.h> 14 + #include <linux/sizes.h> 11 15 #include <linux/slab.h> 12 16 #include <linux/export.h> 13 17 #include <linux/string.h> 14 18 #include <linux/delay.h> 19 + #include <asm/div64.h> 15 20 #include "pci.h" 16 21 17 22 #define VIRTFN_ID_LEN 17 /* "virtfn%u\0" for 2^32 - 1 */ ··· 155 150 if (!dev->is_physfn) 156 151 return 0; 157 152 158 - return dev->sriov->barsz[resno - PCI_IOV_RESOURCES]; 153 + return dev->sriov->barsz[pci_resource_num_to_vf_bar(resno)]; 154 + } 155 + 156 + void pci_iov_resource_set_size(struct pci_dev *dev, int resno, 157 + resource_size_t size) 158 + { 159 + if (!pci_resource_is_iov(resno)) { 160 + pci_warn(dev, "%s is not an IOV resource\n", 161 + pci_resource_name(dev, resno)); 162 + return; 163 + } 164 + 165 + dev->sriov->barsz[pci_resource_num_to_vf_bar(resno)] = size; 166 + } 167 + 168 + bool pci_iov_is_memory_decoding_enabled(struct pci_dev *dev) 169 + { 170 + u16 cmd; 171 + 172 + pci_read_config_word(dev, dev->sriov->pos + PCI_SRIOV_CTRL, &cmd); 173 + 174 + return cmd & PCI_SRIOV_CTRL_MSE; 159 175 } 160 176 161 177 static void pci_read_vf_config_common(struct pci_dev *virtfn) ··· 367 341 virtfn->multifunction = 0; 368 342 369 343 for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { 370 - res = &dev->resource[i + PCI_IOV_RESOURCES]; 344 + int idx = pci_resource_num_from_vf_bar(i); 345 + 346 + res = &dev->resource[idx]; 371 347 if (!res->parent) 372 348 continue; 373 349 virtfn->resource[i].name = pci_name(virtfn); 374 350 virtfn->resource[i].flags = res->flags; 375 - size = pci_iov_resource_size(dev, i + PCI_IOV_RESOURCES); 351 + size = pci_iov_resource_size(dev, idx); 376 352 resource_set_range(&virtfn->resource[i], 377 353 res->start + size * id, size); 378 354 rc = request_resource(res, &virtfn->resource[i]); ··· 671 643 672 644 nres = 0; 673 645 for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { 674 - bars |= (1 << (i + PCI_IOV_RESOURCES)); 675 - res = &dev->resource[i + PCI_IOV_RESOURCES]; 646 + int idx = pci_resource_num_from_vf_bar(i); 647 + resource_size_t vf_bar_sz = pci_iov_resource_size(dev, idx); 648 + 649 + bars |= (1 << idx); 650 + res = &dev->resource[idx]; 651 + if (vf_bar_sz * nr_virtfn > resource_size(res)) 652 + continue; 676 653 if (res->parent) 677 654 nres++; 678 655 } ··· 843 810 844 811 nres = 0; 845 812 for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { 846 - res = &dev->resource[i + PCI_IOV_RESOURCES]; 847 - res_name = pci_resource_name(dev, i + PCI_IOV_RESOURCES); 813 + int idx = pci_resource_num_from_vf_bar(i); 814 + 815 + res = &dev->resource[idx]; 816 + res_name = pci_resource_name(dev, idx); 848 817 849 818 /* 850 819 * If it is already FIXED, don't change it, something ··· 885 850 pci_read_config_byte(dev, pos + PCI_SRIOV_FUNC_LINK, &iov->link); 886 851 if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END) 887 852 iov->link = PCI_DEVFN(PCI_SLOT(dev->devfn), iov->link); 853 + iov->vf_rebar_cap = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_VF_REBAR); 888 854 889 855 if (pdev) 890 856 iov->dev = pci_dev_get(pdev); ··· 905 869 dev->is_physfn = 0; 906 870 failed: 907 871 for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { 908 - res = &dev->resource[i + PCI_IOV_RESOURCES]; 872 + res = &dev->resource[pci_resource_num_from_vf_bar(i)]; 909 873 res->flags = 0; 910 874 } 911 875 ··· 922 886 923 887 kfree(dev->sriov); 924 888 dev->sriov = NULL; 889 + } 890 + 891 + static void sriov_restore_vf_rebar_state(struct pci_dev *dev) 892 + { 893 + unsigned int pos, nbars, i; 894 + u32 ctrl; 895 + 896 + pos = pci_iov_vf_rebar_cap(dev); 897 + if (!pos) 898 + return; 899 + 900 + pci_read_config_dword(dev, pos + PCI_VF_REBAR_CTRL, &ctrl); 901 + nbars = FIELD_GET(PCI_VF_REBAR_CTRL_NBAR_MASK, ctrl); 902 + 903 + for (i = 0; i < nbars; i++, pos += 8) { 904 + int bar_idx, size; 905 + 906 + pci_read_config_dword(dev, pos + PCI_VF_REBAR_CTRL, &ctrl); 907 + bar_idx = FIELD_GET(PCI_VF_REBAR_CTRL_BAR_IDX, ctrl); 908 + size = pci_rebar_bytes_to_size(dev->sriov->barsz[bar_idx]); 909 + ctrl &= ~PCI_VF_REBAR_CTRL_BAR_SIZE; 910 + ctrl |= FIELD_PREP(PCI_VF_REBAR_CTRL_BAR_SIZE, size); 911 + pci_write_config_dword(dev, pos + PCI_VF_REBAR_CTRL, ctrl); 912 + } 925 913 } 926 914 927 915 static void sriov_restore_state(struct pci_dev *dev) ··· 967 907 pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, ctrl); 968 908 969 909 for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) 970 - pci_update_resource(dev, i + PCI_IOV_RESOURCES); 910 + pci_update_resource(dev, pci_resource_num_from_vf_bar(i)); 971 911 972 912 pci_write_config_dword(dev, iov->pos + PCI_SRIOV_SYS_PGSIZE, iov->pgsz); 973 913 pci_iov_set_numvfs(dev, iov->num_VFs); ··· 1033 973 { 1034 974 struct pci_sriov *iov = dev->is_physfn ? dev->sriov : NULL; 1035 975 struct resource *res = pci_resource_n(dev, resno); 1036 - int vf_bar = resno - PCI_IOV_RESOURCES; 976 + int vf_bar = pci_resource_num_to_vf_bar(resno); 1037 977 struct pci_bus_region region; 1038 978 u16 cmd; 1039 979 u32 new; ··· 1107 1047 */ 1108 1048 void pci_restore_iov_state(struct pci_dev *dev) 1109 1049 { 1110 - if (dev->is_physfn) 1050 + if (dev->is_physfn) { 1051 + sriov_restore_vf_rebar_state(dev); 1111 1052 sriov_restore_state(dev); 1053 + } 1112 1054 } 1113 1055 1114 1056 /** ··· 1317 1255 return nr_virtfn; 1318 1256 } 1319 1257 EXPORT_SYMBOL_GPL(pci_sriov_configure_simple); 1258 + 1259 + /** 1260 + * pci_iov_vf_bar_set_size - set a new size for a VF BAR 1261 + * @dev: the PCI device 1262 + * @resno: the resource number 1263 + * @size: new size as defined in the spec (0=1MB, 31=128TB) 1264 + * 1265 + * Set the new size of a VF BAR that supports VF resizable BAR capability. 1266 + * Unlike pci_resize_resource(), this does not cause the resource that 1267 + * reserves the MMIO space (originally up to total_VFs) to be resized, which 1268 + * means that following calls to pci_enable_sriov() can fail if the resources 1269 + * no longer fit. 1270 + * 1271 + * Return: 0 on success, or negative on failure. 1272 + */ 1273 + int pci_iov_vf_bar_set_size(struct pci_dev *dev, int resno, int size) 1274 + { 1275 + u32 sizes; 1276 + int ret; 1277 + 1278 + if (!pci_resource_is_iov(resno)) 1279 + return -EINVAL; 1280 + 1281 + if (pci_iov_is_memory_decoding_enabled(dev)) 1282 + return -EBUSY; 1283 + 1284 + sizes = pci_rebar_get_possible_sizes(dev, resno); 1285 + if (!sizes) 1286 + return -ENOTSUPP; 1287 + 1288 + if (!(sizes & BIT(size))) 1289 + return -EINVAL; 1290 + 1291 + ret = pci_rebar_set_size(dev, resno, size); 1292 + if (ret) 1293 + return ret; 1294 + 1295 + pci_iov_resource_set_size(dev, resno, pci_rebar_size_to_bytes(size)); 1296 + 1297 + return 0; 1298 + } 1299 + EXPORT_SYMBOL_GPL(pci_iov_vf_bar_set_size); 1300 + 1301 + /** 1302 + * pci_iov_vf_bar_get_sizes - get VF BAR sizes allowing to create up to num_vfs 1303 + * @dev: the PCI device 1304 + * @resno: the resource number 1305 + * @num_vfs: number of VFs 1306 + * 1307 + * Get the sizes of a VF resizable BAR that can accommodate @num_vfs within 1308 + * the currently assigned size of the resource @resno. 1309 + * 1310 + * Return: A bitmask of sizes in format defined in the spec (bit 0=1MB, 1311 + * bit 31=128TB). 1312 + */ 1313 + u32 pci_iov_vf_bar_get_sizes(struct pci_dev *dev, int resno, int num_vfs) 1314 + { 1315 + u64 vf_len = pci_resource_len(dev, resno); 1316 + u32 sizes; 1317 + 1318 + if (!num_vfs) 1319 + return 0; 1320 + 1321 + do_div(vf_len, num_vfs); 1322 + sizes = (roundup_pow_of_two(vf_len + 1) - 1) >> ilog2(SZ_1M); 1323 + 1324 + return sizes & pci_rebar_get_possible_sizes(dev, resno); 1325 + } 1326 + EXPORT_SYMBOL_GPL(pci_iov_vf_bar_get_sizes);
+1 -1
drivers/pci/msi/msi.c
··· 943 943 /* 944 944 * This is a horrible hack, but short of implementing a PCI 945 945 * specific interrupt chip callback and a huge pile of 946 - * infrastructure, this is the minor nuissance. It provides the 946 + * infrastructure, this is the minor nuisance. It provides the 947 947 * protection against concurrent operations on this entry and keeps 948 948 * the control word cache in sync. 949 949 */
+1 -6
drivers/pci/pci-acpi.c
··· 816 816 bool pciehp_is_native(struct pci_dev *bridge) 817 817 { 818 818 const struct pci_host_bridge *host; 819 - u32 slot_cap; 820 819 821 820 if (!IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE)) 822 - return false; 823 - 824 - pcie_capability_read_dword(bridge, PCI_EXP_SLTCAP, &slot_cap); 825 - if (!(slot_cap & PCI_EXP_SLTCAP_HPC)) 826 821 return false; 827 822 828 823 if (pcie_ports_native) ··· 997 1002 struct acpi_device *adev, *rpadev; 998 1003 const union acpi_object *obj; 999 1004 1000 - if (acpi_pci_disabled || !dev->is_hotplug_bridge) 1005 + if (acpi_pci_disabled || !dev->is_pciehp) 1001 1006 return false; 1002 1007 1003 1008 adev = ACPI_COMPANION(&dev->dev);
+3 -3
drivers/pci/pci-driver.c
··· 1632 1632 */ 1633 1633 static int pci_dma_configure(struct device *dev) 1634 1634 { 1635 - struct pci_driver *driver = to_pci_driver(dev->driver); 1635 + const struct device_driver *drv = READ_ONCE(dev->driver); 1636 1636 struct device *bridge; 1637 1637 int ret = 0; 1638 1638 ··· 1649 1649 1650 1650 pci_put_host_bridge_device(bridge); 1651 1651 1652 - /* @driver may not be valid when we're called from the IOMMU layer */ 1653 - if (!ret && dev->driver && !driver->driver_managed_dma) { 1652 + /* @drv may not be valid when we're called from the IOMMU layer */ 1653 + if (!ret && drv && !to_pci_driver(drv)->driver_managed_dma) { 1654 1654 ret = iommu_device_use_default_domain(dev); 1655 1655 if (ret) 1656 1656 arch_teardown_dma_ops(dev);
+20 -10
drivers/pci/pci.c
··· 3030 3030 * pci_bridge_d3_possible - Is it possible to put the bridge into D3 3031 3031 * @bridge: Bridge to check 3032 3032 * 3033 - * This function checks if it is possible to move the bridge to D3. 3034 3033 * Currently we only allow D3 for some PCIe ports and for Thunderbolt. 3034 + * 3035 + * Return: Whether it is possible to move the bridge to D3. 3036 + * 3037 + * The return value is guaranteed to be constant across the entire lifetime 3038 + * of the bridge, including its hot-removal. 3035 3039 */ 3036 3040 bool pci_bridge_d3_possible(struct pci_dev *bridge) 3037 3041 { ··· 3050 3046 return false; 3051 3047 3052 3048 /* 3053 - * Hotplug ports handled by firmware in System Management Mode 3054 - * may not be put into D3 by the OS (Thunderbolt on non-Macs). 3049 + * Hotplug ports handled by platform firmware may not be put 3050 + * into D3 by the OS, e.g. ACPI slots ... 3055 3051 */ 3056 - if (bridge->is_hotplug_bridge && !pciehp_is_native(bridge)) 3052 + if (bridge->is_hotplug_bridge && !bridge->is_pciehp) 3053 + return false; 3054 + 3055 + /* ... or PCIe hotplug ports not handled natively by the OS. */ 3056 + if (bridge->is_pciehp && !pciehp_is_native(bridge)) 3057 3057 return false; 3058 3058 3059 3059 if (pci_bridge_d3_force) ··· 3076 3068 * by vendors for runtime D3 at least until 2018 because there 3077 3069 * was no OS support. 3078 3070 */ 3079 - if (bridge->is_hotplug_bridge) 3071 + if (bridge->is_pciehp) 3080 3072 return false; 3081 3073 3082 3074 if (dmi_check_system(bridge_d3_blacklist)) ··· 3213 3205 void pci_pm_init(struct pci_dev *dev) 3214 3206 { 3215 3207 int pm; 3216 - u16 status; 3217 3208 u16 pmc; 3218 3209 3219 3210 device_enable_async_suspend(&dev->dev); ··· 3273 3266 pci_pme_active(dev, false); 3274 3267 } 3275 3268 3276 - pci_read_config_word(dev, PCI_STATUS, &status); 3277 - if (status & PCI_STATUS_IMM_READY) 3278 - dev->imm_ready = 1; 3279 3269 poweron: 3280 3270 pci_pm_power_up_and_verify_state(dev); 3281 3271 pm_runtime_forbid(&dev->dev); ··· 3757 3753 unsigned int pos, nbars, i; 3758 3754 u32 ctrl; 3759 3755 3760 - pos = pdev->rebar_cap; 3756 + if (pci_resource_is_iov(bar)) { 3757 + pos = pci_iov_vf_rebar_cap(pdev); 3758 + bar = pci_resource_num_to_vf_bar(bar); 3759 + } else { 3760 + pos = pdev->rebar_cap; 3761 + } 3762 + 3761 3763 if (!pos) 3762 3764 return -ENOTSUPP; 3763 3765
+63 -21
drivers/pci/pci.h
··· 36 36 #define PCIE_T_PERST_CLK_US 100 37 37 38 38 /* 39 - * End of conventional reset (PERST# de-asserted) to first configuration 40 - * request (device able to respond with a "Request Retry Status" completion), 41 - * from PCIe r6.0, sec 6.6.1. 42 - */ 43 - #define PCIE_T_RRS_READY_MS 100 44 - 45 - /* 46 39 * PCIe r6.0, sec 5.3.3.2.1 <PME Synchronization> 47 40 * Recommends 1ms to 10ms timeout to check L2 ready. 48 41 */ ··· 54 61 * completes before sending a Configuration Request to the device 55 62 * immediately below that Port." 56 63 */ 57 - #define PCIE_RESET_CONFIG_DEVICE_WAIT_MS 100 64 + #define PCIE_RESET_CONFIG_WAIT_MS 100 65 + 66 + /* Parameters for the waiting for link up routine */ 67 + #define PCIE_LINK_WAIT_MAX_RETRIES 10 68 + #define PCIE_LINK_WAIT_SLEEP_MS 90 58 69 59 70 /* Message Routing (r[2:0]); PCIe r6.0, sec 2.2.8 */ 60 71 #define PCIE_MSG_TYPE_R_RC 0 ··· 388 391 389 392 #define PCIE_LNKCAP_SLS2SPEED(lnkcap) \ 390 393 ({ \ 391 - ((lnkcap) == PCI_EXP_LNKCAP_SLS_64_0GB ? PCIE_SPEED_64_0GT : \ 392 - (lnkcap) == PCI_EXP_LNKCAP_SLS_32_0GB ? PCIE_SPEED_32_0GT : \ 393 - (lnkcap) == PCI_EXP_LNKCAP_SLS_16_0GB ? PCIE_SPEED_16_0GT : \ 394 - (lnkcap) == PCI_EXP_LNKCAP_SLS_8_0GB ? PCIE_SPEED_8_0GT : \ 395 - (lnkcap) == PCI_EXP_LNKCAP_SLS_5_0GB ? PCIE_SPEED_5_0GT : \ 396 - (lnkcap) == PCI_EXP_LNKCAP_SLS_2_5GB ? PCIE_SPEED_2_5GT : \ 394 + u32 lnkcap_sls = (lnkcap) & PCI_EXP_LNKCAP_SLS; \ 395 + \ 396 + (lnkcap_sls == PCI_EXP_LNKCAP_SLS_64_0GB ? PCIE_SPEED_64_0GT : \ 397 + lnkcap_sls == PCI_EXP_LNKCAP_SLS_32_0GB ? PCIE_SPEED_32_0GT : \ 398 + lnkcap_sls == PCI_EXP_LNKCAP_SLS_16_0GB ? PCIE_SPEED_16_0GT : \ 399 + lnkcap_sls == PCI_EXP_LNKCAP_SLS_8_0GB ? PCIE_SPEED_8_0GT : \ 400 + lnkcap_sls == PCI_EXP_LNKCAP_SLS_5_0GB ? PCIE_SPEED_5_0GT : \ 401 + lnkcap_sls == PCI_EXP_LNKCAP_SLS_2_5GB ? PCIE_SPEED_2_5GT : \ 397 402 PCI_SPEED_UNKNOWN); \ 398 403 }) 399 404 ··· 410 411 PCI_SPEED_UNKNOWN) 411 412 412 413 #define PCIE_LNKCTL2_TLS2SPEED(lnkctl2) \ 413 - ((lnkctl2) == PCI_EXP_LNKCTL2_TLS_64_0GT ? PCIE_SPEED_64_0GT : \ 414 - (lnkctl2) == PCI_EXP_LNKCTL2_TLS_32_0GT ? PCIE_SPEED_32_0GT : \ 415 - (lnkctl2) == PCI_EXP_LNKCTL2_TLS_16_0GT ? PCIE_SPEED_16_0GT : \ 416 - (lnkctl2) == PCI_EXP_LNKCTL2_TLS_8_0GT ? PCIE_SPEED_8_0GT : \ 417 - (lnkctl2) == PCI_EXP_LNKCTL2_TLS_5_0GT ? PCIE_SPEED_5_0GT : \ 418 - (lnkctl2) == PCI_EXP_LNKCTL2_TLS_2_5GT ? PCIE_SPEED_2_5GT : \ 419 - PCI_SPEED_UNKNOWN) 414 + ({ \ 415 + u16 lnkctl2_tls = (lnkctl2) & PCI_EXP_LNKCTL2_TLS; \ 416 + \ 417 + (lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_64_0GT ? PCIE_SPEED_64_0GT : \ 418 + lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_32_0GT ? PCIE_SPEED_32_0GT : \ 419 + lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_16_0GT ? PCIE_SPEED_16_0GT : \ 420 + lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_8_0GT ? PCIE_SPEED_8_0GT : \ 421 + lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_5_0GT ? PCIE_SPEED_5_0GT : \ 422 + lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_2_5GT ? PCIE_SPEED_2_5GT : \ 423 + PCI_SPEED_UNKNOWN); \ 424 + }) 420 425 421 426 /* PCIe speed to Mb/s reduced by encoding overhead */ 422 427 #define PCIE_SPEED2MBS_ENC(speed) \ ··· 489 486 u16 subsystem_vendor; /* VF subsystem vendor */ 490 487 u16 subsystem_device; /* VF subsystem device */ 491 488 resource_size_t barsz[PCI_SRIOV_NUM_BARS]; /* VF BAR size */ 489 + u16 vf_rebar_cap; /* VF Resizable BAR capability offset */ 492 490 bool drivers_autoprobe; /* Auto probing of VFs by driver */ 493 491 }; 494 492 ··· 714 710 resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno); 715 711 void pci_restore_iov_state(struct pci_dev *dev); 716 712 int pci_iov_bus_range(struct pci_bus *bus); 713 + void pci_iov_resource_set_size(struct pci_dev *dev, int resno, 714 + resource_size_t size); 715 + bool pci_iov_is_memory_decoding_enabled(struct pci_dev *dev); 716 + static inline u16 pci_iov_vf_rebar_cap(struct pci_dev *dev) 717 + { 718 + if (!dev->is_physfn) 719 + return 0; 720 + 721 + return dev->sriov->vf_rebar_cap; 722 + } 717 723 static inline bool pci_resource_is_iov(int resno) 718 724 { 719 725 return resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END; 726 + } 727 + static inline int pci_resource_num_from_vf_bar(int resno) 728 + { 729 + return resno + PCI_IOV_RESOURCES; 730 + } 731 + static inline int pci_resource_num_to_vf_bar(int resno) 732 + { 733 + return resno - PCI_IOV_RESOURCES; 720 734 } 721 735 extern const struct attribute_group sriov_pf_dev_attr_group; 722 736 extern const struct attribute_group sriov_vf_dev_attr_group; ··· 756 734 { 757 735 return 0; 758 736 } 737 + static inline void pci_iov_resource_set_size(struct pci_dev *dev, int resno, 738 + resource_size_t size) { } 739 + static inline bool pci_iov_is_memory_decoding_enabled(struct pci_dev *dev) 740 + { 741 + return false; 742 + } 743 + static inline u16 pci_iov_vf_rebar_cap(struct pci_dev *dev) 744 + { 745 + return 0; 746 + } 759 747 static inline bool pci_resource_is_iov(int resno) 760 748 { 761 749 return false; 750 + } 751 + static inline int pci_resource_num_from_vf_bar(int resno) 752 + { 753 + WARN_ON_ONCE(1); 754 + return -ENODEV; 755 + } 756 + static inline int pci_resource_num_to_vf_bar(int resno) 757 + { 758 + WARN_ON_ONCE(1); 759 + return -ENODEV; 762 760 } 763 761 #endif /* CONFIG_PCI_IOV */ 764 762
+4 -3
drivers/pci/pcie/aer.c
··· 116 116 PCI_ERR_ROOT_MULTI_COR_RCV | \ 117 117 PCI_ERR_ROOT_MULTI_UNCOR_RCV) 118 118 119 - static int pcie_aer_disable; 119 + static bool pcie_aer_disable; 120 120 static pci_ers_result_t aer_root_reset(struct pci_dev *dev); 121 121 122 122 void pci_no_aer(void) 123 123 { 124 - pcie_aer_disable = 1; 124 + pcie_aer_disable = true; 125 125 } 126 126 127 127 bool pci_aer_available(void) ··· 1039 1039 /* List this device */ 1040 1040 if (add_error_device(e_info, dev)) { 1041 1041 /* We cannot handle more... Stop iteration */ 1042 - /* TODO: Should print error message here? */ 1042 + pci_err(dev, "Exceeded max supported (%d) devices with errors logged\n", 1043 + AER_MAX_MULTI_ERR_DEVICES); 1043 1044 return 1; 1044 1045 } 1045 1046
+5 -6
drivers/pci/pcie/aspm.c
··· 245 245 u32 clkpm_disable:1; /* Clock PM disabled */ 246 246 }; 247 247 248 - static int aspm_disabled, aspm_force; 248 + static bool aspm_disabled, aspm_force; 249 249 static bool aspm_support_enabled = true; 250 250 static DEFINE_MUTEX(aspm_lock); 251 251 static LIST_HEAD(link_list); ··· 884 884 /* Configure the ASPM L1 substates. Caller must disable L1 first. */ 885 885 static void pcie_config_aspm_l1ss(struct pcie_link_state *link, u32 state) 886 886 { 887 - u32 val; 887 + u32 val = 0; 888 888 struct pci_dev *child = link->downstream, *parent = link->pdev; 889 889 890 - val = 0; 891 890 if (state & PCIE_LINK_STATE_L1_1) 892 891 val |= PCI_L1SS_CTL1_ASPM_L1_1; 893 892 if (state & PCIE_LINK_STATE_L1_2) ··· 1711 1712 { 1712 1713 if (!strcmp(str, "off")) { 1713 1714 aspm_policy = POLICY_DEFAULT; 1714 - aspm_disabled = 1; 1715 + aspm_disabled = true; 1715 1716 aspm_support_enabled = false; 1716 1717 pr_info("PCIe ASPM is disabled\n"); 1717 1718 } else if (!strcmp(str, "force")) { 1718 - aspm_force = 1; 1719 + aspm_force = true; 1719 1720 pr_info("PCIe ASPM is forcibly enabled\n"); 1720 1721 } 1721 1722 return 1; ··· 1733 1734 */ 1734 1735 if (!aspm_force) { 1735 1736 aspm_policy = POLICY_DEFAULT; 1736 - aspm_disabled = 1; 1737 + aspm_disabled = true; 1737 1738 } 1738 1739 } 1739 1740
+1 -1
drivers/pci/pcie/portdrv.c
··· 220 220 struct pci_host_bridge *host = pci_find_host_bridge(dev->bus); 221 221 int services = 0; 222 222 223 - if (dev->is_hotplug_bridge && 223 + if (dev->is_pciehp && 224 224 (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT || 225 225 pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) && 226 226 (pcie_ports_native || host->native_pcie_hotplug)) {
+1 -1
drivers/pci/pcie/ptm.c
··· 507 507 if (!ops->check_capability) 508 508 return NULL; 509 509 510 - /* Check for PTM capability before creating debugfs attrbutes */ 510 + /* Check for PTM capability before creating debugfs attributes */ 511 511 ret = ops->check_capability(pdata); 512 512 if (!ret) { 513 513 dev_dbg(dev, "PTM capability not present\n");
+11 -1
drivers/pci/probe.c
··· 1678 1678 1679 1679 pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &reg32); 1680 1680 if (reg32 & PCI_EXP_SLTCAP_HPC) 1681 - pdev->is_hotplug_bridge = 1; 1681 + pdev->is_hotplug_bridge = pdev->is_pciehp = 1; 1682 1682 } 1683 1683 1684 1684 static void set_pcie_thunderbolt(struct pci_dev *dev) ··· 2602 2602 __pcie_print_link_status(dev, false); 2603 2603 } 2604 2604 2605 + static void pci_imm_ready_init(struct pci_dev *dev) 2606 + { 2607 + u16 status; 2608 + 2609 + pci_read_config_word(dev, PCI_STATUS, &status); 2610 + if (status & PCI_STATUS_IMM_READY) 2611 + dev->imm_ready = 1; 2612 + } 2613 + 2605 2614 static void pci_init_capabilities(struct pci_dev *dev) 2606 2615 { 2607 2616 pci_ea_init(dev); /* Enhanced Allocation */ ··· 2620 2611 /* Buffers for saving PCIe and PCI-X capabilities */ 2621 2612 pci_allocate_cap_save_buffers(dev); 2622 2613 2614 + pci_imm_ready_init(dev); /* Immediate Readiness */ 2623 2615 pci_pm_init(dev); /* Power Management */ 2624 2616 pci_vpd_init(dev); /* Vital Product Data */ 2625 2617 pci_configure_ari(dev); /* Alternative Routing-ID Forwarding */
+4 -2
drivers/pci/quirks.c
··· 105 105 !pcie_cap_has_lnkctl2(dev) || !dev->link_active_reporting) 106 106 return ret; 107 107 108 - pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &lnkctl2); 109 108 pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta); 110 109 if (!(lnksta & PCI_EXP_LNKSTA_DLLLA) && pcie_lbms_seen(dev, lnksta)) { 111 - u16 oldlnkctl2 = lnkctl2; 110 + u16 oldlnkctl2; 112 111 113 112 pci_info(dev, "broken device, retraining non-functional downstream link at 2.5GT/s\n"); 114 113 114 + pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &oldlnkctl2); 115 115 ret = pcie_set_target_speed(dev, PCIE_SPEED_2_5GT, false); 116 116 if (ret) { 117 117 pci_info(dev, "retraining failed\n"); ··· 122 122 123 123 pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta); 124 124 } 125 + 126 + pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &lnkctl2); 125 127 126 128 if ((lnksta & PCI_EXP_LNKSTA_DLLLA) && 127 129 (lnkctl2 & PCI_EXP_LNKCTL2_TLS) == PCI_EXP_LNKCTL2_TLS_2_5GT &&
+2 -1
drivers/pci/setup-bus.c
··· 1888 1888 bool *unassigned = data; 1889 1889 1890 1890 for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { 1891 - struct resource *r = &dev->resource[i + PCI_IOV_RESOURCES]; 1891 + int idx = pci_resource_num_from_vf_bar(i); 1892 + struct resource *r = &dev->resource[idx]; 1892 1893 struct pci_bus_region region; 1893 1894 1894 1895 /* Not assigned or rejected by kernel? */
+30 -5
drivers/pci/setup-res.c
··· 423 423 } 424 424 EXPORT_SYMBOL(pci_release_resource); 425 425 426 + static bool pci_resize_is_memory_decoding_enabled(struct pci_dev *dev, 427 + int resno) 428 + { 429 + u16 cmd; 430 + 431 + if (pci_resource_is_iov(resno)) 432 + return pci_iov_is_memory_decoding_enabled(dev); 433 + 434 + pci_read_config_word(dev, PCI_COMMAND, &cmd); 435 + 436 + return cmd & PCI_COMMAND_MEMORY; 437 + } 438 + 439 + static void pci_resize_resource_set_size(struct pci_dev *dev, int resno, 440 + int size) 441 + { 442 + resource_size_t res_size = pci_rebar_size_to_bytes(size); 443 + struct resource *res = pci_resource_n(dev, resno); 444 + 445 + if (!pci_resource_is_iov(resno)) { 446 + resource_set_size(res, res_size); 447 + } else { 448 + resource_set_size(res, res_size * pci_sriov_get_totalvfs(dev)); 449 + pci_iov_resource_set_size(dev, resno, res_size); 450 + } 451 + } 452 + 426 453 int pci_resize_resource(struct pci_dev *dev, int resno, int size) 427 454 { 428 455 struct resource *res = pci_resource_n(dev, resno); 429 456 struct pci_host_bridge *host; 430 457 int old, ret; 431 458 u32 sizes; 432 - u16 cmd; 433 459 434 460 /* Check if we must preserve the firmware's resource assignment */ 435 461 host = pci_find_host_bridge(dev->bus); ··· 466 440 if (!(res->flags & IORESOURCE_UNSET)) 467 441 return -EBUSY; 468 442 469 - pci_read_config_word(dev, PCI_COMMAND, &cmd); 470 - if (cmd & PCI_COMMAND_MEMORY) 443 + if (pci_resize_is_memory_decoding_enabled(dev, resno)) 471 444 return -EBUSY; 472 445 473 446 sizes = pci_rebar_get_possible_sizes(dev, resno); ··· 484 459 if (ret) 485 460 return ret; 486 461 487 - resource_set_size(res, pci_rebar_size_to_bytes(size)); 462 + pci_resize_resource_set_size(dev, resno, size); 488 463 489 464 /* Check if the new config works by trying to assign everything. */ 490 465 if (dev->bus->self) { ··· 496 471 497 472 error_resize: 498 473 pci_rebar_set_size(dev, resno, old); 499 - resource_set_size(res, pci_rebar_size_to_bytes(old)); 474 + pci_resize_resource_set_size(dev, resno, old); 500 475 return ret; 501 476 } 502 477 EXPORT_SYMBOL(pci_resize_resource);
+1 -2
drivers/vfio/pci/vfio_pci_igd.c
··· 437 437 438 438 bool vfio_pci_is_intel_display(struct pci_dev *pdev) 439 439 { 440 - return (pdev->vendor == PCI_VENDOR_ID_INTEL) && 441 - ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY); 440 + return (pdev->vendor == PCI_VENDOR_ID_INTEL) && pci_is_display(pdev); 442 441 } 443 442 444 443 int vfio_pci_igd_init(struct vfio_pci_core_device *vdev)
-1
include/linux/cpuhotplug.h
··· 90 90 CPUHP_RADIX_DEAD, 91 91 CPUHP_PAGE_ALLOC, 92 92 CPUHP_NET_DEV_DEAD, 93 - CPUHP_PCI_XGENE_DEAD, 94 93 CPUHP_IOMMU_IOVA_DEAD, 95 94 CPUHP_AP_ARM_CACHE_B15_RAC_DEAD, 96 95 CPUHP_PADATA_DEAD,
+3
include/linux/hypervisor.h
··· 37 37 if (IS_ENABLED(CONFIG_S390)) 38 38 return true; 39 39 40 + if (IS_ENABLED(CONFIG_LOONGARCH)) 41 + return true; 42 + 40 43 return jailhouse_paravirt(); 41 44 } 42 45
+28
include/linux/pci-ep-msi.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * PCI Endpoint *Function* side MSI header file 4 + * 5 + * Copyright (C) 2024 NXP 6 + * Author: Frank Li <Frank.Li@nxp.com> 7 + */ 8 + 9 + #ifndef __PCI_EP_MSI__ 10 + #define __PCI_EP_MSI__ 11 + 12 + struct pci_epf; 13 + 14 + #ifdef CONFIG_PCI_ENDPOINT_MSI_DOORBELL 15 + int pci_epf_alloc_doorbell(struct pci_epf *epf, u16 nums); 16 + void pci_epf_free_doorbell(struct pci_epf *epf); 17 + #else 18 + static inline int pci_epf_alloc_doorbell(struct pci_epf *epf, u16 nums) 19 + { 20 + return -ENODATA; 21 + } 22 + 23 + static inline void pci_epf_free_doorbell(struct pci_epf *epf) 24 + { 25 + } 26 + #endif /* CONFIG_GENERIC_MSI_IRQ */ 27 + 28 + #endif /* __PCI_EP_MSI__ */
+18
include/linux/pci-epf.h
··· 12 12 #include <linux/configfs.h> 13 13 #include <linux/device.h> 14 14 #include <linux/mod_devicetable.h> 15 + #include <linux/msi.h> 15 16 #include <linux/pci.h> 16 17 17 18 struct pci_epf; ··· 130 129 }; 131 130 132 131 /** 132 + * struct pci_epf_doorbell_msg - represents doorbell message 133 + * @msg: MSI message 134 + * @virq: IRQ number of this doorbell MSI message 135 + */ 136 + struct pci_epf_doorbell_msg { 137 + struct msi_msg msg; 138 + int virq; 139 + }; 140 + 141 + /** 133 142 * struct pci_epf - represents the PCI EPF device 134 143 * @dev: the PCI EPF device 135 144 * @name: the name of the PCI EPF device ··· 166 155 * @vfunction_num_map: bitmap to manage virtual function number 167 156 * @pci_vepf: list of virtual endpoint functions associated with this function 168 157 * @event_ops: callbacks for capturing the EPC events 158 + * @db_msg: data for MSI from RC side 159 + * @num_db: number of doorbells 169 160 */ 170 161 struct pci_epf { 171 162 struct device dev; ··· 198 185 unsigned long vfunction_num_map; 199 186 struct list_head pci_vepf; 200 187 const struct pci_epc_event_ops *event_ops; 188 + struct pci_epf_doorbell_msg *db_msg; 189 + u16 num_db; 201 190 }; 202 191 203 192 /** ··· 241 226 enum pci_epc_interface_type type); 242 227 void pci_epf_free_space(struct pci_epf *epf, void *addr, enum pci_barno bar, 243 228 enum pci_epc_interface_type type); 229 + 230 + int pci_epf_align_inbound_addr(struct pci_epf *epf, enum pci_barno bar, 231 + u64 addr, dma_addr_t *base, size_t *off); 244 232 int pci_epf_bind(struct pci_epf *epf); 245 233 void pci_epf_unbind(struct pci_epf *epf); 246 234 int pci_epf_add_vepf(struct pci_epf *epf_pf, struct pci_epf *epf_vf);
+1 -1
include/linux/pci-pwrctrl.h
··· 39 39 struct pci_pwrctrl { 40 40 struct device *dev; 41 41 42 - /* Private: don't use. */ 42 + /* private: internal use only */ 43 43 struct notifier_block nb; 44 44 struct device_link *link; 45 45 struct work_struct work;
+27
include/linux/pci.h
··· 328 328 * determined (e.g., for Root Complex Integrated 329 329 * Endpoints without the relevant Capability 330 330 * Registers). 331 + * @is_hotplug_bridge: Hotplug bridge of any kind (e.g. PCIe Hot-Plug Capable, 332 + * Conventional PCI Hot-Plug, ACPI slot). 333 + * Such bridges are allocated additional MMIO and bus 334 + * number resources to allow for hierarchy expansion. 335 + * @is_pciehp: PCIe Hot-Plug Capable bridge. 331 336 */ 332 337 struct pci_dev { 333 338 struct list_head bus_list; /* Node in per-bus list */ ··· 456 451 unsigned int is_physfn:1; 457 452 unsigned int is_virtfn:1; 458 453 unsigned int is_hotplug_bridge:1; 454 + unsigned int is_pciehp:1; 459 455 unsigned int shpc_managed:1; /* SHPC owned by shpchp */ 460 456 unsigned int is_thunderbolt:1; /* Thunderbolt controller */ 461 457 /* ··· 748 742 return true; 749 743 750 744 return false; 745 + } 746 + 747 + /** 748 + * pci_is_display - check if the PCI device is a display controller 749 + * @pdev: PCI device 750 + * 751 + * Determine whether the given PCI device corresponds to a display 752 + * controller. Display controllers are typically used for graphical output 753 + * and are identified based on their class code. 754 + * 755 + * Return: true if the PCI device is a display controller, false otherwise. 756 + */ 757 + static inline bool pci_is_display(struct pci_dev *pdev) 758 + { 759 + return (pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY; 751 760 } 752 761 753 762 #define for_each_pci_bridge(dev, bus) \ ··· 2459 2438 int pci_sriov_get_totalvfs(struct pci_dev *dev); 2460 2439 int pci_sriov_configure_simple(struct pci_dev *dev, int nr_virtfn); 2461 2440 resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno); 2441 + int pci_iov_vf_bar_set_size(struct pci_dev *dev, int resno, int size); 2442 + u32 pci_iov_vf_bar_get_sizes(struct pci_dev *dev, int resno, int num_vfs); 2462 2443 void pci_vf_drivers_autoprobe(struct pci_dev *dev, bool probe); 2463 2444 2464 2445 /* Arch may override these (weak) */ ··· 2512 2489 { return 0; } 2513 2490 #define pci_sriov_configure_simple NULL 2514 2491 static inline resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno) 2492 + { return 0; } 2493 + static inline int pci_iov_vf_bar_set_size(struct pci_dev *dev, int resno, int size) 2494 + { return -ENODEV; } 2495 + static inline u32 pci_iov_vf_bar_get_sizes(struct pci_dev *dev, int resno, int num_vfs) 2515 2496 { return 0; } 2516 2497 static inline void pci_vf_drivers_autoprobe(struct pci_dev *dev, bool probe) { } 2517 2498 #endif
+2 -1
include/linux/pci_hotplug.h
··· 104 104 105 105 static inline bool hotplug_is_native(struct pci_dev *bridge) 106 106 { 107 - return pciehp_is_native(bridge) || shpchp_is_native(bridge); 107 + return (bridge->is_pciehp && pciehp_is_native(bridge)) || 108 + shpchp_is_native(bridge); 108 109 } 109 110 #endif
+9
include/uapi/linux/pci_regs.h
··· 745 745 #define PCI_EXT_CAP_ID_L1SS 0x1E /* L1 PM Substates */ 746 746 #define PCI_EXT_CAP_ID_PTM 0x1F /* Precision Time Measurement */ 747 747 #define PCI_EXT_CAP_ID_DVSEC 0x23 /* Designated Vendor-Specific */ 748 + #define PCI_EXT_CAP_ID_VF_REBAR 0x24 /* VF Resizable BAR */ 748 749 #define PCI_EXT_CAP_ID_DLF 0x25 /* Data Link Feature */ 749 750 #define PCI_EXT_CAP_ID_PL_16GT 0x26 /* Physical Layer 16.0 GT/s */ 750 751 #define PCI_EXT_CAP_ID_NPEM 0x29 /* Native PCIe Enclosure Management */ ··· 1141 1140 #define PCI_DVSEC_HEADER1_LEN(x) (((x) >> 20) & 0xfff) 1142 1141 #define PCI_DVSEC_HEADER2 0x8 /* Designated Vendor-Specific Header2 */ 1143 1142 #define PCI_DVSEC_HEADER2_ID(x) ((x) & 0xffff) 1143 + 1144 + /* VF Resizable BARs, same layout as PCI_REBAR */ 1145 + #define PCI_VF_REBAR_CAP PCI_REBAR_CAP 1146 + #define PCI_VF_REBAR_CAP_SIZES PCI_REBAR_CAP_SIZES 1147 + #define PCI_VF_REBAR_CTRL PCI_REBAR_CTRL 1148 + #define PCI_VF_REBAR_CTRL_BAR_IDX PCI_REBAR_CTRL_BAR_IDX 1149 + #define PCI_VF_REBAR_CTRL_NBAR_MASK PCI_REBAR_CTRL_NBAR_MASK 1150 + #define PCI_VF_REBAR_CTRL_BAR_SIZE PCI_REBAR_CTRL_BAR_SIZE 1144 1151 1145 1152 /* Data Link Feature */ 1146 1153 #define PCI_DLF_CAP 0x04 /* Capabilities Register */
+1
include/uapi/linux/pcitest.h
··· 21 21 #define PCITEST_SET_IRQTYPE _IOW('P', 0x8, int) 22 22 #define PCITEST_GET_IRQTYPE _IO('P', 0x9) 23 23 #define PCITEST_BARS _IO('P', 0xa) 24 + #define PCITEST_DOORBELL _IO('P', 0xb) 24 25 #define PCITEST_CLEAR_IRQ _IO('P', 0x10) 25 26 26 27 #define PCITEST_IRQ_TYPE_UNDEFINED -1
+7 -1
kernel/irq/chip.c
··· 611 611 { 612 612 guard(raw_spinlock)(&desc->lock); 613 613 614 - if (!irq_can_handle(desc)) 614 + if (!irq_can_handle_pm(desc)) { 615 + if (irqd_needs_resend_when_in_progress(&desc->irq_data)) 616 + desc->istate |= IRQS_PENDING; 617 + return; 618 + } 619 + 620 + if (!irq_can_handle_actions(desc)) 615 621 return; 616 622 617 623 kstat_incr_irqs_this_cpu(desc);
+2 -2
sound/hda/controllers/intel.c
··· 1464 1464 * the dGPU is the one who is involved in 1465 1465 * vgaswitcheroo. 1466 1466 */ 1467 - if (((p->class >> 16) == PCI_BASE_CLASS_DISPLAY) && 1467 + if (pci_is_display(p) && 1468 1468 (atpx_present() || apple_gmux_detect(NULL, NULL))) 1469 1469 return p; 1470 1470 pci_dev_put(p); ··· 1476 1476 p = pci_get_domain_bus_and_slot(pci_domain_nr(pci->bus), 1477 1477 pci->bus->number, 0); 1478 1478 if (p) { 1479 - if ((p->class >> 16) == PCI_BASE_CLASS_DISPLAY) 1479 + if (pci_is_display(p)) 1480 1480 return p; 1481 1481 pci_dev_put(p); 1482 1482 }
+1 -1
sound/hda/core/i915.c
··· 155 155 156 156 for_each_pci_dev(display_dev) { 157 157 if (display_dev->vendor != PCI_VENDOR_ID_INTEL || 158 - (display_dev->class >> 16) != PCI_BASE_CLASS_DISPLAY) 158 + !pci_is_display(display_dev)) 159 159 continue; 160 160 161 161 if (pci_match_id(denylist, display_dev))
+28
tools/testing/selftests/pci_endpoint/pci_endpoint_test.c
··· 229 229 test_size[i]); 230 230 } 231 231 } 232 + 233 + FIXTURE(pcie_ep_doorbell) 234 + { 235 + int fd; 236 + }; 237 + 238 + FIXTURE_SETUP(pcie_ep_doorbell) 239 + { 240 + self->fd = open(test_device, O_RDWR); 241 + 242 + ASSERT_NE(-1, self->fd) TH_LOG("Can't open PCI Endpoint Test device"); 243 + }; 244 + 245 + FIXTURE_TEARDOWN(pcie_ep_doorbell) 246 + { 247 + close(self->fd); 248 + }; 249 + 250 + TEST_F(pcie_ep_doorbell, DOORBELL_TEST) 251 + { 252 + int ret; 253 + 254 + pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_AUTO); 255 + ASSERT_EQ(0, ret) TH_LOG("Can't set AUTO IRQ type"); 256 + 257 + pci_ep_ioctl(PCITEST_DOORBELL, 0); 258 + EXPECT_FALSE(ret) TH_LOG("Test failed for Doorbell\n"); 259 + } 232 260 TEST_HARNESS_MAIN