* [RFC][PATCH v6 6/7] dma-buf: system_heap: Add drm pagepool support to system heap
@ 2021-02-05 8:06 ` John Stultz
0 siblings, 0 replies; 6+ messages in thread
From: John Stultz @ 2021-02-05 8:06 UTC (permalink / raw)
To: lkml
Cc: John Stultz, Daniel Vetter, Christian Koenig, Sumit Semwal,
Liam Mark, Chris Goldsworthy, Laura Abbott, Brian Starkey,
Hridya Valsaraju, Suren Baghdasaryan, Sandeep Patil, Daniel Mentz,
Ørjan Eide, Robin Murphy, Ezequiel Garcia, Simon Ser,
James Jones, linux-media, dri-devel
Utilize the drm pagepool code to speed up allocation
performance.
This is similar to the ION pagepool usage, but tries to
utilize generic code instead of a custom implementation.
Cc: Daniel Vetter <daniel@ffwll.ch>
Cc: Christian Koenig <christian.koenig@amd.com>
Cc: Sumit Semwal <sumit.semwal@linaro.org>
Cc: Liam Mark <lmark@codeaurora.org>
Cc: Chris Goldsworthy <cgoldswo@codeaurora.org>
Cc: Laura Abbott <labbott@kernel.org>
Cc: Brian Starkey <Brian.Starkey@arm.com>
Cc: Hridya Valsaraju <hridya@google.com>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Sandeep Patil <sspatil@google.com>
Cc: Daniel Mentz <danielmentz@google.com>
Cc: Ørjan Eide <orjan.eide@arm.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Ezequiel Garcia <ezequiel@collabora.com>
Cc: Simon Ser <contact@emersion.fr>
Cc: James Jones <jajones@nvidia.com>
Cc: linux-media@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
Signed-off-by: John Stultz <john.stultz@linaro.org>
---
v2:
* Fix build issue caused by selecting PAGE_POOL w/o NET
as Reported-by: kernel test robot <lkp@intel.com>
v3:
* Simplify the page zeroing logic a bit by using kmap_atomic
instead of vmap as suggested by Daniel Mentz
v5:
* Shift away from networking page pool completely to
dmabuf page pool implementation
v6:
* Switch again to using the drm_page_pool code shared w/
ttm_pool
---
drivers/dma-buf/heaps/Kconfig | 1 +
drivers/dma-buf/heaps/system_heap.c | 56 +++++++++++++++++++++++++++--
2 files changed, 54 insertions(+), 3 deletions(-)
diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index f7aef8bc7119..7e28934e0def 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -4,6 +4,7 @@ config DMABUF_HEAPS_DEFERRED_FREE
config DMABUF_HEAPS_SYSTEM
bool "DMA-BUF System Heap"
depends on DMABUF_HEAPS
+ select DRM_PAGE_POOL
help
Choose this option to enable the system dmabuf heap. The system heap
is backed by pages from the buddy allocator. If in doubt, say Y.
diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c
index 17e0e9a68baf..6d39e9f32e36 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -21,6 +21,8 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
+#include <drm/page_pool.h>
+
static struct dma_heap *sys_heap;
struct system_heap_buffer {
@@ -53,6 +55,7 @@ static gfp_t order_flags[] = {HIGH_ORDER_GFP, LOW_ORDER_GFP, LOW_ORDER_GFP};
*/
static const unsigned int orders[] = {8, 4, 0};
#define NUM_ORDERS ARRAY_SIZE(orders)
+struct drm_page_pool *pools[NUM_ORDERS];
static struct sg_table *dup_sg_table(struct sg_table *table)
{
@@ -281,18 +284,49 @@ static void system_heap_vunmap(struct dma_buf *dmabuf, struct dma_buf_map *map)
dma_buf_map_clear(map);
}
+static int system_heap_free_pages(struct page *p, unsigned int order)
+{
+ __free_pages(p, order);
+ return 1 << order;
+}
+
+static int system_heap_zero_buffer(struct system_heap_buffer *buffer)
+{
+ struct sg_table *sgt = &buffer->sg_table;
+ struct sg_page_iter piter;
+ struct page *p;
+ void *vaddr;
+ int ret = 0;
+
+ for_each_sgtable_page(sgt, &piter, 0) {
+ p = sg_page_iter_page(&piter);
+ vaddr = kmap_atomic(p);
+ memset(vaddr, 0, PAGE_SIZE);
+ kunmap_atomic(vaddr);
+ }
+
+ return ret;
+}
+
static void system_heap_dma_buf_release(struct dma_buf *dmabuf)
{
struct system_heap_buffer *buffer = dmabuf->priv;
struct sg_table *table;
struct scatterlist *sg;
- int i;
+ int i, j;
+
+ /* Zero the buffer pages before adding back to the pool */
+ system_heap_zero_buffer(buffer);
table = &buffer->sg_table;
for_each_sg(table->sgl, sg, table->nents, i) {
struct page *page = sg_page(sg);
- __free_pages(page, compound_order(page));
+ for (j = 0; j < NUM_ORDERS; j++) {
+ if (compound_order(page) == orders[j])
+ break;
+ }
+ drm_page_pool_add(pools[j], page);
}
sg_free_table(table);
kfree(buffer);
@@ -323,7 +357,9 @@ static struct page *alloc_largest_available(unsigned long size,
if (max_order < orders[i])
continue;
- page = alloc_pages(order_flags[i], orders[i]);
+ page = drm_page_pool_fetch(pools[i]);
+ if (!page)
+ page = alloc_pages(order_flags[i], orders[i]);
if (!page)
continue;
return page;
@@ -428,6 +464,20 @@ static const struct dma_heap_ops system_heap_ops = {
static int system_heap_create(void)
{
struct dma_heap_export_info exp_info;
+ int i;
+
+ for (i = 0; i < NUM_ORDERS; i++) {
+ pools[i] = drm_page_pool_create(orders[i],
+ system_heap_free_pages);
+ if (IS_ERR(pools[i])) {
+ int j;
+
+ pr_err("%s: page pool creation failed!\n", __func__);
+ for (j = 0; j < i; j++)
+ drm_page_pool_destroy(pools[j]);
+ return PTR_ERR(pools[i]);
+ }
+ }
exp_info.name = "system";
exp_info.ops = &system_heap_ops;
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [RFC][PATCH v6 6/7] dma-buf: system_heap: Add drm pagepool support to system heap
2021-02-05 8:06 ` John Stultz
(?)
@ 2021-02-05 11:13 ` kernel test robot
-1 siblings, 0 replies; 6+ messages in thread
From: kernel test robot @ 2021-02-05 11:13 UTC (permalink / raw)
To: kbuild-all
[-- Attachment #1: Type: text/plain, Size: 7923 bytes --]
Hi John,
[FYI, it's a private test report for your RFC patch.]
[auto build test ERROR on linux/master]
[also build test ERROR on linus/master v5.11-rc6]
[cannot apply to drm-intel/for-linux-next drm-tip/drm-tip drm-exynos/exynos-drm-next tegra-drm/drm/tegra/for-next drm/drm-next next-20210125]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/John-Stultz/Generic-page-pool-deferred-freeing-for-system-dmabuf-heap/20210205-160846
base: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 2ab38c17aac10bf55ab3efde4c4db3893d8691d2
config: i386-randconfig-s001-20210205 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-15) 9.3.0
reproduce:
# apt-get install sparse
# sparse version: v0.6.3-215-g0fb77bb6-dirty
# https://github.com/0day-ci/linux/commit/47bdae8428bf2e9710c79eafb451beb9a184f2c9
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review John-Stultz/Generic-page-pool-deferred-freeing-for-system-dmabuf-heap/20210205-160846
git checkout 47bdae8428bf2e9710c79eafb451beb9a184f2c9
# save the attached .config to linux build tree
make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=i386
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
All errors (new ones prefixed by >>):
ld: drivers/dma-buf/heaps/system_heap.o: in function `system_heap_create':
>> drivers/dma-buf/heaps/system_heap.c:470: undefined reference to `drm_page_pool_create'
ld: drivers/dma-buf/heaps/system_heap.o: in function `system_heap_dma_buf_release':
>> drivers/dma-buf/heaps/system_heap.c:329: undefined reference to `drm_page_pool_add'
ld: drivers/dma-buf/heaps/system_heap.o: in function `alloc_largest_available':
>> drivers/dma-buf/heaps/system_heap.c:360: undefined reference to `drm_page_pool_fetch'
ld: drivers/dma-buf/heaps/system_heap.o: in function `system_heap_create':
>> drivers/dma-buf/heaps/system_heap.c:477: undefined reference to `drm_page_pool_destroy'
Kconfig warnings: (for reference only)
WARNING: unmet direct dependencies detected for DRM_PAGE_POOL
Depends on HAS_IOMEM && DRM
Selected by
- DMABUF_HEAPS_SYSTEM && DMABUF_HEAPS
vim +470 drivers/dma-buf/heaps/system_heap.c
310
311 static void system_heap_dma_buf_release(struct dma_buf *dmabuf)
312 {
313 struct system_heap_buffer *buffer = dmabuf->priv;
314 struct sg_table *table;
315 struct scatterlist *sg;
316 int i, j;
317
318 /* Zero the buffer pages before adding back to the pool */
319 system_heap_zero_buffer(buffer);
320
321 table = &buffer->sg_table;
322 for_each_sg(table->sgl, sg, table->nents, i) {
323 struct page *page = sg_page(sg);
324
325 for (j = 0; j < NUM_ORDERS; j++) {
326 if (compound_order(page) == orders[j])
327 break;
328 }
> 329 drm_page_pool_add(pools[j], page);
330 }
331 sg_free_table(table);
332 kfree(buffer);
333 }
334
335 static const struct dma_buf_ops system_heap_buf_ops = {
336 .attach = system_heap_attach,
337 .detach = system_heap_detach,
338 .map_dma_buf = system_heap_map_dma_buf,
339 .unmap_dma_buf = system_heap_unmap_dma_buf,
340 .begin_cpu_access = system_heap_dma_buf_begin_cpu_access,
341 .end_cpu_access = system_heap_dma_buf_end_cpu_access,
342 .mmap = system_heap_mmap,
343 .vmap = system_heap_vmap,
344 .vunmap = system_heap_vunmap,
345 .release = system_heap_dma_buf_release,
346 };
347
348 static struct page *alloc_largest_available(unsigned long size,
349 unsigned int max_order)
350 {
351 struct page *page;
352 int i;
353
354 for (i = 0; i < NUM_ORDERS; i++) {
355 if (size < (PAGE_SIZE << orders[i]))
356 continue;
357 if (max_order < orders[i])
358 continue;
359
> 360 page = drm_page_pool_fetch(pools[i]);
361 if (!page)
362 page = alloc_pages(order_flags[i], orders[i]);
363 if (!page)
364 continue;
365 return page;
366 }
367 return NULL;
368 }
369
370 static int system_heap_allocate(struct dma_heap *heap,
371 unsigned long len,
372 unsigned long fd_flags,
373 unsigned long heap_flags)
374 {
375 struct system_heap_buffer *buffer;
376 DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
377 unsigned long size_remaining = len;
378 unsigned int max_order = orders[0];
379 struct dma_buf *dmabuf;
380 struct sg_table *table;
381 struct scatterlist *sg;
382 struct list_head pages;
383 struct page *page, *tmp_page;
384 int i, ret = -ENOMEM;
385
386 buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
387 if (!buffer)
388 return -ENOMEM;
389
390 INIT_LIST_HEAD(&buffer->attachments);
391 mutex_init(&buffer->lock);
392 buffer->heap = heap;
393 buffer->len = len;
394
395 INIT_LIST_HEAD(&pages);
396 i = 0;
397 while (size_remaining > 0) {
398 /*
399 * Avoid trying to allocate memory if the process
400 * has been killed by SIGKILL
401 */
402 if (fatal_signal_pending(current))
403 goto free_buffer;
404
405 page = alloc_largest_available(size_remaining, max_order);
406 if (!page)
407 goto free_buffer;
408
409 list_add_tail(&page->lru, &pages);
410 size_remaining -= page_size(page);
411 max_order = compound_order(page);
412 i++;
413 }
414
415 table = &buffer->sg_table;
416 if (sg_alloc_table(table, i, GFP_KERNEL))
417 goto free_buffer;
418
419 sg = table->sgl;
420 list_for_each_entry_safe(page, tmp_page, &pages, lru) {
421 sg_set_page(sg, page, page_size(page), 0);
422 sg = sg_next(sg);
423 list_del(&page->lru);
424 }
425
426 /* create the dmabuf */
427 exp_info.ops = &system_heap_buf_ops;
428 exp_info.size = buffer->len;
429 exp_info.flags = fd_flags;
430 exp_info.priv = buffer;
431 dmabuf = dma_buf_export(&exp_info);
432 if (IS_ERR(dmabuf)) {
433 ret = PTR_ERR(dmabuf);
434 goto free_pages;
435 }
436
437 ret = dma_buf_fd(dmabuf, fd_flags);
438 if (ret < 0) {
439 dma_buf_put(dmabuf);
440 /* just return, as put will call release and that will free */
441 return ret;
442 }
443 return ret;
444
445 free_pages:
446 for_each_sgtable_sg(table, sg, i) {
447 struct page *p = sg_page(sg);
448
449 __free_pages(p, compound_order(p));
450 }
451 sg_free_table(table);
452 free_buffer:
453 list_for_each_entry_safe(page, tmp_page, &pages, lru)
454 __free_pages(page, compound_order(page));
455 kfree(buffer);
456
457 return ret;
458 }
459
460 static const struct dma_heap_ops system_heap_ops = {
461 .allocate = system_heap_allocate,
462 };
463
464 static int system_heap_create(void)
465 {
466 struct dma_heap_export_info exp_info;
467 int i;
468
469 for (i = 0; i < NUM_ORDERS; i++) {
> 470 pools[i] = drm_page_pool_create(orders[i],
471 system_heap_free_pages);
472 if (IS_ERR(pools[i])) {
473 int j;
474
475 pr_err("%s: page pool creation failed!\n", __func__);
476 for (j = 0; j < i; j++)
> 477 drm_page_pool_destroy(pools[j]);
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 28606 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [RFC][PATCH v6 6/7] dma-buf: system_heap: Add drm pagepool support to system heap
2021-02-05 8:06 ` John Stultz
(?)
(?)
@ 2021-02-05 11:22 ` kernel test robot
-1 siblings, 0 replies; 6+ messages in thread
From: kernel test robot @ 2021-02-05 11:22 UTC (permalink / raw)
To: kbuild-all
[-- Attachment #1: Type: text/plain, Size: 2592 bytes --]
Hi John,
[FYI, it's a private test report for your RFC patch.]
[auto build test WARNING on linux/master]
[also build test WARNING on linus/master v5.11-rc6]
[cannot apply to drm-intel/for-linux-next drm-tip/drm-tip drm-exynos/exynos-drm-next tegra-drm/drm/tegra/for-next drm/drm-next next-20210125]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/John-Stultz/Generic-page-pool-deferred-freeing-for-system-dmabuf-heap/20210205-160846
base: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 2ab38c17aac10bf55ab3efde4c4db3893d8691d2
config: mips-randconfig-r033-20210205 (attached as .config)
compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project c9439ca36342fb6013187d0a69aef92736951476)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# install mips cross compiling tool for clang build
# apt-get install binutils-mips-linux-gnu
# https://github.com/0day-ci/linux/commit/47bdae8428bf2e9710c79eafb451beb9a184f2c9
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review John-Stultz/Generic-page-pool-deferred-freeing-for-system-dmabuf-heap/20210205-160846
git checkout 47bdae8428bf2e9710c79eafb451beb9a184f2c9
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=mips
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
All warnings (new ones prefixed by >>):
>> drivers/gpu/drm/page_pool.c:215:5: warning: no previous prototype for function 'drm_page_pool_init_shrinker' [-Wmissing-prototypes]
int drm_page_pool_init_shrinker(void)
^
drivers/gpu/drm/page_pool.c:215:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
int drm_page_pool_init_shrinker(void)
^
static
1 warning generated.
vim +/drm_page_pool_init_shrinker +215 drivers/gpu/drm/page_pool.c
7bd04c721ea25c John Stultz 2021-02-05 214
7bd04c721ea25c John Stultz 2021-02-05 @215 int drm_page_pool_init_shrinker(void)
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 29215 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread