aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_prime.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_prime.c')
-rw-r--r--drivers/gpu/drm/drm_prime.c99
1 files changed, 51 insertions, 48 deletions
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index 366910ddcfcb..dcde35231e25 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -62,6 +62,7 @@ struct drm_prime_member {
62 struct dma_buf *dma_buf; 62 struct dma_buf *dma_buf;
63 uint32_t handle; 63 uint32_t handle;
64}; 64};
65static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle);
65 66
66static struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach, 67static struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach,
67 enum dma_data_direction dir) 68 enum dma_data_direction dir)
@@ -200,7 +201,8 @@ int drm_gem_prime_handle_to_fd(struct drm_device *dev,
200{ 201{
201 struct drm_gem_object *obj; 202 struct drm_gem_object *obj;
202 void *buf; 203 void *buf;
203 int ret; 204 int ret = 0;
205 struct dma_buf *dmabuf;
204 206
205 obj = drm_gem_object_lookup(dev, file_priv, handle); 207 obj = drm_gem_object_lookup(dev, file_priv, handle);
206 if (!obj) 208 if (!obj)
@@ -209,43 +211,44 @@ int drm_gem_prime_handle_to_fd(struct drm_device *dev,
209 mutex_lock(&file_priv->prime.lock); 211 mutex_lock(&file_priv->prime.lock);
210 /* re-export the original imported object */ 212 /* re-export the original imported object */
211 if (obj->import_attach) { 213 if (obj->import_attach) {
212 get_dma_buf(obj->import_attach->dmabuf); 214 dmabuf = obj->import_attach->dmabuf;
213 *prime_fd = dma_buf_fd(obj->import_attach->dmabuf, flags); 215 goto out_have_obj;
214 drm_gem_object_unreference_unlocked(obj);
215 mutex_unlock(&file_priv->prime.lock);
216 return 0;
217 } 216 }
218 217
219 if (obj->export_dma_buf) { 218 if (obj->export_dma_buf) {
220 get_dma_buf(obj->export_dma_buf); 219 dmabuf = obj->export_dma_buf;
221 *prime_fd = dma_buf_fd(obj->export_dma_buf, flags); 220 goto out_have_obj;
222 drm_gem_object_unreference_unlocked(obj); 221 }
223 } else { 222
224 buf = dev->driver->gem_prime_export(dev, obj, flags); 223 buf = dev->driver->gem_prime_export(dev, obj, flags);
225 if (IS_ERR(buf)) { 224 if (IS_ERR(buf)) {
226 /* normally the created dma-buf takes ownership of the ref, 225 /* normally the created dma-buf takes ownership of the ref,
227 * but if that fails then drop the ref 226 * but if that fails then drop the ref
228 */ 227 */
229 drm_gem_object_unreference_unlocked(obj); 228 ret = PTR_ERR(buf);
230 mutex_unlock(&file_priv->prime.lock); 229 goto out;
231 return PTR_ERR(buf);
232 }
233 obj->export_dma_buf = buf;
234 *prime_fd = dma_buf_fd(buf, flags);
235 } 230 }
231 obj->export_dma_buf = buf;
232
236 /* if we've exported this buffer the cheat and add it to the import list 233 /* if we've exported this buffer the cheat and add it to the import list
237 * so we get the correct handle back 234 * so we get the correct handle back
238 */ 235 */
239 ret = drm_prime_add_imported_buf_handle(&file_priv->prime, 236 ret = drm_prime_add_buf_handle(&file_priv->prime,
240 obj->export_dma_buf, handle); 237 obj->export_dma_buf, handle);
241 if (ret) { 238 if (ret)
242 drm_gem_object_unreference_unlocked(obj); 239 goto out;
243 mutex_unlock(&file_priv->prime.lock);
244 return ret;
245 }
246 240
241 *prime_fd = dma_buf_fd(buf, flags);
247 mutex_unlock(&file_priv->prime.lock); 242 mutex_unlock(&file_priv->prime.lock);
248 return 0; 243 return 0;
244
245out_have_obj:
246 get_dma_buf(dmabuf);
247 *prime_fd = dma_buf_fd(dmabuf, flags);
248out:
249 drm_gem_object_unreference_unlocked(obj);
250 mutex_unlock(&file_priv->prime.lock);
251 return ret;
249} 252}
250EXPORT_SYMBOL(drm_gem_prime_handle_to_fd); 253EXPORT_SYMBOL(drm_gem_prime_handle_to_fd);
251 254
@@ -268,7 +271,6 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
268 * refcount on gem itself instead of f_count of dmabuf. 271 * refcount on gem itself instead of f_count of dmabuf.
269 */ 272 */
270 drm_gem_object_reference(obj); 273 drm_gem_object_reference(obj);
271 dma_buf_put(dma_buf);
272 return obj; 274 return obj;
273 } 275 }
274 } 276 }
@@ -277,6 +279,8 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
277 if (IS_ERR(attach)) 279 if (IS_ERR(attach))
278 return ERR_PTR(PTR_ERR(attach)); 280 return ERR_PTR(PTR_ERR(attach));
279 281
282 get_dma_buf(dma_buf);
283
280 sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); 284 sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
281 if (IS_ERR_OR_NULL(sgt)) { 285 if (IS_ERR_OR_NULL(sgt)) {
282 ret = PTR_ERR(sgt); 286 ret = PTR_ERR(sgt);
@@ -297,6 +301,8 @@ fail_unmap:
297 dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL); 301 dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
298fail_detach: 302fail_detach:
299 dma_buf_detach(dma_buf, attach); 303 dma_buf_detach(dma_buf, attach);
304 dma_buf_put(dma_buf);
305
300 return ERR_PTR(ret); 306 return ERR_PTR(ret);
301} 307}
302EXPORT_SYMBOL(drm_gem_prime_import); 308EXPORT_SYMBOL(drm_gem_prime_import);
@@ -314,7 +320,7 @@ int drm_gem_prime_fd_to_handle(struct drm_device *dev,
314 320
315 mutex_lock(&file_priv->prime.lock); 321 mutex_lock(&file_priv->prime.lock);
316 322
317 ret = drm_prime_lookup_imported_buf_handle(&file_priv->prime, 323 ret = drm_prime_lookup_buf_handle(&file_priv->prime,
318 dma_buf, handle); 324 dma_buf, handle);
319 if (!ret) { 325 if (!ret) {
320 ret = 0; 326 ret = 0;
@@ -333,12 +339,15 @@ int drm_gem_prime_fd_to_handle(struct drm_device *dev,
333 if (ret) 339 if (ret)
334 goto out_put; 340 goto out_put;
335 341
336 ret = drm_prime_add_imported_buf_handle(&file_priv->prime, 342 ret = drm_prime_add_buf_handle(&file_priv->prime,
337 dma_buf, *handle); 343 dma_buf, *handle);
338 if (ret) 344 if (ret)
339 goto fail; 345 goto fail;
340 346
341 mutex_unlock(&file_priv->prime.lock); 347 mutex_unlock(&file_priv->prime.lock);
348
349 dma_buf_put(dma_buf);
350
342 return 0; 351 return 0;
343 352
344fail: 353fail:
@@ -401,21 +410,17 @@ int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data,
401struct sg_table *drm_prime_pages_to_sg(struct page **pages, int nr_pages) 410struct sg_table *drm_prime_pages_to_sg(struct page **pages, int nr_pages)
402{ 411{
403 struct sg_table *sg = NULL; 412 struct sg_table *sg = NULL;
404 struct scatterlist *iter;
405 int i;
406 int ret; 413 int ret;
407 414
408 sg = kmalloc(sizeof(struct sg_table), GFP_KERNEL); 415 sg = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
409 if (!sg) 416 if (!sg)
410 goto out; 417 goto out;
411 418
412 ret = sg_alloc_table(sg, nr_pages, GFP_KERNEL); 419 ret = sg_alloc_table_from_pages(sg, pages, nr_pages, 0,
420 nr_pages << PAGE_SHIFT, GFP_KERNEL);
413 if (ret) 421 if (ret)
414 goto out; 422 goto out;
415 423
416 for_each_sg(sg->sgl, iter, nr_pages, i)
417 sg_set_page(iter, pages[i], PAGE_SIZE, 0);
418
419 return sg; 424 return sg;
420out: 425out:
421 kfree(sg); 426 kfree(sg);
@@ -483,15 +488,12 @@ EXPORT_SYMBOL(drm_prime_init_file_private);
483 488
484void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv) 489void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv)
485{ 490{
486 struct drm_prime_member *member, *safe; 491 /* by now drm_gem_release should've made sure the list is empty */
487 list_for_each_entry_safe(member, safe, &prime_fpriv->head, entry) { 492 WARN_ON(!list_empty(&prime_fpriv->head));
488 list_del(&member->entry);
489 kfree(member);
490 }
491} 493}
492EXPORT_SYMBOL(drm_prime_destroy_file_private); 494EXPORT_SYMBOL(drm_prime_destroy_file_private);
493 495
494int drm_prime_add_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle) 496static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle)
495{ 497{
496 struct drm_prime_member *member; 498 struct drm_prime_member *member;
497 499
@@ -499,14 +501,14 @@ int drm_prime_add_imported_buf_handle(struct drm_prime_file_private *prime_fpriv
499 if (!member) 501 if (!member)
500 return -ENOMEM; 502 return -ENOMEM;
501 503
504 get_dma_buf(dma_buf);
502 member->dma_buf = dma_buf; 505 member->dma_buf = dma_buf;
503 member->handle = handle; 506 member->handle = handle;
504 list_add(&member->entry, &prime_fpriv->head); 507 list_add(&member->entry, &prime_fpriv->head);
505 return 0; 508 return 0;
506} 509}
507EXPORT_SYMBOL(drm_prime_add_imported_buf_handle);
508 510
509int drm_prime_lookup_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle) 511int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle)
510{ 512{
511 struct drm_prime_member *member; 513 struct drm_prime_member *member;
512 514
@@ -518,19 +520,20 @@ int drm_prime_lookup_imported_buf_handle(struct drm_prime_file_private *prime_fp
518 } 520 }
519 return -ENOENT; 521 return -ENOENT;
520} 522}
521EXPORT_SYMBOL(drm_prime_lookup_imported_buf_handle); 523EXPORT_SYMBOL(drm_prime_lookup_buf_handle);
522 524
523void drm_prime_remove_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf) 525void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf)
524{ 526{
525 struct drm_prime_member *member, *safe; 527 struct drm_prime_member *member, *safe;
526 528
527 mutex_lock(&prime_fpriv->lock); 529 mutex_lock(&prime_fpriv->lock);
528 list_for_each_entry_safe(member, safe, &prime_fpriv->head, entry) { 530 list_for_each_entry_safe(member, safe, &prime_fpriv->head, entry) {
529 if (member->dma_buf == dma_buf) { 531 if (member->dma_buf == dma_buf) {
532 dma_buf_put(dma_buf);
530 list_del(&member->entry); 533 list_del(&member->entry);
531 kfree(member); 534 kfree(member);
532 } 535 }
533 } 536 }
534 mutex_unlock(&prime_fpriv->lock); 537 mutex_unlock(&prime_fpriv->lock);
535} 538}
536EXPORT_SYMBOL(drm_prime_remove_imported_buf_handle); 539EXPORT_SYMBOL(drm_prime_remove_buf_handle);