On Tue, May 22, 2012 at 8:50 AM, Dave Airlie <airlied@xxxxxxxxx> wrote: > From: Dave Airlie <airlied@xxxxxxxxxx> > > udl can only be used as an output offload so doesn't need to support > handle->fd direction. > > Signed-off-by: Dave Airlie <airlied@xxxxxxxxxx> I'm not real familiar with udl, but the code seems straight-forward. Reviewed-by: Alex Deucher <alexander.deucher@xxxxxxx> > --- > drivers/gpu/drm/udl/udl_drv.c | 6 +++- > drivers/gpu/drm/udl/udl_drv.h | 3 ++ > drivers/gpu/drm/udl/udl_fb.c | 9 +++++ > drivers/gpu/drm/udl/udl_gem.c | 75 +++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 92 insertions(+), 1 deletions(-) > > diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c > index 82e6921..4d02c46 100644 > --- a/drivers/gpu/drm/udl/udl_drv.c > +++ b/drivers/gpu/drm/udl/udl_drv.c > @@ -57,7 +57,7 @@ static const struct file_operations udl_driver_fops = { > }; > > static struct drm_driver driver = { > - .driver_features = DRIVER_MODESET | DRIVER_GEM, > + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME, > .load = udl_driver_load, > .unload = udl_driver_unload, > > @@ -70,6 +70,10 @@ static struct drm_driver driver = { > .dumb_map_offset = udl_gem_mmap, > .dumb_destroy = udl_dumb_destroy, > .fops = &udl_driver_fops, > + > + .prime_fd_to_handle = drm_gem_prime_fd_to_handle, > + .gem_prime_import = udl_gem_prime_import, > + > .name = DRIVER_NAME, > .desc = DRIVER_DESC, > .date = DRIVER_DATE, > diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h > index 96820d0..fccd361 100644 > --- a/drivers/gpu/drm/udl/udl_drv.h > +++ b/drivers/gpu/drm/udl/udl_drv.h > @@ -66,6 +66,7 @@ struct udl_gem_object { > struct drm_gem_object base; > struct page **pages; > void *vmapping; > + struct sg_table *sg; > }; > > #define to_udl_bo(x) container_of(x, struct udl_gem_object, base) > @@ -118,6 +119,8 @@ int udl_gem_init_object(struct drm_gem_object *obj); > void udl_gem_free_object(struct drm_gem_object *gem_obj); > struct udl_gem_object *udl_gem_alloc_object(struct drm_device *dev, > size_t size); > +struct drm_gem_object *udl_gem_prime_import(struct drm_device *dev, > + struct dma_buf *dma_buf); > > int udl_gem_vmap(struct udl_gem_object *obj); > void udl_gem_vunmap(struct udl_gem_object *obj); > diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c > index 4d9c3a5..a029ee3 100644 > --- a/drivers/gpu/drm/udl/udl_fb.c > +++ b/drivers/gpu/drm/udl/udl_fb.c > @@ -593,11 +593,20 @@ udl_fb_user_fb_create(struct drm_device *dev, > struct drm_gem_object *obj; > struct udl_framebuffer *ufb; > int ret; > + uint32_t size; > > obj = drm_gem_object_lookup(dev, file, mode_cmd->handles[0]); > if (obj == NULL) > return ERR_PTR(-ENOENT); > > + size = mode_cmd->pitches[0] * mode_cmd->height; > + size = ALIGN(size, PAGE_SIZE); > + > + if (size > obj->size) { > + DRM_ERROR("object size not sufficient for fb %d %zu %d %d\n", size, obj->size, mode_cmd->pitches[0], mode_cmd->height); > + return ERR_PTR(-ENOMEM); > + } > + > ufb = kzalloc(sizeof(*ufb), GFP_KERNEL); > if (ufb == NULL) > return ERR_PTR(-ENOMEM); > diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c > index 92f19ef..40efd32 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); > +} > -- > 1.7.6 > > _______________________________________________ > dri-devel mailing list > dri-devel@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/dri-devel _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel