PCI: Add device flag PCI_DEV_FLAGS_BRIDGE_XLATE_ROOT
authorJayachandran C <jnair@caviumnetworks.com>
Thu, 13 Apr 2017 20:30:44 +0000 (20:30 +0000)
committerBjorn Helgaas <bhelgaas@google.com>
Thu, 13 Apr 2017 23:49:50 +0000 (18:49 -0500)
Add a new quirk flag PCI_DEV_FLAGS_BRIDGE_XLATE_ROOT to limit the DMA alias
search to go no further than the bridge where the IOMMU unit is attached.

The flag will be used to indicate a bridge device which forwards the
address translation requests to the IOMMU, i.e., where the interrupt and
DMA requests leave the PCIe hierarchy and go into the system blocks.

Usually this happens at the PCI RC, so this flag is not needed.  But on
systems where there are bridges that introduce aliases above the IOMMU,
this flag prevents pci_for_each_dma_alias() from generating aliases that
the IOMMU will never see.

The function pci_for_each_dma_alias() is updated to stop when it see a
bridge with this flag set.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=195447
Signed-off-by: Jayachandran C <jnair@caviumnetworks.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
Acked-by: David Daney <david.daney@cavium.com>
drivers/pci/search.c
include/linux/pci.h

index 33e0f033a48e7e2f6097b13d4425d8d17b1cabb7..4c6044ad7368acbe617fbd6bd90bfb359f29032a 100644 (file)
@@ -60,6 +60,10 @@ int pci_for_each_dma_alias(struct pci_dev *pdev,
 
                tmp = bus->self;
 
+               /* stop at bridge where translation unit is associated */
+               if (tmp->dev_flags & PCI_DEV_FLAGS_BRIDGE_XLATE_ROOT)
+                       return ret;
+
                /*
                 * PCIe-to-PCI/X bridges alias transactions from downstream
                 * devices using the subordinate bus number (PCI Express to
index eb3da1a04e6cdc7d3f4efab5532f53abcdf3a28f..3f596acc05be7f99d8f3f48d431978e8ca6c3ea5 100644 (file)
@@ -178,6 +178,8 @@ enum pci_dev_flags {
        PCI_DEV_FLAGS_NO_PM_RESET = (__force pci_dev_flags_t) (1 << 7),
        /* Get VPD from function 0 VPD */
        PCI_DEV_FLAGS_VPD_REF_F0 = (__force pci_dev_flags_t) (1 << 8),
+       /* a non-root bridge where translation occurs, stop alias search here */
+       PCI_DEV_FLAGS_BRIDGE_XLATE_ROOT = (__force pci_dev_flags_t) (1 << 9),
 };
 
 enum pci_irq_reroute_variant {