Merge branch 'drm-core-next' of git://people.freedesktop.org/~airlied/linux
[pandora-kernel.git] / drivers / char / agp / intel-gtt.c
index 8515101..66cd0b8 100644 (file)
 /*
  * If we have Intel graphics, we're not going to have anything other than
  * an Intel IOMMU. So make the correct use of the PCI DMA API contingent
- * on the Intel IOMMU support (CONFIG_DMAR).
+ * on the Intel IOMMU support (CONFIG_INTEL_IOMMU).
  * Only newer chipsets need to bother with this, of course.
  */
-#ifdef CONFIG_DMAR
+#ifdef CONFIG_INTEL_IOMMU
 #define USE_PCI_DMA_API 1
 #else
 #define USE_PCI_DMA_API 0
@@ -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;