summaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci.c
diff options
context:
space:
mode:
authorJacek Lawrynowicz <jacek.lawrynowicz@intel.com>2016-03-03 09:38:02 -0500
committerBjorn Helgaas <bhelgaas@google.com>2016-04-11 15:34:32 -0400
commit338c3149a221527e202ee26b1e35f76c965bb6c0 (patch)
treea5dfc811d70258c5abac1422e7bd4484a550c165 /drivers/pci/pci.c
parent48c830809ce6e143781172c03a9794cb66802b31 (diff)
PCI: Add support for multiple DMA aliases
Solve IOMMU support issues with PCIe non-transparent bridges that use Requester ID look-up tables (RID-LUT), e.g., the PEX8733. The NTB connects devices in two independent PCI domains. Devices separated by the NTB are not able to discover each other. A PCI packet being forwared from one domain to another has to have its RID modified so it appears on correct bus and completions are forwarded back to the original domain through the NTB. The RID is translated using a preprogrammed table (LUT) and the PCI packet propagates upstream away from the NTB. If the destination system has IOMMU enabled, the packet will be discarded because the new RID is unknown to the IOMMU. Adding a DMA alias for the new RID allows IOMMU to properly recognize the packet. Each device behind the NTB has a unique RID assigned in the RID-LUT. The current DMA alias implementation supports only a single alias, so it's not possible to support mutiple devices behind the NTB when IOMMU is enabled. Enable all possible aliases on a given bus (256) that are stored in a bitset. Alias devfn is directly translated to a bit number. The bitset is not allocated for devices that have no need for DMA aliases. More details can be found in the following article: http://www.plxtech.com/files/pdf/technical/expresslane/RTC_Enabling%20MulitHostSystemDesigns.pdf Signed-off-by: Jacek Lawrynowicz <jacek.lawrynowicz@intel.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Alex Williamson <alex.williamson@redhat.com> Acked-by: David Woodhouse <David.Woodhouse@intel.com> Acked-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r--drivers/pci/pci.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index c82ebd0f6982..0b90c2186f1c 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -4588,12 +4588,27 @@ int pci_set_vga_state(struct pci_dev *dev, bool decode,
4588 */ 4588 */
4589void pci_add_dma_alias(struct pci_dev *dev, u8 devfn) 4589void pci_add_dma_alias(struct pci_dev *dev, u8 devfn)
4590{ 4590{
4591 dev->dma_alias_devfn = devfn; 4591 if (!dev->dma_alias_mask)
4592 dev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN; 4592 dev->dma_alias_mask = kcalloc(BITS_TO_LONGS(U8_MAX),
4593 sizeof(long), GFP_KERNEL);
4594 if (!dev->dma_alias_mask) {
4595 dev_warn(&dev->dev, "Unable to allocate DMA alias mask\n");
4596 return;
4597 }
4598
4599 set_bit(devfn, dev->dma_alias_mask);
4593 dev_info(&dev->dev, "Enabling fixed DMA alias to %02x.%d\n", 4600 dev_info(&dev->dev, "Enabling fixed DMA alias to %02x.%d\n",
4594 PCI_SLOT(devfn), PCI_FUNC(devfn)); 4601 PCI_SLOT(devfn), PCI_FUNC(devfn));
4595} 4602}
4596 4603
4604bool pci_devs_are_dma_aliases(struct pci_dev *dev1, struct pci_dev *dev2)
4605{
4606 return (dev1->dma_alias_mask &&
4607 test_bit(dev2->devfn, dev1->dma_alias_mask)) ||
4608 (dev2->dma_alias_mask &&
4609 test_bit(dev1->devfn, dev2->dma_alias_mask));
4610}
4611
4597bool pci_device_is_present(struct pci_dev *pdev) 4612bool pci_device_is_present(struct pci_dev *pdev)
4598{ 4613{
4599 u32 v; 4614 u32 v;