Skip to content

Commit b1012ca

Browse files
LuBaolujoergroedel
authored andcommitted
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 <[email protected]> Tested-by: Koba Ko <[email protected]> Tested-by: Jun Miao <[email protected]> Cc: Ashok Raj <[email protected]> Cc: [email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent 02f3eff commit b1012ca

File tree

4 files changed

+31
-0
lines changed

4 files changed

+31
-0
lines changed

drivers/iommu/intel/dmar.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,7 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
11021102
}
11031103

11041104
drhd->iommu = iommu;
1105+
iommu->drhd = drhd;
11051106

11061107
return 0;
11071108

drivers/iommu/intel/iommu.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ static int intel_iommu_strict;
356356
static int intel_iommu_superpage = 1;
357357
static int iommu_identity_mapping;
358358
static int intel_no_bounce;
359+
static int iommu_skip_te_disable;
359360

360361
#define IDENTMAP_GFX 2
361362
#define IDENTMAP_AZALIA 4
@@ -1633,6 +1634,10 @@ static void iommu_disable_translation(struct intel_iommu *iommu)
16331634
u32 sts;
16341635
unsigned long flag;
16351636

1637+
if (iommu_skip_te_disable && iommu->drhd->gfx_dedicated &&
1638+
(cap_read_drain(iommu->cap) || cap_write_drain(iommu->cap)))
1639+
return;
1640+
16361641
raw_spin_lock_irqsave(&iommu->register_lock, flag);
16371642
iommu->gcmd &= ~DMA_GCMD_TE;
16381643
writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
@@ -4043,6 +4048,7 @@ static void __init init_no_remapping_devices(void)
40434048

40444049
/* This IOMMU has *only* gfx devices. Either bypass it or
40454050
set the gfx_mapped flag, as appropriate */
4051+
drhd->gfx_dedicated = 1;
40464052
if (!dmar_map_gfx) {
40474053
drhd->ignored = 1;
40484054
for_each_active_dev_scope(drhd->devices,
@@ -6170,6 +6176,27 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_g
61706176
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt);
61716177
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt);
61726178

6179+
static void quirk_igfx_skip_te_disable(struct pci_dev *dev)
6180+
{
6181+
unsigned short ver;
6182+
6183+
if (!IS_GFX_DEVICE(dev))
6184+
return;
6185+
6186+
ver = (dev->device >> 8) & 0xff;
6187+
if (ver != 0x45 && ver != 0x46 && ver != 0x4c &&
6188+
ver != 0x4e && ver != 0x8a && ver != 0x98 &&
6189+
ver != 0x9a)
6190+
return;
6191+
6192+
if (risky_device(dev))
6193+
return;
6194+
6195+
pci_info(dev, "Skip IOMMU disabling for graphics\n");
6196+
iommu_skip_te_disable = 1;
6197+
}
6198+
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_igfx_skip_te_disable);
6199+
61736200
/* On Tylersburg chipsets, some BIOSes have been known to enable the
61746201
ISOCH DMAR unit for the Azalia sound device, but not give it any
61756202
TLB entries, which causes it to deadlock. Check for that. We do

include/linux/dmar.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ struct dmar_drhd_unit {
4848
u16 segment; /* PCI domain */
4949
u8 ignored:1; /* ignore drhd */
5050
u8 include_all:1;
51+
u8 gfx_dedicated:1; /* graphic dedicated */
5152
struct intel_iommu *iommu;
5253
};
5354

include/linux/intel-iommu.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,8 @@ struct intel_iommu {
599599
struct iommu_device iommu; /* IOMMU core code handle */
600600
int node;
601601
u32 flags; /* Software defined flags */
602+
603+
struct dmar_drhd_unit *drhd;
602604
};
603605

604606
/* PCI domain-device relationship */

0 commit comments

Comments
 (0)