mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-16 16:54:20 +08:00
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
@ -391,6 +391,7 @@ struct dmar_domain {
|
|||||||
* domain ids are 16 bit wide according
|
* domain ids are 16 bit wide according
|
||||||
* to VT-d spec, section 9.3 */
|
* to VT-d spec, section 9.3 */
|
||||||
|
|
||||||
|
bool has_iotlb_device;
|
||||||
struct list_head devices; /* all devices' list */
|
struct list_head devices; /* all devices' list */
|
||||||
struct iova_domain iovad; /* iova's that belong to this domain */
|
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;
|
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)
|
static void iommu_enable_dev_iotlb(struct device_domain_info *info)
|
||||||
{
|
{
|
||||||
struct pci_dev *pdev;
|
struct pci_dev *pdev;
|
||||||
|
|
||||||
|
assert_spin_locked(&device_domain_lock);
|
||||||
|
|
||||||
if (!info || !dev_is_pci(info->dev))
|
if (!info || !dev_is_pci(info->dev))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1487,6 +1513,7 @@ static void iommu_enable_dev_iotlb(struct device_domain_info *info)
|
|||||||
#endif
|
#endif
|
||||||
if (info->ats_supported && !pci_enable_ats(pdev, VTD_PAGE_SHIFT)) {
|
if (info->ats_supported && !pci_enable_ats(pdev, VTD_PAGE_SHIFT)) {
|
||||||
info->ats_enabled = 1;
|
info->ats_enabled = 1;
|
||||||
|
domain_update_iotlb(info->domain);
|
||||||
info->ats_qdep = pci_ats_queue_depth(pdev);
|
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;
|
struct pci_dev *pdev;
|
||||||
|
|
||||||
|
assert_spin_locked(&device_domain_lock);
|
||||||
|
|
||||||
if (!dev_is_pci(info->dev))
|
if (!dev_is_pci(info->dev))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1503,6 +1532,7 @@ static void iommu_disable_dev_iotlb(struct device_domain_info *info)
|
|||||||
if (info->ats_enabled) {
|
if (info->ats_enabled) {
|
||||||
pci_disable_ats(pdev);
|
pci_disable_ats(pdev);
|
||||||
info->ats_enabled = 0;
|
info->ats_enabled = 0;
|
||||||
|
domain_update_iotlb(info->domain);
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_INTEL_IOMMU_SVM
|
#ifdef CONFIG_INTEL_IOMMU_SVM
|
||||||
if (info->pri_enabled) {
|
if (info->pri_enabled) {
|
||||||
@ -1523,6 +1553,9 @@ static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
|
|||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct device_domain_info *info;
|
struct device_domain_info *info;
|
||||||
|
|
||||||
|
if (!domain->has_iotlb_device)
|
||||||
|
return;
|
||||||
|
|
||||||
spin_lock_irqsave(&device_domain_lock, flags);
|
spin_lock_irqsave(&device_domain_lock, flags);
|
||||||
list_for_each_entry(info, &domain->devices, link) {
|
list_for_each_entry(info, &domain->devices, link) {
|
||||||
if (!info->ats_enabled)
|
if (!info->ats_enabled)
|
||||||
@ -1740,6 +1773,7 @@ static struct dmar_domain *alloc_domain(int flags)
|
|||||||
memset(domain, 0, sizeof(*domain));
|
memset(domain, 0, sizeof(*domain));
|
||||||
domain->nid = -1;
|
domain->nid = -1;
|
||||||
domain->flags = flags;
|
domain->flags = flags;
|
||||||
|
domain->has_iotlb_device = false;
|
||||||
INIT_LIST_HEAD(&domain->devices);
|
INIT_LIST_HEAD(&domain->devices);
|
||||||
|
|
||||||
return domain;
|
return domain;
|
||||||
|
Loading…
Reference in New Issue
Block a user