[137/190] drm/i915: Shrink pages around failure to dma map
diff mbox

Message ID 1452509174-16671-51-git-send-email-chris@chris-wilson.co.uk
State New
Headers show

Commit Message

Chris Wilson Jan. 11, 2016, 10:45 a.m. UTC
Similar to how we handle resource allocation failure of both physical
memory and GGTT mmap space, if we fail to allocate our DMAR remapping,
shrink some of our other objects and try again.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_gem_gtt.c | 35 ++++++++++++++++++++++++++++++-----
 1 file changed, 30 insertions(+), 5 deletions(-)

Patch
diff mbox

diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 3fcf2fd73453..59e7b11bf0ac 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -2313,12 +2313,37 @@  void i915_gem_suspend_gtt_mappings(struct drm_device *dev)
 
 int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj)
 {
-	if (!dma_map_sg(&obj->base.dev->pdev->dev,
-			obj->pages->sgl, obj->pages->nents,
-			PCI_DMA_BIDIRECTIONAL))
-		return -ENOSPC;
+	struct drm_i915_private *i915 = to_i915(obj->base.dev);
+	struct device *dma_device = &obj->base.dev->pdev->dev;
 
-	return 0;
+	if (dma_map_sg(dma_device,
+		       obj->pages->sgl, obj->pages->nents,
+		       PCI_DMA_BIDIRECTIONAL))
+		return 0;
+
+	/* If we fail here, it is likely we couldn't allocate the map, or
+	 * we have exhausted the available DMAR space. First throw out
+	 * objects to make enough rooom for the mapping and try again,
+	 * though this doesn't take fragmentation into account. So if we
+	 * still fail, throw out everything we can and start afresh.
+	 */
+	i915_gem_shrink(i915,
+			obj->base.size >> PAGE_SHIFT,
+			I915_SHRINK_BOUND |
+			I915_SHRINK_UNBOUND |
+			I915_SHRINK_PURGEABLE);
+	if (dma_map_sg(dma_device,
+		       obj->pages->sgl, obj->pages->nents,
+		       PCI_DMA_BIDIRECTIONAL))
+		return 0;
+
+	i915_gem_shrink_all(i915);
+	if (dma_map_sg(dma_device,
+		       obj->pages->sgl, obj->pages->nents,
+		       PCI_DMA_BIDIRECTIONAL))
+		return 0;
+
+	return -ENOSPC;
 }
 
 static void gen8_set_pte(void __iomem *addr, gen8_pte_t pte)