aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2011-12-21 06:23:44 -0500
committerDave Airlie <airlied@redhat.com>2012-05-23 05:46:05 -0400
commit96503f592fd729f296f5870a57be0417eeffc92a (patch)
treef83af0f69cd4ca5023d44c7706ee4459918499b2 /drivers
parent0ff926c7d4f06f9703226dc09acad17e86f169d6 (diff)
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')
-rw-r--r--drivers/gpu/drm/udl/udl_drv.c6
-rw-r--r--drivers/gpu/drm/udl/udl_drv.h3
-rw-r--r--drivers/gpu/drm/udl/udl_fb.c9
-rw-r--r--drivers/gpu/drm/udl/udl_gem.c75
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 82e6921e6865..4d02c46a9420 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 = {
57}; 57};
58 58
59static struct drm_driver driver = { 59static struct drm_driver driver = {
60 .driver_features = DRIVER_MODESET | DRIVER_GEM, 60 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
61 .load = udl_driver_load, 61 .load = udl_driver_load,
62 .unload = udl_driver_unload, 62 .unload = udl_driver_unload,
63 63
@@ -70,6 +70,10 @@ static struct drm_driver driver = {
70 .dumb_map_offset = udl_gem_mmap, 70 .dumb_map_offset = udl_gem_mmap,
71 .dumb_destroy = udl_dumb_destroy, 71 .dumb_destroy = udl_dumb_destroy,
72 .fops = &udl_driver_fops, 72 .fops = &udl_driver_fops,
73
74 .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
75 .gem_prime_import = udl_gem_prime_import,
76
73 .name = DRIVER_NAME, 77 .name = DRIVER_NAME,
74 .desc = DRIVER_DESC, 78 .desc = DRIVER_DESC,
75 .date = DRIVER_DATE, 79 .date = DRIVER_DATE,
diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h
index 96820d03a303..fccd361f7b50 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 {
66 struct drm_gem_object base; 66 struct drm_gem_object base;
67 struct page **pages; 67 struct page **pages;
68 void *vmapping; 68 void *vmapping;
69 struct sg_table *sg;
69}; 70};
70 71
71#define to_udl_bo(x) container_of(x, struct udl_gem_object, base) 72#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);
118void udl_gem_free_object(struct drm_gem_object *gem_obj); 119void udl_gem_free_object(struct drm_gem_object *gem_obj);
119struct udl_gem_object *udl_gem_alloc_object(struct drm_device *dev, 120struct udl_gem_object *udl_gem_alloc_object(struct drm_device *dev,
120 size_t size); 121 size_t size);
122struct drm_gem_object *udl_gem_prime_import(struct drm_device *dev,
123 struct dma_buf *dma_buf);
121 124
122int udl_gem_vmap(struct udl_gem_object *obj); 125int udl_gem_vmap(struct udl_gem_object *obj);
123void udl_gem_vunmap(struct udl_gem_object *obj); 126void 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 4d9c3a5d8a45..a029ee39b0c5 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,
593 struct drm_gem_object *obj; 593 struct drm_gem_object *obj;
594 struct udl_framebuffer *ufb; 594 struct udl_framebuffer *ufb;
595 int ret; 595 int ret;
596 uint32_t size;
596 597
597 obj = drm_gem_object_lookup(dev, file, mode_cmd->handles[0]); 598 obj = drm_gem_object_lookup(dev, file, mode_cmd->handles[0]);
598 if (obj == NULL) 599 if (obj == NULL)
599 return ERR_PTR(-ENOENT); 600 return ERR_PTR(-ENOENT);
600 601
602 size = mode_cmd->pitches[0] * mode_cmd->height;
603 size = ALIGN(size, PAGE_SIZE);
604
605 if (size > obj->size) {
606 DRM_ERROR("object size not sufficient for fb %d %zu %d %d\n", size, obj->size, mode_cmd->pitches[0], mode_cmd->height);
607 return ERR_PTR(-ENOMEM);
608 }
609
601 ufb = kzalloc(sizeof(*ufb), GFP_KERNEL); 610 ufb = kzalloc(sizeof(*ufb), GFP_KERNEL);
602 if (ufb == NULL) 611 if (ufb == NULL)
603 return ERR_PTR(-ENOMEM); 612 return ERR_PTR(-ENOMEM);
diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c
index 92f19ef329b0..40efd32f7dce 100644
--- a/drivers/gpu/drm/udl/udl_gem.c
+++ b/drivers/gpu/drm/udl/udl_gem.c
@@ -9,6 +9,7 @@
9#include "drmP.h" 9#include "drmP.h"
10#include "udl_drv.h" 10#include "udl_drv.h"
11#include <linux/shmem_fs.h> 11#include <linux/shmem_fs.h>
12#include <linux/dma-buf.h>
12 13
13struct udl_gem_object *udl_gem_alloc_object(struct drm_device *dev, 14struct udl_gem_object *udl_gem_alloc_object(struct drm_device *dev,
14 size_t size) 15 size_t size)
@@ -161,6 +162,12 @@ static void udl_gem_put_pages(struct udl_gem_object *obj)
161 int page_count = obj->base.size / PAGE_SIZE; 162 int page_count = obj->base.size / PAGE_SIZE;
162 int i; 163 int i;
163 164
165 if (obj->base.import_attach) {
166 drm_free_large(obj->pages);
167 obj->pages = NULL;
168 return;
169 }
170
164 for (i = 0; i < page_count; i++) 171 for (i = 0; i < page_count; i++)
165 page_cache_release(obj->pages[i]); 172 page_cache_release(obj->pages[i]);
166 173
@@ -195,6 +202,9 @@ void udl_gem_free_object(struct drm_gem_object *gem_obj)
195{ 202{
196 struct udl_gem_object *obj = to_udl_bo(gem_obj); 203 struct udl_gem_object *obj = to_udl_bo(gem_obj);
197 204
205 if (gem_obj->import_attach)
206 drm_prime_gem_destroy(gem_obj, obj->sg);
207
198 if (obj->vmapping) 208 if (obj->vmapping)
199 udl_gem_vunmap(obj); 209 udl_gem_vunmap(obj);
200 210
@@ -239,3 +249,68 @@ unlock:
239 mutex_unlock(&dev->struct_mutex); 249 mutex_unlock(&dev->struct_mutex);
240 return ret; 250 return ret;
241} 251}
252
253static int udl_prime_create(struct drm_device *dev,
254 size_t size,
255 struct sg_table *sg,
256 struct udl_gem_object **obj_p)
257{
258 struct udl_gem_object *obj;
259 int npages;
260 int i;
261 struct scatterlist *iter;
262
263 npages = size / PAGE_SIZE;
264
265 *obj_p = NULL;
266 obj = udl_gem_alloc_object(dev, npages * PAGE_SIZE);
267 if (!obj)
268 return -ENOMEM;
269
270 obj->sg = sg;
271 obj->pages = drm_malloc_ab(npages, sizeof(struct page *));
272 if (obj->pages == NULL) {
273 DRM_ERROR("obj pages is NULL %d\n", npages);
274 return -ENOMEM;
275 }
276
277 drm_prime_sg_to_page_addr_arrays(sg, obj->pages, NULL, npages);
278
279 *obj_p = obj;
280 return 0;
281}
282
283struct drm_gem_object *udl_gem_prime_import(struct drm_device *dev,
284 struct dma_buf *dma_buf)
285{
286 struct dma_buf_attachment *attach;
287 struct sg_table *sg;
288 struct udl_gem_object *uobj;
289 int ret;
290
291 /* need to attach */
292 attach = dma_buf_attach(dma_buf, dev->dev);
293 if (IS_ERR(attach))
294 return ERR_PTR(PTR_ERR(attach));
295
296 sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
297 if (IS_ERR(sg)) {
298 ret = PTR_ERR(sg);
299 goto fail_detach;
300 }
301
302 ret = udl_prime_create(dev, dma_buf->size, sg, &uobj);
303 if (ret) {
304 goto fail_unmap;
305 }
306
307 uobj->base.import_attach = attach;
308
309 return &uobj->base;
310
311fail_unmap:
312 dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL);
313fail_detach:
314 dma_buf_detach(dma_buf, attach);
315 return ERR_PTR(ret);
316}