summaryrefslogtreecommitdiff
path: root/drivers/pci/ats.c
diff options
context:
space:
mode:
authorKuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>2019-09-05 14:31:42 -0500
committerBjorn Helgaas <bhelgaas@google.com>2019-10-15 16:39:09 -0500
commit9bf49e36d7183a170a9906d19acc5254818fc574 (patch)
tree55cc33da51fd07b665012f45d26a54971c5e47c4 /drivers/pci/ats.c
parent8cbb8a9374a271099bacdc890fb16d374261332b (diff)
PCI/ATS: Handle sharing of PF PRI Capability with all VFs
Per PCIe r5.0, sec 9.3.7.11, VFs must not implement the PRI Capability. If the PF implements PRI, it is shared by the VFs. Since VFs don't have a PRI Capability, pci_enable_pri() always failed, which caused IOMMU setup to fail. Update the PRI interfaces so for VFs they reflect the state of the PF PRI. [bhelgaas: rebase without pri_cap caching, commit log] Suggested-by: Ashok Raj <ashok.raj@intel.com> Link: https://lore.kernel.org/r/b971e31f8695980da8e4a7f93e3b6a3edba3edaa.1567029860.git.sathyanarayanan.kuppuswamy@linux.intel.com Link: https://lore.kernel.org/r/20190905193146.90250-2-helgaas@kernel.org Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Cc: Ashok Raj <ashok.raj@intel.com> Cc: Keith Busch <keith.busch@intel.com>
Diffstat (limited to 'drivers/pci/ats.c')
-rw-r--r--drivers/pci/ats.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c
index 0d06177252c7..b0f68c0ea91e 100644
--- a/drivers/pci/ats.c
+++ b/drivers/pci/ats.c
@@ -182,6 +182,17 @@ int pci_enable_pri(struct pci_dev *pdev, u32 reqs)
u32 max_requests;
int pos;
+ /*
+ * VFs must not implement the PRI Capability. If their PF
+ * implements PRI, it is shared by the VFs, so if the PF PRI is
+ * enabled, it is also enabled for the VF.
+ */
+ if (pdev->is_virtfn) {
+ if (pci_physfn(pdev)->pri_enabled)
+ return 0;
+ return -EINVAL;
+ }
+
if (WARN_ON(pdev->pri_enabled))
return -EBUSY;
@@ -218,6 +229,10 @@ void pci_disable_pri(struct pci_dev *pdev)
u16 control;
int pos;
+ /* VFs share the PF PRI */
+ if (pdev->is_virtfn)
+ return;
+
if (WARN_ON(!pdev->pri_enabled))
return;
@@ -243,6 +258,9 @@ void pci_restore_pri_state(struct pci_dev *pdev)
u32 reqs = pdev->pri_reqs_alloc;
int pos;
+ if (pdev->is_virtfn)
+ return;
+
if (!pdev->pri_enabled)
return;
@@ -267,6 +285,9 @@ int pci_reset_pri(struct pci_dev *pdev)
u16 control;
int pos;
+ if (pdev->is_virtfn)
+ return 0;
+
if (WARN_ON(pdev->pri_enabled))
return -EBUSY;
@@ -293,6 +314,9 @@ int pci_prg_resp_pasid_required(struct pci_dev *pdev)
u16 status;
int pos;
+ if (pdev->is_virtfn)
+ pdev = pci_physfn(pdev);
+
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI);
if (!pos)
return 0;