When SRIOV VF device IOTLB is invalidated, we need to provide
the PF source SID such that IOMMU hardware can gauge the depth
of invalidation queue which is shared among VFs. This is needed
when device invalidation throttle (DIT) capability is supported.

Signed-off-by: Jacob Pan <jacob.jun....@linux.intel.com>
---
 drivers/iommu/intel-iommu.c | 13 +++++++++++++
 include/linux/intel-iommu.h |  3 +++
 2 files changed, 16 insertions(+)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 000b2b3..e1bd219 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -1459,6 +1459,19 @@ static void iommu_enable_dev_iotlb(struct 
device_domain_info *info)
                return;
 
        pdev = to_pci_dev(info->dev);
+       /* For IOMMU that supports device IOTLB throttling (DIT), we assign
+        * PFSID to the invalidation desc of a VF such that IOMMU HW can gauge
+        * queue depth at PF level. If DIT is not set, PFSID will be treated as
+        * reserved, which should be set to 0.
+        */
+       if (!ecap_dit(info->iommu->ecap))
+               info->pfsid = 0;
+       else if (pdev && pdev->is_virtfn) {
+               if (ecap_dit(info->iommu->ecap))
+                       dev_warn(&pdev->dev, "SRIOV VF device IOTLB enabled 
without flow control\n");
+               info->pfsid = PCI_DEVID(pdev->physfn->bus->number, 
pdev->physfn->devfn);
+       } else
+               info->pfsid = PCI_DEVID(info->bus, info->devfn);
 
 #ifdef CONFIG_INTEL_IOMMU_SVM
        /* The PCIe spec, in its wisdom, declares that the behaviour of
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
index 7f05e36..6956a4e 100644
--- a/include/linux/intel-iommu.h
+++ b/include/linux/intel-iommu.h
@@ -112,6 +112,7 @@
  * Extended Capability Register
  */
 
+#define ecap_dit(e)            ((e >> 41) & 0x1)
 #define ecap_pasid(e)          ((e >> 40) & 0x1)
 #define ecap_pss(e)            ((e >> 35) & 0x1f)
 #define ecap_eafs(e)           ((e >> 34) & 0x1)
@@ -285,6 +286,7 @@ enum {
 #define QI_DEV_IOTLB_SID(sid)  ((u64)((sid) & 0xffff) << 32)
 #define QI_DEV_IOTLB_QDEP(qdep)        (((qdep) & 0x1f) << 16)
 #define QI_DEV_IOTLB_ADDR(addr)        ((u64)(addr) & VTD_PAGE_MASK)
+#define QI_DEV_IOTLB_PFSID(pfsid) (((u64)(pfsid & 0xf) << 12) | ((u64)(pfsid & 
0xff0) << 48))
 #define QI_DEV_IOTLB_SIZE      1
 #define QI_DEV_IOTLB_MAX_INVS  32
 
@@ -475,6 +477,7 @@ struct device_domain_info {
        struct list_head global; /* link to global list */
        u8 bus;                 /* PCI bus number */
        u8 devfn;               /* PCI devfn number */
+       u16 pfsid;              /* SRIOV physical function source ID */
        u8 pasid_supported:3;
        u8 pasid_enabled:1;
        u8 pri_supported:1;
-- 
2.7.4

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Reply via email to