Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iommu/vt-d: Skip TE disabling on quirky gfx dedicated iommu

The VT-d spec requires (10.4.4 Global Command Register, TE field) that:

Hardware implementations supporting DMA draining must drain any in-flight
DMA read/write requests queued within the Root-Complex before completing
the translation enable command and reflecting the status of the command
through the TES field in the Global Status register.

Unfortunately, some integrated graphic devices fail to do so after some
kind of power state transition. As the result, the system might stuck in
iommu_disable_translation(), waiting for the completion of TE transition.

This provides a quirk list for those devices and skips TE disabling if
the qurik hits.

Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=208363
Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=206571
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
Tested-by: Koba Ko <koba.ko@canonical.com>
Tested-by: Jun Miao <jun.miao@windriver.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20200723013437.2268-1-baolu.lu@linux.intel.com
Signed-off-by: Joerg Roedel <jroedel@suse.de>

authored by

Lu Baolu and committed by
Joerg Roedel
b1012ca8 02f3effd

+31
+1
drivers/iommu/intel/dmar.c
··· 1102 1102 } 1103 1103 1104 1104 drhd->iommu = iommu; 1105 + iommu->drhd = drhd; 1105 1106 1106 1107 return 0; 1107 1108
+27
drivers/iommu/intel/iommu.c
··· 356 356 static int intel_iommu_superpage = 1; 357 357 static int iommu_identity_mapping; 358 358 static int intel_no_bounce; 359 + static int iommu_skip_te_disable; 359 360 360 361 #define IDENTMAP_GFX 2 361 362 #define IDENTMAP_AZALIA 4 ··· 1633 1632 { 1634 1633 u32 sts; 1635 1634 unsigned long flag; 1635 + 1636 + if (iommu_skip_te_disable && iommu->drhd->gfx_dedicated && 1637 + (cap_read_drain(iommu->cap) || cap_write_drain(iommu->cap))) 1638 + return; 1636 1639 1637 1640 raw_spin_lock_irqsave(&iommu->register_lock, flag); 1638 1641 iommu->gcmd &= ~DMA_GCMD_TE; ··· 4048 4043 4049 4044 /* This IOMMU has *only* gfx devices. Either bypass it or 4050 4045 set the gfx_mapped flag, as appropriate */ 4046 + drhd->gfx_dedicated = 1; 4051 4047 if (!dmar_map_gfx) { 4052 4048 drhd->ignored = 1; 4053 4049 for_each_active_dev_scope(drhd->devices, ··· 6175 6169 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_gtt); 6176 6170 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt); 6177 6171 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt); 6172 + 6173 + static void quirk_igfx_skip_te_disable(struct pci_dev *dev) 6174 + { 6175 + unsigned short ver; 6176 + 6177 + if (!IS_GFX_DEVICE(dev)) 6178 + return; 6179 + 6180 + ver = (dev->device >> 8) & 0xff; 6181 + if (ver != 0x45 && ver != 0x46 && ver != 0x4c && 6182 + ver != 0x4e && ver != 0x8a && ver != 0x98 && 6183 + ver != 0x9a) 6184 + return; 6185 + 6186 + if (risky_device(dev)) 6187 + return; 6188 + 6189 + pci_info(dev, "Skip IOMMU disabling for graphics\n"); 6190 + iommu_skip_te_disable = 1; 6191 + } 6192 + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_igfx_skip_te_disable); 6178 6193 6179 6194 /* On Tylersburg chipsets, some BIOSes have been known to enable the 6180 6195 ISOCH DMAR unit for the Azalia sound device, but not give it any
+1
include/linux/dmar.h
··· 48 48 u16 segment; /* PCI domain */ 49 49 u8 ignored:1; /* ignore drhd */ 50 50 u8 include_all:1; 51 + u8 gfx_dedicated:1; /* graphic dedicated */ 51 52 struct intel_iommu *iommu; 52 53 }; 53 54
+2
include/linux/intel-iommu.h
··· 599 599 struct iommu_device iommu; /* IOMMU core code handle */ 600 600 int node; 601 601 u32 flags; /* Software defined flags */ 602 + 603 + struct dmar_drhd_unit *drhd; 602 604 }; 603 605 604 606 /* PCI domain-device relationship */