Skip to content

Commit 5518f23

Browse files
LuBaolujoergroedel
authored andcommitted
iommu/vt-d: Move scalable mode ATS enablement to probe path
Device ATS is currently enabled when a domain is attached to the device and disabled when the domain is detached. This creates a limitation: when the IOMMU is operating in scalable mode and IOPF is enabled, the device's domain cannot be changed. The previous code enables ATS when a domain is set to a device's RID and disables it during RID domain switch. So, if a PASID is set with a domain requiring PRI, ATS should remain enabled until the domain is removed. During the PASID domain's lifecycle, if the RID's domain changes, PRI will be disrupted because it depends on ATS, which is disabled when the blocking domain is set for the device's RID. Remove this limitation by moving ATS enablement to the device probe path. Signed-off-by: Lu Baolu <[email protected]> Reviewed-by: Kevin Tian <[email protected]> Tested-by: Zhangfei Gao <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent 607ba1b commit 5518f23

File tree

1 file changed

+27
-24
lines changed

1 file changed

+27
-24
lines changed

drivers/iommu/intel/iommu.c

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1173,32 +1173,28 @@ static bool dev_needs_extra_dtlb_flush(struct pci_dev *pdev)
11731173
return true;
11741174
}
11751175

1176-
static void iommu_enable_pci_caps(struct device_domain_info *info)
1176+
static void iommu_enable_pci_ats(struct device_domain_info *info)
11771177
{
11781178
struct pci_dev *pdev;
11791179

1180-
if (!dev_is_pci(info->dev))
1180+
if (!info->ats_supported)
11811181
return;
11821182

11831183
pdev = to_pci_dev(info->dev);
1184-
if (info->ats_supported && pci_ats_page_aligned(pdev) &&
1185-
!pci_enable_ats(pdev, VTD_PAGE_SHIFT))
1184+
if (!pci_ats_page_aligned(pdev))
1185+
return;
1186+
1187+
if (!pci_enable_ats(pdev, VTD_PAGE_SHIFT))
11861188
info->ats_enabled = 1;
11871189
}
11881190

1189-
static void iommu_disable_pci_caps(struct device_domain_info *info)
1191+
static void iommu_disable_pci_ats(struct device_domain_info *info)
11901192
{
1191-
struct pci_dev *pdev;
1192-
1193-
if (!dev_is_pci(info->dev))
1193+
if (!info->ats_enabled)
11941194
return;
11951195

1196-
pdev = to_pci_dev(info->dev);
1197-
1198-
if (info->ats_enabled) {
1199-
pci_disable_ats(pdev);
1200-
info->ats_enabled = 0;
1201-
}
1196+
pci_disable_ats(to_pci_dev(info->dev));
1197+
info->ats_enabled = 0;
12021198
}
12031199

12041200
static void intel_flush_iotlb_all(struct iommu_domain *domain)
@@ -1557,12 +1553,19 @@ domain_context_mapping(struct dmar_domain *domain, struct device *dev)
15571553
struct device_domain_info *info = dev_iommu_priv_get(dev);
15581554
struct intel_iommu *iommu = info->iommu;
15591555
u8 bus = info->bus, devfn = info->devfn;
1556+
int ret;
15601557

15611558
if (!dev_is_pci(dev))
15621559
return domain_context_mapping_one(domain, iommu, bus, devfn);
15631560

1564-
return pci_for_each_dma_alias(to_pci_dev(dev),
1565-
domain_context_mapping_cb, domain);
1561+
ret = pci_for_each_dma_alias(to_pci_dev(dev),
1562+
domain_context_mapping_cb, domain);
1563+
if (ret)
1564+
return ret;
1565+
1566+
iommu_enable_pci_ats(info);
1567+
1568+
return 0;
15661569
}
15671570

15681571
/* Return largest possible superpage level for a given mapping */
@@ -1844,8 +1847,6 @@ static int dmar_domain_attach_device(struct dmar_domain *domain,
18441847
if (ret)
18451848
goto out_block_translation;
18461849

1847-
iommu_enable_pci_caps(info);
1848-
18491850
ret = cache_tag_assign_domain(domain, dev, IOMMU_NO_PASID);
18501851
if (ret)
18511852
goto out_block_translation;
@@ -3202,6 +3203,7 @@ static void domain_context_clear(struct device_domain_info *info)
32023203

32033204
pci_for_each_dma_alias(to_pci_dev(info->dev),
32043205
&domain_context_clear_one_cb, info);
3206+
iommu_disable_pci_ats(info);
32053207
}
32063208

32073209
/*
@@ -3218,7 +3220,6 @@ void device_block_translation(struct device *dev)
32183220
if (info->domain)
32193221
cache_tag_unassign_domain(info->domain, dev, IOMMU_NO_PASID);
32203222

3221-
iommu_disable_pci_caps(info);
32223223
if (!dev_is_real_dma_subdevice(dev)) {
32233224
if (sm_supported(iommu))
32243225
intel_pasid_tear_down_entry(iommu, dev,
@@ -3753,6 +3754,9 @@ static struct iommu_device *intel_iommu_probe_device(struct device *dev)
37533754
!pci_enable_pasid(pdev, info->pasid_supported & ~1))
37543755
info->pasid_enabled = 1;
37553756

3757+
if (sm_supported(iommu))
3758+
iommu_enable_pci_ats(info);
3759+
37563760
return &iommu->iommu;
37573761
free_table:
37583762
intel_pasid_free_table(dev);
@@ -3769,6 +3773,8 @@ static void intel_iommu_release_device(struct device *dev)
37693773
struct device_domain_info *info = dev_iommu_priv_get(dev);
37703774
struct intel_iommu *iommu = info->iommu;
37713775

3776+
iommu_disable_pci_ats(info);
3777+
37723778
if (info->pasid_enabled) {
37733779
pci_disable_pasid(to_pci_dev(dev));
37743780
info->pasid_enabled = 0;
@@ -4375,13 +4381,10 @@ static int identity_domain_attach_dev(struct iommu_domain *domain, struct device
43754381
if (dev_is_real_dma_subdevice(dev))
43764382
return 0;
43774383

4378-
if (sm_supported(iommu)) {
4384+
if (sm_supported(iommu))
43794385
ret = intel_pasid_setup_pass_through(iommu, dev, IOMMU_NO_PASID);
4380-
if (!ret)
4381-
iommu_enable_pci_caps(info);
4382-
} else {
4386+
else
43834387
ret = device_setup_pass_through(dev);
4384-
}
43854388

43864389
return ret;
43874390
}

0 commit comments

Comments
 (0)