Skip to content

Commit

Permalink
Merge branches 'pci/hotplug', 'pci/iommu', 'pci/irq' and 'pci/virtual…
Browse files Browse the repository at this point in the history
…ization' into next

* pci/hotplug:
  PCI: pciehp: Remove ignored MRL sensor interrupt events
  PCI: pciehp: Remove unused interrupt events
  PCI: pciehp: Handle invalid data when reading from non-existent devices
  PCI: Hold pci_slot_mutex while searching bus->slots list
  PCI: Protect pci_bus->slots with pci_slot_mutex, not pci_bus_sem
  PCI: pciehp: Simplify pcie_poll_cmd()
  PCI: Use "slot" and "pci_slot" for struct hotplug_slot and struct pci_slot

* pci/iommu:
  PCI: Remove pci_ats_enabled()
  PCI: Stop caching ATS Invalidate Queue Depth
  PCI: Move ATS declarations to linux/pci.h so they're all together
  PCI: Clean up ATS error handling
  PCI: Use pci_physfn() rather than looking up physfn by hand
  PCI: Inline the ATS setup code into pci_ats_init()
  PCI: Rationalize pci_ats_queue_depth() error checking
  PCI: Reduce size of ATS structure elements
  PCI: Embed ATS info directly into struct pci_dev
  PCI: Allocate ATS struct during enumeration
  iommu/vt-d: Cache PCI ATS state and Invalidate Queue Depth

* pci/irq:
  PCI: Kill off set_irq_flags() usage

* pci/virtualization:
  PCI: Add ACS quirks for Intel I219-LM/V
  • Loading branch information
Bjorn Helgaas committed Aug 14, 2015
5 parents 5a4f3cf + 2db0f71 + f7ef134 + 3e14675 + 95e1658 commit 1f408d5
Show file tree
Hide file tree
Showing 19 changed files with 209 additions and 271 deletions.
6 changes: 1 addition & 5 deletions arch/powerpc/kernel/pci_of_scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
{
struct pci_dev *dev;
const char *type;
struct pci_slot *slot;

dev = pci_alloc_dev(bus);
if (!dev)
Expand All @@ -145,10 +144,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
dev->needs_freset = 0; /* pcie fundamental reset required */
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);
dev->vendor = get_int_prop(node, "vendor-id", 0xffff);
dev->device = get_int_prop(node, "device-id", 0xffff);
dev->subsystem_vendor = get_int_prop(node, "subsystem-vendor-id", 0);
Expand Down
6 changes: 1 addition & 5 deletions arch/sparc/kernel/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,6 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
struct pci_bus *bus, int devfn)
{
struct dev_archdata *sd;
struct pci_slot *slot;
struct platform_device *op;
struct pci_dev *dev;
const char *type;
Expand Down Expand Up @@ -290,10 +289,7 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
dev->multifunction = 0; /* maybe a lie? */
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);
dev->vendor = of_getintprop_default(node, "vendor-id", 0xffff);
dev->device = of_getintprop_default(node, "device-id", 0xffff);
dev->subsystem_vendor =
Expand Down
28 changes: 18 additions & 10 deletions drivers/iommu/intel-iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,10 @@ struct device_domain_info {
struct list_head global; /* link to global list */
u8 bus; /* PCI bus number */
u8 devfn; /* PCI devfn number */
struct {
u8 enabled:1;
u8 qdep;
} ats; /* ATS state */
struct device *dev; /* it's NULL for PCIe-to-PCI bridge */
struct intel_iommu *iommu; /* IOMMU used by this device */
struct dmar_domain *domain; /* pointer to domain */
Expand Down Expand Up @@ -1391,19 +1395,26 @@ iommu_support_dev_iotlb (struct dmar_domain *domain, struct intel_iommu *iommu,

static void iommu_enable_dev_iotlb(struct device_domain_info *info)
{
struct pci_dev *pdev;

if (!info || !dev_is_pci(info->dev))
return;

pci_enable_ats(to_pci_dev(info->dev), VTD_PAGE_SHIFT);
pdev = to_pci_dev(info->dev);
if (pci_enable_ats(pdev, VTD_PAGE_SHIFT))
return;

info->ats.enabled = 1;
info->ats.qdep = pci_ats_queue_depth(pdev);
}

static void iommu_disable_dev_iotlb(struct device_domain_info *info)
{
if (!info->dev || !dev_is_pci(info->dev) ||
!pci_ats_enabled(to_pci_dev(info->dev)))
if (!info->ats.enabled)
return;

pci_disable_ats(to_pci_dev(info->dev));
info->ats.enabled = 0;
}

static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
Expand All @@ -1415,16 +1426,11 @@ static void iommu_flush_dev_iotlb(struct dmar_domain *domain,

spin_lock_irqsave(&device_domain_lock, flags);
list_for_each_entry(info, &domain->devices, link) {
struct pci_dev *pdev;
if (!info->dev || !dev_is_pci(info->dev))
continue;

pdev = to_pci_dev(info->dev);
if (!pci_ats_enabled(pdev))
if (!info->ats.enabled)
continue;

sid = info->bus << 8 | info->devfn;
qdep = pci_ats_queue_depth(pdev);
qdep = info->ats.qdep;
qi_flush_dev_iotlb(info->iommu, sid, qdep, addr, mask);
}
spin_unlock_irqrestore(&device_domain_lock, flags);
Expand Down Expand Up @@ -2272,6 +2278,8 @@ static struct dmar_domain *dmar_insert_dev_info(struct intel_iommu *iommu,

info->bus = bus;
info->devfn = devfn;
info->ats.enabled = 0;
info->ats.qdep = 0;
info->dev = dev;
info->domain = domain;
info->iommu = iommu;
Expand Down
131 changes: 46 additions & 85 deletions drivers/pci/ats.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/**
Expand All @@ -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);
Expand All @@ -103,45 +77,39 @@ 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);

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);

Expand All @@ -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);

Expand Down
1 change: 0 additions & 1 deletion drivers/pci/host/pci-dra7xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
2 changes: 0 additions & 2 deletions drivers/pci/host/pci-keystone-dw.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down
1 change: 0 additions & 1 deletion drivers/pci/host/pci-tegra.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
1 change: 0 additions & 1 deletion drivers/pci/host/pci-xgene-msi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
1 change: 0 additions & 1 deletion drivers/pci/host/pcie-designware.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
1 change: 0 additions & 1 deletion drivers/pci/host/pcie-rcar.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
2 changes: 0 additions & 2 deletions drivers/pci/host/pcie-xilinx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down
Loading

0 comments on commit 1f408d5

Please sign in to comment.