From 96503f592fd729f296f5870a57be0417eeffc92a Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 21 Dec 2011 11:23:44 +0000 Subject: 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 Signed-off-by: Dave Airlie --- drivers/gpu/drm/udl/udl_gem.c | 75 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) (limited to 'drivers/gpu/drm/udl/udl_gem.c') 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 +#include 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); +} -- cgit v1.2.3-70-g09d2 From ace281e8ab62e026b95c413db5f3c6beed42b829 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 22 Mar 2012 09:30:56 +0300 Subject: drm/udl: unlock before returning in udl_gem_mmap() If we hit an error here, then we should unlock and unreference obj before returning. Signed-off-by: Dan Carpenter Signed-off-by: Dave Airlie --- drivers/gpu/drm/udl/udl_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/udl/udl_gem.c') diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c index 40efd32f7dc..d9609e2a4d8 100644 --- a/drivers/gpu/drm/udl/udl_gem.c +++ b/drivers/gpu/drm/udl/udl_gem.c @@ -234,7 +234,7 @@ int udl_gem_mmap(struct drm_file *file, struct drm_device *dev, ret = udl_gem_get_pages(gobj, GFP_KERNEL); if (ret) - return ret; + goto out; if (!gobj->base.map_list.map) { ret = drm_gem_create_mmap_offset(obj); if (ret) -- cgit v1.2.3-70-g09d2 From 1c780f2cfec8b533b9cfda77209b4e3e7adaddbf Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 29 May 2012 13:47:59 +0100 Subject: drm/udl: remove unused variables. These two variables were not required after new API was introduced. Signed-off-by: Dave Airlie --- drivers/gpu/drm/udl/udl_gem.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu/drm/udl/udl_gem.c') diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c index d9609e2a4d8..97acc9c6c95 100644 --- a/drivers/gpu/drm/udl/udl_gem.c +++ b/drivers/gpu/drm/udl/udl_gem.c @@ -257,8 +257,6 @@ static int udl_prime_create(struct drm_device *dev, { struct udl_gem_object *obj; int npages; - int i; - struct scatterlist *iter; npages = size / PAGE_SIZE; -- cgit v1.2.3-70-g09d2 From e8aa1d1ebcbcf98fbb20cad83098f25c7d52753f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 26 Mar 2012 14:36:56 +0100 Subject: udl: support vmapping imported dma-bufs This allows udl to get a vmapping of an imported buffer for scanout. Signed-off-by: Dave Airlie --- drivers/gpu/drm/udl/udl_fb.c | 13 +++++++++++-- drivers/gpu/drm/udl/udl_gem.c | 25 ++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/udl/udl_gem.c') diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index a029ee39b0c..ce9a6117992 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c @@ -156,8 +156,17 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, if (!fb->active_16) return 0; - if (!fb->obj->vmapping) - udl_gem_vmap(fb->obj); + if (!fb->obj->vmapping) { + ret = udl_gem_vmap(fb->obj); + if (ret == -ENOMEM) { + DRM_ERROR("failed to vmap fb\n"); + return 0; + } + if (!fb->obj->vmapping) { + DRM_ERROR("failed to vmapping\n"); + return 0; + } + } start_cycles = get_cycles(); diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c index 97acc9c6c95..7bd65bdd15a 100644 --- a/drivers/gpu/drm/udl/udl_gem.c +++ b/drivers/gpu/drm/udl/udl_gem.c @@ -180,6 +180,18 @@ int udl_gem_vmap(struct udl_gem_object *obj) int page_count = obj->base.size / PAGE_SIZE; int ret; + if (obj->base.import_attach) { + ret = dma_buf_begin_cpu_access(obj->base.import_attach->dmabuf, + 0, obj->base.size, DMA_BIDIRECTIONAL); + if (ret) + return -EINVAL; + + obj->vmapping = dma_buf_vmap(obj->base.import_attach->dmabuf); + if (!obj->vmapping) + return -ENOMEM; + return 0; + } + ret = udl_gem_get_pages(obj, GFP_KERNEL); if (ret) return ret; @@ -192,6 +204,13 @@ int udl_gem_vmap(struct udl_gem_object *obj) void udl_gem_vunmap(struct udl_gem_object *obj) { + if (obj->base.import_attach) { + dma_buf_vunmap(obj->base.import_attach->dmabuf, obj->vmapping); + dma_buf_end_cpu_access(obj->base.import_attach->dmabuf, 0, + obj->base.size, DMA_BIDIRECTIONAL); + return; + } + if (obj->vmapping) vunmap(obj->vmapping); @@ -202,12 +221,12 @@ 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); + if (gem_obj->import_attach) + drm_prime_gem_destroy(gem_obj, obj->sg); + if (obj->pages) udl_gem_put_pages(obj); -- cgit v1.2.3-70-g09d2