@@ -43,6 +43,15 @@ static void pci_pasid_init(struct pci_dev *pdev)
#ifdef CONFIG_PCI_PASID
int pos;
+ /*
+ * As per PCIe r4.0, sec 9.3.7.14, only PF is permitted to
+ * implement PASID Capability and all associated VFs can
+ * only use it. Since PF already initialized the PASID
+ * parameters there is no need to proceed further.
+ */
+ if (pdev->is_virtfn)
+ return;
+
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PASID);
if (!pos)
return;
@@ -355,7 +364,20 @@ EXPORT_SYMBOL_GPL(pci_reset_pri);
int pci_enable_pasid(struct pci_dev *pdev, int features)
{
u16 control, supported;
+ struct pci_dev *pf = pci_physfn(pdev);
+ /*
+ * IOMMU is the only user of this function and as per
+ * current usage, PF PASID enable always happens before
+ * VF and hence we don't need to do anything special
+ * for VF. So just return success if PASID is enabled in PF.
+ */
+ if (pdev->is_virtfn) {
+ if (pf->pasid_enabled)
+ return 0;
+ else
+ return -EINVAL;
+ }
if (WARN_ON(pdev->pasid_enabled))
return -EBUSY;
@@ -392,6 +414,14 @@ void pci_disable_pasid(struct pci_dev *pdev)
{
u16 control = 0;
+ /*
+ * As per PCIe r4.0, sec 9.3.7.14, only PF is permitted to
+ * implement PASID Capability and all associated VFs can
+ * only use it. So don't do anything for VF and just return.
+ */
+ if (pdev->is_virtfn)
+ return;
+
if (WARN_ON(!pdev->pasid_enabled))
return;
@@ -412,6 +442,13 @@ void pci_restore_pasid_state(struct pci_dev *pdev)
{
u16 control;
+ /*
+ * PF should have already restored the PASID state. So for
+ * VF, just return.
+ */
+ if (pdev->is_virtfn)
+ return;
+
if (!pdev->pasid_enabled)
return;
@@ -436,12 +473,12 @@ EXPORT_SYMBOL_GPL(pci_restore_pasid_state);
int pci_pasid_features(struct pci_dev *pdev)
{
u16 supported;
+ struct pci_dev *pf = pci_physfn(pdev);
- if (!pdev->pasid_cap)
+ if (!pf->pasid_cap)
return -EINVAL;
- pci_read_config_word(pdev, pdev->pasid_cap + PCI_PASID_CAP,
- &supported);
+ pci_read_config_word(pf, pf->pasid_cap + PCI_PASID_CAP, &supported);
supported &= PCI_PASID_CAP_EXEC | PCI_PASID_CAP_PRIV;
@@ -492,12 +529,12 @@ EXPORT_SYMBOL_GPL(pci_prg_resp_pasid_required);
int pci_max_pasids(struct pci_dev *pdev)
{
u16 supported;
+ struct pci_dev *pf = pci_physfn(pdev);
- if (!pdev->pasid_cap)
+ if (!pf->pasid_cap)
return -EINVAL;
- pci_read_config_word(pdev, pdev->pasid_cap + PCI_PASID_CAP,
- &supported);
+ pci_read_config_word(pf, pf->pasid_cap + PCI_PASID_CAP, &supported);
supported = (supported & PASID_NUMBER_MASK) >> PASID_NUMBER_SHIFT;