summaryrefslogtreecommitdiffstats
path: root/drivers/iommu
diff options
context:
space:
mode:
authorLogan Gunthorpe <logang@deltatee.com>2019-02-13 12:54:46 -0500
committerJoerg Roedel <jroedel@suse.de>2019-02-26 04:34:03 -0500
commit3f0c625c6ae714cf4dbab534b4c399f1d720e5db (patch)
treebee418b3b341a6fae11154766af35e56f08042c9 /drivers/iommu
parent9ca8261173fc06ba1bd3c52e83eae0a0b7146b3b (diff)
iommu/vt-d: Allow interrupts from the entire bus for aliased devices
When a device has multiple aliases that all are from the same bus, we program the IRTE to accept requests from any matching device on the bus. This is so NTB devices which can have requests from multiple bus-devfns can pass MSI interrupts through across the bridge. Signed-off-by: Logan Gunthorpe <logang@deltatee.com> Cc: David Woodhouse <dwmw2@infradead.org> Cc: Joerg Roedel <joro@8bytes.org> Cc: Jacob Pan <jacob.jun.pan@linux.intel.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu')
-rw-r--r--drivers/iommu/intel_irq_remapping.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c
index 5a55bef8e379..2d74641b7f7b 100644
--- a/drivers/iommu/intel_irq_remapping.c
+++ b/drivers/iommu/intel_irq_remapping.c
@@ -368,6 +368,8 @@ static int set_hpet_sid(struct irte *irte, u8 id)
368struct set_msi_sid_data { 368struct set_msi_sid_data {
369 struct pci_dev *pdev; 369 struct pci_dev *pdev;
370 u16 alias; 370 u16 alias;
371 int count;
372 int busmatch_count;
371}; 373};
372 374
373static int set_msi_sid_cb(struct pci_dev *pdev, u16 alias, void *opaque) 375static int set_msi_sid_cb(struct pci_dev *pdev, u16 alias, void *opaque)
@@ -376,6 +378,10 @@ static int set_msi_sid_cb(struct pci_dev *pdev, u16 alias, void *opaque)
376 378
377 data->pdev = pdev; 379 data->pdev = pdev;
378 data->alias = alias; 380 data->alias = alias;
381 data->count++;
382
383 if (PCI_BUS_NUM(alias) == pdev->bus->number)
384 data->busmatch_count++;
379 385
380 return 0; 386 return 0;
381} 387}
@@ -387,6 +393,8 @@ static int set_msi_sid(struct irte *irte, struct pci_dev *dev)
387 if (!irte || !dev) 393 if (!irte || !dev)
388 return -1; 394 return -1;
389 395
396 data.count = 0;
397 data.busmatch_count = 0;
390 pci_for_each_dma_alias(dev, set_msi_sid_cb, &data); 398 pci_for_each_dma_alias(dev, set_msi_sid_cb, &data);
391 399
392 /* 400 /*
@@ -395,6 +403,11 @@ static int set_msi_sid(struct irte *irte, struct pci_dev *dev)
395 * device is the case of a PCIe-to-PCI bridge, where the alias is for 403 * device is the case of a PCIe-to-PCI bridge, where the alias is for
396 * the subordinate bus. In this case we can only verify the bus. 404 * the subordinate bus. In this case we can only verify the bus.
397 * 405 *
406 * If there are multiple aliases, all with the same bus number,
407 * then all we can do is verify the bus. This is typical in NTB
408 * hardware which use proxy IDs where the device will generate traffic
409 * from multiple devfn numbers on the same bus.
410 *
398 * If the alias device is on a different bus than our source device 411 * If the alias device is on a different bus than our source device
399 * then we have a topology based alias, use it. 412 * then we have a topology based alias, use it.
400 * 413 *
@@ -405,6 +418,8 @@ static int set_msi_sid(struct irte *irte, struct pci_dev *dev)
405 if (PCI_BUS_NUM(data.alias) != data.pdev->bus->number) 418 if (PCI_BUS_NUM(data.alias) != data.pdev->bus->number)
406 set_irte_verify_bus(irte, PCI_BUS_NUM(data.alias), 419 set_irte_verify_bus(irte, PCI_BUS_NUM(data.alias),
407 dev->bus->number); 420 dev->bus->number);
421 else if (data.count >= 2 && data.busmatch_count == data.count)
422 set_irte_verify_bus(irte, dev->bus->number, dev->bus->number);
408 else if (data.pdev->bus->number != dev->bus->number) 423 else if (data.pdev->bus->number != dev->bus->number)
409 set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16, data.alias); 424 set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16, data.alias);
410 else 425 else