drm/i915: Pin tiled objects for L-shaped configs
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Thu, 20 Nov 2014 08:26:30 +0000 (09:26 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Thu, 20 Nov 2014 12:03:33 +0000 (13:03 +0100)
Let's just throw in the towel on this one and take the cheap way out.

Based on a patch from Chris Wilson, but checking for a different bit.
Chris' patch checked for even bank layout, this one here for a magic
bit. Given the evidence we've gathered (not much) both work I think,
but checking for the magic bit might be more accurate.

Anyway, works on my gm45 here.

For paranoi restrict to gen4 (and mobile), since we've only ever seen
this on gm45 and i965gm.

Also add some debugfs output so that we can skip the tiled swapping
tests properly in these cases.

v2: Clean up the quirk'ed pin count in free_object to avoid upsetting
the WARN_ON. Spotted by Chris.

Cc: Chris Wilson <chris@chris-wilson.co.uk>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=28813
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=45092
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_tiling.c
drivers/gpu/drm/i915/i915_reg.h

index bb1458381dc45d8704f86a950b7d9bc46879feb2..a27b1e47e89c50f85439a19082b5d8db1c3a732f 100644 (file)
@@ -1983,6 +1983,8 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
        if (IS_GEN3(dev) || IS_GEN4(dev)) {
                seq_printf(m, "DDC = 0x%08x\n",
                           I915_READ(DCC));
+               seq_printf(m, "DDC2 = 0x%08x\n",
+                          I915_READ(DCC2));
                seq_printf(m, "C0DRB3 = 0x%04x\n",
                           I915_READ16(C0DRB3));
                seq_printf(m, "C1DRB3 = 0x%04x\n",
@@ -2005,6 +2007,10 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
                seq_printf(m, "DISP_ARB_CTL = 0x%08x\n",
                           I915_READ(DISP_ARB_CTL));
        }
+
+       if (dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES)
+               seq_puts(m, "L-shaped memory detected\n");
+
        intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
 
index 02b3cb32c8a63ad55211f5bd1adeedfe38a38162..5448ce9d1490869cfb594885f13095e8d499077c 100644 (file)
@@ -764,6 +764,7 @@ enum intel_sbi_destination {
 #define QUIRK_INVERT_BRIGHTNESS (1<<2)
 #define QUIRK_BACKLIGHT_PRESENT (1<<3)
 #define QUIRK_PIPEB_FORCE (1<<4)
+#define QUIRK_PIN_SWIZZLED_PAGES (1<<5)
 
 struct intel_fbdev;
 struct intel_fbc_work;
index 480d00e672fa1173c4353a4200c9d9b45fce6484..3c64eb6abf2d71084003ab43b6fb7467ac93cf92 100644 (file)
@@ -2176,6 +2176,10 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
        if (i915_gem_object_needs_bit17_swizzle(obj))
                i915_gem_object_do_bit_17_swizzle(obj);
 
+       if (obj->tiling_mode != I915_TILING_NONE &&
+           dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES)
+               i915_gem_object_pin_pages(obj);
+
        return 0;
 
 err_pages:
@@ -4374,6 +4378,7 @@ int
 i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
                       struct drm_file *file_priv)
 {
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_gem_madvise *args = data;
        struct drm_i915_gem_object *obj;
        int ret;
@@ -4401,6 +4406,15 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
                goto out;
        }
 
+       if (obj->pages &&
+           obj->tiling_mode != I915_TILING_NONE &&
+           dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES) {
+               if (obj->madv == I915_MADV_WILLNEED)
+                       i915_gem_object_unpin_pages(obj);
+               if (args->madv == I915_MADV_WILLNEED)
+                       i915_gem_object_pin_pages(obj);
+       }
+
        if (obj->madv != __I915_MADV_PURGED)
                obj->madv = args->madv;
 
@@ -4550,6 +4564,11 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
 
        WARN_ON(obj->frontbuffer_bits);
 
+       if (obj->pages && obj->madv == I915_MADV_WILLNEED &&
+           dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES &&
+           obj->tiling_mode != I915_TILING_NONE)
+               i915_gem_object_unpin_pages(obj);
+
        if (WARN_ON(obj->pages_pin_count))
                obj->pages_pin_count = 0;
        if (discard_backing_storage(obj))
index cd7f4734c9f8175e8ddebb5e82c75713f52b86c4..4727a4e2c87c98669c03c07a526723b8dcec49a9 100644 (file)
@@ -178,6 +178,15 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
                        }
                        break;
                }
+
+               /* check for L-shaped memory aka modified enhanced addressing */
+               if (IS_GEN4(dev)) {
+                       uint32_t ddc2 = I915_READ(DCC2);
+
+                       if (!(ddc2 & DCC2_MODIFIED_ENHANCED_DISABLE))
+                               dev_priv->quirks |= QUIRK_PIN_SWIZZLED_PAGES;
+               }
+
                if (dcc == 0xffffffff) {
                        DRM_ERROR("Couldn't read from MCHBAR.  "
                                  "Disabling tiling.\n");
@@ -380,6 +389,15 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
                        ret = i915_gem_object_ggtt_unbind(obj);
 
                if (ret == 0) {
+                       if (obj->pages &&
+                           obj->madv == I915_MADV_WILLNEED &&
+                           dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES) {
+                               if (args->tiling_mode == I915_TILING_NONE)
+                                       i915_gem_object_unpin_pages(obj);
+                               if (obj->tiling_mode == I915_TILING_NONE)
+                                       i915_gem_object_pin_pages(obj);
+                       }
+
                        obj->fence_dirty =
                                obj->last_fenced_seqno ||
                                obj->fence_reg != I915_FENCE_REG_NONE;
index 3a51c05ca5522f5bc2442d986fabcb836a6d03fe..3102907a96a7fb4724ba38361568ff36a3368cb1 100644 (file)
@@ -2043,6 +2043,8 @@ enum punit_power_well {
 #define DCC_ADDRESSING_MODE_MASK                       (3 << 0)
 #define DCC_CHANNEL_XOR_DISABLE                                (1 << 10)
 #define DCC_CHANNEL_XOR_BIT_17                         (1 << 9)
+#define DCC2                   0x10204
+#define DCC2_MODIFIED_ENHANCED_DISABLE                 (1 << 20)
 
 /* Pineview MCH register contains DDR3 setting */
 #define CSHRDDR3CTL            0x101a8