diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/agp/intel-gtt.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 2774ac1086d..66cd0b8096c 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -923,6 +923,9 @@ static int intel_fake_agp_insert_entries(struct agp_memory *mem, { int ret = -EINVAL; + if (intel_private.base.do_idle_maps) + return -ENODEV; + if (intel_private.clear_fake_agp) { int start = intel_private.base.stolen_size / PAGE_SIZE; int end = intel_private.base.gtt_mappable_entries; @@ -985,6 +988,9 @@ static int intel_fake_agp_remove_entries(struct agp_memory *mem, if (mem->page_count == 0) return 0; + if (intel_private.base.do_idle_maps) + return -ENODEV; + intel_gtt_clear_range(pg_start, mem->page_count); if (intel_private.base.needs_dmar) { @@ -1177,6 +1183,25 @@ static void gen6_cleanup(void) { } +/* Certain Gen5 chipsets require require idling the GPU before + * unmapping anything from the GTT when VT-d is enabled. + */ +extern int intel_iommu_gfx_mapped; +static inline int needs_idle_maps(void) +{ + 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; + + return 0; +} + static int i9xx_setup(void) { u32 reg_addr; @@ -1211,6 +1236,9 @@ static int i9xx_setup(void) intel_private.gtt_bus_addr = reg_addr + gtt_offset; } + if (needs_idle_maps()); + intel_private.base.do_idle_maps = 1; + intel_i9xx_setup_flush(); return 0; |