summaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/Kconfig2
-rw-r--r--drivers/pci/Makefile1
-rw-r--r--drivers/pci/access.c84
-rw-r--r--drivers/pci/ats.c131
-rw-r--r--drivers/pci/host/Kconfig8
-rw-r--r--drivers/pci/host/pci-dra7xx.c122
-rw-r--r--drivers/pci/host/pci-host-generic.c52
-rw-r--r--drivers/pci/host/pci-imx6.c12
-rw-r--r--drivers/pci/host/pci-keystone-dw.c23
-rw-r--r--drivers/pci/host/pci-keystone.c13
-rw-r--r--drivers/pci/host/pci-mvebu.c1
-rw-r--r--drivers/pci/host/pci-tegra.c1
-rw-r--r--drivers/pci/host/pci-xgene-msi.c57
-rw-r--r--drivers/pci/host/pci-xgene.c13
-rw-r--r--drivers/pci/host/pcie-designware.c21
-rw-r--r--drivers/pci/host/pcie-iproc.c60
-rw-r--r--drivers/pci/host/pcie-iproc.h4
-rw-r--r--drivers/pci/host/pcie-rcar.c1
-rw-r--r--drivers/pci/host/pcie-spear13xx.c3
-rw-r--r--drivers/pci/host/pcie-xilinx.c42
-rw-r--r--drivers/pci/hotplug/pci_hotplug_core.c122
-rw-r--r--drivers/pci/hotplug/pciehp.h14
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c48
-rw-r--r--drivers/pci/msi.c128
-rw-r--r--drivers/pci/of.c30
-rw-r--r--drivers/pci/pci-acpi.c2
-rw-r--r--drivers/pci/pci-driver.c26
-rw-r--r--drivers/pci/pci.c28
-rw-r--r--drivers/pci/pci.h2
-rw-r--r--drivers/pci/pcie/portdrv_core.c2
-rw-r--r--drivers/pci/probe.c146
-rw-r--r--drivers/pci/quirks.c211
-rw-r--r--drivers/pci/slot.c29
-rw-r--r--drivers/pci/xen-pcifront.c2
34 files changed, 937 insertions, 504 deletions
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 73de4efcbe6e..944f50015ed0 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -2,7 +2,7 @@
# PCI configuration
#
config PCI_BUS_ADDR_T_64BIT
- def_bool y if (ARCH_DMA_ADDR_T_64BIT || 64BIT)
+ def_bool y if (ARCH_DMA_ADDR_T_64BIT || (64BIT && !PARISC))
depends on PCI
config PCI_MSI
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 73e4af400a5a..be3f631c3f75 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_PCI_IOV) += iov.o
#
obj-$(CONFIG_ALPHA) += setup-irq.o
obj-$(CONFIG_ARM) += setup-irq.o
+obj-$(CONFIG_ARM64) += setup-irq.o
obj-$(CONFIG_UNICORE32) += setup-irq.o
obj-$(CONFIG_SUPERH) += setup-irq.o
obj-$(CONFIG_MIPS) += setup-irq.o
diff --git a/drivers/pci/access.c b/drivers/pci/access.c
index d9b64a175990..769f7e35f1a2 100644
--- a/drivers/pci/access.c
+++ b/drivers/pci/access.c
@@ -439,6 +439,56 @@ static const struct pci_vpd_ops pci_vpd_pci22_ops = {
.release = pci_vpd_pci22_release,
};
+static ssize_t pci_vpd_f0_read(struct pci_dev *dev, loff_t pos, size_t count,
+ void *arg)
+{
+ struct pci_dev *tdev = pci_get_slot(dev->bus, PCI_SLOT(dev->devfn));
+ ssize_t ret;
+
+ if (!tdev)
+ return -ENODEV;
+
+ ret = pci_read_vpd(tdev, pos, count, arg);
+ pci_dev_put(tdev);
+ return ret;
+}
+
+static ssize_t pci_vpd_f0_write(struct pci_dev *dev, loff_t pos, size_t count,
+ const void *arg)
+{
+ struct pci_dev *tdev = pci_get_slot(dev->bus, PCI_SLOT(dev->devfn));
+ ssize_t ret;
+
+ if (!tdev)
+ return -ENODEV;
+
+ ret = pci_write_vpd(tdev, pos, count, arg);
+ pci_dev_put(tdev);
+ return ret;
+}
+
+static const struct pci_vpd_ops pci_vpd_f0_ops = {
+ .read = pci_vpd_f0_read,
+ .write = pci_vpd_f0_write,
+ .release = pci_vpd_pci22_release,
+};
+
+static int pci_vpd_f0_dev_check(struct pci_dev *dev)
+{
+ struct pci_dev *tdev = pci_get_slot(dev->bus, PCI_SLOT(dev->devfn));
+ int ret = 0;
+
+ if (!tdev)
+ return -ENODEV;
+ if (!tdev->vpd || !tdev->multifunction ||
+ dev->class != tdev->class || dev->vendor != tdev->vendor ||
+ dev->device != tdev->device)
+ ret = -ENODEV;
+
+ pci_dev_put(tdev);
+ return ret;
+}
+
int pci_vpd_pci22_init(struct pci_dev *dev)
{
struct pci_vpd_pci22 *vpd;
@@ -447,12 +497,21 @@ int pci_vpd_pci22_init(struct pci_dev *dev)
cap = pci_find_capability(dev, PCI_CAP_ID_VPD);
if (!cap)
return -ENODEV;
+ if (dev->dev_flags & PCI_DEV_FLAGS_VPD_REF_F0) {
+ int ret = pci_vpd_f0_dev_check(dev);
+
+ if (ret)
+ return ret;
+ }
vpd = kzalloc(sizeof(*vpd), GFP_ATOMIC);
if (!vpd)
return -ENOMEM;
vpd->base.len = PCI_VPD_PCI22_SIZE;
- vpd->base.ops = &pci_vpd_pci22_ops;
+ if (dev->dev_flags & PCI_DEV_FLAGS_VPD_REF_F0)
+ vpd->base.ops = &pci_vpd_f0_ops;
+ else
+ vpd->base.ops = &pci_vpd_pci22_ops;
mutex_init(&vpd->lock);
vpd->cap = cap;
vpd->busy = false;
@@ -531,6 +590,14 @@ static inline int pcie_cap_version(const struct pci_dev *dev)
return pcie_caps_reg(dev) & PCI_EXP_FLAGS_VERS;
}
+static bool pcie_downstream_port(const struct pci_dev *dev)
+{
+ int type = pci_pcie_type(dev);
+
+ return type == PCI_EXP_TYPE_ROOT_PORT ||
+ type == PCI_EXP_TYPE_DOWNSTREAM;
+}
+
bool pcie_cap_has_lnkctl(const struct pci_dev *dev)
{
int type = pci_pcie_type(dev);
@@ -546,10 +613,7 @@ bool pcie_cap_has_lnkctl(const struct pci_dev *dev)
static inline bool pcie_cap_has_sltctl(const struct pci_dev *dev)
{
- int type = pci_pcie_type(dev);
-
- return (type == PCI_EXP_TYPE_ROOT_PORT ||
- type == PCI_EXP_TYPE_DOWNSTREAM) &&
+ return pcie_downstream_port(dev) &&
pcie_caps_reg(dev) & PCI_EXP_FLAGS_SLOT;
}
@@ -628,10 +692,9 @@ int pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *val)
* State bit in the Slot Status register of Downstream Ports,
* which must be hardwired to 1b. (PCIe Base Spec 3.0, sec 7.8)
*/
- if (pci_is_pcie(dev) && pos == PCI_EXP_SLTSTA &&
- pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) {
+ if (pci_is_pcie(dev) && pcie_downstream_port(dev) &&
+ pos == PCI_EXP_SLTSTA)
*val = PCI_EXP_SLTSTA_PDS;
- }
return 0;
}
@@ -657,10 +720,9 @@ int pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *val)
return ret;
}
- if (pci_is_pcie(dev) && pos == PCI_EXP_SLTCTL &&
- pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) {
+ if (pci_is_pcie(dev) && pcie_downstream_port(dev) &&
+ pos == PCI_EXP_SLTSTA)
*val = PCI_EXP_SLTSTA_PDS;
- }
return 0;
}
diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c
index a8099d4d0c9d..eeb9fb2b47aa 100644
--- a/drivers/pci/ats.c
+++ b/drivers/pci/ats.c
@@ -17,34 +17,15 @@
#include "pci.h"
-static int ats_alloc_one(struct pci_dev *dev, int ps)
+void pci_ats_init(struct pci_dev *dev)
{
int pos;
- u16 cap;
- struct pci_ats *ats;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS);
if (!pos)
- return -ENODEV;
-
- ats = kzalloc(sizeof(*ats), GFP_KERNEL);
- if (!ats)
- return -ENOMEM;
-
- ats->pos = pos;
- ats->stu = ps;
- pci_read_config_word(dev, pos + PCI_ATS_CAP, &cap);
- ats->qdep = PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) :
- PCI_ATS_MAX_QDEP;
- dev->ats = ats;
-
- return 0;
-}
+ return;
-static void ats_free_one(struct pci_dev *dev)
-{
- kfree(dev->ats);
- dev->ats = NULL;
+ dev->ats_cap = pos;
}
/**
@@ -56,43 +37,36 @@ static void ats_free_one(struct pci_dev *dev)
*/
int pci_enable_ats(struct pci_dev *dev, int ps)
{
- int rc;
u16 ctrl;
+ struct pci_dev *pdev;
- BUG_ON(dev->ats && dev->ats->is_enabled);
-
- if (ps < PCI_ATS_MIN_STU)
+ if (!dev->ats_cap)
return -EINVAL;
- if (dev->is_physfn || dev->is_virtfn) {
- struct pci_dev *pdev = dev->is_physfn ? dev : dev->physfn;
-
- mutex_lock(&pdev->sriov->lock);
- if (pdev->ats)
- rc = pdev->ats->stu == ps ? 0 : -EINVAL;
- else
- rc = ats_alloc_one(pdev, ps);
-
- if (!rc)
- pdev->ats->ref_cnt++;
- mutex_unlock(&pdev->sriov->lock);
- if (rc)
- return rc;
- }
+ if (WARN_ON(dev->ats_enabled))
+ return -EBUSY;
- if (!dev->is_physfn) {
- rc = ats_alloc_one(dev, ps);
- if (rc)
- return rc;
- }
+ if (ps < PCI_ATS_MIN_STU)
+ return -EINVAL;
+ /*
+ * Note that enabling ATS on a VF fails unless it's already enabled
+ * with the same STU on the PF.
+ */
ctrl = PCI_ATS_CTRL_ENABLE;
- if (!dev->is_virtfn)
- ctrl |= PCI_ATS_CTRL_STU(ps - PCI_ATS_MIN_STU);
- pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl);
-
- dev->ats->is_enabled = 1;
+ if (dev->is_virtfn) {
+ pdev = pci_physfn(dev);
+ if (pdev->ats_stu != ps)
+ return -EINVAL;
+
+ atomic_inc(&pdev->ats_ref_cnt); /* count enabled VFs */
+ } else {
+ dev->ats_stu = ps;
+ ctrl |= PCI_ATS_CTRL_STU(dev->ats_stu - PCI_ATS_MIN_STU);
+ }
+ pci_write_config_word(dev, dev->ats_cap + PCI_ATS_CTRL, ctrl);
+ dev->ats_enabled = 1;
return 0;
}
EXPORT_SYMBOL_GPL(pci_enable_ats);
@@ -103,28 +77,25 @@ EXPORT_SYMBOL_GPL(pci_enable_ats);
*/
void pci_disable_ats(struct pci_dev *dev)
{
+ struct pci_dev *pdev;
u16 ctrl;
- BUG_ON(!dev->ats || !dev->ats->is_enabled);
-
- pci_read_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, &ctrl);
- ctrl &= ~PCI_ATS_CTRL_ENABLE;
- pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl);
-
- dev->ats->is_enabled = 0;
+ if (WARN_ON(!dev->ats_enabled))
+ return;
- if (dev->is_physfn || dev->is_virtfn) {
- struct pci_dev *pdev = dev->is_physfn ? dev : dev->physfn;
+ if (atomic_read(&dev->ats_ref_cnt))
+ return; /* VFs still enabled */
- mutex_lock(&pdev->sriov->lock);
- pdev->ats->ref_cnt--;
- if (!pdev->ats->ref_cnt)
- ats_free_one(pdev);
- mutex_unlock(&pdev->sriov->lock);
+ if (dev->is_virtfn) {
+ pdev = pci_physfn(dev);
+ atomic_dec(&pdev->ats_ref_cnt);
}
- if (!dev->is_physfn)
- ats_free_one(dev);
+ pci_read_config_word(dev, dev->ats_cap + PCI_ATS_CTRL, &ctrl);
+ ctrl &= ~PCI_ATS_CTRL_ENABLE;
+ pci_write_config_word(dev, dev->ats_cap + PCI_ATS_CTRL, ctrl);
+
+ dev->ats_enabled = 0;
}
EXPORT_SYMBOL_GPL(pci_disable_ats);
@@ -132,16 +103,13 @@ void pci_restore_ats_state(struct pci_dev *dev)
{
u16 ctrl;
- if (!pci_ats_enabled(dev))
+ if (!dev->ats_enabled)
return;
- if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS))
- BUG();
ctrl = PCI_ATS_CTRL_ENABLE;
if (!dev->is_virtfn)
- ctrl |= PCI_ATS_CTRL_STU(dev->ats->stu - PCI_ATS_MIN_STU);
-
- pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl);
+ ctrl |= PCI_ATS_CTRL_STU(dev->ats_stu - PCI_ATS_MIN_STU);
+ pci_write_config_word(dev, dev->ats_cap + PCI_ATS_CTRL, ctrl);
}
EXPORT_SYMBOL_GPL(pci_restore_ats_state);
@@ -159,23 +127,16 @@ EXPORT_SYMBOL_GPL(pci_restore_ats_state);
*/
int pci_ats_queue_depth(struct pci_dev *dev)
{
- int pos;
u16 cap;
+ if (!dev->ats_cap)
+ return -EINVAL;
+
if (dev->is_virtfn)
return 0;
- if (dev->ats)
- return dev->ats->qdep;
-
- pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS);
- if (!pos)
- return -ENODEV;
-
- pci_read_config_word(dev, pos + PCI_ATS_CAP, &cap);
-
- return PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) :
- PCI_ATS_MAX_QDEP;
+ pci_read_config_word(dev, dev->ats_cap + PCI_ATS_CAP, &cap);
+ return PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) : PCI_ATS_MAX_QDEP;
}
EXPORT_SYMBOL_GPL(pci_ats_queue_depth);
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index c132bddc03f3..d5e58bae95cf 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -53,7 +53,7 @@ config PCI_RCAR_GEN2_PCIE
config PCI_HOST_GENERIC
bool "Generic PCI host controller"
- depends on ARM && OF
+ depends on (ARM || ARM64) && OF
help
Say Y here if you want to support a simple generic PCI host
controller, such as the one emulated by kvmtool.
@@ -117,7 +117,7 @@ config PCI_VERSATILE
config PCIE_IPROC
tristate "Broadcom iProc PCIe controller"
- depends on OF && ARM
+ depends on OF && (ARM || ARM64)
default n
help
This enables the iProc PCIe core controller support for Broadcom's
@@ -135,8 +135,8 @@ config PCIE_IPROC_PLATFORM
through the generic platform bus interface
config PCIE_IPROC_BCMA
- bool "Broadcom iProc PCIe BCMA bus driver"
- depends on ARCH_BCM_IPROC || (ARM && COMPILE_TEST)
+ tristate "Broadcom iProc PCIe BCMA bus driver"
+ depends on ARM && (ARCH_BCM_IPROC || COMPILE_TEST)
select PCIE_IPROC
select BCMA
select PCI_DOMAINS
diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c
index 80db09e47800..199e29a044cd 100644
--- a/drivers/pci/host/pci-dra7xx.c
+++ b/drivers/pci/host/pci-dra7xx.c
@@ -17,6 +17,7 @@
#include <linux/irqdomain.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/of_gpio.h>
#include <linux/pci.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
@@ -83,6 +84,17 @@ static inline void dra7xx_pcie_writel(struct dra7xx_pcie *pcie, u32 offset,
writel(value, pcie->base + offset);
}
+static inline u32 dra7xx_pcie_readl_rc(struct pcie_port *pp, u32 offset)
+{
+ return readl(pp->dbi_base + offset);
+}
+
+static inline void dra7xx_pcie_writel_rc(struct pcie_port *pp, u32 offset,
+ u32 value)
+{
+ writel(value, pp->dbi_base + offset);
+}
+
static int dra7xx_pcie_link_up(struct pcie_port *pp)
{
struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp);
@@ -155,7 +167,6 @@ static int dra7xx_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
{
irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
irq_set_chip_data(irq, domain->host_data);
- set_irq_flags(irq, IRQF_VALID);
return 0;
}
@@ -325,6 +336,9 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
char name[10];
+ int gpio_sel;
+ enum of_gpio_flags flags;
+ unsigned long gpio_flags;
dra7xx = devm_kzalloc(dev, sizeof(*dra7xx), GFP_KERNEL);
if (!dra7xx)
@@ -382,9 +396,25 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
pm_runtime_enable(dev);
ret = pm_runtime_get_sync(dev);
- if (IS_ERR_VALUE(ret)) {
+ if (ret < 0) {
dev_err(dev, "pm_runtime_get_sync failed\n");
- goto err_phy;
+ goto err_get_sync;
+ }
+
+ gpio_sel = of_get_gpio_flags(dev->of_node, 0, &flags);
+ if (gpio_is_valid(gpio_sel)) {
+ gpio_flags = (flags & OF_GPIO_ACTIVE_LOW) ?
+ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH;
+ ret = devm_gpio_request_one(dev, gpio_sel, gpio_flags,
+ "pcie_reset");
+ if (ret) {
+ dev_err(&pdev->dev, "gpio%d request failed, ret %d\n",
+ gpio_sel, ret);
+ goto err_gpio;
+ }
+ } else if (gpio_sel == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto err_gpio;
}
reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD);
@@ -395,12 +425,14 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
ret = dra7xx_add_pcie_port(dra7xx, pdev);
if (ret < 0)
- goto err_add_port;
+ goto err_gpio;
return 0;
-err_add_port:
+err_gpio:
pm_runtime_put(dev);
+
+err_get_sync:
pm_runtime_disable(dev);
err_phy:
@@ -431,6 +463,85 @@ static int __exit dra7xx_pcie_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+static int dra7xx_pcie_suspend(struct device *dev)
+{
+ struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev);
+ struct pcie_port *pp = &dra7xx->pp;
+ u32 val;
+
+ /* clear MSE */
+ val = dra7xx_pcie_readl_rc(pp, PCI_COMMAND);
+ val &= ~PCI_COMMAND_MEMORY;
+ dra7xx_pcie_writel_rc(pp, PCI_COMMAND, val);
+
+ return 0;
+}
+
+static int dra7xx_pcie_resume(struct device *dev)
+{
+ struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev);
+ struct pcie_port *pp = &dra7xx->pp;
+ u32 val;
+
+ /* set MSE */
+ val = dra7xx_pcie_readl_rc(pp, PCI_COMMAND);
+ val |= PCI_COMMAND_MEMORY;
+ dra7xx_pcie_writel_rc(pp, PCI_COMMAND, val);
+
+ return 0;
+}
+
+static int dra7xx_pcie_suspend_noirq(struct device *dev)
+{
+ struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev);
+ int count = dra7xx->phy_count;
+
+ while (count--) {
+ phy_power_off(dra7xx->phy[count]);
+ phy_exit(dra7xx->phy[count]);
+ }
+
+ return 0;
+}
+
+static int dra7xx_pcie_resume_noirq(struct device *dev)
+{
+ struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev);
+ int phy_count = dra7xx->phy_count;
+ int ret;
+ int i;
+
+ for (i = 0; i < phy_count; i++) {
+ ret = phy_init(dra7xx->phy[i]);
+ if (ret < 0)
+ goto err_phy;
+
+ ret = phy_power_on(dra7xx->phy[i]);
+ if (ret < 0) {
+ phy_exit(dra7xx->phy[i]);
+ goto err_phy;
+ }
+ }
+
+ return 0;
+
+err_phy:
+ while (--i >= 0) {
+ phy_power_off(dra7xx->phy[i]);
+ phy_exit(dra7xx->phy[i]);
+ }
+
+ return ret;
+}
+#endif
+
+static const struct dev_pm_ops dra7xx_pcie_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(dra7xx_pcie_suspend, dra7xx_pcie_resume)
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(dra7xx_pcie_suspend_noirq,
+ dra7xx_pcie_resume_noirq)
+};
+
static const struct of_device_id of_dra7xx_pcie_match[] = {
{ .compatible = "ti,dra7-pcie", },
{},
@@ -442,6 +553,7 @@ static struct platform_driver dra7xx_pcie_driver = {
.driver = {
.name = "dra7-pcie",
.of_match_table = of_dra7xx_pcie_match,
+ .pm = &dra7xx_pcie_pm_ops,
},
};
diff --git a/drivers/pci/host/pci-host-generic.c b/drivers/pci/host/pci-host-generic.c
index ba46e581db99..265dd25169bf 100644
--- a/drivers/pci/host/pci-host-generic.c
+++ b/drivers/pci/host/pci-host-generic.c
@@ -38,7 +38,16 @@ struct gen_pci_cfg_windows {
const 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;
@@ -48,8 +57,7 @@ static void __iomem *gen_pci_map_cfg_bus_cam(struct pci_bus *bus,
unsigned int devfn,
int where)
{
- struct pci_sys_data *sys = bus->sysdata;
- struct gen_pci *pci = sys->private_data;
+ struct gen_pci *pci = bus->sysdata;
resource_size_t idx = bus->number - pci->cfg.bus_range->start;
return pci->cfg.win[idx] + ((devfn << 8) | where);
@@ -64,8 +72,7 @@ static void __iomem *gen_pci_map_cfg_bus_ecam(struct pci_bus *bus,
unsigned int devfn,
int where)
{
- struct pci_sys_data *sys = bus->sysdata;
- struct gen_pci *pci = sys->private_data;
+ struct gen_pci *pci = bus->sysdata;
resource_size_t idx = bus->number - pci->cfg.bus_range->start;
return pci->cfg.win[idx] + ((devfn << 12) | where);
@@ -198,13 +205,6 @@ static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci)
return 0;
}
-static int gen_pci_setup(int nr, struct pci_sys_data *sys)
-{
- struct gen_pci *pci = sys->private_data;
- list_splice_init(&pci->resources, &sys->resources);
- return 1;
-}
-
static int gen_pci_probe(struct platform_device *pdev)
{
int err;
@@ -214,13 +214,7 @@ static int gen_pci_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct gen_pci *pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
- struct hw_pci hw = {
- .nr_controllers = 1,
- .private_data = (void **)&pci,
- .setup = gen_pci_setup,
- .map_irq = of_irq_parse_and_map_pci,
- .ops = &gen_pci_ops,
- };
+ struct pci_bus *bus, *child;
if (!pci)
return -ENOMEM;
@@ -258,7 +252,27 @@ static int gen_pci_probe(struct platform_device *pdev)
return err;
}
- pci_common_init_dev(dev, &hw);
+ /* Do not reassign resources if probe only */
+ if (!pci_has_flag(PCI_PROBE_ONLY))
+ pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS);
+
+ bus = pci_scan_root_bus(dev, 0, &gen_pci_ops, pci, &pci->resources);
+ if (!bus) {
+ dev_err(dev, "Scanning rootbus failed");
+ return -ENODEV;
+ }
+
+ pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+
+ if (!pci_has_flag(PCI_PROBE_ONLY)) {
+ pci_bus_size_bridges(bus);
+ pci_bus_assign_resources(bus);
+
+ list_for_each_entry(child, &bus->children, node)
+ pcie_bus_configure_settings(child);
+ }
+
+ pci_bus_add_devices(bus);
return 0;
}
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index 233a196c6e66..8f3a9813c4e5 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -117,11 +117,7 @@ static int pcie_phy_wait_ack(void __iomem *dbi_base, int addr)
val = addr << PCIE_PHY_CTRL_DATA_LOC;
writel(val, dbi_base + PCIE_PHY_CTRL);
- ret = pcie_phy_poll_ack(dbi_base, 0);
- if (ret)
- return ret;
-
- return 0;
+ return pcie_phy_poll_ack(dbi_base, 0);
}
/* Read from the 16-bit PCIe PHY control registers (not memory-mapped) */
@@ -148,11 +144,7 @@ static int pcie_phy_read(void __iomem *dbi_base, int addr , int *data)
/* deassert Read signal */
writel(0x00, dbi_base + PCIE_PHY_CTRL);
- ret = pcie_phy_poll_ack(dbi_base, 0);
- if (ret)
- return ret;
-
- return 0;
+ return pcie_phy_poll_ack(dbi_base, 0);
}
static int pcie_phy_write(void __iomem *dbi_base, int addr, int data)
diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/host/pci-keystone-dw.c
index f34892e0edb4..e71da991949b 100644
--- a/drivers/pci/host/pci-keystone-dw.c
+++ b/drivers/pci/host/pci-keystone-dw.c
@@ -104,14 +104,13 @@ static void ks_dw_pcie_msi_irq_ack(struct irq_data *d)
{
u32 offset, reg_offset, bit_pos;
struct keystone_pcie *ks_pcie;
- unsigned int irq = d->irq;
struct msi_desc *msi;
struct pcie_port *pp;
- msi = irq_get_msi_desc(irq);
- pp = sys_to_pcie(msi->dev->bus->sysdata);
+ msi = irq_data_get_msi_desc(d);
+ pp = sys_to_pcie(msi_desc_to_pci_sysdata(msi));
ks_pcie = to_keystone_pcie(pp);
- offset = irq - irq_linear_revmap(pp->irq_domain, 0);
+ offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
update_reg_offset_bit_pos(offset, &reg_offset, &bit_pos);
writel(BIT(bit_pos),
@@ -142,15 +141,14 @@ void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq)
static void ks_dw_pcie_msi_irq_mask(struct irq_data *d)
{
struct keystone_pcie *ks_pcie;
- unsigned int irq = d->irq;
struct msi_desc *msi;
struct pcie_port *pp;
u32 offset;
- msi = irq_get_msi_desc(irq);
- pp = sys_to_pcie(msi->dev->bus->sysdata);
+ msi = irq_data_get_msi_desc(d);
+ pp = sys_to_pcie(msi_desc_to_pci_sysdata(msi));
ks_pcie = to_keystone_pcie(pp);
- offset = irq - irq_linear_revmap(pp->irq_domain, 0);
+ offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
/* Mask the end point if PVM implemented */
if (IS_ENABLED(CONFIG_PCI_MSI)) {
@@ -164,15 +162,14 @@ static void ks_dw_pcie_msi_irq_mask(struct irq_data *d)
static void ks_dw_pcie_msi_irq_unmask(struct irq_data *d)
{
struct keystone_pcie *ks_pcie;
- unsigned int irq = d->irq;
struct msi_desc *msi;
struct pcie_port *pp;
u32 offset;
- msi = irq_get_msi_desc(irq);
- pp = sys_to_pcie(msi->dev->bus->sysdata);
+ msi = irq_data_get_msi_desc(d);
+ pp = sys_to_pcie(msi_desc_to_pci_sysdata(msi));
ks_pcie = to_keystone_pcie(pp);
- offset = irq - irq_linear_revmap(pp->irq_domain, 0);
+ offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
/* Mask the end point if PVM implemented */
if (IS_ENABLED(CONFIG_PCI_MSI)) {
@@ -196,7 +193,6 @@ static int ks_dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq,
irq_set_chip_and_handler(irq, &ks_dw_pcie_msi_irq_chip,
handle_level_irq);
irq_set_chip_data(irq, domain->host_data);
- set_irq_flags(irq, IRQF_VALID);
return 0;
}
@@ -277,7 +273,6 @@ static int ks_dw_pcie_init_legacy_irq_map(struct irq_domain *d,
irq_set_chip_and_handler(irq, &ks_dw_pcie_legacy_irq_chip,
handle_level_irq);
irq_set_chip_data(irq, d->host_data);
- set_irq_flags(irq, IRQF_VALID);
return 0;
}
diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c
index 734da589cdfb..81253e70b1c5 100644
--- a/drivers/pci/host/pci-keystone.c
+++ b/drivers/pci/host/pci-keystone.c
@@ -110,8 +110,9 @@ static int ks_pcie_establish_link(struct keystone_pcie *ks_pcie)
return -EINVAL;
}
-static void ks_pcie_msi_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void ks_pcie_msi_irq_handler(unsigned int __irq, struct irq_desc *desc)
{
+ unsigned int irq = irq_desc_get_irq(desc);
struct keystone_pcie *ks_pcie = irq_desc_get_handler_data(desc);
u32 offset = irq - ks_pcie->msi_host_irqs[0];
struct pcie_port *pp = &ks_pcie->pp;
@@ -137,8 +138,10 @@ static void ks_pcie_msi_irq_handler(unsigned int irq, struct irq_desc *desc)
* Traverse through pending legacy interrupts and invoke handler for each. Also
* takes care of interrupt controller level mask/ack operation.
*/
-static void ks_pcie_legacy_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void ks_pcie_legacy_irq_handler(unsigned int __irq,
+ struct irq_desc *desc)
{
+ unsigned int irq = irq_desc_get_irq(desc);
struct keystone_pcie *ks_pcie = irq_desc_get_handler_data(desc);
struct pcie_port *pp = &ks_pcie->pp;
u32 irq_offset = irq - ks_pcie->legacy_host_irqs[0];
@@ -212,9 +215,9 @@ static void ks_pcie_setup_interrupts(struct keystone_pcie *ks_pcie)
/* Legacy IRQ */
for (i = 0; i < ks_pcie->num_legacy_host_irqs; i++) {
- irq_set_handler_data(ks_pcie->legacy_host_irqs[i], ks_pcie);
- irq_set_chained_handler(ks_pcie->legacy_host_irqs[i],
- ks_pcie_legacy_irq_handler);
+ irq_set_chained_handler_and_data(ks_pcie->legacy_host_irqs[i],
+ ks_pcie_legacy_irq_handler,
+ ks_pcie);
}
ks_dw_pcie_enable_legacy_irqs(ks_pcie);
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index 70aa09556ec5..67ec5e1c99db 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -879,6 +879,7 @@ static void mvebu_pcie_msi_enable(struct mvebu_pcie *pcie)
return;
pcie->msi = of_pci_find_msi_chip_by_node(msi_node);
+ of_node_put(msi_node);
if (pcie->msi)
pcie->msi->dev = &pcie->pdev->dev;
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
index 10c05718dbfd..81df0c1fe063 100644
--- a/drivers/pci/host/pci-tegra.c
+++ b/drivers/pci/host/pci-tegra.c
@@ -1248,7 +1248,6 @@ static int tegra_msi_map(struct irq_domain *domain, unsigned int irq,
{
irq_set_chip_and_handler(irq, &tegra_msi_irq_chip, handle_simple_irq);
irq_set_chip_data(irq, domain->host_data);
- set_irq_flags(irq, IRQF_VALID);
tegra_cpuidle_pcie_irqs_in_use();
diff --git a/drivers/pci/host/pci-xgene-msi.c b/drivers/pci/host/pci-xgene-msi.c
index 2d31d4d6fd08..996327cfa1e1 100644
--- a/drivers/pci/host/pci-xgene-msi.c
+++ b/drivers/pci/host/pci-xgene-msi.c
@@ -40,8 +40,8 @@ struct xgene_msi_group {
struct xgene_msi {
struct device_node *node;
- struct msi_controller mchip;
- struct irq_domain *domain;
+ struct irq_domain *inner_domain;
+ struct irq_domain *msi_domain;
u64 msi_addr;
void __iomem *msi_regs;
unsigned long *bitmap;
@@ -223,7 +223,6 @@ static int xgene_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
irq_domain_set_info(domain, virq, msi_irq,
&xgene_msi_bottom_irq_chip, domain->host_data,
handle_simple_irq, NULL, NULL);
- set_irq_flags(virq, IRQF_VALID);
return 0;
}
@@ -252,17 +251,17 @@ static const struct irq_domain_ops msi_domain_ops = {
static int xgene_allocate_domains(struct xgene_msi *msi)
{
- msi->domain = irq_domain_add_linear(NULL, NR_MSI_VEC,
- &msi_domain_ops, msi);
- if (!msi->domain)
+ msi->inner_domain = irq_domain_add_linear(NULL, NR_MSI_VEC,
+ &msi_domain_ops, msi);
+ if (!msi->inner_domain)
return -ENOMEM;
- msi->mchip.domain = pci_msi_create_irq_domain(msi->mchip.of_node,
- &xgene_msi_domain_info,
- msi->domain);
+ msi->msi_domain = pci_msi_create_irq_domain(msi->node,
+ &xgene_msi_domain_info,
+ msi->inner_domain);
- if (!msi->mchip.domain) {
- irq_domain_remove(msi->domain);
+ if (!msi->msi_domain) {
+ irq_domain_remove(msi->inner_domain);
return -ENOMEM;
}
@@ -271,10 +270,10 @@ static int xgene_allocate_domains(struct xgene_msi *msi)
static void xgene_free_domains(struct xgene_msi *msi)
{
- if (msi->mchip.domain)
- irq_domain_remove(msi->mchip.domain);
- if (msi->domain)
- irq_domain_remove(msi->domain);
+ if (msi->msi_domain)
+ irq_domain_remove(msi->msi_domain);
+ if (msi->inner_domain)
+ irq_domain_remove(msi->inner_domain);
}
static int xgene_msi_init_allocator(struct xgene_msi *xgene_msi)
@@ -340,7 +339,7 @@ static void xgene_msi_isr(unsigned int irq, struct irq_desc *desc)
* CPU0
*/
hw_irq = hwirq_to_canonical_hwirq(hw_irq);
- virq = irq_find_mapping(xgene_msi->domain, hw_irq);
+ virq = irq_find_mapping(xgene_msi->inner_domain, hw_irq);
WARN_ON(!virq);
if (virq != 0)
generic_handle_irq(virq);
@@ -368,10 +367,8 @@ static int xgene_msi_remove(struct platform_device *pdev)
for (i = 0; i < NR_HW_IRQS; i++) {
virq = msi->msi_groups[i].gic_irq;
- if (virq != 0) {
- irq_set_chained_handler(virq, NULL);
- irq_set_handler_data(virq, NULL);
- }
+ if (virq != 0)
+ irq_set_chained_handler_and_data(virq, NULL, NULL);
}
kfree(msi->msi_groups);
@@ -421,8 +418,8 @@ static int xgene_msi_hwirq_alloc(unsigned int cpu)
}
if (err) {
- irq_set_chained_handler(msi_group->gic_irq, NULL);
- irq_set_handler_data(msi_group->gic_irq, NULL);
+ irq_set_chained_handler_and_data(msi_group->gic_irq,
+ NULL, NULL);
return err;
}
}
@@ -441,8 +438,8 @@ static void xgene_msi_hwirq_free(unsigned int cpu)
if (!msi_group->gic_irq)
continue;
- irq_set_chained_handler(msi_group->gic_irq, NULL);
- irq_set_handler_data(msi_group->gic_irq, NULL);
+ irq_set_chained_handler_and_data(msi_group->gic_irq, NULL,
+ NULL);
}
}
@@ -497,7 +494,7 @@ static int xgene_msi_probe(struct platform_device *pdev)
goto error;
}
xgene_msi->msi_addr = res->start;
-
+ xgene_msi->node = pdev->dev.of_node;
xgene_msi->num_cpus = num_possible_cpus();
rc = xgene_msi_init_allocator(xgene_msi);
@@ -561,19 +558,10 @@ static int xgene_msi_probe(struct platform_device *pdev)
cpu_notifier_register_done();
- xgene_msi->mchip.of_node = pdev->dev.of_node;
- rc = of_pci_msi_chip_add(&xgene_msi->mchip);
- if (rc) {
- dev_err(&pdev->dev, "failed to add MSI controller chip\n");
- goto error_notifier;
- }
-
dev_info(&pdev->dev, "APM X-Gene PCIe MSI driver loaded\n");
return 0;
-error_notifier:
- unregister_hotcpu_notifier(&xgene_msi_cpu_notifier);
error:
xgene_msi_remove(pdev);
return rc;
@@ -582,7 +570,6 @@ error:
static struct platform_driver xgene_msi_driver = {
.driver = {
.name = "xgene-msi",
- .owner = THIS_MODULE,
.of_match_table = xgene_msi_match_table,
},
.probe = xgene_msi_probe,
diff --git a/drivers/pci/host/pci-xgene.c b/drivers/pci/host/pci-xgene.c
index a9dfb70d623a..0236ab9d5720 100644
--- a/drivers/pci/host/pci-xgene.c
+++ b/drivers/pci/host/pci-xgene.c
@@ -321,8 +321,16 @@ static int xgene_pcie_map_ranges(struct xgene_pcie_port *port,
return ret;
break;
case IORESOURCE_MEM:
- xgene_pcie_setup_ob_reg(port, res, OMR1BARL, res->start,
- res->start - window->offset);
+ if (res->flags & IORESOURCE_PREFETCH)
+ xgene_pcie_setup_ob_reg(port, res, OMR2BARL,
+ res->start,
+ res->start -
+ window->offset);
+ else
+ xgene_pcie_setup_ob_reg(port, res, OMR1BARL,
+ res->start,
+ res->start -
+ window->offset);
break;
case IORESOURCE_BUS:
break;
@@ -514,6 +522,7 @@ static int xgene_pcie_msi_enable(struct pci_bus *bus)
if (!bus->msi)
return -ENODEV;
+ of_node_put(msi_node);
bus->msi->dev = &bus->dev;
return 0;
}
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 69486be7181e..52aa6e34002b 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -255,7 +255,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
{
int irq, pos0, i;
- struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
+ struct pcie_port *pp = sys_to_pcie(msi_desc_to_pci_sysdata(desc));
pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
order_base_2(no_irqs));
@@ -326,8 +326,8 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
{
struct irq_data *data = irq_get_irq_data(irq);
- struct msi_desc *msi = irq_data_get_msi(data);
- struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
+ struct msi_desc *msi = irq_data_get_msi_desc(data);
+ struct pcie_port *pp = sys_to_pcie(msi_desc_to_pci_sysdata(msi));
clear_irq_range(pp, irq, 1, data->hwirq);
}
@@ -350,7 +350,6 @@ static int dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq,
{
irq_set_chip_and_handler(irq, &dw_msi_irq_chip, handle_simple_irq);
irq_set_chip_data(irq, domain->host_data);
- set_irq_flags(irq, IRQF_VALID);
return 0;
}
@@ -388,7 +387,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
addrp = of_get_address(np, index, NULL, NULL);
pp->cfg0_mod_base = of_read_number(addrp, ns);
pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
- } else {
+ } else if (!pp->va_cfg0_base) {
dev_err(pp->dev, "missing *config* reg space\n");
}
@@ -526,7 +525,6 @@ int dw_pcie_host_init(struct pcie_port *pp)
#ifdef CONFIG_PCI_MSI
dw_pcie_msi_chip.dev = pp->dev;
- dw_pci.msi_ctrl = &dw_pcie_msi_chip;
#endif
dw_pci.nr_controllers = 1;
@@ -708,8 +706,15 @@ static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
struct pcie_port *pp = sys_to_pcie(sys);
pp->root_bus_nr = sys->busnr;
- bus = pci_scan_root_bus(pp->dev, sys->busnr,
- &dw_pcie_ops, sys, &sys->resources);
+
+ if (IS_ENABLED(CONFIG_PCI_MSI))
+ bus = pci_scan_root_bus_msi(pp->dev, sys->busnr, &dw_pcie_ops,
+ sys, &sys->resources,
+ &dw_pcie_msi_chip);
+ else
+ bus = pci_scan_root_bus(pp->dev, sys->busnr, &dw_pcie_ops,
+ sys, &sys->resources);
+
if (!bus)
return NULL;
diff --git a/drivers/pci/host/pcie-iproc.c b/drivers/pci/host/pcie-iproc.c
index d77481ea553e..fe2efb141a9b 100644
--- a/drivers/pci/host/pcie-iproc.c
+++ b/drivers/pci/host/pcie-iproc.c
@@ -58,9 +58,17 @@
#define SYS_RC_INTX_EN 0x330
#define SYS_RC_INTX_MASK 0xf
-static inline struct iproc_pcie *sys_to_pcie(struct pci_sys_data *sys)
+static inline struct iproc_pcie *iproc_data(struct pci_bus *bus)
{
- return sys->private_data;
+ struct iproc_pcie *pcie;
+#ifdef CONFIG_ARM
+ struct pci_sys_data *sys = bus->sysdata;
+
+ pcie = sys->private_data;
+#else
+ pcie = bus->sysdata;
+#endif
+ return pcie;
}
/**
@@ -71,8 +79,7 @@ static void __iomem *iproc_pcie_map_cfg_bus(struct pci_bus *bus,
unsigned int devfn,
int where)
{
- struct pci_sys_data *sys = bus->sysdata;
- struct iproc_pcie *pcie = sys_to_pcie(sys);
+ struct iproc_pcie *pcie = iproc_data(bus);
unsigned slot = PCI_SLOT(devfn);
unsigned fn = PCI_FUNC(devfn);
unsigned busno = bus->number;
@@ -186,32 +193,34 @@ static void iproc_pcie_enable(struct iproc_pcie *pcie)
int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res)
{
int ret;
+ void *sysdata;
struct pci_bus *bus;
if (!pcie || !pcie->dev || !pcie->base)
return -EINVAL;
- if (pcie->phy) {
- ret = phy_init(pcie->phy);
- if (ret) {
- dev_err(pcie->dev, "unable to initialize PCIe PHY\n");
- return ret;
- }
-
- ret = phy_power_on(pcie->phy);
- if (ret) {
- dev_err(pcie->dev, "unable to power on PCIe PHY\n");
- goto err_exit_phy;
- }
+ ret = phy_init(pcie->phy);
+ if (ret) {
+ dev_err(pcie->dev, "unable to initialize PCIe PHY\n");
+ return ret;
+ }
+ ret = phy_power_on(pcie->phy);
+ if (ret) {
+ dev_err(pcie->dev, "unable to power on PCIe PHY\n");
+ goto err_exit_phy;
}
iproc_pcie_reset(pcie);
+#ifdef CONFIG_ARM
pcie->sysdata.private_data = pcie;
+ sysdata = &pcie->sysdata;
+#else
+ sysdata = pcie;
+#endif
- bus = pci_create_root_bus(pcie->dev, 0, &iproc_pcie_ops,
- &pcie->sysdata, res);
+ bus = pci_create_root_bus(pcie->dev, 0, &iproc_pcie_ops, sysdata, res);
if (!bus) {
dev_err(pcie->dev, "unable to create PCI root bus\n");
ret = -ENOMEM;
@@ -229,7 +238,9 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res)
pci_scan_child_bus(bus);
pci_assign_unassigned_bus_resources(bus);
+#ifdef CONFIG_ARM
pci_fixup_irqs(pci_common_swizzle, pcie->map_irq);
+#endif
pci_bus_add_devices(bus);
return 0;
@@ -239,12 +250,9 @@ err_rm_root_bus:
pci_remove_root_bus(bus);
err_power_off_phy:
- if (pcie->phy)
- phy_power_off(pcie->phy);
+ phy_power_off(pcie->phy);
err_exit_phy:
- if (pcie->phy)
- phy_exit(pcie->phy);
-
+ phy_exit(pcie->phy);
return ret;
}
EXPORT_SYMBOL(iproc_pcie_setup);
@@ -254,10 +262,8 @@ int iproc_pcie_remove(struct iproc_pcie *pcie)
pci_stop_root_bus(pcie->root_bus);
pci_remove_root_bus(pcie->root_bus);
- if (pcie->phy) {
- phy_power_off(pcie->phy);
- phy_exit(pcie->phy);
- }
+ phy_power_off(pcie->phy);
+ phy_exit(pcie->phy);
return 0;
}
diff --git a/drivers/pci/host/pcie-iproc.h b/drivers/pci/host/pcie-iproc.h
index ba0a108309cc..c9e4c10a462e 100644
--- a/drivers/pci/host/pcie-iproc.h
+++ b/drivers/pci/host/pcie-iproc.h
@@ -21,7 +21,7 @@
* @dev: pointer to device data structure
* @base: PCIe host controller I/O register base
* @resources: linked list of all PCI resources
- * @sysdata: Per PCI controller data
+ * @sysdata: Per PCI controller data (ARM-specific)
* @root_bus: pointer to root bus
* @phy: optional PHY device that controls the Serdes
* @irqs: interrupt IDs
@@ -29,7 +29,9 @@
struct iproc_pcie {
struct device *dev;
void __iomem *base;
+#ifdef CONFIG_ARM
struct pci_sys_data sysdata;
+#endif
struct pci_bus *root_bus;
struct phy *phy;
int irqs[IPROC_PCIE_MAX_NUM_IRQS];
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
index c086210f2ffd..7678fe0820d7 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/host/pcie-rcar.c
@@ -664,7 +664,6 @@ static int rcar_msi_map(struct irq_domain *domain, unsigned int irq,
{
irq_set_chip_and_handler(irq, &rcar_msi_irq_chip, handle_simple_irq);
irq_set_chip_data(irq, domain->host_data);
- set_irq_flags(irq, IRQF_VALID);
return 0;
}
diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c
index c49fbdc0f6e4..98d2683181bc 100644
--- a/drivers/pci/host/pcie-spear13xx.c
+++ b/drivers/pci/host/pcie-spear13xx.c
@@ -223,8 +223,7 @@ static irqreturn_t spear13xx_pcie_irq_handler(int irq, void *arg)
status = readl(&app_reg->int_sts);
if (status & MSI_CTRL_INT) {
- if (!IS_ENABLED(CONFIG_PCI_MSI))
- BUG();
+ BUG_ON(!IS_ENABLED(CONFIG_PCI_MSI));
dw_handle_msi_irq(pp);
}
diff --git a/drivers/pci/host/pcie-xilinx.c b/drivers/pci/host/pcie-xilinx.c
index f1a06a091ccb..3c7a0d580b1e 100644
--- a/drivers/pci/host/pcie-xilinx.c
+++ b/drivers/pci/host/pcie-xilinx.c
@@ -227,18 +227,16 @@ static struct pci_ops xilinx_pcie_ops = {
*/
static void xilinx_pcie_destroy_msi(unsigned int irq)
{
- struct irq_desc *desc;
struct msi_desc *msi;
struct xilinx_pcie_port *port;
- desc = irq_to_desc(irq);
- msi = irq_desc_get_msi_desc(desc);
- port = sys_to_pcie(msi->dev->bus->sysdata);
-
- if (!test_bit(irq, msi_irq_in_use))
+ if (!test_bit(irq, msi_irq_in_use)) {
+ msi = irq_get_msi_desc(irq);
+ port = sys_to_pcie(msi_desc_to_pci_sysdata(msi));
dev_err(port->dev, "Trying to free unused MSI#%d\n", irq);
- else
+ } else {
clear_bit(irq, msi_irq_in_use);
+ }
}
/**
@@ -338,7 +336,6 @@ static int xilinx_pcie_msi_map(struct irq_domain *domain, unsigned int irq,
{
irq_set_chip_and_handler(irq, &xilinx_msi_irq_chip, handle_simple_irq);
irq_set_chip_data(irq, domain->host_data);
- set_irq_flags(irq, IRQF_VALID);
return 0;
}
@@ -377,7 +374,6 @@ static int xilinx_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
{
irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
irq_set_chip_data(irq, domain->host_data);
- set_irq_flags(irq, IRQF_VALID);
return 0;
}
@@ -449,14 +445,17 @@ static irqreturn_t xilinx_pcie_intr_handler(int irq, void *data)
return IRQ_HANDLED;
}
- /* Clear interrupt FIFO register 1 */
- pcie_write(port, XILINX_PCIE_RPIFR1_ALL_MASK,
- XILINX_PCIE_REG_RPIFR1);
+ if (!(val & XILINX_PCIE_RPIFR1_MSI_INTR)) {
+ /* Clear interrupt FIFO register 1 */
+ pcie_write(port, XILINX_PCIE_RPIFR1_ALL_MASK,
+ XILINX_PCIE_REG_RPIFR1);
- /* Handle INTx Interrupt */
- val = ((val & XILINX_PCIE_RPIFR1_INTR_MASK) >>
- XILINX_PCIE_RPIFR1_INTR_SHIFT) + 1;
- generic_handle_irq(irq_find_mapping(port->irq_domain, val));
+ /* Handle INTx Interrupt */
+ val = ((val & XILINX_PCIE_RPIFR1_INTR_MASK) >>
+ XILINX_PCIE_RPIFR1_INTR_SHIFT) + 1;
+ generic_handle_irq(irq_find_mapping(port->irq_domain,
+ val));
+ }
}
if (status & XILINX_PCIE_INTR_MSI) {
@@ -647,9 +646,15 @@ static struct pci_bus *xilinx_pcie_scan_bus(int nr, struct pci_sys_data *sys)
struct pci_bus *bus;
port->root_busno = sys->busnr;
- bus = pci_scan_root_bus(port->dev, sys->busnr, &xilinx_pcie_ops,
- sys, &sys->resources);
+ if (IS_ENABLED(CONFIG_PCI_MSI))
+ bus = pci_scan_root_bus_msi(port->dev, sys->busnr,
+ &xilinx_pcie_ops, sys,
+ &sys->resources,
+ &xilinx_pcie_msi_chip);
+ else
+ bus = pci_scan_root_bus(port->dev, sys->busnr,
+ &xilinx_pcie_ops, sys, &sys->resources);
return bus;
}
@@ -847,7 +852,6 @@ static int xilinx_pcie_probe(struct platform_device *pdev)
#ifdef CONFIG_PCI_MSI
xilinx_pcie_msi_chip.dev = port->dev;
- hw.msi_ctrl = &xilinx_pcie_msi_chip;
#endif
pci_common_init_dev(dev, &hw);
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
index 56d8486dc167..d1fab97d6b01 100644
--- a/drivers/pci/hotplug/pci_hotplug_core.c
+++ b/drivers/pci/hotplug/pci_hotplug_core.c
@@ -83,12 +83,12 @@ GET_STATUS(attention_status, u8)
GET_STATUS(latch_status, u8)
GET_STATUS(adapter_status, u8)
-static ssize_t power_read_file(struct pci_slot *slot, char *buf)
+static ssize_t power_read_file(struct pci_slot *pci_slot, char *buf)
{
int retval;
u8 value;
- retval = get_power_status(slot->hotplug, &value);
+ retval = get_power_status(pci_slot->hotplug, &value);
if (retval)
return retval;
@@ -140,22 +140,22 @@ static struct pci_slot_attribute hotplug_slot_attr_power = {
.store = power_write_file
};
-static ssize_t attention_read_file(struct pci_slot *slot, char *buf)
+static ssize_t attention_read_file(struct pci_slot *pci_slot, char *buf)
{
int retval;
u8 value;
- retval = get_attention_status(slot->hotplug, &value);
+ retval = get_attention_status(pci_slot->hotplug, &value);
if (retval)
return retval;
return sprintf(buf, "%d\n", value);
}
-static ssize_t attention_write_file(struct pci_slot *slot, const char *buf,
+static ssize_t attention_write_file(struct pci_slot *pci_slot, const char *buf,
size_t count)
{
- struct hotplug_slot_ops *ops = slot->hotplug->ops;
+ struct hotplug_slot_ops *ops = pci_slot->hotplug->ops;
unsigned long lattention;
u8 attention;
int retval = 0;
@@ -169,7 +169,7 @@ static ssize_t attention_write_file(struct pci_slot *slot, const char *buf,
goto exit;
}
if (ops->set_attention_status)
- retval = ops->set_attention_status(slot->hotplug, attention);
+ retval = ops->set_attention_status(pci_slot->hotplug, attention);
module_put(ops->owner);
exit:
@@ -184,12 +184,12 @@ static struct pci_slot_attribute hotplug_slot_attr_attention = {
.store = attention_write_file
};
-static ssize_t latch_read_file(struct pci_slot *slot, char *buf)
+static ssize_t latch_read_file(struct pci_slot *pci_slot, char *buf)
{
int retval;
u8 value;
- retval = get_latch_status(slot->hotplug, &value);
+ retval = get_latch_status(pci_slot->hotplug, &value);
if (retval)
return retval;
@@ -201,12 +201,12 @@ static struct pci_slot_attribute hotplug_slot_attr_latch = {
.show = latch_read_file,
};
-static ssize_t presence_read_file(struct pci_slot *slot, char *buf)
+static ssize_t presence_read_file(struct pci_slot *pci_slot, char *buf)
{
int retval;
u8 value;
- retval = get_adapter_status(slot->hotplug, &value);
+ retval = get_adapter_status(pci_slot->hotplug, &value);
if (retval)
return retval;
@@ -307,43 +307,43 @@ static bool has_test_file(struct pci_slot *pci_slot)
return false;
}
-static int fs_add_slot(struct pci_slot *slot)
+static int fs_add_slot(struct pci_slot *pci_slot)
{
int retval = 0;
/* Create symbolic link to the hotplug driver module */
- pci_hp_create_module_link(slot);
+ pci_hp_create_module_link(pci_slot);
- if (has_power_file(slot)) {
- retval = sysfs_create_file(&slot->kobj,
+ if (has_power_file(pci_slot)) {
+ retval = sysfs_create_file(&pci_slot->kobj,
&hotplug_slot_attr_power.attr);
if (retval)
goto exit_power;
}
- if (has_attention_file(slot)) {
- retval = sysfs_create_file(&slot->kobj,
+ if (has_attention_file(pci_slot)) {
+ retval = sysfs_create_file(&pci_slot->kobj,
&hotplug_slot_attr_attention.attr);
if (retval)
goto exit_attention;
}
- if (has_latch_file(slot)) {
- retval = sysfs_create_file(&slot->kobj,
+ if (has_latch_file(pci_slot)) {
+ retval = sysfs_create_file(&pci_slot->kobj,
&hotplug_slot_attr_latch.attr);
if (retval)
goto exit_latch;
}
- if (has_adapter_file(slot)) {
- retval = sysfs_create_file(&slot->kobj,
+ if (has_adapter_file(pci_slot)) {
+ retval = sysfs_create_file(&pci_slot->kobj,
&hotplug_slot_attr_presence.attr);
if (retval)
goto exit_adapter;
}
- if (has_test_file(slot)) {
- retval = sysfs_create_file(&slot->kobj,
+ if (has_test_file(pci_slot)) {
+ retval = sysfs_create_file(&pci_slot->kobj,
&hotplug_slot_attr_test.attr);
if (retval)
goto exit_test;
@@ -352,45 +352,45 @@ static int fs_add_slot(struct pci_slot *slot)
goto exit;
exit_test:
- if (has_adapter_file(slot))
- sysfs_remove_file(&slot->kobj,
+ if (has_adapter_file(pci_slot))
+ sysfs_remove_file(&pci_slot->kobj,
&hotplug_slot_attr_presence.attr);
exit_adapter:
- if (has_latch_file(slot))
- sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_latch.attr);
+ if (has_latch_file(pci_slot))
+ sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_latch.attr);
exit_latch:
- if (has_attention_file(slot))
- sysfs_remove_file(&slot->kobj,
+ if (has_attention_file(pci_slot))
+ sysfs_remove_file(&pci_slot->kobj,
&hotplug_slot_attr_attention.attr);
exit_attention:
- if (has_power_file(slot))
- sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_power.attr);
+ if (has_power_file(pci_slot))
+ sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_power.attr);
exit_power:
- pci_hp_remove_module_link(slot);
+ pci_hp_remove_module_link(pci_slot);
exit:
return retval;
}
-static void fs_remove_slot(struct pci_slot *slot)
+static void fs_remove_slot(struct pci_slot *pci_slot)
{
- if (has_power_file(slot))
- sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_power.attr);
+ if (has_power_file(pci_slot))
+ sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_power.attr);
- if (has_attention_file(slot))
- sysfs_remove_file(&slot->kobj,
+ if (has_attention_file(pci_slot))
+ sysfs_remove_file(&pci_slot->kobj,
&hotplug_slot_attr_attention.attr);
- if (has_latch_file(slot))
- sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_latch.attr);
+ if (has_latch_file(pci_slot))
+ sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_latch.attr);
- if (has_adapter_file(slot))
- sysfs_remove_file(&slot->kobj,
+ if (has_adapter_file(pci_slot))
+ sysfs_remove_file(&pci_slot->kobj,
&hotplug_slot_attr_presence.attr);
- if (has_test_file(slot))
- sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_test.attr);
+ if (has_test_file(pci_slot))
+ sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_test.attr);
- pci_hp_remove_module_link(slot);
+ pci_hp_remove_module_link(pci_slot);
}
static struct hotplug_slot *get_slot_from_name(const char *name)
@@ -467,37 +467,37 @@ EXPORT_SYMBOL_GPL(__pci_hp_register);
/**
* pci_hp_deregister - deregister a hotplug_slot with the PCI hotplug subsystem
- * @hotplug: pointer to the &struct hotplug_slot to deregister
+ * @slot: pointer to the &struct hotplug_slot to deregister
*
* The @slot must have been registered with the pci hotplug subsystem
* previously with a call to pci_hp_register().
*
* Returns 0 if successful, anything else for an error.
*/
-int pci_hp_deregister(struct hotplug_slot *hotplug)
+int pci_hp_deregister(struct hotplug_slot *slot)
{
struct hotplug_slot *temp;
- struct pci_slot *slot;
+ struct pci_slot *pci_slot;
- if (!hotplug)
+ if (!slot)
return -ENODEV;
mutex_lock(&pci_hp_mutex);
- temp = get_slot_from_name(hotplug_slot_name(hotplug));
- if (temp != hotplug) {
+ temp = get_slot_from_name(hotplug_slot_name(slot));
+ if (temp != slot) {
mutex_unlock(&pci_hp_mutex);
return -ENODEV;
}
- list_del(&hotplug->slot_list);
+ list_del(&slot->slot_list);
- slot = hotplug->pci_slot;
- fs_remove_slot(slot);
- dbg("Removed slot %s from the list\n", hotplug_slot_name(hotplug));
+ pci_slot = slot->pci_slot;
+ fs_remove_slot(pci_slot);
+ dbg("Removed slot %s from the list\n", hotplug_slot_name(slot));
- hotplug->release(hotplug);
- slot->hotplug = NULL;
- pci_destroy_slot(slot);
+ slot->release(slot);
+ pci_slot->hotplug = NULL;
+ pci_destroy_slot(pci_slot);
mutex_unlock(&pci_hp_mutex);
return 0;
@@ -506,7 +506,7 @@ EXPORT_SYMBOL_GPL(pci_hp_deregister);
/**
* pci_hp_change_slot_info - changes the slot's information structure in the core
- * @hotplug: pointer to the slot whose info has changed
+ * @slot: pointer to the slot whose info has changed
* @info: pointer to the info copy into the slot's info structure
*
* @slot must have been registered with the pci
@@ -514,13 +514,13 @@ EXPORT_SYMBOL_GPL(pci_hp_deregister);
*
* Returns 0 if successful, anything else for an error.
*/
-int pci_hp_change_slot_info(struct hotplug_slot *hotplug,
+int pci_hp_change_slot_info(struct hotplug_slot *slot,
struct hotplug_slot_info *info)
{
- if (!hotplug || !info)
+ if (!slot || !info)
return -ENODEV;
- memcpy(hotplug->info, info, sizeof(struct hotplug_slot_info));
+ memcpy(slot->info, info, sizeof(struct hotplug_slot_info));
return 0;
}
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 57cd1327346f..62d6fe6c3714 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -101,18 +101,12 @@ struct controller {
unsigned int power_fault_detected;
};
-#define INT_BUTTON_IGNORE 0
#define INT_PRESENCE_ON 1
#define INT_PRESENCE_OFF 2
-#define INT_SWITCH_CLOSE 3
-#define INT_SWITCH_OPEN 4
-#define INT_POWER_FAULT 5
-#define INT_POWER_FAULT_CLEAR 6
-#define INT_BUTTON_PRESS 7
-#define INT_BUTTON_RELEASE 8
-#define INT_BUTTON_CANCEL 9
-#define INT_LINK_UP 10
-#define INT_LINK_DOWN 11
+#define INT_POWER_FAULT 3
+#define INT_BUTTON_PRESS 4
+#define INT_LINK_UP 5
+#define INT_LINK_DOWN 6
#define STATIC_STATE 0
#define BLINKINGON_STATE 1
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 2913f7e68a10..5c24e938042f 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -109,21 +109,23 @@ static int pcie_poll_cmd(struct controller *ctrl, int timeout)
struct pci_dev *pdev = ctrl_dev(ctrl);
u16 slot_status;
- pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);
- if (slot_status & PCI_EXP_SLTSTA_CC) {
- pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
- PCI_EXP_SLTSTA_CC);
- return 1;
- }
- while (timeout > 0) {
- msleep(10);
- timeout -= 10;
+ while (true) {
pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);
+ if (slot_status == (u16) ~0) {
+ ctrl_info(ctrl, "%s: no response from device\n",
+ __func__);
+ return 0;
+ }
+
if (slot_status & PCI_EXP_SLTSTA_CC) {
pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
PCI_EXP_SLTSTA_CC);
return 1;
}
+ if (timeout < 0)
+ break;
+ msleep(10);
+ timeout -= 10;
}
return 0; /* timeout */
}
@@ -190,6 +192,11 @@ static void pcie_do_write_cmd(struct controller *ctrl, u16 cmd,
pcie_wait_cmd(ctrl);
pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl);
+ if (slot_ctrl == (u16) ~0) {
+ ctrl_info(ctrl, "%s: no response from device\n", __func__);
+ goto out;
+ }
+
slot_ctrl &= ~mask;
slot_ctrl |= (cmd & mask);
ctrl->cmd_busy = 1;
@@ -205,6 +212,7 @@ static void pcie_do_write_cmd(struct controller *ctrl, u16 cmd,
if (wait)
pcie_wait_cmd(ctrl);
+out:
mutex_unlock(&ctrl->ctrl_lock);
}
@@ -535,7 +543,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
struct pci_dev *dev;
struct slot *slot = ctrl->slot;
u16 detected, intr_loc;
- u8 open, present;
+ u8 present;
bool link;
/*
@@ -546,9 +554,14 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
intr_loc = 0;
do {
pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &detected);
+ if (detected == (u16) ~0) {
+ ctrl_info(ctrl, "%s: no response from device\n",
+ __func__);
+ return IRQ_HANDLED;
+ }
detected &= (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD |
- PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC |
+ PCI_EXP_SLTSTA_PDC |
PCI_EXP_SLTSTA_CC | PCI_EXP_SLTSTA_DLLSC);
detected &= ~intr_loc;
intr_loc |= detected;
@@ -581,15 +594,6 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
if (!(intr_loc & ~PCI_EXP_SLTSTA_CC))
return IRQ_HANDLED;
- /* Check MRL Sensor Changed */
- if (intr_loc & PCI_EXP_SLTSTA_MRLSC) {
- pciehp_get_latch_status(slot, &open);
- ctrl_info(ctrl, "Latch %s on Slot(%s)\n",
- open ? "open" : "close", slot_name(slot));
- pciehp_queue_interrupt_event(slot, open ? INT_SWITCH_OPEN :
- INT_SWITCH_CLOSE);
- }
-
/* Check Attention Button Pressed */
if (intr_loc & PCI_EXP_SLTSTA_ABP) {
ctrl_info(ctrl, "Button pressed on Slot(%s)\n",
@@ -649,13 +653,11 @@ void pcie_enable_notification(struct controller *ctrl)
cmd |= PCI_EXP_SLTCTL_ABPE;
else
cmd |= PCI_EXP_SLTCTL_PDCE;
- if (MRL_SENS(ctrl))
- cmd |= PCI_EXP_SLTCTL_MRLSCE;
if (!pciehp_poll_mode)
cmd |= PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE;
mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE |
- PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE |
+ PCI_EXP_SLTCTL_PFDE |
PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE |
PCI_EXP_SLTCTL_DLLSCE);
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index f66be868ad21..d4497141d083 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -39,14 +39,13 @@ struct irq_domain * __weak arch_get_pci_msi_domain(struct pci_dev *dev)
static struct irq_domain *pci_msi_get_domain(struct pci_dev *dev)
{
- struct irq_domain *domain = NULL;
+ struct irq_domain *domain;
- if (dev->bus->msi)
- domain = dev->bus->msi->domain;
- if (!domain)
- domain = arch_get_pci_msi_domain(dev);
+ domain = dev_get_msi_domain(&dev->dev);
+ if (domain)
+ return domain;
- return domain;
+ return arch_get_pci_msi_domain(dev);
}
static int pci_msi_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
@@ -77,24 +76,9 @@ static void pci_msi_teardown_msi_irqs(struct pci_dev *dev)
/* Arch hooks */
-struct msi_controller * __weak pcibios_msi_controller(struct pci_dev *dev)
-{
- return NULL;
-}
-
-static struct msi_controller *pci_msi_controller(struct pci_dev *dev)
-{
- struct msi_controller *msi_ctrl = dev->bus->msi;
-
- if (msi_ctrl)
- return msi_ctrl;
-
- return pcibios_msi_controller(dev);
-}
-
int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
{
- struct msi_controller *chip = pci_msi_controller(dev);
+ struct msi_controller *chip = dev->bus->msi;
int err;
if (!chip || !chip->setup_irq)
@@ -131,7 +115,7 @@ int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
if (type == PCI_CAP_ID_MSI && nvec > 1)
return 1;
- list_for_each_entry(entry, &dev->msi_list, list) {
+ for_each_pci_msi_entry(entry, dev) {
ret = arch_setup_msi_irq(dev, entry);
if (ret < 0)
return ret;
@@ -151,7 +135,7 @@ void default_teardown_msi_irqs(struct pci_dev *dev)
int i;
struct msi_desc *entry;
- list_for_each_entry(entry, &dev->msi_list, list)
+ for_each_pci_msi_entry(entry, dev)
if (entry->irq)
for (i = 0; i < entry->nvec_used; i++)
arch_teardown_msi_irq(entry->irq + i);
@@ -168,7 +152,7 @@ static void default_restore_msi_irq(struct pci_dev *dev, int irq)
entry = NULL;
if (dev->msix_enabled) {
- list_for_each_entry(entry, &dev->msi_list, list) {
+ for_each_pci_msi_entry(entry, dev) {
if (irq == entry->irq)
break;
}
@@ -208,7 +192,8 @@ u32 __pci_msi_desc_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
mask_bits &= ~mask;
mask_bits |= flag;
- pci_write_config_dword(desc->dev, desc->mask_pos, mask_bits);
+ pci_write_config_dword(msi_desc_to_pci_dev(desc), desc->mask_pos,
+ mask_bits);
return mask_bits;
}
@@ -249,7 +234,7 @@ static void msix_mask_irq(struct msi_desc *desc, u32 flag)
static void msi_set_mask_bit(struct irq_data *data, u32 flag)
{
- struct msi_desc *desc = irq_data_get_msi(data);
+ struct msi_desc *desc = irq_data_get_msi_desc(data);
if (desc->msi_attrib.is_msix) {
msix_mask_irq(desc, flag);
@@ -282,13 +267,15 @@ void default_restore_msi_irqs(struct pci_dev *dev)
{
struct msi_desc *entry;
- list_for_each_entry(entry, &dev->msi_list, list)
+ for_each_pci_msi_entry(entry, dev)
default_restore_msi_irq(dev, entry->irq);
}
void __pci_read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
{
- BUG_ON(entry->dev->current_state != PCI_D0);
+ struct pci_dev *dev = msi_desc_to_pci_dev(entry);
+
+ BUG_ON(dev->current_state != PCI_D0);
if (entry->msi_attrib.is_msix) {
void __iomem *base = entry->mask_base +
@@ -298,7 +285,6 @@ void __pci_read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR);
msg->data = readl(base + PCI_MSIX_ENTRY_DATA);
} else {
- struct pci_dev *dev = entry->dev;
int pos = dev->msi_cap;
u16 data;
@@ -318,7 +304,9 @@ void __pci_read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
{
- if (entry->dev->current_state != PCI_D0) {
+ struct pci_dev *dev = msi_desc_to_pci_dev(entry);
+
+ if (dev->current_state != PCI_D0) {
/* Don't touch the hardware now */
} else if (entry->msi_attrib.is_msix) {
void __iomem *base;
@@ -329,7 +317,6 @@ void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
writel(msg->address_hi, base + PCI_MSIX_ENTRY_UPPER_ADDR);
writel(msg->data, base + PCI_MSIX_ENTRY_DATA);
} else {
- struct pci_dev *dev = entry->dev;
int pos = dev->msi_cap;
u16 msgctl;
@@ -363,21 +350,22 @@ EXPORT_SYMBOL_GPL(pci_write_msi_msg);
static void free_msi_irqs(struct pci_dev *dev)
{
+ struct list_head *msi_list = dev_to_msi_list(&dev->dev);
struct msi_desc *entry, *tmp;
struct attribute **msi_attrs;
struct device_attribute *dev_attr;
int i, count = 0;
- list_for_each_entry(entry, &dev->msi_list, list)
+ for_each_pci_msi_entry(entry, dev)
if (entry->irq)
for (i = 0; i < entry->nvec_used; i++)
BUG_ON(irq_has_action(entry->irq + i));
pci_msi_teardown_msi_irqs(dev);
- list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) {
+ list_for_each_entry_safe(entry, tmp, msi_list, list) {
if (entry->msi_attrib.is_msix) {
- if (list_is_last(&entry->list, &dev->msi_list))
+ if (list_is_last(&entry->list, msi_list))
iounmap(entry->mask_base);
}
@@ -402,18 +390,6 @@ static void free_msi_irqs(struct pci_dev *dev)
}
}
-static struct msi_desc *alloc_msi_entry(struct pci_dev *dev)
-{
- struct msi_desc *desc = kzalloc(sizeof(*desc), GFP_KERNEL);
- if (!desc)
- return NULL;
-
- INIT_LIST_HEAD(&desc->list);
- desc->dev = dev;
-
- return desc;
-}
-
static void pci_intx_for_msi(struct pci_dev *dev, int enable)
{
if (!(dev->dev_flags & PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG))
@@ -448,7 +424,7 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
if (!dev->msix_enabled)
return;
- BUG_ON(list_empty(&dev->msi_list));
+ BUG_ON(list_empty(dev_to_msi_list(&dev->dev)));
/* route the table */
pci_intx_for_msi(dev, 0);
@@ -456,7 +432,7 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
PCI_MSIX_FLAGS_ENABLE | PCI_MSIX_FLAGS_MASKALL);
arch_restore_msi_irqs(dev);
- list_for_each_entry(entry, &dev->msi_list, list)
+ for_each_pci_msi_entry(entry, dev)
msix_mask_irq(entry, entry->masked);
pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0);
@@ -501,7 +477,7 @@ static int populate_msi_sysfs(struct pci_dev *pdev)
int count = 0;
/* Determine how many msi entries we have */
- list_for_each_entry(entry, &pdev->msi_list, list)
+ for_each_pci_msi_entry(entry, pdev)
++num_msi;
if (!num_msi)
return 0;
@@ -510,7 +486,7 @@ static int populate_msi_sysfs(struct pci_dev *pdev)
msi_attrs = kzalloc(sizeof(void *) * (num_msi + 1), GFP_KERNEL);
if (!msi_attrs)
return -ENOMEM;
- list_for_each_entry(entry, &pdev->msi_list, list) {
+ for_each_pci_msi_entry(entry, pdev) {
msi_dev_attr = kzalloc(sizeof(*msi_dev_attr), GFP_KERNEL);
if (!msi_dev_attr)
goto error_attrs;
@@ -568,7 +544,7 @@ static struct msi_desc *msi_setup_entry(struct pci_dev *dev, int nvec)
struct msi_desc *entry;
/* MSI Entry Initialization */
- entry = alloc_msi_entry(dev);
+ entry = alloc_msi_entry(&dev->dev);
if (!entry)
return NULL;
@@ -599,7 +575,7 @@ static int msi_verify_entries(struct pci_dev *dev)
{
struct msi_desc *entry;
- list_for_each_entry(entry, &dev->msi_list, list) {
+ for_each_pci_msi_entry(entry, dev) {
if (!dev->no_64bit_msi || !entry->msg.address_hi)
continue;
dev_err(&dev->dev, "Device has broken 64-bit MSI but arch"
@@ -636,7 +612,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
mask = msi_mask(entry->msi_attrib.multi_cap);
msi_mask_irq(entry, mask, mask);
- list_add_tail(&entry->list, &dev->msi_list);
+ list_add_tail(&entry->list, dev_to_msi_list(&dev->dev));
/* Configure MSI capability structure */
ret = pci_msi_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSI);
@@ -665,6 +641,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
pci_msi_set_enable(dev, 1);
dev->msi_enabled = 1;
+ pcibios_free_irq(dev);
dev->irq = entry->irq;
return 0;
}
@@ -696,7 +673,7 @@ static int msix_setup_entries(struct pci_dev *dev, void __iomem *base,
int i;
for (i = 0; i < nvec; i++) {
- entry = alloc_msi_entry(dev);
+ entry = alloc_msi_entry(&dev->dev);
if (!entry) {
if (!i)
iounmap(base);
@@ -713,7 +690,7 @@ static int msix_setup_entries(struct pci_dev *dev, void __iomem *base,
entry->mask_base = base;
entry->nvec_used = 1;
- list_add_tail(&entry->list, &dev->msi_list);
+ list_add_tail(&entry->list, dev_to_msi_list(&dev->dev));
}
return 0;
@@ -725,7 +702,7 @@ static void msix_program_entries(struct pci_dev *dev,
struct msi_desc *entry;
int i = 0;
- list_for_each_entry(entry, &dev->msi_list, list) {
+ for_each_pci_msi_entry(entry, dev) {
int offset = entries[i].entry * PCI_MSIX_ENTRY_SIZE +
PCI_MSIX_ENTRY_VECTOR_CTRL;
@@ -792,9 +769,9 @@ static int msix_capability_init(struct pci_dev *dev,
/* Set MSI-X enabled bits and unmask the function */
pci_intx_for_msi(dev, 0);
dev->msix_enabled = 1;
-
pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0);
+ pcibios_free_irq(dev);
return 0;
out_avail:
@@ -806,7 +783,7 @@ out_avail:
struct msi_desc *entry;
int avail = 0;
- list_for_each_entry(entry, &dev->msi_list, list) {
+ for_each_pci_msi_entry(entry, dev) {
if (entry->irq != 0)
avail++;
}
@@ -895,8 +872,8 @@ void pci_msi_shutdown(struct pci_dev *dev)
if (!pci_msi_enable || !dev || !dev->msi_enabled)
return;
- BUG_ON(list_empty(&dev->msi_list));
- desc = list_first_entry(&dev->msi_list, struct msi_desc, list);
+ BUG_ON(list_empty(dev_to_msi_list(&dev->dev)));
+ desc = first_pci_msi_entry(dev);
pci_msi_set_enable(dev, 0);
pci_intx_for_msi(dev, 1);
@@ -909,6 +886,7 @@ void pci_msi_shutdown(struct pci_dev *dev)
/* Restore dev->irq to its default pin-assertion irq */
dev->irq = desc->msi_attrib.default_irq;
+ pcibios_alloc_irq(dev);
}
void pci_disable_msi(struct pci_dev *dev)
@@ -1001,7 +979,7 @@ void pci_msix_shutdown(struct pci_dev *dev)
return;
/* Return the device with MSI-X masked as initial states */
- list_for_each_entry(entry, &dev->msi_list, list) {
+ for_each_pci_msi_entry(entry, dev) {
/* Keep cached states to be restored */
__pci_msix_desc_mask_irq(entry, 1);
}
@@ -1009,6 +987,7 @@ void pci_msix_shutdown(struct pci_dev *dev)
pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
pci_intx_for_msi(dev, 1);
dev->msix_enabled = 0;
+ pcibios_alloc_irq(dev);
}
void pci_disable_msix(struct pci_dev *dev)
@@ -1040,7 +1019,6 @@ EXPORT_SYMBOL(pci_msi_enabled);
void pci_msi_init_pci_dev(struct pci_dev *dev)
{
- INIT_LIST_HEAD(&dev->msi_list);
}
/**
@@ -1137,6 +1115,19 @@ int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries,
}
EXPORT_SYMBOL(pci_enable_msix_range);
+struct pci_dev *msi_desc_to_pci_dev(struct msi_desc *desc)
+{
+ return to_pci_dev(desc->dev);
+}
+
+void *msi_desc_to_pci_sysdata(struct msi_desc *desc)
+{
+ struct pci_dev *dev = msi_desc_to_pci_dev(desc);
+
+ return dev->bus->sysdata;
+}
+EXPORT_SYMBOL_GPL(msi_desc_to_pci_sysdata);
+
#ifdef CONFIG_PCI_MSI_IRQ_DOMAIN
/**
* pci_msi_domain_write_msg - Helper to write MSI message to PCI config space
@@ -1145,7 +1136,7 @@ EXPORT_SYMBOL(pci_enable_msix_range);
*/
void pci_msi_domain_write_msg(struct irq_data *irq_data, struct msi_msg *msg)
{
- struct msi_desc *desc = irq_data->msi_desc;
+ struct msi_desc *desc = irq_data_get_msi_desc(irq_data);
/*
* For MSI-X desc->irq is always equal to irq_data->irq. For
@@ -1269,12 +1260,19 @@ struct irq_domain *pci_msi_create_irq_domain(struct device_node *node,
struct msi_domain_info *info,
struct irq_domain *parent)
{
+ struct irq_domain *domain;
+
if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS)
pci_msi_domain_update_dom_ops(info);
if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
pci_msi_domain_update_chip_ops(info);
- return msi_create_irq_domain(node, info, parent);
+ domain = msi_create_irq_domain(node, info, parent);
+ if (!domain)
+ return NULL;
+
+ domain->bus_token = DOMAIN_BUS_PCI_MSI;
+ return domain;
}
/**
diff --git a/drivers/pci/of.c b/drivers/pci/of.c
index f0929934bb7a..2e99a500cb83 100644
--- a/drivers/pci/of.c
+++ b/drivers/pci/of.c
@@ -9,6 +9,7 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/irqdomain.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/of.h>
@@ -59,3 +60,32 @@ struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus)
return of_node_get(bus->bridge->parent->of_node);
return NULL;
}
+
+struct irq_domain *pci_host_bridge_of_msi_domain(struct pci_bus *bus)
+{
+#ifdef CONFIG_IRQ_DOMAIN
+ struct device_node *np;
+ struct irq_domain *d;
+
+ if (!bus->dev.of_node)
+ return NULL;
+
+ /* Start looking for a phandle to an MSI controller. */
+ np = of_parse_phandle(bus->dev.of_node, "msi-parent", 0);
+
+ /*
+ * If we don't have an msi-parent property, look for a domain
+ * directly attached to the host bridge.
+ */
+ if (!np)
+ np = bus->dev.of_node;
+
+ d = irq_find_matching_host(np, DOMAIN_BUS_PCI_MSI);
+ if (d)
+ return d;
+
+ return irq_find_host(np);
+#else
+ return NULL;
+#endif
+}
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 314a625b78d6..a32ba753e413 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -594,7 +594,7 @@ static struct acpi_device *acpi_pci_find_companion(struct device *dev)
/**
* pci_acpi_optimize_delay - optimize PCI D3 and D3cold delay from ACPI
* @pdev: the PCI device whose delay is to be updated
- * @adev: the companion ACPI device of this PCI device
+ * @handle: ACPI handle of this device
*
* Update the d3_delay and d3cold_delay of a PCI device from the ACPI _DSM
* control method of either the device itself or the PCI host bridge.
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 3cb2210de553..52a880ca1768 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -388,18 +388,31 @@ static int __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
return error;
}
+int __weak pcibios_alloc_irq(struct pci_dev *dev)
+{
+ return 0;
+}
+
+void __weak pcibios_free_irq(struct pci_dev *dev)
+{
+}
+
static int pci_device_probe(struct device *dev)
{
- int error = 0;
- struct pci_driver *drv;
- struct pci_dev *pci_dev;
+ int error;
+ struct pci_dev *pci_dev = to_pci_dev(dev);
+ struct pci_driver *drv = to_pci_driver(dev->driver);
+
+ error = pcibios_alloc_irq(pci_dev);
+ if (error < 0)
+ return error;
- drv = to_pci_driver(dev->driver);
- pci_dev = to_pci_dev(dev);
pci_dev_get(pci_dev);
error = __pci_device_probe(drv, pci_dev);
- if (error)
+ if (error) {
+ pcibios_free_irq(pci_dev);
pci_dev_put(pci_dev);
+ }
return error;
}
@@ -415,6 +428,7 @@ static int pci_device_remove(struct device *dev)
drv->remove(pci_dev);
pm_runtime_put_noidle(dev);
}
+ pcibios_free_irq(pci_dev);
pci_dev->driver = NULL;
}
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 0008c950452c..6a9a1116f1eb 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -81,7 +81,7 @@ unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE;
unsigned long pci_hotplug_io_size = DEFAULT_HOTPLUG_IO_SIZE;
unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_SIZE;
-enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_TUNE_OFF;
+enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_DEFAULT;
/*
* The default CLS is used if arch didn't set CLS explicitly and not
@@ -138,9 +138,22 @@ void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar)
return ioremap_nocache(res->start, resource_size(res));
}
EXPORT_SYMBOL_GPL(pci_ioremap_bar);
+
+void __iomem *pci_ioremap_wc_bar(struct pci_dev *pdev, int bar)
+{
+ /*
+ * Make sure the BAR is actually a memory resource, not an IO resource
+ */
+ if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) {
+ WARN_ON(1);
+ return NULL;
+ }
+ return ioremap_wc(pci_resource_start(pdev, bar),
+ pci_resource_len(pdev, bar));
+}
+EXPORT_SYMBOL_GPL(pci_ioremap_wc_bar);
#endif
-#define PCI_FIND_CAP_TTL 48
static int __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn,
u8 pos, int cap, int *ttl)
@@ -196,8 +209,6 @@ static int __pci_bus_find_cap_start(struct pci_bus *bus,
return PCI_CAPABILITY_LIST;
case PCI_HEADER_TYPE_CARDBUS:
return PCI_CB_CAPABILITY_LIST;
- default:
- return 0;
}
return 0;
@@ -972,7 +983,7 @@ static int pci_save_pcix_state(struct pci_dev *dev)
struct pci_cap_saved_state *save_state;
pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
- if (pos <= 0)
+ if (!pos)
return 0;
save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX);
@@ -995,7 +1006,7 @@ static void pci_restore_pcix_state(struct pci_dev *dev)
save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX);
pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
- if (!save_state || pos <= 0)
+ if (!save_state || !pos)
return;
cap = (u16 *)&save_state->cap.data[0];
@@ -1092,6 +1103,9 @@ void pci_restore_state(struct pci_dev *dev)
pci_restore_pcix_state(dev);
pci_restore_msi_state(dev);
+
+ /* Restore ACS and IOV configuration state */
+ pci_enable_acs(dev);
pci_restore_iov_state(dev);
dev->state_saved = false;
@@ -2159,7 +2173,7 @@ static int _pci_add_cap_save_buffer(struct pci_dev *dev, u16 cap,
else
pos = pci_find_capability(dev, cap);
- if (pos <= 0)
+ if (!pos)
return 0;
save_state = kzalloc(sizeof(*save_state) + size, GFP_KERNEL);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 4ff0ff1c4088..24ba9dc8910a 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -4,6 +4,8 @@
#define PCI_CFG_SPACE_SIZE 256
#define PCI_CFG_SPACE_EXP_SIZE 4096
+#define PCI_FIND_CAP_TTL 48
+
extern const unsigned char pcie_link_speed[];
bool pcie_cap_has_lnkctl(const struct pci_dev *dev);
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index 2f0ce668a775..88122dc2e1b1 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -448,7 +448,7 @@ static int resume_iter(struct device *dev, void *data)
}
/**
- * pcie_port_device_suspend - resume port services associated with a PCIe port
+ * pcie_port_device_resume - resume port services associated with a PCIe port
* @dev: PCI Express port to handle
*/
int pcie_port_device_resume(struct device *dev)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 8ed37dd04056..0b2be174d981 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -660,6 +660,35 @@ static void pci_set_bus_speed(struct pci_bus *bus)
}
}
+static struct irq_domain *pci_host_bridge_msi_domain(struct pci_bus *bus)
+{
+ struct irq_domain *d;
+
+ /*
+ * Any firmware interface that can resolve the msi_domain
+ * should be called from here.
+ */
+ d = pci_host_bridge_of_msi_domain(bus);
+
+ return d;
+}
+
+static void pci_set_bus_msi_domain(struct pci_bus *bus)
+{
+ struct irq_domain *d;
+
+ /*
+ * Either bus is the root, and we must obtain it from the
+ * firmware, or we inherit it from the bridge device.
+ */
+ if (pci_is_root_bus(bus))
+ d = pci_host_bridge_msi_domain(bus);
+ else
+ d = dev_get_msi_domain(&bus->self->dev);
+
+ dev_set_msi_domain(&bus->dev, d);
+}
+
static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
struct pci_dev *bridge, int busnr)
{
@@ -713,6 +742,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
bridge->subordinate = child;
add_dev:
+ pci_set_bus_msi_domain(child);
ret = device_register(&child->dev);
WARN_ON(ret < 0);
@@ -825,6 +855,9 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
child->bridge_ctl = bctl;
}
+ /* Read and initialize bridge resources */
+ pci_read_bridge_bases(child);
+
cmax = pci_scan_child_bus(child);
if (cmax > subordinate)
dev_warn(&dev->dev, "bridge has subordinate %02x but max busn %02x\n",
@@ -885,6 +918,9 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
if (!is_cardbus) {
child->bridge_ctl = bctl;
+
+ /* Read and initialize bridge resources */
+ pci_read_bridge_bases(child);
max = pci_scan_child_bus(child);
} else {
/*
@@ -996,7 +1032,12 @@ void set_pcie_port_type(struct pci_dev *pdev)
else if (type == PCI_EXP_TYPE_UPSTREAM ||
type == PCI_EXP_TYPE_DOWNSTREAM) {
parent = pci_upstream_bridge(pdev);
- if (!parent->has_secondary_link)
+
+ /*
+ * Usually there's an upstream device (Root Port or Switch
+ * Downstream Port), but we can't assume one exists.
+ */
+ if (parent && !parent->has_secondary_link)
pdev->has_secondary_link = 1;
}
}
@@ -1102,7 +1143,7 @@ int pci_cfg_space_size(struct pci_dev *dev)
#define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED)
-static void pci_msi_setup_pci_dev(struct pci_dev *dev)
+void pci_msi_setup_pci_dev(struct pci_dev *dev)
{
/*
* Disable the MSI hardware to avoid screaming interrupts
@@ -1132,7 +1173,6 @@ int pci_setup_device(struct pci_dev *dev)
{
u32 class;
u8 hdr_type;
- struct pci_slot *slot;
int pos = 0;
struct pci_bus_region region;
struct resource *res;
@@ -1148,10 +1188,7 @@ int pci_setup_device(struct pci_dev *dev)
dev->error_state = pci_channel_io_normal;
set_pcie_port_type(dev);
- list_for_each_entry(slot, &dev->bus->slots, list)
- if (PCI_SLOT(dev->devfn) == slot->number)
- dev->slot = slot;
-
+ pci_dev_assign_slot(dev);
/* Assume 32-bit PCI; let 64-bit PCI cards (which are far rarer)
set this higher, assuming the system even supports it. */
dev->dma_mask = 0xffffffff;
@@ -1267,13 +1304,51 @@ int pci_setup_device(struct pci_dev *dev)
bad:
dev_err(&dev->dev, "ignoring class %#08x (doesn't match header type %02x)\n",
dev->class, dev->hdr_type);
- dev->class = PCI_CLASS_NOT_DEFINED;
+ dev->class = PCI_CLASS_NOT_DEFINED << 8;
}
/* We found a fine healthy device, go go go... */
return 0;
}
+static void pci_configure_mps(struct pci_dev *dev)
+{
+ struct pci_dev *bridge = pci_upstream_bridge(dev);
+ int mps, p_mps, rc;
+
+ if (!pci_is_pcie(dev) || !bridge || !pci_is_pcie(bridge))
+ return;
+
+ mps = pcie_get_mps(dev);
+ p_mps = pcie_get_mps(bridge);
+
+ if (mps == p_mps)
+ return;
+
+ if (pcie_bus_config == PCIE_BUS_TUNE_OFF) {
+ dev_warn(&dev->dev, "Max Payload Size %d, but upstream %s set to %d; if necessary, use \"pci=pcie_bus_safe\" and report a bug\n",
+ mps, pci_name(bridge), p_mps);
+ return;
+ }
+
+ /*
+ * Fancier MPS configuration is done later by
+ * pcie_bus_configure_settings()
+ */
+ if (pcie_bus_config != PCIE_BUS_DEFAULT)
+ return;
+
+ rc = pcie_set_mps(dev, p_mps);
+ if (rc) {
+ dev_warn(&dev->dev, "can't set Max Payload Size to %d; if necessary, use \"pci=pcie_bus_safe\" and report a bug\n",
+ p_mps);
+ return;
+ }
+
+ dev_info(&dev->dev, "Max Payload Size set to %d (was %d, max %d)\n",
+ p_mps, mps, 128 << dev->pcie_mpss);
+}
+
static struct hpp_type0 pci_default_type0 = {
.revision = 1,
.cache_line_size = 8,
@@ -1395,6 +1470,8 @@ static void pci_configure_device(struct pci_dev *dev)
struct hotplug_params hpp;
int ret;
+ pci_configure_mps(dev);
+
memset(&hpp, 0, sizeof(hpp));
ret = pci_get_hp_params(dev, &hpp);
if (ret)
@@ -1539,10 +1616,24 @@ static void pci_init_capabilities(struct pci_dev *dev)
/* Single Root I/O Virtualization */
pci_iov_init(dev);
+ /* Address Translation Services */
+ pci_ats_init(dev);
+
/* Enable ACS P2P upstream forwarding */
pci_enable_acs(dev);
}
+static void pci_set_msi_domain(struct pci_dev *dev)
+{
+ /*
+ * If no domain has been set through the pcibios_add_device
+ * callback, inherit the default from the bus device.
+ */
+ if (!dev_get_msi_domain(&dev->dev))
+ dev_set_msi_domain(&dev->dev,
+ dev_get_msi_domain(&dev->bus->dev));
+}
+
void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
{
int ret;
@@ -1584,6 +1675,9 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
ret = pcibios_add_device(dev);
WARN_ON(ret < 0);
+ /* Setup MSI irq domain */
+ pci_set_msi_domain(dev);
+
/* Notifier could use PCI capabilities */
dev->match_driver = false;
ret = device_add(&dev->dev);
@@ -1790,22 +1884,6 @@ static void pcie_write_mrrs(struct pci_dev *dev)
dev_err(&dev->dev, "MRRS was unable to be configured with a safe value. If problems are experienced, try running with pci=pcie_bus_safe\n");
}
-static void pcie_bus_detect_mps(struct pci_dev *dev)
-{
- struct pci_dev *bridge = dev->bus->self;
- int mps, p_mps;
-
- if (!bridge)
- return;
-
- mps = pcie_get_mps(dev);
- p_mps = pcie_get_mps(bridge);
-
- if (mps != p_mps)
- dev_warn(&dev->dev, "Max Payload Size %d, but upstream %s set to %d; if necessary, use \"pci=pcie_bus_safe\" and report a bug\n",
- mps, pci_name(bridge), p_mps);
-}
-
static int pcie_bus_configure_set(struct pci_dev *dev, void *data)
{
int mps, orig_mps;
@@ -1813,10 +1891,9 @@ static int pcie_bus_configure_set(struct pci_dev *dev, void *data)
if (!pci_is_pcie(dev))
return 0;
- if (pcie_bus_config == PCIE_BUS_TUNE_OFF) {
- pcie_bus_detect_mps(dev);
+ if (pcie_bus_config == PCIE_BUS_TUNE_OFF ||
+ pcie_bus_config == PCIE_BUS_DEFAULT)
return 0;
- }
mps = 128 << *(u8 *)data;
orig_mps = pcie_get_mps(dev);
@@ -1974,6 +2051,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
b->bridge = get_device(&bridge->dev);
device_enable_async_suspend(b->bridge);
pci_set_bus_of_node(b);
+ pci_set_bus_msi_domain(b);
if (!parent)
set_dev_node(b->bridge, pcibus_to_node(b));
@@ -2095,8 +2173,9 @@ void pci_bus_release_busn_res(struct pci_bus *b)
res, ret ? "can not be" : "is");
}
-struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
- struct pci_ops *ops, void *sysdata, struct list_head *resources)
+struct pci_bus *pci_scan_root_bus_msi(struct device *parent, int bus,
+ struct pci_ops *ops, void *sysdata,
+ struct list_head *resources, struct msi_controller *msi)
{
struct resource_entry *window;
bool found = false;
@@ -2113,6 +2192,8 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
if (!b)
return NULL;
+ b->msi = msi;
+
if (!found) {
dev_info(&b->dev,
"No busn resource found for root bus, will use [bus %02x-ff]\n",
@@ -2127,6 +2208,13 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
return b;
}
+
+struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
+ struct pci_ops *ops, void *sysdata, struct list_head *resources)
+{
+ return pci_scan_root_bus_msi(parent, bus, ops, sysdata, resources,
+ NULL);
+}
EXPORT_SYMBOL(pci_scan_root_bus);
struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops,
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index e9fd0e90fa3b..6a30252cd79f 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -163,7 +163,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82439TX, quirk_
* VIA Apollo KT133 needs PCI latency patch
* Made according to a windows driver based patch by George E. Breese
* see PCI Latency Adjust on http://www.viahardware.com/download/viatweak.shtm
- * and http://www.georgebreese.com/net/software/#PCI
* Also see http://www.au-ja.org/review-kt133a-1-en.phtml for
* the info on which Mr Breese based his work.
*
@@ -424,10 +423,12 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS100, quirk_ati_
*/
static void quirk_amd_nl_class(struct pci_dev *pdev)
{
- /*
- * Use 'USB Device' (0x0c03fe) instead of PCI header provided
- */
- pdev->class = 0x0c03fe;
+ u32 class = pdev->class;
+
+ /* Use "USB Device (not host controller)" class */
+ pdev->class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe;
+ dev_info(&pdev->dev, "PCI class overridden (%#08x -> %#08x) so dwc3 driver can claim this instead of xhci\n",
+ class, pdev->class);
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_NL_USB,
quirk_amd_nl_class);
@@ -1569,6 +1570,18 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB3
#endif
+static void quirk_jmicron_async_suspend(struct pci_dev *dev)
+{
+ if (dev->multifunction) {
+ device_disable_async_suspend(&dev->dev);
+ dev_info(&dev->dev, "async suspend disabled to avoid multi-function power-on ordering issue\n");
+ }
+}
+DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE, 8, quirk_jmicron_async_suspend);
+DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_CLASS_STORAGE_SATA_AHCI, 0, quirk_jmicron_async_suspend);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_JMICRON, 0x2362, quirk_jmicron_async_suspend);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_JMICRON, 0x236f, quirk_jmicron_async_suspend);
+
#ifdef CONFIG_X86_IO_APIC
static void quirk_alder_ioapic(struct pci_dev *pdev)
{
@@ -1894,6 +1907,15 @@ static void quirk_netmos(struct pci_dev *dev)
DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID,
PCI_CLASS_COMMUNICATION_SERIAL, 8, quirk_netmos);
+static void quirk_f0_vpd_link(struct pci_dev *dev)
+{
+ if (!dev->multifunction || !PCI_FUNC(dev->devfn))
+ return;
+ dev->dev_flags |= PCI_DEV_FLAGS_VPD_REF_F0;
+}
+DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
+ PCI_CLASS_NETWORK_ETHERNET, 8, quirk_f0_vpd_link);
+
static void quirk_e100_interrupt(struct pci_dev *dev)
{
u16 command, pmcsr;
@@ -1986,14 +2008,18 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1508, quirk_disable_aspm_l0s);
static void fixup_rev1_53c810(struct pci_dev *dev)
{
- /* rev 1 ncr53c810 chips don't set the class at all which means
+ u32 class = dev->class;
+
+ /*
+ * rev 1 ncr53c810 chips don't set the class at all which means
* they don't get their resources remapped. Fix that here.
*/
+ if (class)
+ return;
- if (dev->class == PCI_CLASS_NOT_DEFINED) {
- dev_info(&dev->dev, "NCR 53c810 rev 1 detected; setting PCI class\n");
- dev->class = PCI_CLASS_STORAGE_SCSI;
- }
+ dev->class = PCI_CLASS_STORAGE_SCSI << 8;
+ dev_info(&dev->dev, "NCR 53c810 rev 1 PCI class overridden (%#08x -> %#08x)\n",
+ class, dev->class);
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810);
@@ -2241,7 +2267,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x9601, quirk_amd_780_apc_msi);
* return 1 if a HT MSI capability is found and enabled */
static int msi_ht_cap_enabled(struct pci_dev *dev)
{
- int pos, ttl = 48;
+ int pos, ttl = PCI_FIND_CAP_TTL;
pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
while (pos && ttl--) {
@@ -2300,7 +2326,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
/* Force enable MSI mapping capability on HT bridges */
static void ht_enable_msi_mapping(struct pci_dev *dev)
{
- int pos, ttl = 48;
+ int pos, ttl = PCI_FIND_CAP_TTL;
pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
while (pos && ttl--) {
@@ -2379,7 +2405,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA,
static int ht_check_msi_mapping(struct pci_dev *dev)
{
- int pos, ttl = 48;
+ int pos, ttl = PCI_FIND_CAP_TTL;
int found = 0;
/* check if there is HT MSI cap or enabled on this device */
@@ -2504,7 +2530,7 @@ out:
static void ht_disable_msi_mapping(struct pci_dev *dev)
{
- int pos, ttl = 48;
+ int pos, ttl = PCI_FIND_CAP_TTL;
pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
while (pos && ttl--) {
@@ -2829,12 +2855,15 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x3c28, vtd_mask_spec_errors);
static void fixup_ti816x_class(struct pci_dev *dev)
{
+ u32 class = dev->class;
+
/* TI 816x devices do not have class code set when in PCIe boot mode */
- dev_info(&dev->dev, "Setting PCI class for 816x PCIe device\n");
- dev->class = PCI_CLASS_MULTIMEDIA_VIDEO;
+ dev->class = PCI_CLASS_MULTIMEDIA_VIDEO << 8;
+ dev_info(&dev->dev, "PCI class overridden (%#08x -> %#08x)\n",
+ class, dev->class);
}
DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_TI, 0xb800,
- PCI_CLASS_NOT_DEFINED, 0, fixup_ti816x_class);
+ PCI_CLASS_NOT_DEFINED, 8, fixup_ti816x_class);
/* Some PCIe devices do not work reliably with the claimed maximum
* payload size supported.
@@ -2862,7 +2891,8 @@ static void quirk_intel_mc_errata(struct pci_dev *dev)
int err;
u16 rcc;
- if (pcie_bus_config == PCIE_BUS_TUNE_OFF)
+ if (pcie_bus_config == PCIE_BUS_TUNE_OFF ||
+ pcie_bus_config == PCIE_BUS_DEFAULT)
return;
/* Intel errata specifies bits to change but does not say what they are.
@@ -3028,7 +3058,16 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c26, quirk_remove_d3_delay);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c4e, quirk_remove_d3_delay);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c02, quirk_remove_d3_delay);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c22, quirk_remove_d3_delay);
-
+/* Intel Cherrytrail devices do not need 10ms d3_delay */
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2280, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b0, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b8, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22d8, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22dc, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b5, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b7, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2298, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x229c, quirk_remove_d3_delay);
/*
* Some devices may pass our check in pci_intx_mask_supported if
* PCI_COMMAND_INTX_DISABLE works though they actually do not properly
@@ -3326,28 +3365,6 @@ fs_initcall_sync(pci_apply_final_quirks);
* reset a single function if other methods (e.g. FLR, PM D0->D3) are
* not available.
*/
-static int reset_intel_generic_dev(struct pci_dev *dev, int probe)
-{
- int pos;
-
- /* only implement PCI_CLASS_SERIAL_USB at present */
- if (dev->class == PCI_CLASS_SERIAL_USB) {
- pos = pci_find_capability(dev, PCI_CAP_ID_VNDR);
- if (!pos)
- return -ENOTTY;
-
- if (probe)
- return 0;
-
- pci_write_config_byte(dev, pos + 0x4, 1);
- msleep(100);
-
- return 0;
- } else {
- return -ENOTTY;
- }
-}
-
static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe)
{
/*
@@ -3506,8 +3523,6 @@ static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
reset_ivb_igd },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_M2_VGA,
reset_ivb_igd },
- { PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
- reset_intel_generic_dev },
{ PCI_VENDOR_ID_CHELSIO, PCI_ANY_ID,
reset_chelsio_generic_dev },
{ 0 }
@@ -3655,6 +3670,28 @@ DECLARE_PCI_FIXUP_HEADER(0x1283, 0x8892, quirk_use_pcie_bridge_dma_alias);
DECLARE_PCI_FIXUP_HEADER(0x8086, 0x244e, quirk_use_pcie_bridge_dma_alias);
/*
+ * Intersil/Techwell TW686[4589]-based video capture cards have an empty (zero)
+ * class code. Fix it.
+ */
+static void quirk_tw686x_class(struct pci_dev *pdev)
+{
+ u32 class = pdev->class;
+
+ /* Use "Multimedia controller" class */
+ pdev->class = (PCI_CLASS_MULTIMEDIA_OTHER << 8) | 0x01;
+ dev_info(&pdev->dev, "TW686x PCI class overridden (%#08x -> %#08x)\n",
+ class, pdev->class);
+}
+DECLARE_PCI_FIXUP_CLASS_EARLY(0x1797, 0x6864, PCI_CLASS_NOT_DEFINED, 8,
+ quirk_tw686x_class);
+DECLARE_PCI_FIXUP_CLASS_EARLY(0x1797, 0x6865, PCI_CLASS_NOT_DEFINED, 8,
+ quirk_tw686x_class);
+DECLARE_PCI_FIXUP_CLASS_EARLY(0x1797, 0x6868, PCI_CLASS_NOT_DEFINED, 8,
+ quirk_tw686x_class);
+DECLARE_PCI_FIXUP_CLASS_EARLY(0x1797, 0x6869, PCI_CLASS_NOT_DEFINED, 8,
+ quirk_tw686x_class);
+
+/*
* AMD has indicated that the devices below do not support peer-to-peer
* in any system where they are found in the southbridge with an AMD
* IOMMU in the system. Multifunction devices that do not support
@@ -3848,6 +3885,9 @@ static const struct pci_dev_acs_enabled {
{ PCI_VENDOR_ID_INTEL, 0x105F, pci_quirk_mf_endpoint_acs },
{ PCI_VENDOR_ID_INTEL, 0x1060, pci_quirk_mf_endpoint_acs },
{ PCI_VENDOR_ID_INTEL, 0x10D9, pci_quirk_mf_endpoint_acs },
+ /* I219 */
+ { PCI_VENDOR_ID_INTEL, 0x15b7, pci_quirk_mf_endpoint_acs },
+ { PCI_VENDOR_ID_INTEL, 0x15b8, pci_quirk_mf_endpoint_acs },
/* Intel PCH root ports */
{ PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_pch_acs },
{ 0x19a2, 0x710, pci_quirk_mf_endpoint_acs }, /* Emulex BE3-R */
@@ -4008,3 +4048,88 @@ void pci_dev_specific_enable_acs(struct pci_dev *dev)
}
}
}
+
+/*
+ * The PCI capabilities list for Intel DH895xCC VFs (device id 0x0443) with
+ * QuickAssist Technology (QAT) is prematurely terminated in hardware. The
+ * Next Capability pointer in the MSI Capability Structure should point to
+ * the PCIe Capability Structure but is incorrectly hardwired as 0 terminating
+ * the list.
+ */
+static void quirk_intel_qat_vf_cap(struct pci_dev *pdev)
+{
+ int pos, i = 0;
+ u8 next_cap;
+ u16 reg16, *cap;
+ struct pci_cap_saved_state *state;
+
+ /* Bail if the hardware bug is fixed */
+ if (pdev->pcie_cap || pci_find_capability(pdev, PCI_CAP_ID_EXP))
+ return;
+
+ /* Bail if MSI Capability Structure is not found for some reason */
+ pos = pci_find_capability(pdev, PCI_CAP_ID_MSI);
+ if (!pos)
+ return;
+
+ /*
+ * Bail if Next Capability pointer in the MSI Capability Structure
+ * is not the expected incorrect 0x00.
+ */
+ pci_read_config_byte(pdev, pos + 1, &next_cap);
+ if (next_cap)
+ return;
+
+ /*
+ * PCIe Capability Structure is expected to be at 0x50 and should
+ * terminate the list (Next Capability pointer is 0x00). Verify
+ * Capability Id and Next Capability pointer is as expected.
+ * Open-code some of set_pcie_port_type() and pci_cfg_space_size_ext()
+ * to correctly set kernel data structures which have already been
+ * set incorrectly due to the hardware bug.
+ */
+ pos = 0x50;
+ pci_read_config_word(pdev, pos, &reg16);
+ if (reg16 == (0x0000 | PCI_CAP_ID_EXP)) {
+ u32 status;
+#ifndef PCI_EXP_SAVE_REGS
+#define PCI_EXP_SAVE_REGS 7
+#endif
+ int size = PCI_EXP_SAVE_REGS * sizeof(u16);
+
+ pdev->pcie_cap = pos;
+ pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, &reg16);
+ pdev->pcie_flags_reg = reg16;
+ pci_read_config_word(pdev, pos + PCI_EXP_DEVCAP, &reg16);
+ pdev->pcie_mpss = reg16 & PCI_EXP_DEVCAP_PAYLOAD;
+
+ pdev->cfg_size = PCI_CFG_SPACE_EXP_SIZE;
+ if (pci_read_config_dword(pdev, PCI_CFG_SPACE_SIZE, &status) !=
+ PCIBIOS_SUCCESSFUL || (status == 0xffffffff))
+ pdev->cfg_size = PCI_CFG_SPACE_SIZE;
+
+ if (pci_find_saved_cap(pdev, PCI_CAP_ID_EXP))
+ return;
+
+ /*
+ * Save PCIE cap
+ */
+ state = kzalloc(sizeof(*state) + size, GFP_KERNEL);
+ if (!state)
+ return;
+
+ state->cap.cap_nr = PCI_CAP_ID_EXP;
+ state->cap.cap_extended = 0;
+ state->cap.size = size;
+ cap = (u16 *)&state->cap.data[0];
+ pcie_capability_read_word(pdev, PCI_EXP_DEVCTL, &cap[i++]);
+ pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &cap[i++]);
+ pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &cap[i++]);
+ pcie_capability_read_word(pdev, PCI_EXP_RTCTL, &cap[i++]);
+ pcie_capability_read_word(pdev, PCI_EXP_DEVCTL2, &cap[i++]);
+ pcie_capability_read_word(pdev, PCI_EXP_LNKCTL2, &cap[i++]);
+ pcie_capability_read_word(pdev, PCI_EXP_SLTCTL2, &cap[i++]);
+ hlist_add_head(&state->next, &pdev->saved_cap_space);
+ }
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x443, quirk_intel_qat_vf_cap);
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c
index 396c200b9ddb..429d34c348b9 100644
--- a/drivers/pci/slot.c
+++ b/drivers/pci/slot.c
@@ -14,6 +14,7 @@
struct kset *pci_slots_kset;
EXPORT_SYMBOL_GPL(pci_slots_kset);
+static DEFINE_MUTEX(pci_slot_mutex);
static ssize_t pci_slot_attr_show(struct kobject *kobj,
struct attribute *attr, char *buf)
@@ -106,9 +107,11 @@ static void pci_slot_release(struct kobject *kobj)
dev_dbg(&slot->bus->dev, "dev %02x, released physical slot %s\n",
slot->number, pci_slot_name(slot));
+ down_read(&pci_bus_sem);
list_for_each_entry(dev, &slot->bus->devices, bus_list)
if (PCI_SLOT(dev->devfn) == slot->number)
dev->slot = NULL;
+ up_read(&pci_bus_sem);
list_del(&slot->list);
@@ -191,12 +194,22 @@ static int rename_slot(struct pci_slot *slot, const char *name)
return result;
}
+void pci_dev_assign_slot(struct pci_dev *dev)
+{
+ struct pci_slot *slot;
+
+ mutex_lock(&pci_slot_mutex);
+ list_for_each_entry(slot, &dev->bus->slots, list)
+ if (PCI_SLOT(dev->devfn) == slot->number)
+ dev->slot = slot;
+ mutex_unlock(&pci_slot_mutex);
+}
+
static struct pci_slot *get_slot(struct pci_bus *parent, int slot_nr)
{
struct pci_slot *slot;
- /*
- * We already hold pci_bus_sem so don't worry
- */
+
+ /* We already hold pci_slot_mutex */
list_for_each_entry(slot, &parent->slots, list)
if (slot->number == slot_nr) {
kobject_get(&slot->kobj);
@@ -253,7 +266,7 @@ struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
int err = 0;
char *slot_name = NULL;
- down_write(&pci_bus_sem);
+ mutex_lock(&pci_slot_mutex);
if (slot_nr == -1)
goto placeholder;
@@ -301,16 +314,18 @@ placeholder:
INIT_LIST_HEAD(&slot->list);
list_add(&slot->list, &parent->slots);
+ down_read(&pci_bus_sem);
list_for_each_entry(dev, &parent->devices, bus_list)
if (PCI_SLOT(dev->devfn) == slot_nr)
dev->slot = slot;
+ up_read(&pci_bus_sem);
dev_dbg(&parent->dev, "dev %02x, created physical slot %s\n",
slot_nr, pci_slot_name(slot));
out:
kfree(slot_name);
- up_write(&pci_bus_sem);
+ mutex_unlock(&pci_slot_mutex);
return slot;
err:
kfree(slot);
@@ -332,9 +347,9 @@ void pci_destroy_slot(struct pci_slot *slot)
dev_dbg(&slot->bus->dev, "dev %02x, dec refcount to %d\n",
slot->number, atomic_read(&slot->kobj.kref.refcount) - 1);
- down_write(&pci_bus_sem);
+ mutex_lock(&pci_slot_mutex);
kobject_put(&slot->kobj);
- up_write(&pci_bus_sem);
+ mutex_unlock(&pci_slot_mutex);
}
EXPORT_SYMBOL_GPL(pci_destroy_slot);
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
index 8b7a900cd28b..c777b97207d5 100644
--- a/drivers/pci/xen-pcifront.c
+++ b/drivers/pci/xen-pcifront.c
@@ -265,7 +265,7 @@ static int pci_frontend_enable_msix(struct pci_dev *dev,
}
i = 0;
- list_for_each_entry(entry, &dev->msi_list, list) {
+ for_each_pci_msi_entry(entry, dev) {
op.msix_entries[i].entry = entry->msi_attrib.entry_nr;
/* Vector is useless at this point. */
op.msix_entries[i].vector = -1;