lsdc_gem.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2023 Loongson Technology Corporation Limited
  4. */
  5. #include <linux/dma-buf.h>
  6. #include <drm/drm_debugfs.h>
  7. #include <drm/drm_dumb_buffers.h>
  8. #include <drm/drm_file.h>
  9. #include <drm/drm_gem.h>
  10. #include <drm/drm_prime.h>
  11. #include <drm/drm_print.h>
  12. #include "lsdc_drv.h"
  13. #include "lsdc_gem.h"
  14. #include "lsdc_ttm.h"
  15. static int lsdc_gem_prime_pin(struct drm_gem_object *obj)
  16. {
  17. struct lsdc_bo *lbo = gem_to_lsdc_bo(obj);
  18. int ret;
  19. dma_resv_assert_held(obj->resv);
  20. ret = lsdc_bo_pin(lbo, LSDC_GEM_DOMAIN_GTT, NULL);
  21. if (likely(ret == 0))
  22. lbo->sharing_count++;
  23. return ret;
  24. }
  25. static void lsdc_gem_prime_unpin(struct drm_gem_object *obj)
  26. {
  27. struct lsdc_bo *lbo = gem_to_lsdc_bo(obj);
  28. dma_resv_assert_held(obj->resv);
  29. lsdc_bo_unpin(lbo);
  30. if (lbo->sharing_count)
  31. lbo->sharing_count--;
  32. }
  33. static struct sg_table *lsdc_gem_prime_get_sg_table(struct drm_gem_object *obj)
  34. {
  35. struct ttm_buffer_object *tbo = to_ttm_bo(obj);
  36. struct ttm_tt *tt = tbo->ttm;
  37. if (!tt) {
  38. drm_err(obj->dev, "sharing a buffer without backing memory\n");
  39. return ERR_PTR(-ENOMEM);
  40. }
  41. return drm_prime_pages_to_sg(obj->dev, tt->pages, tt->num_pages);
  42. }
  43. static void lsdc_gem_object_free(struct drm_gem_object *obj)
  44. {
  45. struct ttm_buffer_object *tbo = to_ttm_bo(obj);
  46. if (tbo)
  47. ttm_bo_fini(tbo);
  48. }
  49. static int lsdc_gem_object_vmap(struct drm_gem_object *obj, struct iosys_map *map)
  50. {
  51. struct ttm_buffer_object *tbo = to_ttm_bo(obj);
  52. struct lsdc_bo *lbo = to_lsdc_bo(tbo);
  53. int ret;
  54. if (lbo->vmap_count > 0) {
  55. ++lbo->vmap_count;
  56. goto out;
  57. }
  58. ret = lsdc_bo_pin(lbo, 0, NULL);
  59. if (unlikely(ret)) {
  60. drm_err(obj->dev, "pin %p for vmap failed\n", lbo);
  61. return ret;
  62. }
  63. ret = ttm_bo_vmap(tbo, &lbo->map);
  64. if (ret) {
  65. drm_err(obj->dev, "ttm bo vmap failed\n");
  66. lsdc_bo_unpin(lbo);
  67. return ret;
  68. }
  69. lbo->vmap_count = 1;
  70. out:
  71. *map = lbo->map;
  72. return 0;
  73. }
  74. static void lsdc_gem_object_vunmap(struct drm_gem_object *obj, struct iosys_map *map)
  75. {
  76. struct ttm_buffer_object *tbo = to_ttm_bo(obj);
  77. struct lsdc_bo *lbo = to_lsdc_bo(tbo);
  78. if (unlikely(!lbo->vmap_count)) {
  79. drm_warn(obj->dev, "%p is not mapped\n", lbo);
  80. return;
  81. }
  82. --lbo->vmap_count;
  83. if (lbo->vmap_count == 0) {
  84. ttm_bo_vunmap(tbo, &lbo->map);
  85. lsdc_bo_unpin(lbo);
  86. }
  87. }
  88. static int lsdc_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
  89. {
  90. struct ttm_buffer_object *tbo = to_ttm_bo(obj);
  91. int ret;
  92. ret = ttm_bo_mmap_obj(vma, tbo);
  93. if (unlikely(ret)) {
  94. drm_warn(obj->dev, "mmap %p failed\n", tbo);
  95. return ret;
  96. }
  97. drm_gem_object_put(obj);
  98. return 0;
  99. }
  100. static const struct drm_gem_object_funcs lsdc_gem_object_funcs = {
  101. .free = lsdc_gem_object_free,
  102. .export = drm_gem_prime_export,
  103. .pin = lsdc_gem_prime_pin,
  104. .unpin = lsdc_gem_prime_unpin,
  105. .get_sg_table = lsdc_gem_prime_get_sg_table,
  106. .vmap = lsdc_gem_object_vmap,
  107. .vunmap = lsdc_gem_object_vunmap,
  108. .mmap = lsdc_gem_object_mmap,
  109. };
  110. struct drm_gem_object *lsdc_gem_object_create(struct drm_device *ddev,
  111. u32 domain,
  112. size_t size,
  113. bool kerenl,
  114. struct sg_table *sg,
  115. struct dma_resv *resv)
  116. {
  117. struct lsdc_device *ldev = to_lsdc(ddev);
  118. struct drm_gem_object *gobj;
  119. struct lsdc_bo *lbo;
  120. int ret;
  121. lbo = lsdc_bo_create(ddev, domain, size, kerenl, sg, resv);
  122. if (IS_ERR(lbo)) {
  123. ret = PTR_ERR(lbo);
  124. return ERR_PTR(ret);
  125. }
  126. if (!sg) {
  127. /* VRAM is filled with random data */
  128. lsdc_bo_clear(lbo);
  129. }
  130. gobj = &lbo->tbo.base;
  131. gobj->funcs = &lsdc_gem_object_funcs;
  132. /* tracking the BOs we created */
  133. mutex_lock(&ldev->gem.mutex);
  134. list_add_tail(&lbo->list, &ldev->gem.objects);
  135. mutex_unlock(&ldev->gem.mutex);
  136. return gobj;
  137. }
  138. struct drm_gem_object *
  139. lsdc_prime_import_sg_table(struct drm_device *ddev,
  140. struct dma_buf_attachment *attach,
  141. struct sg_table *sg)
  142. {
  143. struct dma_resv *resv = attach->dmabuf->resv;
  144. u64 size = attach->dmabuf->size;
  145. struct drm_gem_object *gobj;
  146. struct lsdc_bo *lbo;
  147. dma_resv_lock(resv, NULL);
  148. gobj = lsdc_gem_object_create(ddev, LSDC_GEM_DOMAIN_GTT, size, false,
  149. sg, resv);
  150. dma_resv_unlock(resv);
  151. if (IS_ERR(gobj)) {
  152. drm_err(ddev, "Failed to import sg table\n");
  153. return gobj;
  154. }
  155. lbo = gem_to_lsdc_bo(gobj);
  156. lbo->sharing_count = 1;
  157. return gobj;
  158. }
  159. int lsdc_dumb_create(struct drm_file *file, struct drm_device *ddev,
  160. struct drm_mode_create_dumb *args)
  161. {
  162. struct lsdc_device *ldev = to_lsdc(ddev);
  163. const struct lsdc_desc *descp = ldev->descp;
  164. u32 domain = LSDC_GEM_DOMAIN_VRAM;
  165. struct drm_gem_object *gobj;
  166. int ret;
  167. ret = drm_mode_size_dumb(ddev, args, descp->pitch_align, 0);
  168. if (ret)
  169. return ret;
  170. /* Maximum single bo size allowed is the half vram size available */
  171. if (args->size > ldev->vram_size / 2) {
  172. drm_err(ddev, "Requesting(%zuMiB) failed\n", (size_t)(args->size >> PAGE_SHIFT));
  173. return -ENOMEM;
  174. }
  175. gobj = lsdc_gem_object_create(ddev, domain, args->size, false, NULL, NULL);
  176. if (IS_ERR(gobj)) {
  177. drm_err(ddev, "Failed to create gem object\n");
  178. return PTR_ERR(gobj);
  179. }
  180. ret = drm_gem_handle_create(file, gobj, &args->handle);
  181. /* drop reference from allocate, handle holds it now */
  182. drm_gem_object_put(gobj);
  183. if (ret)
  184. return ret;
  185. return 0;
  186. }
  187. int lsdc_dumb_map_offset(struct drm_file *filp, struct drm_device *ddev,
  188. u32 handle, uint64_t *offset)
  189. {
  190. struct drm_gem_object *gobj;
  191. gobj = drm_gem_object_lookup(filp, handle);
  192. if (!gobj)
  193. return -ENOENT;
  194. *offset = drm_vma_node_offset_addr(&gobj->vma_node);
  195. drm_gem_object_put(gobj);
  196. return 0;
  197. }
  198. void lsdc_gem_init(struct drm_device *ddev)
  199. {
  200. struct lsdc_device *ldev = to_lsdc(ddev);
  201. mutex_init(&ldev->gem.mutex);
  202. INIT_LIST_HEAD(&ldev->gem.objects);
  203. }
  204. int lsdc_show_buffer_object(struct seq_file *m, void *arg)
  205. {
  206. struct drm_info_node *node = (struct drm_info_node *)m->private;
  207. struct drm_device *ddev = node->minor->dev;
  208. struct lsdc_device *ldev = to_lsdc(ddev);
  209. struct lsdc_bo *lbo;
  210. unsigned int i;
  211. mutex_lock(&ldev->gem.mutex);
  212. i = 0;
  213. list_for_each_entry(lbo, &ldev->gem.objects, list) {
  214. struct ttm_buffer_object *tbo = &lbo->tbo;
  215. struct ttm_resource *resource = tbo->resource;
  216. seq_printf(m, "bo[%04u][%p]: size: %8zuKiB %s offset: %8llx\n",
  217. i, lbo, lsdc_bo_size(lbo) >> 10,
  218. lsdc_mem_type_to_str(resource->mem_type),
  219. lsdc_bo_gpu_offset(lbo));
  220. i++;
  221. }
  222. mutex_unlock(&ldev->gem.mutex);
  223. seq_printf(m, "Pinned BO size: VRAM: %zuKiB, GTT: %zu KiB\n",
  224. ldev->vram_pinned_size >> 10, ldev->gtt_pinned_size >> 10);
  225. return 0;
  226. }