Merge branch 'core' of git://git.kernel.org/pub/scm/linux/kernel/git/rric/oprofile...
[safe/jmp/linux-2.6] / drivers / gpu / drm / i915 / i915_gem_tiling.c
index e774a4a..4bdccef 100644 (file)
@@ -25,8 +25,6 @@
  *
  */
 
-#include <linux/acpi.h>
-#include <linux/pnp.h>
 #include "linux/string.h"
 #include "linux/bitops.h"
 #include "drmP.h"
  * to match what the GPU expects.
  */
 
-#define MCHBAR_I915 0x44
-#define MCHBAR_I965 0x48
-#define MCHBAR_SIZE (4*4096)
-
-#define DEVEN_REG 0x54
-#define   DEVEN_MCHBAR_EN (1 << 28)
-
-/* Allocate space for the MCH regs if needed, return nonzero on error */
-static int
-intel_alloc_mchbar_resource(struct drm_device *dev)
-{
-       struct pci_dev *bridge_dev;
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       int reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
-       u32 temp_lo, temp_hi = 0;
-       u64 mchbar_addr;
-       int ret = 0;
-
-       bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
-       if (!bridge_dev) {
-               DRM_DEBUG("no bridge dev?!\n");
-               ret = -ENODEV;
-               goto out;
-       }
-
-       if (IS_I965G(dev))
-               pci_read_config_dword(bridge_dev, reg + 4, &temp_hi);
-       pci_read_config_dword(bridge_dev, reg, &temp_lo);
-       mchbar_addr = ((u64)temp_hi << 32) | temp_lo;
-
-       /* If ACPI doesn't have it, assume we need to allocate it ourselves */
-#ifdef CONFIG_PNP
-       if (mchbar_addr &&
-           pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) {
-               ret = 0;
-               goto out_put;
-       }
-#endif
-
-       /* Get some space for it */
-       ret = pci_bus_alloc_resource(bridge_dev->bus, &dev_priv->mch_res,
-                                    MCHBAR_SIZE, MCHBAR_SIZE,
-                                    PCIBIOS_MIN_MEM,
-                                    0,   pcibios_align_resource,
-                                    bridge_dev);
-       if (ret) {
-               DRM_DEBUG("failed bus alloc: %d\n", ret);
-               dev_priv->mch_res.start = 0;
-               goto out_put;
-       }
-
-       if (IS_I965G(dev))
-               pci_write_config_dword(bridge_dev, reg + 4,
-                                      upper_32_bits(dev_priv->mch_res.start));
-
-       pci_write_config_dword(bridge_dev, reg,
-                              lower_32_bits(dev_priv->mch_res.start));
-out_put:
-       pci_dev_put(bridge_dev);
-out:
-       return ret;
-}
-
-/* Setup MCHBAR if possible, return true if we should disable it again */
-static bool
-intel_setup_mchbar(struct drm_device *dev)
-{
-       struct pci_dev *bridge_dev;
-       int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
-       u32 temp;
-       bool need_disable = false, enabled;
-
-       bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
-       if (!bridge_dev) {
-               DRM_DEBUG("no bridge dev?!\n");
-               goto out;
-       }
-
-       if (IS_I915G(dev) || IS_I915GM(dev)) {
-               pci_read_config_dword(bridge_dev, DEVEN_REG, &temp);
-               enabled = !!(temp & DEVEN_MCHBAR_EN);
-       } else {
-               pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
-               enabled = temp & 1;
-       }
-
-       /* If it's already enabled, don't have to do anything */
-       if (enabled)
-               goto out_put;
-
-       if (intel_alloc_mchbar_resource(dev))
-               goto out_put;
-
-       need_disable = true;
-
-       /* Space is allocated or reserved, so enable it. */
-       if (IS_I915G(dev) || IS_I915GM(dev)) {
-               pci_write_config_dword(bridge_dev, DEVEN_REG,
-                                      temp | DEVEN_MCHBAR_EN);
-       } else {
-               pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
-               pci_write_config_dword(bridge_dev, mchbar_reg, temp | 1);
-       }
-out_put:
-       pci_dev_put(bridge_dev);
-out:
-       return need_disable;
-}
-
-static void
-intel_teardown_mchbar(struct drm_device *dev, bool disable)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       struct pci_dev *bridge_dev;
-       int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
-       u32 temp;
-
-       bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
-       if (!bridge_dev) {
-               DRM_DEBUG("no bridge dev?!\n");
-               return;
-       }
-
-       if (disable) {
-               if (IS_I915G(dev) || IS_I915GM(dev)) {
-                       pci_read_config_dword(bridge_dev, DEVEN_REG, &temp);
-                       temp &= ~DEVEN_MCHBAR_EN;
-                       pci_write_config_dword(bridge_dev, DEVEN_REG, temp);
-               } else {
-                       pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
-                       temp &= ~1;
-                       pci_write_config_dword(bridge_dev, mchbar_reg, temp);
-               }
-       }
-
-       if (dev_priv->mch_res.start)
-               release_resource(&dev_priv->mch_res);
-}
-
 /**
  * Detects bit 6 swizzling of address lookup between IGD access and CPU
  * access through main memory.
@@ -232,10 +91,9 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
        uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
        uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
-       bool need_disable;
 
-       if (IS_IGDNG(dev)) {
-               /* On IGDNG whatever DRAM config, GPU always do
+       if (IS_IRONLAKE(dev) || IS_GEN6(dev)) {
+               /* On Ironlake whatever DRAM config, GPU always do
                 * same swizzling setup.
                 */
                swizzle_x = I915_BIT_6_SWIZZLE_9_10;
@@ -249,9 +107,6 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
        } else if (IS_MOBILE(dev)) {
                uint32_t dcc;
 
-               /* Try to make sure MCHBAR is enabled before poking at it */
-               need_disable = intel_setup_mchbar(dev);
-
                /* On mobile 9xx chipsets, channel interleave by the CPU is
                 * determined by DCC.  For single-channel, neither the CPU
                 * nor the GPU do swizzling.  For dual channel interleaved,
@@ -291,8 +146,6 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
                        swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
                        swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
                }
-
-               intel_teardown_mchbar(dev, need_disable);
        } else {
                /* The 965, G33, and newer, have a very flexible memory
                 * configuration.  It will enable dual-channel mode
@@ -327,37 +180,8 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
        dev_priv->mm.bit_6_swizzle_y = swizzle_y;
 }
 
-
-/**
- * Returns the size of the fence for a tiled object of the given size.
- */
-static int
-i915_get_fence_size(struct drm_device *dev, int size)
-{
-       int i;
-       int start;
-
-       if (IS_I965G(dev)) {
-               /* The 965 can have fences at any page boundary. */
-               return ALIGN(size, 4096);
-       } else {
-               /* Align the size to a power of two greater than the smallest
-                * fence size.
-                */
-               if (IS_I9XX(dev))
-                       start = 1024 * 1024;
-               else
-                       start = 512 * 1024;
-
-               for (i = start; i < size; i <<= 1)
-                       ;
-
-               return i;
-       }
-}
-
 /* Check pitch constriants for all chips & tiling formats */
-static bool
+bool
 i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
 {
        int tile_width;
@@ -378,21 +202,17 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
                 * reg, so dont bother to check the size */
                if (stride / 128 > I965_FENCE_MAX_PITCH_VAL)
                        return false;
-       } else if (IS_I9XX(dev)) {
-               uint32_t pitch_val = ffs(stride / tile_width) - 1;
-
-               /* XXX: For Y tiling, FENCE_MAX_PITCH_VAL is actually 6 (8KB)
-                * instead of 4 (2KB) on 945s.
-                */
-               if (pitch_val > I915_FENCE_MAX_PITCH_VAL ||
-                   size > (I830_FENCE_MAX_SIZE_VAL << 20))
+       } else if (IS_GEN3(dev) || IS_GEN2(dev)) {
+               if (stride > 8192)
                        return false;
-       } else {
-               uint32_t pitch_val = ffs(stride / tile_width) - 1;
 
-               if (pitch_val > I830_FENCE_MAX_PITCH_VAL ||
-                   size > (I830_FENCE_MAX_SIZE_VAL << 19))
-                       return false;
+               if (IS_GEN3(dev)) {
+                       if (size > I830_FENCE_MAX_SIZE_VAL << 20)
+                               return false;
+               } else {
+                       if (size > I830_FENCE_MAX_SIZE_VAL << 19)
+                               return false;
+               }
        }
 
        /* 965+ just needs multiples of tile width */
@@ -409,20 +229,14 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
        if (stride & (stride - 1))
                return false;
 
-       /* We don't 0handle the aperture area covered by the fence being bigger
-        * than the object size.
-        */
-       if (i915_get_fence_size(dev, size) != size)
-               return false;
-
        return true;
 }
 
-static bool
+bool
 i915_gem_object_fence_offset_ok(struct drm_gem_object *obj, int tiling_mode)
 {
        struct drm_device *dev = obj->dev;
-       struct drm_i915_gem_object *obj_priv = obj->driver_private;
+       struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 
        if (obj_priv->gtt_space == NULL)
                return true;
@@ -462,12 +276,10 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
        obj = drm_gem_object_lookup(dev, file_priv, args->handle);
        if (obj == NULL)
                return -EINVAL;
-       obj_priv = obj->driver_private;
+       obj_priv = to_intel_bo(obj);
 
        if (!i915_tiling_ok(dev, args->stride, obj->size, args->tiling_mode)) {
-               mutex_lock(&dev->struct_mutex);
-               drm_gem_object_unreference(obj);
-               mutex_unlock(&dev->struct_mutex);
+               drm_gem_object_unreference_unlocked(obj);
                return -EINVAL;
        }
 
@@ -509,9 +321,12 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
                 * need to ensure that any fence register is cleared.
                 */
                if (!i915_gem_object_fence_offset_ok(obj, args->tiling_mode))
-                   ret = i915_gem_object_unbind(obj);
+                       ret = i915_gem_object_unbind(obj);
+               else if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
+                       ret = i915_gem_object_put_fence_reg(obj);
                else
-                   ret = i915_gem_object_put_fence_reg(obj);
+                       i915_gem_release_mmap(obj);
+
                if (ret != 0) {
                        WARN(ret != -ERESTARTSYS,
                             "failed to reset object for tiling switch");
@@ -520,12 +335,6 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
                        goto err;
                }
 
-               /* If we've changed tiling, GTT-mappings of the object
-                * need to re-fault to ensure that the correct fence register
-                * setup is in place.
-                */
-               i915_gem_release_mmap(obj);
-
                obj_priv->tiling_mode = args->tiling_mode;
                obj_priv->stride = args->stride;
        }
@@ -551,7 +360,7 @@ i915_gem_get_tiling(struct drm_device *dev, void *data,
        obj = drm_gem_object_lookup(dev, file_priv, args->handle);
        if (obj == NULL)
                return -EINVAL;
-       obj_priv = obj->driver_private;
+       obj_priv = to_intel_bo(obj);
 
        mutex_lock(&dev->struct_mutex);
 
@@ -614,7 +423,7 @@ i915_gem_object_do_bit_17_swizzle(struct drm_gem_object *obj)
 {
        struct drm_device *dev = obj->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_i915_gem_object *obj_priv = obj->driver_private;
+       struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
        int page_count = obj->size >> PAGE_SHIFT;
        int i;
 
@@ -643,7 +452,7 @@ i915_gem_object_save_bit_17_swizzle(struct drm_gem_object *obj)
 {
        struct drm_device *dev = obj->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_i915_gem_object *obj_priv = obj->driver_private;
+       struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
        int page_count = obj->size >> PAGE_SHIFT;
        int i;