| From 2e34673be0bd6bb0c6c496a861cbc3f7431e7ce3 Mon Sep 17 00:00:00 2001 |
| From: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> |
| Date: Wed, 29 Jan 2020 11:14:00 -0800 |
| Subject: PCI/ATS: Use PF PASID for VFs |
| |
| From: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> |
| |
| commit 2e34673be0bd6bb0c6c496a861cbc3f7431e7ce3 upstream. |
| |
| Per PCIe r5.0, sec 9.3.7.14, if a PF implements the PASID Capability, the |
| PF PASID configuration is shared by its VFs, and VFs must not implement |
| their own PASID Capability. But commit 751035b8dc06 ("PCI/ATS: Cache PASID |
| Capability offset") changed pci_max_pasids() and pci_pasid_features() to |
| use the PASID Capability of the VF device instead of the associated PF |
| device. This leads to IOMMU bind failures when pci_max_pasids() and |
| pci_pasid_features() are called for VFs. |
| |
| In pci_max_pasids() and pci_pasid_features(), always use the PF PASID |
| Capability. |
| |
| Fixes: 751035b8dc06 ("PCI/ATS: Cache PASID Capability offset") |
| Link: https://lore.kernel.org/r/fe891f9755cb18349389609e7fed9940fc5b081a.1580325170.git.sathyanarayanan.kuppuswamy@linux.intel.com |
| Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> |
| Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> |
| CC: stable@vger.kernel.org # v5.5+ |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/pci/ats.c | 6 ++++-- |
| 1 file changed, 4 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/pci/ats.c |
| +++ b/drivers/pci/ats.c |
| @@ -424,11 +424,12 @@ void pci_restore_pasid_state(struct pci_ |
| int pci_pasid_features(struct pci_dev *pdev) |
| { |
| u16 supported; |
| - int pasid = pdev->pasid_cap; |
| + int pasid; |
| |
| if (pdev->is_virtfn) |
| pdev = pci_physfn(pdev); |
| |
| + pasid = pdev->pasid_cap; |
| if (!pasid) |
| return -EINVAL; |
| |
| @@ -451,11 +452,12 @@ int pci_pasid_features(struct pci_dev *p |
| int pci_max_pasids(struct pci_dev *pdev) |
| { |
| u16 supported; |
| - int pasid = pdev->pasid_cap; |
| + int pasid; |
| |
| if (pdev->is_virtfn) |
| pdev = pci_physfn(pdev); |
| |
| + pasid = pdev->pasid_cap; |
| if (!pasid) |
| return -EINVAL; |
| |