panfrost_gem.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Copyright 2019 Linaro, Ltd, Rob Herring <robh@kernel.org> */
  3. /* Copyright 2025 Amazon.com, Inc. or its affiliates */
  4. #include <linux/cleanup.h>
  5. #include <linux/err.h>
  6. #include <linux/slab.h>
  7. #include <linux/dma-buf.h>
  8. #include <linux/dma-mapping.h>
  9. #include <drm/panfrost_drm.h>
  10. #include <drm/drm_print.h>
  11. #include "panfrost_device.h"
  12. #include "panfrost_drv.h"
  13. #include "panfrost_gem.h"
  14. #include "panfrost_mmu.h"
  15. void panfrost_gem_init(struct panfrost_device *pfdev)
  16. {
  17. int err;
  18. if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) &&
  19. !panfrost_transparent_hugepage)
  20. return;
  21. err = drm_gem_huge_mnt_create(&pfdev->base, "within_size");
  22. if (drm_gem_get_huge_mnt(&pfdev->base))
  23. drm_info(&pfdev->base, "Using Transparent Hugepage\n");
  24. else if (err)
  25. drm_warn(&pfdev->base, "Can't use Transparent Hugepage (%d)\n",
  26. err);
  27. }
  28. #ifdef CONFIG_DEBUG_FS
  29. static void panfrost_gem_debugfs_bo_add(struct panfrost_device *pfdev,
  30. struct panfrost_gem_object *bo)
  31. {
  32. bo->debugfs.creator.tgid = current->tgid;
  33. get_task_comm(bo->debugfs.creator.process_name, current->group_leader);
  34. mutex_lock(&pfdev->debugfs.gems_lock);
  35. list_add_tail(&bo->debugfs.node, &pfdev->debugfs.gems_list);
  36. mutex_unlock(&pfdev->debugfs.gems_lock);
  37. }
  38. static void panfrost_gem_debugfs_bo_rm(struct panfrost_gem_object *bo)
  39. {
  40. struct panfrost_device *pfdev = to_panfrost_device(bo->base.base.dev);
  41. if (list_empty(&bo->debugfs.node))
  42. return;
  43. mutex_lock(&pfdev->debugfs.gems_lock);
  44. list_del_init(&bo->debugfs.node);
  45. mutex_unlock(&pfdev->debugfs.gems_lock);
  46. }
  47. #else
  48. static void panfrost_gem_debugfs_bo_add(struct panfrost_device *pfdev,
  49. struct panfrost_gem_object *bo)
  50. {}
  51. static void panfrost_gem_debugfs_bo_rm(struct panfrost_gem_object *bo) {}
  52. #endif
  53. /* Called DRM core on the last userspace/kernel unreference of the
  54. * BO.
  55. */
  56. static void panfrost_gem_free_object(struct drm_gem_object *obj)
  57. {
  58. struct panfrost_gem_object *bo = to_panfrost_bo(obj);
  59. struct panfrost_device *pfdev = to_panfrost_device(obj->dev);
  60. /*
  61. * Make sure the BO is no longer inserted in the shrinker list before
  62. * taking care of the destruction itself. If we don't do that we have a
  63. * race condition between this function and what's done in
  64. * panfrost_gem_shrinker_scan().
  65. */
  66. mutex_lock(&pfdev->shrinker_lock);
  67. list_del_init(&bo->base.madv_list);
  68. mutex_unlock(&pfdev->shrinker_lock);
  69. /*
  70. * If we still have mappings attached to the BO, there's a problem in
  71. * our refcounting.
  72. */
  73. WARN_ON_ONCE(!list_empty(&bo->mappings.list));
  74. kfree_const(bo->label.str);
  75. panfrost_gem_debugfs_bo_rm(bo);
  76. mutex_destroy(&bo->label.lock);
  77. if (bo->sgts) {
  78. int i;
  79. int n_sgt = bo->base.base.size / SZ_2M;
  80. for (i = 0; i < n_sgt; i++) {
  81. if (bo->sgts[i].sgl) {
  82. dma_unmap_sgtable(pfdev->base.dev, &bo->sgts[i],
  83. DMA_BIDIRECTIONAL, 0);
  84. sg_free_table(&bo->sgts[i]);
  85. }
  86. }
  87. kvfree(bo->sgts);
  88. }
  89. drm_gem_shmem_free(&bo->base);
  90. }
  91. struct panfrost_gem_mapping *
  92. panfrost_gem_mapping_get(struct panfrost_gem_object *bo,
  93. struct panfrost_file_priv *priv)
  94. {
  95. struct panfrost_gem_mapping *iter, *mapping = NULL;
  96. mutex_lock(&bo->mappings.lock);
  97. list_for_each_entry(iter, &bo->mappings.list, node) {
  98. if (iter->mmu == priv->mmu) {
  99. kref_get(&iter->refcount);
  100. mapping = iter;
  101. break;
  102. }
  103. }
  104. mutex_unlock(&bo->mappings.lock);
  105. return mapping;
  106. }
  107. static void
  108. panfrost_gem_teardown_mapping(struct panfrost_gem_mapping *mapping)
  109. {
  110. if (mapping->active)
  111. panfrost_mmu_unmap(mapping);
  112. spin_lock(&mapping->mmu->mm_lock);
  113. if (drm_mm_node_allocated(&mapping->mmnode))
  114. drm_mm_remove_node(&mapping->mmnode);
  115. spin_unlock(&mapping->mmu->mm_lock);
  116. }
  117. static void panfrost_gem_mapping_release(struct kref *kref)
  118. {
  119. struct panfrost_gem_mapping *mapping;
  120. mapping = container_of(kref, struct panfrost_gem_mapping, refcount);
  121. panfrost_gem_teardown_mapping(mapping);
  122. drm_gem_object_put(&mapping->obj->base.base);
  123. panfrost_mmu_ctx_put(mapping->mmu);
  124. kfree(mapping);
  125. }
  126. void panfrost_gem_mapping_put(struct panfrost_gem_mapping *mapping)
  127. {
  128. if (!mapping)
  129. return;
  130. kref_put(&mapping->refcount, panfrost_gem_mapping_release);
  131. }
  132. void panfrost_gem_teardown_mappings_locked(struct panfrost_gem_object *bo)
  133. {
  134. struct panfrost_gem_mapping *mapping;
  135. list_for_each_entry(mapping, &bo->mappings.list, node)
  136. panfrost_gem_teardown_mapping(mapping);
  137. }
  138. int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_priv)
  139. {
  140. int ret;
  141. size_t size = obj->size;
  142. u64 align;
  143. struct panfrost_gem_object *bo = to_panfrost_bo(obj);
  144. unsigned long color = bo->noexec ? PANFROST_BO_NOEXEC : 0;
  145. struct panfrost_file_priv *priv = file_priv->driver_priv;
  146. struct panfrost_gem_mapping *mapping;
  147. mapping = kzalloc_obj(*mapping);
  148. if (!mapping)
  149. return -ENOMEM;
  150. INIT_LIST_HEAD(&mapping->node);
  151. kref_init(&mapping->refcount);
  152. drm_gem_object_get(obj);
  153. mapping->obj = bo;
  154. /*
  155. * Executable buffers cannot cross a 16MB boundary as the program
  156. * counter is 24-bits. We assume executable buffers will be less than
  157. * 16MB and aligning executable buffers to their size will avoid
  158. * crossing a 16MB boundary.
  159. */
  160. if (!bo->noexec)
  161. align = size >> PAGE_SHIFT;
  162. else
  163. align = size >= SZ_2M ? SZ_2M >> PAGE_SHIFT : 0;
  164. mapping->mmu = panfrost_mmu_ctx_get(priv->mmu);
  165. spin_lock(&mapping->mmu->mm_lock);
  166. ret = drm_mm_insert_node_generic(&mapping->mmu->mm, &mapping->mmnode,
  167. size >> PAGE_SHIFT, align, color, 0);
  168. spin_unlock(&mapping->mmu->mm_lock);
  169. if (ret)
  170. goto err;
  171. if (!bo->is_heap) {
  172. ret = panfrost_mmu_map(mapping);
  173. if (ret)
  174. goto err;
  175. }
  176. mutex_lock(&bo->mappings.lock);
  177. WARN_ON(bo->base.madv != PANFROST_MADV_WILLNEED);
  178. list_add_tail(&mapping->node, &bo->mappings.list);
  179. mutex_unlock(&bo->mappings.lock);
  180. err:
  181. if (ret)
  182. panfrost_gem_mapping_put(mapping);
  183. return ret;
  184. }
  185. void panfrost_gem_close(struct drm_gem_object *obj, struct drm_file *file_priv)
  186. {
  187. struct panfrost_file_priv *priv = file_priv->driver_priv;
  188. struct panfrost_gem_object *bo = to_panfrost_bo(obj);
  189. struct panfrost_gem_mapping *mapping = NULL, *iter;
  190. mutex_lock(&bo->mappings.lock);
  191. list_for_each_entry(iter, &bo->mappings.list, node) {
  192. if (iter->mmu == priv->mmu) {
  193. mapping = iter;
  194. list_del(&iter->node);
  195. break;
  196. }
  197. }
  198. mutex_unlock(&bo->mappings.lock);
  199. panfrost_gem_mapping_put(mapping);
  200. }
  201. static int panfrost_gem_pin(struct drm_gem_object *obj)
  202. {
  203. struct panfrost_gem_object *bo = to_panfrost_bo(obj);
  204. if (bo->is_heap)
  205. return -EINVAL;
  206. return drm_gem_shmem_pin_locked(&bo->base);
  207. }
  208. static enum drm_gem_object_status panfrost_gem_status(struct drm_gem_object *obj)
  209. {
  210. struct panfrost_gem_object *bo = to_panfrost_bo(obj);
  211. enum drm_gem_object_status res = 0;
  212. if (drm_gem_is_imported(&bo->base.base) || bo->base.pages)
  213. res |= DRM_GEM_OBJECT_RESIDENT;
  214. if (bo->base.madv == PANFROST_MADV_DONTNEED)
  215. res |= DRM_GEM_OBJECT_PURGEABLE;
  216. return res;
  217. }
  218. static size_t panfrost_gem_rss(struct drm_gem_object *obj)
  219. {
  220. struct panfrost_gem_object *bo = to_panfrost_bo(obj);
  221. if (bo->is_heap) {
  222. return bo->heap_rss_size;
  223. } else if (bo->base.pages) {
  224. WARN_ON(bo->heap_rss_size);
  225. return bo->base.base.size;
  226. }
  227. return 0;
  228. }
  229. static struct sg_table *
  230. panfrost_gem_prime_map_dma_buf(struct dma_buf_attachment *attach,
  231. enum dma_data_direction dir)
  232. {
  233. struct sg_table *sgt = drm_gem_map_dma_buf(attach, dir);
  234. if (!IS_ERR(sgt))
  235. attach->priv = sgt;
  236. return sgt;
  237. }
  238. static void
  239. panfrost_gem_prime_unmap_dma_buf(struct dma_buf_attachment *attach,
  240. struct sg_table *sgt,
  241. enum dma_data_direction dir)
  242. {
  243. attach->priv = NULL;
  244. drm_gem_unmap_dma_buf(attach, sgt, dir);
  245. }
  246. static int
  247. panfrost_gem_prime_begin_cpu_access(struct dma_buf *dma_buf,
  248. enum dma_data_direction dir)
  249. {
  250. struct drm_gem_object *obj = dma_buf->priv;
  251. struct drm_device *dev = obj->dev;
  252. struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
  253. struct dma_buf_attachment *attach;
  254. dma_resv_lock(obj->resv, NULL);
  255. if (shmem->sgt)
  256. dma_sync_sgtable_for_cpu(dev->dev, shmem->sgt, dir);
  257. if (shmem->vaddr)
  258. invalidate_kernel_vmap_range(shmem->vaddr, shmem->base.size);
  259. list_for_each_entry(attach, &dma_buf->attachments, node) {
  260. struct sg_table *sgt = attach->priv;
  261. if (sgt)
  262. dma_sync_sgtable_for_cpu(attach->dev, sgt, dir);
  263. }
  264. dma_resv_unlock(obj->resv);
  265. return 0;
  266. }
  267. static int
  268. panfrost_gem_prime_end_cpu_access(struct dma_buf *dma_buf,
  269. enum dma_data_direction dir)
  270. {
  271. struct drm_gem_object *obj = dma_buf->priv;
  272. struct drm_device *dev = obj->dev;
  273. struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
  274. struct dma_buf_attachment *attach;
  275. dma_resv_lock(obj->resv, NULL);
  276. list_for_each_entry(attach, &dma_buf->attachments, node) {
  277. struct sg_table *sgt = attach->priv;
  278. if (sgt)
  279. dma_sync_sgtable_for_device(attach->dev, sgt, dir);
  280. }
  281. if (shmem->vaddr)
  282. flush_kernel_vmap_range(shmem->vaddr, shmem->base.size);
  283. if (shmem->sgt)
  284. dma_sync_sgtable_for_device(dev->dev, shmem->sgt, dir);
  285. dma_resv_unlock(obj->resv);
  286. return 0;
  287. }
  288. static const struct dma_buf_ops panfrost_dma_buf_ops = {
  289. .attach = drm_gem_map_attach,
  290. .detach = drm_gem_map_detach,
  291. .map_dma_buf = panfrost_gem_prime_map_dma_buf,
  292. .unmap_dma_buf = panfrost_gem_prime_unmap_dma_buf,
  293. .release = drm_gem_dmabuf_release,
  294. .mmap = drm_gem_dmabuf_mmap,
  295. .vmap = drm_gem_dmabuf_vmap,
  296. .vunmap = drm_gem_dmabuf_vunmap,
  297. .begin_cpu_access = panfrost_gem_prime_begin_cpu_access,
  298. .end_cpu_access = panfrost_gem_prime_end_cpu_access,
  299. };
  300. static struct dma_buf *
  301. panfrost_gem_prime_export(struct drm_gem_object *obj, int flags)
  302. {
  303. struct drm_device *dev = obj->dev;
  304. struct dma_buf_export_info exp_info = {
  305. .exp_name = KBUILD_MODNAME,
  306. .owner = THIS_MODULE,
  307. .ops = &panfrost_dma_buf_ops,
  308. .size = obj->size,
  309. .flags = flags,
  310. .priv = obj,
  311. .resv = obj->resv,
  312. };
  313. return drm_gem_dmabuf_export(dev, &exp_info);
  314. }
  315. struct drm_gem_object *
  316. panfrost_gem_prime_import(struct drm_device *dev,
  317. struct dma_buf *dma_buf)
  318. {
  319. struct drm_gem_object *obj = dma_buf->priv;
  320. if (dma_buf->ops == &panfrost_dma_buf_ops && obj->dev == dev) {
  321. /* Importing dmabuf exported from our own gem increases
  322. * refcount on gem itself instead of f_count of dmabuf.
  323. */
  324. drm_gem_object_get(obj);
  325. return obj;
  326. }
  327. return drm_gem_prime_import(dev, dma_buf);
  328. }
  329. static const struct drm_gem_object_funcs panfrost_gem_funcs = {
  330. .free = panfrost_gem_free_object,
  331. .open = panfrost_gem_open,
  332. .close = panfrost_gem_close,
  333. .print_info = drm_gem_shmem_object_print_info,
  334. .pin = panfrost_gem_pin,
  335. .unpin = drm_gem_shmem_object_unpin,
  336. .get_sg_table = drm_gem_shmem_object_get_sg_table,
  337. .export = panfrost_gem_prime_export,
  338. .vmap = drm_gem_shmem_object_vmap,
  339. .vunmap = drm_gem_shmem_object_vunmap,
  340. .mmap = drm_gem_shmem_object_mmap,
  341. .status = panfrost_gem_status,
  342. .rss = panfrost_gem_rss,
  343. .vm_ops = &drm_gem_shmem_vm_ops,
  344. };
  345. /**
  346. * panfrost_gem_create_object - Implementation of driver->gem_create_object.
  347. * @dev: DRM device
  348. * @size: Size in bytes of the memory the object will reference
  349. *
  350. * This lets the GEM helpers allocate object structs for us, and keep
  351. * our BO stats correct.
  352. */
  353. struct drm_gem_object *panfrost_gem_create_object(struct drm_device *dev, size_t size)
  354. {
  355. struct panfrost_device *pfdev = to_panfrost_device(dev);
  356. struct panfrost_gem_object *obj;
  357. obj = kzalloc_obj(*obj);
  358. if (!obj)
  359. return ERR_PTR(-ENOMEM);
  360. INIT_LIST_HEAD(&obj->mappings.list);
  361. mutex_init(&obj->mappings.lock);
  362. obj->base.base.funcs = &panfrost_gem_funcs;
  363. obj->base.map_wc = !pfdev->coherent;
  364. mutex_init(&obj->label.lock);
  365. panfrost_gem_debugfs_bo_add(pfdev, obj);
  366. return &obj->base.base;
  367. }
  368. static bool
  369. should_map_wc(struct panfrost_gem_object *bo)
  370. {
  371. struct panfrost_device *pfdev = to_panfrost_device(bo->base.base.dev);
  372. /* We can't do uncached mappings if the device is coherent,
  373. * because the zeroing done by the shmem layer at page allocation
  374. * time happens on a cached mapping which isn't CPU-flushed (at least
  375. * not on Arm64 where the flush is deferred to PTE setup time, and
  376. * only done conditionally based on the mapping permissions). We can't
  377. * rely on dma_map_sgtable()/dma_sync_sgtable_for_xxx() either to flush
  378. * those, because they are NOPed if dma_dev_coherent() returns true.
  379. */
  380. if (pfdev->coherent)
  381. return false;
  382. /* Cached mappings are explicitly requested, so no write-combine. */
  383. if (bo->wb_mmap)
  384. return false;
  385. /* The default is write-combine. */
  386. return true;
  387. }
  388. struct panfrost_gem_object *
  389. panfrost_gem_create(struct drm_device *dev, size_t size, u32 flags)
  390. {
  391. struct drm_gem_shmem_object *shmem;
  392. struct panfrost_gem_object *bo;
  393. /* The heap buffer is not supposed to be CPU-visible, so don't allow
  394. * WB_MMAP on those.
  395. */
  396. if ((flags & PANFROST_BO_HEAP) && (flags & PANFROST_BO_WB_MMAP))
  397. return ERR_PTR(-EINVAL);
  398. /* Round up heap allocations to 2MB to keep fault handling simple */
  399. if (flags & PANFROST_BO_HEAP)
  400. size = roundup(size, SZ_2M);
  401. shmem = drm_gem_shmem_create(dev, size);
  402. if (IS_ERR(shmem))
  403. return ERR_CAST(shmem);
  404. bo = to_panfrost_bo(&shmem->base);
  405. bo->noexec = !!(flags & PANFROST_BO_NOEXEC);
  406. bo->is_heap = !!(flags & PANFROST_BO_HEAP);
  407. bo->wb_mmap = !!(flags & PANFROST_BO_WB_MMAP);
  408. bo->base.map_wc = should_map_wc(bo);
  409. return bo;
  410. }
  411. struct drm_gem_object *
  412. panfrost_gem_prime_import_sg_table(struct drm_device *dev,
  413. struct dma_buf_attachment *attach,
  414. struct sg_table *sgt)
  415. {
  416. struct drm_gem_object *obj;
  417. struct panfrost_gem_object *bo;
  418. obj = drm_gem_shmem_prime_import_sg_table(dev, attach, sgt);
  419. if (IS_ERR(obj))
  420. return ERR_CAST(obj);
  421. bo = to_panfrost_bo(obj);
  422. bo->noexec = true;
  423. /*
  424. * We assign this generic label because this function cannot
  425. * be reached through any of the Panfrost UM driver-specific
  426. * code paths, unless one is given by explicitly calling the
  427. * SET_LABEL_BO ioctl. It is therefore preferable to have a
  428. * blanket BO tag that tells us the object was imported from
  429. * another driver than nothing at all.
  430. */
  431. panfrost_gem_internal_set_label(obj, "GEM PRIME buffer");
  432. return obj;
  433. }
  434. void
  435. panfrost_gem_set_label(struct drm_gem_object *obj, const char *label)
  436. {
  437. struct panfrost_gem_object *bo = to_panfrost_bo(obj);
  438. const char *old_label;
  439. scoped_guard(mutex, &bo->label.lock) {
  440. old_label = bo->label.str;
  441. bo->label.str = label;
  442. }
  443. kfree_const(old_label);
  444. }
  445. int
  446. panfrost_gem_sync(struct drm_gem_object *obj, u32 type, u32 offset, u32 size)
  447. {
  448. struct panfrost_gem_object *bo = to_panfrost_bo(obj);
  449. struct drm_gem_shmem_object *shmem = &bo->base;
  450. const struct drm_device *dev = shmem->base.dev;
  451. struct sg_table *sgt;
  452. struct scatterlist *sgl;
  453. unsigned int count;
  454. /* Make sure the range is in bounds. */
  455. if (offset + size < offset || offset + size > shmem->base.size)
  456. return -EINVAL;
  457. /* Disallow CPU-cache maintenance on imported buffers. */
  458. if (drm_gem_is_imported(&shmem->base))
  459. return -EINVAL;
  460. switch (type) {
  461. case PANFROST_BO_SYNC_CPU_CACHE_FLUSH:
  462. case PANFROST_BO_SYNC_CPU_CACHE_FLUSH_AND_INVALIDATE:
  463. break;
  464. default:
  465. return -EINVAL;
  466. }
  467. /* Don't bother if it's WC-mapped */
  468. if (shmem->map_wc)
  469. return 0;
  470. /* Nothing to do if the size is zero. */
  471. if (size == 0)
  472. return 0;
  473. sgt = drm_gem_shmem_get_pages_sgt(shmem);
  474. if (IS_ERR(sgt))
  475. return PTR_ERR(sgt);
  476. for_each_sgtable_dma_sg(sgt, sgl, count) {
  477. if (size == 0)
  478. break;
  479. dma_addr_t paddr = sg_dma_address(sgl);
  480. size_t len = sg_dma_len(sgl);
  481. if (len <= offset) {
  482. offset -= len;
  483. continue;
  484. }
  485. paddr += offset;
  486. len -= offset;
  487. len = min_t(size_t, len, size);
  488. size -= len;
  489. offset = 0;
  490. /* It's unclear whether dma_sync_xxx() is the right API to do CPU
  491. * cache maintenance given an IOMMU can register their own
  492. * implementation doing more than just CPU cache flushes/invalidation,
  493. * and what we really care about here is CPU caches only, but that's
  494. * the best we have that is both arch-agnostic and does at least the
  495. * CPU cache maintenance on a <page,offset,size> tuple.
  496. *
  497. * Also, I wish we could do a single
  498. *
  499. * dma_sync_single_for_device(BIDIR)
  500. *
  501. * and get a flush+invalidate, but that's not how it's implemented
  502. * in practice (at least on arm64), so we have to make it
  503. *
  504. * dma_sync_single_for_device(TO_DEVICE)
  505. * dma_sync_single_for_cpu(FROM_DEVICE)
  506. *
  507. * for the flush+invalidate case.
  508. */
  509. dma_sync_single_for_device(dev->dev, paddr, len, DMA_TO_DEVICE);
  510. if (type == PANFROST_BO_SYNC_CPU_CACHE_FLUSH_AND_INVALIDATE)
  511. dma_sync_single_for_cpu(dev->dev, paddr, len, DMA_FROM_DEVICE);
  512. }
  513. return 0;
  514. }
  515. void
  516. panfrost_gem_internal_set_label(struct drm_gem_object *obj, const char *label)
  517. {
  518. struct panfrost_gem_object *bo = to_panfrost_bo(obj);
  519. const char *str;
  520. /* We should never attempt labelling a UM-exposed GEM object */
  521. if (drm_WARN_ON(bo->base.base.dev, bo->base.base.handle_count > 0))
  522. return;
  523. if (!label)
  524. return;
  525. str = kstrdup_const(label, GFP_KERNEL);
  526. if (!str) {
  527. /* Failing to allocate memory for a label isn't a fatal condition */
  528. drm_warn(bo->base.base.dev, "Not enough memory to allocate BO label");
  529. return;
  530. }
  531. panfrost_gem_set_label(obj, str);
  532. }
  533. #ifdef CONFIG_DEBUG_FS
  534. struct gem_size_totals {
  535. size_t size;
  536. size_t resident;
  537. size_t reclaimable;
  538. };
  539. struct flag_def {
  540. u32 flag;
  541. const char *name;
  542. };
  543. static void panfrost_gem_debugfs_print_flag_names(struct seq_file *m)
  544. {
  545. int len;
  546. int i;
  547. static const struct flag_def gem_state_flags_names[] = {
  548. {PANFROST_DEBUGFS_GEM_STATE_FLAG_IMPORTED, "imported"},
  549. {PANFROST_DEBUGFS_GEM_STATE_FLAG_EXPORTED, "exported"},
  550. {PANFROST_DEBUGFS_GEM_STATE_FLAG_PURGED, "purged"},
  551. {PANFROST_DEBUGFS_GEM_STATE_FLAG_PURGEABLE, "purgeable"},
  552. };
  553. seq_puts(m, "GEM state flags: ");
  554. for (i = 0, len = ARRAY_SIZE(gem_state_flags_names); i < len; i++) {
  555. seq_printf(m, "%s (0x%x)%s", gem_state_flags_names[i].name,
  556. gem_state_flags_names[i].flag, (i < len - 1) ? ", " : "\n\n");
  557. }
  558. }
  559. static void panfrost_gem_debugfs_bo_print(struct panfrost_gem_object *bo,
  560. struct seq_file *m,
  561. struct gem_size_totals *totals)
  562. {
  563. unsigned int refcount = kref_read(&bo->base.base.refcount);
  564. char creator_info[32] = {};
  565. size_t resident_size;
  566. u32 gem_state_flags = 0;
  567. /* Skip BOs being destroyed. */
  568. if (!refcount)
  569. return;
  570. resident_size = panfrost_gem_rss(&bo->base.base);
  571. snprintf(creator_info, sizeof(creator_info),
  572. "%s/%d", bo->debugfs.creator.process_name, bo->debugfs.creator.tgid);
  573. seq_printf(m, "%-32s%-16d%-16d%-16zd%-16zd0x%-16lx",
  574. creator_info,
  575. bo->base.base.name,
  576. refcount,
  577. bo->base.base.size,
  578. resident_size,
  579. drm_vma_node_start(&bo->base.base.vma_node));
  580. if (bo->base.base.import_attach)
  581. gem_state_flags |= PANFROST_DEBUGFS_GEM_STATE_FLAG_IMPORTED;
  582. if (bo->base.base.dma_buf)
  583. gem_state_flags |= PANFROST_DEBUGFS_GEM_STATE_FLAG_EXPORTED;
  584. if (bo->base.madv < 0)
  585. gem_state_flags |= PANFROST_DEBUGFS_GEM_STATE_FLAG_PURGED;
  586. else if (bo->base.madv > 0)
  587. gem_state_flags |= PANFROST_DEBUGFS_GEM_STATE_FLAG_PURGEABLE;
  588. seq_printf(m, "0x%-10x", gem_state_flags);
  589. scoped_guard(mutex, &bo->label.lock) {
  590. seq_printf(m, "%s\n", bo->label.str ? : "");
  591. }
  592. totals->size += bo->base.base.size;
  593. totals->resident += resident_size;
  594. if (bo->base.madv > 0)
  595. totals->reclaimable += resident_size;
  596. }
  597. void panfrost_gem_debugfs_print_bos(struct panfrost_device *pfdev,
  598. struct seq_file *m)
  599. {
  600. struct gem_size_totals totals = {0};
  601. struct panfrost_gem_object *bo;
  602. panfrost_gem_debugfs_print_flag_names(m);
  603. seq_puts(m, "created-by global-name refcount size resident-size file-offset state label\n");
  604. seq_puts(m, "-----------------------------------------------------------------------------------------------------------------------------------\n");
  605. scoped_guard(mutex, &pfdev->debugfs.gems_lock) {
  606. list_for_each_entry(bo, &pfdev->debugfs.gems_list, debugfs.node) {
  607. panfrost_gem_debugfs_bo_print(bo, m, &totals);
  608. }
  609. }
  610. seq_puts(m, "===================================================================================================================================\n");
  611. seq_printf(m, "Total size: %zd, Total resident: %zd, Total reclaimable: %zd\n",
  612. totals.size, totals.resident, totals.reclaimable);
  613. }
  614. #endif