SOC-integrated devices on some platforms require their PCI ATS enabled for operation when the IOMMU is in scalable mode. Those devices are reported via ACPI/SATC table with the ATC_REQUIRED bit set in the Flags field.
The PCI subsystem offers the 'pci=noats' kernel command to disable PCI ATS on all devices. Using 'pci=noat' with devices that require PCI ATS can cause a conflict, leading to boot failure, especially if the device is a graphics device.
To prevent this issue, check PCI ATS support before enumerating the IOMMU devices. If any device requires PCI ATS, but PCI ATS is disabled by 'pci=noats', switch the IOMMU to operate in legacy mode to ensure successful booting.
Fixes: 97f2f2c5317f ("iommu/vt-d: Enable ATS for the devices in SATC table") Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12036 Cc: stable@vger.kernel.org Signed-off-by: Lu Baolu baolu.lu@linux.intel.com --- drivers/iommu/intel/iommu.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-)
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 4aa070cf56e7..8f275e046e91 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -3127,10 +3127,26 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info) (void *)satc + satc->header.length, satc->segment, satcu->devices, satcu->devices_cnt); - if (ret > 0) - break; - else if (ret < 0) + if (ret < 0) return ret; + + if (ret > 0) { + /* + * The device requires PCI/ATS when the IOMMU + * works in the scalable mode. If PCI/ATS is + * disabled using the pci=noats kernel parameter, + * the IOMMU will default to legacy mode. Users + * are informed of this change. + */ + if (intel_iommu_sm && satcu->atc_required && + !pci_ats_supported(info->dev)) { + pci_warn(info->dev, + "PCI/ATS not supported, system working in IOMMU legacy mode\n"); + intel_iommu_sm = 0; + } + + break; + } } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) { if (dmar_remove_dev_scope(info, satc->segment, satcu->devices, satcu->devices_cnt))