diff options
author | Daniel Vetter | 2012-05-10 15:25:09 +0200 |
---|---|---|
committer | Dave Airlie | 2012-05-23 10:47:10 +0100 |
commit | 1286ff7397737e407cdd8e5cd574318db177ba1f (patch) | |
tree | d83344e3beba60c8ec8bec566bd8f58a08f696ef /drivers/gpu/drm/i915/i915_gem.c | |
parent | 22b33e8ed0e38b8ddcf082e35580f2e67a3a0262 (diff) |
i915: add dmabuf/prime buffer sharing support.
This adds handle->fd and fd->handle support to i915, this is to allow
for offloading of rendering in one direction and outputs in the other.
v2 from Daniel Vetter:
- fixup conflicts with the prepare/finish gtt prep work.
- implement ppgtt binding support.
Note that we have squat i-g-t testcoverage for any of the lifetime and
access rules dma_buf/prime support brings along. And there are quite a
few intricate situations here.
Also note that the integration with the existing code is a bit
hackish, especially around get_gtt_pages and put_gtt_pages. It imo
would be easier with the prep code from Chris Wilson's unbound series,
but that is for 3.6.
Also note that I didn't bother to put the new prepare/finish gtt hooks
to good use by moving the dma_buf_map/unmap_attachment calls in there
(like we've originally planned for).
Last but not least this patch is only compile-tested, but I've changed
very little compared to Dave Airlie's version. So there's a decent
chance v2 on drm-next works as well as v1 on 3.4-rc.
v3: Right when I've hit sent I've noticed that I've screwed up one
obj->sg_list (for dmar support) and obj->sg_table (for prime support)
disdinction. We should be able to merge these 2 paths, but that's
material for another patch.
v4: fix the error reporting bugs pointed out by ickle.
v5: fix another error, and stop non-gtt mmaps on shared objects
stop pread/pwrite on imported objects, add fake kmap
Signed-off-by: Dave Airlie <airlied@redhat.com>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6d2180cf3da5..c1e5c66553df 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -35,6 +35,7 @@ #include <linux/slab.h> #include <linux/swap.h> #include <linux/pci.h> +#include <linux/dma-buf.h> static __must_check int i915_gem_object_flush_gpu_write_domain(struct drm_i915_gem_object *obj); static void i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj); @@ -538,6 +539,14 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, goto out; } + /* prime objects have no backing filp to GEM pread/pwrite + * pages from. + */ + if (!obj->base.filp) { + ret = -EINVAL; + goto out; + } + trace_i915_gem_object_pread(obj, args->offset, args->size); ret = i915_gem_shmem_pread(dev, obj, args, file); @@ -880,6 +889,14 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, goto out; } + /* prime objects have no backing filp to GEM pread/pwrite + * pages from. + */ + if (!obj->base.filp) { + ret = -EINVAL; + goto out; + } + trace_i915_gem_object_pwrite(obj, args->offset, args->size); ret = -EFAULT; @@ -1021,6 +1038,14 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data, if (obj == NULL) return -ENOENT; + /* prime objects have no backing filp to GEM mmap + * pages from. + */ + if (!obj->filp) { + drm_gem_object_unreference_unlocked(obj); + return -EINVAL; + } + addr = vm_mmap(obj->filp, 0, args->size, PROT_READ | PROT_WRITE, MAP_SHARED, args->offset); @@ -1302,8 +1327,7 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, return i915_gem_mmap_gtt(file, dev, args->handle, &args->offset); } - -static int +int i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj, gfp_t gfpmask) { @@ -1312,6 +1336,9 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj, struct inode *inode; struct page *page; + if (obj->pages || obj->sg_table) + return 0; + /* Get the list of pages out of our struct file. They'll be pinned * at this point until we release them. */ @@ -1353,6 +1380,9 @@ i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj) int page_count = obj->base.size / PAGE_SIZE; int i; + if (!obj->pages) + return; + BUG_ON(obj->madv == __I915_MADV_PURGED); if (i915_gem_object_needs_bit17_swizzle(obj)) @@ -3327,6 +3357,9 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj) trace_i915_gem_object_destroy(obj); + if (gem_obj->import_attach) + drm_prime_gem_destroy(gem_obj, obj->sg_table); + if (obj->phys_obj) i915_gem_detach_phys_object(dev, obj); |