exynos_drm_gem.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /* exynos_drm_gem.c
  3. *
  4. * Copyright (c) 2011 Samsung Electronics Co., Ltd.
  5. * Author: Inki Dae <inki.dae@samsung.com>
  6. */
  7. #include <linux/dma-buf.h>
  8. #include <linux/shmem_fs.h>
  9. #include <linux/module.h>
  10. #include <drm/drm_dumb_buffers.h>
  11. #include <drm/drm_prime.h>
  12. #include <drm/drm_print.h>
  13. #include <drm/drm_vma_manager.h>
  14. #include <drm/exynos_drm.h>
  15. #include "exynos_drm_drv.h"
  16. #include "exynos_drm_gem.h"
  17. MODULE_IMPORT_NS("DMA_BUF");
  18. static int exynos_drm_gem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma);
  19. static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem, bool kvmap)
  20. {
  21. struct drm_device *dev = exynos_gem->base.dev;
  22. unsigned long attr = 0;
  23. if (exynos_gem->dma_addr) {
  24. DRM_DEV_DEBUG_KMS(to_dma_dev(dev), "already allocated.\n");
  25. return 0;
  26. }
  27. /*
  28. * if EXYNOS_BO_CONTIG, fully physically contiguous memory
  29. * region will be allocated else physically contiguous
  30. * as possible.
  31. */
  32. if (!(exynos_gem->flags & EXYNOS_BO_NONCONTIG))
  33. attr |= DMA_ATTR_FORCE_CONTIGUOUS;
  34. /*
  35. * if EXYNOS_BO_WC or EXYNOS_BO_NONCACHABLE, writecombine mapping
  36. * else cachable mapping.
  37. */
  38. if (exynos_gem->flags & EXYNOS_BO_WC ||
  39. !(exynos_gem->flags & EXYNOS_BO_CACHABLE))
  40. attr |= DMA_ATTR_WRITE_COMBINE;
  41. /* FBDev emulation requires kernel mapping */
  42. if (!kvmap)
  43. attr |= DMA_ATTR_NO_KERNEL_MAPPING;
  44. exynos_gem->dma_attrs = attr;
  45. exynos_gem->cookie = dma_alloc_attrs(to_dma_dev(dev), exynos_gem->size,
  46. &exynos_gem->dma_addr, GFP_KERNEL,
  47. exynos_gem->dma_attrs);
  48. if (!exynos_gem->cookie) {
  49. DRM_DEV_ERROR(to_dma_dev(dev), "failed to allocate buffer.\n");
  50. return -ENOMEM;
  51. }
  52. if (kvmap)
  53. exynos_gem->kvaddr = exynos_gem->cookie;
  54. DRM_DEV_DEBUG_KMS(to_dma_dev(dev), "dma_addr(0x%lx), size(0x%lx)\n",
  55. (unsigned long)exynos_gem->dma_addr, exynos_gem->size);
  56. return 0;
  57. }
  58. static void exynos_drm_free_buf(struct exynos_drm_gem *exynos_gem)
  59. {
  60. struct drm_device *dev = exynos_gem->base.dev;
  61. if (!exynos_gem->dma_addr) {
  62. DRM_DEV_DEBUG_KMS(dev->dev, "dma_addr is invalid.\n");
  63. return;
  64. }
  65. DRM_DEV_DEBUG_KMS(dev->dev, "dma_addr(0x%lx), size(0x%lx)\n",
  66. (unsigned long)exynos_gem->dma_addr, exynos_gem->size);
  67. dma_free_attrs(to_dma_dev(dev), exynos_gem->size, exynos_gem->cookie,
  68. (dma_addr_t)exynos_gem->dma_addr,
  69. exynos_gem->dma_attrs);
  70. }
  71. static int exynos_drm_gem_handle_create(struct drm_gem_object *obj,
  72. struct drm_file *file_priv,
  73. unsigned int *handle)
  74. {
  75. int ret;
  76. /*
  77. * allocate a id of idr table where the obj is registered
  78. * and handle has the id what user can see.
  79. */
  80. ret = drm_gem_handle_create(file_priv, obj, handle);
  81. if (ret)
  82. return ret;
  83. DRM_DEV_DEBUG_KMS(to_dma_dev(obj->dev), "gem handle = 0x%x\n", *handle);
  84. /* drop reference from allocate - handle holds it now. */
  85. drm_gem_object_put(obj);
  86. return 0;
  87. }
  88. void exynos_drm_gem_destroy(struct exynos_drm_gem *exynos_gem)
  89. {
  90. struct drm_gem_object *obj = &exynos_gem->base;
  91. DRM_DEV_DEBUG_KMS(to_dma_dev(obj->dev), "handle count = %d\n",
  92. obj->handle_count);
  93. /*
  94. * do not release memory region from exporter.
  95. *
  96. * the region will be released by exporter
  97. * once dmabuf's refcount becomes 0.
  98. */
  99. if (obj->import_attach)
  100. drm_prime_gem_destroy(obj, exynos_gem->sgt);
  101. else
  102. exynos_drm_free_buf(exynos_gem);
  103. /* release file pointer to gem object. */
  104. drm_gem_object_release(obj);
  105. kfree(exynos_gem);
  106. }
  107. static const struct vm_operations_struct exynos_drm_gem_vm_ops = {
  108. .open = drm_gem_vm_open,
  109. .close = drm_gem_vm_close,
  110. };
  111. static const struct drm_gem_object_funcs exynos_drm_gem_object_funcs = {
  112. .free = exynos_drm_gem_free_object,
  113. .get_sg_table = exynos_drm_gem_prime_get_sg_table,
  114. .mmap = exynos_drm_gem_mmap,
  115. .vm_ops = &exynos_drm_gem_vm_ops,
  116. };
  117. static struct exynos_drm_gem *exynos_drm_gem_init(struct drm_device *dev,
  118. unsigned long size)
  119. {
  120. struct exynos_drm_gem *exynos_gem;
  121. struct drm_gem_object *obj;
  122. int ret;
  123. exynos_gem = kzalloc_obj(*exynos_gem);
  124. if (!exynos_gem)
  125. return ERR_PTR(-ENOMEM);
  126. exynos_gem->size = size;
  127. obj = &exynos_gem->base;
  128. obj->funcs = &exynos_drm_gem_object_funcs;
  129. ret = drm_gem_object_init(dev, obj, size);
  130. if (ret < 0) {
  131. DRM_DEV_ERROR(dev->dev, "failed to initialize gem object\n");
  132. kfree(exynos_gem);
  133. return ERR_PTR(ret);
  134. }
  135. ret = drm_gem_create_mmap_offset(obj);
  136. if (ret < 0) {
  137. drm_gem_object_release(obj);
  138. kfree(exynos_gem);
  139. return ERR_PTR(ret);
  140. }
  141. DRM_DEV_DEBUG_KMS(dev->dev, "created file object = %p\n", obj->filp);
  142. return exynos_gem;
  143. }
  144. struct exynos_drm_gem *exynos_drm_gem_create(struct drm_device *dev,
  145. unsigned int flags,
  146. unsigned long size,
  147. bool kvmap)
  148. {
  149. struct exynos_drm_gem *exynos_gem;
  150. int ret;
  151. if (flags & ~(EXYNOS_BO_MASK)) {
  152. DRM_DEV_ERROR(dev->dev,
  153. "invalid GEM buffer flags: %u\n", flags);
  154. return ERR_PTR(-EINVAL);
  155. }
  156. if (!size) {
  157. DRM_DEV_ERROR(dev->dev, "invalid GEM buffer size: %lu\n", size);
  158. return ERR_PTR(-EINVAL);
  159. }
  160. size = roundup(size, PAGE_SIZE);
  161. exynos_gem = exynos_drm_gem_init(dev, size);
  162. if (IS_ERR(exynos_gem))
  163. return exynos_gem;
  164. if (!is_drm_iommu_supported(dev) && (flags & EXYNOS_BO_NONCONTIG)) {
  165. /*
  166. * when no IOMMU is available, all allocated buffers are
  167. * contiguous anyway, so drop EXYNOS_BO_NONCONTIG flag
  168. */
  169. flags &= ~EXYNOS_BO_NONCONTIG;
  170. DRM_WARN("Non-contiguous allocation is not supported without IOMMU, falling back to contiguous buffer\n");
  171. }
  172. /* set memory type and cache attribute from user side. */
  173. exynos_gem->flags = flags;
  174. ret = exynos_drm_alloc_buf(exynos_gem, kvmap);
  175. if (ret < 0) {
  176. drm_gem_object_release(&exynos_gem->base);
  177. kfree(exynos_gem);
  178. return ERR_PTR(ret);
  179. }
  180. return exynos_gem;
  181. }
  182. int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data,
  183. struct drm_file *file_priv)
  184. {
  185. struct drm_exynos_gem_create *args = data;
  186. struct exynos_drm_gem *exynos_gem;
  187. int ret;
  188. exynos_gem = exynos_drm_gem_create(dev, args->flags, args->size, false);
  189. if (IS_ERR(exynos_gem))
  190. return PTR_ERR(exynos_gem);
  191. ret = exynos_drm_gem_handle_create(&exynos_gem->base, file_priv,
  192. &args->handle);
  193. if (ret) {
  194. exynos_drm_gem_destroy(exynos_gem);
  195. return ret;
  196. }
  197. return 0;
  198. }
  199. int exynos_drm_gem_map_ioctl(struct drm_device *dev, void *data,
  200. struct drm_file *file_priv)
  201. {
  202. struct drm_exynos_gem_map *args = data;
  203. return drm_gem_dumb_map_offset(file_priv, dev, args->handle,
  204. &args->offset);
  205. }
  206. struct exynos_drm_gem *exynos_drm_gem_get(struct drm_file *filp,
  207. unsigned int gem_handle)
  208. {
  209. struct drm_gem_object *obj;
  210. obj = drm_gem_object_lookup(filp, gem_handle);
  211. if (!obj)
  212. return NULL;
  213. return to_exynos_gem(obj);
  214. }
  215. static int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem *exynos_gem,
  216. struct vm_area_struct *vma)
  217. {
  218. struct drm_device *drm_dev = exynos_gem->base.dev;
  219. unsigned long vm_size;
  220. int ret;
  221. vm_flags_clear(vma, VM_PFNMAP);
  222. vma->vm_pgoff = 0;
  223. vm_size = vma->vm_end - vma->vm_start;
  224. /* check if user-requested size is valid. */
  225. if (vm_size > exynos_gem->size)
  226. return -EINVAL;
  227. ret = dma_mmap_attrs(to_dma_dev(drm_dev), vma, exynos_gem->cookie,
  228. exynos_gem->dma_addr, exynos_gem->size,
  229. exynos_gem->dma_attrs);
  230. if (ret < 0) {
  231. DRM_ERROR("failed to mmap.\n");
  232. return ret;
  233. }
  234. return 0;
  235. }
  236. int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data,
  237. struct drm_file *file_priv)
  238. {
  239. struct exynos_drm_gem *exynos_gem;
  240. struct drm_exynos_gem_info *args = data;
  241. struct drm_gem_object *obj;
  242. obj = drm_gem_object_lookup(file_priv, args->handle);
  243. if (!obj) {
  244. DRM_DEV_ERROR(dev->dev, "failed to lookup gem object.\n");
  245. return -EINVAL;
  246. }
  247. exynos_gem = to_exynos_gem(obj);
  248. args->flags = exynos_gem->flags;
  249. args->size = exynos_gem->size;
  250. drm_gem_object_put(obj);
  251. return 0;
  252. }
  253. void exynos_drm_gem_free_object(struct drm_gem_object *obj)
  254. {
  255. exynos_drm_gem_destroy(to_exynos_gem(obj));
  256. }
  257. int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
  258. struct drm_device *dev,
  259. struct drm_mode_create_dumb *args)
  260. {
  261. struct exynos_drm_gem *exynos_gem;
  262. unsigned int flags;
  263. int ret;
  264. ret = drm_mode_size_dumb(dev, args, 0, 0);
  265. if (ret)
  266. return ret;
  267. /*
  268. * allocate memory to be used for framebuffer.
  269. * - this callback would be called by user application
  270. * with DRM_IOCTL_MODE_CREATE_DUMB command.
  271. */
  272. if (is_drm_iommu_supported(dev))
  273. flags = EXYNOS_BO_NONCONTIG | EXYNOS_BO_WC;
  274. else
  275. flags = EXYNOS_BO_CONTIG | EXYNOS_BO_WC;
  276. exynos_gem = exynos_drm_gem_create(dev, flags, args->size, false);
  277. if (IS_ERR(exynos_gem)) {
  278. dev_warn(dev->dev, "FB allocation failed.\n");
  279. return PTR_ERR(exynos_gem);
  280. }
  281. ret = exynos_drm_gem_handle_create(&exynos_gem->base, file_priv,
  282. &args->handle);
  283. if (ret) {
  284. exynos_drm_gem_destroy(exynos_gem);
  285. return ret;
  286. }
  287. return 0;
  288. }
  289. static int exynos_drm_gem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
  290. {
  291. struct exynos_drm_gem *exynos_gem = to_exynos_gem(obj);
  292. int ret;
  293. if (obj->import_attach)
  294. return dma_buf_mmap(obj->dma_buf, vma, 0);
  295. vm_flags_set(vma, VM_IO | VM_DONTEXPAND | VM_DONTDUMP);
  296. DRM_DEV_DEBUG_KMS(to_dma_dev(obj->dev), "flags = 0x%x\n",
  297. exynos_gem->flags);
  298. /* non-cachable as default. */
  299. if (exynos_gem->flags & EXYNOS_BO_CACHABLE)
  300. vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
  301. else if (exynos_gem->flags & EXYNOS_BO_WC)
  302. vma->vm_page_prot =
  303. pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
  304. else
  305. vma->vm_page_prot =
  306. pgprot_noncached(vm_get_page_prot(vma->vm_flags));
  307. ret = exynos_drm_gem_mmap_buffer(exynos_gem, vma);
  308. if (ret)
  309. goto err_close_vm;
  310. return ret;
  311. err_close_vm:
  312. drm_gem_vm_close(vma);
  313. return ret;
  314. }
  315. /* low-level interface prime helpers */
  316. struct drm_gem_object *exynos_drm_gem_prime_import(struct drm_device *dev,
  317. struct dma_buf *dma_buf)
  318. {
  319. return drm_gem_prime_import_dev(dev, dma_buf, to_dma_dev(dev));
  320. }
  321. struct sg_table *exynos_drm_gem_prime_get_sg_table(struct drm_gem_object *obj)
  322. {
  323. struct exynos_drm_gem *exynos_gem = to_exynos_gem(obj);
  324. struct drm_device *drm_dev = obj->dev;
  325. struct sg_table *sgt;
  326. int ret;
  327. sgt = kzalloc_obj(*sgt);
  328. if (!sgt)
  329. return ERR_PTR(-ENOMEM);
  330. ret = dma_get_sgtable_attrs(to_dma_dev(drm_dev), sgt, exynos_gem->cookie,
  331. exynos_gem->dma_addr, exynos_gem->size,
  332. exynos_gem->dma_attrs);
  333. if (ret) {
  334. DRM_ERROR("failed to get sgtable, %d\n", ret);
  335. kfree(sgt);
  336. return ERR_PTR(ret);
  337. }
  338. return sgt;
  339. }
  340. struct drm_gem_object *
  341. exynos_drm_gem_prime_import_sg_table(struct drm_device *dev,
  342. struct dma_buf_attachment *attach,
  343. struct sg_table *sgt)
  344. {
  345. struct exynos_drm_gem *exynos_gem;
  346. /* check if the entries in the sg_table are contiguous */
  347. if (drm_prime_get_contiguous_size(sgt) < attach->dmabuf->size) {
  348. DRM_ERROR("buffer chunks must be mapped contiguously");
  349. return ERR_PTR(-EINVAL);
  350. }
  351. exynos_gem = exynos_drm_gem_init(dev, attach->dmabuf->size);
  352. if (IS_ERR(exynos_gem))
  353. return ERR_CAST(exynos_gem);
  354. /*
  355. * Buffer has been mapped as contiguous into DMA address space,
  356. * but if there is IOMMU, it can be either CONTIG or NONCONTIG.
  357. * We assume a simplified logic below:
  358. */
  359. if (is_drm_iommu_supported(dev))
  360. exynos_gem->flags |= EXYNOS_BO_NONCONTIG;
  361. else
  362. exynos_gem->flags |= EXYNOS_BO_CONTIG;
  363. exynos_gem->dma_addr = sg_dma_address(sgt->sgl);
  364. exynos_gem->sgt = sgt;
  365. return &exynos_gem->base;
  366. }