iommu/vt-d: Enable ATS for the devices in SATC table
Starting from Intel VT-d v3.2, Intel platform BIOS can provide additional SATC table structure. SATC table includes a list of SoC integrated devices that support ATC (Address translation cache). Enabling ATC (via ATS capability) can be a functional requirement for SATC device operation or optional to enhance device performance/functionality. This is determined by the bit of ATC_REQUIRED in SATC table. When IOMMU is working in scalable mode, software chooses to always enable ATS for every device in SATC table because Intel SoC devices in SATC table are trusted to use ATS. On the other hand, if IOMMU is in legacy mode, ATS of SATC capable devices can work transparently to software and be automatically enabled by IOMMU hardware. As the result, there is no need for software to enable ATS on these devices. This also removes dmar_find_matched_atsr_unit() helper as it becomes dead code now. Signed-off-by: Yian Chen <yian.chen@intel.com> Link: https://lore.kernel.org/r/20220222185416.1722611-1-yian.chen@intel.com Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> Link: https://lore.kernel.org/r/20220301020159.633356-13-baolu.lu@linux.intel.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
Родитель
b897a1b7ad
Коммит
97f2f2c531
|
@ -3693,7 +3693,31 @@ static void intel_iommu_free_dmars(void)
|
|||
}
|
||||
}
|
||||
|
||||
int dmar_find_matched_atsr_unit(struct pci_dev *dev)
|
||||
static struct dmar_satc_unit *dmar_find_matched_satc_unit(struct pci_dev *dev)
|
||||
{
|
||||
struct dmar_satc_unit *satcu;
|
||||
struct acpi_dmar_satc *satc;
|
||||
struct device *tmp;
|
||||
int i;
|
||||
|
||||
dev = pci_physfn(dev);
|
||||
rcu_read_lock();
|
||||
|
||||
list_for_each_entry_rcu(satcu, &dmar_satc_units, list) {
|
||||
satc = container_of(satcu->hdr, struct acpi_dmar_satc, header);
|
||||
if (satc->segment != pci_domain_nr(dev->bus))
|
||||
continue;
|
||||
for_each_dev_scope(satcu->devices, satcu->devices_cnt, i, tmp)
|
||||
if (to_pci_dev(tmp) == dev)
|
||||
goto out;
|
||||
}
|
||||
satcu = NULL;
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
return satcu;
|
||||
}
|
||||
|
||||
static int dmar_ats_supported(struct pci_dev *dev, struct intel_iommu *iommu)
|
||||
{
|
||||
int i, ret = 1;
|
||||
struct pci_bus *bus;
|
||||
|
@ -3701,8 +3725,20 @@ int dmar_find_matched_atsr_unit(struct pci_dev *dev)
|
|||
struct device *tmp;
|
||||
struct acpi_dmar_atsr *atsr;
|
||||
struct dmar_atsr_unit *atsru;
|
||||
struct dmar_satc_unit *satcu;
|
||||
|
||||
dev = pci_physfn(dev);
|
||||
satcu = dmar_find_matched_satc_unit(dev);
|
||||
if (satcu)
|
||||
/*
|
||||
* This device supports ATS as it is in SATC table.
|
||||
* When IOMMU is in legacy mode, enabling ATS is done
|
||||
* automatically by HW for the device that requires
|
||||
* ATS, hence OS should not enable this device ATS
|
||||
* to avoid duplicated TLB invalidation.
|
||||
*/
|
||||
return !(satcu->atc_required && !sm_supported(iommu));
|
||||
|
||||
for (bus = dev->bus; bus; bus = bus->parent) {
|
||||
bridge = bus->self;
|
||||
/* If it's an integrated device, allow ATS */
|
||||
|
@ -4550,7 +4586,7 @@ static struct iommu_device *intel_iommu_probe_device(struct device *dev)
|
|||
if (dev_is_pci(dev)) {
|
||||
if (ecap_dev_iotlb_support(iommu->ecap) &&
|
||||
pci_ats_supported(pdev) &&
|
||||
dmar_find_matched_atsr_unit(pdev))
|
||||
dmar_ats_supported(pdev, iommu))
|
||||
info->ats_supported = 1;
|
||||
|
||||
if (sm_supported(iommu)) {
|
||||
|
|
|
@ -693,7 +693,6 @@ static inline int nr_pte_to_next_page(struct dma_pte *pte)
|
|||
}
|
||||
|
||||
extern struct dmar_drhd_unit * dmar_find_matched_drhd_unit(struct pci_dev *dev);
|
||||
extern int dmar_find_matched_atsr_unit(struct pci_dev *dev);
|
||||
|
||||
extern int dmar_enable_qi(struct intel_iommu *iommu);
|
||||
extern void dmar_disable_qi(struct intel_iommu *iommu);
|
||||
|
|
Загрузка…
Ссылка в новой задаче