@@ -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)
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(-)