diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/ats.c | 131 | ||||
-rw-r--r-- | drivers/pci/host/pci-dra7xx.c | 1 | ||||
-rw-r--r-- | drivers/pci/host/pci-keystone-dw.c | 2 | ||||
-rw-r--r-- | drivers/pci/host/pci-tegra.c | 1 | ||||
-rw-r--r-- | drivers/pci/host/pci-xgene-msi.c | 1 | ||||
-rw-r--r-- | drivers/pci/host/pcie-designware.c | 1 | ||||
-rw-r--r-- | drivers/pci/host/pcie-rcar.c | 1 | ||||
-rw-r--r-- | drivers/pci/host/pcie-xilinx.c | 2 | ||||
-rw-r--r-- | drivers/pci/hotplug/pci_hotplug_core.c | 122 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp.h | 14 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 48 | ||||
-rw-r--r-- | drivers/pci/probe.c | 9 | ||||
-rw-r--r-- | drivers/pci/quirks.c | 3 | ||||
-rw-r--r-- | drivers/pci/slot.c | 29 |
14 files changed, 165 insertions, 200 deletions
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/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c index 80db09e47800..1a0d124b199a 100644 --- a/drivers/pci/host/pci-dra7xx.c +++ b/drivers/pci/host/pci-dra7xx.c @@ -155,7 +155,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-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 9e1889e6aec7..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; } diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index b48b8a2c50b9..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; } 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-xilinx.c b/drivers/pci/host/pcie-xilinx.c index dcb9b57ed7ea..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; } 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/probe.c b/drivers/pci/probe.c index 0fb0c74ae160..51ebb9783f5e 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1139,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; @@ -1155,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; @@ -1546,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 b6af4b0192b8..7741250f1095 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3872,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); |