Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b91b09ee authored by Matthew Auld's avatar Matthew Auld Committed by Chris Wilson
Browse files

drm/i915: push set_pages down to the callers



Each backend is now responsible for calling __i915_gem_object_set_pages
upon successfully gathering its backing storage. This eliminates the
inconsistency between the async and sync paths, which stands out even
more when we start throwing around an sg_mask in a later patch.

Suggested-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: default avatarMatthew Auld <matthew.auld@intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
Reviewed-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Link: https://patchwork.freedesktop.org/patch/msgid/20171006145041.21673-6-matthew.auld@intel.com


Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Link: https://patchwork.freedesktop.org/patch/msgid/20171006221833.32439-5-chris@chris-wilson.co.uk
parent 2a9654b2
Loading
Loading
Loading
Loading
+24 −21
Original line number Original line Diff line number Diff line
@@ -162,8 +162,7 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
	return 0;
	return 0;
}
}


static struct sg_table *
static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
{
{
	struct address_space *mapping = obj->base.filp->f_mapping;
	struct address_space *mapping = obj->base.filp->f_mapping;
	drm_dma_handle_t *phys;
	drm_dma_handle_t *phys;
@@ -171,9 +170,10 @@ i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
	struct scatterlist *sg;
	struct scatterlist *sg;
	char *vaddr;
	char *vaddr;
	int i;
	int i;
	int err;


	if (WARN_ON(i915_gem_object_needs_bit17_swizzle(obj)))
	if (WARN_ON(i915_gem_object_needs_bit17_swizzle(obj)))
		return ERR_PTR(-EINVAL);
		return -EINVAL;


	/* Always aligning to the object size, allows a single allocation
	/* Always aligning to the object size, allows a single allocation
	 * to handle all possible callers, and given typical object sizes,
	 * to handle all possible callers, and given typical object sizes,
@@ -183,7 +183,7 @@ i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
			     roundup_pow_of_two(obj->base.size),
			     roundup_pow_of_two(obj->base.size),
			     roundup_pow_of_two(obj->base.size));
			     roundup_pow_of_two(obj->base.size));
	if (!phys)
	if (!phys)
		return ERR_PTR(-ENOMEM);
		return -ENOMEM;


	vaddr = phys->vaddr;
	vaddr = phys->vaddr;
	for (i = 0; i < obj->base.size / PAGE_SIZE; i++) {
	for (i = 0; i < obj->base.size / PAGE_SIZE; i++) {
@@ -192,7 +192,7 @@ i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)


		page = shmem_read_mapping_page(mapping, i);
		page = shmem_read_mapping_page(mapping, i);
		if (IS_ERR(page)) {
		if (IS_ERR(page)) {
			st = ERR_CAST(page);
			err = PTR_ERR(page);
			goto err_phys;
			goto err_phys;
		}
		}


@@ -209,13 +209,13 @@ i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)


	st = kmalloc(sizeof(*st), GFP_KERNEL);
	st = kmalloc(sizeof(*st), GFP_KERNEL);
	if (!st) {
	if (!st) {
		st = ERR_PTR(-ENOMEM);
		err = -ENOMEM;
		goto err_phys;
		goto err_phys;
	}
	}


	if (sg_alloc_table(st, 1, GFP_KERNEL)) {
	if (sg_alloc_table(st, 1, GFP_KERNEL)) {
		kfree(st);
		kfree(st);
		st = ERR_PTR(-ENOMEM);
		err = -ENOMEM;
		goto err_phys;
		goto err_phys;
	}
	}


@@ -227,11 +227,15 @@ i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
	sg_dma_len(sg) = obj->base.size;
	sg_dma_len(sg) = obj->base.size;


	obj->phys_handle = phys;
	obj->phys_handle = phys;
	return st;

	__i915_gem_object_set_pages(obj, st);

	return 0;


err_phys:
err_phys:
	drm_pci_free(obj->base.dev, phys);
	drm_pci_free(obj->base.dev, phys);
	return st;

	return err;
}
}


static void __start_cpu_write(struct drm_i915_gem_object *obj)
static void __start_cpu_write(struct drm_i915_gem_object *obj)
@@ -2292,8 +2296,7 @@ static bool i915_sg_trim(struct sg_table *orig_st)
	return true;
	return true;
}
}


static struct sg_table *
static int i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
{
{
	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
	const unsigned long page_count = obj->base.size / PAGE_SIZE;
	const unsigned long page_count = obj->base.size / PAGE_SIZE;
@@ -2317,12 +2320,12 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)


	st = kmalloc(sizeof(*st), GFP_KERNEL);
	st = kmalloc(sizeof(*st), GFP_KERNEL);
	if (st == NULL)
	if (st == NULL)
		return ERR_PTR(-ENOMEM);
		return -ENOMEM;


rebuild_st:
rebuild_st:
	if (sg_alloc_table(st, page_count, GFP_KERNEL)) {
	if (sg_alloc_table(st, page_count, GFP_KERNEL)) {
		kfree(st);
		kfree(st);
		return ERR_PTR(-ENOMEM);
		return -ENOMEM;
	}
	}


	/* Get the list of pages out of our struct file.  They'll be pinned
	/* Get the list of pages out of our struct file.  They'll be pinned
@@ -2430,7 +2433,9 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
	if (i915_gem_object_needs_bit17_swizzle(obj))
	if (i915_gem_object_needs_bit17_swizzle(obj))
		i915_gem_object_do_bit_17_swizzle(obj, st);
		i915_gem_object_do_bit_17_swizzle(obj, st);


	return st;
	__i915_gem_object_set_pages(obj, st);

	return 0;


err_sg:
err_sg:
	sg_mark_end(sg);
	sg_mark_end(sg);
@@ -2451,7 +2456,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
	if (ret == -ENOSPC)
	if (ret == -ENOSPC)
		ret = -ENOMEM;
		ret = -ENOMEM;


	return ERR_PTR(ret);
	return ret;
}
}


void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
@@ -2474,19 +2479,17 @@ void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,


static int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
static int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
{
{
	struct sg_table *pages;
	int err;


	if (unlikely(obj->mm.madv != I915_MADV_WILLNEED)) {
	if (unlikely(obj->mm.madv != I915_MADV_WILLNEED)) {
		DRM_DEBUG("Attempting to obtain a purgeable object\n");
		DRM_DEBUG("Attempting to obtain a purgeable object\n");
		return -EFAULT;
		return -EFAULT;
	}
	}


	pages = obj->ops->get_pages(obj);
	err = obj->ops->get_pages(obj);
	if (unlikely(IS_ERR(pages)))
	GEM_BUG_ON(!err && IS_ERR_OR_NULL(obj->mm.pages));
		return PTR_ERR(pages);


	__i915_gem_object_set_pages(obj, pages);
	return err;
	return 0;
}
}


/* Ensure that the associated pages are gathered from the backing storage
/* Ensure that the associated pages are gathered from the backing storage
+11 −4
Original line number Original line Diff line number Diff line
@@ -256,11 +256,18 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
	return drm_gem_dmabuf_export(dev, &exp_info);
	return drm_gem_dmabuf_export(dev, &exp_info);
}
}


static struct sg_table *
static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)
i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)
{
{
	return dma_buf_map_attachment(obj->base.import_attach,
	struct sg_table *pages;

	pages = dma_buf_map_attachment(obj->base.import_attach,
				       DMA_BIDIRECTIONAL);
				       DMA_BIDIRECTIONAL);
	if (IS_ERR(pages))
		return PTR_ERR(pages);

	__i915_gem_object_set_pages(obj, pages);

	return 0;
}
}


static void i915_gem_object_put_pages_dmabuf(struct drm_i915_gem_object *obj,
static void i915_gem_object_put_pages_dmabuf(struct drm_i915_gem_object *obj,
+9 −6
Original line number Original line Diff line number Diff line
@@ -44,8 +44,7 @@ static void internal_free_pages(struct sg_table *st)
	kfree(st);
	kfree(st);
}
}


static struct sg_table *
static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
{
{
	struct drm_i915_private *i915 = to_i915(obj->base.dev);
	struct drm_i915_private *i915 = to_i915(obj->base.dev);
	struct sg_table *st;
	struct sg_table *st;
@@ -78,12 +77,12 @@ i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
create_st:
create_st:
	st = kmalloc(sizeof(*st), GFP_KERNEL);
	st = kmalloc(sizeof(*st), GFP_KERNEL);
	if (!st)
	if (!st)
		return ERR_PTR(-ENOMEM);
		return -ENOMEM;


	npages = obj->base.size / PAGE_SIZE;
	npages = obj->base.size / PAGE_SIZE;
	if (sg_alloc_table(st, npages, GFP_KERNEL)) {
	if (sg_alloc_table(st, npages, GFP_KERNEL)) {
		kfree(st);
		kfree(st);
		return ERR_PTR(-ENOMEM);
		return -ENOMEM;
	}
	}


	sg = st->sgl;
	sg = st->sgl;
@@ -132,13 +131,17 @@ i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
	 * object are only valid whilst active and pinned.
	 * object are only valid whilst active and pinned.
	 */
	 */
	obj->mm.madv = I915_MADV_DONTNEED;
	obj->mm.madv = I915_MADV_DONTNEED;
	return st;

	__i915_gem_object_set_pages(obj, st);

	return 0;


err:
err:
	sg_set_page(sg, NULL, 0, 0);
	sg_set_page(sg, NULL, 0, 0);
	sg_mark_end(sg);
	sg_mark_end(sg);
	internal_free_pages(st);
	internal_free_pages(st);
	return ERR_PTR(-ENOMEM);

	return -ENOMEM;
}
}


static void i915_gem_object_put_pages_internal(struct drm_i915_gem_object *obj,
static void i915_gem_object_put_pages_internal(struct drm_i915_gem_object *obj,
+1 −1
Original line number Original line Diff line number Diff line
@@ -69,7 +69,7 @@ struct drm_i915_gem_object_ops {
	 * being released or under memory pressure (where we attempt to
	 * being released or under memory pressure (where we attempt to
	 * reap pages for the shrinker).
	 * reap pages for the shrinker).
	 */
	 */
	struct sg_table *(*get_pages)(struct drm_i915_gem_object *);
	int (*get_pages)(struct drm_i915_gem_object *);
	void (*put_pages)(struct drm_i915_gem_object *, struct sg_table *);
	void (*put_pages)(struct drm_i915_gem_object *, struct sg_table *);


	int (*pwrite)(struct drm_i915_gem_object *,
	int (*pwrite)(struct drm_i915_gem_object *,
+11 −5
Original line number Original line Diff line number Diff line
@@ -539,12 +539,18 @@ i915_pages_create_for_stolen(struct drm_device *dev,
	return st;
	return st;
}
}


static struct sg_table *
static int i915_gem_object_get_pages_stolen(struct drm_i915_gem_object *obj)
i915_gem_object_get_pages_stolen(struct drm_i915_gem_object *obj)
{
{
	return i915_pages_create_for_stolen(obj->base.dev,
	struct sg_table *pages =
		i915_pages_create_for_stolen(obj->base.dev,
					     obj->stolen->start,
					     obj->stolen->start,
					     obj->stolen->size);
					     obj->stolen->size);
	if (IS_ERR(pages))
		return PTR_ERR(pages);

	__i915_gem_object_set_pages(obj, pages);

	return 0;
}
}


static void i915_gem_object_put_pages_stolen(struct drm_i915_gem_object *obj,
static void i915_gem_object_put_pages_stolen(struct drm_i915_gem_object *obj,
Loading