]> Pileus Git - ~andy/linux/blobdiff - drivers/char/agp/intel-gtt.c
Merge branch 'next' of git://git.infradead.org/users/vkoul/slave-dma
[~andy/linux] / drivers / char / agp / intel-gtt.c
index 2774ac1086d33432436da9c937a82ae14a4441ac..66cd0b8096ca426f9755f958797fb80560770f49 100644 (file)
@@ -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;