diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2015-07-17 15:05:46 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2015-08-13 15:57:21 -0500 |
commit | edc90fee916b4f0d14af9c6b5c08666747488ef8 (patch) | |
tree | 25ea93038ec7285c9bb6dbdd07ad7727e442eb23 /include/linux/pci-ats.h | |
parent | fb0cc3aa552642631c3a4e83deae2b5c1a1ef4fa (diff) | |
download | talos-op-linux-edc90fee916b4f0d14af9c6b5c08666747488ef8.tar.gz talos-op-linux-edc90fee916b4f0d14af9c6b5c08666747488ef8.zip |
PCI: Allocate ATS struct during enumeration
Previously, we allocated pci_ats structures when an IOMMU driver called
pci_enable_ats(). An SR-IOV VF shares the STU setting with its PF, so when
enabling ATS on the VF, we allocated a pci_ats struct for the PF if it
didn't already have one. We held the sriov->lock to serialize threads
concurrently enabling ATS on several VFS so only one would allocate the PF
pci_ats.
Gregor reported a deadlock here:
pci_enable_sriov
sriov_enable
virtfn_add
mutex_lock(dev->sriov->lock) # acquire sriov->lock
pci_device_add
device_add
BUS_NOTIFY_ADD_DEVICE notifier chain
iommu_bus_notifier
amd_iommu_add_device # iommu_ops.add_device
init_iommu_group
iommu_group_get_for_dev
iommu_group_add_device
__iommu_attach_device
amd_iommu_attach_device # iommu_ops.attach_device
attach_device
pci_enable_ats
mutex_lock(dev->sriov->lock) # deadlock
There's no reason to delay allocating the pci_ats struct, and if we
allocate it for each device at enumeration-time, there's no need for
locking in pci_enable_ats().
Allocate pci_ats struct during enumeration, when we initialize other
capabilities.
Note that this implementation requires ATS to be enabled on the PF first,
before on any of the VFs because the PF controls the STU for all the VFs.
Link: http://permalink.gmane.org/gmane.linux.kernel.iommu/9433
Reported-by: Gregor Dick <gdick@solarflare.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'include/linux/pci-ats.h')
-rw-r--r-- | include/linux/pci-ats.h | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/include/linux/pci-ats.h b/include/linux/pci-ats.h index 72031785fe1d..e2dcc2ff3d0e 100644 --- a/include/linux/pci-ats.h +++ b/include/linux/pci-ats.h @@ -8,7 +8,7 @@ struct pci_ats { int pos; /* capability position */ int stu; /* Smallest Translation Unit */ int qdep; /* Invalidate Queue Depth */ - int ref_cnt; /* Physical Function reference count */ + atomic_t ref_cnt; /* number of VFs with ATS enabled */ unsigned int is_enabled:1; /* Enable bit is set */ }; |