drm/i915: Set up an MTRR covering the GTT at driver load.
authorEric Anholt <eric@anholt.net>
Fri, 23 Jan 2009 20:57:47 +0000 (12:57 -0800)
committerDave Airlie <airlied@linux.ie>
Sun, 8 Feb 2009 11:37:50 +0000 (21:37 +1000)
We'd love to just be using PAT, but even on chips with PAT it gets disabled
sometimes due to an errata.  It would probably be better to have pat_enabled
exported and only bother with this when !pat_enabled.

Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@linux.ie>
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c

index ee64b7301f6722300bc4362ac5c84010e9355562..1e01e78471558674ba0a702018a7b05d8cc98e91 100644 (file)
@@ -966,10 +966,6 @@ static int i915_load_modeset_init(struct drm_device *dev)
        if (ret)
                goto kfree_devname;
 
-        dev_priv->mm.gtt_mapping =
-               io_mapping_create_wc(dev->agp->base,
-                                    dev->agp->agp_info.aper_size * 1024*1024);
-
        /* Allow hardware batchbuffers unless told otherwise.
         */
        dev_priv->allow_batchbuffer = 1;
@@ -1081,6 +1077,23 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                goto free_priv;
        }
 
+        dev_priv->mm.gtt_mapping =
+               io_mapping_create_wc(dev->agp->base,
+                                    dev->agp->agp_info.aper_size * 1024*1024);
+       /* Set up a WC MTRR for non-PAT systems.  This is more common than
+        * one would think, because the kernel disables PAT on first
+        * generation Core chips because WC PAT gets overridden by a UC
+        * MTRR if present.  Even if a UC MTRR isn't present.
+        */
+       dev_priv->mm.gtt_mtrr = mtrr_add(dev->agp->base,
+                                        dev->agp->agp_info.aper_size *
+                                        1024 * 1024,
+                                        MTRR_TYPE_WRCOMB, 1);
+       if (dev_priv->mm.gtt_mtrr < 0) {
+               DRM_INFO("MTRR allocation failed\n.  Graphics "
+                        "performance may suffer.\n");
+       }
+
 #ifdef CONFIG_HIGHMEM64G
        /* don't enable GEM on PAE - needs agp + set_memory_* interface fixes */
        dev_priv->has_gem = 0;
@@ -1145,8 +1158,14 @@ int i915_driver_unload(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
+       io_mapping_free(dev_priv->mm.gtt_mapping);
+       if (dev_priv->mm.gtt_mtrr >= 0) {
+               mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base,
+                        dev->agp->agp_info.aper_size * 1024 * 1024);
+               dev_priv->mm.gtt_mtrr = -1;
+       }
+
        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-               io_mapping_free(dev_priv->mm.gtt_mapping);
                drm_irq_uninstall(dev);
        }
 
index e1351825200712078b8fe2bf65d238d57435e7b5..f471d218b89ad214f21fa578d71916ff6ce9f242 100644 (file)
@@ -284,6 +284,7 @@ typedef struct drm_i915_private {
                struct drm_mm gtt_space;
 
                struct io_mapping *gtt_mapping;
+               int gtt_mtrr;
 
                /**
                 * List of objects currently involved in rendering from the
index a590d61ff692e2d9ca46edc01e3f6c9b7b7402a4..af8034d525113275621d50bff1260bd8dc22608d 100644 (file)
@@ -3229,10 +3229,6 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
                dev_priv->mm.wedged = 0;
        }
 
-       dev_priv->mm.gtt_mapping = io_mapping_create_wc(dev->agp->base,
-                                                       dev->agp->agp_info.aper_size
-                                                       * 1024 * 1024);
-
        mutex_lock(&dev->struct_mutex);
        dev_priv->mm.suspended = 0;
 
@@ -3255,7 +3251,6 @@ int
 i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
                       struct drm_file *file_priv)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
        int ret;
 
        if (drm_core_check_feature(dev, DRIVER_MODESET))
@@ -3264,7 +3259,6 @@ i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
        ret = i915_gem_idle(dev);
        drm_irq_uninstall(dev);
 
-       io_mapping_free(dev_priv->mm.gtt_mapping);
        return ret;
 }