aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2013-02-13 04:31:53 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-02-19 18:21:49 -0500
commitda88a5f7f7d434e2cde1b3e19d952e6d84533662 (patch)
tree60ae0e971de884cd10e07fbd3452f563cad48924
parent86d3efce2c37d3fb98f75f56f21e6ab75c745bb6 (diff)
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>
-rw-r--r--drivers/char/agp/intel-gtt.c37
1 files changed, 35 insertions, 2 deletions
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c
index 207e5c36e9ec..b8e2014cb9cb 100644
--- a/drivers/char/agp/intel-gtt.c
+++ b/drivers/char/agp/intel-gtt.c
@@ -572,6 +572,40 @@ static void intel_gtt_cleanup(void)
572 intel_gtt_teardown_scratch_page(); 572 intel_gtt_teardown_scratch_page();
573} 573}
574 574
575/* Certain Gen5 chipsets require require idling the GPU before
576 * unmapping anything from the GTT when VT-d is enabled.
577 */
578static 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
594static 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
575static int intel_gtt_init(void) 609static int intel_gtt_init(void)
576{ 610{
577 u32 gma_addr; 611 u32 gma_addr;
@@ -601,7 +635,7 @@ static int intel_gtt_init(void)
601 gtt_map_size = intel_private.gtt_total_entries * 4; 635 gtt_map_size = intel_private.gtt_total_entries * 4;
602 636
603 intel_private.gtt = NULL; 637 intel_private.gtt = NULL;
604 if (INTEL_GTT_GEN < 6 && INTEL_GTT_GEN > 2) 638 if (intel_gtt_can_wc())
605 intel_private.gtt = ioremap_wc(intel_private.gtt_bus_addr, 639 intel_private.gtt = ioremap_wc(intel_private.gtt_bus_addr,
606 gtt_map_size); 640 gtt_map_size);
607 if (intel_private.gtt == NULL) 641 if (intel_private.gtt == NULL)
@@ -1072,7 +1106,6 @@ static void i965_write_entry(dma_addr_t addr,
1072 writel(addr | pte_flags, intel_private.gtt + entry); 1106 writel(addr | pte_flags, intel_private.gtt + entry);
1073} 1107}
1074 1108
1075
1076static int i9xx_setup(void) 1109static int i9xx_setup(void)
1077{ 1110{
1078 u32 reg_addr, gtt_addr; 1111 u32 reg_addr, gtt_addr;