diff options
Diffstat (limited to 'drivers/pci')
27 files changed, 406 insertions, 321 deletions
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..e339a8c42f76 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig @@ -135,7 +135,7 @@ config PCIE_IPROC_PLATFORM through the generic platform bus interface config PCIE_IPROC_BCMA - bool "Broadcom iProc PCIe BCMA bus driver" + tristate "Broadcom iProc PCIe BCMA bus driver" depends on ARCH_BCM_IPROC || (ARM && COMPILE_TEST) select PCIE_IPROC select BCMA diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c index 190989908a1a..199e29a044cd 100644 --- a/drivers/pci/host/pci-dra7xx.c +++ b/drivers/pci/host/pci-dra7xx.c @@ -167,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; } 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..f1d0749ebbf0 100644 --- a/drivers/pci/host/pci-keystone-dw.c +++ b/drivers/pci/host/pci-keystone-dw.c @@ -196,7 +196,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 +276,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-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..398c9bfe13a9 100644 --- a/drivers/pci/host/pci-xgene-msi.c +++ b/drivers/pci/host/pci-xgene-msi.c @@ -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; } @@ -582,7 +581,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..55fe86548d77 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; diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index 69486be7181e..308957f09873 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c @@ -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"); } 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..0e1f480b9db4 100644 --- a/drivers/pci/host/pcie-xilinx.c +++ b/drivers/pci/host/pcie-xilinx.c @@ -338,7 +338,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 +376,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 +447,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) { 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..bb74238c0cb6 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -665,6 +665,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; } @@ -792,9 +793,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: @@ -909,6 +910,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) @@ -1009,6 +1011,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) 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..8037c27beb05 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -140,7 +140,6 @@ void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar) EXPORT_SYMBOL_GPL(pci_ioremap_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 +195,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 +969,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 +992,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 +1089,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 +2159,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 cefd636681b6..51ebb9783f5e 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -826,6 +826,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", @@ -886,6 +889,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 { /* @@ -1133,7 +1139,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; @@ -1149,10 +1154,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; @@ -1268,7 +1270,7 @@ 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... */ @@ -1540,6 +1542,9 @@ 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); } diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index e9fd0e90fa3b..7741250f1095 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); @@ -1894,6 +1895,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 +1996,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 +2255,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 +2314,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 +2393,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 +2518,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 +2843,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. @@ -3028,7 +3045,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 +3352,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 +3510,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 +3657,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 +3872,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 */ 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); |