Merge tag 'drm-intel-fixes-2015-07-15' into drm-intel-next-queued
[linux-drm-fsl-dcu.git] / drivers / gpu / drm / i915 / i915_gem_stolen.c
index 8b5b784c62fea276fc9bc947a85734f75f81a9eb..ed682a9a9cbba2a0d79af9369a3761e39d6b5e1c 100644 (file)
  * for is a boon.
  */
 
+int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv,
+                               struct drm_mm_node *node, u64 size,
+                               unsigned alignment)
+{
+       int ret;
+
+       if (!drm_mm_initialized(&dev_priv->mm.stolen))
+               return -ENODEV;
+
+       mutex_lock(&dev_priv->mm.stolen_lock);
+       ret = drm_mm_insert_node(&dev_priv->mm.stolen, node, size, alignment,
+                                DRM_MM_SEARCH_DEFAULT);
+       mutex_unlock(&dev_priv->mm.stolen_lock);
+
+       return ret;
+}
+
+void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv,
+                                struct drm_mm_node *node)
+{
+       mutex_lock(&dev_priv->mm.stolen_lock);
+       drm_mm_remove_node(node);
+       mutex_unlock(&dev_priv->mm.stolen_lock);
+}
+
 static unsigned long i915_stolen_to_physical(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -151,134 +176,6 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
        return base;
 }
 
-static int find_compression_threshold(struct drm_device *dev,
-                                     struct drm_mm_node *node,
-                                     int size,
-                                     int fb_cpp)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int compression_threshold = 1;
-       int ret;
-
-       /* HACK: This code depends on what we will do in *_enable_fbc. If that
-        * code changes, this code needs to change as well.
-        *
-        * The enable_fbc code will attempt to use one of our 2 compression
-        * thresholds, therefore, in that case, we only have 1 resort.
-        */
-
-       /* Try to over-allocate to reduce reallocations and fragmentation. */
-       ret = drm_mm_insert_node(&dev_priv->mm.stolen, node,
-                                size <<= 1, 4096, DRM_MM_SEARCH_DEFAULT);
-       if (ret == 0)
-               return compression_threshold;
-
-again:
-       /* HW's ability to limit the CFB is 1:4 */
-       if (compression_threshold > 4 ||
-           (fb_cpp == 2 && compression_threshold == 2))
-               return 0;
-
-       ret = drm_mm_insert_node(&dev_priv->mm.stolen, node,
-                                size >>= 1, 4096,
-                                DRM_MM_SEARCH_DEFAULT);
-       if (ret && INTEL_INFO(dev)->gen <= 4) {
-               return 0;
-       } else if (ret) {
-               compression_threshold <<= 1;
-               goto again;
-       } else {
-               return compression_threshold;
-       }
-}
-
-static int i915_setup_compression(struct drm_device *dev, int size, int fb_cpp)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_mm_node *uninitialized_var(compressed_llb);
-       int ret;
-
-       ret = find_compression_threshold(dev, &dev_priv->fbc.compressed_fb,
-                                        size, fb_cpp);
-       if (!ret)
-               goto err_llb;
-       else if (ret > 1) {
-               DRM_INFO("Reducing the compressed framebuffer size. This may lead to less power savings than a non-reduced-size. Try to increase stolen memory size if available in BIOS.\n");
-
-       }
-
-       dev_priv->fbc.threshold = ret;
-
-       if (INTEL_INFO(dev_priv)->gen >= 5)
-               I915_WRITE(ILK_DPFC_CB_BASE, dev_priv->fbc.compressed_fb.start);
-       else if (IS_GM45(dev)) {
-               I915_WRITE(DPFC_CB_BASE, dev_priv->fbc.compressed_fb.start);
-       } else {
-               compressed_llb = kzalloc(sizeof(*compressed_llb), GFP_KERNEL);
-               if (!compressed_llb)
-                       goto err_fb;
-
-               ret = drm_mm_insert_node(&dev_priv->mm.stolen, compressed_llb,
-                                        4096, 4096, DRM_MM_SEARCH_DEFAULT);
-               if (ret)
-                       goto err_fb;
-
-               dev_priv->fbc.compressed_llb = compressed_llb;
-
-               I915_WRITE(FBC_CFB_BASE,
-                          dev_priv->mm.stolen_base + dev_priv->fbc.compressed_fb.start);
-               I915_WRITE(FBC_LL_BASE,
-                          dev_priv->mm.stolen_base + compressed_llb->start);
-       }
-
-       dev_priv->fbc.uncompressed_size = size;
-
-       DRM_DEBUG_KMS("reserved %d bytes of contiguous stolen space for FBC\n",
-                     size);
-
-       return 0;
-
-err_fb:
-       kfree(compressed_llb);
-       drm_mm_remove_node(&dev_priv->fbc.compressed_fb);
-err_llb:
-       pr_info_once("drm: not enough stolen space for compressed buffer (need %d more bytes), disabling. Hint: you may be able to increase stolen memory size in the BIOS to avoid this.\n", size);
-       return -ENOSPC;
-}
-
-int i915_gem_stolen_setup_compression(struct drm_device *dev, int size, int fb_cpp)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       if (!drm_mm_initialized(&dev_priv->mm.stolen))
-               return -ENODEV;
-
-       if (size <= dev_priv->fbc.uncompressed_size)
-               return 0;
-
-       /* Release any current block */
-       i915_gem_stolen_cleanup_compression(dev);
-
-       return i915_setup_compression(dev, size, fb_cpp);
-}
-
-void i915_gem_stolen_cleanup_compression(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       if (dev_priv->fbc.uncompressed_size == 0)
-               return;
-
-       drm_mm_remove_node(&dev_priv->fbc.compressed_fb);
-
-       if (dev_priv->fbc.compressed_llb) {
-               drm_mm_remove_node(dev_priv->fbc.compressed_llb);
-               kfree(dev_priv->fbc.compressed_llb);
-       }
-
-       dev_priv->fbc.uncompressed_size = 0;
-}
-
 void i915_gem_cleanup_stolen(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -286,7 +183,6 @@ void i915_gem_cleanup_stolen(struct drm_device *dev)
        if (!drm_mm_initialized(&dev_priv->mm.stolen))
                return;
 
-       i915_gem_stolen_cleanup_compression(dev);
        drm_mm_takedown(&dev_priv->mm.stolen);
 }
 
@@ -296,6 +192,8 @@ int i915_gem_init_stolen(struct drm_device *dev)
        u32 tmp;
        int bios_reserved = 0;
 
+       mutex_init(&dev_priv->mm.stolen_lock);
+
 #ifdef CONFIG_INTEL_IOMMU
        if (intel_iommu_gfx_mapped && INTEL_INFO(dev)->gen < 8) {
                DRM_INFO("DMAR active, disabling use of stolen memory\n");
@@ -386,8 +284,10 @@ static void i915_gem_object_put_pages_stolen(struct drm_i915_gem_object *obj)
 static void
 i915_gem_object_release_stolen(struct drm_i915_gem_object *obj)
 {
+       struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
+
        if (obj->stolen) {
-               drm_mm_remove_node(obj->stolen);
+               i915_gem_stolen_remove_node(dev_priv, obj->stolen);
                kfree(obj->stolen);
                obj->stolen = NULL;
        }
@@ -448,8 +348,7 @@ i915_gem_object_create_stolen(struct drm_device *dev, u32 size)
        if (!stolen)
                return NULL;
 
-       ret = drm_mm_insert_node(&dev_priv->mm.stolen, stolen, size,
-                                4096, DRM_MM_SEARCH_DEFAULT);
+       ret = i915_gem_stolen_insert_node(dev_priv, stolen, size, 4096);
        if (ret) {
                kfree(stolen);
                return NULL;
@@ -459,7 +358,7 @@ i915_gem_object_create_stolen(struct drm_device *dev, u32 size)
        if (obj)
                return obj;
 
-       drm_mm_remove_node(stolen);
+       i915_gem_stolen_remove_node(dev_priv, stolen);
        kfree(stolen);
        return NULL;
 }
@@ -494,7 +393,9 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
 
        stolen->start = stolen_offset;
        stolen->size = size;
+       mutex_lock(&dev_priv->mm.stolen_lock);
        ret = drm_mm_reserve_node(&dev_priv->mm.stolen, stolen);
+       mutex_unlock(&dev_priv->mm.stolen_lock);
        if (ret) {
                DRM_DEBUG_KMS("failed to allocate stolen space\n");
                kfree(stolen);
@@ -504,7 +405,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
        obj = _i915_gem_object_create_stolen(dev, stolen);
        if (obj == NULL) {
                DRM_DEBUG_KMS("failed to allocate stolen object\n");
-               drm_mm_remove_node(stolen);
+               i915_gem_stolen_remove_node(dev_priv, stolen);
                kfree(stolen);
                return NULL;
        }
@@ -545,7 +446,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
 err_vma:
        i915_gem_vma_destroy(vma);
 err_out:
-       drm_mm_remove_node(stolen);
+       i915_gem_stolen_remove_node(dev_priv, stolen);
        kfree(stolen);
        drm_gem_object_unreference(&obj->base);
        return NULL;