Skip to content

Commit

Permalink
drm/i915: Disable WC PTE updates to w/a buggy IOMMU on ILK
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
ickle authored and danvet committed Feb 19, 2013
1 parent 86d3efc commit da88a5f
Showing 1 changed file with 35 additions and 2 deletions.
37 changes: 35 additions & 2 deletions drivers/char/agp/intel-gtt.c
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,40 @@ static void intel_gtt_cleanup(void)
intel_gtt_teardown_scratch_page();
}

/* Certain Gen5 chipsets require require idling the GPU before
* unmapping anything from the GTT when VT-d is enabled.
*/
static inline int needs_ilk_vtd_wa(void)
{
#ifdef CONFIG_INTEL_IOMMU
const unsigned short gpu_devid = intel_private.pcidev->device;

/* Query intel_iommu to see if we need the workaround. Presumably that
* was loaded first.
*/
if ((gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB ||
gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG) &&
intel_iommu_gfx_mapped)
return 1;
#endif
return 0;
}

static bool intel_gtt_can_wc(void)
{
if (INTEL_GTT_GEN <= 2)
return false;

if (INTEL_GTT_GEN >= 6)
return false;

/* Reports of major corruption with ILK vt'd enabled */
if (needs_ilk_vtd_wa())
return false;

return true;
}

static int intel_gtt_init(void)
{
u32 gma_addr;
Expand Down Expand Up @@ -601,7 +635,7 @@ static int intel_gtt_init(void)
gtt_map_size = intel_private.gtt_total_entries * 4;

intel_private.gtt = NULL;
if (INTEL_GTT_GEN < 6 && INTEL_GTT_GEN > 2)
if (intel_gtt_can_wc())
intel_private.gtt = ioremap_wc(intel_private.gtt_bus_addr,
gtt_map_size);
if (intel_private.gtt == NULL)
Expand Down Expand Up @@ -1072,7 +1106,6 @@ static void i965_write_entry(dma_addr_t addr,
writel(addr | pte_flags, intel_private.gtt + entry);
}


static int i9xx_setup(void)
{
u32 reg_addr, gtt_addr;
Expand Down

0 comments on commit da88a5f

Please sign in to comment.