From 950334bcf17a6ab55ce13d3bdf050f7b429320d5 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sat, 28 May 2016 18:09:16 -0500 Subject: PCI: Add devm_request_pci_bus_resources() Several host bridge drivers iterate through the list of bridge windows to request resources. Several others don't request the window resources at all. Add a devm_request_pci_bus_resources() interface to make it easier for drivers to request all the window resources. Export to GPL modules (from Arnd Bergmann ). Signed-off-by: Bjorn Helgaas --- drivers/pci/bus.c | 30 +++++++++++++++++++++++++++++- include/linux/pci.h | 5 ++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index dd7cdbee8029..6293ce0f3532 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -91,6 +91,35 @@ void pci_bus_remove_resources(struct pci_bus *bus) } } +int devm_request_pci_bus_resources(struct device *dev, + struct list_head *resources) +{ + struct resource_entry *win; + struct resource *parent, *res; + int err; + + resource_list_for_each_entry(win, resources) { + res = win->res; + switch (resource_type(res)) { + case IORESOURCE_IO: + parent = &ioport_resource; + break; + case IORESOURCE_MEM: + parent = &iomem_resource; + break; + default: + continue; + } + + err = devm_request_resource(dev, parent, res); + if (err) + return err; + } + + return 0; +} +EXPORT_SYMBOL_GPL(devm_request_pci_bus_resources); + static struct pci_bus_region pci_32_bit = {0, 0xffffffffULL}; #ifdef CONFIG_PCI_BUS_ADDR_T_64BIT static struct pci_bus_region pci_64_bit = {0, @@ -397,4 +426,3 @@ void pci_bus_put(struct pci_bus *bus) put_device(&bus->dev); } EXPORT_SYMBOL(pci_bus_put); - diff --git a/include/linux/pci.h b/include/linux/pci.h index b67e4df20801..6ac83606cb0d 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1143,9 +1143,12 @@ void pci_add_resource(struct list_head *resources, struct resource *res); void pci_add_resource_offset(struct list_head *resources, struct resource *res, resource_size_t offset); void pci_free_resource_list(struct list_head *resources); -void pci_bus_add_resource(struct pci_bus *bus, struct resource *res, unsigned int flags); +void pci_bus_add_resource(struct pci_bus *bus, struct resource *res, + unsigned int flags); struct resource *pci_bus_resource_n(const struct pci_bus *bus, int n); void pci_bus_remove_resources(struct pci_bus *bus); +int devm_request_pci_bus_resources(struct device *dev, + struct list_head *resources); #define pci_bus_for_each_resource(bus, res, i) \ for (i = 0; \ -- cgit v1.2.3 From d7d5677c5ac39af5956ac6c88ac59cea052fea78 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 18 May 2016 16:15:53 +0200 Subject: PCI: generic: Select IRQ_DOMAIN The generic PCI host controller calls of_irq_parse_and_map_pci() in its IRQ fixup, but that function is only available when CONFIG_IRQ_DOMAIN is set: drivers/pci/built-in.o: In function `pci_host_common_probe': drivers/pci/host/pci-host-common.c:181: undefined reference to `of_irq_parse_and_map_pci' There is no downside in enabling the domains here, so use a Kconfig select statement to ensure it's always available to this driver. Signed-off-by: Arnd Bergmann Signed-off-by: Bjorn Helgaas --- drivers/pci/host/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index 5d2374e4ee7f..2057f71d855c 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig @@ -85,6 +85,7 @@ config PCI_HOST_GENERIC bool "Generic PCI host controller" depends on (ARM || ARM64) && OF select PCI_HOST_COMMON + select IRQ_DOMAIN help Say Y here if you want to support a simple generic PCI host controller, such as the one emulated by kvmtool. -- cgit v1.2.3 From 3f3f67cbf64227fc9c06113585d9570baddc9bcd Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Mon, 9 May 2016 13:48:27 +0200 Subject: PCI: Add DT binding for Axis ARTPEC-6 PCIe controller Add the Device Tree binding documentation that allows to describe the PCIe controller found in the Axis ARTPEC-6 SoC. Signed-off-by: Niklas Cassel Signed-off-by: Bjorn Helgaas Acked-by: Rob Herring --- .../devicetree/bindings/pci/axis,artpec6-pcie.txt | 46 ++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 Documentation/devicetree/bindings/pci/axis,artpec6-pcie.txt diff --git a/Documentation/devicetree/bindings/pci/axis,artpec6-pcie.txt b/Documentation/devicetree/bindings/pci/axis,artpec6-pcie.txt new file mode 100644 index 000000000000..330a45b5f0b5 --- /dev/null +++ b/Documentation/devicetree/bindings/pci/axis,artpec6-pcie.txt @@ -0,0 +1,46 @@ +* Axis ARTPEC-6 PCIe interface + +This PCIe host controller is based on the Synopsys DesignWare PCIe IP +and thus inherits all the common properties defined in designware-pcie.txt. + +Required properties: +- compatible: "axis,artpec6-pcie", "snps,dw-pcie" +- reg: base addresses and lengths of the PCIe controller (DBI), + the phy controller, and configuration address space. +- reg-names: Must include the following entries: + - "dbi" + - "phy" + - "config" +- interrupts: A list of interrupt outputs of the controller. Must contain an + entry for each entry in the interrupt-names property. +- interrupt-names: Must include the following entries: + - "msi": The interrupt that is asserted when an MSI is received +- axis,syscon-pcie: A phandle pointing to the ARTPEC-6 system controller, + used to enable and control the Synopsys IP. + +Example: + + pcie@f8050000 { + compatible = "axis,artpec6-pcie", "snps,dw-pcie"; + reg = <0xf8050000 0x2000 + 0xf8040000 0x1000 + 0xc0000000 0x1000>; + reg-names = "dbi", "phy", "config"; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + /* downstream I/O */ + ranges = <0x81000000 0 0x00010000 0xc0010000 0 0x00010000 + /* non-prefetchable memory */ + 0x82000000 0 0xc0020000 0xc0020000 0 0x1ffe0000>; + num-lanes = <2>; + interrupts = ; + interrupt-names = "msi"; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0x7>; + interrupt-map = <0 0 0 1 &intc GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &intc GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &intc GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &intc GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>; + axis,syscon-pcie = <&syscon>; + }; -- cgit v1.2.3 From a3cbfae1f7b3b5b3bdac23f2feea16a3bd571d1f Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Mon, 9 May 2016 13:49:03 +0200 Subject: PCI: artpec: Add Axis ARTPEC-6 PCIe controller driver The Axis ARTPEC-6 SoC integrates a PCIe controller from Synopsys. Add a new driver that provides the small glue needed to use the existing DesignWare driver to make it work on the Axis ARTPEC-6 SoC. [bhelgaas: return errors directly without gotos, fold in section mismatch fix] Signed-off-by: Niklas Cassel Signed-off-by: Bjorn Helgaas --- MAINTAINERS | 9 ++ drivers/pci/host/Kconfig | 9 ++ drivers/pci/host/Makefile | 1 + drivers/pci/host/pcie-artpec6.c | 284 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 303 insertions(+) create mode 100644 drivers/pci/host/pcie-artpec6.c diff --git a/MAINTAINERS b/MAINTAINERS index ed42cb65a19b..d26687f863ef 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8823,6 +8823,15 @@ S: Maintained F: Documentation/devicetree/bindings/pci/xgene-pci-msi.txt F: drivers/pci/host/pci-xgene-msi.c +PCIE DRIVER FOR AXIS ARTPEC +M: Niklas Cassel +M: Jesper Nilsson +L: linux-arm-kernel@axis.com +L: linux-pci@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/pci/axis,artpec* +F: drivers/pci/host/*artpec* + PCIE DRIVER FOR HISILICON M: Zhou Wang M: Gabriele Paoloni diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index 5d2374e4ee7f..033d9ad37c74 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig @@ -245,4 +245,13 @@ config PCIE_ARMADA_8K Designware hardware and therefore the driver re-uses the Designware core functions to implement the driver. +config PCIE_ARTPEC6 + bool "Axis ARTPEC-6 PCIe controller" + depends on MACH_ARTPEC6 + select PCIE_DW + select PCIEPORTBUS + help + Say Y here to enable PCIe controller support on Axis ARTPEC-6 + SoCs. This PCIe controller uses the DesignWare core. + endmenu diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile index 9c8698e89e96..5bc0af2f5c5b 100644 --- a/drivers/pci/host/Makefile +++ b/drivers/pci/host/Makefile @@ -29,3 +29,4 @@ obj-$(CONFIG_PCIE_QCOM) += pcie-qcom.o obj-$(CONFIG_PCI_HOST_THUNDER_ECAM) += pci-thunder-ecam.o obj-$(CONFIG_PCI_HOST_THUNDER_PEM) += pci-thunder-pem.o obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o +obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o diff --git a/drivers/pci/host/pcie-artpec6.c b/drivers/pci/host/pcie-artpec6.c new file mode 100644 index 000000000000..be54fad4698b --- /dev/null +++ b/drivers/pci/host/pcie-artpec6.c @@ -0,0 +1,284 @@ +/* + * PCIe host controller driver for Axis ARTPEC-6 SoC + * + * Based on work done by Phil Edworthy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pcie-designware.h" + +#define to_artpec6_pcie(x) container_of(x, struct artpec6_pcie, pp) + +struct artpec6_pcie { + struct pcie_port pp; + struct regmap *regmap; + void __iomem *phy_base; +}; + +/* PCIe Port Logic registers (memory-mapped) */ +#define PL_OFFSET 0x700 +#define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28) +#define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c) + +#define MISC_CONTROL_1_OFF (PL_OFFSET + 0x1bc) +#define DBI_RO_WR_EN 1 + +/* ARTPEC-6 specific registers */ +#define PCIECFG 0x18 +#define PCIECFG_DBG_OEN (1 << 24) +#define PCIECFG_CORE_RESET_REQ (1 << 21) +#define PCIECFG_LTSSM_ENABLE (1 << 20) +#define PCIECFG_CLKREQ_B (1 << 11) +#define PCIECFG_REFCLK_ENABLE (1 << 10) +#define PCIECFG_PLL_ENABLE (1 << 9) +#define PCIECFG_PCLK_ENABLE (1 << 8) +#define PCIECFG_RISRCREN (1 << 4) +#define PCIECFG_MODE_TX_DRV_EN (1 << 3) +#define PCIECFG_CISRREN (1 << 2) +#define PCIECFG_MACRO_ENABLE (1 << 0) + +#define NOCCFG 0x40 +#define NOCCFG_ENABLE_CLK_PCIE (1 << 4) +#define NOCCFG_POWER_PCIE_IDLEACK (1 << 3) +#define NOCCFG_POWER_PCIE_IDLE (1 << 2) +#define NOCCFG_POWER_PCIE_IDLEREQ (1 << 1) + +#define PHY_STATUS 0x118 +#define PHY_COSPLLLOCK (1 << 0) + +#define ARTPEC6_CPU_TO_BUS_ADDR 0x0fffffff + +static int artpec6_pcie_establish_link(struct pcie_port *pp) +{ + struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pp); + u32 val; + unsigned int retries; + + /* Hold DW core in reset */ + regmap_read(artpec6_pcie->regmap, PCIECFG, &val); + val |= PCIECFG_CORE_RESET_REQ; + regmap_write(artpec6_pcie->regmap, PCIECFG, val); + + regmap_read(artpec6_pcie->regmap, PCIECFG, &val); + val |= PCIECFG_RISRCREN | /* Receiver term. 50 Ohm */ + PCIECFG_MODE_TX_DRV_EN | + PCIECFG_CISRREN | /* Reference clock term. 100 Ohm */ + PCIECFG_MACRO_ENABLE; + val |= PCIECFG_REFCLK_ENABLE; + val &= ~PCIECFG_DBG_OEN; + val &= ~PCIECFG_CLKREQ_B; + regmap_write(artpec6_pcie->regmap, PCIECFG, val); + usleep_range(5000, 6000); + + regmap_read(artpec6_pcie->regmap, NOCCFG, &val); + val |= NOCCFG_ENABLE_CLK_PCIE; + regmap_write(artpec6_pcie->regmap, NOCCFG, val); + usleep_range(20, 30); + + regmap_read(artpec6_pcie->regmap, PCIECFG, &val); + val |= PCIECFG_PCLK_ENABLE | PCIECFG_PLL_ENABLE; + regmap_write(artpec6_pcie->regmap, PCIECFG, val); + usleep_range(6000, 7000); + + regmap_read(artpec6_pcie->regmap, NOCCFG, &val); + val &= ~NOCCFG_POWER_PCIE_IDLEREQ; + regmap_write(artpec6_pcie->regmap, NOCCFG, val); + + retries = 50; + do { + usleep_range(1000, 2000); + regmap_read(artpec6_pcie->regmap, NOCCFG, &val); + retries--; + } while (retries && + (val & (NOCCFG_POWER_PCIE_IDLEACK | NOCCFG_POWER_PCIE_IDLE))); + + retries = 50; + do { + usleep_range(1000, 2000); + val = readl(artpec6_pcie->phy_base + PHY_STATUS); + retries--; + } while (retries && !(val & PHY_COSPLLLOCK)); + + /* Take DW core out of reset */ + regmap_read(artpec6_pcie->regmap, PCIECFG, &val); + val &= ~PCIECFG_CORE_RESET_REQ; + regmap_write(artpec6_pcie->regmap, PCIECFG, val); + usleep_range(100, 200); + + /* + * Enable writing to config regs. This is required as the Synopsys + * driver changes the class code. That register needs DBI write enable. + */ + writel(DBI_RO_WR_EN, pp->dbi_base + MISC_CONTROL_1_OFF); + + pp->io_base &= ARTPEC6_CPU_TO_BUS_ADDR; + pp->mem_base &= ARTPEC6_CPU_TO_BUS_ADDR; + pp->cfg0_base &= ARTPEC6_CPU_TO_BUS_ADDR; + pp->cfg1_base &= ARTPEC6_CPU_TO_BUS_ADDR; + + /* setup root complex */ + dw_pcie_setup_rc(pp); + + /* assert LTSSM enable */ + regmap_read(artpec6_pcie->regmap, PCIECFG, &val); + val |= PCIECFG_LTSSM_ENABLE; + regmap_write(artpec6_pcie->regmap, PCIECFG, val); + + /* check if the link is up or not */ + if (!dw_pcie_wait_for_link(pp)) + return 0; + + dev_dbg(pp->dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n", + readl(pp->dbi_base + PCIE_PHY_DEBUG_R0), + readl(pp->dbi_base + PCIE_PHY_DEBUG_R1)); + + return -ETIMEDOUT; +} + +static void artpec6_pcie_enable_interrupts(struct pcie_port *pp) +{ + if (IS_ENABLED(CONFIG_PCI_MSI)) + dw_pcie_msi_init(pp); +} + +static void artpec6_pcie_host_init(struct pcie_port *pp) +{ + artpec6_pcie_establish_link(pp); + artpec6_pcie_enable_interrupts(pp); +} + +static int artpec6_pcie_link_up(struct pcie_port *pp) +{ + u32 rc; + + /* + * Get status from Synopsys IP + * link is debug bit 36, debug register 1 starts at bit 32 + */ + rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1) & (0x1 << (36 - 32)); + if (rc) + return 1; + + return 0; +} + +static struct pcie_host_ops artpec6_pcie_host_ops = { + .link_up = artpec6_pcie_link_up, + .host_init = artpec6_pcie_host_init, +}; + +static irqreturn_t artpec6_pcie_msi_handler(int irq, void *arg) +{ + struct pcie_port *pp = arg; + + return dw_handle_msi_irq(pp); +} + +static int __init artpec6_add_pcie_port(struct pcie_port *pp, + struct platform_device *pdev) +{ + int ret; + + if (IS_ENABLED(CONFIG_PCI_MSI)) { + pp->msi_irq = platform_get_irq_byname(pdev, "msi"); + if (pp->msi_irq <= 0) { + dev_err(&pdev->dev, "failed to get MSI irq\n"); + return -ENODEV; + } + + ret = devm_request_irq(&pdev->dev, pp->msi_irq, + artpec6_pcie_msi_handler, + IRQF_SHARED | IRQF_NO_THREAD, + "artpec6-pcie-msi", pp); + if (ret) { + dev_err(&pdev->dev, "failed to request MSI irq\n"); + return ret; + } + } + + pp->root_bus_nr = -1; + pp->ops = &artpec6_pcie_host_ops; + + ret = dw_pcie_host_init(pp); + if (ret) { + dev_err(&pdev->dev, "failed to initialize host\n"); + return ret; + } + + return 0; +} + +static int artpec6_pcie_probe(struct platform_device *pdev) +{ + struct artpec6_pcie *artpec6_pcie; + struct pcie_port *pp; + struct resource *dbi_base; + struct resource *phy_base; + int ret; + + artpec6_pcie = devm_kzalloc(&pdev->dev, sizeof(*artpec6_pcie), + GFP_KERNEL); + if (!artpec6_pcie) + return -ENOMEM; + + pp = &artpec6_pcie->pp; + pp->dev = &pdev->dev; + + dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); + pp->dbi_base = devm_ioremap_resource(&pdev->dev, dbi_base); + if (IS_ERR(pp->dbi_base)) + return PTR_ERR(pp->dbi_base); + + phy_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy"); + artpec6_pcie->phy_base = devm_ioremap_resource(&pdev->dev, phy_base); + if (IS_ERR(artpec6_pcie->phy_base)) + return PTR_ERR(artpec6_pcie->phy_base); + + artpec6_pcie->regmap = + syscon_regmap_lookup_by_phandle(pdev->dev.of_node, + "axis,syscon-pcie"); + if (IS_ERR(artpec6_pcie->regmap)) + return PTR_ERR(artpec6_pcie->regmap); + + ret = artpec6_add_pcie_port(pp, pdev); + if (ret < 0) + return ret; + + platform_set_drvdata(pdev, artpec6_pcie); + return 0; +} + +static const struct of_device_id artpec6_pcie_of_match[] = { + { .compatible = "axis,artpec6-pcie", }, + {}, +}; +MODULE_DEVICE_TABLE(of, artpec6_pcie_of_match); + +static struct platform_driver artpec6_pcie_driver = { + .probe = artpec6_pcie_probe, + .driver = { + .name = "artpec6-pcie", + .of_match_table = artpec6_pcie_of_match, + }, +}; + +module_platform_driver(artpec6_pcie_driver); + +MODULE_AUTHOR("Niklas Cassel "); +MODULE_DESCRIPTION("Axis ARTPEC-6 PCIe host controller driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 27d9cb7ed2643cee96c4af5cfc4b941f68f42395 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 31 May 2016 11:14:08 -0500 Subject: PCI: designware: Free bridge resource list on failure of_pci_get_host_bridge_resources() allocates a list of resources for host bridge windows. If we fail after allocating that list, free it before we return error. Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pcie-designware.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index aafd766546f3..9ade76752336 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c @@ -493,7 +493,8 @@ int dw_pcie_host_init(struct pcie_port *pp) resource_size(pp->cfg)); if (!pp->dbi_base) { dev_err(pp->dev, "error with ioremap\n"); - return -ENOMEM; + ret = -ENOMEM; + goto error; } } @@ -504,7 +505,8 @@ int dw_pcie_host_init(struct pcie_port *pp) pp->cfg0_size); if (!pp->va_cfg0_base) { dev_err(pp->dev, "error with ioremap in function\n"); - return -ENOMEM; + ret = -ENOMEM; + goto error; } } @@ -513,7 +515,8 @@ int dw_pcie_host_init(struct pcie_port *pp) pp->cfg1_size); if (!pp->va_cfg1_base) { dev_err(pp->dev, "error with ioremap\n"); - return -ENOMEM; + ret = -ENOMEM; + goto error; } } @@ -528,7 +531,8 @@ int dw_pcie_host_init(struct pcie_port *pp) &dw_pcie_msi_chip); if (!pp->irq_domain) { dev_err(pp->dev, "irq domain init failed\n"); - return -ENXIO; + ret = -ENXIO; + goto error; } for (i = 0; i < MAX_MSI_IRQS; i++) @@ -536,7 +540,7 @@ int dw_pcie_host_init(struct pcie_port *pp) } else { ret = pp->ops->msi_host_init(pp, &dw_pcie_msi_chip); if (ret < 0) - return ret; + goto error; } } @@ -552,8 +556,10 @@ int dw_pcie_host_init(struct pcie_port *pp) } else bus = pci_scan_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops, pp, &res); - if (!bus) - return -ENOMEM; + if (!bus) { + ret = -ENOMEM; + goto error; + } if (pp->ops->scan_bus) pp->ops->scan_bus(pp); @@ -571,6 +577,10 @@ int dw_pcie_host_init(struct pcie_port *pp) pci_bus_add_devices(bus); return 0; + +error: + pci_free_resource_list(&res); + return ret; } static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, -- cgit v1.2.3 From 12722dbbda12125314611a76d47d492120e830a4 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sat, 28 May 2016 18:18:54 -0500 Subject: PCI: designware: Request host bridge window resources Request host bridge window resources so they appear in ioport_resource and iomem_resource and are reflected in /proc/ioports and /proc/iomem. Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pcie-designware.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index 9ade76752336..8304aeba4fb5 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c @@ -452,6 +452,10 @@ int dw_pcie_host_init(struct pcie_port *pp) if (ret) return ret; + ret = devm_request_pci_bus_resources(&pdev->dev, &res); + if (ret) + goto error; + /* Get the I/O and memory ranges from DT */ resource_list_for_each_entry(win, &res) { switch (resource_type(win->res)) { -- cgit v1.2.3 From 7baf69c7c3025d18dbf7a4b903f9ddc647aacaaf Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sat, 28 May 2016 18:48:11 -0500 Subject: PCI: designware: Simplify host bridge window iteration The switch is the only statement in the resource_list_for_each_entry() loop, so remove unnecessary "continue" statements in the switch. No functional change intended. Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pcie-designware.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index 8304aeba4fb5..12afce19890b 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c @@ -465,11 +465,9 @@ int dw_pcie_host_init(struct pcie_port *pp) pp->io_size = resource_size(pp->io); pp->io_bus_addr = pp->io->start - win->offset; ret = pci_remap_iospace(pp->io, pp->io_base); - if (ret) { + if (ret) dev_warn(pp->dev, "error %d: failed to map resource %pR\n", ret, pp->io); - continue; - } break; case IORESOURCE_MEM: pp->mem = win->res; @@ -487,8 +485,6 @@ int dw_pcie_host_init(struct pcie_port *pp) case IORESOURCE_BUS: pp->busn = win->res; break; - default: - continue; } } -- cgit v1.2.3 From c3245a5664003360bd9deda9777be7cea4fe9982 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sat, 28 May 2016 18:22:24 -0500 Subject: PCI: iproc: Request host bridge window resources Request host bridge window resources so they appear in ioport_resource and iomem_resource and are reflected in /proc/ioports and /proc/iomem. Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pcie-iproc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/pci/host/pcie-iproc.c b/drivers/pci/host/pcie-iproc.c index a576aeeb22da..e167b2f0098d 100644 --- a/drivers/pci/host/pcie-iproc.c +++ b/drivers/pci/host/pcie-iproc.c @@ -462,6 +462,10 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) if (!pcie || !pcie->dev || !pcie->base) return -EINVAL; + ret = devm_request_pci_bus_resources(pcie->dev, res); + if (ret) + return ret; + ret = phy_init(pcie->phy); if (ret) { dev_err(pcie->dev, "unable to initialize PCIe PHY\n"); -- cgit v1.2.3 From 11659a1d54b670f05ff91627934aaadf376db937 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 31 May 2016 11:07:30 -0500 Subject: PCI: xgene: Free bridge resource list on failure of_pci_get_host_bridge_resources() allocates a list of resources for host bridge windows. If we fail after allocating that list, free it before we return error. Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pci-xgene.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/pci/host/pci-xgene.c b/drivers/pci/host/pci-xgene.c index ae00ce22d5a6..bc4e1c61206c 100644 --- a/drivers/pci/host/pci-xgene.c +++ b/drivers/pci/host/pci-xgene.c @@ -542,12 +542,14 @@ static int xgene_pcie_probe_bridge(struct platform_device *pdev) ret = xgene_pcie_setup(port, &res, iobase); if (ret) - return ret; + goto error; bus = pci_create_root_bus(&pdev->dev, 0, &xgene_pcie_ops, port, &res); - if (!bus) - return -ENOMEM; + if (!bus) { + ret = -ENOMEM; + goto error; + } pci_scan_child_bus(bus); pci_assign_unassigned_bus_resources(bus); @@ -555,6 +557,10 @@ static int xgene_pcie_probe_bridge(struct platform_device *pdev) platform_set_drvdata(pdev, port); return 0; + +error: + pci_free_resource_list(&res); + return ret; } static const struct of_device_id xgene_pcie_match_table[] = { -- cgit v1.2.3 From 0ccb7eefeb56c8d3cdce53ede23e06c8be894670 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sat, 28 May 2016 18:14:24 -0500 Subject: PCI: xgene: Request host bridge window resources Request host bridge window resources so they appear in ioport_resource and iomem_resource and are reflected in /proc/ioports and /proc/iomem. For example, the following entries did not previously appear in /proc/iomem: e180000000-e1ffffffff : /soc/pcie@1f2b0000 e180000000-e182ffffff : PCI Bus 0000:01 e180000000-e181ffffff : 0000:01:00.0 e182000000-e1820fffff : 0000:01:00.0 e182100000-e1821fffff : 0000:01:00.0 f000000000-ffffffffff : /soc/pcie@1f2b0000 Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pci-xgene.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/pci/host/pci-xgene.c b/drivers/pci/host/pci-xgene.c index bc4e1c61206c..7eb20cc76dd3 100644 --- a/drivers/pci/host/pci-xgene.c +++ b/drivers/pci/host/pci-xgene.c @@ -540,6 +540,10 @@ static int xgene_pcie_probe_bridge(struct platform_device *pdev) if (ret) return ret; + ret = devm_request_pci_bus_resources(&pdev->dev, &res); + if (ret) + goto error; + ret = xgene_pcie_setup(port, &res, iobase); if (ret) goto error; -- cgit v1.2.3 From c41be7a695edeb00480a95eaf1c23a76b35f0b8b Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 31 May 2016 11:49:14 -0500 Subject: PCI: xilinx: Free bridge resource list on failure of_pci_get_host_bridge_resources() allocates a list of resources for host bridge windows. If we fail after allocating that list, free it before we return error. Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pcie-xilinx.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/pci/host/pcie-xilinx.c b/drivers/pci/host/pcie-xilinx.c index 65f0fe0c2eaf..5c456db47c49 100644 --- a/drivers/pci/host/pcie-xilinx.c +++ b/drivers/pci/host/pcie-xilinx.c @@ -660,7 +660,6 @@ static int xilinx_pcie_probe(struct platform_device *pdev) struct xilinx_pcie_port *port; struct device *dev = &pdev->dev; struct pci_bus *bus; - int err; resource_size_t iobase = 0; LIST_HEAD(res); @@ -696,8 +695,10 @@ static int xilinx_pcie_probe(struct platform_device *pdev) } bus = pci_create_root_bus(&pdev->dev, 0, &xilinx_pcie_ops, port, &res); - if (!bus) - return -ENOMEM; + if (!bus) { + err = -ENOMEM; + goto error; + } #ifdef CONFIG_PCI_MSI xilinx_pcie_msi_chip.dev = port->dev; @@ -712,6 +713,10 @@ static int xilinx_pcie_probe(struct platform_device *pdev) platform_set_drvdata(pdev, port); return 0; + +error: + pci_free_resource_list(&res); + return err; } /** -- cgit v1.2.3 From 93a5b5e5876e45096d0e448bbdc4cf715f2f346e Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sat, 28 May 2016 18:27:03 -0500 Subject: PCI: xilinx: Request host bridge window resources Request host bridge window resources so they appear in ioport_resource and iomem_resource and are reflected in /proc/ioports and /proc/iomem. Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pcie-xilinx.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/pci/host/pcie-xilinx.c b/drivers/pci/host/pcie-xilinx.c index 5c456db47c49..4703aa336041 100644 --- a/drivers/pci/host/pcie-xilinx.c +++ b/drivers/pci/host/pcie-xilinx.c @@ -693,6 +693,11 @@ static int xilinx_pcie_probe(struct platform_device *pdev) dev_err(dev, "Getting bridge resources failed\n"); return err; } + + err = devm_request_pci_bus_resources(dev, &res); + if (err) + goto error; + bus = pci_create_root_bus(&pdev->dev, 0, &xilinx_pcie_ops, port, &res); if (!bus) { -- cgit v1.2.3 From 0bb01307557ca5042fb96bc5261b847a68203ba2 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 31 May 2016 11:26:01 -0500 Subject: PCI: xilinx-nwl: Free bridge resource list on failure of_pci_get_host_bridge_resources() allocates a list of resources for host bridge windows. If we fail after allocating that list, free it before we return error. Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pcie-xilinx-nwl.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/pci/host/pcie-xilinx-nwl.c b/drivers/pci/host/pcie-xilinx-nwl.c index 3479d30e2be8..506da7bacf1d 100644 --- a/drivers/pci/host/pcie-xilinx-nwl.c +++ b/drivers/pci/host/pcie-xilinx-nwl.c @@ -832,20 +832,22 @@ static int nwl_pcie_probe(struct platform_device *pdev) err = nwl_pcie_init_irq_domain(pcie); if (err) { dev_err(pcie->dev, "Failed creating IRQ Domain\n"); - return err; + goto error; } bus = pci_create_root_bus(&pdev->dev, pcie->root_busno, &nwl_pcie_ops, pcie, &res); - if (!bus) - return -ENOMEM; + if (!bus) { + err = -ENOMEM; + goto error; + } if (IS_ENABLED(CONFIG_PCI_MSI)) { err = nwl_pcie_enable_msi(pcie, bus); if (err < 0) { dev_err(&pdev->dev, "failed to enable MSI support: %d\n", err); - return err; + goto error; } } pci_scan_child_bus(bus); @@ -855,6 +857,10 @@ static int nwl_pcie_probe(struct platform_device *pdev) pci_bus_add_devices(bus); platform_set_drvdata(pdev, pcie); return 0; + +error: + pci_free_resource_list(&res); + return err; } static int nwl_pcie_remove(struct platform_device *pdev) -- cgit v1.2.3 From 21f7fc241e8eac59f5870202824bca7960c6c05d Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sat, 28 May 2016 18:24:36 -0500 Subject: PCI: xilinx-nwl: Request host bridge window resources Request host bridge window resources so they appear in ioport_resource and iomem_resource and are reflected in /proc/ioports and /proc/iomem. Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pcie-xilinx-nwl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/pci/host/pcie-xilinx-nwl.c b/drivers/pci/host/pcie-xilinx-nwl.c index 506da7bacf1d..3c16bbf970e3 100644 --- a/drivers/pci/host/pcie-xilinx-nwl.c +++ b/drivers/pci/host/pcie-xilinx-nwl.c @@ -829,6 +829,10 @@ static int nwl_pcie_probe(struct platform_device *pdev) return err; } + err = devm_request_pci_bus_resources(pcie->dev, &res); + if (err) + goto error; + err = nwl_pcie_init_irq_domain(pcie); if (err) { dev_err(pcie->dev, "Failed creating IRQ Domain\n"); -- cgit v1.2.3 From 9061f9bea4c995cea06c638606d1d56f95a759e0 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sat, 28 May 2016 18:26:01 -0500 Subject: PCI: xilinx-nwl: Use dev_printk() when possible Use dev_printk() when possible to make messages more useful. Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pcie-xilinx-nwl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/host/pcie-xilinx-nwl.c b/drivers/pci/host/pcie-xilinx-nwl.c index 3c16bbf970e3..0b597d9190b4 100644 --- a/drivers/pci/host/pcie-xilinx-nwl.c +++ b/drivers/pci/host/pcie-xilinx-nwl.c @@ -825,7 +825,7 @@ static int nwl_pcie_probe(struct platform_device *pdev) err = of_pci_get_host_bridge_resources(node, 0, 0xff, &res, &iobase); if (err) { - pr_err("Getting bridge resources failed\n"); + dev_err(pcie->dev, "Getting bridge resources failed\n"); return err; } -- cgit v1.2.3 From 74462284bdda85216c3cf49d52920d4164f47e80 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 31 May 2016 12:14:17 -0500 Subject: PCI: altera: Request host bridge window resources with core function Use devm_request_pci_bus_resources() to request host bridge window resources instead of doing it by hand in the driver. No functional change intended. Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pcie-altera.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/pci/host/pcie-altera.c b/drivers/pci/host/pcie-altera.c index dbac6fb3f0bd..b97abbcdba33 100644 --- a/drivers/pci/host/pcie-altera.c +++ b/drivers/pci/host/pcie-altera.c @@ -432,21 +432,20 @@ static int altera_pcie_parse_request_of_pci_ranges(struct altera_pcie *pcie) if (err) return err; + err = devm_request_pci_bus_resources(dev, &pcie->resources); + if (err) + goto out_release_res; + resource_list_for_each_entry(win, &pcie->resources) { - struct resource *parent, *res = win->res; + struct resource *res = win->res; switch (resource_type(res)) { case IORESOURCE_MEM: - parent = &iomem_resource; res_valid |= !(res->flags & IORESOURCE_PREFETCH); break; default: continue; } - - err = devm_request_resource(dev, parent, res); - if (err) - goto out_release_res; } if (!res_valid) { -- cgit v1.2.3 From ba4f6d9201a7b8840786a29bfe5020cc06bf0f19 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sat, 28 May 2016 18:33:46 -0500 Subject: PCI: altera: Simplify host bridge window iteration The switch is the only statement in the resource_list_for_each_entry() loop, so remove unnecessary "continue" statements in the switch. Simplify checking for the required non-prefetchable memory aperture. Inline altera_pcie_release_of_pci_ranges(), which is only called once. No functional change intended. Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pcie-altera.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/drivers/pci/host/pcie-altera.c b/drivers/pci/host/pcie-altera.c index b97abbcdba33..cf20c67a48f8 100644 --- a/drivers/pci/host/pcie-altera.c +++ b/drivers/pci/host/pcie-altera.c @@ -415,11 +415,6 @@ static void altera_pcie_isr(struct irq_desc *desc) chained_irq_exit(chip, desc); } -static void altera_pcie_release_of_pci_ranges(struct altera_pcie *pcie) -{ - pci_free_resource_list(&pcie->resources); -} - static int altera_pcie_parse_request_of_pci_ranges(struct altera_pcie *pcie) { int err, res_valid = 0; @@ -439,25 +434,18 @@ static int altera_pcie_parse_request_of_pci_ranges(struct altera_pcie *pcie) resource_list_for_each_entry(win, &pcie->resources) { struct resource *res = win->res; - switch (resource_type(res)) { - case IORESOURCE_MEM: + if (resource_type(res) == IORESOURCE_MEM) res_valid |= !(res->flags & IORESOURCE_PREFETCH); - break; - default: - continue; - } } - if (!res_valid) { - dev_err(dev, "non-prefetchable memory resource required\n"); - err = -EINVAL; - goto out_release_res; - } + if (res_valid) + return 0; - return 0; + dev_err(dev, "non-prefetchable memory resource required\n"); + err = -EINVAL; out_release_res: - altera_pcie_release_of_pci_ranges(pcie); + pci_free_resource_list(&pcie->resources); return err; } -- cgit v1.2.3 From b7f957ac272cb6f7a36536a1801b4da453df9c9b Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 31 May 2016 12:05:05 -0500 Subject: PCI: generic: Request host bridge window resources with core function Use devm_request_pci_bus_resources() to request host bridge window resources instead of doing it by hand in the driver. No functional change intended. Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pci-host-common.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/pci/host/pci-host-common.c b/drivers/pci/host/pci-host-common.c index 8cba7ab73df9..533d50c500a9 100644 --- a/drivers/pci/host/pci-host-common.c +++ b/drivers/pci/host/pci-host-common.c @@ -36,12 +36,15 @@ static int gen_pci_parse_request_of_pci_ranges(struct device *dev, if (err) return err; + err = devm_request_pci_bus_resources(dev, resources); + if (err) + goto out_release_res; + resource_list_for_each_entry(win, resources) { - struct resource *parent, *res = win->res; + struct resource *res = win->res; switch (resource_type(res)) { case IORESOURCE_IO: - parent = &ioport_resource; err = pci_remap_iospace(res, iobase); if (err) { dev_warn(dev, "error %d: failed to map resource %pR\n", @@ -50,7 +53,6 @@ static int gen_pci_parse_request_of_pci_ranges(struct device *dev, } break; case IORESOURCE_MEM: - parent = &iomem_resource; res_valid |= !(res->flags & IORESOURCE_PREFETCH); break; case IORESOURCE_BUS: @@ -58,10 +60,6 @@ static int gen_pci_parse_request_of_pci_ranges(struct device *dev, default: continue; } - - err = devm_request_resource(dev, parent, res); - if (err) - goto out_release_res; } if (!res_valid) { -- cgit v1.2.3 From 5aa182a26ca6b2427473d9c61e369c860fca628c Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sat, 28 May 2016 18:28:51 -0500 Subject: PCI: generic: Simplify host bridge window iteration The switch is the only statement in the resource_list_for_each_entry() loop, so remove unnecessary "continue" statements in the switch. Remove unnecessary "goto" statements and label. Simplify checking for the required non-prefetchable memory aperture. No functional change intended. Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pci-host-common.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/drivers/pci/host/pci-host-common.c b/drivers/pci/host/pci-host-common.c index 533d50c500a9..5852c40fda43 100644 --- a/drivers/pci/host/pci-host-common.c +++ b/drivers/pci/host/pci-host-common.c @@ -38,7 +38,7 @@ static int gen_pci_parse_request_of_pci_ranges(struct device *dev, err = devm_request_pci_bus_resources(dev, resources); if (err) - goto out_release_res; + return err; resource_list_for_each_entry(win, resources) { struct resource *res = win->res; @@ -46,32 +46,24 @@ static int gen_pci_parse_request_of_pci_ranges(struct device *dev, switch (resource_type(res)) { case IORESOURCE_IO: err = pci_remap_iospace(res, iobase); - if (err) { + if (err) dev_warn(dev, "error %d: failed to map resource %pR\n", err, res); - continue; - } break; case IORESOURCE_MEM: res_valid |= !(res->flags & IORESOURCE_PREFETCH); break; case IORESOURCE_BUS: *bus_range = res; - default: - continue; + break; } } - if (!res_valid) { - dev_err(dev, "non-prefetchable memory resource required\n"); - err = -EINVAL; - goto out_release_res; - } - - return 0; + if (res_valid) + return 0; -out_release_res: - return err; + dev_err(dev, "non-prefetchable memory resource required\n"); + return -EINVAL; } static void gen_pci_unmap_cfg(void *ptr) -- cgit v1.2.3 From 6df68f22df726ffdda3199602ace4d03ec012372 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 6 Jun 2016 15:35:39 -0500 Subject: PCI: mvebu: Request host bridge window resources with core function Use devm_request_pci_bus_resources() to request host bridge window resources instead of doing it by hand in the driver. No functional change intended. Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pci-mvebu.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index 6b451df6502c..2287a4e18add 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c @@ -839,25 +839,22 @@ static struct pci_ops mvebu_pcie_ops = { static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys) { struct mvebu_pcie *pcie = sys_to_pcie(sys); - int i; + int err, i; pcie->mem.name = "PCI MEM"; pcie->realio.name = "PCI I/O"; - if (request_resource(&iomem_resource, &pcie->mem)) - return 0; - - if (resource_size(&pcie->realio) != 0) { - if (request_resource(&ioport_resource, &pcie->realio)) { - release_resource(&pcie->mem); - return 0; - } + if (resource_size(&pcie->realio) != 0) pci_add_resource_offset(&sys->resources, &pcie->realio, sys->io_offset); - } + pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset); pci_add_resource(&sys->resources, &pcie->busn); + err = devm_request_pci_bus_resources(&pcie->pdev->dev, &sys->resources); + if (err) + return 0; + for (i = 0; i < pcie->nports; i++) { struct mvebu_pcie_port *port = &pcie->ports[i]; -- cgit v1.2.3 From 1fa051018d85b829e4b9a7ed20147df8760293ee Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 21 Jun 2016 10:54:29 -0500 Subject: ARM: Make PCI I/O space optional For callers of pci_common_init_dev(), we previously always required a PCI I/O port resource. If the caller's ->setup() function had added an I/O resource, we used that; otherwise, we added a default 64K I/O port space for it. There are PCI host bridges that do not support I/O port space, and we should not add fictitious spaces for them. If a caller sets struct hw_pci.io_optional, assume it is responsible for adding any I/O port resource it desires, and do not add any default I/O port space. Tested-by: Geert Uytterhoeven Signed-off-by: Bjorn Helgaas --- arch/arm/include/asm/mach/pci.h | 1 + arch/arm/kernel/bios32.c | 13 +++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/arch/arm/include/asm/mach/pci.h b/arch/arm/include/asm/mach/pci.h index 0070e8520cd4..2d88af5be45f 100644 --- a/arch/arm/include/asm/mach/pci.h +++ b/arch/arm/include/asm/mach/pci.h @@ -22,6 +22,7 @@ struct hw_pci { struct msi_controller *msi_ctrl; struct pci_ops *ops; int nr_controllers; + unsigned int io_optional:1; void **private_data; int (*setup)(int nr, struct pci_sys_data *); struct pci_bus *(*scan)(int nr, struct pci_sys_data *); diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index 05e61a2eeabe..65f12ef6aa62 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -410,7 +410,8 @@ static int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) return irq; } -static int pcibios_init_resources(int busnr, struct pci_sys_data *sys) +static int pcibios_init_resource(int busnr, struct pci_sys_data *sys, + int io_optional) { int ret; struct resource_entry *window; @@ -420,6 +421,14 @@ static int pcibios_init_resources(int busnr, struct pci_sys_data *sys) &iomem_resource, sys->mem_offset); } + /* + * If a platform says I/O port support is optional, we don't add + * the default I/O space. The platform is responsible for adding + * any I/O space it needs. + */ + if (io_optional) + return 0; + resource_list_for_each_entry(window, &sys->resources) if (resource_type(window->res) == IORESOURCE_IO) return 0; @@ -466,7 +475,7 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw, if (ret > 0) { struct pci_host_bridge *host_bridge; - ret = pcibios_init_resources(nr, sys); + ret = pcibios_init_resource(nr, sys, hw->io_optional); if (ret) { kfree(sys); break; -- cgit v1.2.3 From b2a5d3e2cf65e46522b695b76f93ec1b0f6cad30 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 21 Jun 2016 09:19:34 -0500 Subject: PCI: rcar: Drop gen2 dummy I/O port region Previously we added a dummy I/O port region even though the R-Car controller doesn't support PCI port I/O. This resulted in bogus root bus resources like this: pci_bus 0000:00: root bus resource [io 0xee080000-0xee0810ff] pci_bus 0000:00: root bus resource [mem 0xee080000-0xee0810ff] Drop the unused dummy I/O port region and set struct hw_pci.io_optional so the ARM PCI code doesn't add a default one for us. Tested-by: Geert Uytterhoeven Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pci-rcar-gen2.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/pci/host/pci-rcar-gen2.c b/drivers/pci/host/pci-rcar-gen2.c index 9980a4bdae7e..ddf776556c78 100644 --- a/drivers/pci/host/pci-rcar-gen2.c +++ b/drivers/pci/host/pci-rcar-gen2.c @@ -97,7 +97,6 @@ struct rcar_pci_priv { struct device *dev; void __iomem *reg; - struct resource io_res; struct resource mem_res; struct resource *cfg_res; unsigned busnr; @@ -273,7 +272,6 @@ static int rcar_pci_setup(int nr, struct pci_sys_data *sys) rcar_pci_setup_errirq(priv); /* Add PCI resources */ - pci_add_resource(&sys->resources, &priv->io_res); pci_add_resource(&sys->resources, &priv->mem_res); /* Setup bus number based on platform device id / of bus-range */ @@ -371,14 +369,6 @@ static int rcar_pci_probe(struct platform_device *pdev) return -ENOMEM; priv->mem_res = *mem_res; - /* - * The controller does not support/use port I/O, - * so setup a dummy port I/O region here. - */ - priv->io_res.start = priv->mem_res.start; - priv->io_res.end = priv->mem_res.end; - priv->io_res.flags = IORESOURCE_IO; - priv->cfg_res = cfg_res; priv->irq = platform_get_irq(pdev, 0); @@ -421,6 +411,7 @@ static int rcar_pci_probe(struct platform_device *pdev) hw_private[0] = priv; memset(&hw, 0, sizeof(hw)); hw.nr_controllers = ARRAY_SIZE(hw_private); + hw.io_optional = 1; hw.private_data = hw_private; hw.map_irq = rcar_pci_map_irq; hw.ops = &rcar_pci_ops; -- cgit v1.2.3 From ac575ead871f6529f30baeda5ac34696ac64ec33 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 6 Jun 2016 17:26:31 -0500 Subject: PCI: rcar Gen2: Request host bridge window resources Request host bridge window resources so they appear in ioport_resource and iomem_resource and are reflected in /proc/ioports and /proc/iomem. Tested-by: Geert Uytterhoeven Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pci-rcar-gen2.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/pci/host/pci-rcar-gen2.c b/drivers/pci/host/pci-rcar-gen2.c index ddf776556c78..e8f5ac84b2c6 100644 --- a/drivers/pci/host/pci-rcar-gen2.c +++ b/drivers/pci/host/pci-rcar-gen2.c @@ -193,6 +193,7 @@ static int rcar_pci_setup(int nr, struct pci_sys_data *sys) struct rcar_pci_priv *priv = sys->private_data; void __iomem *reg = priv->reg; u32 val; + int ret; pm_runtime_enable(priv->dev); pm_runtime_get_sync(priv->dev); @@ -273,6 +274,9 @@ static int rcar_pci_setup(int nr, struct pci_sys_data *sys) /* Add PCI resources */ pci_add_resource(&sys->resources, &priv->mem_res); + ret = devm_request_pci_bus_resources(priv->dev, &sys->resources); + if (ret < 0) + return ret; /* Setup bus number based on platform device id / of bus-range */ sys->busnr = priv->busnr; -- cgit v1.2.3 From 6fd7f550975a2186493dbea6170acbe7da3b8ab9 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 31 May 2016 12:20:57 -0500 Subject: PCI: rcar: Request host bridge window resources with core function Use devm_request_pci_bus_resources() to request host bridge window resources instead of doing it by hand in the driver. No functional change intended. Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pcie-rcar.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c index 35092188039b..ce096db38af4 100644 --- a/drivers/pci/host/pcie-rcar.c +++ b/drivers/pci/host/pcie-rcar.c @@ -955,12 +955,15 @@ static int rcar_pcie_parse_request_of_pci_ranges(struct rcar_pcie *pci) if (err) return err; + err = devm_request_pci_bus_resources(dev, &pci->resources); + if (err) + goto out_release_res; + resource_list_for_each_entry(win, &pci->resources) { - struct resource *parent, *res = win->res; + struct resource *res = win->res; switch (resource_type(res)) { case IORESOURCE_IO: - parent = &ioport_resource; err = pci_remap_iospace(res, iobase); if (err) { dev_warn(dev, "error %d: failed to map resource %pR\n", @@ -969,17 +972,12 @@ static int rcar_pcie_parse_request_of_pci_ranges(struct rcar_pcie *pci) } break; case IORESOURCE_MEM: - parent = &iomem_resource; break; case IORESOURCE_BUS: default: continue; } - - err = devm_request_resource(dev, parent, res); - if (err) - goto out_release_res; } return 0; -- cgit v1.2.3 From 4c540a35c06963fa853a14daaf9a4f7df39856d5 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sat, 28 May 2016 18:37:46 -0500 Subject: PCI: rcar: Simplify host bridge window iteration The switch is the only statement in the resource_list_for_each_entry() loop, so remove unnecessary cases and "continue" statements in the switch. Inline rcar_pcie_release_of_pci_ranges(), which is only called once. No functional change intended. Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pcie-rcar.c | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c index ce096db38af4..6546ca79f188 100644 --- a/drivers/pci/host/pcie-rcar.c +++ b/drivers/pci/host/pcie-rcar.c @@ -938,11 +938,6 @@ static const struct of_device_id rcar_pcie_of_match[] = { }; MODULE_DEVICE_TABLE(of, rcar_pcie_of_match); -static void rcar_pcie_release_of_pci_ranges(struct rcar_pcie *pci) -{ - pci_free_resource_list(&pci->resources); -} - static int rcar_pcie_parse_request_of_pci_ranges(struct rcar_pcie *pci) { int err; @@ -962,28 +957,18 @@ static int rcar_pcie_parse_request_of_pci_ranges(struct rcar_pcie *pci) resource_list_for_each_entry(win, &pci->resources) { struct resource *res = win->res; - switch (resource_type(res)) { - case IORESOURCE_IO: + if (resource_type(res) == IORESOURCE_IO) { err = pci_remap_iospace(res, iobase); - if (err) { + if (err) dev_warn(dev, "error %d: failed to map resource %pR\n", err, res); - continue; - } - break; - case IORESOURCE_MEM: - break; - - case IORESOURCE_BUS: - default: - continue; } } return 0; out_release_res: - rcar_pcie_release_of_pci_ranges(pci); + pci_free_resource_list(&pci->resources); return err; } -- cgit v1.2.3 From c4102c92dfe99396382af33f47479a12388bec82 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 6 Jun 2016 15:55:04 -0500 Subject: PCI: tegra: Remove top-level resource from hierarchy 41534e53786d ("PCI: tegra: Implement a proper resource hierarchy") did two things: 1) It added a top-level resource that encloses all resources declared in the DT description, including registers and bridge apertures, and 2) It requested the bridge apertures, which means the PCI core can track the resources used by PCI devices below the bridge. The latter is necessary, but the former is questionable because there's no guarantee that the bridge registers and the apertures are contiguous. In this example: # cat /proc/iomem 00000000-3fffffff : /pcie-controller@00003000 00000000-00000fff : /pcie-controller@00003000/pci@1,0 00003000-000037ff : pads 00003800-000039ff : afi 10000000-1fffffff : cs the resource tree claims that [mem 0x00003a00-0x0fffffff] is consumed by /pcie-controller@00003000, but it's not mentioned in the DT, and it might actually be used by other devices. Remove the top-level resource so we don't claim more than the device actually consumes. This reintroduces the problem that we can't match the resources, e.g., "pads", "afi", "cs", etc., to the DT device. I think this should be solved by having the DT core request all resources of all devices in the DT (it does not do that today). If a driver claims the device, it can request the resources it uses. For example: # cat /proc/iomem 00000000-00000fff : /pcie-controller@00003000 00000000-00000fff : /pcie-controller@00003000/pci@1,0 00003000-000037ff : /pcie-controller@00003000 00003000-000037ff : pads 00003800-000039ff : /pcie-controller@00003000 00003800-000039ff : afi 10000000-1fffffff : /pcie-controller@00003000 10000000-1fffffff : cs ... Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pci-tegra.c | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index c388468c202a..920a8990c596 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c @@ -274,7 +274,6 @@ struct tegra_pcie { struct list_head buses; struct resource *cs; - struct resource all; struct resource io; struct resource pio; struct resource mem; @@ -623,7 +622,7 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys) sys->mem_offset = pcie->offset.mem; sys->io_offset = pcie->offset.io; - err = devm_request_resource(pcie->dev, &pcie->all, &pcie->io); + err = devm_request_resource(pcie->dev, &iomem_resource, &pcie->io); if (err < 0) return err; @@ -631,11 +630,11 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys) if (err < 0) return err; - err = devm_request_resource(pcie->dev, &pcie->all, &pcie->mem); + err = devm_request_resource(pcie->dev, &iomem_resource, &pcie->mem); if (err < 0) return err; - err = devm_request_resource(pcie->dev, &pcie->all, &pcie->prefetch); + err = devm_request_resource(pcie->dev, &iomem_resource, &pcie->prefetch); if (err) return err; @@ -1822,12 +1821,6 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie) struct resource res; int err; - memset(&pcie->all, 0, sizeof(pcie->all)); - pcie->all.flags = IORESOURCE_MEM; - pcie->all.name = np->full_name; - pcie->all.start = ~0; - pcie->all.end = 0; - if (of_pci_range_parser_init(&parser, np)) { dev_err(pcie->dev, "missing \"ranges\" property\n"); return -EINVAL; @@ -1880,18 +1873,8 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie) } break; } - - if (res.start <= pcie->all.start) - pcie->all.start = res.start; - - if (res.end >= pcie->all.end) - pcie->all.end = res.end; } - err = devm_request_resource(pcie->dev, &iomem_resource, &pcie->all); - if (err < 0) - return err; - err = of_pci_parse_bus_range(np, &pcie->busn); if (err < 0) { dev_err(pcie->dev, "failed to parse ranges property: %d\n", -- cgit v1.2.3 From 45c64b6ac4ef0f50ba754e997585c02b10c93c02 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 6 Jun 2016 15:47:24 -0500 Subject: PCI: tegra: Request host bridge window resources with core function Use devm_request_pci_bus_resources() to request host bridge window resources instead of doing it by hand in the driver. No functional change intended. Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pci-tegra.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 920a8990c596..6e6ef0d3d739 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c @@ -626,17 +626,7 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys) if (err < 0) return err; - err = devm_request_resource(pcie->dev, &ioport_resource, &pcie->pio); - if (err < 0) - return err; - - err = devm_request_resource(pcie->dev, &iomem_resource, &pcie->mem); - if (err < 0) - return err; - - err = devm_request_resource(pcie->dev, &iomem_resource, &pcie->prefetch); - if (err) - return err; + pci_ioremap_io(pcie->pio.start, pcie->io.start); pci_add_resource_offset(&sys->resources, &pcie->pio, sys->io_offset); pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset); @@ -644,7 +634,9 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys) sys->mem_offset); pci_add_resource(&sys->resources, &pcie->busn); - pci_ioremap_io(pcie->pio.start, pcie->io.start); + err = devm_request_pci_bus_resources(pcie->dev, &sys->resources); + if (err < 0) + return err; return 1; } -- cgit v1.2.3 From 2fbb353041891ce8527667ca956d9c53222dec01 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 31 May 2016 12:09:28 -0500 Subject: PCI: versatile: Request host bridge window resources with core function Use devm_request_pci_bus_resources() to request host bridge window resources instead of doing it by hand in the driver. No functional change intended. Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pci-versatile.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/pci/host/pci-versatile.c b/drivers/pci/host/pci-versatile.c index f843a72dc51c..273edaca8f49 100644 --- a/drivers/pci/host/pci-versatile.c +++ b/drivers/pci/host/pci-versatile.c @@ -80,12 +80,15 @@ static int versatile_pci_parse_request_of_pci_ranges(struct device *dev, if (err) return err; + err = devm_request_pci_bus_resources(dev, res); + if (err) + goto out_release_res; + resource_list_for_each_entry(win, res) { - struct resource *parent, *res = win->res; + struct resource *res = win->res; switch (resource_type(res)) { case IORESOURCE_IO: - parent = &ioport_resource; err = pci_remap_iospace(res, iobase); if (err) { dev_warn(dev, "error %d: failed to map resource %pR\n", @@ -94,7 +97,6 @@ static int versatile_pci_parse_request_of_pci_ranges(struct device *dev, } break; case IORESOURCE_MEM: - parent = &iomem_resource; res_valid |= !(res->flags & IORESOURCE_PREFETCH); writel(res->start >> 28, PCI_IMAP(mem)); @@ -106,10 +108,6 @@ static int versatile_pci_parse_request_of_pci_ranges(struct device *dev, default: continue; } - - err = devm_request_resource(dev, parent, res); - if (err) - goto out_release_res; } if (!res_valid) { -- cgit v1.2.3 From da6163ad3aae627d0b12ae58300c5d02d8ee613e Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sat, 28 May 2016 18:31:26 -0500 Subject: PCI: versatile: Simplify host bridge window iteration The switch is the only statement in the resource_list_for_each_entry() loop, so remove unnecessary "continue" statements in the switch. Simplify checking for the required non-prefetchable memory aperture. No functional change intended. Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pci-versatile.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/pci/host/pci-versatile.c b/drivers/pci/host/pci-versatile.c index 273edaca8f49..f234405770ab 100644 --- a/drivers/pci/host/pci-versatile.c +++ b/drivers/pci/host/pci-versatile.c @@ -90,11 +90,9 @@ static int versatile_pci_parse_request_of_pci_ranges(struct device *dev, switch (resource_type(res)) { case IORESOURCE_IO: err = pci_remap_iospace(res, iobase); - if (err) { + if (err) dev_warn(dev, "error %d: failed to map resource %pR\n", err, res); - continue; - } break; case IORESOURCE_MEM: res_valid |= !(res->flags & IORESOURCE_PREFETCH); @@ -104,19 +102,14 @@ static int versatile_pci_parse_request_of_pci_ranges(struct device *dev, mem++; break; - case IORESOURCE_BUS: - default: - continue; } } - if (!res_valid) { - dev_err(dev, "non-prefetchable memory resource required\n"); - err = -EINVAL; - goto out_release_res; - } + if (res_valid) + return 0; - return 0; + dev_err(dev, "non-prefetchable memory resource required\n"); + err = -EINVAL; out_release_res: pci_free_resource_list(res); -- cgit v1.2.3 From 09e3cded27709d148ce06313f96b777ba7617f26 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 6 Jul 2016 14:46:04 +0200 Subject: PCI: artpec: Add PCI_MSI_IRQ_DOMAIN dependency The DesignWare PCIe driver requires MSI support, so we get a warning for the artpec6 glue driver if that is not enabled: warning: (PCIE_ARTPEC6) selects PCIE_DW which has unmet direct dependencies (PCI && PCI_MSI_IRQ_DOMAIN) Add the same dependency that all other such drivers have. Signed-off-by: Arnd Bergmann Signed-off-by: Bjorn Helgaas Acked-by: Niklas Cassel --- drivers/pci/host/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index 033d9ad37c74..2f9ca9434989 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig @@ -248,6 +248,7 @@ config PCIE_ARMADA_8K config PCIE_ARTPEC6 bool "Axis ARTPEC-6 PCIe controller" depends on MACH_ARTPEC6 + depends on PCI_MSI_IRQ_DOMAIN select PCIE_DW select PCIEPORTBUS help -- cgit v1.2.3 From 0e6f98cb6269c7f5810509fc965e09049060d675 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sat, 2 Jul 2016 19:13:21 -0400 Subject: PCI: armada8k: Make explicitly non-modular This code is not being built as a module by anyone: drivers/pci/host/Kconfig:config PCIE_ARMADA_8K drivers/pci/host/Kconfig: bool "Marvell Armada-8K PCIe controller" Remove uses of MODULE_DESCRIPTION(), MODULE_AUTHOR(), MODULE_LICENSE(), etc., so that when reading the driver there is no doubt it is builtin-only. The information is preserved in comments at the top of the file. Replace module_platform_driver() with builtin_platform_driver(), which uses the same init level priority, so init ordering is unchanged. Note that MODULE_DEVICE_TABLE is a no-op for non-modular code. [bhelgaas: changelog] Signed-off-by: Paul Gortmaker Signed-off-by: Bjorn Helgaas CC: Thomas Petazzoni --- drivers/pci/host/pcie-armada8k.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/pci/host/pcie-armada8k.c b/drivers/pci/host/pcie-armada8k.c index 55723567b5d4..0f4f570068e3 100644 --- a/drivers/pci/host/pcie-armada8k.c +++ b/drivers/pci/host/pcie-armada8k.c @@ -5,6 +5,9 @@ * * Copyright (C) 2016 Marvell Technology Group Ltd. * + * Author: Yehuda Yitshak + * Author: Shadi Ammouri + * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any * warranty of any kind, whether express or implied. @@ -14,7 +17,7 @@ #include #include #include -#include +#include #include #include #include @@ -244,7 +247,6 @@ static const struct of_device_id armada8k_pcie_of_match[] = { { .compatible = "marvell,armada8k-pcie", }, {}, }; -MODULE_DEVICE_TABLE(of, armada8k_pcie_of_match); static struct platform_driver armada8k_pcie_driver = { .probe = armada8k_pcie_probe, @@ -253,10 +255,4 @@ static struct platform_driver armada8k_pcie_driver = { .of_match_table = of_match_ptr(armada8k_pcie_of_match), }, }; - -module_platform_driver(armada8k_pcie_driver); - -MODULE_DESCRIPTION("Armada 8k PCIe host controller driver"); -MODULE_AUTHOR("Yehuda Yitshak "); -MODULE_AUTHOR("Shadi Ammouri "); -MODULE_LICENSE("GPL v2"); +builtin_platform_driver(armada8k_pcie_driver); -- cgit v1.2.3 From 58bdaa1d38d1d7e8bc41f903ff0e83fedc58ccdc Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sat, 2 Jul 2016 19:13:22 -0400 Subject: PCI: artpec6: Make explicitly non-modular This code is not being built as a module by anyone: drivers/pci/host/Kconfig:config PCIE_ARTPEC6 drivers/pci/host/Kconfig: bool "Axis ARTPEC-6 PCIe controller" Remove uses of MODULE_DESCRIPTION(), MODULE_AUTHOR(), MODULE_LICENSE(), etc., so that when reading the driver there is no doubt it is builtin-only. The information is preserved in comments at the top of the file. Replace module_platform_driver() with builtin_platform_driver(), which uses the same init level priority, so init ordering is unchanged. Note that MODULE_DEVICE_TABLE is a no-op for non-modular code. [bhelgaas: changelog, add "Author" comment] Signed-off-by: Paul Gortmaker Signed-off-by: Bjorn Helgaas CC: Niklas Cassel CC: Jesper Nilsson --- drivers/pci/host/pcie-artpec6.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/pci/host/pcie-artpec6.c b/drivers/pci/host/pcie-artpec6.c index be54fad4698b..16ba70b7ec65 100644 --- a/drivers/pci/host/pcie-artpec6.c +++ b/drivers/pci/host/pcie-artpec6.c @@ -1,6 +1,8 @@ /* * PCIe