Skip to content

Commit da88a5f

Browse files
ickledanvet
authored andcommitted
drm/i915: Disable WC PTE updates to w/a buggy IOMMU on ILK
Whilst IOMMU is enabled for the Intel GPU on Ironlake, it appears that using WC writes to update the PTE on the GPU fails miserably. The result looks like the majority of the writes do not land leading to lots of screen corruption and a hard system hang. v2: s/</<=/ to preserve the current exclusion of Sandybridge Reported-by: Nathan Myers <ncm@cantrip.org> Bugzilla: https://bugzilla.freedesktop.org/show_bug.cgi?id=60391 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Tested-by: Nathan Myers <ncm@cantrip.org> [danvet: Remove cc: stable and add tested-by.] Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
1 parent 86d3efc commit da88a5f

File tree

1 file changed

+35
-2
lines changed

1 file changed

+35
-2
lines changed

drivers/char/agp/intel-gtt.c

+35-2
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,40 @@ static void intel_gtt_cleanup(void)
572572
intel_gtt_teardown_scratch_page();
573573
}
574574

575+
/* Certain Gen5 chipsets require require idling the GPU before
576+
* unmapping anything from the GTT when VT-d is enabled.
577+
*/
578+
static inline int needs_ilk_vtd_wa(void)
579+
{
580+
#ifdef CONFIG_INTEL_IOMMU
581+
const unsigned short gpu_devid = intel_private.pcidev->device;
582+
583+
/* Query intel_iommu to see if we need the workaround. Presumably that
584+
* was loaded first.
585+
*/
586+
if ((gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB ||
587+
gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG) &&
588+
intel_iommu_gfx_mapped)
589+
return 1;
590+
#endif
591+
return 0;
592+
}
593+
594+
static bool intel_gtt_can_wc(void)
595+
{
596+
if (INTEL_GTT_GEN <= 2)
597+
return false;
598+
599+
if (INTEL_GTT_GEN >= 6)
600+
return false;
601+
602+
/* Reports of major corruption with ILK vt'd enabled */
603+
if (needs_ilk_vtd_wa())
604+
return false;
605+
606+
return true;
607+
}
608+
575609
static int intel_gtt_init(void)
576610
{
577611
u32 gma_addr;
@@ -601,7 +635,7 @@ static int intel_gtt_init(void)
601635
gtt_map_size = intel_private.gtt_total_entries * 4;
602636

603637
intel_private.gtt = NULL;
604-
if (INTEL_GTT_GEN < 6 && INTEL_GTT_GEN > 2)
638+
if (intel_gtt_can_wc())
605639
intel_private.gtt = ioremap_wc(intel_private.gtt_bus_addr,
606640
gtt_map_size);
607641
if (intel_private.gtt == NULL)
@@ -1072,7 +1106,6 @@ static void i965_write_entry(dma_addr_t addr,
10721106
writel(addr | pte_flags, intel_private.gtt + entry);
10731107
}
10741108

1075-
10761109
static int i9xx_setup(void)
10771110
{
10781111
u32 reg_addr, gtt_addr;

0 commit comments

Comments
 (0)