iommu/vt-d: avoid dev iotlb logic for domains with no dev iotlbs
This patch avoids taking the device_domain_lock in iommu_flush_dev_iotlb() for domains with no dev iotlb devices. Signed-off-by: Omer Peleg <omer@cs.technion.ac.il> [gvdl@google.com: fixed locking issues] Signed-off-by: Godfrey van der Linden <gvdl@google.com> [mad@cs.technion.ac.il: rebased and reworded the commit message] Signed-off-by: Adam Morrison <mad@cs.technion.ac.il> Reviewed-by: Shaohua Li <shli@fb.com> Reviewed-by: Ben Serebrin <serebrin@google.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
This commit is contained in:
parent
769530e4ba
commit
0824c5920b
1 changed files with 34 additions and 0 deletions
|
@ -391,6 +391,7 @@ struct dmar_domain {
|
|||
* domain ids are 16 bit wide according
|
||||
* to VT-d spec, section 9.3 */
|
||||
|
||||
bool has_iotlb_device;
|
||||
struct list_head devices; /* all devices' list */
|
||||
struct iova_domain iovad; /* iova's that belong to this domain */
|
||||
|
||||
|
@ -1464,10 +1465,35 @@ iommu_support_dev_iotlb (struct dmar_domain *domain, struct intel_iommu *iommu,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void domain_update_iotlb(struct dmar_domain *domain)
|
||||
{
|
||||
struct device_domain_info *info;
|
||||
bool has_iotlb_device = false;
|
||||
|
||||
assert_spin_locked(&device_domain_lock);
|
||||
|
||||
list_for_each_entry(info, &domain->devices, link) {
|
||||
struct pci_dev *pdev;
|
||||
|
||||
if (!info->dev || !dev_is_pci(info->dev))
|
||||
continue;
|
||||
|
||||
pdev = to_pci_dev(info->dev);
|
||||
if (pdev->ats_enabled) {
|
||||
has_iotlb_device = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
domain->has_iotlb_device = has_iotlb_device;
|
||||
}
|
||||
|
||||
static void iommu_enable_dev_iotlb(struct device_domain_info *info)
|
||||
{
|
||||
struct pci_dev *pdev;
|
||||
|
||||
assert_spin_locked(&device_domain_lock);
|
||||
|
||||
if (!info || !dev_is_pci(info->dev))
|
||||
return;
|
||||
|
||||
|
@ -1487,6 +1513,7 @@ static void iommu_enable_dev_iotlb(struct device_domain_info *info)
|
|||
#endif
|
||||
if (info->ats_supported && !pci_enable_ats(pdev, VTD_PAGE_SHIFT)) {
|
||||
info->ats_enabled = 1;
|
||||
domain_update_iotlb(info->domain);
|
||||
info->ats_qdep = pci_ats_queue_depth(pdev);
|
||||
}
|
||||
}
|
||||
|
@ -1495,6 +1522,8 @@ static void iommu_disable_dev_iotlb(struct device_domain_info *info)
|
|||
{
|
||||
struct pci_dev *pdev;
|
||||
|
||||
assert_spin_locked(&device_domain_lock);
|
||||
|
||||
if (!dev_is_pci(info->dev))
|
||||
return;
|
||||
|
||||
|
@ -1503,6 +1532,7 @@ static void iommu_disable_dev_iotlb(struct device_domain_info *info)
|
|||
if (info->ats_enabled) {
|
||||
pci_disable_ats(pdev);
|
||||
info->ats_enabled = 0;
|
||||
domain_update_iotlb(info->domain);
|
||||
}
|
||||
#ifdef CONFIG_INTEL_IOMMU_SVM
|
||||
if (info->pri_enabled) {
|
||||
|
@ -1523,6 +1553,9 @@ static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
|
|||
unsigned long flags;
|
||||
struct device_domain_info *info;
|
||||
|
||||
if (!domain->has_iotlb_device)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&device_domain_lock, flags);
|
||||
list_for_each_entry(info, &domain->devices, link) {
|
||||
if (!info->ats_enabled)
|
||||
|
@ -1740,6 +1773,7 @@ static struct dmar_domain *alloc_domain(int flags)
|
|||
memset(domain, 0, sizeof(*domain));
|
||||
domain->nid = -1;
|
||||
domain->flags = flags;
|
||||
domain->has_iotlb_device = false;
|
||||
INIT_LIST_HEAD(&domain->devices);
|
||||
|
||||
return domain;
|
||||
|
|
Loading…
Reference in a new issue