forked from Minki/linux
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>
This commit is contained in:
parent
8cbb8a9374
commit
9bf49e36d7
@ -182,6 +182,17 @@ int pci_enable_pri(struct pci_dev *pdev, u32 reqs)
|
|||||||
u32 max_requests;
|
u32 max_requests;
|
||||||
int pos;
|
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))
|
if (WARN_ON(pdev->pri_enabled))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
@ -218,6 +229,10 @@ void pci_disable_pri(struct pci_dev *pdev)
|
|||||||
u16 control;
|
u16 control;
|
||||||
int pos;
|
int pos;
|
||||||
|
|
||||||
|
/* VFs share the PF PRI */
|
||||||
|
if (pdev->is_virtfn)
|
||||||
|
return;
|
||||||
|
|
||||||
if (WARN_ON(!pdev->pri_enabled))
|
if (WARN_ON(!pdev->pri_enabled))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -243,6 +258,9 @@ void pci_restore_pri_state(struct pci_dev *pdev)
|
|||||||
u32 reqs = pdev->pri_reqs_alloc;
|
u32 reqs = pdev->pri_reqs_alloc;
|
||||||
int pos;
|
int pos;
|
||||||
|
|
||||||
|
if (pdev->is_virtfn)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!pdev->pri_enabled)
|
if (!pdev->pri_enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -267,6 +285,9 @@ int pci_reset_pri(struct pci_dev *pdev)
|
|||||||
u16 control;
|
u16 control;
|
||||||
int pos;
|
int pos;
|
||||||
|
|
||||||
|
if (pdev->is_virtfn)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (WARN_ON(pdev->pri_enabled))
|
if (WARN_ON(pdev->pri_enabled))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
@ -293,6 +314,9 @@ int pci_prg_resp_pasid_required(struct pci_dev *pdev)
|
|||||||
u16 status;
|
u16 status;
|
||||||
int pos;
|
int pos;
|
||||||
|
|
||||||
|
if (pdev->is_virtfn)
|
||||||
|
pdev = pci_physfn(pdev);
|
||||||
|
|
||||||
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI);
|
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI);
|
||||||
if (!pos)
|
if (!pos)
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user