diff options
author | Dave Airlie <airlied@redhat.com> | 2011-12-21 06:23:44 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2012-05-23 05:46:05 -0400 |
commit | 96503f592fd729f296f5870a57be0417eeffc92a (patch) | |
tree | f83af0f69cd4ca5023d44c7706ee4459918499b2 /drivers | |
parent | 0ff926c7d4f06f9703226dc09acad17e86f169d6 (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.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/udl/udl_drv.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/udl/udl_fb.c | 9 | ||||
-rw-r--r-- | 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 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 | ||
59 | static struct drm_driver driver = { | 59 | static 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); | |||
118 | void udl_gem_free_object(struct drm_gem_object *gem_obj); | 119 | void udl_gem_free_object(struct drm_gem_object *gem_obj); |
119 | struct udl_gem_object *udl_gem_alloc_object(struct drm_device *dev, | 120 | struct udl_gem_object *udl_gem_alloc_object(struct drm_device *dev, |
120 | size_t size); | 121 | size_t size); |
122 | struct drm_gem_object *udl_gem_prime_import(struct drm_device *dev, | ||
123 | struct dma_buf *dma_buf); | ||
121 | 124 | ||
122 | int udl_gem_vmap(struct udl_gem_object *obj); | 125 | int udl_gem_vmap(struct udl_gem_object *obj); |
123 | void udl_gem_vunmap(struct udl_gem_object *obj); | 126 | 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 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 | ||
13 | struct udl_gem_object *udl_gem_alloc_object(struct drm_device *dev, | 14 | struct 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 | |||
253 | static 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 | |||
283 | struct 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 | |||
311 | fail_unmap: | ||
312 | dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL); | ||
313 | fail_detach: | ||
314 | dma_buf_detach(dma_buf, attach); | ||
315 | return ERR_PTR(ret); | ||
316 | } | ||