summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/pci/pci-rcar-gen2.txt17
-rw-r--r--Documentation/devicetree/bindings/pci/rcar-pci.txt14
-rw-r--r--arch/powerpc/kernel/eeh_driver.c2
-rw-r--r--arch/powerpc/kernel/pci_of_scan.c3
-rw-r--r--arch/x86/include/asm/pci_x86.h10
-rw-r--r--arch/x86/pci/pcbios.c108
-rw-r--r--drivers/pci/host/Kconfig3
-rw-r--r--drivers/pci/host/pci-host-generic.c9
-rw-r--r--drivers/pci/host/pci-imx6.c20
-rw-r--r--drivers/pci/host/pci-rcar-gen2.c77
-rw-r--r--drivers/pci/host/pci-versatile.c5
-rw-r--r--drivers/pci/host/pcie-rcar.c118
-rw-r--r--drivers/pci/hotplug/ibmphp_pci.c2
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c2
-rw-r--r--drivers/pci/msi.c4
-rw-r--r--drivers/pci/pci-sysfs.c18
-rw-r--r--drivers/pci/pci.h2
-rw-r--r--drivers/pci/pcie/aer/aerdrv_core.c10
-rw-r--r--drivers/pci/pcie/aspm.c16
-rw-r--r--drivers/pci/probe.c33
-rw-r--r--drivers/pci/quirks.c11
-rw-r--r--drivers/pci/rom.c20
-rw-r--r--include/linux/pci.h2
-rw-r--r--include/linux/pci_ids.h6
24 files changed, 287 insertions, 225 deletions
diff --git a/Documentation/devicetree/bindings/pci/pci-rcar-gen2.txt b/Documentation/devicetree/bindings/pci/pci-rcar-gen2.txt
index 7fab84b33531..4e8b90e43dd8 100644
--- a/Documentation/devicetree/bindings/pci/pci-rcar-gen2.txt
+++ b/Documentation/devicetree/bindings/pci/pci-rcar-gen2.txt
@@ -8,7 +8,14 @@ OHCI and EHCI controllers.
Required properties:
- compatible: "renesas,pci-r8a7790" for the R8A7790 SoC;
"renesas,pci-r8a7791" for the R8A7791 SoC;
- "renesas,pci-r8a7794" for the R8A7794 SoC.
+ "renesas,pci-r8a7794" for the R8A7794 SoC;
+ "renesas,pci-rcar-gen2" for a generic R-Car Gen2 compatible device
+
+
+ When compatible with the generic version, nodes must list the
+ SoC-specific version corresponding to the platform first
+ followed by the generic version.
+
- reg: A list of physical regions to access the device: the first is
the operational registers for the OHCI/EHCI controllers and the
second is for the bridge configuration and control registers.
@@ -24,10 +31,15 @@ Required properties:
- interrupt-map-mask: standard property that helps to define the interrupt
mapping.
+Optional properties:
+- dma-ranges: a single range for the inbound memory region. If not supplied,
+ defaults to 1GiB at 0x40000000. Note there are hardware restrictions on the
+ allowed combinations of address and size.
+
Example SoC configuration:
pci0: pci@ee090000 {
- compatible = "renesas,pci-r8a7790";
+ compatible = "renesas,pci-r8a7790", "renesas,pci-rcar-gen2";
clocks = <&mstp7_clks R8A7790_CLK_EHCI>;
reg = <0x0 0xee090000 0x0 0xc00>,
<0x0 0xee080000 0x0 0x1100>;
@@ -38,6 +50,7 @@ Example SoC configuration:
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
+ dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x40000000>;
interrupt-map-mask = <0xff00 0 0 0x7>;
interrupt-map = <0x0000 0 0 1 &gic 0 108 IRQ_TYPE_LEVEL_HIGH
0x0800 0 0 1 &gic 0 108 IRQ_TYPE_LEVEL_HIGH
diff --git a/Documentation/devicetree/bindings/pci/rcar-pci.txt b/Documentation/devicetree/bindings/pci/rcar-pci.txt
index 29d3b989d3b0..558fe528ae19 100644
--- a/Documentation/devicetree/bindings/pci/rcar-pci.txt
+++ b/Documentation/devicetree/bindings/pci/rcar-pci.txt
@@ -1,8 +1,16 @@
* Renesas RCar PCIe interface
Required properties:
-- compatible: should contain one of the following
- "renesas,pcie-r8a7779", "renesas,pcie-r8a7790", "renesas,pcie-r8a7791"
+compatible: "renesas,pcie-r8a7779" for the R8A7779 SoC;
+ "renesas,pcie-r8a7790" for the R8A7790 SoC;
+ "renesas,pcie-r8a7791" for the R8A7791 SoC;
+ "renesas,pcie-r8a7795" for the R8A7795 SoC;
+ "renesas,pcie-rcar-gen2" for a generic R-Car Gen2 compatible device.
+
+ When compatible with the generic version, nodes must list the
+ SoC-specific version corresponding to the platform first
+ followed by the generic version.
+
- reg: base address and length of the pcie controller registers.
- #address-cells: set to <3>
- #size-cells: set to <2>
@@ -25,7 +33,7 @@ Example:
SoC specific DT Entry:
pcie: pcie@fe000000 {
- compatible = "renesas,pcie-r8a7791";
+ compatible = "renesas,pcie-r8a7791", "renesas,pcie-rcar-gen2";
reg = <0 0xfe000000 0 0x80000>;
#address-cells = <3>;
#size-cells = <2>;
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
index 80dfe8965df9..44bca7892f66 100644
--- a/arch/powerpc/kernel/eeh_driver.c
+++ b/arch/powerpc/kernel/eeh_driver.c
@@ -400,7 +400,7 @@ static void *eeh_rmv_device(void *data, void *userdata)
* support EEH. So we just care about PCI devices for
* simplicity here.
*/
- if (!dev || (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE))
+ if (!dev || (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE))
return NULL;
/*
diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c
index 2e710c15893f..526ac6750e4d 100644
--- a/arch/powerpc/kernel/pci_of_scan.c
+++ b/arch/powerpc/kernel/pci_of_scan.c
@@ -187,9 +187,6 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
pci_device_add(dev, bus);
- /* Setup MSI caps & disable MSI/MSI-X interrupts */
- pci_msi_setup_pci_dev(dev);
-
return dev;
}
EXPORT_SYMBOL(of_create_pci_dev);
diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h
index fa1195dae425..46873fbd44e1 100644
--- a/arch/x86/include/asm/pci_x86.h
+++ b/arch/x86/include/asm/pci_x86.h
@@ -151,11 +151,11 @@ extern struct list_head pci_mmcfg_list;
#define PCI_MMCFG_BUS_OFFSET(bus) ((bus) << 20)
/*
- * AMD Fam10h CPUs are buggy, and cannot access MMIO config space
- * on their northbrige except through the * %eax register. As such, you MUST
- * NOT use normal IOMEM accesses, you need to only use the magic mmio-config
- * accessor functions.
- * In fact just use pci_config_*, nothing else please.
+ * On AMD Fam10h CPUs, all PCI MMIO configuration space accesses must use
+ * %eax. No other source or target registers may be used. The following
+ * mmio_config_* accessors enforce this. See "BIOS and Kernel Developer's
+ * Guide (BKDG) For AMD Family 10h Processors", rev. 3.48, sec 2.11.1,
+ * "MMIO Configuration Coding Requirements".
*/
static inline unsigned char mmio_config_readb(void __iomem *pos)
{
diff --git a/arch/x86/pci/pcbios.c b/arch/x86/pci/pcbios.c
index 9b83b9051ae7..9770e55e768f 100644
--- a/arch/x86/pci/pcbios.c
+++ b/arch/x86/pci/pcbios.c
@@ -180,6 +180,7 @@ static int pci_bios_read(unsigned int seg, unsigned int bus,
unsigned long result = 0;
unsigned long flags;
unsigned long bx = (bus << 8) | devfn;
+ u16 number = 0, mask = 0;
WARN_ON(seg);
if (!value || (bus > 255) || (devfn > 255) || (reg > 255))
@@ -189,53 +190,35 @@ static int pci_bios_read(unsigned int seg, unsigned int bus,
switch (len) {
case 1:
- __asm__("lcall *(%%esi); cld\n\t"
- "jc 1f\n\t"
- "xor %%ah, %%ah\n"
- "1:"
- : "=c" (*value),
- "=a" (result)
- : "1" (PCIBIOS_READ_CONFIG_BYTE),
- "b" (bx),
- "D" ((long)reg),
- "S" (&pci_indirect));
- /*
- * Zero-extend the result beyond 8 bits, do not trust the
- * BIOS having done it:
- */
- *value &= 0xff;
+ number = PCIBIOS_READ_CONFIG_BYTE;
+ mask = 0xff;
break;
case 2:
- __asm__("lcall *(%%esi); cld\n\t"
- "jc 1f\n\t"
- "xor %%ah, %%ah\n"
- "1:"
- : "=c" (*value),
- "=a" (result)
- : "1" (PCIBIOS_READ_CONFIG_WORD),
- "b" (bx),
- "D" ((long)reg),
- "S" (&pci_indirect));
- /*
- * Zero-extend the result beyond 16 bits, do not trust the
- * BIOS having done it:
- */
- *value &= 0xffff;
+ number = PCIBIOS_READ_CONFIG_WORD;
+ mask = 0xffff;
break;
case 4:
- __asm__("lcall *(%%esi); cld\n\t"
- "jc 1f\n\t"
- "xor %%ah, %%ah\n"
- "1:"
- : "=c" (*value),
- "=a" (result)
- : "1" (PCIBIOS_READ_CONFIG_DWORD),
- "b" (bx),
- "D" ((long)reg),
- "S" (&pci_indirect));
+ number = PCIBIOS_READ_CONFIG_DWORD;
break;
}
+ __asm__("lcall *(%%esi); cld\n\t"
+ "jc 1f\n\t"
+ "xor %%ah, %%ah\n"
+ "1:"
+ : "=c" (*value),
+ "=a" (result)
+ : "1" (number),
+ "b" (bx),
+ "D" ((long)reg),
+ "S" (&pci_indirect));
+ /*
+ * Zero-extend the result beyond 8 or 16 bits, do not trust the
+ * BIOS having done it:
+ */
+ if (mask)
+ *value &= mask;
+
raw_spin_unlock_irqrestore(&pci_config_lock, flags);
return (int)((result & 0xff00) >> 8);
@@ -247,6 +230,7 @@ static int pci_bios_write(unsigned int seg, unsigned int bus,
unsigned long result = 0;
unsigned long flags;
unsigned long bx = (bus << 8) | devfn;
+ u16 number = 0;
WARN_ON(seg);
if ((bus > 255) || (devfn > 255) || (reg > 255))
@@ -256,43 +240,27 @@ static int pci_bios_write(unsigned int seg, unsigned int bus,
switch (len) {
case 1:
- __asm__("lcall *(%%esi); cld\n\t"
- "jc 1f\n\t"
- "xor %%ah, %%ah\n"
- "1:"
- : "=a" (result)
- : "0" (PCIBIOS_WRITE_CONFIG_BYTE),
- "c" (value),
- "b" (bx),
- "D" ((long)reg),
- "S" (&pci_indirect));
+ number = PCIBIOS_WRITE_CONFIG_BYTE;
break;
case 2:
- __asm__("lcall *(%%esi); cld\n\t"
- "jc 1f\n\t"
- "xor %%ah, %%ah\n"
- "1:"
- : "=a" (result)
- : "0" (PCIBIOS_WRITE_CONFIG_WORD),
- "c" (value),
- "b" (bx),
- "D" ((long)reg),
- "S" (&pci_indirect));
+ number = PCIBIOS_WRITE_CONFIG_WORD;
break;
case 4:
- __asm__("lcall *(%%esi); cld\n\t"
- "jc 1f\n\t"
- "xor %%ah, %%ah\n"
- "1:"
- : "=a" (result)
- : "0" (PCIBIOS_WRITE_CONFIG_DWORD),
- "c" (value),
- "b" (bx),
- "D" ((long)reg),
- "S" (&pci_indirect));
+ number = PCIBIOS_WRITE_CONFIG_DWORD;
break;
}
+ __asm__("lcall *(%%esi); cld\n\t"
+ "jc 1f\n\t"
+ "xor %%ah, %%ah\n"
+ "1:"
+ : "=a" (result)
+ : "0" (number),
+ "c" (value),
+ "b" (bx),
+ "D" ((long)reg),
+ "S" (&pci_indirect));
+
raw_spin_unlock_irqrestore(&pci_config_lock, flags);
return (int)((result & 0xff00) >> 8);
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index 1cb50d21c21d..98ce5474d26e 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -48,8 +48,7 @@ config PCI_RCAR_GEN2
config PCI_RCAR_GEN2_PCIE
bool "Renesas R-Car PCIe controller"
- depends on ARM
- depends on ARCH_SHMOBILE || COMPILE_TEST
+ depends on ARCH_SHMOBILE || (ARM && COMPILE_TEST)
help
Say Y here if you want PCIe controller support on R-Car Gen2 SoCs.
diff --git a/drivers/pci/host/pci-host-generic.c b/drivers/pci/host/pci-host-generic.c
index 5434c90db243..1652bc70b145 100644
--- a/drivers/pci/host/pci-host-generic.c
+++ b/drivers/pci/host/pci-host-generic.c
@@ -38,16 +38,7 @@ struct gen_pci_cfg_windows {
struct gen_pci_cfg_bus_ops *ops;
};
-/*
- * ARM pcibios functions expect the ARM struct pci_sys_data as the PCI
- * sysdata. Add pci_sys_data as the first element in struct gen_pci so
- * that when we use a gen_pci pointer as sysdata, it is also a pointer to
- * a struct pci_sys_data.
- */
struct gen_pci {
-#ifdef CONFIG_ARM
- struct pci_sys_data sys;
-#endif
struct pci_host_bridge host;
struct gen_pci_cfg_windows cfg;
struct list_head resources;
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index 22e8224126fd..8e9afa5bd7de 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -32,7 +32,7 @@
#define to_imx6_pcie(x) container_of(x, struct imx6_pcie, pp)
struct imx6_pcie {
- int reset_gpio;
+ struct gpio_desc *reset_gpio;
struct clk *pcie_bus;
struct clk *pcie_phy;
struct clk *pcie;
@@ -287,10 +287,10 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp)
usleep_range(200, 500);
/* Some boards don't have PCIe reset GPIO. */
- if (gpio_is_valid(imx6_pcie->reset_gpio)) {
- gpio_set_value(imx6_pcie->reset_gpio, 0);
+ if (imx6_pcie->reset_gpio) {
+ gpiod_set_value_cansleep(imx6_pcie->reset_gpio, 0);
msleep(100);
- gpio_set_value(imx6_pcie->reset_gpio, 1);
+ gpiod_set_value_cansleep(imx6_pcie->reset_gpio, 1);
}
return 0;
@@ -560,7 +560,6 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
{
struct imx6_pcie *imx6_pcie;
struct pcie_port *pp;
- struct device_node *np = pdev->dev.of_node;
struct resource *dbi_base;
int ret;
@@ -581,15 +580,8 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
return PTR_ERR(pp->dbi_base);
/* Fetch GPIOs */
- imx6_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
- if (gpio_is_valid(imx6_pcie->reset_gpio)) {
- ret = devm_gpio_request_one(&pdev->dev, imx6_pcie->reset_gpio,
- GPIOF_OUT_INIT_LOW, "PCIe reset");
- if (ret) {
- dev_err(&pdev->dev, "unable to get reset gpio\n");
- return ret;
- }
- }
+ imx6_pcie->reset_gpio = devm_gpiod_get_optional(&pdev->dev, "reset",
+ GPIOD_OUT_LOW);
/* Fetch clocks */
imx6_pcie->pcie_phy = devm_clk_get(&pdev->dev, "pcie_phy");
diff --git a/drivers/pci/host/pci-rcar-gen2.c b/drivers/pci/host/pci-rcar-gen2.c
index c4f64bfee551..9980a4bdae7e 100644
--- a/drivers/pci/host/pci-rcar-gen2.c
+++ b/drivers/pci/host/pci-rcar-gen2.c
@@ -15,6 +15,7 @@
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/of_address.h>
#include <linux/of_pci.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
@@ -102,6 +103,8 @@ struct rcar_pci_priv {
unsigned busnr;
int irq;
unsigned long window_size;
+ unsigned long window_addr;
+ unsigned long window_pci;
};
/* PCI configuration space operations */
@@ -239,8 +242,8 @@ static int rcar_pci_setup(int nr, struct pci_sys_data *sys)
RCAR_PCI_ARBITER_PCIBP_MODE;
iowrite32(val, reg + RCAR_PCI_ARBITER_CTR_REG);
- /* PCI-AHB mapping: 0x40000000 base */
- iowrite32(0x40000000 | RCAR_PCIAHB_PREFETCH16,
+ /* PCI-AHB mapping */
+ iowrite32(priv->window_addr | RCAR_PCIAHB_PREFETCH16,
reg + RCAR_PCIAHB_WIN1_CTR_REG);
/* AHB-PCI mapping: OHCI/EHCI registers */
@@ -251,7 +254,7 @@ static int rcar_pci_setup(int nr, struct pci_sys_data *sys)
iowrite32(RCAR_AHBPCI_WIN1_HOST | RCAR_AHBPCI_WIN_CTR_CFG,
reg + RCAR_AHBPCI_WIN1_CTR_REG);
/* Set PCI-AHB Window1 address */
- iowrite32(0x40000000 | PCI_BASE_ADDRESS_MEM_PREFETCH,
+ iowrite32(priv->window_pci | PCI_BASE_ADDRESS_MEM_PREFETCH,
reg + PCI_BASE_ADDRESS_1);
/* Set AHB-PCI bridge PCI communication area address */
val = priv->cfg_res->start + RCAR_AHBPCI_PCICOM_OFFSET;
@@ -284,6 +287,64 @@ static struct pci_ops rcar_pci_ops = {
.write = pci_generic_config_write,
};
+static int pci_dma_range_parser_init(struct of_pci_range_parser *parser,
+ struct device_node *node)
+{
+ const int na = 3, ns = 2;
+ int rlen;
+
+ parser->node = node;
+ parser->pna = of_n_addr_cells(node);
+ parser->np = parser->pna + na + ns;
+
+ parser->range = of_get_property(node, "dma-ranges", &rlen);
+ if (!parser->range)
+ return -ENOENT;
+
+ parser->end = parser->range + rlen / sizeof(__be32);
+ return 0;
+}
+
+static int rcar_pci_parse_map_dma_ranges(struct rcar_pci_priv *pci,
+ struct device_node *np)
+{
+ struct of_pci_range range;
+ struct of_pci_range_parser parser;
+ int index = 0;
+
+ /* Failure to parse is ok as we fall back to defaults */
+ if (pci_dma_range_parser_init(&parser, np))
+ return 0;
+
+ /* Get the dma-ranges from DT */
+ for_each_of_pci_range(&parser, &range) {
+ /* Hardware only allows one inbound 32-bit range */
+ if (index)
+ return -EINVAL;
+
+ pci->window_addr = (unsigned long)range.cpu_addr;
+ pci->window_pci = (unsigned long)range.pci_addr;
+ pci->window_size = (unsigned long)range.size;
+
+ /* Catch HW limitations */
+ if (!(range.flags & IORESOURCE_PREFETCH)) {
+ dev_err(pci->dev, "window must be prefetchable\n");
+ return -EINVAL;
+ }
+ if (pci->window_addr) {
+ u32 lowaddr = 1 << (ffs(pci->window_addr) - 1);
+
+ if (lowaddr < pci->window_size) {
+ dev_err(pci->dev, "invalid window size/addr\n");
+ return -EINVAL;
+ }
+ }
+ index++;
+ }
+
+ return 0;
+}
+
static int rcar_pci_probe(struct platform_device *pdev)
{
struct resource *cfg_res, *mem_res;
@@ -329,6 +390,9 @@ static int rcar_pci_probe(struct platform_device *pdev)
return priv->irq;
}
+ /* default window addr and size if not specified in DT */
+ priv->window_addr = 0x40000000;
+ priv->window_pci = 0x40000000;
priv->window_size = SZ_1G;
if (pdev->dev.of_node) {
@@ -344,6 +408,12 @@ static int rcar_pci_probe(struct platform_device *pdev)
priv->busnr = busnr.start;
if (busnr.end != busnr.start)
dev_warn(&pdev->dev, "only one bus number supported\n");
+
+ ret = rcar_pci_parse_map_dma_ranges(priv, pdev->dev.of_node);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to parse dma-range\n");
+ return ret;
+ }
} else {
priv->busnr = pdev->id;
}
@@ -360,6 +430,7 @@ static int rcar_pci_probe(struct platform_device *pdev)
}
static struct of_device_id rcar_pci_of_match[] = {
+ { .compatible = "renesas,pci-rcar-gen2", },
{ .compatible = "renesas,pci-r8a7790", },
{ .compatible = "renesas,pci-r8a7791", },
{ .compatible = "renesas,pci-r8a7794", },
diff --git a/drivers/pci/host/pci-versatile.c b/drivers/pci/host/pci-versatile.c
index 0863d9cc25f8..f843a72dc51c 100644
--- a/drivers/pci/host/pci-versatile.c
+++ b/drivers/pci/host/pci-versatile.c
@@ -125,9 +125,6 @@ out_release_res:
return err;
}
-/* Unused, temporary to satisfy ARM arch code */
-struct pci_sys_data sys;
-
static int versatile_pci_probe(struct platform_device *pdev)
{
struct resource *res;
@@ -208,7 +205,7 @@ static int versatile_pci_probe(struct platform_device *pdev)
pci_add_flags(PCI_ENABLE_PROC_DOMAINS);
pci_add_flags(PCI_REASSIGN_ALL_BUS | PCI_REASSIGN_ALL_RSRC);
- bus = pci_scan_root_bus(&pdev->dev, 0, &pci_versatile_ops, &sys, &pci_res);
+ bus = pci_scan_root_bus(&pdev->dev, 0, &pci_versatile_ops, NULL, &pci_res);
if (!bus)
return -ENOMEM;
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
index f4fa6c537448..5c2962646b17 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/host/pcie-rcar.c
@@ -108,8 +108,6 @@
#define RCAR_PCI_MAX_RESOURCES 4
#define MAX_NR_INBOUND_MAPS 6
-static unsigned long global_io_offset;
-
struct rcar_msi {
DECLARE_BITMAP(used, INT_PCI_MSI_NR);
struct irq_domain *domain;
@@ -138,8 +136,7 @@ struct rcar_pcie {
#endif
struct device *dev;
void __iomem *base;
- struct resource res[RCAR_PCI_MAX_RESOURCES];
- struct resource busn;
+ struct list_head resources;
int root_bus_nr;
struct clk *clk;
struct clk *bus_clk;
@@ -323,10 +320,9 @@ static struct pci_ops rcar_pcie_ops = {
.write = rcar_pcie_write_conf,
};
-static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
+static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie,
+ struct resource *res)
{
- struct resource *res = &pcie->res[win];
-
/* Setup PCIe address space mappings for each resource */
resource_size_t size;
resource_size_t res_start;
@@ -359,31 +355,33 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
rcar_pci_write_reg(pcie, mask, PCIEPTCTLR(win));
}
-static int rcar_pcie_setup(struct list_head *resource, struct rcar_pcie *pcie)
+static int rcar_pcie_setup(struct list_head *resource, struct rcar_pcie *pci)
{
- struct resource *res;
- int i;
-
- pcie->root_bus_nr = pcie->busn.start;
+ struct resource_entry *win;
+ int i = 0;
/* Setup PCI resources */
- for (i = 0; i < RCAR_PCI_MAX_RESOURCES; i++) {
+ resource_list_for_each_entry(win, &pci->resources) {
+ struct resource *res = win->res;
- res = &pcie->res[i];
if (!res->flags)
continue;
- rcar_pcie_setup_window(i, pcie);
-
- if (res->flags & IORESOURCE_IO) {
- phys_addr_t io_start = pci_pio_to_address(res->start);
- pci_ioremap_io(global_io_offset, io_start);
- global_io_offset += SZ_64K;
+ switch (resource_type(res)) {
+ case IORESOURCE_IO:
+ case IORESOURCE_MEM:
+ rcar_pcie_setup_window(i, pci, res);
+ i++;
+ break;
+ case IORESOURCE_BUS:
+ pci->root_bus_nr = res->start;
+ break;
+ default:
+ continue;
}
pci_add_resource(resource, res);
}
- pci_add_resource(resource, &pcie->busn);
return 1;
}
@@ -917,20 +915,71 @@ static int rcar_pcie_parse_map_dma_ranges(struct rcar_pcie *pcie,
static const struct of_device_id rcar_pcie_of_match[] = {
{ .compatible = "renesas,pcie-r8a7779", .data = rcar_pcie_hw_init_h1 },
+ { .compatible = "renesas,pcie-rcar-gen2", .data = rcar_pcie_hw_init },
{ .compatible = "renesas,pcie-r8a7790", .data = rcar_pcie_hw_init },
{ .compatible = "renesas,pcie-r8a7791", .data = rcar_pcie_hw_init },
+ { .compatible = "renesas,pcie-r8a7795", .data = rcar_pcie_hw_init },
{},
};
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;
+ struct device *dev = pci->dev;
+ struct device_node *np = dev->of_node;
+ resource_size_t iobase;
+ struct resource_entry *win;
+
+ err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pci->resources, &iobase);
+ if (err)
+ return err;
+
+ resource_list_for_each_entry(win, &pci->resources) {
+ struct resource *parent, *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",
+ err, res);
+ continue;
+ }
+ 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;
+
+out_release_res:
+ rcar_pcie_release_of_pci_ranges(pci);
+ return err;
+}
+
static int rcar_pcie_probe(struct platform_device *pdev)
{
struct rcar_pcie *pcie;
unsigned int data;
- struct of_pci_range range;
- struct of_pci_range_parser parser;
const struct of_device_id *of_id;
- int err, win = 0;
+ int err;
int (*hw_init_fn)(struct rcar_pcie *);
pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL);
@@ -940,16 +989,9 @@ static int rcar_pcie_probe(struct platform_device *pdev)
pcie->dev = &pdev->dev;
platform_set_drvdata(pdev, pcie);
- /* Get the bus range */
- if (of_pci_parse_bus_range(pdev->dev.of_node, &pcie->busn)) {
- dev_err(&pdev->dev, "failed to parse bus-range property\n");
- return -EINVAL;
- }
+ INIT_LIST_HEAD(&pcie->resources);
- if (of_pci_range_parser_init(&parser, pdev->dev.of_node)) {
- dev_err(&pdev->dev, "missing ranges property\n");
- return -EINVAL;
- }
+ rcar_pcie_parse_request_of_pci_ranges(pcie);
err = rcar_pcie_get_resources(pdev, pcie);
if (err < 0) {
@@ -957,16 +999,6 @@ static int rcar_pcie_probe(struct platform_device *pdev)
return err;
}
- for_each_of_pci_range(&parser, &range) {
- err = of_pci_range_to_resource(&range, pdev->dev.of_node,
- &pcie->res[win++]);
- if (err < 0)
- return err;
-
- if (win > RCAR_PCI_MAX_RESOURCES)
- break;
- }
-
err = rcar_pcie_parse_map_dma_ranges(pcie, pdev->dev.of_node);
if (err)
return err;
diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c
index 814cea22a9fa..5824df538f72 100644
--- a/drivers/pci/hotplug/ibmphp_pci.c
+++ b/drivers/pci/hotplug/ibmphp_pci.c
@@ -1119,7 +1119,7 @@ static struct res_needed *scan_behind_bridge (struct pci_func *func, u8 busno)
pci_bus_read_config_dword (ibmphp_pci_bus, devfn, PCI_CLASS_REVISION, &class);
debug ("hdr_type behind the bridge is %x\n", hdr_type);
- if (hdr_type & PCI_HEADER_TYPE_BRIDGE) {
+ if ((hdr_type & 0x7f) == PCI_HEADER_TYPE_BRIDGE) {
err ("embedded bridges not supported for hot-plugging.\n");
amount->not_correct = 1;
return amount;
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 4c8f4cde6854..880978b6d534 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -511,7 +511,9 @@ int pciehp_sysfs_disable_slot(struct slot *p_slot)
case STATIC_STATE:
p_slot->state = POWEROFF_STATE;
mutex_unlock(&p_slot->lock);
+ mutex_lock(&p_slot->hotplug_lock);
retval = pciehp_disable_slot(p_slot);
+ mutex_unlock(&p_slot->hotplug_lock);
mutex_lock(&p_slot->lock);
p_slot->state = STATIC_STATE;
break;
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 53e463244bb7..b64d26719906 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -1024,10 +1024,6 @@ int pci_msi_enabled(void)
}
EXPORT_SYMBOL(pci_msi_enabled);
-void pci_msi_init_pci_dev(struct pci_dev *dev)
-{
-}
-
/**
* pci_enable_msi_range - configure device's MSI capability structure
* @dev: device to configure
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 92618686604c..9cd27b703dd6 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -1369,10 +1369,10 @@ int __must_check pci_create_sysfs_dev_files(struct pci_dev *pdev)
if (!sysfs_initialized)
return -EACCES;
- if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
- retval = sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr);
- else
+ if (pdev->cfg_size > PCI_CFG_SPACE_SIZE)
retval = sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr);
+ else
+ retval = sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr);
if (retval)
goto err;
@@ -1424,10 +1424,10 @@ err_rom_file:
err_resource_files:
pci_remove_resource_files(pdev);
err_config_file:
- if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
- sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
- else
+ if (pdev->cfg_size > PCI_CFG_SPACE_SIZE)
sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
+ else
+ sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
err:
return retval;
}
@@ -1461,10 +1461,10 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
pci_remove_capabilities_sysfs(pdev);
- if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
- sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
- else
+ if (pdev->cfg_size > PCI_CFG_SPACE_SIZE)
sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
+ else
+ sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
pci_remove_resource_files(pdev);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index fd2f03fa53f3..44d9859057b4 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -144,10 +144,8 @@ extern unsigned int pci_pm_d3_delay;
#ifdef CONFIG_PCI_MSI
void pci_no_msi(void);
-void pci_msi_init_pci_dev(struct pci_dev *dev);
#else
static inline void pci_no_msi(void) { }
-static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { }
#endif
static inline void pci_msi_set_enable(struct pci_dev *dev, int enable)
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index fba785e9df75..712392504ed9 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -246,7 +246,7 @@ static int report_error_detected(struct pci_dev *dev, void *data)
!dev->driver->err_handler ||
!dev->driver->err_handler->error_detected) {
if (result_data->state == pci_channel_io_frozen &&
- !(dev->hdr_type & PCI_HEADER_TYPE_BRIDGE)) {
+ dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
/*
* In case of fatal recovery, if one of down-
* stream device has no driver. We might be
@@ -269,7 +269,7 @@ static int report_error_detected(struct pci_dev *dev, void *data)
* without recovery.
*/
- if (!(dev->hdr_type & PCI_HEADER_TYPE_BRIDGE))
+ if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE)
vote = PCI_ERS_RESULT_NO_AER_DRIVER;
else
vote = PCI_ERS_RESULT_NONE;
@@ -369,7 +369,7 @@ static pci_ers_result_t broadcast_error_message(struct pci_dev *dev,
else
result_data.result = PCI_ERS_RESULT_RECOVERED;
- if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) {
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
/*
* If the error is reported by a bridge, we think this error
* is related to the downstream link of the bridge, so we
@@ -440,7 +440,7 @@ static pci_ers_result_t reset_link(struct pci_dev *dev)
pci_ers_result_t status;
struct pcie_port_service_driver *driver;
- if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) {
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
/* Reset this port for all subordinates */
udev = dev;
} else {
@@ -660,7 +660,7 @@ static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info)
&info->mask);
if (!(info->status & ~info->mask))
return 0;
- } else if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE ||
+ } else if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
info->severity == AER_NONFATAL) {
/* Link is still healthy for IO reads */
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 317e3558a35e..2dfe7fdb77e7 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -834,21 +834,15 @@ static ssize_t link_state_store(struct device *dev,
{
struct pci_dev *pdev = to_pci_dev(dev);
struct pcie_link_state *link, *root = pdev->link_state->root;
- u32 val, state = 0;
-
- if (kstrtouint(buf, 10, &val))
- return -EINVAL;
+ u32 state;
if (aspm_disabled)
return -EPERM;
- if (n < 1 || val > 3)
- return -EINVAL;
- /* Convert requested state to ASPM state */
- if (val & PCIE_LINK_STATE_L0S)
- state |= ASPM_STATE_L0S;
- if (val & PCIE_LINK_STATE_L1)
- state |= ASPM_STATE_L1;
+ if (kstrtouint(buf, 10, &state))
+ return -EINVAL;
+ if ((state & ~ASPM_STATE_ALL) != 0)
+ return -EINVAL;
down_read(&pci_bus_sem);
mutex_lock(&aspm_lock);
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index edb1984201e9..32b9f1b88266 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1107,14 +1107,11 @@ static int pci_cfg_space_size_ext(struct pci_dev *dev)
int pos = PCI_CFG_SPACE_SIZE;
if (pci_read_config_dword(dev, pos, &status) != PCIBIOS_SUCCESSFUL)
- goto fail;
+ return PCI_CFG_SPACE_SIZE;
if (status == 0xffffffff || pci_ext_cfg_is_aliased(dev))
- goto fail;
+ return PCI_CFG_SPACE_SIZE;
return PCI_CFG_SPACE_EXP_SIZE;
-
- fail:
- return PCI_CFG_SPACE_SIZE;
}
int pci_cfg_space_size(struct pci_dev *dev)
@@ -1127,25 +1124,23 @@ int pci_cfg_space_size(struct pci_dev *dev)
if (class == PCI_CLASS_BRIDGE_HOST)
return pci_cfg_space_size_ext(dev);
- if (!pci_is_pcie(dev)) {
- pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
- if (!pos)
- goto fail;
+ if (pci_is_pcie(dev))
+ return pci_cfg_space_size_ext(dev);
- pci_read_config_dword(dev, pos + PCI_X_STATUS, &status);
- if (!(status & (PCI_X_STATUS_266MHZ | PCI_X_STATUS_533MHZ)))
- goto fail;
- }
+ pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
+ if (!pos)
+ return PCI_CFG_SPACE_SIZE;
- return pci_cfg_space_size_ext(dev);
+ pci_read_config_dword(dev, pos + PCI_X_STATUS, &status);
+ if (status & (PCI_X_STATUS_266MHZ | PCI_X_STATUS_533MHZ))
+ return pci_cfg_space_size_ext(dev);
- fail:
return PCI_CFG_SPACE_SIZE;
}
#define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED)
-void pci_msi_setup_pci_dev(struct pci_dev *dev)
+static void pci_msi_setup_pci_dev(struct pci_dev *dev)
{
/*
* Disable the MSI hardware to avoid screaming interrupts
@@ -1212,8 +1207,6 @@ int pci_setup_device(struct pci_dev *dev)
/* "Unknown power state" */
dev->current_state = PCI_UNKNOWN;
- pci_msi_setup_pci_dev(dev);
-
/* Early fixups, before probing the BARs */
pci_fixup_device(pci_fixup_early, dev);
/* device class may be changed after fixup */
@@ -1603,8 +1596,8 @@ static void pci_init_capabilities(struct pci_dev *dev)
/* Enhanced Allocation */
pci_ea_init(dev);
- /* MSI/MSI-X list */
- pci_msi_init_pci_dev(dev);
+ /* Setup MSI caps & disable MSI/MSI-X interrupts */
+ pci_msi_setup_pci_dev(dev);
/* Buffers for saving PCIe and PCI-X capabilities */
pci_allocate_cap_save_buffers(dev);
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 7e327309cf69..83e93d7ca4b9 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -287,6 +287,17 @@ static void quirk_citrine(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, quirk_citrine);
+/*
+ * This chip can cause bus lockups if config addresses above 0x600
+ * are read or written.
+ */
+static void quirk_nfp6000(struct pci_dev *dev)
+{
+ dev->cfg_size = 0x600;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETRONOME, PCI_DEVICE_ID_NETRONOME_NFP6000, quirk_nfp6000);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETRONOME, PCI_DEVICE_ID_NETRONOME_NFP6000_VF, quirk_nfp6000);
+
/* On IBM Crocodile ipr SAS adapters, expand BAR to system page size */
static void quirk_extend_bar_to_page(struct pci_dev *dev)
{
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c
index eb0ad530dc43..5a1a39df75a1 100644
--- a/drivers/pci/rom.c
+++ b/drivers/pci/rom.c
@@ -77,22 +77,18 @@ size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size)
do {
void __iomem *pds;
/* Standard PCI ROMs start out with these bytes 55 AA */
- if (readb(image) != 0x55) {
- dev_err(&pdev->dev, "Invalid ROM contents\n");
+ if (readw(image) != 0xAA55) {
+ dev_err(&pdev->dev, "Invalid PCI ROM header signature: expecting 0xaa55, got %#06x\n",
+ readw(image));
break;
}
- if (readb(image + 1) != 0xAA)
- break;
- /* get the PCI data structure and check its signature */
+ /* get the PCI data structure and check its "PCIR" signature */
pds = image + readw(image + 24);
- if (readb(pds) != 'P')
- break;
- if (readb(pds + 1) != 'C')
- break;
- if (readb(pds + 2) != 'I')
- break;
- if (readb(pds + 3) != 'R')
+ if (readl(pds) != 0x52494350) {
+ dev_err(&pdev->dev, "Invalid PCI ROM data signature: expecting 0x52494350, got %#010x\n",
+ readl(pds));
break;
+ }
last_image = readb(pds + 21) & 0x80;
length = readw(pds + 16);
image += length * 512;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index e828e7b4afec..f9f79add0afb 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1248,8 +1248,6 @@ struct msix_entry {
u16 entry; /* driver uses to specify entry, OS writes */
};
-void pci_msi_setup_pci_dev(struct pci_dev *dev);
-
#ifdef CONFIG_PCI_MSI
int pci_msi_vec_count(struct pci_dev *dev);
void pci_msi_shutdown(struct pci_dev *dev);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index d9ba49cedc5d..526e2c12ae59 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2495,6 +2495,12 @@
#define PCI_DEVICE_ID_KORENIX_JETCARDF2 0x1700
#define PCI_DEVICE_ID_KORENIX_JETCARDF3 0x17ff
+#define PCI_VENDOR_ID_NETRONOME 0x19ee
+#define PCI_DEVICE_ID_NETRONOME_NFP3200 0x3200
+#define PCI_DEVICE_ID_NETRONOME_NFP3240 0x3240
+#define PCI_DEVICE_ID_NETRONOME_NFP6000 0x6000
+#define PCI_DEVICE_ID_NETRONOME_NFP6000_VF 0x6003
+
#define PCI_VENDOR_ID_QMI 0x1a32
#define PCI_VENDOR_ID_AZWAVE 0x1a3b