Commit 5cfacded authored by Chris Wilson's avatar Chris Wilson Committed by Daniel Vetter
Browse files

drm/i915: Pin pages whilst mapping the dma-buf



As we attempt to kmalloc after calling get_pages, there is a possibility
that the shrinker may reap the pages we just acquired. To prevent this
we need to increment the pages_pin_count early, so rearrange the code
and error paths to make it so.

Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarDamien Lespiau <damien.lespiau@intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 1f5d76db
Loading
Loading
Loading
Loading
+22 −19
Original line number Original line Diff line number Diff line
@@ -42,27 +42,24 @@ static struct sg_table *i915_gem_map_dma_buf(struct dma_buf_attachment *attachme


	ret = i915_mutex_lock_interruptible(obj->base.dev);
	ret = i915_mutex_lock_interruptible(obj->base.dev);
	if (ret)
	if (ret)
		return ERR_PTR(ret);
		goto err;


	ret = i915_gem_object_get_pages(obj);
	ret = i915_gem_object_get_pages(obj);
	if (ret) {
	if (ret)
		st = ERR_PTR(ret);
		goto err_unlock;
		goto out;

	}
	i915_gem_object_pin_pages(obj);


	/* Copy sg so that we make an independent mapping */
	/* Copy sg so that we make an independent mapping */
	st = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
	st = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
	if (st == NULL) {
	if (st == NULL) {
		st = ERR_PTR(-ENOMEM);
		ret = -ENOMEM;
		goto out;
		goto err_unpin;
	}
	}


	ret = sg_alloc_table(st, obj->pages->nents, GFP_KERNEL);
	ret = sg_alloc_table(st, obj->pages->nents, GFP_KERNEL);
	if (ret) {
	if (ret)
		kfree(st);
		goto err_free;
		st = ERR_PTR(ret);
		goto out;
	}


	src = obj->pages->sgl;
	src = obj->pages->sgl;
	dst = st->sgl;
	dst = st->sgl;
@@ -73,17 +70,23 @@ static struct sg_table *i915_gem_map_dma_buf(struct dma_buf_attachment *attachme
	}
	}


	if (!dma_map_sg(attachment->dev, st->sgl, st->nents, dir)) {
	if (!dma_map_sg(attachment->dev, st->sgl, st->nents, dir)) {
		sg_free_table(st);
		ret =-ENOMEM;
		kfree(st);
		goto err_free_sg;
		st = ERR_PTR(-ENOMEM);
		goto out;
	}
	}


	i915_gem_object_pin_pages(obj);

out:
	mutex_unlock(&obj->base.dev->struct_mutex);
	mutex_unlock(&obj->base.dev->struct_mutex);
	return st;
	return st;

err_free_sg:
	sg_free_table(st);
err_free:
	kfree(st);
err_unpin:
	i915_gem_object_unpin_pages(obj);
err_unlock:
	mutex_unlock(&obj->base.dev->struct_mutex);
err:
	return ERR_PTR(ret);
}
}


static void i915_gem_unmap_dma_buf(struct dma_buf_attachment *attachment,
static void i915_gem_unmap_dma_buf(struct dma_buf_attachment *attachment,