msm_gem_prime.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2013 Red Hat
  4. * Author: Rob Clark <robdclark@gmail.com>
  5. */
  6. #include <linux/dma-buf.h>
  7. #include <drm/drm_drv.h>
  8. #include <drm/drm_prime.h>
  9. #include "msm_drv.h"
  10. #include "msm_gem.h"
  11. struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj)
  12. {
  13. struct msm_gem_object *msm_obj = to_msm_bo(obj);
  14. size_t npages = obj->size >> PAGE_SHIFT;
  15. if (msm_obj->flags & MSM_BO_NO_SHARE)
  16. return ERR_PTR(-EINVAL);
  17. if (WARN_ON(!msm_obj->pages)) /* should have already pinned! */
  18. return ERR_PTR(-ENOMEM);
  19. return drm_prime_pages_to_sg(obj->dev, msm_obj->pages, npages);
  20. }
  21. int msm_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map)
  22. {
  23. void *vaddr;
  24. vaddr = msm_gem_get_vaddr_locked(obj);
  25. if (IS_ERR(vaddr))
  26. return PTR_ERR(vaddr);
  27. iosys_map_set_vaddr(map, vaddr);
  28. return 0;
  29. }
  30. void msm_gem_prime_vunmap(struct drm_gem_object *obj, struct iosys_map *map)
  31. {
  32. msm_gem_put_vaddr_locked(obj);
  33. }
  34. static void msm_gem_dmabuf_release(struct dma_buf *dma_buf)
  35. {
  36. struct drm_gem_object *obj = dma_buf->priv;
  37. msm_gem_vma_put(obj);
  38. drm_gem_dmabuf_release(dma_buf);
  39. }
  40. static const struct dma_buf_ops msm_gem_prime_dmabuf_ops = {
  41. .attach = drm_gem_map_attach,
  42. .detach = drm_gem_map_detach,
  43. .map_dma_buf = drm_gem_map_dma_buf,
  44. .unmap_dma_buf = drm_gem_unmap_dma_buf,
  45. .release = msm_gem_dmabuf_release,
  46. .mmap = drm_gem_dmabuf_mmap,
  47. .vmap = drm_gem_dmabuf_vmap,
  48. .vunmap = drm_gem_dmabuf_vunmap,
  49. };
  50. struct drm_gem_object *msm_gem_prime_import(struct drm_device *dev,
  51. struct dma_buf *buf)
  52. {
  53. if (buf->ops == &msm_gem_prime_dmabuf_ops) {
  54. struct drm_gem_object *obj = buf->priv;
  55. if (obj->dev == dev) {
  56. /*
  57. * Importing dmabuf exported from our own gem increases
  58. * refcount on gem itself instead of f_count of dmabuf.
  59. */
  60. drm_gem_object_get(obj);
  61. return obj;
  62. }
  63. }
  64. return drm_gem_prime_import(dev, buf);
  65. }
  66. struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev,
  67. struct dma_buf_attachment *attach, struct sg_table *sg)
  68. {
  69. return msm_gem_import(dev, attach->dmabuf, sg);
  70. }
  71. struct dma_buf *msm_gem_prime_export(struct drm_gem_object *obj, int flags)
  72. {
  73. if (to_msm_bo(obj)->flags & MSM_BO_NO_SHARE)
  74. return ERR_PTR(-EPERM);
  75. msm_gem_vma_get(obj);
  76. struct drm_device *dev = obj->dev;
  77. struct dma_buf_export_info exp_info = {
  78. .exp_name = KBUILD_MODNAME, /* white lie for debug */
  79. .owner = dev->driver->fops->owner,
  80. .ops = &msm_gem_prime_dmabuf_ops,
  81. .size = obj->size,
  82. .flags = flags,
  83. .priv = obj,
  84. .resv = obj->resv,
  85. };
  86. return drm_gem_dmabuf_export(dev, &exp_info);
  87. }
  88. int msm_gem_prime_pin(struct drm_gem_object *obj)
  89. {
  90. struct page **pages;
  91. int ret = 0;
  92. if (drm_gem_is_imported(obj))
  93. return 0;
  94. if (to_msm_bo(obj)->flags & MSM_BO_NO_SHARE)
  95. return -EINVAL;
  96. pages = msm_gem_pin_pages_locked(obj);
  97. if (IS_ERR(pages))
  98. ret = PTR_ERR(pages);
  99. return ret;
  100. }
  101. void msm_gem_prime_unpin(struct drm_gem_object *obj)
  102. {
  103. if (drm_gem_is_imported(obj))
  104. return;
  105. msm_gem_unpin_pages_locked(obj);
  106. }