diff options
| author | Dave Airlie <airlied@redhat.com> | 2011-12-21 11:23:44 +0000 | 
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2012-05-23 10:46:05 +0100 | 
| commit | 96503f592fd729f296f5870a57be0417eeffc92a (patch) | |
| tree | f83af0f69cd4ca5023d44c7706ee4459918499b2 /drivers/gpu/drm/udl/udl_gem.c | |
| parent | 0ff926c7d4f06f9703226dc09acad17e86f169d6 (diff) | |
| download | olio-linux-3.10-96503f592fd729f296f5870a57be0417eeffc92a.tar.xz olio-linux-3.10-96503f592fd729f296f5870a57be0417eeffc92a.zip  | |
udl: add prime fd->handle support.
udl can only be used as an output offload so doesn't need to support
handle->fd direction.
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/udl/udl_gem.c')
| -rw-r--r-- | drivers/gpu/drm/udl/udl_gem.c | 75 | 
1 files changed, 75 insertions, 0 deletions
diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c index 92f19ef329b..40efd32f7dc 100644 --- a/drivers/gpu/drm/udl/udl_gem.c +++ b/drivers/gpu/drm/udl/udl_gem.c @@ -9,6 +9,7 @@  #include "drmP.h"  #include "udl_drv.h"  #include <linux/shmem_fs.h> +#include <linux/dma-buf.h>  struct udl_gem_object *udl_gem_alloc_object(struct drm_device *dev,  					    size_t size) @@ -161,6 +162,12 @@ static void udl_gem_put_pages(struct udl_gem_object *obj)  	int page_count = obj->base.size / PAGE_SIZE;  	int i; +	if (obj->base.import_attach) { +		drm_free_large(obj->pages); +		obj->pages = NULL; +		return; +	} +  	for (i = 0; i < page_count; i++)  		page_cache_release(obj->pages[i]); @@ -195,6 +202,9 @@ void udl_gem_free_object(struct drm_gem_object *gem_obj)  {  	struct udl_gem_object *obj = to_udl_bo(gem_obj); +	if (gem_obj->import_attach) +		drm_prime_gem_destroy(gem_obj, obj->sg); +  	if (obj->vmapping)  		udl_gem_vunmap(obj); @@ -239,3 +249,68 @@ unlock:  	mutex_unlock(&dev->struct_mutex);  	return ret;  } + +static int udl_prime_create(struct drm_device *dev, +			    size_t size, +			    struct sg_table *sg, +			    struct udl_gem_object **obj_p) +{ +	struct udl_gem_object *obj; +	int npages; +	int i; +	struct scatterlist *iter; + +	npages = size / PAGE_SIZE; + +	*obj_p = NULL; +	obj = udl_gem_alloc_object(dev, npages * PAGE_SIZE); +	if (!obj) +		return -ENOMEM; + +	obj->sg = sg; +	obj->pages = drm_malloc_ab(npages, sizeof(struct page *)); +	if (obj->pages == NULL) { +		DRM_ERROR("obj pages is NULL %d\n", npages); +		return -ENOMEM; +	} + +	drm_prime_sg_to_page_addr_arrays(sg, obj->pages, NULL, npages); + +	*obj_p = obj; +	return 0; +} + +struct drm_gem_object *udl_gem_prime_import(struct drm_device *dev, +				struct dma_buf *dma_buf) +{ +	struct dma_buf_attachment *attach; +	struct sg_table *sg; +	struct udl_gem_object *uobj; +	int ret; + +	/* need to attach */ +	attach = dma_buf_attach(dma_buf, dev->dev); +	if (IS_ERR(attach)) +		return ERR_PTR(PTR_ERR(attach)); + +	sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); +	if (IS_ERR(sg)) { +		ret = PTR_ERR(sg); +		goto fail_detach; +	} + +	ret = udl_prime_create(dev, dma_buf->size, sg, &uobj); +	if (ret) { +		goto fail_unmap; +	} + +	uobj->base.import_attach = attach; + +	return &uobj->base; + +fail_unmap: +	dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL); +fail_detach: +	dma_buf_detach(dma_buf, attach); +	return ERR_PTR(ret); +}  |