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/gpu/drm/udl/udl_gem.c | |
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/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 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 | } | ||