X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=drivers%2Fgpu%2Fdrm%2Fi915%2Fi915_gem_stolen.c;h=ed682a9a9cbba2a0d79af9369a3761e39d6b5e1c;hb=ca6e4405779ed56ebac941570615abd667c72c02;hp=8b5b784c62fea276fc9bc947a85734f75f81a9eb;hpb=ccfb8b2ed4d4e12c3c35de3db5fbbbaa11277736;p=firefly-linux-kernel-4.4.55.git diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index 8b5b784c62fe..ed682a9a9cbb 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -42,6 +42,31 @@ * 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;