Re: [RFC PATCH v2] ptp: Add vDSO-style vmclock support

2024-06-25 Thread John Stultz
On Tue, Jun 25, 2024 at 2:48 PM David Woodhouse  wrote:
> On Tue, 2024-06-25 at 23:34 +0200, Thomas Gleixner wrote:
> > On Tue, Jun 25 2024 at 20:01, David Woodhouse wrote:
> > > From: David Woodhouse 
> > >
> > > The vmclock "device" provides a shared memory region with precision clock
> > > information. By using shared memory, it is safe across Live Migration.
> > >
> > > Like the KVM PTP clock, this can convert TSC-based cross timestamps into
> > > KVM clock values. Unlike the KVM PTP clock, it does so only when such is
> > > actually helpful.
> > >
> > > The memory region of the device is also exposed to userspace so it can be
> > > read or memory mapped by application which need reliable notification of
> > > clock disruptions.
> >
> > There is effort underway to expose PTP clocks to user space via VDSO.
>
> Ooh, interesting. Got a reference to that please?
>
> >  Can we please not expose an ad hoc interface for that?
>
> Absolutely. I'm explicitly trying to intercept the virtio-rtc
> specification here, to *avoid* having to do anything ad hoc.
>
> Note that this is a "vDSO-style" interface from hypervisor to guest via
> a shared memory region, not necessarily an actual vDSO.
>
> But yes, it *is* intended to be exposed to userspace, so that userspace
> can know the *accurate* time without a system call, and know that it
> hasn't been perturbed by live migration.

Yea, I was going to raise a concern that just defining an mmaped
structure means it has to trust the guest logic is as expected. It's
good that it's versioned! :)

I'd fret a bit about exposing this to userland. It feels very similar
to the old powerpc systemcfg implementation that similarly mapped just
kernel data out to userland and was difficult to maintain as changes
were made. Would including a code page like a proper vdso make sense
to make this more flexible of an UABI to maintain?

thanks
-john



Re: [PATCH] drm/msm: Fix removal of valid error case when checking speed_bin

2021-04-05 Thread John Stultz
On Mon, Mar 29, 2021 at 6:34 PM John Stultz  wrote:
>
> Commit 7bf168c8fe8c  ("drm/msm: Fix speed-bin support not to
> access outside valid memory"), reworked the nvmem reading of
> "speed_bin", but in doing so dropped handling of the -ENOENT
> case which was previously documented as "fine".
>
> That change resulted in the db845c board display to fail to
> start, with the following error:
>
> adreno 500.gpu: [drm:a6xx_gpu_init] *ERROR* failed to read speed-bin 
> (-2). Some OPPs may not be supported by hardware
>
> Thus, this patch simply re-adds the ENOENT handling so the lack
> of the speed_bin entry isn't fatal for display, and gets things
> working on db845c.

Hey Folks,
  Just wanted to re-ping you on this, as it resolves a regression
introduced in 5.12-rc5 and I'm not yet seeing this in -next. Would be
nice to have this in place before 5.12 final.

thanks
-john


[PATCH] drm/msm: Fix removal of valid error case when checking speed_bin

2021-03-29 Thread John Stultz
Commit 7bf168c8fe8c  ("drm/msm: Fix speed-bin support not to
access outside valid memory"), reworked the nvmem reading of
"speed_bin", but in doing so dropped handling of the -ENOENT
case which was previously documented as "fine".

That change resulted in the db845c board display to fail to
start, with the following error:

adreno 500.gpu: [drm:a6xx_gpu_init] *ERROR* failed to read speed-bin (-2). 
Some OPPs may not be supported by hardware

Thus, this patch simply re-adds the ENOENT handling so the lack
of the speed_bin entry isn't fatal for display, and gets things
working on db845c.

Cc: Rob Clark 
Cc: Sean Paul 
Cc: Jordan Crouse 
Cc: Eric Anholt 
Cc: Douglas Anderson 
Cc: linux-arm-...@vger.kernel.org
Cc: freedr...@lists.freedesktop.org
Cc: Bjorn Andersson 
Cc: YongQin Liu 
Reported-by: YongQin Liu 
Fixes: 7bf168c8fe8c  ("drm/msm: Fix speed-bin support not to access outside 
valid memory")
Signed-off-by: John Stultz 
---
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 690409ca8a186..cb2df8736ca85 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -1406,7 +1406,13 @@ static int a6xx_set_supported_hw(struct device *dev, 
struct a6xx_gpu *a6xx_gpu,
int ret;
 
ret = nvmem_cell_read_u16(dev, "speed_bin", );
-   if (ret) {
+   /*
+* -ENOENT means that the platform doesn't support speedbin which is
+* fine
+*/
+   if (ret == -ENOENT) {
+   return 0;
+   } else if (ret) {
DRM_DEV_ERROR(dev,
  "failed to read speed-bin (%d). Some OPPs may not 
be supported by hardware",
  ret);
-- 
2.25.1



Re: [PATCH v3 1/2] usb: dwc3: Trigger a GCTL soft reset when switching modes in DRD

2021-03-29 Thread John Stultz
On Mon, Mar 29, 2021 at 3:15 PM Wesley Cheng  wrote:
>
>
>
> On 3/19/2021 4:09 PM, Thinh Nguyen wrote:
> > Wesley Cheng wrote:
> >>
> >>
> >> On 3/8/2021 10:33 PM, Wesley Cheng wrote:
> >>>
> >>>
> >>> On 3/8/2021 7:05 PM, Thinh Nguyen wrote:
> >>>> Wesley Cheng wrote:
> >>>>>
> >>>>> On 3/6/2021 3:41 PM, Thinh Nguyen wrote:
> >>>>>> Wesley Cheng wrote:
> >>>>>>> On 1/8/2021 4:44 PM, Thinh Nguyen wrote:
> >>>>>>>> Hi,
> >>>>>>>>
> >>>>>>>> John Stultz wrote:
> >>>>>>>>> On Fri, Jan 8, 2021 at 4:26 AM Felipe Balbi  
> >>>>>>>>> wrote:
> >>>>>>>>>> Hi,
> >>>>>>>>>>
> >>>>>>>>>> John Stultz  writes:
> >>>>>>>>>>> From: Yu Chen 
> >>>>>>>>>>>
> >>>>>>>>>>> Just resending this, as discussion died out a bit and I'm not
> >>>>>>>>>>> sure how to make further progress. See here for debug data that
> >>>>>>>>>>> was requested last time around:
> >>>>>>>>>>>   
> >>>>>>>>>>> https://urldefense.com/v3/__https://lore.kernel.org/lkml/calaqxlxdnaufjkx0an9xwwtfwvjmwigppy2aqsnj56yvnbu...@mail.gmail.com/__;!!A4F2R9G_pg!LNzuprAeg-O80SgolYkIkW4-ne-M-yLWCDUY9MygAIrQC398Z6gRJ9wnsnlqd3w$
> >>>>>>>>>>>
> >>>>>>>>>>> With the current dwc3 code on the HiKey960 we often see the
> >>>>>>>>>>> COREIDLE flag get stuck off in __dwc3_gadget_start(), which
> >>>>>>>>>>> seems to prevent the reset irq and causes the USB gadget to
> >>>>>>>>>>> fail to initialize.
> >>>>>>>>>>>
> >>>>>>>>>>> We had seen occasional initialization failures with older
> >>>>>>>>>>> kernels but with recent 5.x era kernels it seemed to be becoming
> >>>>>>>>>>> much more common, so I dug back through some older trees and
> >>>>>>>>>>> realized I dropped this quirk from Yu Chen during upstreaming
> >>>>>>>>>>> as I couldn't provide a proper rational for it and it didn't
> >>>>>>>>>>> seem to be necessary. I now realize I was wrong.
> >>>>>>>>>>>
> >>>>>>>>>>> After resubmitting the quirk, Thinh Nguyen pointed out that it
> >>>>>>>>>>> shouldn't be a quirk at all and it is actually mentioned in the
> >>>>>>>>>>> programming guide that it should be done when switching modes
> >>>>>>>>>>> in DRD.
> >>>>>>>>>>>
> >>>>>>>>>>> So, to avoid these !COREIDLE lockups seen on HiKey960, this
> >>>>>>>>>>> patch issues GCTL soft reset when switching modes if the
> >>>>>>>>>>> controller is in DRD mode.
> >>>>>>>>>>>
> >>>>>>>>>>> Cc: Felipe Balbi 
> >>>>>>>>>>> Cc: Tejas Joglekar 
> >>>>>>>>>>> Cc: Yang Fei 
> >>>>>>>>>>> Cc: YongQin Liu 
> >>>>>>>>>>> Cc: Andrzej Pietrasiewicz 
> >>>>>>>>>>> Cc: Thinh Nguyen 
> >>>>>>>>>>> Cc: Jun Li 
> >>>>>>>>>>> Cc: Mauro Carvalho Chehab 
> >>>>>>>>>>> Cc: Greg Kroah-Hartman 
> >>>>>>>>>>> Cc: linux-...@vger.kernel.org
> >>>>>>>>>>> Signed-off-by: Yu Chen 
> >>>>>>>>>>> Signed-off-by: John Stultz 
> >>>>>>>>>>> ---
> >>>>>>>>>>> v2:
> >>>>>>>>>>> * Rework to always call the GCTL soft reset in DRD mode,
> >>>>>>>>>>>   rather then using a quirk as suggested by Thinh Nguyen
> >>>>>>>>>>>
> >>>

Re: [PATCH] selftests: timers: remove unneeded semicolon

2021-03-15 Thread John Stultz
On Mon, Mar 15, 2021 at 1:08 AM Jiapeng Chong
 wrote:
>
> Fix the following coccicheck warnings:
>
> ./tools/testing/selftests/timers/inconsistency-check.c:75:2-3: Unneeded
> semicolon.
>
> Reported-by: Abaci Robot 
> Signed-off-by: Jiapeng Chong 

No objection here. Thanks for sending this along.

Acked-by: John Stultz 

thanks
-john


Re: [PATCH] selftests/timers: Fix spelling mistake "clocksourc" -> "clocksource"

2021-03-15 Thread John Stultz
On Mon, Mar 15, 2021 at 5:33 AM Colin King  wrote:
>
> From: Colin Ian King 
>
> There is a spelling mistake in a comment. Fix it.
>
> Signed-off-by: Colin Ian King 

Akcde-yb: John Stultz 

I kid, I kid!  My apologies and thanks!

Acked-by: John Stultz 


Re: [PATCH v2 0/3] ASoC: sdm845: array out of bound issues

2021-03-09 Thread John Stultz
On Tue, Mar 9, 2021 at 6:21 AM Srinivas Kandagatla
 wrote:
>
> During testing John Stultz and Amit reported few array our bound issues
> after enabling bound sanitizer
>
> This patch series attempts to fix those!
>
> changes since v1:
> - make sure the wcd is not de-referenced without intialization
>
> Srinivas Kandagatla (3):
>   ASoC: qcom: sdm845: Fix array out of bounds access
>   ASoC: qcom: sdm845: Fix array out of range on rx slim channels
>   ASoC: codecs: wcd934x: add a sanity check in set channel map

For the whole series:
Tested-by: John Stultz 

Thanks so much for fixing these up so fast!
-john


[PATCH v8 5/5] dma-buf: system_heap: Add deferred freeing to the system heap

2021-03-04 Thread John Stultz
Utilize the deferred free helper library in the system heap.

This provides a nice performance bump and puts the
system heap performance on par with ION.

Cc: Daniel Vetter 
Cc: Christian Koenig 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
v2:
* Rework deferred-free api to use reason enum as suggested by
  Suren Baghdasaryan
* Rework for deferred-free api change to use nr_pages rather
  than size as suggsted by Suren Baghdasaryan
v8:
* Reworked to drop buffer zeroing logic, as the drm_page_pool now
  handles that.
---
 drivers/dma-buf/heaps/Kconfig   |  1 +
 drivers/dma-buf/heaps/system_heap.c | 28 ++--
 2 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index 7e28934e0def..10632ccfb4a5 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -5,6 +5,7 @@ config DMABUF_HEAPS_SYSTEM
bool "DMA-BUF System Heap"
depends on DMABUF_HEAPS
select DRM_PAGE_POOL
+   select DMABUF_HEAPS_DEFERRED_FREE
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 006271881d85..c753c82fd9f1 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -22,6 +22,7 @@
 #include 
 
 #include 
+#include "deferred-free-helper.h"
 
 static struct dma_heap *sys_heap;
 
@@ -33,6 +34,7 @@ struct system_heap_buffer {
struct sg_table sg_table;
int vmap_cnt;
void *vaddr;
+   struct deferred_freelist_item deferred_free;
 };
 
 struct dma_heap_attachment {
@@ -290,27 +292,41 @@ static unsigned long system_heap_free_pages(struct 
drm_page_pool *pool, struct p
return 1 << pool->order;
 }
 
-static void system_heap_dma_buf_release(struct dma_buf *dmabuf)
+static void system_heap_buf_free(struct deferred_freelist_item *item,
+enum df_reason reason)
 {
-   struct system_heap_buffer *buffer = dmabuf->priv;
+   struct system_heap_buffer *buffer;
struct sg_table *table;
struct scatterlist *sg;
int i, j;
 
+   buffer = container_of(item, struct system_heap_buffer, deferred_free);
table = >sg_table;
for_each_sg(table->sgl, sg, table->nents, i) {
struct page *page = sg_page(sg);
 
-   for (j = 0; j < NUM_ORDERS; j++) {
-   if (compound_order(page) == orders[j])
-   break;
+   if (reason == DF_UNDER_PRESSURE) {
+   __free_pages(page, compound_order(page));
+   } else {
+   for (j = 0; j < NUM_ORDERS; j++) {
+   if (compound_order(page) == orders[j])
+   break;
+   }
+   drm_page_pool_add([j], page);
}
-   drm_page_pool_add([j], page);
}
sg_free_table(table);
kfree(buffer);
 }
 
+static void system_heap_dma_buf_release(struct dma_buf *dmabuf)
+{
+   struct system_heap_buffer *buffer = dmabuf->priv;
+   int npages = PAGE_ALIGN(buffer->len) / PAGE_SIZE;
+
+   deferred_free(>deferred_free, system_heap_buf_free, npages);
+}
+
 static const struct dma_buf_ops system_heap_buf_ops = {
.attach = system_heap_attach,
.detach = system_heap_detach,
-- 
2.25.1



[PATCH v8 4/5] dma-buf: system_heap: Add drm pagepool support to system heap

2021-03-04 Thread John Stultz
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 
Cc: Christian Koenig 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
v2:
* Fix build issue caused by selecting PAGE_POOL w/o NET
  as Reported-by: kernel test robot 
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
v7:
* Slight rework for drm_page_pool changes
v8:
* Rework to use the rewritten drm_page_pool logic
* Drop explicit buffer zeroing, as the drm_page_pool handles that
---
 drivers/dma-buf/heaps/Kconfig   |  1 +
 drivers/dma-buf/heaps/system_heap.c | 27 ---
 2 files changed, 25 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 29e49ac17251..006271881d85 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -21,6 +21,8 @@
 #include 
 #include 
 
+#include 
+
 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,28 @@ static void system_heap_vunmap(struct dma_buf *dmabuf, 
struct dma_buf_map *map)
dma_buf_map_clear(map);
 }
 
+static unsigned long system_heap_free_pages(struct drm_page_pool *pool, struct 
page *p)
+{
+   __free_pages(p, pool->order);
+   return 1 << pool->order;
+}
+
 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;
 
table = >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([j], page);
}
sg_free_table(table);
kfree(buffer);
@@ -323,7 +336,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_remove([i]);
+   if (!page)
+   page = alloc_pages(order_flags[i], orders[i]);
if (!page)
continue;
return page;
@@ -423,6 +438,12 @@ 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++) {
+   drm_page_pool_init([i], orders[i],
+  system_heap_free_pages);
+   }
 
exp_info.name = "system";
exp_info.ops = _heap_ops;
-- 
2.25.1



[PATCH v8 3/5] dma-buf: heaps: Add deferred-free-helper library code

2021-03-04 Thread John Stultz
This patch provides infrastructure for deferring buffer frees.

This is a feature ION provided which when used with some form
of a page pool, provides a nice performance boost in an
allocation microbenchmark. The reason it helps is it allows the
page-zeroing to be done out of the normal allocation/free path,
and pushed off to a kthread.

As not all heaps will find this useful, its implemented as
a optional helper library that heaps can utilize.

Cc: Daniel Vetter 
Cc: Christian Koenig 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
v2:
* Fix sleep in atomic issue from using a mutex, by switching
  to a spinlock as Reported-by: kernel test robot 
* Cleanup API to use a reason enum for clarity and add some documentation
  comments as suggested by Suren Baghdasaryan.
v3:
* Minor tweaks so it can be built as a module
* A few small fixups suggested by Daniel Mentz
v4:
* Tweak from Daniel Mentz to make sure the shrinker
  count/freed values are tracked in pages not bytes
v5:
* Fix up page count tracking as suggested by Suren Baghdasaryan
v7:
* Rework accounting to use nr_pages rather then size, as suggested
  by Suren Baghdasaryan
---
 drivers/dma-buf/heaps/Kconfig|   3 +
 drivers/dma-buf/heaps/Makefile   |   1 +
 drivers/dma-buf/heaps/deferred-free-helper.c | 138 +++
 drivers/dma-buf/heaps/deferred-free-helper.h |  55 
 4 files changed, 197 insertions(+)
 create mode 100644 drivers/dma-buf/heaps/deferred-free-helper.c
 create mode 100644 drivers/dma-buf/heaps/deferred-free-helper.h

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index a5eef06c4226..f7aef8bc7119 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -1,3 +1,6 @@
+config DMABUF_HEAPS_DEFERRED_FREE
+   tristate
+
 config DMABUF_HEAPS_SYSTEM
bool "DMA-BUF System Heap"
depends on DMABUF_HEAPS
diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile
index 974467791032..4e7839875615 100644
--- a/drivers/dma-buf/heaps/Makefile
+++ b/drivers/dma-buf/heaps/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_DMABUF_HEAPS_DEFERRED_FREE) += deferred-free-helper.o
 obj-$(CONFIG_DMABUF_HEAPS_SYSTEM)  += system_heap.o
 obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o
diff --git a/drivers/dma-buf/heaps/deferred-free-helper.c 
b/drivers/dma-buf/heaps/deferred-free-helper.c
new file mode 100644
index ..e19c8b68dfeb
--- /dev/null
+++ b/drivers/dma-buf/heaps/deferred-free-helper.c
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Deferred dmabuf freeing helper
+ *
+ * Copyright (C) 2020 Linaro, Ltd.
+ *
+ * Based on the ION page pool code
+ * Copyright (C) 2011 Google, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "deferred-free-helper.h"
+
+static LIST_HEAD(free_list);
+static size_t list_nr_pages;
+wait_queue_head_t freelist_waitqueue;
+struct task_struct *freelist_task;
+static DEFINE_SPINLOCK(free_list_lock);
+
+void deferred_free(struct deferred_freelist_item *item,
+  void (*free)(struct deferred_freelist_item*,
+   enum df_reason),
+  size_t nr_pages)
+{
+   unsigned long flags;
+
+   INIT_LIST_HEAD(>list);
+   item->nr_pages = nr_pages;
+   item->free = free;
+
+   spin_lock_irqsave(_list_lock, flags);
+   list_add(>list, _list);
+   list_nr_pages += nr_pages;
+   spin_unlock_irqrestore(_list_lock, flags);
+   wake_up(_waitqueue);
+}
+EXPORT_SYMBOL_GPL(deferred_free);
+
+static size_t free_one_item(enum df_reason reason)
+{
+   unsigned long flags;
+   size_t nr_pages;
+   struct deferred_freelist_item *item;
+
+   spin_lock_irqsave(_list_lock, flags);
+   if (list_empty(_list)) {
+   spin_unlock_irqrestore(_list_lock, flags);
+   return 0;
+   }
+   item = list_first_entry(_list, struct deferred_freelist_item, 
list);
+   list_del(>list);
+   nr_pages = item->nr_pages;
+   list_nr_pages -= nr_pages;
+   spin_unlock_irqrestore(_list_lock, flags);
+
+   item->free(item, reason);
+   return nr_pages;
+}
+
+static unsigned long get_freelist_nr_pages(void)
+{
+   unsigned long nr_pages;
+   unsigned long flags;
+
+   spin_lock_irqsave(_list_lock, flags);
+   nr_pages = list_nr_pages;
+   spin_unlock_irqrestore(_list_lock, flags);
+   return nr_pages;
+}
+
+static unsigned long freelist_shrink_count(struct shrinker *shrinker,
+  str

[PATCH v8 2/5] drm: ttm_pool: Rework ttm_pool to use drm_page_pool

2021-03-04 Thread John Stultz
This patch reworks the ttm_pool logic to utilize the recently
added drm_page_pool code.

This adds drm_page_pool structures to the ttm_pool_type
structures, and then removes all the ttm_pool_type shrinker
logic (as its handled in the drm_page_pool shrinker).

NOTE: There is one mismatch in the interfaces I'm not totally
happy with. The ttm_pool tracks all of its pooled pages across
a number of different pools, and tries to keep this size under
the specified page_pool_size value. With the drm_page_pool,
there may other users, however there is still one global
shrinker list of pools. So we can't easily reduce the ttm
pool under the ttm specified size without potentially doing
a lot of shrinking to other non-ttm pools. So either we can:
  1) Try to split it so each user of drm_page_pools manages its
 own pool shrinking.
  2) Push the max value into the drm_page_pool, and have it
 manage shrinking to fit under that global max. Then share
 those size/max values out so the ttm_pool debug output
 can have more context.

I've taken the second path in this patch set, but wanted to call
it out so folks could look closely.

Thoughts would be greatly appreciated here!

Cc: Daniel Vetter 
Cc: Christian Koenig 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
v7:
* Major refactoring to use drm_page_pools inside the
  ttm_pool_type structure. This allows us to use container_of to
  get the needed context to free a page. This also means less
  code is changed overall.
v8:
* Reworked to use the new cleanly rewritten drm_page_pool logic
---
 drivers/gpu/drm/Kconfig|   1 +
 drivers/gpu/drm/ttm/ttm_pool.c | 156 ++---
 include/drm/ttm/ttm_pool.h |   6 +-
 3 files changed, 31 insertions(+), 132 deletions(-)

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 7cbcecb8f7df..a6cbdb63f6c7 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -184,6 +184,7 @@ config DRM_PAGE_POOL
 config DRM_TTM
tristate
depends on DRM && MMU
+   select DRM_PAGE_POOL
help
  GPU memory management subsystem for devices with multiple
  GPU memory types. Will be enabled automatically if a device driver
diff --git a/drivers/gpu/drm/ttm/ttm_pool.c b/drivers/gpu/drm/ttm/ttm_pool.c
index 6e27cb1bf48b..f74ea801d7ab 100644
--- a/drivers/gpu/drm/ttm/ttm_pool.c
+++ b/drivers/gpu/drm/ttm/ttm_pool.c
@@ -39,6 +39,7 @@
 #include 
 #endif
 
+#include 
 #include 
 #include 
 #include 
@@ -68,8 +69,6 @@ static struct ttm_pool_type 
global_dma32_write_combined[MAX_ORDER];
 static struct ttm_pool_type global_dma32_uncached[MAX_ORDER];
 
 static struct mutex shrinker_lock;
-static struct list_head shrinker_list;
-static struct shrinker mm_shrinker;
 
 /* Allocate pages of size 1 << order with the given gfp_flags */
 static struct page *ttm_pool_alloc_page(struct ttm_pool *pool, gfp_t gfp_flags,
@@ -125,8 +124,9 @@ static struct page *ttm_pool_alloc_page(struct ttm_pool 
*pool, gfp_t gfp_flags,
 }
 
 /* Reset the caching and pages of size 1 << order */
-static void ttm_pool_free_page(struct ttm_pool *pool, enum ttm_caching caching,
-  unsigned int order, struct page *p)
+static unsigned long ttm_pool_free_page(struct ttm_pool *pool,
+   enum ttm_caching caching,
+   unsigned int order, struct page *p)
 {
unsigned long attr = DMA_ATTR_FORCE_CONTIGUOUS;
struct ttm_pool_dma *dma;
@@ -142,7 +142,7 @@ static void ttm_pool_free_page(struct ttm_pool *pool, enum 
ttm_caching caching,
 
if (!pool || !pool->use_dma_alloc) {
__free_pages(p, order);
-   return;
+   return 1UL << order;
}
 
if (order)
@@ -153,6 +153,16 @@ static void ttm_pool_free_page(struct ttm_pool *pool, enum 
ttm_caching caching,
dma_free_attrs(pool->dev, (1UL << order) * PAGE_SIZE, vaddr, dma->addr,
   attr);
kfree(dma);
+   return 1UL << order;
+}
+
+static unsigned long ttm_subpool_free_page(struct drm_page_pool *subpool,
+  struct page *p)
+{
+   struct ttm_pool_type *pt;
+
+   pt = container_of(subpool, struct ttm_pool_type, subpool);
+   return ttm_pool_free_page(pt->pool, pt->caching, pt->order, p);
 }
 
 /* Apply a new caching to an array of pages */
@@ -216,40 +226,6 @@ static void ttm_pool_unmap(struct ttm_pool *pool, 
dma_addr_t dma_addr,
   DMA_BIDIRECTIONAL);
 }
 
-/* Give pages into a specific pool_type */
-static 

[PATCH v8 1/5] drm: Add a sharable drm page-pool implementation

2021-03-04 Thread John Stultz
This adds a shrinker controlled page pool, extracted
out of the ttm_pool logic, and abstracted out a bit
so it can be used by other non-ttm drivers.

Cc: Daniel Vetter 
Cc: Christian Koenig 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
v8:
* Completely rewritten from scratch, using only the
  ttm_pool logic so it can be dual licensed.
---
 drivers/gpu/drm/Kconfig |   4 +
 drivers/gpu/drm/Makefile|   2 +
 drivers/gpu/drm/page_pool.c | 214 
 include/drm/page_pool.h |  65 +++
 4 files changed, 285 insertions(+)
 create mode 100644 drivers/gpu/drm/page_pool.c
 create mode 100644 include/drm/page_pool.h

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index e392a90ca687..7cbcecb8f7df 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -177,6 +177,10 @@ config DRM_DP_CEC
  Note: not all adapters support this feature, and even for those
  that do support this they often do not hook up the CEC pin.
 
+config DRM_PAGE_POOL
+   bool
+   depends on DRM
+
 config DRM_TTM
tristate
depends on DRM && MMU
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 926adef289db..2dc7b2fe3fe5 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -39,6 +39,8 @@ obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o
 drm_ttm_helper-y := drm_gem_ttm_helper.o
 obj-$(CONFIG_DRM_TTM_HELPER) += drm_ttm_helper.o
 
+drm-$(CONFIG_DRM_PAGE_POOL) += page_pool.o
+
 drm_kms_helper-y := drm_bridge_connector.o drm_crtc_helper.o drm_dp_helper.o \
drm_dsc.o drm_probe_helper.o \
drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
diff --git a/drivers/gpu/drm/page_pool.c b/drivers/gpu/drm/page_pool.c
new file mode 100644
index ..a60b954cfe0f
--- /dev/null
+++ b/drivers/gpu/drm/page_pool.c
@@ -0,0 +1,214 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Sharable page pool implementation
+ *
+ * Extracted from drivers/gpu/drm/ttm/ttm_pool.c
+ * Copyright 2020 Advanced Micro Devices, Inc.
+ * Copyright 2021 Linaro Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Christian König, John Stultz
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+static unsigned long page_pool_size;
+
+MODULE_PARM_DESC(page_pool_size, "Number of pages in the WC/UC/DMA pool");
+module_param(page_pool_size, ulong, 0644);
+
+static atomic_long_t allocated_pages;
+
+static struct mutex shrinker_lock;
+static struct list_head shrinker_list;
+static struct shrinker mm_shrinker;
+
+void drm_page_pool_set_max(unsigned long max)
+{
+   if (!page_pool_size)
+   page_pool_size = max;
+}
+
+unsigned long drm_page_pool_get_max(void)
+{
+   return page_pool_size;
+}
+
+unsigned long drm_page_pool_get_total(void)
+{
+   return atomic_long_read(_pages);
+}
+
+unsigned long drm_page_pool_get_size(struct drm_page_pool *pool)
+{
+   unsigned long size;
+
+   spin_lock(>lock);
+   size = pool->page_count;
+   spin_unlock(>lock);
+   return size;
+}
+
+/* Give pages into a specific pool */
+void drm_page_pool_add(struct drm_page_pool *pool, struct page *p)
+{
+   unsigned int i, num_pages = 1 << pool->order;
+
+   for (i = 0; i < num_pages; ++i) {
+   if (PageHighMem(p))
+   clear_highpage(p + i);
+   else
+   clear_page(page_address(p + i));
+   }
+
+   spin_lock(>lock);
+   list_add(>lru, >pages);
+  

[PATCH v8 0/5] Generic page pool & deferred freeing for system dmabuf heap

2021-03-04 Thread John Stultz
Apologies for letting so much time pass since the last revision!

The point of this series is trying to add both deferred-freeing
logic as well as a page pool to the DMA-BUF system heap to improve
allocation performance.

This is desired, as the combination of deferred freeing along
with the page pool allows us to offload page-zeroing out of
the allocation hot path. This was done originally with ION
and this patch series allows the DMA-BUF system heap to match
ION's system heap allocation performance in a simple
microbenchmark [1] (ION re-added to the kernel for comparision,
running on an x86 vm image):

./dmabuf-heap-bench -i 0 1 system
Testing dmabuf system vs ion heaptype 0 (flags: 0x1)
-
dmabuf heap: alloc 4096 bytes 5000 times in 88092722 ns  17618 ns/call
ion heap:alloc 4096 bytes 5000 times in 103043547 ns 20608 ns/call
dmabuf heap: alloc 1048576 bytes 5000 times in 252416639 ns  50483 ns/call
ion heap:alloc 1048576 bytes 5000 times in 358190744 ns  71638 ns/call
dmabuf heap: alloc 8388608 bytes 5000 times in 2854351310 ns 570870 ns/call
ion heap:alloc 8388608 bytes 5000 times in 3676328905 ns 735265 ns/call
dmabuf heap: alloc 33554432 bytes 5000 times in 13208119197 ns   2641623 ns/call
ion heap:alloc 33554432 bytes 5000 times in 15306975287 ns   3061395 ns/call


Daniel didn't like earlier attempts to re-use the network
page-pool code to achieve this, and suggested the ttm_pool be
used instead, so this series pulls the page pool functionality
out of the ttm_pool logic and creates a generic page pool
that can be shared.

New in v7 (never submitted):
* Reworked how I integrated the page pool with the ttm logic
  to use container of to avoid allocating structures per page. 

New in v8:
* Due to the dual license requirement from Christian König
  I completely threw away the earlier shared page pool
  implementation (which had evolved from ion code), and
  rewrote it using just the ttm_pool logic. My apologies
  for any previously reviewed issues that I've reintroduced
  in doing so.

Input would be greatly appreciated. Testing as well, as I don't
have any development hardware that utilizes the ttm pool.

thanks
-john

[1] 
https://android.googlesource.com/platform/system/memory/libdmabufheap/+/refs/heads/master/tests/dmabuf_heap_bench.c

Cc: Daniel Vetter 
Cc: Christian Koenig 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org

John Stultz (5):
  drm: Add a sharable drm page-pool implementation
  drm: ttm_pool: Rework ttm_pool to use drm_page_pool
  dma-buf: heaps: Add deferred-free-helper library code
  dma-buf: system_heap: Add drm pagepool support to system heap
  dma-buf: system_heap: Add deferred freeing to the system heap

 drivers/dma-buf/heaps/Kconfig|   5 +
 drivers/dma-buf/heaps/Makefile   |   1 +
 drivers/dma-buf/heaps/deferred-free-helper.c | 138 
 drivers/dma-buf/heaps/deferred-free-helper.h |  55 +
 drivers/dma-buf/heaps/system_heap.c  |  47 +++-
 drivers/gpu/drm/Kconfig  |   5 +
 drivers/gpu/drm/Makefile |   2 +
 drivers/gpu/drm/page_pool.c  | 214 +++
 drivers/gpu/drm/ttm/ttm_pool.c   | 156 +++---
 include/drm/page_pool.h  |  65 ++
 include/drm/ttm/ttm_pool.h   |   6 +-
 11 files changed, 557 insertions(+), 137 deletions(-)
 create mode 100644 drivers/dma-buf/heaps/deferred-free-helper.c
 create mode 100644 drivers/dma-buf/heaps/deferred-free-helper.h
 create mode 100644 drivers/gpu/drm/page_pool.c
 create mode 100644 include/drm/page_pool.h

-- 
2.25.1



Re: [PATCH v2] dma-buf: system_heap: do not warn for costly allocation

2021-03-04 Thread John Stultz
On Wed, Feb 10, 2021 at 6:33 PM Minchan Kim  wrote:
>
> Dmabuf system_heap allocation logic starts with the highest necessary
> allocation order before falling back to lower orders. The requested
> order can be higher than PAGE_ALLOC_COSTLY_ODER and failures to
> allocate will flood dmesg with warnings. Such high-order allocations
> are not unexpected and are handled by the system_heap's allocation
> fallback mechanism.
> Prevent these warnings when allocating higher than
> PAGE_ALLOC_COSTLY_ODER pages using __GFP_NOWARN flag.
>
> Below is ION warning example I got but dmabuf system heap is nothing 
> different:
>
> [ 1233.911533][  T460] warn_alloc: 11 callbacks suppressed
> [ 1233.911539][  T460] allocator@2.0-s: page allocation failure: order:4, 
> mode:0x140dc2(GFP_HIGHUSER|__GFP_COMP|__GFP_ZERO), 
> nodemask=(null),cpuset=/,mems_allowed=0
> [ 1233.926235][  T460] Call trace:
> [ 1233.929370][  T460]  dump_backtrace+0x0/0x1d8
> [ 1233.933704][  T460]  show_stack+0x18/0x24
> [ 1233.937701][  T460]  dump_stack+0xc0/0x140
> [ 1233.941783][  T460]  warn_alloc+0xf4/0x148
> [ 1233.945862][  T460]  __alloc_pages_slowpath+0x9fc/0xa10
> [ 1233.951101][  T460]  __alloc_pages_nodemask+0x278/0x2c0
> [ 1233.956285][  T460]  ion_page_pool_alloc+0xd8/0x100
> [ 1233.961144][  T460]  ion_system_heap_allocate+0xbc/0x2f0
> [ 1233.966440][  T460]  ion_buffer_create+0x68/0x274
> [ 1233.971130][  T460]  ion_buffer_alloc+0x8c/0x110
> [ 1233.975733][  T460]  ion_dmabuf_alloc+0x44/0xe8
> [ 1233.980248][  T460]  ion_ioctl+0x100/0x320
> [ 1233.984332][  T460]  __arm64_sys_ioctl+0x90/0xc8
> [ 1233.988934][  T460]  el0_svc_common+0x9c/0x168
> [ 1233.993360][  T460]  do_el0_svc+0x1c/0x28
> [ 1233.997358][  T460]  el0_sync_handler+0xd8/0x250
> [ 1234.001989][  T460]  el0_sync+0x148/0x180
>
> Signed-off-by: Minchan Kim 
> ---
> * from v1 - 
> https://lore.kernel.org/lkml/20210210162632.3903128-1-minc...@kernel.org/
>  * better description - surenb
>  * use mid_order_gfp - john.stultz
>
>  drivers/dma-buf/heaps/system_heap.c | 9 +++--
>  1 file changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/dma-buf/heaps/system_heap.c 
> b/drivers/dma-buf/heaps/system_heap.c
> index 29e49ac17251..e5f545ada587 100644
> --- a/drivers/dma-buf/heaps/system_heap.c
> +++ b/drivers/dma-buf/heaps/system_heap.c
> @@ -40,11 +40,16 @@ struct dma_heap_attachment {
> bool mapped;
>  };
>
> +#define LOW_ORDER_GFP (GFP_HIGHUSER | __GFP_ZERO | __GFP_COMP)
> +/*
> + * Avoid warning on order-4 allocation failures as we'll fall back to
> + * order-0 in that case.
> + */
> +#define MID_ORDER_GFP (LOW_ORDER_GFP | __GFP_NOWARN)
>  #define HIGH_ORDER_GFP  (((GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN \
> | __GFP_NORETRY) & ~__GFP_RECLAIM) \
> | __GFP_COMP)
> -#define LOW_ORDER_GFP (GFP_HIGHUSER | __GFP_ZERO | __GFP_COMP)
> -static gfp_t order_flags[] = {HIGH_ORDER_GFP, LOW_ORDER_GFP, LOW_ORDER_GFP};
> +static gfp_t order_flags[] = {HIGH_ORDER_GFP, MID_ORDER_GFP, LOW_ORDER_GFP};
>  /*
>   * The selection of the orders used for allocation (1MB, 64K, 4K) is designed
>   * to match with the sizes often found in IOMMUs. Using order 4 pages instead

This looks good to me! Thanks for sending this and apologies for the
slow reply, the patch slipped by me!

Reviewed-by: John Stultz 

thanks again!
-john


[RESEND][PATCH v2 1/2] dma-buf: dma-heap: Provide accessor to get heap name

2021-03-01 Thread John Stultz
It can be useful to access the name for the heap,
so provide an accessor to do so.

Cc: Daniel Vetter 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
v2:
* Make sure to use "const char *" as Reported-by: kernel test robot 

---
 drivers/dma-buf/dma-heap.c | 12 
 include/linux/dma-heap.h   |  9 +
 2 files changed, 21 insertions(+)

diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
index 6b5db954569f..56bf5ad01ad5 100644
--- a/drivers/dma-buf/dma-heap.c
+++ b/drivers/dma-buf/dma-heap.c
@@ -202,6 +202,18 @@ void *dma_heap_get_drvdata(struct dma_heap *heap)
return heap->priv;
 }
 
+/**
+ * dma_heap_get_name() - get heap name
+ * @heap: DMA-Heap to retrieve private data for
+ *
+ * Returns:
+ * The char* for the heap name.
+ */
+const char *dma_heap_get_name(struct dma_heap *heap)
+{
+   return heap->name;
+}
+
 struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info)
 {
struct dma_heap *heap, *h, *err_ret;
diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h
index 5bc5c946af58..0c05561cad6e 100644
--- a/include/linux/dma-heap.h
+++ b/include/linux/dma-heap.h
@@ -50,6 +50,15 @@ struct dma_heap_export_info {
  */
 void *dma_heap_get_drvdata(struct dma_heap *heap);
 
+/**
+ * dma_heap_get_name() - get heap name
+ * @heap: DMA-Heap to retrieve private data for
+ *
+ * Returns:
+ * The char* for the heap name.
+ */
+const char *dma_heap_get_name(struct dma_heap *heap);
+
 /**
  * dma_heap_add - adds a heap to dmabuf heaps
  * @exp_info:  information needed to register this heap
-- 
2.25.1



[RESEND][PATCH v2 2/2] dma-buf: heaps: Fix the name used when exporting dmabufs to be the actual heap name

2021-03-01 Thread John Stultz
By default dma_buf_export() sets the exporter name to be
KBUILD_MODNAME. Unfortunately this may not be identical to the
string used as the heap name (ie: "system" vs "system_heap").

This can cause some minor confusion with tooling, and there is
the future potential where multiple heap types may be exported
by the same module (but would all have the same name).

So to avoid all this, set the exporter exp_name to the heap name.

Cc: Daniel Vetter 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
 drivers/dma-buf/heaps/cma_heap.c| 1 +
 drivers/dma-buf/heaps/system_heap.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c
index 5d64eccd21d6..0c05b79870f9 100644
--- a/drivers/dma-buf/heaps/cma_heap.c
+++ b/drivers/dma-buf/heaps/cma_heap.c
@@ -339,6 +339,7 @@ static struct dma_buf *cma_heap_allocate(struct dma_heap 
*heap,
buffer->pagecount = pagecount;
 
/* create the dmabuf */
+   exp_info.exp_name = dma_heap_get_name(heap);
exp_info.ops = _heap_buf_ops;
exp_info.size = buffer->len;
exp_info.flags = fd_flags;
diff --git a/drivers/dma-buf/heaps/system_heap.c 
b/drivers/dma-buf/heaps/system_heap.c
index 29e49ac17251..23a7e74ef966 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -390,6 +390,7 @@ static struct dma_buf *system_heap_allocate(struct dma_heap 
*heap,
}
 
/* create the dmabuf */
+   exp_info.exp_name = dma_heap_get_name(heap);
exp_info.ops = _heap_buf_ops;
exp_info.size = buffer->len;
exp_info.flags = fd_flags;
-- 
2.25.1



Re: [PATCH] dma-buf: heaps: Set VM_PFNMAP in mmap for system and cma heaps

2021-03-01 Thread John Stultz
On Sat, Feb 27, 2021 at 1:44 AM Christoph Hellwig  wrote:
>
> On Fri, Feb 26, 2021 at 08:36:55AM +0100, Daniel Vetter wrote:
> > Also given that both deal with struct page there's a ton of divergence
> > between these two that doesn't make much sense. Maybe could even share
> > the code fully, aside from how you allocate the struct pages.
>
> I've been saying that since the code was first submitted.  Once pages
> are allocated from CMA they should be treated not different from normal
> pages.
>
> Please take a look at how the DMA contigous allocator manages to share
> all code for handling CMA vs alloc_pages pages.

I'll take a look at that! Thanks for the pointer!
-john


Re: [PATCH v2] drm/bridge: lt9611: Fix handling of 4k panels

2021-03-01 Thread John Stultz
On Thu, Jan 21, 2021 at 1:50 AM Robert Foss  wrote:
> +Sam Ravnborg
>
> I think this patch is ready to get pulled into the drm-misc tree.
>
> On Thu, 17 Dec 2020 at 15:09, Robert Foss  wrote:
> >
> > 4k requires two dsi pipes, so don't report MODE_OK when only a
> > single pipe is configured. But rather report MODE_PANEL to
> > signal that requirements of the panel are not being met.

Hey All, I just wanted to follow up on this patch as it seems like it
missed 5.12 ?

Just wanted to make sure it didn't slip through the cracks.

thanks
-john


[PATCH] dma-buf: heaps: Set VM_PFNMAP in mmap for system and cma heaps

2021-02-25 Thread John Stultz
Per discussion and patches here:
  
https://lore.kernel.org/dri-devel/20210223105951.912577-1-daniel.vet...@ffwll.ch/

Daniel is planning on making VM_PFNMAP required on dmabufs.

Thus to avoid the warn_on noise, set the VM_PFNMAP in the
system and cma heap's mmap handler.

Cc: Daniel Vetter 
Cc: Jason Gunthorpe 
Cc: Christian Koenig 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
 drivers/dma-buf/heaps/cma_heap.c| 1 +
 drivers/dma-buf/heaps/system_heap.c | 4 +++-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c
index 364fc2f3e499..34bc3987f942 100644
--- a/drivers/dma-buf/heaps/cma_heap.c
+++ b/drivers/dma-buf/heaps/cma_heap.c
@@ -185,6 +185,7 @@ static int cma_heap_mmap(struct dma_buf *dmabuf, struct 
vm_area_struct *vma)
 
vma->vm_ops = _heap_vm_ops;
vma->vm_private_data = buffer;
+   vma->vm_flags |= VM_PFNMAP;
 
return 0;
 }
diff --git a/drivers/dma-buf/heaps/system_heap.c 
b/drivers/dma-buf/heaps/system_heap.c
index 3548b20cb98c..8995e3cbfcaf 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -228,8 +228,10 @@ static int system_heap_mmap(struct dma_buf *dmabuf, struct 
vm_area_struct *vma)
return ret;
addr += PAGE_SIZE;
if (addr >= vma->vm_end)
-   return 0;
+   break;
}
+
+   vma->vm_flags |= VM_PFNMAP;
return 0;
 }
 
-- 
2.25.1



Re: [REGRESSION] "split bio_kmalloc from bio_alloc_bioset" causing crash shortly after bootup

2021-02-23 Thread John Stultz
On Mon, Feb 22, 2021 at 11:22 PM Christoph Hellwig  wrote:
>
> On Tue, Feb 23, 2021 at 08:04:08AM +0100, Christoph Hellwig wrote:
> > The problem is that the blk-crypto fallback code calls bio_split
> > with a NULL bioset.  That was aready broken before, as the mempool
> > needed to guarantee forward progress was missing, but is not fatal.
> >
> > Satya, can you look into adding a mempool that can guarantees forward
> > progress here?
>
> Something like this would be the minimum viable fix:

This seems to work for me!

Tested-by: John Stultz 

thanks
-john


Re: [REGRESSION] "add a disk_uevent helper" breaks booting Andorid w/ dynamic partitions

2021-02-23 Thread John Stultz
On Mon, Feb 22, 2021 at 10:31 PM Christoph Hellwig  wrote:
>
> Please try the patch below:
>
> ---
> From 85943345b41ec04f5a9e92dfad85b0fb24e2d2eb Mon Sep 17 00:00:00 2001
> From: Christoph Hellwig 
> Date: Tue, 23 Feb 2021 07:28:22 +0100
> Subject: block: don't skip empty device in in disk_uevent
>
> Restore the previous behavior by using the correct flag for the whole device
> ("part0").
>
> Fixes: 99dfc43ecbf6 ("block: use ->bi_bdev for bio based I/O accounting")
> Reported-by: John Stultz 
> Signed-off-by: Christoph Hellwig 

Yes, this seems to fix the problem! Thank you so much!
Tested-by: John Stultz 


Re: [REGRESSION] "split bio_kmalloc from bio_alloc_bioset" causing crash shortly after bootup

2021-02-22 Thread John Stultz
On Mon, Feb 22, 2021 at 7:39 PM Chaitanya Kulkarni
 wrote:
>
> On 2/22/21 19:07, John Stultz wrote:
> > [   34.784901] ueventd: LoadWithAliases was unable to load 
> > platform:regulatory
> > [   34.785313]  bio_alloc_bioset+0x14/0x230
> > [   34.796189]  bio_clone_fast+0x28/0x80
> > [   34.799848]  bio_split+0x50/0xd0
> > [   34.803072]  blk_crypto_fallback_encrypt_bio+0x2ec/0x5e8
> > [   34.808384]  blk_crypto_fallback_bio_prep+0xfc/0x140
> > [   34.813345]  __blk_crypto_bio_prep+0x13c/0x150
> > [   34.817784]  submit_bio_noacct+0x3c0/0x548
> > [   34.821880]  submit_bio+0x48/0x200
> > [   34.825278]  ext4_io_submit+0x50/0x68
> > [   34.828939]  ext4_writepages+0x558/0xca8
> > [   34.832860]  do_writepages+0x58/0x108
> > [   34.836522]  __writeback_single_inode+0x44/0x510
> > [   34.841137]  writeback_sb_inodes+0x1e0/0x4a8
> > [   34.845404]  __writeback_inodes_wb+0x78/0xe8
> > [   34.849670]  wb_writeback+0x274/0x3e8
> > [   34.853328]  wb_workfn+0x308/0x5f0
> > [   34.856726]  process_one_work+0x1ec/0x4d0
> > [   34.860734]  worker_thread+0x44/0x478
> > [   34.864392]  kthread+0x140/0x150
> > [   34.867618]  ret_from_fork+0x10/0x30
> > [   34.871197] Code: a9ba7bfd 910003fd f9000bf3 7900bfa1 (f9403441)
> > [   34.877289] ---[ end trace e6c2a3ab108278f0 ]---
> > [   34.893636] Kernel panic - not syncing: Oops: Fatal exception
> >
>
> If you have time then until you get the reply from others, can you try
> following patch ?
>
> diff --git a/block/bio.c b/block/bio.c
> index a1c4d2900c7a..9976400ec66a 100644
> --- a/block/bio.c
> +++ b/block/bio.c
> @@ -663,7 +663,10 @@ struct bio *bio_clone_fast(struct bio *bio, gfp_t
> gfp_mask, struct bio_set *bs)
>  {
> struct bio *b;
>
> -   b = bio_alloc_bioset(gfp_mask, 0, bs);
> +   if (bs)
> +   b = bio_alloc_bioset(gfp_mask, 0, bs);
> +   else
> +   b = bio_kmalloc(gfp_mask, 0);
> if (!b)
> return NULL;
>
> P.S.This is purely based on the code inspection and it may not solve your
> issue. Proceed with the caution as it may *break* your system.

So with an initial quick test, this patch (along with the follow-on
one you sent) seems to avoid the issue.

I'm wondering if given there are multiple call sites, that in
bio_alloc_bioset() would something like the following make more sense?
(apologies, copy pasted so this is whitespace corrupted)
thanks
-john

diff --git a/block/bio.c b/block/bio.c
index a1c4d2900c7a..391d5cde79fc 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -402,6 +402,9 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask,
unsigned short nr_iovecs,
struct bio *bio;
void *p;

+   if(!bs)
+   return bio_kmalloc(gfp_mask, 0);
+
/* should not use nobvec bioset for nr_iovecs > 0 */
if (WARN_ON_ONCE(!mempool_initialized(>bvec_pool) && nr_iovecs > 0))
return NULL;


[REGRESSION] "split bio_kmalloc from bio_alloc_bioset" causing crash shortly after bootup

2021-02-22 Thread John Stultz
Hey all,
  In testing Linus' HEAD today I found another[1] regression in the block merge.

This time I see a crash on my hikey960 board shortly after booting
ASOP. See the log below.

I bisected the issue down to "block: split bio_kmalloc from bio_alloc_bioset":
  
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3175199ab0ac8c874ec25c6bf169f74888917435

But unfortunately that does not revert cleanly against Linus' HEAD.

It seems like the issue is that the function is no longer handling the
case where the bio_set *bs is NULL as is done here:
  
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/block/blk-crypto-fallback.c#n230

If there's anything I can do to help debug this issue, please let me know!

thanks
-john

[1]: "add a disk_uevent helper" also was giving me trouble as reported here:
https://lore.kernel.org/lkml/calaqxlu3b8ycs_mtnr2lpasvn8oljvd2qo4hkfkzeewvnfe...@mail.gmail.com/


[   34.600558] Unable to handle kernel read from unreadable memory at
virtual address 0068
[   34.609819] Mem abort info:
[   34.612644]   ESR = 0x9605
[   34.615707]   EC = 0x25: DABT (current EL), IL = 32 bits
[   34.621157]   SET = 0, FnV = 0
[   34.624288]   EA = 0, S1PTW = 0
[   34.628312] Data abort info:
[   34.631236]   ISV = 0, ISS = 0x0005
[   34.635222]   CM = 0, WnR = 0
[   34.638186] user pgtable: 4k pages, 39-bit VAs, pgdp=0774f000
[   34.644639] [0068] pgd=,
p4d=, pud=
[   34.653381] Internal error: Oops: 9605 [#1] PREEMPT SMP
[   34.658954] Modules linked in:
[   34.662007] CPU: 0 PID: 173 Comm: kworker/u16:3 Not tainted
5.11.0-04196-ga8e8932e4ae #559
[   34.670270] Hardware name: HiKey960 (DT)
[   34.674190] Workqueue: writeback wb_workfn (flush-8:48)
[   34.679429] pstate: 8045 (Nzcv daif +PAN -UAO -TCO BTYPE=--)
[   34.685435] pc : bio_alloc_bioset+0x14/0x230
[   34.689720] lr : bio_clone_fast+0x28/0x80
[   34.693728] sp : ffc012a13530
[   34.697036] x29: ffc012a13530 x28: 3400
[   34.702351] x27:  x26: ff8001993040
[   34.703203] dwmmc_k3 ff3ff000.dwmmc2: Unexpected interrupt latency
[   34.707662] x25: 0001 x24: ff8001fc8800
[   34.719145] x23:  x22: ffc012a137e8
[   34.724456] x21: 0c00 x20: ff8001fc8800
[   34.729767] x19: 0800 x18: fffe013efe80
[   34.735078] x17: 0068 x16: fffe012aa440
[   34.740389] x15: 1000 x14: ff8001fc8800
[   34.745700] x13: ff805c3e4000 x12: 001ce000
[   34.751009] x11: 00fb x10: 1000
[   34.756320] x9 : 0033 x8 : 000d9000
[   34.761631] x7 :  x6 : a000
[   34.766941] x5 : 0c00 x4 : 1000
[   34.772251] x3 :  x2 : 
[   34.777561] x1 :  x0 : 0c00
[   34.782873] Call trace:
[   34.784901] ueventd: LoadWithAliases was unable to load platform:regulatory
[   34.785313]  bio_alloc_bioset+0x14/0x230
[   34.796189]  bio_clone_fast+0x28/0x80
[   34.799848]  bio_split+0x50/0xd0
[   34.803072]  blk_crypto_fallback_encrypt_bio+0x2ec/0x5e8
[   34.808384]  blk_crypto_fallback_bio_prep+0xfc/0x140
[   34.813345]  __blk_crypto_bio_prep+0x13c/0x150
[   34.817784]  submit_bio_noacct+0x3c0/0x548
[   34.821880]  submit_bio+0x48/0x200
[   34.825278]  ext4_io_submit+0x50/0x68
[   34.828939]  ext4_writepages+0x558/0xca8
[   34.832860]  do_writepages+0x58/0x108
[   34.836522]  __writeback_single_inode+0x44/0x510
[   34.841137]  writeback_sb_inodes+0x1e0/0x4a8
[   34.845404]  __writeback_inodes_wb+0x78/0xe8
[   34.849670]  wb_writeback+0x274/0x3e8
[   34.853328]  wb_workfn+0x308/0x5f0
[   34.856726]  process_one_work+0x1ec/0x4d0
[   34.860734]  worker_thread+0x44/0x478
[   34.864392]  kthread+0x140/0x150
[   34.867618]  ret_from_fork+0x10/0x30
[   34.871197] Code: a9ba7bfd 910003fd f9000bf3 7900bfa1 (f9403441)
[   34.877289] ---[ end trace e6c2a3ab108278f0 ]---
[   34.893636] Kernel panic - not syncing: Oops: Fatal exception


[REGRESSION] "add a disk_uevent helper" breaks booting Andorid w/ dynamic partitions

2021-02-22 Thread John Stultz
Hey all,
  After updating to Linus' HEAD today I found my db845c board wouldn't
boot to android with the error below.

I was able to bisect the boot regression down to "block: add a
disk_uevent helper":
  
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bc359d03c7ec1bf3b86d03bafaf6bbb21e6414fd

And have validated that reverting that change seems to get things working again.

I don't really know the dynamic partition DM details well, so any tips
as to what might be going wrong here would be appreciated!

thanks
-john

[   25.782268] init: [libfs_mgr]Skipping mounting '/dev/block/dm-0'
[   25.788373] init: [libfs_mgr]Failed to open '/dev/block/dm-0': No
such file or directory
[   25.796579] init:
[libfs_mgr]__mount(source=/dev/block/dm-0(missing),target=/system,type=ext4)=-1:
No such file or directory
[   25.807978] init: Failed to mount /system: No such file or directory
[   25.814466] init: Failed to mount required partitions early ...
[   25.820757] init: InitFatalReboot: signal 6
[   25.833635] init: #00 pc 003936a8  /init
(UnwindStackCurrent::UnwindFromContext(unsigned long, void*)+96)
[   25.844001] init: #01 pc 002f1df0  /init
(android::init::InitFatalReboot(int)+208)
[   25.852340] init: #02 pc 002f21d8  /init
(android::init::InstallRebootSignalHandlers()::$_22::__invoke(int)+32)
[   25.863211] init: #03 pc 053c  [vdso:007f97c34000]
[   25.869449] init: #04 pc 0045ffb0  /init (abort+176)
[   25.875163] init: #05 pc 002f714c  /init
(android::init::InitAborter(char const*)+44)
[   25.883760] init: #06 pc 0034dc98  /init
(android::base::SetAborter(std::__1::function&&)::$_3::__invoke(char const*)+80)
[   25.897241] init: #07 pc 0034d840  /init
(android::base::LogMessage::~LogMessage()+360)
[   25.906002] init: #08 pc 002e93a8  /init
(android::init::FirstStageMain(int, char**)+6648)
[   25.915039] init: #09 pc 0045ee58  /init
(__real_libc_init(void*, void (*)(), int (*)(int, char**, char**),
structors_array_t const*, bionic_tc)
[   25.929411] init: Reboot ending, jumping to kernel


Re: [PATCH] dma-buf: system_heap: do not warn for costly allocation

2021-02-10 Thread John Stultz
On Wed, Feb 10, 2021 at 3:17 PM Minchan Kim  wrote:
>
> On Wed, Feb 10, 2021 at 01:40:02PM -0800, John Stultz wrote:
> > On Wed, Feb 10, 2021 at 9:48 AM Minchan Kim  wrote:
> > >
> > > On Wed, Feb 10, 2021 at 09:32:09AM -0800, John Stultz wrote:
> > > > On Wed, Feb 10, 2021 at 8:26 AM Minchan Kim  wrote:
> > > > >
> > > > > Linux VM is not hard to support PAGE_ALLOC_COSTLY_ODER allocation
> > > > > so normally expects driver passes __GFP_NOWARN in that case
> > > > > if they has fallback options.
> > > > >
> > > > > system_heap in dmabuf is the case so do not flood into demsg
> > > > > with the warning for recording more precious information logs.
> > > > > (below is ION warning example I got but dmabuf system heap is
> > > > > nothing different).
> > > > >
> > > > > [ 1233.911533][  T460] warn_alloc: 11 callbacks suppressed
> > > > > [ 1233.911539][  T460] allocator@2.0-s: page allocation failure: 
> > > > > order:4, mode:0x140dc2(GFP_HIGHUSER|__GFP_COMP|__GFP_ZERO), 
> > > > > nodemask=(null),cpuset=/,mems_allowed=0
> > > > > [ 1233.926235][  T460] Call trace:
> > > > > [ 1233.929370][  T460]  dump_backtrace+0x0/0x1d8
> > > > > [ 1233.933704][  T460]  show_stack+0x18/0x24
> > > > > [ 1233.937701][  T460]  dump_stack+0xc0/0x140
> > > > > [ 1233.941783][  T460]  warn_alloc+0xf4/0x148
> > > > > [ 1233.945862][  T460]  __alloc_pages_slowpath+0x9fc/0xa10
> > > > > [ 1233.951101][  T460]  __alloc_pages_nodemask+0x278/0x2c0
> > > > > [ 1233.956285][  T460]  ion_page_pool_alloc+0xd8/0x100
> > > > > [ 1233.961144][  T460]  ion_system_heap_allocate+0xbc/0x2f0
> > > > > [ 1233.966440][  T460]  ion_buffer_create+0x68/0x274
> > > > > [ 1233.971130][  T460]  ion_buffer_alloc+0x8c/0x110
> > > > > [ 1233.975733][  T460]  ion_dmabuf_alloc+0x44/0xe8
> > > > > [ 1233.980248][  T460]  ion_ioctl+0x100/0x320
> > > > > [ 1233.984332][  T460]  __arm64_sys_ioctl+0x90/0xc8
> > > > > [ 1233.988934][  T460]  el0_svc_common+0x9c/0x168
> > > > > [ 1233.993360][  T460]  do_el0_svc+0x1c/0x28
> > > > > [ 1233.997358][  T460]  el0_sync_handler+0xd8/0x250
> > > > > [ 1234.001989][  T460]  el0_sync+0x148/0x180
> > > > >
> > > > > Signed-off-by: Minchan Kim 
> > > > > ---
> > > > >  drivers/dma-buf/heaps/system_heap.c | 9 +++--
> > > > >  1 files changed, 7 insertions(+), 2 deletions(-)
> > > > >
> > > > > diff --git a/drivers/dma-buf/heaps/system_heap.c 
> > > > > b/drivers/dma-buf/heaps/system_heap.c
> > > > > index 29e49ac17251..33c25a5e06f9 100644
> > > > > --- a/drivers/dma-buf/heaps/system_heap.c
> > > > > +++ b/drivers/dma-buf/heaps/system_heap.c
> > > > > @@ -40,7 +40,7 @@ struct dma_heap_attachment {
> > > > > bool mapped;
> > > > >  };
> > > > >
> > > > > -#define HIGH_ORDER_GFP  (((GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN \
> > > > > +#define HIGH_ORDER_GFP  (((GFP_HIGHUSER | __GFP_ZERO \
> > > > > | __GFP_NORETRY) & ~__GFP_RECLAIM) \
> > > > > | __GFP_COMP)
> > > > >  #define LOW_ORDER_GFP (GFP_HIGHUSER | __GFP_ZERO | __GFP_COMP)
> > > > > @@ -315,6 +315,7 @@ static struct page 
> > > > > *alloc_largest_available(unsigned long size,
> > > > > unsigned int max_order)
> > > > >  {
> > > > > struct page *page;
> > > > > +   unsigned long gfp_flags;
> > > > > int i;
> > > > >
> > > > > for (i = 0; i < NUM_ORDERS; i++) {
> > > > > @@ -323,7 +324,11 @@ static struct page 
> > > > > *alloc_largest_available(unsigned long size,
> > > > > if (max_order < orders[i])
> > > > > continue;
> > > > >
> > > > > -   page = alloc_pages(order_flags[i], orders[i]);
> > > > > +   gfp_flags = order_flags[i];
> > > > > +   if (orders[i] > PAGE_ALLOC_COSTLY_ORDER)
> > > > > +   gfp_flags |= __GFP_NO

Re: [PATCH] dma-buf: system_heap: do not warn for costly allocation

2021-02-10 Thread John Stultz
On Wed, Feb 10, 2021 at 9:48 AM Minchan Kim  wrote:
>
> On Wed, Feb 10, 2021 at 09:32:09AM -0800, John Stultz wrote:
> > On Wed, Feb 10, 2021 at 8:26 AM Minchan Kim  wrote:
> > >
> > > Linux VM is not hard to support PAGE_ALLOC_COSTLY_ODER allocation
> > > so normally expects driver passes __GFP_NOWARN in that case
> > > if they has fallback options.
> > >
> > > system_heap in dmabuf is the case so do not flood into demsg
> > > with the warning for recording more precious information logs.
> > > (below is ION warning example I got but dmabuf system heap is
> > > nothing different).
> > >
> > > [ 1233.911533][  T460] warn_alloc: 11 callbacks suppressed
> > > [ 1233.911539][  T460] allocator@2.0-s: page allocation failure: order:4, 
> > > mode:0x140dc2(GFP_HIGHUSER|__GFP_COMP|__GFP_ZERO), 
> > > nodemask=(null),cpuset=/,mems_allowed=0
> > > [ 1233.926235][  T460] Call trace:
> > > [ 1233.929370][  T460]  dump_backtrace+0x0/0x1d8
> > > [ 1233.933704][  T460]  show_stack+0x18/0x24
> > > [ 1233.937701][  T460]  dump_stack+0xc0/0x140
> > > [ 1233.941783][  T460]  warn_alloc+0xf4/0x148
> > > [ 1233.945862][  T460]  __alloc_pages_slowpath+0x9fc/0xa10
> > > [ 1233.951101][  T460]  __alloc_pages_nodemask+0x278/0x2c0
> > > [ 1233.956285][  T460]  ion_page_pool_alloc+0xd8/0x100
> > > [ 1233.961144][  T460]  ion_system_heap_allocate+0xbc/0x2f0
> > > [ 1233.966440][  T460]  ion_buffer_create+0x68/0x274
> > > [ 1233.971130][  T460]  ion_buffer_alloc+0x8c/0x110
> > > [ 1233.975733][  T460]  ion_dmabuf_alloc+0x44/0xe8
> > > [ 1233.980248][  T460]  ion_ioctl+0x100/0x320
> > > [ 1233.984332][  T460]  __arm64_sys_ioctl+0x90/0xc8
> > > [ 1233.988934][  T460]  el0_svc_common+0x9c/0x168
> > > [ 1233.993360][  T460]  do_el0_svc+0x1c/0x28
> > > [ 1233.997358][  T460]  el0_sync_handler+0xd8/0x250
> > > [ 1234.001989][  T460]  el0_sync+0x148/0x180
> > >
> > > Signed-off-by: Minchan Kim 
> > > ---
> > >  drivers/dma-buf/heaps/system_heap.c | 9 +++--
> > >  1 files changed, 7 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/dma-buf/heaps/system_heap.c 
> > > b/drivers/dma-buf/heaps/system_heap.c
> > > index 29e49ac17251..33c25a5e06f9 100644
> > > --- a/drivers/dma-buf/heaps/system_heap.c
> > > +++ b/drivers/dma-buf/heaps/system_heap.c
> > > @@ -40,7 +40,7 @@ struct dma_heap_attachment {
> > > bool mapped;
> > >  };
> > >
> > > -#define HIGH_ORDER_GFP  (((GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN \
> > > +#define HIGH_ORDER_GFP  (((GFP_HIGHUSER | __GFP_ZERO \
> > > | __GFP_NORETRY) & ~__GFP_RECLAIM) \
> > > | __GFP_COMP)
> > >  #define LOW_ORDER_GFP (GFP_HIGHUSER | __GFP_ZERO | __GFP_COMP)
> > > @@ -315,6 +315,7 @@ static struct page *alloc_largest_available(unsigned 
> > > long size,
> > > unsigned int max_order)
> > >  {
> > > struct page *page;
> > > +   unsigned long gfp_flags;
> > > int i;
> > >
> > > for (i = 0; i < NUM_ORDERS; i++) {
> > > @@ -323,7 +324,11 @@ static struct page *alloc_largest_available(unsigned 
> > > long size,
> > > if (max_order < orders[i])
> > > continue;
> > >
> > > -   page = alloc_pages(order_flags[i], orders[i]);
> > > +   gfp_flags = order_flags[i];
> > > +   if (orders[i] > PAGE_ALLOC_COSTLY_ORDER)
> > > +   gfp_flags |= __GFP_NOWARN;
> > > +
> > > +   page = alloc_pages(gfp_flags, orders[i]);
> >
> > Would it be cleaner to just set up the flags properly in the
> > order_flags array? I'm not sure I understand why your patch does it
> > dynamically?
>
> That's exactly I had in my branch for aosp fix but I wanted to
> hear it explicitly from dmabuf maintainer since I was worried
> chaninging order-4 allocation behavior, especially,
> __GFP_NORETRY and &~__GFP_RECLAIM.
> (It will make allocation failure easier than old and that's not
> thing my patch is addressing).

Yea. I might stick to changing just the __GFP_NOWARN.

> If you want this, I am happy to change it. Shall I?
>
> diff --git a/drivers/dma-buf/heaps/system_heap.c 
> b/drivers/dma-buf/heaps/system_heap.c
> index 29e49ac17251..865ec847013d 100644
> --- a/drivers/dma-buf/heaps/system_heap.c
> +++ b/drivers/dma-buf/heaps/system_heap.c
> @@ -44,7 +44,7 @@ struct dma_heap_attachment {
> | __GFP_NORETRY) & ~__GFP_RECLAIM) \
> | __GFP_COMP)
>  #define LOW_ORDER_GFP (GFP_HIGHUSER | __GFP_ZERO | __GFP_COMP)
> -static gfp_t order_flags[] = {HIGH_ORDER_GFP, LOW_ORDER_GFP, LOW_ORDER_GFP};
> +static gfp_t order_flags[] = {HIGH_ORDER_GFP, HIGH_ORDER_GFP, LOW_ORDER_GFP};

Maybe can you define a MID_ORDER_GFP as LOW_ORDER | __GFP_NOWARN
(along with a comment in the code as to why) instead ?

That avoids introducing any subtle behavioral change unintentionally.

thanks
-john


Re: [PATCH] dma-buf: system_heap: do not warn for costly allocation

2021-02-10 Thread John Stultz
On Wed, Feb 10, 2021 at 8:26 AM Minchan Kim  wrote:
>
> Linux VM is not hard to support PAGE_ALLOC_COSTLY_ODER allocation
> so normally expects driver passes __GFP_NOWARN in that case
> if they has fallback options.
>
> system_heap in dmabuf is the case so do not flood into demsg
> with the warning for recording more precious information logs.
> (below is ION warning example I got but dmabuf system heap is
> nothing different).
>
> [ 1233.911533][  T460] warn_alloc: 11 callbacks suppressed
> [ 1233.911539][  T460] allocator@2.0-s: page allocation failure: order:4, 
> mode:0x140dc2(GFP_HIGHUSER|__GFP_COMP|__GFP_ZERO), 
> nodemask=(null),cpuset=/,mems_allowed=0
> [ 1233.926235][  T460] Call trace:
> [ 1233.929370][  T460]  dump_backtrace+0x0/0x1d8
> [ 1233.933704][  T460]  show_stack+0x18/0x24
> [ 1233.937701][  T460]  dump_stack+0xc0/0x140
> [ 1233.941783][  T460]  warn_alloc+0xf4/0x148
> [ 1233.945862][  T460]  __alloc_pages_slowpath+0x9fc/0xa10
> [ 1233.951101][  T460]  __alloc_pages_nodemask+0x278/0x2c0
> [ 1233.956285][  T460]  ion_page_pool_alloc+0xd8/0x100
> [ 1233.961144][  T460]  ion_system_heap_allocate+0xbc/0x2f0
> [ 1233.966440][  T460]  ion_buffer_create+0x68/0x274
> [ 1233.971130][  T460]  ion_buffer_alloc+0x8c/0x110
> [ 1233.975733][  T460]  ion_dmabuf_alloc+0x44/0xe8
> [ 1233.980248][  T460]  ion_ioctl+0x100/0x320
> [ 1233.984332][  T460]  __arm64_sys_ioctl+0x90/0xc8
> [ 1233.988934][  T460]  el0_svc_common+0x9c/0x168
> [ 1233.993360][  T460]  do_el0_svc+0x1c/0x28
> [ 1233.997358][  T460]  el0_sync_handler+0xd8/0x250
> [ 1234.001989][  T460]  el0_sync+0x148/0x180
>
> Signed-off-by: Minchan Kim 
> ---
>  drivers/dma-buf/heaps/system_heap.c | 9 +++--
>  1 files changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/dma-buf/heaps/system_heap.c 
> b/drivers/dma-buf/heaps/system_heap.c
> index 29e49ac17251..33c25a5e06f9 100644
> --- a/drivers/dma-buf/heaps/system_heap.c
> +++ b/drivers/dma-buf/heaps/system_heap.c
> @@ -40,7 +40,7 @@ struct dma_heap_attachment {
> bool mapped;
>  };
>
> -#define HIGH_ORDER_GFP  (((GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN \
> +#define HIGH_ORDER_GFP  (((GFP_HIGHUSER | __GFP_ZERO \
> | __GFP_NORETRY) & ~__GFP_RECLAIM) \
> | __GFP_COMP)
>  #define LOW_ORDER_GFP (GFP_HIGHUSER | __GFP_ZERO | __GFP_COMP)
> @@ -315,6 +315,7 @@ static struct page *alloc_largest_available(unsigned long 
> size,
> unsigned int max_order)
>  {
> struct page *page;
> +   unsigned long gfp_flags;
> int i;
>
> for (i = 0; i < NUM_ORDERS; i++) {
> @@ -323,7 +324,11 @@ static struct page *alloc_largest_available(unsigned 
> long size,
> if (max_order < orders[i])
> continue;
>
> -   page = alloc_pages(order_flags[i], orders[i]);
> +   gfp_flags = order_flags[i];
> +   if (orders[i] > PAGE_ALLOC_COSTLY_ORDER)
> +   gfp_flags |= __GFP_NOWARN;
> +
> +   page = alloc_pages(gfp_flags, orders[i]);

Would it be cleaner to just set up the flags properly in the
order_flags array? I'm not sure I understand why your patch does it
dynamically?

thanks
-john


[PATCH v2 1/2] dma-buf: dma-heap: Provide accessor to get heap name

2021-02-09 Thread John Stultz
It can be useful to access the name for the heap,
so provide an accessor to do so.

Cc: Daniel Vetter 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
v2:
* Make sure to use "const char *" as Reported-by: kernel test robot 

---
 drivers/dma-buf/dma-heap.c | 12 
 include/linux/dma-heap.h   |  9 +
 2 files changed, 21 insertions(+)

diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
index afd22c9dbdcf..70e410c64c1c 100644
--- a/drivers/dma-buf/dma-heap.c
+++ b/drivers/dma-buf/dma-heap.c
@@ -190,6 +190,18 @@ void *dma_heap_get_drvdata(struct dma_heap *heap)
return heap->priv;
 }
 
+/**
+ * dma_heap_get_name() - get heap name
+ * @heap: DMA-Heap to retrieve private data for
+ *
+ * Returns:
+ * The char* for the heap name.
+ */
+const char *dma_heap_get_name(struct dma_heap *heap)
+{
+   return heap->name;
+}
+
 struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info)
 {
struct dma_heap *heap, *h, *err_ret;
diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h
index 454e354d1ffb..83b8cfb2d760 100644
--- a/include/linux/dma-heap.h
+++ b/include/linux/dma-heap.h
@@ -50,6 +50,15 @@ struct dma_heap_export_info {
  */
 void *dma_heap_get_drvdata(struct dma_heap *heap);
 
+/**
+ * dma_heap_get_name() - get heap name
+ * @heap: DMA-Heap to retrieve private data for
+ *
+ * Returns:
+ * The char* for the heap name.
+ */
+const char *dma_heap_get_name(struct dma_heap *heap);
+
 /**
  * dma_heap_add - adds a heap to dmabuf heaps
  * @exp_info:  information needed to register this heap
-- 
2.25.1



[PATCH v2 2/2] dma-buf: heaps: Fix the name used when exporting dmabufs to be the actual heap name

2021-02-09 Thread John Stultz
By default dma_buf_export() sets the exporter name to be
KBUILD_MODNAME. Unfortunately this may not be identical to the
string used as the heap name (ie: "system" vs "system_heap").

This can cause some minor confusion with tooling, and there is
the future potential where multiple heap types may be exported
by the same module (but would all have the same name).

So to avoid all this, set the exporter exp_name to the heap name.

Cc: Daniel Vetter 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
 drivers/dma-buf/heaps/cma_heap.c| 1 +
 drivers/dma-buf/heaps/system_heap.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c
index 364fc2f3e499..62465d61ccc7 100644
--- a/drivers/dma-buf/heaps/cma_heap.c
+++ b/drivers/dma-buf/heaps/cma_heap.c
@@ -339,6 +339,7 @@ static int cma_heap_allocate(struct dma_heap *heap,
buffer->pagecount = pagecount;
 
/* create the dmabuf */
+   exp_info.exp_name = dma_heap_get_name(heap);
exp_info.ops = _heap_buf_ops;
exp_info.size = buffer->len;
exp_info.flags = fd_flags;
diff --git a/drivers/dma-buf/heaps/system_heap.c 
b/drivers/dma-buf/heaps/system_heap.c
index 17e0e9a68baf..2d4afc79c700 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -388,6 +388,7 @@ static int system_heap_allocate(struct dma_heap *heap,
}
 
/* create the dmabuf */
+   exp_info.exp_name = dma_heap_get_name(heap);
exp_info.ops = _heap_buf_ops;
exp_info.size = buffer->len;
exp_info.flags = fd_flags;
-- 
2.25.1



Re: [RFC][PATCH v6 1/7] drm: Add a sharable drm page-pool implementation

2021-02-09 Thread John Stultz
On Tue, Feb 9, 2021 at 4:11 AM Christian König  wrote:
>
>
>
> Am 05.02.21 um 21:46 schrieb John Stultz:
> > On Fri, Feb 5, 2021 at 12:47 AM Christian König
> >  wrote:
> >> Am 05.02.21 um 09:06 schrieb John Stultz:
> >>> diff --git a/drivers/gpu/drm/page_pool.c b/drivers/gpu/drm/page_pool.c
> >>> new file mode 100644
> >>> index ..2139f86e6ca7
> >>> --- /dev/null
> >>> +++ b/drivers/gpu/drm/page_pool.c
> >>> @@ -0,0 +1,220 @@
> >>> +// SPDX-License-Identifier: GPL-2.0
> >> Please use a BSD/MIT compatible license if you want to copy this from
> >> the TTM code.
> > Hrm. This may be problematic, as it's not just TTM code, but some of
> > the TTM logic integrated into a page-pool implementation I wrote based
> > on logic from the ION code (which was GPL-2.0 before it was dropped).
> > So I don't think I can just make it MIT.  Any extra context on the
> > need for MIT, or suggestions on how to best resolve this?
>
> Most of the DRM/TTM code is also license able under the BSD/MIT style
> license since we want to enable the BSD guys to port it over as well.
>
> What stuff do you need from the ION code that you can't just code
> yourself? As far as I have seen this is like 99% code from the TTM pool.

Yea, it evolved into being mostly logic from the TTM pool (or code
that was very similar to begin with), but it's not where it started.
My old days at IBM makes me wary of claiming it's no longer the Ship
of Theseus.

So instead I think I'll have to just throw out my patch and rewrite it
in full (so apologies in advance for any review issues I
introduce/reintroduce).

thanks
-john


Re: [RFC][PATCH v6 3/7] drm: ttm_pool: Rework ttm_pool_free_page to allow us to use it as a function pointer

2021-02-09 Thread John Stultz
On Tue, Feb 9, 2021 at 4:14 AM Christian König  wrote:
> Am 05.02.21 um 20:47 schrieb John Stultz:
> > On Fri, Feb 5, 2021 at 12:28 AM Christian König
> >  wrote:
> >> Adding this to all pages would increase the memory footprint drastically.
> > Yea, that's a good point!  Hrm... bummer. I'll have to see if there's
> > some other way I can get the needed context for the free from the
> > generic page-pool side.
>
> What exactly is the problem here?

Me, usually. :)

> As far as I can see we just have the
> lru entry (list_head) and the pool.

Yea, I reworked it to an embedded drm_page_pool struct, but that is
mostly a list_head.

> How the lru is cast to the page can be completely pool implementation
> specific.

Yea, I had it do container_of(), just haven't gotten around to sending
it out yet.

Thanks so much for the feedback and ideas!

thanks
-john


Re: [RFC][PATCH 2/2] dma-buf: heaps: Fix the name used when exporting dmabufs to be the actual heap name

2021-02-08 Thread John Stultz
On Mon, Feb 8, 2021 at 10:03 PM Sumit Semwal  wrote:
>
> Hi Daniel,
>
> On Tue, 9 Feb 2021 at 02:36, Daniel Vetter  wrote:
> >
> > On Mon, Feb 8, 2021 at 9:51 PM John Stultz  wrote:
> > > On Mon, Feb 8, 2021 at 2:08 AM Daniel Vetter  wrote:
> > > > On Sat, Feb 06, 2021 at 05:47:48AM +, John Stultz wrote:
> > > > > By default dma_buf_export() sets the exporter name to be
> > > > > KBUILD_MODNAME. Unfortunately this may not be identical to the
> > > > > string used as the heap name (ie: "system" vs "system_heap").
> > > > >
> > > > > This can cause some minor confusion with tooling, and there is
> > > > > the future potential where multiple heap types may be exported
> > > > > by the same module (but would all have the same name).
> > > > >
> > > > > So to avoid all this, set the exporter exp_name to the heap name.
> > > > >
> > > > > Cc: Daniel Vetter 
> > > > > Cc: Sumit Semwal 
> > > > > Cc: Liam Mark 
> > > > > Cc: Chris Goldsworthy 
> > > > > Cc: Laura Abbott 
> > > > > Cc: Brian Starkey 
> > > > > Cc: Hridya Valsaraju 
> > > > > Cc: Suren Baghdasaryan 
> > > > > Cc: Sandeep Patil 
> > > > > Cc: Daniel Mentz 
> > > > > Cc: Ørjan Eide 
> > > > > Cc: Robin Murphy 
> > > > > Cc: Ezequiel Garcia 
> > > > > Cc: Simon Ser 
> > > > > Cc: James Jones 
> > > > > Cc: linux-me...@vger.kernel.org
> > > > > Cc: dri-de...@lists.freedesktop.org
> > > > > Signed-off-by: John Stultz 
> > > >
> > > > Looks reasonable to me.
> > > >
> > > > I guess the main worry is "does this mean heap names become uapi", in
> > > > which case I'm maybe not so sure anymore how this will tie into the
> > > > overall gpu memory accounting story.
> > > >
> > > > Since for dma-buf heaps one name per buffer is perfectly fine, since
> > > > dma-buf heaps aren't very dynamic. But on discrete gpu drivers buffers
> > > > move, so baking in the assumption that "exporter name = resource usage 
> > > > for
> > > > this buffer" is broken.
> > >
> > > I suspect I'm missing a subtlety in what you're describing. My sense
> > > of the exporter name doesn't account for a buffer's usage, it just
> > > describes what code allocated it and implicitly which dmabuf_ops
> > > handles it.  Maybe could you give a more specific example of what
> > > you're hoping to avoid?
> >
> > Just paranoia really - on the linux side where we allocate most
> > buffers (even shared ones) with the driver, that allocator info isn't
> > that meaningful, it really just tells you which code
> > allocated/exported that dma-buf.
> >
> > But on Android, where all shared buffers come from specific heaps, it
> > is rather meaningful information. So I wondered whether e.g. the
> > android dmabuf debug tool uses that to collect per-heap stats, but
> > sounds like no right now. Plus with the chat we've had I think we have
> > a long-term plan for how to expose that information properly.
> >
> > > To me this patch is mostly just a consistency/least-surprise thing, so
> > > the heaps exporter name matches the string used for the heap's chardev
> > > device (the interface used to allocate it) in output like
> > > debugfs/dma_buf/bufinfo.
> >
> > Yeah for debug this makes sense. a-b: me if you want that somewhere on
> > the patches.
>
> Great that this got sorted; I'll apply both the patches of this series
> to drm-misc-next, with your a-b.

Before you do, let me spin a v2 as I got some minor tweaks needed
(using const char*) to fix the kbuild bot errors.

thanks
-john


Re: [PATCH 1/5] kselftests: dmabuf-heaps: Fix Makefile's inclusion of the kernel's usr/include dir

2021-02-08 Thread John Stultz
On Mon, Feb 8, 2021 at 3:23 PM Shuah Khan  wrote:
> On 1/28/21 8:05 PM, John Stultz wrote:
> Thanks John for all these 5 fix and cleanup patches.
>
> Applied to linux-kselftest next for 5.12-rc1
>

Great! I was just prepping to resend them :)
Thanks so much!
-john


Re: [RFC][PATCH 2/2] dma-buf: heaps: Fix the name used when exporting dmabufs to be the actual heap name

2021-02-08 Thread John Stultz
On Mon, Feb 8, 2021 at 2:08 AM Daniel Vetter  wrote:
> On Sat, Feb 06, 2021 at 05:47:48AM +0000, John Stultz wrote:
> > By default dma_buf_export() sets the exporter name to be
> > KBUILD_MODNAME. Unfortunately this may not be identical to the
> > string used as the heap name (ie: "system" vs "system_heap").
> >
> > This can cause some minor confusion with tooling, and there is
> > the future potential where multiple heap types may be exported
> > by the same module (but would all have the same name).
> >
> > So to avoid all this, set the exporter exp_name to the heap name.
> >
> > Cc: Daniel Vetter 
> > Cc: Sumit Semwal 
> > Cc: Liam Mark 
> > Cc: Chris Goldsworthy 
> > Cc: Laura Abbott 
> > Cc: Brian Starkey 
> > Cc: Hridya Valsaraju 
> > Cc: Suren Baghdasaryan 
> > Cc: Sandeep Patil 
> > Cc: Daniel Mentz 
> > Cc: Ørjan Eide 
> > Cc: Robin Murphy 
> > Cc: Ezequiel Garcia 
> > Cc: Simon Ser 
> > Cc: James Jones 
> > Cc: linux-me...@vger.kernel.org
> > Cc: dri-de...@lists.freedesktop.org
> > Signed-off-by: John Stultz 
>
> Looks reasonable to me.
>
> I guess the main worry is "does this mean heap names become uapi", in
> which case I'm maybe not so sure anymore how this will tie into the
> overall gpu memory accounting story.
>
> Since for dma-buf heaps one name per buffer is perfectly fine, since
> dma-buf heaps aren't very dynamic. But on discrete gpu drivers buffers
> move, so baking in the assumption that "exporter name = resource usage for
> this buffer" is broken.

I suspect I'm missing a subtlety in what you're describing. My sense
of the exporter name doesn't account for a buffer's usage, it just
describes what code allocated it and implicitly which dmabuf_ops
handles it.  Maybe could you give a more specific example of what
you're hoping to avoid?

To me this patch is mostly just a consistency/least-surprise thing, so
the heaps exporter name matches the string used for the heap's chardev
device (the interface used to allocate it) in output like
debugfs/dma_buf/bufinfo.

thanks
-john


[RFC][PATCH 1/2] dma-buf: dma-heap: Provide accessor to get heap name

2021-02-05 Thread John Stultz
It can be useful to access the name for the heap,
so provide an accessor to do so.

Cc: Daniel Vetter 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
 drivers/dma-buf/dma-heap.c | 13 +
 include/linux/dma-heap.h   |  9 +
 2 files changed, 22 insertions(+)

diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
index afd22c9dbdcf..6c746ea67676 100644
--- a/drivers/dma-buf/dma-heap.c
+++ b/drivers/dma-buf/dma-heap.c
@@ -190,6 +190,19 @@ void *dma_heap_get_drvdata(struct dma_heap *heap)
return heap->priv;
 }
 
+
+/**
+ * dma_heap_get_name() - get heap name
+ * @heap: DMA-Heap to retrieve private data for
+ *
+ * Returns:
+ * The char* for the heap name.
+ */
+char *dma_heap_get_name(struct dma_heap *heap)
+{
+   return heap->name;
+}
+
 struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info)
 {
struct dma_heap *heap, *h, *err_ret;
diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h
index 454e354d1ffb..b91778291fb1 100644
--- a/include/linux/dma-heap.h
+++ b/include/linux/dma-heap.h
@@ -50,6 +50,15 @@ struct dma_heap_export_info {
  */
 void *dma_heap_get_drvdata(struct dma_heap *heap);
 
+/**
+ * dma_heap_get_name() - get heap name
+ * @heap: DMA-Heap to retrieve private data for
+ *
+ * Returns:
+ * The char* for the heap name.
+ */
+char *dma_heap_get_name(struct dma_heap *heap);
+
 /**
  * dma_heap_add - adds a heap to dmabuf heaps
  * @exp_info:  information needed to register this heap
-- 
2.25.1



[RFC][PATCH 2/2] dma-buf: heaps: Fix the name used when exporting dmabufs to be the actual heap name

2021-02-05 Thread John Stultz
By default dma_buf_export() sets the exporter name to be
KBUILD_MODNAME. Unfortunately this may not be identical to the
string used as the heap name (ie: "system" vs "system_heap").

This can cause some minor confusion with tooling, and there is
the future potential where multiple heap types may be exported
by the same module (but would all have the same name).

So to avoid all this, set the exporter exp_name to the heap name.

Cc: Daniel Vetter 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
 drivers/dma-buf/heaps/cma_heap.c| 1 +
 drivers/dma-buf/heaps/system_heap.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c
index 364fc2f3e499..62465d61ccc7 100644
--- a/drivers/dma-buf/heaps/cma_heap.c
+++ b/drivers/dma-buf/heaps/cma_heap.c
@@ -339,6 +339,7 @@ static int cma_heap_allocate(struct dma_heap *heap,
buffer->pagecount = pagecount;
 
/* create the dmabuf */
+   exp_info.exp_name = dma_heap_get_name(heap);
exp_info.ops = _heap_buf_ops;
exp_info.size = buffer->len;
exp_info.flags = fd_flags;
diff --git a/drivers/dma-buf/heaps/system_heap.c 
b/drivers/dma-buf/heaps/system_heap.c
index 17e0e9a68baf..2d4afc79c700 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -388,6 +388,7 @@ static int system_heap_allocate(struct dma_heap *heap,
}
 
/* create the dmabuf */
+   exp_info.exp_name = dma_heap_get_name(heap);
exp_info.ops = _heap_buf_ops;
exp_info.size = buffer->len;
exp_info.flags = fd_flags;
-- 
2.25.1



Re: [RFC][PATCH v6 0/7] Generic page pool & deferred freeing for system dmabuf heap

2021-02-05 Thread John Stultz
On Fri, Feb 5, 2021 at 2:36 AM Christian König  wrote:
> Am 05.02.21 um 09:06 schrieb John Stultz:
> > Input would be greatly appreciated. Testing as well, as I don't
> > have any development hardware that utilizes the ttm pool.
>
> We can easily do the testing and the general idea sounds solid to me.
>

Thanks so much again for the feedback!

> I see three major things we need to clean up here.
> 1. The licensing, you are moving from BSD/MIT to GPL2.

Yea, this may be sticky, as it's not just code re-used from one dual
licensed file, but combination of GPL2 work, so advice here would be
appreciated.

> 2. Don't add any new overhead to the TTM pool, especially allocating a
> private object per page is a no-go.

This will need some more series rework to solve. I've got some ideas,
but we'll see if they work.

> 3. What are you doing with the reclaim stuff and why?

As I mentioned, it's a holdover from earlier code, and I'm happy to
drop it and defer to other accounting/stats discussions that are
ongoing.

> 4. Keeping the documentation would be nice to have.

True. I didn't spend much time with documentation, as I worried folks
may have disagreed with the whole approach. I'll work to improve it
for the next go around.

Thanks so much again for the review and feedback! I really appreciate
your time here.
-john


Re: [RFC][PATCH v6 1/7] drm: Add a sharable drm page-pool implementation

2021-02-05 Thread John Stultz
On Fri, Feb 5, 2021 at 12:47 AM Christian König
 wrote:
> Am 05.02.21 um 09:06 schrieb John Stultz:
> > diff --git a/drivers/gpu/drm/page_pool.c b/drivers/gpu/drm/page_pool.c
> > new file mode 100644
> > index ..2139f86e6ca7
> > --- /dev/null
> > +++ b/drivers/gpu/drm/page_pool.c
> > @@ -0,0 +1,220 @@
> > +// SPDX-License-Identifier: GPL-2.0
>
> Please use a BSD/MIT compatible license if you want to copy this from
> the TTM code.

Hrm. This may be problematic, as it's not just TTM code, but some of
the TTM logic integrated into a page-pool implementation I wrote based
on logic from the ION code (which was GPL-2.0 before it was dropped).
So I don't think I can just make it MIT.  Any extra context on the
need for MIT, or suggestions on how to best resolve this?

> > +int drm_page_pool_get_size(struct drm_page_pool *pool)
> > +{
> > + int ret;
> > +
> > + spin_lock(>lock);
> > + ret = pool->count;
> > + spin_unlock(>lock);
>
> Maybe use an atomic for the count instead?
>

I can do that, but am curious as to the benefit? We are mostly using
count where we already have to take the pool->lock anyway, and this
drm_page_pool_get_size() is only used for debugfs output so far, so I
don't expect it to be a hot path.


> > +void drm_page_pool_add(struct drm_page_pool *pool, struct page *page)
> > +{
> > + spin_lock(>lock);
> > + list_add_tail(>lru, >items);
> > + pool->count++;
> > + atomic_long_add(1 << pool->order, _pages);
> > + spin_unlock(>lock);
> > +
> > + mod_node_page_state(page_pgdat(page), NR_KERNEL_MISC_RECLAIMABLE,
> > + 1 << pool->order);
>
> Hui what? What should that be good for?

This is a carryover from the ION page pool implementation:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/staging/android/ion/ion_page_pool.c?h=v5.10#n28

My sense is it helps with the vmstat/meminfo accounting so folks can
see the cached pages are shrinkable/freeable. This maybe falls under
other dmabuf accounting/stats discussions, so I'm happy to remove it
for now, or let the drivers using the shared page pool logic handle
the accounting themselves?


> > +static struct page *drm_page_pool_remove(struct drm_page_pool *pool)
> > +{
> > + struct page *page;
> > +
> > + if (!pool->count)
> > + return NULL;
>
> Better use list_first_entry_or_null instead of checking the count.
>
> This way you can also pull the lock into the function.

Yea, that cleans a number of things up nicely. Thank you!


> > +struct drm_page_pool *drm_page_pool_create(unsigned int order,
> > +int (*free_page)(struct page *p, 
> > unsigned int order))
> > +{
> > + struct drm_page_pool *pool = kmalloc(sizeof(*pool), GFP_KERNEL);
>
> Why not making this an embedded object? We should not see much dynamic
> pool creation.

Yea, it felt cleaner at the time this way, but I think I will need to
switch to an embedded object in order to resolve the memory usage
issue you pointed out with growing the ttm_pool_dma, so thank you for
the suggestion!


> > +void drm_page_pool_destroy(struct drm_page_pool *pool)
> > +{
> > + struct page *page;
> > +
> > + /* Remove us from the pool list */
> > + mutex_lock(_list_lock);
> > + list_del(>list);
> > + mutex_unlock(_list_lock);
> > +
> > + /* Free any remaining pages in the pool */
> > + spin_lock(>lock);
>
> Locking should be unnecessary when the pool is destroyed anyway.

I guess if we've already pruned ourself from the pool list, then your
right, we can't race with the shrinker and it's maybe not necessary.
But it also seems easier to consistently follow the locking rules in a
very unlikely path rather than leaning on subtlety.  Either way, I
think this becomes moot if I make the improvements you suggest to
drm_page_pool_remove().

> > +static int drm_page_pool_shrink_one(void)
> > +{
> > + struct drm_page_pool *pool;
> > + struct page *page;
> > + int nr_freed = 0;
> > +
> > + mutex_lock(_list_lock);
> > + pool = list_first_entry(_list, typeof(*pool), list);
> > +
> > + spin_lock(>lock);
> > + page = drm_page_pool_remove(pool);
> > + spin_unlock(>lock);
> > +
> > + if (page)
> > + nr_freed = drm_page_pool_free_pages(pool, page);
> > +
> > + list_move_tail(>list, _list);
>
> Better to move this up, directly after the list_first_entry().

Sounds good!

Thanks so much for your review and feedback! I'll try to get some of
the easy suggestions integrated, and will have to figure out what to
do about the re-licensing request.

thanks
-john


Re: [RFC][PATCH v6 3/7] drm: ttm_pool: Rework ttm_pool_free_page to allow us to use it as a function pointer

2021-02-05 Thread John Stultz
On Fri, Feb 5, 2021 at 12:28 AM Christian König
 wrote:
> Am 05.02.21 um 09:06 schrieb John Stultz:
> > This refactors ttm_pool_free_page(), and by adding extra entries
> > to ttm_pool_page_dat, we then use it for all allocations, which
> > allows us to simplify the arguments needed to be passed to
> > ttm_pool_free_page().
>
> This is a clear NAK since the peer page data is just a workaround for
> the DMA-API hack to grab pages from there.
>
> Adding this to all pages would increase the memory footprint drastically.

Yea, that's a good point!  Hrm... bummer. I'll have to see if there's
some other way I can get the needed context for the free from the
generic page-pool side.

Thanks so much for the review!
-john


[RFC][PATCH v6 0/7] Generic page pool & deferred freeing for system dmabuf heap

2021-02-05 Thread John Stultz
This series is starting to get long, so I figured I'd add a
short cover letter for context.

The point of this series is trying to add both deferred-freeing
logic as well as a page pool to the DMA-BUF system heap.

This is desired, as the combination of deferred freeing along
with the page pool allows us to offload page-zeroing out of
the allocation hot path. This was done originally with ION
and this patch series allows the DMA-BUF system heap to match
ION's system heap allocation performance in a simple
microbenchmark [1] (ION re-added to the kernel for comparision,
running on an x86 vm image):

./dmabuf-heap-bench -i 0 1 system 
Testing dmabuf system vs ion heaptype 0 (flags: 0x1)
-
dmabuf heap: alloc 4096 bytes 5000 times in 86572223 ns  17314 ns/call
ion heap:alloc 4096 bytes 5000 times in 97442526 ns  19488 ns/call
dmabuf heap: alloc 1048576 bytes 5000 times in 196635057 ns  39327 ns/call
ion heap:alloc 1048576 bytes 5000 times in 357323629 ns  71464 ns/call
dmabuf heap: alloc 8388608 bytes 5000 times in 3165445534 ns 633089 ns/call
ion heap:alloc 8388608 bytes 5000 times in 3699591271 ns 739918 ns/call
dmabuf heap: alloc 33554432 bytes 5000 times in 13327402517 ns   2665480 ns/call
ion heap:alloc 33554432 bytes 5000 times in 15292352796 ns   3058470 ns/call

Daniel didn't like earlier attempts to re-use the network
page-pool code to achieve this, and suggested the ttm_pool be
used instead. This required pulling the fairly tightly knit
ttm_pool logic apart, but after many failed attmempts I think
I found a workable abstraction to split out shared logic.

So this series contains a new generic drm_page_pool helper
library, converts the ttm_pool to use it, and then adds the
dmabuf deferred freeing and adds support to the dmabuf system
heap to use both deferred freeing and the new drm_page_pool.

Input would be greatly appreciated. Testing as well, as I don't
have any development hardware that utilizes the ttm pool.

thanks
-john

[1] 
https://android.googlesource.com/platform/system/memory/libdmabufheap/+/refs/heads/master/tests/dmabuf_heap_bench.c

Cc: Daniel Vetter 
Cc: Christian Koenig 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org

John Stultz (7):
  drm: Add a sharable drm page-pool implementation
  drm: ttm_pool: Rename the ttm_pool_dma structure to ttm_pool_page_dat
  drm: ttm_pool: Rework ttm_pool_free_page to allow us to use it as a
function pointer
  drm: ttm_pool: Rework ttm_pool to use drm_page_pool
  dma-buf: heaps: Add deferred-free-helper library code
  dma-buf: system_heap: Add drm pagepool support to system heap
  dma-buf: system_heap: Add deferred freeing to the system heap

 drivers/dma-buf/heaps/Kconfig|   5 +
 drivers/dma-buf/heaps/Makefile   |   1 +
 drivers/dma-buf/heaps/deferred-free-helper.c | 145 ++
 drivers/dma-buf/heaps/deferred-free-helper.h |  55 
 drivers/dma-buf/heaps/system_heap.c  |  77 -
 drivers/gpu/drm/Kconfig  |   5 +
 drivers/gpu/drm/Makefile |   1 +
 drivers/gpu/drm/page_pool.c  | 220 +++
 drivers/gpu/drm/ttm/ttm_pool.c   | 278 ++-
 include/drm/page_pool.h  |  54 
 include/drm/ttm/ttm_pool.h   |  23 +-
 11 files changed, 639 insertions(+), 225 deletions(-)
 create mode 100644 drivers/dma-buf/heaps/deferred-free-helper.c
 create mode 100644 drivers/dma-buf/heaps/deferred-free-helper.h
 create mode 100644 drivers/gpu/drm/page_pool.c
 create mode 100644 include/drm/page_pool.h

-- 
2.25.1



[RFC][PATCH v6 1/7] drm: Add a sharable drm page-pool implementation

2021-02-05 Thread John Stultz
This adds a shrinker controlled page pool, closely
following the ttm_pool logic, which is abstracted out
a bit so it can be used by other non-ttm drivers.

Cc: Daniel Vetter 
Cc: Christian Koenig 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
 drivers/gpu/drm/Kconfig |   4 +
 drivers/gpu/drm/Makefile|   1 +
 drivers/gpu/drm/page_pool.c | 220 
 include/drm/page_pool.h |  54 +
 4 files changed, 279 insertions(+)
 create mode 100644 drivers/gpu/drm/page_pool.c
 create mode 100644 include/drm/page_pool.h

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 0973f408d75f..d16bf340ed2e 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -174,6 +174,10 @@ config DRM_DP_CEC
  Note: not all adapters support this feature, and even for those
  that do support this they often do not hook up the CEC pin.
 
+config DRM_PAGE_POOL
+   bool
+   depends on DRM
+
 config DRM_TTM
tristate
depends on DRM && MMU
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index fefaff4c832d..877e0111ed34 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -32,6 +32,7 @@ drm-$(CONFIG_AGP) += drm_agpsupport.o
 drm-$(CONFIG_PCI) += drm_pci.o
 drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o
 drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
+drm-$(CONFIG_DRM_PAGE_POOL) += page_pool.o
 
 drm_vram_helper-y := drm_gem_vram_helper.o
 obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o
diff --git a/drivers/gpu/drm/page_pool.c b/drivers/gpu/drm/page_pool.c
new file mode 100644
index ..2139f86e6ca7
--- /dev/null
+++ b/drivers/gpu/drm/page_pool.c
@@ -0,0 +1,220 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DRM page pool system
+ *
+ * Copyright (C) 2020 Linaro Ltd.
+ *
+ * Based on the ION page pool code
+ * Copyright (C) 2011 Google, Inc.
+ * As well as the ttm_pool code
+ * Copyright (C) 2020 Advanced Micro Devices, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static LIST_HEAD(pool_list);
+static DEFINE_MUTEX(pool_list_lock);
+static atomic_long_t total_pages;
+static unsigned long page_pool_max;
+MODULE_PARM_DESC(page_pool_max, "Number of pages in the WC/UC/DMA pool");
+module_param(page_pool_max, ulong, 0644);
+
+void drm_page_pool_set_max(unsigned long max)
+{
+   /* only write once */
+   if (!page_pool_max)
+   page_pool_max = max;
+}
+
+unsigned long drm_page_pool_get_max(void)
+{
+   return page_pool_max;
+}
+
+unsigned long drm_page_pool_get_total(void)
+{
+   return atomic_long_read(_pages);
+}
+
+int drm_page_pool_get_size(struct drm_page_pool *pool)
+{
+   int ret;
+
+   spin_lock(>lock);
+   ret = pool->count;
+   spin_unlock(>lock);
+   return ret;
+}
+
+static inline unsigned int drm_page_pool_free_pages(struct drm_page_pool *pool,
+   struct page *page)
+{
+   return pool->free(page, pool->order);
+}
+
+static int drm_page_pool_shrink_one(void);
+
+void drm_page_pool_add(struct drm_page_pool *pool, struct page *page)
+{
+   spin_lock(>lock);
+   list_add_tail(>lru, >items);
+   pool->count++;
+   atomic_long_add(1 << pool->order, _pages);
+   spin_unlock(>lock);
+
+   mod_node_page_state(page_pgdat(page), NR_KERNEL_MISC_RECLAIMABLE,
+   1 << pool->order);
+
+   /* make sure we don't grow too large */
+   while (page_pool_max && atomic_long_read(_pages) > page_pool_max)
+   drm_page_pool_shrink_one();
+}
+EXPORT_SYMBOL_GPL(drm_page_pool_add);
+
+static struct page *drm_page_pool_remove(struct drm_page_pool *pool)
+{
+   struct page *page;
+
+   if (!pool->count)
+   return NULL;
+
+   page = list_first_entry(>items, struct page, lru);
+   pool->count--;
+   atomic_long_sub(1 << pool->order, _pages);
+
+   list_del(>lru);
+   mod_node_page_state(page_pgdat(page), NR_KERNEL_MISC_RECLAIMABLE,
+   -(1 << pool->order));
+   return page;
+}
+
+struct page *drm_page_pool_fetch(struct drm_page_pool *pool)
+{
+   struct page *page = NULL;
+
+   if (!pool) {
+   WARN_ON(!pool);
+   return NULL;
+   }
+
+   spin_lock(>lock);
+   page = drm_page_pool_remove(pool);
+   spin_unlock(>lock);
+
+   return page;
+}
+EXPORT_SYMBOL_GPL(drm_page_pool_fetch);
+
+struct drm_page_pool *drm_page_pool_create(un

[RFC][PATCH v6 4/7] drm: ttm_pool: Rework ttm_pool to use drm_page_pool

2021-02-05 Thread John Stultz
This patch reworks the ttm_pool logic to utilize the recently
added drm_page_pool code.

Basically all the ttm_pool_type structures are replaced with
drm_page_pool pointers, and since the drm_page_pool logic has
its own shrinker, we can remove all of the ttm_pool shrinker
logic.

NOTE: There is one mismatch in the interfaces I'm not totally
happy with. The ttm_pool tracks all of its pooled pages across
a number of different pools, and tries to keep this size under
the specified page_pool_size value. With the drm_page_pool,
there may other users, however there is still one global
shrinker list of pools. So we can't easily reduce the ttm
pool under the ttm specified size without potentially doing
a lot of shrinking to other non-ttm pools. So either we can:
  1) Try to split it so each user of drm_page_pools manages its
 own pool shrinking.
  2) Push the max value into the drm_page_pool, and have it
 manage shrinking to fit under that global max. Then share
 those size/max values out so the ttm_pool debug output
 can have more context.

I've taken the second path in this patch set, but wanted to call
it out so folks could look closely.

Thoughts would be greatly appreciated here!

Cc: Daniel Vetter 
Cc: Christian Koenig 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
 drivers/gpu/drm/Kconfig|   1 +
 drivers/gpu/drm/ttm/ttm_pool.c | 199 +++--
 include/drm/ttm/ttm_pool.h |  23 +---
 3 files changed, 41 insertions(+), 182 deletions(-)

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index d16bf340ed2e..d427abefabfb 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -181,6 +181,7 @@ config DRM_PAGE_POOL
 config DRM_TTM
tristate
depends on DRM && MMU
+   select DRM_PAGE_POOL
help
  GPU memory management subsystem for devices with multiple
  GPU memory types. Will be enabled automatically if a device driver
diff --git a/drivers/gpu/drm/ttm/ttm_pool.c b/drivers/gpu/drm/ttm/ttm_pool.c
index eca36678f967..dbbaf55ca5df 100644
--- a/drivers/gpu/drm/ttm/ttm_pool.c
+++ b/drivers/gpu/drm/ttm/ttm_pool.c
@@ -37,6 +37,7 @@
 #ifdef CONFIG_X86
 #include 
 #endif
+#include 
 #include 
 #include 
 #include 
@@ -63,15 +64,13 @@ module_param(page_pool_size, ulong, 0644);
 
 static atomic_long_t allocated_pages;
 
-static struct ttm_pool_type global_write_combined[MAX_ORDER];
-static struct ttm_pool_type global_uncached[MAX_ORDER];
+static struct drm_page_pool *global_write_combined[MAX_ORDER];
+static struct drm_page_pool *global_uncached[MAX_ORDER];
 
-static struct ttm_pool_type global_dma32_write_combined[MAX_ORDER];
-static struct ttm_pool_type global_dma32_uncached[MAX_ORDER];
+static struct drm_page_pool *global_dma32_write_combined[MAX_ORDER];
+static struct drm_page_pool *global_dma32_uncached[MAX_ORDER];
 
 static struct mutex shrinker_lock;
-static struct list_head shrinker_list;
-static struct shrinker mm_shrinker;
 
 /* Allocate pages of size 1 << order with the given gfp_flags */
 static struct page *ttm_pool_alloc_page(struct ttm_pool *pool, gfp_t gfp_flags,
@@ -223,79 +222,26 @@ static void ttm_pool_unmap(struct ttm_pool *pool, 
dma_addr_t dma_addr,
   DMA_BIDIRECTIONAL);
 }
 
-/* Give pages into a specific pool_type */
-static void ttm_pool_type_give(struct ttm_pool_type *pt, struct page *p)
-{
-   spin_lock(>lock);
-   list_add(>lru, >pages);
-   spin_unlock(>lock);
-   atomic_long_add(1 << pt->order, _pages);
-}
-
-/* Take pages from a specific pool_type, return NULL when nothing available */
-static struct page *ttm_pool_type_take(struct ttm_pool_type *pt)
-{
-   struct page *p;
-
-   spin_lock(>lock);
-   p = list_first_entry_or_null(>pages, typeof(*p), lru);
-   if (p) {
-   atomic_long_sub(1 << pt->order, _pages);
-   list_del(>lru);
-   }
-   spin_unlock(>lock);
-
-   return p;
-}
-
-/* Initialize and add a pool type to the global shrinker list */
-static void ttm_pool_type_init(struct ttm_pool_type *pt, struct ttm_pool *pool,
-  enum ttm_caching caching, unsigned int order)
-{
-   pt->pool = pool;
-   pt->caching = caching;
-   pt->order = order;
-   spin_lock_init(>lock);
-   INIT_LIST_HEAD(>pages);
-
-   mutex_lock(_lock);
-   list_add_tail(>shrinker_list, _list);
-   mutex_unlock(_lock);
-}
-
-/* Remove a pool_type from the global shrinker list and free all pages */
-static void ttm_pool_type_fini(struct ttm_pool_type *pt)
-{
-   struct p

[RFC][PATCH v6 5/7] dma-buf: heaps: Add deferred-free-helper library code

2021-02-05 Thread John Stultz
This patch provides infrastructure for deferring buffer frees.

This is a feature ION provided which when used with some form
of a page pool, provides a nice performance boost in an
allocation microbenchmark. The reason it helps is it allows the
page-zeroing to be done out of the normal allocation/free path,
and pushed off to a kthread.

As not all heaps will find this useful, its implemented as
a optional helper library that heaps can utilize.

Cc: Daniel Vetter 
Cc: Christian Koenig 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
v2:
* Fix sleep in atomic issue from using a mutex, by switching
  to a spinlock as Reported-by: kernel test robot 
* Cleanup API to use a reason enum for clarity and add some documentation
  comments as suggested by Suren Baghdasaryan.
v3:
* Minor tweaks so it can be built as a module
* A few small fixups suggested by Daniel Mentz
v4:
* Tweak from Daniel Mentz to make sure the shrinker
  count/freed values are tracked in pages not bytes
v5:
* Fix up page count tracking as suggested by Suren Baghdasaryan
---
 drivers/dma-buf/heaps/Kconfig|   3 +
 drivers/dma-buf/heaps/Makefile   |   1 +
 drivers/dma-buf/heaps/deferred-free-helper.c | 145 +++
 drivers/dma-buf/heaps/deferred-free-helper.h |  55 +++
 4 files changed, 204 insertions(+)
 create mode 100644 drivers/dma-buf/heaps/deferred-free-helper.c
 create mode 100644 drivers/dma-buf/heaps/deferred-free-helper.h

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index a5eef06c4226..f7aef8bc7119 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -1,3 +1,6 @@
+config DMABUF_HEAPS_DEFERRED_FREE
+   tristate
+
 config DMABUF_HEAPS_SYSTEM
bool "DMA-BUF System Heap"
depends on DMABUF_HEAPS
diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile
index 974467791032..4e7839875615 100644
--- a/drivers/dma-buf/heaps/Makefile
+++ b/drivers/dma-buf/heaps/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_DMABUF_HEAPS_DEFERRED_FREE) += deferred-free-helper.o
 obj-$(CONFIG_DMABUF_HEAPS_SYSTEM)  += system_heap.o
 obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o
diff --git a/drivers/dma-buf/heaps/deferred-free-helper.c 
b/drivers/dma-buf/heaps/deferred-free-helper.c
new file mode 100644
index ..672c3d5872e9
--- /dev/null
+++ b/drivers/dma-buf/heaps/deferred-free-helper.c
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Deferred dmabuf freeing helper
+ *
+ * Copyright (C) 2020 Linaro, Ltd.
+ *
+ * Based on the ION page pool code
+ * Copyright (C) 2011 Google, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "deferred-free-helper.h"
+
+static LIST_HEAD(free_list);
+static size_t list_size_pages;
+wait_queue_head_t freelist_waitqueue;
+struct task_struct *freelist_task;
+static DEFINE_SPINLOCK(free_list_lock);
+
+static inline size_t size_to_pages(size_t size)
+{
+   if (!size)
+   return 0;
+   return ((size - 1) >> PAGE_SHIFT) + 1;
+}
+
+void deferred_free(struct deferred_freelist_item *item,
+  void (*free)(struct deferred_freelist_item*,
+   enum df_reason),
+  size_t size)
+{
+   unsigned long flags;
+
+   INIT_LIST_HEAD(>list);
+   item->size = size;
+   item->free = free;
+
+   spin_lock_irqsave(_list_lock, flags);
+   list_add(>list, _list);
+   list_size_pages += size_to_pages(size);
+   spin_unlock_irqrestore(_list_lock, flags);
+   wake_up(_waitqueue);
+}
+EXPORT_SYMBOL_GPL(deferred_free);
+
+static size_t free_one_item(enum df_reason reason)
+{
+   unsigned long flags;
+   size_t nr_pages;
+   struct deferred_freelist_item *item;
+
+   spin_lock_irqsave(_list_lock, flags);
+   if (list_empty(_list)) {
+   spin_unlock_irqrestore(_list_lock, flags);
+   return 0;
+   }
+   item = list_first_entry(_list, struct deferred_freelist_item, 
list);
+   list_del(>list);
+   nr_pages = size_to_pages(item->size);
+   list_size_pages -= nr_pages;
+   spin_unlock_irqrestore(_list_lock, flags);
+
+   item->free(item, reason);
+   return nr_pages;
+}
+
+static unsigned long get_freelist_size_pages(void)
+{
+   unsigned long size;
+   unsigned long flags;
+
+   spin_lock_irqsave(_list_lock, flags);
+   size = list_size_pages;
+   spin_unlock_irqrestore(_list_lock, flags);
+   return size;
+}
+
+static unsigned long 

[RFC][PATCH v6 6/7] dma-buf: system_heap: Add drm pagepool support to system heap

2021-02-05 Thread John Stultz
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 
Cc: Christian Koenig 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
v2:
* Fix build issue caused by selecting PAGE_POOL w/o NET
  as Reported-by: kernel test robot 
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 
 #include 
 
+#include 
+
 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 = >sg_table;
+   struct sg_page_iter piter;
+   struct page *p;
+   void *vaddr;
+   int ret = 0;
+
+   for_each_sgtable_page(sgt, , 0) {
+   p = sg_page_iter_page();
+   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 = >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(pool

[RFC][PATCH v6 3/7] drm: ttm_pool: Rework ttm_pool_free_page to allow us to use it as a function pointer

2021-02-05 Thread John Stultz
This refactors ttm_pool_free_page(), and by adding extra entries
to ttm_pool_page_dat, we then use it for all allocations, which
allows us to simplify the arguments needed to be passed to
ttm_pool_free_page().

This is critical for allowing the free function to be called
by the sharable drm_page_pool logic.

Cc: Daniel Vetter 
Cc: Christian Koenig 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
 drivers/gpu/drm/ttm/ttm_pool.c | 60 ++
 1 file changed, 32 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/ttm/ttm_pool.c b/drivers/gpu/drm/ttm/ttm_pool.c
index c0274e256be3..eca36678f967 100644
--- a/drivers/gpu/drm/ttm/ttm_pool.c
+++ b/drivers/gpu/drm/ttm/ttm_pool.c
@@ -44,10 +44,14 @@
 /**
  * struct ttm_pool_page_dat - Helper object for coherent DMA mappings
  *
+ * @pool: ttm_pool pointer the page was allocated by
+ * @caching: the caching value the allocated page was configured for
  * @addr: original DMA address returned for the mapping
  * @vaddr: original vaddr return for the mapping and order in the lower bits
  */
 struct ttm_pool_page_dat {
+   struct ttm_pool *pool;
+   enum ttm_caching caching;
dma_addr_t addr;
unsigned long vaddr;
 };
@@ -71,13 +75,20 @@ static struct shrinker mm_shrinker;
 
 /* Allocate pages of size 1 << order with the given gfp_flags */
 static struct page *ttm_pool_alloc_page(struct ttm_pool *pool, gfp_t gfp_flags,
-   unsigned int order)
+   unsigned int order, enum ttm_caching 
caching)
 {
unsigned long attr = DMA_ATTR_FORCE_CONTIGUOUS;
struct ttm_pool_page_dat *dat;
struct page *p;
void *vaddr;
 
+   dat = kmalloc(sizeof(*dat), GFP_KERNEL);
+   if (!dat)
+   return NULL;
+
+   dat->pool = pool;
+   dat->caching = caching;
+
/* Don't set the __GFP_COMP flag for higher order allocations.
 * Mapping pages directly into an userspace process and calling
 * put_page() on a TTM allocated page is illegal.
@@ -88,15 +99,13 @@ static struct page *ttm_pool_alloc_page(struct ttm_pool 
*pool, gfp_t gfp_flags,
 
if (!pool->use_dma_alloc) {
p = alloc_pages(gfp_flags, order);
-   if (p)
-   p->private = order;
+   if (!p)
+   goto error_free;
+   dat->vaddr = order;
+   p->private = (unsigned long)dat;
return p;
}
 
-   dat = kmalloc(sizeof(*dat), GFP_KERNEL);
-   if (!dat)
-   return NULL;
-
if (order)
attr |= DMA_ATTR_NO_WARN;
 
@@ -123,34 +132,34 @@ static struct page *ttm_pool_alloc_page(struct ttm_pool 
*pool, gfp_t gfp_flags,
 }
 
 /* Reset the caching and pages of size 1 << order */
-static void ttm_pool_free_page(struct ttm_pool *pool, enum ttm_caching caching,
-  unsigned int order, struct page *p)
+static int ttm_pool_free_page(struct page *p, unsigned int order)
 {
unsigned long attr = DMA_ATTR_FORCE_CONTIGUOUS;
-   struct ttm_pool_page_dat *dat;
+   struct ttm_pool_page_dat *dat = (void *)p->private;
void *vaddr;
 
 #ifdef CONFIG_X86
/* We don't care that set_pages_wb is inefficient here. This is only
 * used when we have to shrink and CPU overhead is irrelevant then.
 */
-   if (caching != ttm_cached && !PageHighMem(p))
+   if (dat->caching != ttm_cached && !PageHighMem(p))
set_pages_wb(p, 1 << order);
 #endif
 
-   if (!pool || !pool->use_dma_alloc) {
+   if (!dat->pool || !dat->pool->use_dma_alloc) {
__free_pages(p, order);
-   return;
+   goto out;
}
 
if (order)
attr |= DMA_ATTR_NO_WARN;
 
-   dat = (void *)p->private;
vaddr = (void *)(dat->vaddr & PAGE_MASK);
-   dma_free_attrs(pool->dev, (1UL << order) * PAGE_SIZE, vaddr, dat->addr,
+   dma_free_attrs(dat->pool->dev, (1UL << order) * PAGE_SIZE, vaddr, 
dat->addr,
   attr);
+out:
kfree(dat);
+   return 1 << order;
 }
 
 /* Apply a new caching to an array of pages */
@@ -264,7 +273,7 @@ static void ttm_pool_type_fini(struct ttm_pool_type *pt)
mutex_unlock(_lock);
 
list_for_each_entry_safe(p, tmp, >pages, lru)
-   ttm_pool_free_page(pt->pool, pt->caching, pt->order, p);
+   ttm_pool_free_page(p, pt->order);
 }
 
 /* Return t

[RFC][PATCH v6 7/7] dma-buf: system_heap: Add deferred freeing to the system heap

2021-02-05 Thread John Stultz
Utilize the deferred free helper library in the system heap.

This provides a nice performance bump and puts the
system heap performance on par with ION.

Cc: Daniel Vetter 
Cc: Christian Koenig 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
v2:
* Rework deferred-free api to use reason enum as suggested by
  Suren Baghdasaryan
---
 drivers/dma-buf/heaps/Kconfig   |  1 +
 drivers/dma-buf/heaps/system_heap.c | 31 ++---
 2 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index 7e28934e0def..10632ccfb4a5 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -5,6 +5,7 @@ config DMABUF_HEAPS_SYSTEM
bool "DMA-BUF System Heap"
depends on DMABUF_HEAPS
select DRM_PAGE_POOL
+   select DMABUF_HEAPS_DEFERRED_FREE
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 6d39e9f32e36..042244407db5 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -22,6 +22,7 @@
 #include 
 
 #include 
+#include "deferred-free-helper.h"
 
 static struct dma_heap *sys_heap;
 
@@ -33,6 +34,7 @@ struct system_heap_buffer {
struct sg_table sg_table;
int vmap_cnt;
void *vaddr;
+   struct deferred_freelist_item deferred_free;
 };
 
 struct dma_heap_attachment {
@@ -308,30 +310,45 @@ static int system_heap_zero_buffer(struct 
system_heap_buffer *buffer)
return ret;
 }
 
-static void system_heap_dma_buf_release(struct dma_buf *dmabuf)
+static void system_heap_buf_free(struct deferred_freelist_item *item,
+enum df_reason reason)
 {
-   struct system_heap_buffer *buffer = dmabuf->priv;
+   struct system_heap_buffer *buffer;
struct sg_table *table;
struct scatterlist *sg;
int i, j;
 
+   buffer = container_of(item, struct system_heap_buffer, deferred_free);
/* Zero the buffer pages before adding back to the pool */
-   system_heap_zero_buffer(buffer);
+   if (reason == DF_NORMAL)
+   if (system_heap_zero_buffer(buffer))
+   reason = DF_UNDER_PRESSURE; // On failure, just free
 
table = >sg_table;
for_each_sg(table->sgl, sg, table->nents, i) {
struct page *page = sg_page(sg);
 
-   for (j = 0; j < NUM_ORDERS; j++) {
-   if (compound_order(page) == orders[j])
-   break;
+   if (reason == DF_UNDER_PRESSURE) {
+   __free_pages(page, compound_order(page));
+   } else {
+   for (j = 0; j < NUM_ORDERS; j++) {
+   if (compound_order(page) == orders[j])
+   break;
+   }
+   drm_page_pool_add(pools[j], page);
}
-   drm_page_pool_add(pools[j], page);
}
sg_free_table(table);
kfree(buffer);
 }
 
+static void system_heap_dma_buf_release(struct dma_buf *dmabuf)
+{
+   struct system_heap_buffer *buffer = dmabuf->priv;
+
+   deferred_free(>deferred_free, system_heap_buf_free, 
buffer->len);
+}
+
 static const struct dma_buf_ops system_heap_buf_ops = {
.attach = system_heap_attach,
.detach = system_heap_detach,
-- 
2.25.1



[RFC][PATCH v6 2/7] drm: ttm_pool: Rename the ttm_pool_dma structure to ttm_pool_page_dat

2021-02-05 Thread John Stultz
This patch simply renames the ttm_pool_dma structure to
ttm_pool_page_dat, as we will extend it to store more then just
dma related info in it.

Cc: Daniel Vetter 
Cc: Christian Koenig 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
 drivers/gpu/drm/ttm/ttm_pool.c | 37 +-
 1 file changed, 18 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/ttm/ttm_pool.c b/drivers/gpu/drm/ttm/ttm_pool.c
index 11e0313db0ea..c0274e256be3 100644
--- a/drivers/gpu/drm/ttm/ttm_pool.c
+++ b/drivers/gpu/drm/ttm/ttm_pool.c
@@ -37,18 +37,17 @@
 #ifdef CONFIG_X86
 #include 
 #endif
-
 #include 
 #include 
 #include 
 
 /**
- * struct ttm_pool_dma - Helper object for coherent DMA mappings
+ * struct ttm_pool_page_dat - Helper object for coherent DMA mappings
  *
  * @addr: original DMA address returned for the mapping
  * @vaddr: original vaddr return for the mapping and order in the lower bits
  */
-struct ttm_pool_dma {
+struct ttm_pool_page_dat {
dma_addr_t addr;
unsigned long vaddr;
 };
@@ -75,7 +74,7 @@ static struct page *ttm_pool_alloc_page(struct ttm_pool 
*pool, gfp_t gfp_flags,
unsigned int order)
 {
unsigned long attr = DMA_ATTR_FORCE_CONTIGUOUS;
-   struct ttm_pool_dma *dma;
+   struct ttm_pool_page_dat *dat;
struct page *p;
void *vaddr;
 
@@ -94,15 +93,15 @@ static struct page *ttm_pool_alloc_page(struct ttm_pool 
*pool, gfp_t gfp_flags,
return p;
}
 
-   dma = kmalloc(sizeof(*dma), GFP_KERNEL);
-   if (!dma)
+   dat = kmalloc(sizeof(*dat), GFP_KERNEL);
+   if (!dat)
return NULL;
 
if (order)
attr |= DMA_ATTR_NO_WARN;
 
vaddr = dma_alloc_attrs(pool->dev, (1ULL << order) * PAGE_SIZE,
-   >addr, gfp_flags, attr);
+   >addr, gfp_flags, attr);
if (!vaddr)
goto error_free;
 
@@ -114,12 +113,12 @@ static struct page *ttm_pool_alloc_page(struct ttm_pool 
*pool, gfp_t gfp_flags,
else
p = virt_to_page(vaddr);
 
-   dma->vaddr = (unsigned long)vaddr | order;
-   p->private = (unsigned long)dma;
+   dat->vaddr = (unsigned long)vaddr | order;
+   p->private = (unsigned long)dat;
return p;
 
 error_free:
-   kfree(dma);
+   kfree(dat);
return NULL;
 }
 
@@ -128,7 +127,7 @@ static void ttm_pool_free_page(struct ttm_pool *pool, enum 
ttm_caching caching,
   unsigned int order, struct page *p)
 {
unsigned long attr = DMA_ATTR_FORCE_CONTIGUOUS;
-   struct ttm_pool_dma *dma;
+   struct ttm_pool_page_dat *dat;
void *vaddr;
 
 #ifdef CONFIG_X86
@@ -147,11 +146,11 @@ static void ttm_pool_free_page(struct ttm_pool *pool, 
enum ttm_caching caching,
if (order)
attr |= DMA_ATTR_NO_WARN;
 
-   dma = (void *)p->private;
-   vaddr = (void *)(dma->vaddr & PAGE_MASK);
-   dma_free_attrs(pool->dev, (1UL << order) * PAGE_SIZE, vaddr, dma->addr,
+   dat = (void *)p->private;
+   vaddr = (void *)(dat->vaddr & PAGE_MASK);
+   dma_free_attrs(pool->dev, (1UL << order) * PAGE_SIZE, vaddr, dat->addr,
   attr);
-   kfree(dma);
+   kfree(dat);
 }
 
 /* Apply a new caching to an array of pages */
@@ -184,9 +183,9 @@ static int ttm_pool_map(struct ttm_pool *pool, unsigned int 
order,
unsigned int i;
 
if (pool->use_dma_alloc) {
-   struct ttm_pool_dma *dma = (void *)p->private;
+   struct ttm_pool_page_dat *dat = (void *)p->private;
 
-   addr = dma->addr;
+   addr = dat->addr;
} else {
size_t size = (1ULL << order) * PAGE_SIZE;
 
@@ -324,9 +323,9 @@ static unsigned int ttm_pool_shrink(void)
 static unsigned int ttm_pool_page_order(struct ttm_pool *pool, struct page *p)
 {
if (pool->use_dma_alloc) {
-   struct ttm_pool_dma *dma = (void *)p->private;
+   struct ttm_pool_page_dat *dat = (void *)p->private;
 
-   return dma->vaddr & ~PAGE_MASK;
+   return dat->vaddr & ~PAGE_MASK;
}
 
return p->private;
-- 
2.25.1



Re: [RFC][PATCH 2/3] dma-buf: system_heap: Add pagepool support to system heap

2021-02-02 Thread John Stultz
On Tue, Feb 2, 2021 at 6:04 AM Daniel Vetter  wrote:
>
> On Fri, Jan 22, 2021 at 05:28:32PM -0800, John Stultz wrote:
> > On Mon, Dec 21, 2020 at 2:09 PM Daniel Vetter  wrote:
> > >
> > > On Fri, Dec 18, 2020 at 05:16:56PM -0800, John Stultz wrote:
> > > > On Fri, Dec 18, 2020 at 6:36 AM Daniel Vetter  wrote:
> > > > > On Thu, Dec 17, 2020 at 11:06:11PM +, John Stultz wrote:
> > > > > > Reuse/abuse the pagepool code from the network 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.
> > > > >
> > > > > We also have one of these in ttm. I think we should have at most one 
> > > > > of
> > > > > these for the gpu ecosystem overall, maybe as a helper that can be 
> > > > > plugged
> > > > > into all the places.
> > > > >
> > > > > Or I'm kinda missing something, which could be since I only glanced at
> > > > > yours for a bit. But it's also called page pool for buffer 
> > > > > allocations,
> > > > > and I don't think there's that many ways to implement that really :-)
> > > >
> > > > Yea, when I was looking around the ttm one didn't seem quite as
> > > > generic as the networking one, which more easily fit in here.
> > >
> > > Oops, I didn't look that closely and didn't realize you're reusing the one
> > > from net/core/.
> > >
> > > > The main benefit for the system heap is not so much the pool itself
> > > > (the normal page allocator is pretty good), as it being able to defer
> > > > the free and zero the pages in a background thread, so the pool is
> > > > effectively filled with pre-zeroed pages.
> > > >
> > > > But I'll take another look at the ttm implementation and see if it can
> > > > be re-used or the shared code refactored and pulled out somehow.
> > >
> > > I think moving the page_pool from net into lib and using it in ttm might
> > > also be an option. Lack of shrinker in the networking one might be a bit a
> > > problem.
> >
> > Yea. I've been looking at this, to see how to abstract out a generic
> > pool implementation, but each pool implementation has been tweaked for
> > the specific use cases, so a general abstraction is a bit tough right
> > off.
> >
> > For example the ttm pool's handling allocations both from alloc_pages
> > and dma_alloc in a pool, where the net page pool only uses alloc_pages
> > (but can pre map via dma_map_attr).
> >
> > And as you mentioned, the networking page pool is statically sized
> > where the ttm pool is dynamic and shrinker controlled.
> >
> > Further, as the ttm pool is utilized for keeping pools of pages set
> > for specific cache types, it makes it difficult to abstract that out
> > as we have to be able to reset the caching (set_pages_wb()) when
> > shrinking, so that would also have to be pushed down into the pool
> > attributes as well.
> >
> > So far, in my attempts to share an abstraction for both the net
> > page_pool and the ttm page pool, it seems to make the code complexity
> > worse on both sides -  so while I'm interested in continuing to try to
> > find a way to share code here, I'm not sure it makes sense to hold up
> > this series (which is already re-using an existing implementation and
> > provide a performance bump in microbenchmarks) for the
> > grand-unified-page-pool. Efforts to refactor the ttm pool and net page
> > pool can continue on indepently, and I'd be happy to move the system
> > heap to whatever that ends up being.
>
> The thing is, I'm not sure sharing code with net/core is a really good
> idea, at least it seems like we have some impendence mismatch with the ttm
> pool. And going forward I expect sooner or later we need alignment between
> the pools/caches under drm with dma-buf heap pools a lot more than between
> dma-buf and net/core.

I mean...  I don't think you're wrong here, but it was your suggestion.

> So this feels like a bit code sharing for code sharing's sake and not
> where it makes sense. Expecting net/core and gpu stacks to have the exact
> same needs for a page pool allocator has good chances to bite us in the
> long run.

Again, I agree with you at the high level here (dmabuf system heap and
ttm page pooling are conceptually more likely to align, and
duplication of buffer pools is non-optimal), but there's still the
practical aspect of the ttm pool being pretty tied to the ttm code
(utilizing ttm contexts, fixed MAX_ORDER*TTM_NUM_CACHING_TYPES
subpools per pool + 4 global sub-pools for only x86).

So... I guess I'll go for another pass at trying to pull something
generic out of the ttm_pool, but the cynic in me suspects folks will
just object to any inefficiencies added in order to do so (the
code-sharing for its own sake argument above) and I'll be back to
where I am now. But we'll see.

thanks
-john


Re: [PATCH v2 2/2] dma-buf: heaps: Map system heap pages as managed by linux vm

2021-02-02 Thread John Stultz
On Tue, Feb 2, 2021 at 4:31 PM Suren Baghdasaryan  wrote:
> Currently system heap maps its buffers with VM_PFNMAP flag using
> remap_pfn_range. This results in such buffers not being accounted
> for in PSS calculations because vm treats this memory as having no
> page structs. Without page structs there are no counters representing
> how many processes are mapping a page and therefore PSS calculation
> is impossible.
> Historically, ION driver used to map its buffers as VM_PFNMAP areas
> due to memory carveouts that did not have page structs [1]. That
> is not the case anymore and it seems there was desire to move away
> from remap_pfn_range [2].
> Dmabuf system heap design inherits this ION behavior and maps its
> pages using remap_pfn_range even though allocated pages are backed
> by page structs.
> Replace remap_pfn_range with vm_insert_page, following Laura's suggestion
> in [1]. This would allow correct PSS calculation for dmabufs.
>
> [1] 
> https://driverdev-devel.linuxdriverproject.narkive.com/v0fJGpaD/using-ion-memory-for-direct-io
> [2] 
> http://driverdev.linuxdriverproject.org/pipermail/driverdev-devel/2018-October/127519.html
> (sorry, could not find lore links for these discussions)
>
> Suggested-by: Laura Abbott 
> Signed-off-by: Suren Baghdasaryan 

For consistency, do we need something similar for the cma heap as well?

thanks
-john


[PATCH v4 3/3] dma-buf: system_heap: Add deferred freeing to the system heap

2021-02-01 Thread John Stultz
Utilize the deferred free helper library in the system heap.

This provides a nice performance bump and puts the
system heap performance on par with ION.

Cc: Daniel Vetter 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
v2:
* Rework deferred-free api to use reason enum as suggested by
  Suren Baghdasaryan
---
 drivers/dma-buf/heaps/Kconfig   |  1 +
 drivers/dma-buf/heaps/system_heap.c | 32 ++---
 2 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index 45c7d277448b..2276420ae905 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -6,6 +6,7 @@ config DMABUF_HEAPS_SYSTEM
depends on DMABUF_HEAPS
select NET
select PAGE_POOL
+   select DMABUF_HEAPS_DEFERRED_FREE
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 2addb6d832e0..fe122b5eff10 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -22,6 +22,8 @@
 #include 
 #include 
 
+#include "deferred-free-helper.h"
+
 static struct dma_heap *sys_heap;
 
 struct system_heap_buffer {
@@ -32,6 +34,7 @@ struct system_heap_buffer {
struct sg_table sg_table;
int vmap_cnt;
void *vaddr;
+   struct deferred_freelist_item deferred_free;
 };
 
 struct dma_heap_attachment {
@@ -301,30 +304,45 @@ static int system_heap_zero_buffer(struct 
system_heap_buffer *buffer)
return ret;
 }
 
-static void system_heap_dma_buf_release(struct dma_buf *dmabuf)
+static void system_heap_buf_free(struct deferred_freelist_item *item,
+enum df_reason reason)
 {
-   struct system_heap_buffer *buffer = dmabuf->priv;
+   struct system_heap_buffer *buffer;
struct sg_table *table;
struct scatterlist *sg;
int i, j;
 
+   buffer = container_of(item, struct system_heap_buffer, deferred_free);
/* Zero the buffer pages before adding back to the pool */
-   system_heap_zero_buffer(buffer);
+   if (reason == DF_NORMAL)
+   if (system_heap_zero_buffer(buffer))
+   reason = DF_UNDER_PRESSURE; // On failure, just free
 
table = >sg_table;
for_each_sg(table->sgl, sg, table->nents, i) {
struct page *page = sg_page(sg);
 
-   for (j = 0; j < NUM_ORDERS; j++) {
-   if (compound_order(page) == orders[j])
-   break;
+   if (reason == DF_UNDER_PRESSURE) {
+   __free_pages(page, compound_order(page));
+   } else {
+   for (j = 0; j < NUM_ORDERS; j++) {
+   if (compound_order(page) == orders[j])
+   break;
+   }
+   page_pool_put_full_page(pools[j], page, false);
}
-   page_pool_put_full_page(pools[j], page, false);
}
sg_free_table(table);
kfree(buffer);
 }
 
+static void system_heap_dma_buf_release(struct dma_buf *dmabuf)
+{
+   struct system_heap_buffer *buffer = dmabuf->priv;
+
+   deferred_free(>deferred_free, system_heap_buf_free, 
buffer->len);
+}
+
 static const struct dma_buf_ops system_heap_buf_ops = {
.attach = system_heap_attach,
.detach = system_heap_detach,
-- 
2.25.1



[PATCH v4 2/3] dma-buf: system_heap: Add pagepool support to system heap

2021-02-01 Thread John Stultz
Reuse/abuse the pagepool code from the network 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 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
v2:
* Fix build issue caused by selecting PAGE_POOL w/o NET
  as Reported-by: kernel test robot 
v3:
* Simplify the page zeroing logic a bit by using kmap_atomic
  instead of vmap as suggested by Daniel Mentz
---
 drivers/dma-buf/heaps/Kconfig   |  2 ++
 drivers/dma-buf/heaps/system_heap.c | 52 ++---
 2 files changed, 50 insertions(+), 4 deletions(-)

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index f7aef8bc7119..45c7d277448b 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -4,6 +4,8 @@ config DMABUF_HEAPS_DEFERRED_FREE
 config DMABUF_HEAPS_SYSTEM
bool "DMA-BUF System Heap"
depends on DMABUF_HEAPS
+   select NET
+   select 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..2addb6d832e0 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 
 static struct dma_heap *sys_heap;
 
@@ -53,6 +54,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 page_pool *pools[NUM_ORDERS];
 
 static struct sg_table *dup_sg_table(struct sg_table *table)
 {
@@ -281,18 +283,43 @@ static void system_heap_vunmap(struct dma_buf *dmabuf, 
struct dma_buf_map *map)
dma_buf_map_clear(map);
 }
 
+static int system_heap_zero_buffer(struct system_heap_buffer *buffer)
+{
+   struct sg_table *sgt = >sg_table;
+   struct sg_page_iter piter;
+   struct page *p;
+   void *vaddr;
+   int ret = 0;
+
+   for_each_sgtable_page(sgt, , 0) {
+   p = sg_page_iter_page();
+   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 = >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;
+   }
+   page_pool_put_full_page(pools[j], page, false);
}
sg_free_table(table);
kfree(buffer);
@@ -322,8 +349,7 @@ static struct page *alloc_largest_available(unsigned long 
size,
continue;
if (max_order < orders[i])
continue;
-
-   page = alloc_pages(order_flags[i], orders[i]);
+   page = page_pool_alloc_pages(pools[i], order_flags[i]);
if (!page)
continue;
return page;
@@ -428,6 +454,24 @@ 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++) {
+   struct page_pool_params pp;
+
+   memset(, 0, sizeof(pp));
+   pp.order = orders[i];
+   pools[i] = page_pool_create();
+
+   if (IS_ERR(pools[i])) {
+   int j;
+
+   pr_err("%s: page pool creation failed!\n", __func__);
+   for (j = 0; j < i; j++)
+   page_pool_destroy(pools[j]);
+   return PTR_ERR(pools[i]);
+   }
+   }
 
exp_info.name = "system";
exp_info.ops = _heap_ops;
-- 
2.25.1



[PATCH v4 1/3] dma-buf: heaps: Add deferred-free-helper library code

2021-02-01 Thread John Stultz
This patch provides infrastructure for deferring buffer frees.

This is a feature ION provided which when used with some form
of a page pool, provides a nice performance boost in an
allocation microbenchmark. The reason it helps is it allows the
page-zeroing to be done out of the normal allocation/free path,
and pushed off to a kthread.

As not all heaps will find this useful, its implemented as
a optional helper library that heaps can utilize.

Cc: Daniel Vetter 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
v2:
* Fix sleep in atomic issue from using a mutex, by switching
  to a spinlock as Reported-by: kernel test robot 
* Cleanup API to use a reason enum for clarity and add some documentation
  comments as suggested by Suren Baghdasaryan.

v3:
* Minor tweaks so it can be built as a module
* A few small fixups suggested by Daniel Mentz

v4:
* Tweak from Daniel Mentz to make sure the shrinker
  count/freed values are tracked in pages not bytes
---
 drivers/dma-buf/heaps/Kconfig|   3 +
 drivers/dma-buf/heaps/Makefile   |   1 +
 drivers/dma-buf/heaps/deferred-free-helper.c | 138 +++
 drivers/dma-buf/heaps/deferred-free-helper.h |  55 
 4 files changed, 197 insertions(+)
 create mode 100644 drivers/dma-buf/heaps/deferred-free-helper.c
 create mode 100644 drivers/dma-buf/heaps/deferred-free-helper.h

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index a5eef06c4226..f7aef8bc7119 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -1,3 +1,6 @@
+config DMABUF_HEAPS_DEFERRED_FREE
+   tristate
+
 config DMABUF_HEAPS_SYSTEM
bool "DMA-BUF System Heap"
depends on DMABUF_HEAPS
diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile
index 974467791032..4e7839875615 100644
--- a/drivers/dma-buf/heaps/Makefile
+++ b/drivers/dma-buf/heaps/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_DMABUF_HEAPS_DEFERRED_FREE) += deferred-free-helper.o
 obj-$(CONFIG_DMABUF_HEAPS_SYSTEM)  += system_heap.o
 obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o
diff --git a/drivers/dma-buf/heaps/deferred-free-helper.c 
b/drivers/dma-buf/heaps/deferred-free-helper.c
new file mode 100644
index ..0ba02de9dc1c
--- /dev/null
+++ b/drivers/dma-buf/heaps/deferred-free-helper.c
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Deferred dmabuf freeing helper
+ *
+ * Copyright (C) 2020 Linaro, Ltd.
+ *
+ * Based on the ION page pool code
+ * Copyright (C) 2011 Google, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "deferred-free-helper.h"
+
+static LIST_HEAD(free_list);
+static size_t list_size_pages;
+wait_queue_head_t freelist_waitqueue;
+struct task_struct *freelist_task;
+static DEFINE_SPINLOCK(free_list_lock);
+
+void deferred_free(struct deferred_freelist_item *item,
+  void (*free)(struct deferred_freelist_item*,
+   enum df_reason),
+  size_t size)
+{
+   unsigned long flags;
+
+   INIT_LIST_HEAD(>list);
+   item->size = size;
+   item->free = free;
+
+   spin_lock_irqsave(_list_lock, flags);
+   list_add(>list, _list);
+   list_size_pages += size >> PAGE_SHIFT;
+   spin_unlock_irqrestore(_list_lock, flags);
+   wake_up(_waitqueue);
+}
+EXPORT_SYMBOL_GPL(deferred_free);
+
+static size_t free_one_item(enum df_reason reason)
+{
+   unsigned long flags;
+   size_t size = 0;
+   struct deferred_freelist_item *item;
+
+   spin_lock_irqsave(_list_lock, flags);
+   if (list_empty(_list)) {
+   spin_unlock_irqrestore(_list_lock, flags);
+   return 0;
+   }
+   item = list_first_entry(_list, struct deferred_freelist_item, 
list);
+   list_del(>list);
+   size = item->size;
+   list_size_pages -= size >> PAGE_SHIFT;
+   spin_unlock_irqrestore(_list_lock, flags);
+
+   item->free(item, reason);
+   return size >> PAGE_SHIFT;
+}
+
+static unsigned long get_freelist_size_pages(void)
+{
+   unsigned long size;
+   unsigned long flags;
+
+   spin_lock_irqsave(_list_lock, flags);
+   size = list_size_pages;
+   spin_unlock_irqrestore(_list_lock, flags);
+   return size;
+}
+
+static unsigned long freelist_shrink_count(struct shrinker *shrinker,
+  struct shrink_control *sc)
+{
+   return get_freelist_size_pages();
+}
+
+static unsigned long freelist_shrink_scan(struct shrinker *shrinker,
+

[PATCH 3/5] kselftests: dmabuf-heaps: Softly fail if don't find a vgem device

2021-01-28 Thread John Stultz
While testing against a vgem device is helpful for testing importing
they aren't always configured in, so don't make it a fatal failure.

Cc: Shuah Khan 
Cc: Brian Starkey 
Cc: Sumit Semwal 
Cc: Laura Abbott 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Cc: linux-kselft...@vger.kernel.org
Signed-off-by: John Stultz 
---
 .../testing/selftests/dmabuf-heaps/dmabuf-heap.c  | 15 +++
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c 
b/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c
index 46f6759a8acc..8cedd539c7fb 100644
--- a/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c
+++ b/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c
@@ -184,15 +184,14 @@ static int test_alloc_and_import(char *heap_name)
if (importer_fd < 0) {
ret = importer_fd;
printf("Failed to open vgem\n");
-   goto out;
-   }
-
-   ret = import_vgem_fd(importer_fd, dmabuf_fd, );
-   if (ret < 0) {
-   printf("Failed to import buffer\n");
-   goto out;
+   } else {
+   ret = import_vgem_fd(importer_fd, dmabuf_fd, );
+   if (ret < 0) {
+   printf("Failed to import buffer\n");
+   goto out;
+   }
+   printf("import passed\n");
}
-   printf("import passed\n");
 
ret = dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_START);
if (ret < 0) {
-- 
2.25.1



[PATCH 4/5] kselftests: dmabuf-heaps: Cleanup test output

2021-01-28 Thread John Stultz
Cleanup the test output so it is a bit easier to read

Cc: Shuah Khan 
Cc: Brian Starkey 
Cc: Sumit Semwal 
Cc: Laura Abbott 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Cc: linux-kselft...@vger.kernel.org
Signed-off-by: John Stultz 
---
 .../selftests/dmabuf-heaps/dmabuf-heap.c  | 44 +--
 1 file changed, 21 insertions(+), 23 deletions(-)

diff --git a/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c 
b/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c
index 8cedd539c7fb..d179d81e2355 100644
--- a/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c
+++ b/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c
@@ -148,16 +148,14 @@ static int test_alloc_and_import(char *heap_name)
void *p = NULL;
int ret;
 
-   printf("Testing heap: %s\n", heap_name);
-
heap_fd = dmabuf_heap_open(heap_name);
if (heap_fd < 0)
return -1;
 
-   printf("Allocating 1 MEG\n");
+   printf("  Testing allocation and importing:  ");
ret = dmabuf_heap_alloc(heap_fd, ONE_MEG, 0, _fd);
if (ret) {
-   printf("Allocation Failed!\n");
+   printf("FAIL (Allocation Failed!)\n");
ret = -1;
goto out;
}
@@ -169,11 +167,10 @@ static int test_alloc_and_import(char *heap_name)
 dmabuf_fd,
 0);
if (p == MAP_FAILED) {
-   printf("mmap() failed: %m\n");
+   printf("FAIL (mmap() failed)\n");
ret = -1;
goto out;
}
-   printf("mmap passed\n");
 
dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_START);
memset(p, 1, ONE_MEG / 2);
@@ -183,33 +180,31 @@ static int test_alloc_and_import(char *heap_name)
importer_fd = open_vgem();
if (importer_fd < 0) {
ret = importer_fd;
-   printf("Failed to open vgem\n");
+   printf("(Could not open vgem - skipping):  ");
} else {
ret = import_vgem_fd(importer_fd, dmabuf_fd, );
if (ret < 0) {
-   printf("Failed to import buffer\n");
+   printf("FAIL (Failed to import buffer)\n");
goto out;
}
-   printf("import passed\n");
}
 
ret = dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_START);
if (ret < 0) {
-   printf("Sync start failed!\n");
+   printf("FAIL (DMA_BUF_SYNC_START failed!)\n");
goto out;
}
 
memset(p, 0xff, ONE_MEG);
ret = dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_END);
if (ret < 0) {
-   printf("Sync end failed!\n");
+   printf("FAIL (DMA_BUF_SYNC_END failed!)\n");
goto out;
}
-   printf("syncs passed\n");
 
close_handle(importer_fd, handle);
ret = 0;
-
+   printf(" OK\n");
 out:
if (p)
munmap(p, ONE_MEG);
@@ -297,23 +292,24 @@ static int test_alloc_compat(char *heap_name)
if (heap_fd < 0)
return -1;
 
-   printf("Testing (theoretical)older alloc compat\n");
+   printf("  Testing (theoretical)older alloc compat:  ");
ret = dmabuf_heap_alloc_older(heap_fd, ONE_MEG, 0, _fd);
if (ret) {
-   printf("Older compat allocation failed!\n");
+   printf("FAIL (Older compat allocation failed!)\n");
ret = -1;
goto out;
}
close(dmabuf_fd);
+   printf("OK\n");
 
-   printf("Testing (theoretical)newer alloc compat\n");
+   printf("  Testing (theoretical)newer alloc compat:  ");
ret = dmabuf_heap_alloc_newer(heap_fd, ONE_MEG, 0, _fd);
if (ret) {
-   printf("Newer compat allocation failed!\n");
+   printf("FAIL (Newer compat allocation failed!)\n");
ret = -1;
goto out;
}
-   printf("Ioctl compatibility tests passed\n");
+   printf("OK\n");
 out:
if (dmabuf_fd >= 0)
close(dmabuf_fd);
@@ -332,17 +328,17 @@ static int test_alloc_errors(char *heap_name)
if (heap_fd < 0)
return -1;
 
-   printf("Testing expected error cases\n");
+   printf("  Testing expected error cases:  ");
ret = dmabuf_heap_alloc(0, ONE_MEG, 0x11, _fd);
if (!ret) {
-   printf("Did not see expected error (invalid fd)!\n");
+   printf("FAIL (Did not see expected error

[PATCH 5/5] kselftests: dmabuf-heaps: Add extra checking that allocated buffers are zeroed

2021-01-28 Thread John Stultz
Add a check to validate that buffers allocated from the heaps
are properly zeroed before being given to userland.

It is done by allocating a number of buffers, and filling them
with a nonzero pattern, then closing and reallocating more
buffers and checking that they are all properly zeroed.

This is helpful to validate any cached buffers are zeroed
before being given back out.

Cc: Shuah Khan 
Cc: Brian Starkey 
Cc: Sumit Semwal 
Cc: Laura Abbott 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Cc: linux-kselft...@vger.kernel.org
Signed-off-by: John Stultz 
---
 .../selftests/dmabuf-heaps/dmabuf-heap.c  | 86 +++
 1 file changed, 86 insertions(+)

diff --git a/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c 
b/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c
index d179d81e2355..29af27acd40e 100644
--- a/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c
+++ b/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c
@@ -218,6 +218,84 @@ static int test_alloc_and_import(char *heap_name)
return ret;
 }
 
+static int test_alloc_zeroed(char *heap_name, size_t size)
+{
+   int heap_fd = -1, dmabuf_fd[32];
+   int i, j, ret;
+   void *p = NULL;
+   char *c;
+
+   printf("  Testing alloced %ldk buffers are zeroed:  ", size / 1024);
+   heap_fd = dmabuf_heap_open(heap_name);
+   if (heap_fd < 0)
+   return -1;
+
+   /* Allocate and fill a bunch of buffers */
+   for (i = 0; i < 32; i++) {
+   ret = dmabuf_heap_alloc(heap_fd, size, 0, _fd[i]);
+   if (ret < 0) {
+   printf("FAIL (Allocation (%i) failed)\n", i);
+   goto out;
+   }
+   /* mmap and fill with simple pattern */
+   p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, 
dmabuf_fd[i], 0);
+   if (p == MAP_FAILED) {
+   printf("FAIL (mmap() failed!)\n");
+   ret = -1;
+   goto out;
+   }
+   dmabuf_sync(dmabuf_fd[i], DMA_BUF_SYNC_START);
+   memset(p, 0xff, size);
+   dmabuf_sync(dmabuf_fd[i], DMA_BUF_SYNC_END);
+   munmap(p, size);
+   }
+   /* close them all */
+   for (i = 0; i < 32; i++)
+   close(dmabuf_fd[i]);
+
+   /* Allocate and validate all buffers are zeroed */
+   for (i = 0; i < 32; i++) {
+   ret = dmabuf_heap_alloc(heap_fd, size, 0, _fd[i]);
+   if (ret < 0) {
+   printf("FAIL (Allocation (%i) failed)\n", i);
+   goto out;
+   }
+
+   /* mmap and validate everything is zero */
+   p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, 
dmabuf_fd[i], 0);
+   if (p == MAP_FAILED) {
+   printf("FAIL (mmap() failed!)\n");
+   ret = -1;
+   goto out;
+   }
+   dmabuf_sync(dmabuf_fd[i], DMA_BUF_SYNC_START);
+   c = (char *)p;
+   for (j = 0; j < size; j++) {
+   if (c[j] != 0) {
+   printf("FAIL (Allocated buffer not zeroed @ 
%i)\n", j);
+   break;
+   }
+   }
+   dmabuf_sync(dmabuf_fd[i], DMA_BUF_SYNC_END);
+   munmap(p, size);
+   }
+   /* close them all */
+   for (i = 0; i < 32; i++)
+   close(dmabuf_fd[i]);
+
+   close(heap_fd);
+   printf("OK\n");
+   return 0;
+
+out:
+   while (i > 0) {
+   close(dmabuf_fd[i]);
+   i--;
+   }
+   close(heap_fd);
+   return ret;
+}
+
 /* Test the ioctl version compatibility w/ a smaller structure then expected */
 static int dmabuf_heap_alloc_older(int fd, size_t len, unsigned int flags,
   int *dmabuf_fd)
@@ -386,6 +464,14 @@ int main(void)
if (ret)
break;
 
+   ret = test_alloc_zeroed(dir->d_name, 4 * 1024);
+   if (ret)
+   break;
+
+   ret = test_alloc_zeroed(dir->d_name, ONE_MEG);
+   if (ret)
+   break;
+
ret = test_alloc_compat(dir->d_name);
if (ret)
break;
-- 
2.25.1



[PATCH 1/5] kselftests: dmabuf-heaps: Fix Makefile's inclusion of the kernel's usr/include dir

2021-01-28 Thread John Stultz
Copied in from somewhere else, the makefile was including
the kerne's usr/include dir, which caused the asm/ioctl.h file
to be used.

Unfortunately, that file has different values for _IOC_SIZEBITS
and _IOC_WRITE than include/uapi/asm-generic/ioctl.h which then
causes the _IOCW macros to give the wrong ioctl numbers,
specifically for DMA_BUF_IOCTL_SYNC.

This patch simply removes the extra include from the Makefile

Cc: Shuah Khan 
Cc: Brian Starkey 
Cc: Sumit Semwal 
Cc: Laura Abbott 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Cc: linux-kselft...@vger.kernel.org
Fixes: a8779927fd86c ("kselftests: Add dma-heap test")
Signed-off-by: John Stultz 
---
 tools/testing/selftests/dmabuf-heaps/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/testing/selftests/dmabuf-heaps/Makefile 
b/tools/testing/selftests/dmabuf-heaps/Makefile
index 607c2acd2082..604b43ece15f 100644
--- a/tools/testing/selftests/dmabuf-heaps/Makefile
+++ b/tools/testing/selftests/dmabuf-heaps/Makefile
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
-CFLAGS += -static -O3 -Wl,-no-as-needed -Wall -I../../../../usr/include
+CFLAGS += -static -O3 -Wl,-no-as-needed -Wall
 
 TEST_GEN_PROGS = dmabuf-heap
 
-- 
2.25.1



[PATCH 2/5] kselftests: dmabuf-heaps: Add clearer checks on DMABUF_BEGIN/END_SYNC

2021-01-28 Thread John Stultz
Add logic to check the dmabuf sync calls succeed.

Cc: Shuah Khan 
Cc: Brian Starkey 
Cc: Sumit Semwal 
Cc: Laura Abbott 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Cc: linux-kselft...@vger.kernel.org
Signed-off-by: John Stultz 
---
 .../selftests/dmabuf-heaps/dmabuf-heap.c  | 20 ---
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c 
b/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c
index 909da9cdda97..46f6759a8acc 100644
--- a/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c
+++ b/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c
@@ -130,16 +130,13 @@ static int dmabuf_heap_alloc(int fd, size_t len, unsigned 
int flags,
 dmabuf_fd);
 }
 
-static void dmabuf_sync(int fd, int start_stop)
+static int dmabuf_sync(int fd, int start_stop)
 {
struct dma_buf_sync sync = {
.flags = start_stop | DMA_BUF_SYNC_RW,
};
-   int ret;
 
-   ret = ioctl(fd, DMA_BUF_IOCTL_SYNC, );
-   if (ret)
-   printf("sync failed %d\n", errno);
+   return ioctl(fd, DMA_BUF_IOCTL_SYNC, );
 }
 
 #define ONE_MEG (1024 * 1024)
@@ -197,9 +194,18 @@ static int test_alloc_and_import(char *heap_name)
}
printf("import passed\n");
 
-   dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_START);
+   ret = dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_START);
+   if (ret < 0) {
+   printf("Sync start failed!\n");
+   goto out;
+   }
+
memset(p, 0xff, ONE_MEG);
-   dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_END);
+   ret = dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_END);
+   if (ret < 0) {
+   printf("Sync end failed!\n");
+   goto out;
+   }
printf("syncs passed\n");
 
close_handle(importer_fd, handle);
-- 
2.25.1



[PATCH v3 2/3] dma-buf: system_heap: Add pagepool support to system heap

2021-01-27 Thread John Stultz
Reuse/abuse the pagepool code from the network 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 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
v2:
* Fix build issue caused by selecting PAGE_POOL w/o NET
  as Reported-by: kernel test robot 
v3:
* Simplify the page zeroing logic a bit by using kmap_atomic
  instead of vmap as suggested by Daniel Mentz
---
 drivers/dma-buf/heaps/Kconfig   |  2 ++
 drivers/dma-buf/heaps/system_heap.c | 52 ++---
 2 files changed, 50 insertions(+), 4 deletions(-)

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index f7aef8bc7119..45c7d277448b 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -4,6 +4,8 @@ config DMABUF_HEAPS_DEFERRED_FREE
 config DMABUF_HEAPS_SYSTEM
bool "DMA-BUF System Heap"
depends on DMABUF_HEAPS
+   select NET
+   select 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..2addb6d832e0 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 
 static struct dma_heap *sys_heap;
 
@@ -53,6 +54,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 page_pool *pools[NUM_ORDERS];
 
 static struct sg_table *dup_sg_table(struct sg_table *table)
 {
@@ -281,18 +283,43 @@ static void system_heap_vunmap(struct dma_buf *dmabuf, 
struct dma_buf_map *map)
dma_buf_map_clear(map);
 }
 
+static int system_heap_zero_buffer(struct system_heap_buffer *buffer)
+{
+   struct sg_table *sgt = >sg_table;
+   struct sg_page_iter piter;
+   struct page *p;
+   void *vaddr;
+   int ret = 0;
+
+   for_each_sgtable_page(sgt, , 0) {
+   p = sg_page_iter_page();
+   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 = >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;
+   }
+   page_pool_put_full_page(pools[j], page, false);
}
sg_free_table(table);
kfree(buffer);
@@ -322,8 +349,7 @@ static struct page *alloc_largest_available(unsigned long 
size,
continue;
if (max_order < orders[i])
continue;
-
-   page = alloc_pages(order_flags[i], orders[i]);
+   page = page_pool_alloc_pages(pools[i], order_flags[i]);
if (!page)
continue;
return page;
@@ -428,6 +454,24 @@ 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++) {
+   struct page_pool_params pp;
+
+   memset(, 0, sizeof(pp));
+   pp.order = orders[i];
+   pools[i] = page_pool_create();
+
+   if (IS_ERR(pools[i])) {
+   int j;
+
+   pr_err("%s: page pool creation failed!\n", __func__);
+   for (j = 0; j < i; j++)
+   page_pool_destroy(pools[j]);
+   return PTR_ERR(pools[i]);
+   }
+   }
 
exp_info.name = "system";
exp_info.ops = _heap_ops;
-- 
2.25.1



[PATCH v3 1/3] dma-buf: heaps: Add deferred-free-helper library code

2021-01-27 Thread John Stultz
This patch provides infrastructure for deferring buffer frees.

This is a feature ION provided which when used with some form
of a page pool, provides a nice performance boost in an
allocation microbenchmark. The reason it helps is it allows the
page-zeroing to be done out of the normal allocation/free path,
and pushed off to a kthread.

As not all heaps will find this useful, its implemented as
a optional helper library that heaps can utilize.

Cc: Daniel Vetter 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
v2:
* Fix sleep in atomic issue from using a mutex, by switching
  to a spinlock as Reported-by: kernel test robot 
* Cleanup API to use a reason enum for clarity and add some documentation
  comments as suggested by Suren Baghdasaryan.

v3:
* Minor tweaks so it can be built as a module
* A few small fixups suggested by Daniel Mentz
---
 drivers/dma-buf/heaps/Kconfig|   3 +
 drivers/dma-buf/heaps/Makefile   |   1 +
 drivers/dma-buf/heaps/deferred-free-helper.c | 138 +++
 drivers/dma-buf/heaps/deferred-free-helper.h |  55 
 4 files changed, 197 insertions(+)
 create mode 100644 drivers/dma-buf/heaps/deferred-free-helper.c
 create mode 100644 drivers/dma-buf/heaps/deferred-free-helper.h

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index a5eef06c4226..f7aef8bc7119 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -1,3 +1,6 @@
+config DMABUF_HEAPS_DEFERRED_FREE
+   tristate
+
 config DMABUF_HEAPS_SYSTEM
bool "DMA-BUF System Heap"
depends on DMABUF_HEAPS
diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile
index 974467791032..4e7839875615 100644
--- a/drivers/dma-buf/heaps/Makefile
+++ b/drivers/dma-buf/heaps/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_DMABUF_HEAPS_DEFERRED_FREE) += deferred-free-helper.o
 obj-$(CONFIG_DMABUF_HEAPS_SYSTEM)  += system_heap.o
 obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o
diff --git a/drivers/dma-buf/heaps/deferred-free-helper.c 
b/drivers/dma-buf/heaps/deferred-free-helper.c
new file mode 100644
index ..941608319a94
--- /dev/null
+++ b/drivers/dma-buf/heaps/deferred-free-helper.c
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Deferred dmabuf freeing helper
+ *
+ * Copyright (C) 2020 Linaro, Ltd.
+ *
+ * Based on the ION page pool code
+ * Copyright (C) 2011 Google, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "deferred-free-helper.h"
+
+static LIST_HEAD(free_list);
+static size_t list_size;
+wait_queue_head_t freelist_waitqueue;
+struct task_struct *freelist_task;
+static DEFINE_SPINLOCK(free_list_lock);
+
+void deferred_free(struct deferred_freelist_item *item,
+  void (*free)(struct deferred_freelist_item*,
+   enum df_reason),
+  size_t size)
+{
+   unsigned long flags;
+
+   INIT_LIST_HEAD(>list);
+   item->size = size;
+   item->free = free;
+
+   spin_lock_irqsave(_list_lock, flags);
+   list_add(>list, _list);
+   list_size += size;
+   spin_unlock_irqrestore(_list_lock, flags);
+   wake_up(_waitqueue);
+}
+EXPORT_SYMBOL_GPL(deferred_free);
+
+static size_t free_one_item(enum df_reason reason)
+{
+   unsigned long flags;
+   size_t size = 0;
+   struct deferred_freelist_item *item;
+
+   spin_lock_irqsave(_list_lock, flags);
+   if (list_empty(_list)) {
+   spin_unlock_irqrestore(_list_lock, flags);
+   return 0;
+   }
+   item = list_first_entry(_list, struct deferred_freelist_item, 
list);
+   list_del(>list);
+   size = item->size;
+   list_size -= size;
+   spin_unlock_irqrestore(_list_lock, flags);
+
+   item->free(item, reason);
+   return size;
+}
+
+static unsigned long get_freelist_size(void)
+{
+   unsigned long size;
+   unsigned long flags;
+
+   spin_lock_irqsave(_list_lock, flags);
+   size = list_size;
+   spin_unlock_irqrestore(_list_lock, flags);
+   return size;
+}
+
+static unsigned long freelist_shrink_count(struct shrinker *shrinker,
+  struct shrink_control *sc)
+{
+   return get_freelist_size();
+}
+
+static unsigned long freelist_shrink_scan(struct shrinker *shrinker,
+ struct shrink_control *sc)
+{
+   unsigned long total_freed = 0;
+
+   if (sc->nr_to_scan == 0)
+   return 0;
+
+   while (total_freed < sc->nr_to_sc

[PATCH v3 3/3] dma-buf: system_heap: Add deferred freeing to the system heap

2021-01-27 Thread John Stultz
Utilize the deferred free helper library in the system heap.

This provides a nice performance bump and puts the
system heap performance on par with ION.

Cc: Daniel Vetter 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
v2:
* Rework deferred-free api to use reason enum as suggested by
  Suren Baghdasaryan
---
 drivers/dma-buf/heaps/Kconfig   |  1 +
 drivers/dma-buf/heaps/system_heap.c | 32 ++---
 2 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index 45c7d277448b..2276420ae905 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -6,6 +6,7 @@ config DMABUF_HEAPS_SYSTEM
depends on DMABUF_HEAPS
select NET
select PAGE_POOL
+   select DMABUF_HEAPS_DEFERRED_FREE
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 2addb6d832e0..fe122b5eff10 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -22,6 +22,8 @@
 #include 
 #include 
 
+#include "deferred-free-helper.h"
+
 static struct dma_heap *sys_heap;
 
 struct system_heap_buffer {
@@ -32,6 +34,7 @@ struct system_heap_buffer {
struct sg_table sg_table;
int vmap_cnt;
void *vaddr;
+   struct deferred_freelist_item deferred_free;
 };
 
 struct dma_heap_attachment {
@@ -301,30 +304,45 @@ static int system_heap_zero_buffer(struct 
system_heap_buffer *buffer)
return ret;
 }
 
-static void system_heap_dma_buf_release(struct dma_buf *dmabuf)
+static void system_heap_buf_free(struct deferred_freelist_item *item,
+enum df_reason reason)
 {
-   struct system_heap_buffer *buffer = dmabuf->priv;
+   struct system_heap_buffer *buffer;
struct sg_table *table;
struct scatterlist *sg;
int i, j;
 
+   buffer = container_of(item, struct system_heap_buffer, deferred_free);
/* Zero the buffer pages before adding back to the pool */
-   system_heap_zero_buffer(buffer);
+   if (reason == DF_NORMAL)
+   if (system_heap_zero_buffer(buffer))
+   reason = DF_UNDER_PRESSURE; // On failure, just free
 
table = >sg_table;
for_each_sg(table->sgl, sg, table->nents, i) {
struct page *page = sg_page(sg);
 
-   for (j = 0; j < NUM_ORDERS; j++) {
-   if (compound_order(page) == orders[j])
-   break;
+   if (reason == DF_UNDER_PRESSURE) {
+   __free_pages(page, compound_order(page));
+   } else {
+   for (j = 0; j < NUM_ORDERS; j++) {
+   if (compound_order(page) == orders[j])
+   break;
+   }
+   page_pool_put_full_page(pools[j], page, false);
}
-   page_pool_put_full_page(pools[j], page, false);
}
sg_free_table(table);
kfree(buffer);
 }
 
+static void system_heap_dma_buf_release(struct dma_buf *dmabuf)
+{
+   struct system_heap_buffer *buffer = dmabuf->priv;
+
+   deferred_free(>deferred_free, system_heap_buf_free, 
buffer->len);
+}
+
 static const struct dma_buf_ops system_heap_buf_ops = {
.attach = system_heap_attach,
.detach = system_heap_detach,
-- 
2.25.1



Re: [PATCH v2 2/3] dma-buf: system_heap: Add pagepool support to system heap

2021-01-27 Thread John Stultz
On Wed, Jan 27, 2021 at 12:21 PM Daniel Mentz  wrote:
>
> On Fri, Jan 22, 2021 at 7:47 PM John Stultz  wrote:
> > +static int system_heap_clear_pages(struct page **pages, int num, pgprot_t 
> > pgprot)
> > +{
> > +   void *addr = vmap(pages, num, VM_MAP, pgprot);
> > +
> > +   if (!addr)
> > +   return -ENOMEM;
> > +   memset(addr, 0, PAGE_SIZE * num);
> > +   vunmap(addr);
> > +   return 0;
> > +}
>
> I thought that vmap/vunmap are expensive, and I am wondering if
> there's a faster way that avoids vmap.
>
> How about lifting this code from lib/iov_iter.c
> static void memzero_page(struct page *page, size_t offset, size_t len)
> {
> char *addr = kmap_atomic(page);
> memset(addr + offset, 0, len);
> kunmap_atomic(addr);
> }
>
> Or what about lifting that code from the old ion_cma_heap.c
>
> if (PageHighMem(pages)) {
> unsigned long nr_clear_pages = nr_pages;
> struct page *page = pages;
>
> while (nr_clear_pages > 0) {
> void *vaddr = kmap_atomic(page);
>
> memset(vaddr, 0, PAGE_SIZE);
> kunmap_atomic(vaddr);
> page++;
> nr_clear_pages--;
> }
> } else {
> memset(page_address(pages), 0, size);
> }

Though, this last memset only works since CMA is contiguous, so it
probably needs to always do the kmap_atomic for each page, right?

I'm still a little worried if this is right, as the current
implementation with the vmap comes from the old ion_heap_sglist_zero
logic, which similarly tries to batch the vmaps  32 pages at at time,
but I'll give it a try.

thanks
-john


Re: [PATCH v4 4/4] dma-buf: heaps: add chunk heap to dmabuf heaps

2021-01-26 Thread John Stultz
On Thu, Jan 21, 2021 at 9:55 AM Minchan Kim  wrote:

Hey Minchan,
  Thanks for sending this out! I'm still working through testing with
this patch set, so I may have some more feedback tomorrow, but a few
quick items I did hit below.

> +
> +#define CHUNK_PREFIX "chunk-"
> +
> +static int register_chunk_heap(struct chunk_heap *chunk_heap_info)
> +{
> +   struct dma_heap_export_info exp_info;
> +   const char *name = cma_get_name(chunk_heap_info->cma);
> +   size_t len = strlen(CHUNK_PREFIX) + strlen(name) + 1;
> +   char *buf = kmalloc(len, GFP_KERNEL);
> +
> +   if (!buf)
> +   return -ENOMEM;
> +
> +   sprintf(buf, CHUNK_PREFIX"%s", cma_get_name(chunk_heap_info->cma));
> +   buf[len] = '\0';
> +
> +   exp_info.name = buf;
> +   exp_info.name = cma_get_name(chunk_heap_info->cma);

I think you intended to delete this line, as it's overwriting your
prefixed name.

> +   exp_info.ops = _heap_ops;
> +   exp_info.priv = chunk_heap_info;
> +
> +   chunk_heap_info->heap = dma_heap_add(_info);
> +   if (IS_ERR(chunk_heap_info->heap)) {
> +   kfree(buf);
> +   return PTR_ERR(chunk_heap_info->heap);
> +   }
> +
> +   return 0;
> +}
> +
> +static int __init chunk_heap_init(void)
> +{
> +   unsigned int i;
> +
> +   for (i = 0; i < chunk_heap_count; i++)
> +   register_chunk_heap(_heaps[i]);
> +
> +   return 0;
> +}
> +module_init(chunk_heap_init);
> +
> +#ifdef CONFIG_OF_EARLY_FLATTREE
> +
> +static int __init dmabuf_chunk_heap_area_init(struct reserved_mem *rmem)
> +{
> +   int ret;
> +   struct cma *cma;
> +   struct chunk_heap *chunk_heap_info;
> +   const __be32 *chunk_order;
> +
> +   phys_addr_t align = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order);
> +   phys_addr_t mask = align - 1;
> +
> +   if ((rmem->base & mask) || (rmem->size & mask)) {
> +   pr_err("Incorrect alignment for CMA region\n");
> +   return -EINVAL;

Passing this check can be tough if you're using dynamically assigned
rmem, so it might be helpful for debugging to print the base/size/mask
values?

thanks
-john


Re: [PATCH v4 3/4] dt-bindings: reserved-memory: Make DMA-BUF CMA heap DT-configurable

2021-01-26 Thread John Stultz
On Thu, Jan 21, 2021 at 9:55 AM Minchan Kim  wrote:
>  .../reserved-memory/dma_heap_chunk.yaml   | 56 +++
>  1 file changed, 56 insertions(+)
>  create mode 100644 
> Documentation/devicetree/bindings/reserved-memory/dma_heap_chunk.yaml
>
> diff --git 
> a/Documentation/devicetree/bindings/reserved-memory/dma_heap_chunk.yaml 
> b/Documentation/devicetree/bindings/reserved-memory/dma_heap_chunk.yaml
> new file mode 100644
> index ..00db0ae6af61
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/reserved-memory/dma_heap_chunk.yaml
> @@ -0,0 +1,56 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/reserved-memory/dma_heap_chunk.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Device tree binding for chunk heap on DMA HEAP FRAMEWORK
> +
> +description: |
> +  The DMA chunk heap is backed by the Contiguous Memory Allocator (CMA) and
> +  supports bulk allocation of fixed size pages.
> +
> +maintainers:
> +  - Hyesoo Yu 
> +  - John Stultz 
> +  - Minchan Kim 
> +  - Hridya Valsaraju
> +
> +
> +properties:
> +  compatible:
> +enum:
> +  - dma_heap,chunk
> +
> +  chunk-order:
> +description: |
> +order of pages that will get allocated from the chunk DMA heap.
> +maxItems: 1
> +
> +  size:
> +maxItems: 1
> +
> +  alignment:
> +maxItems: 1
> +
> +required:
> +  - compatible
> +  - size
> +  - alignment
> +  - chunk-order
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +reserved-memory {
> +#address-cells = <2>;
> +#size-cells = <1>;
> +
> +chunk_memory: chunk_memory {
> +compatible = "dma_heap,chunk";
> +size = <0x300>;

Hey Minchan,
  Looking closer here, would it make more sense to document the "reg =
<>" parameter here as well instead of just "size = <>"?

That way the address of the region could be explicitly specified (for
instance, to ensure the CMA region created is 32bit addressable). And
more practically, trying to satisfy the base address alignment checks
in the final patch when its set dynamically may require a fair amount
of luck  - I couldn't manage it in my own testing on the hikey960 w/o
resorting to reg=  :)

It does look like the RESERVEDMEM_OF_DECLARE() logic already supports
this, so it's likely just a matter of documenting it here?

thanks
-john


[PATCH v2 2/3] dma-buf: system_heap: Add pagepool support to system heap

2021-01-22 Thread John Stultz
Reuse/abuse the pagepool code from the network 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 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
v2:
* Fix build issue caused by selecting PAGE_POOL w/o NET
  as Reported-by: kernel test robot 
---
 drivers/dma-buf/heaps/Kconfig   |  2 +
 drivers/dma-buf/heaps/system_heap.c | 68 +++--
 2 files changed, 66 insertions(+), 4 deletions(-)

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index ecf65204f714..748e840e6edd 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -4,6 +4,8 @@ config DMABUF_HEAPS_DEFERRED_FREE
 config DMABUF_HEAPS_SYSTEM
bool "DMA-BUF System Heap"
depends on DMABUF_HEAPS
+   select NET
+   select 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..885e30894b77 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 
 static struct dma_heap *sys_heap;
 
@@ -53,6 +54,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 page_pool *pools[NUM_ORDERS];
 
 static struct sg_table *dup_sg_table(struct sg_table *table)
 {
@@ -281,18 +283,59 @@ static void system_heap_vunmap(struct dma_buf *dmabuf, 
struct dma_buf_map *map)
dma_buf_map_clear(map);
 }
 
+static int system_heap_clear_pages(struct page **pages, int num, pgprot_t 
pgprot)
+{
+   void *addr = vmap(pages, num, VM_MAP, pgprot);
+
+   if (!addr)
+   return -ENOMEM;
+   memset(addr, 0, PAGE_SIZE * num);
+   vunmap(addr);
+   return 0;
+}
+
+static int system_heap_zero_buffer(struct system_heap_buffer *buffer)
+{
+   struct sg_table *sgt = >sg_table;
+   struct sg_page_iter piter;
+   struct page *pages[32];
+   int p = 0;
+   int ret = 0;
+
+   for_each_sgtable_page(sgt, , 0) {
+   pages[p++] = sg_page_iter_page();
+   if (p == ARRAY_SIZE(pages)) {
+   ret = system_heap_clear_pages(pages, p, PAGE_KERNEL);
+   if (ret)
+   return ret;
+   p = 0;
+   }
+   }
+   if (p)
+   ret = system_heap_clear_pages(pages, p, PAGE_KERNEL);
+
+   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 = >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;
+   }
+   page_pool_put_full_page(pools[j], page, false);
}
sg_free_table(table);
kfree(buffer);
@@ -322,8 +365,7 @@ static struct page *alloc_largest_available(unsigned long 
size,
continue;
if (max_order < orders[i])
continue;
-
-   page = alloc_pages(order_flags[i], orders[i]);
+   page = page_pool_alloc_pages(pools[i], order_flags[i]);
if (!page)
continue;
return page;
@@ -428,6 +470,24 @@ 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++) {
+   struct page_pool_params pp;
+
+   memset(, 0, sizeof(pp));
+   pp.order = orders[i];
+   pools[i] = page_pool_create();
+
+   if (IS_ERR(pools[i])) {
+   int j;
+
+   pr_err("%s: page pool creation failed!\n", __func__);

[PATCH v2 3/3] dma-buf: system_heap: Add deferred freeing to the system heap

2021-01-22 Thread John Stultz
Utilize the deferred free helper library in the system heap.

This provides a nice performance bump and puts the
system heap performance on par with ION.

Cc: Daniel Vetter 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
v2:
* Rework deferred-free api to use reason enum as suggested by
  Suren Baghdasaryan
---
 drivers/dma-buf/heaps/Kconfig   |  1 +
 drivers/dma-buf/heaps/system_heap.c | 32 ++---
 2 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index 748e840e6edd..3f4d7b949301 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -6,6 +6,7 @@ config DMABUF_HEAPS_SYSTEM
depends on DMABUF_HEAPS
select NET
select PAGE_POOL
+   select DMABUF_HEAPS_DEFERRED_FREE
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 885e30894b77..747fa2250e84 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -22,6 +22,8 @@
 #include 
 #include 
 
+#include "deferred-free-helper.h"
+
 static struct dma_heap *sys_heap;
 
 struct system_heap_buffer {
@@ -32,6 +34,7 @@ struct system_heap_buffer {
struct sg_table sg_table;
int vmap_cnt;
void *vaddr;
+   struct deferred_freelist_item deferred_free;
 };
 
 struct dma_heap_attachment {
@@ -317,30 +320,45 @@ static int system_heap_zero_buffer(struct 
system_heap_buffer *buffer)
return ret;
 }
 
-static void system_heap_dma_buf_release(struct dma_buf *dmabuf)
+static void system_heap_buf_free(struct deferred_freelist_item *item,
+enum df_reason reason)
 {
-   struct system_heap_buffer *buffer = dmabuf->priv;
+   struct system_heap_buffer *buffer;
struct sg_table *table;
struct scatterlist *sg;
int i, j;
 
+   buffer = container_of(item, struct system_heap_buffer, deferred_free);
/* Zero the buffer pages before adding back to the pool */
-   system_heap_zero_buffer(buffer);
+   if (reason == DF_NORMAL)
+   if (system_heap_zero_buffer(buffer))
+   reason = DF_UNDER_PRESSURE; // On failure, just free
 
table = >sg_table;
for_each_sg(table->sgl, sg, table->nents, i) {
struct page *page = sg_page(sg);
 
-   for (j = 0; j < NUM_ORDERS; j++) {
-   if (compound_order(page) == orders[j])
-   break;
+   if (reason == DF_UNDER_PRESSURE) {
+   __free_pages(page, compound_order(page));
+   } else {
+   for (j = 0; j < NUM_ORDERS; j++) {
+   if (compound_order(page) == orders[j])
+   break;
+   }
+   page_pool_put_full_page(pools[j], page, false);
}
-   page_pool_put_full_page(pools[j], page, false);
}
sg_free_table(table);
kfree(buffer);
 }
 
+static void system_heap_dma_buf_release(struct dma_buf *dmabuf)
+{
+   struct system_heap_buffer *buffer = dmabuf->priv;
+
+   deferred_free(>deferred_free, system_heap_buf_free, 
buffer->len);
+}
+
 static const struct dma_buf_ops system_heap_buf_ops = {
.attach = system_heap_attach,
.detach = system_heap_detach,
-- 
2.17.1



[PATCH v2 1/3] dma-buf: heaps: Add deferred-free-helper library code

2021-01-22 Thread John Stultz
This patch provides infrastructure for deferring buffer frees.

This is a feature ION provided which when used with some form
of a page pool, provides a nice performance boost in an
allocation microbenchmark. The reason it helps is it allows the
page-zeroing to be done out of the normal allocation/free path,
and pushed off to a kthread.

As not all heaps will find this useful, its implemented as
a optional helper library that heaps can utilize.

Cc: Daniel Vetter 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
v2:
* Fix sleep in atomic issue from using a mutex, by switching
  to a spinlock as Reported-by: kernel test robot 
* Cleanup API to use a reason enum for clarity and add some documentation
  comments as suggested by Suren Baghdasaryan.
---
 drivers/dma-buf/heaps/Kconfig|   3 +
 drivers/dma-buf/heaps/Makefile   |   1 +
 drivers/dma-buf/heaps/deferred-free-helper.c | 136 +++
 drivers/dma-buf/heaps/deferred-free-helper.h |  55 
 4 files changed, 195 insertions(+)
 create mode 100644 drivers/dma-buf/heaps/deferred-free-helper.c
 create mode 100644 drivers/dma-buf/heaps/deferred-free-helper.h

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index a5eef06c4226..ecf65204f714 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -1,3 +1,6 @@
+config DMABUF_HEAPS_DEFERRED_FREE
+   bool
+
 config DMABUF_HEAPS_SYSTEM
bool "DMA-BUF System Heap"
depends on DMABUF_HEAPS
diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile
index 974467791032..4e7839875615 100644
--- a/drivers/dma-buf/heaps/Makefile
+++ b/drivers/dma-buf/heaps/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_DMABUF_HEAPS_DEFERRED_FREE) += deferred-free-helper.o
 obj-$(CONFIG_DMABUF_HEAPS_SYSTEM)  += system_heap.o
 obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o
diff --git a/drivers/dma-buf/heaps/deferred-free-helper.c 
b/drivers/dma-buf/heaps/deferred-free-helper.c
new file mode 100644
index ..cf04148167a2
--- /dev/null
+++ b/drivers/dma-buf/heaps/deferred-free-helper.c
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Deferred dmabuf freeing helper
+ *
+ * Copyright (C) 2020 Linaro, Ltd.
+ *
+ * Based on the ION page pool code
+ * Copyright (C) 2011 Google, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "deferred-free-helper.h"
+
+static LIST_HEAD(free_list);
+static size_t list_size;
+wait_queue_head_t freelist_waitqueue;
+struct task_struct *freelist_task;
+static DEFINE_SPINLOCK(free_list_lock);
+
+void deferred_free(struct deferred_freelist_item *item,
+  void (*free)(struct deferred_freelist_item*,
+   enum df_reason),
+  size_t size)
+{
+   unsigned long flags;
+
+   INIT_LIST_HEAD(>list);
+   item->size = size;
+   item->free = free;
+
+   spin_lock_irqsave(_list_lock, flags);
+   list_add(>list, _list);
+   list_size += size;
+   spin_unlock_irqrestore(_list_lock, flags);
+   wake_up(_waitqueue);
+}
+
+static size_t free_one_item(enum df_reason reason)
+{
+   unsigned long flags;
+   size_t size = 0;
+   struct deferred_freelist_item *item;
+
+   spin_lock_irqsave(_list_lock, flags);
+   if (list_empty(_list)) {
+   spin_unlock_irqrestore(_list_lock, flags);
+   return 0;
+   }
+   item = list_first_entry(_list, struct deferred_freelist_item, 
list);
+   list_del(>list);
+   size = item->size;
+   list_size -= size;
+   spin_unlock_irqrestore(_list_lock, flags);
+
+   item->free(item, reason);
+   return size;
+}
+
+static unsigned long get_freelist_size(void)
+{
+   unsigned long size;
+   unsigned long flags;
+
+   spin_lock_irqsave(_list_lock, flags);
+   size = list_size;
+   spin_unlock_irqrestore(_list_lock, flags);
+   return size;
+}
+
+static unsigned long freelist_shrink_count(struct shrinker *shrinker,
+  struct shrink_control *sc)
+{
+   return get_freelist_size();
+}
+
+static unsigned long freelist_shrink_scan(struct shrinker *shrinker,
+ struct shrink_control *sc)
+{
+   int total_freed = 0;
+
+   if (sc->nr_to_scan == 0)
+   return 0;
+
+   while (total_freed < sc->nr_to_scan) {
+   int freed = free_one_item(DF_UNDER_PRESSURE);
+
+   if (!freed)
+   break;
+
+   total_free

Re: [RFC][PATCH 2/3] dma-buf: system_heap: Add pagepool support to system heap

2021-01-22 Thread John Stultz
On Mon, Dec 21, 2020 at 2:09 PM Daniel Vetter  wrote:
>
> On Fri, Dec 18, 2020 at 05:16:56PM -0800, John Stultz wrote:
> > On Fri, Dec 18, 2020 at 6:36 AM Daniel Vetter  wrote:
> > > On Thu, Dec 17, 2020 at 11:06:11PM +, John Stultz wrote:
> > > > Reuse/abuse the pagepool code from the network 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.
> > >
> > > We also have one of these in ttm. I think we should have at most one of
> > > these for the gpu ecosystem overall, maybe as a helper that can be plugged
> > > into all the places.
> > >
> > > Or I'm kinda missing something, which could be since I only glanced at
> > > yours for a bit. But it's also called page pool for buffer allocations,
> > > and I don't think there's that many ways to implement that really :-)
> >
> > Yea, when I was looking around the ttm one didn't seem quite as
> > generic as the networking one, which more easily fit in here.
>
> Oops, I didn't look that closely and didn't realize you're reusing the one
> from net/core/.
>
> > The main benefit for the system heap is not so much the pool itself
> > (the normal page allocator is pretty good), as it being able to defer
> > the free and zero the pages in a background thread, so the pool is
> > effectively filled with pre-zeroed pages.
> >
> > But I'll take another look at the ttm implementation and see if it can
> > be re-used or the shared code refactored and pulled out somehow.
>
> I think moving the page_pool from net into lib and using it in ttm might
> also be an option. Lack of shrinker in the networking one might be a bit a
> problem.

Yea. I've been looking at this, to see how to abstract out a generic
pool implementation, but each pool implementation has been tweaked for
the specific use cases, so a general abstraction is a bit tough right
off.

For example the ttm pool's handling allocations both from alloc_pages
and dma_alloc in a pool, where the net page pool only uses alloc_pages
(but can pre map via dma_map_attr).

And as you mentioned, the networking page pool is statically sized
where the ttm pool is dynamic and shrinker controlled.

Further, as the ttm pool is utilized for keeping pools of pages set
for specific cache types, it makes it difficult to abstract that out
as we have to be able to reset the caching (set_pages_wb()) when
shrinking, so that would also have to be pushed down into the pool
attributes as well.

So far, in my attempts to share an abstraction for both the net
page_pool and the ttm page pool, it seems to make the code complexity
worse on both sides -  so while I'm interested in continuing to try to
find a way to share code here, I'm not sure it makes sense to hold up
this series (which is already re-using an existing implementation and
provide a performance bump in microbenchmarks) for the
grand-unified-page-pool. Efforts to refactor the ttm pool and net page
pool can continue on indepently, and I'd be happy to move the system
heap to whatever that ends up being.

thanks
-john


Re: [RESEND][PATCH 2/3] dma-buf: heaps: Add a WARN_ON should the vmap_cnt go negative

2021-01-22 Thread John Stultz
On Fri, Jan 22, 2021 at 2:21 PM Suren Baghdasaryan  wrote:
> On Thu, Jan 21, 2021 at 11:56 PM Sumit Semwal  wrote:
> > On Wed, 20 Jan 2021 at 02:15, John Stultz  wrote:
> > >
> > > We shouldn't vunmap more then we vmap, but if we do, make
> > > sure we complain loudly.
> >
> > I was checking the general usage of vunmap in the kernel, and I
> > couldn't find many instances where we need to WARN_ON for the vunmap
> > count more than vmap count. Is there a specific need for this in the heaps?
>
> Hi Sumit,
> My worry was that buffer->vmap_cnt could silently go negative. But if
> this warning is not consistent with other places we do refcounted
> vmap/vunmap then feel free to ignore my suggestion.
>

Yea,
 My sense is that it didn't seem like it would hurt, and if the
warning happened to be tripped, it would be good to catch.

However, if you are skeptical, feel free to drop that patch from this
series for now (it shouldn't impact the following patches).

thanks
-john


[PATCH 2/3] dma-buf: system_heap: Add a system-uncached heap re-using the system heap

2021-01-20 Thread John Stultz
This adds a heap that allocates non-contiguous buffers that are
marked as writecombined, so they are not cached by the CPU.

This is useful, as most graphics buffers are usually not touched
by the CPU or only written into once by the CPU. So when mapping
the buffer over and over between devices, we can skip the CPU
syncing, which saves a lot of cache management overhead, greatly
improving performance.

For folk using ION, there was a ION_FLAG_CACHED flag, which
signaled if the returned buffer should be CPU cacheable or not.
With DMA-BUF heaps, we do not yet have such a flag, and by default
the current heaps (system and cma) produce CPU cachable buffers.
So for folks transitioning from ION to DMA-BUF Heaps, this fills
in some of that missing functionality.

There has been a suggestion to make this functionality a flag
(DMAHEAP_FLAG_UNCACHED?) on the system heap, similar to how
ION used the ION_FLAG_CACHED. But I want to make sure an
_UNCACHED flag would truely be a generic attribute across all
heaps. So far that has been unclear, so having it as a separate
heap seemes better for now. (But I'm open to discussion on this
point!)

This is a rework of earlier efforts to add a uncached system heap,
done utilizing the exisitng system heap, adding just a bit of
logic to handle the uncached case.

Feedback would be very welcome!

Many thanks to Liam Mark for his help to get this working.

Pending opensource users of this code include:
* AOSP HiKey960 gralloc:
  - https://android-review.googlesource.com/c/device/linaro/hikey/+/1399519
  - Visibly improves performance over the system heap
* AOSP Codec2:
  - https://android-review.googlesource.com/c/platform/frameworks/av/+/1543685

Cc: Daniel Vetter 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Chris Goldsworthy 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: Bing Song 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
v4:
* Make sys_uncached_heap static, as
Reported-by: kernel test robot 
* Fix wrong return value, caught by smatch
Reported-by: kernel test robot 
Reported-by: Dan Carpenter 
* Ensure we call flush/invalidate_kernel_vmap_range() in the
  uncached cases to try to address feedback about VIVT caches
  from Christoph
* Reorder a few lines as suggested by BrianS
* Avoid holding the initial mapping for the lifetime of the buffer
  as suggested by BrianS
* Fix a unlikely race between allocate and updating the dma_mask
  that BrianS noticed.
---
 drivers/dma-buf/heaps/system_heap.c | 111 
 1 file changed, 95 insertions(+), 16 deletions(-)

diff --git a/drivers/dma-buf/heaps/system_heap.c 
b/drivers/dma-buf/heaps/system_heap.c
index 17e0e9a68baf..3548b20cb98c 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -22,6 +22,7 @@
 #include 
 
 static struct dma_heap *sys_heap;
+static struct dma_heap *sys_uncached_heap;
 
 struct system_heap_buffer {
struct dma_heap *heap;
@@ -31,6 +32,8 @@ struct system_heap_buffer {
struct sg_table sg_table;
int vmap_cnt;
void *vaddr;
+
+   bool uncached;
 };
 
 struct dma_heap_attachment {
@@ -38,6 +41,8 @@ struct dma_heap_attachment {
struct sg_table *table;
struct list_head list;
bool mapped;
+
+   bool uncached;
 };
 
 #define HIGH_ORDER_GFP  (((GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN \
@@ -100,7 +105,7 @@ static int system_heap_attach(struct dma_buf *dmabuf,
a->dev = attachment->dev;
INIT_LIST_HEAD(>list);
a->mapped = false;
-
+   a->uncached = buffer->uncached;
attachment->priv = a;
 
mutex_lock(>lock);
@@ -130,9 +135,13 @@ static struct sg_table *system_heap_map_dma_buf(struct 
dma_buf_attachment *attac
 {
struct dma_heap_attachment *a = attachment->priv;
struct sg_table *table = a->table;
+   int attr = 0;
int ret;
 
-   ret = dma_map_sgtable(attachment->dev, table, direction, 0);
+   if (a->uncached)
+   attr = DMA_ATTR_SKIP_CPU_SYNC;
+
+   ret = dma_map_sgtable(attachment->dev, table, direction, attr);
if (ret)
return ERR_PTR(ret);
 
@@ -145,9 +154,12 @@ static void system_heap_unmap_dma_buf(struct 
dma_buf_attachment *attachment,
  enum dma_data_direction direction)
 {
struct dma_heap_attachment *a = attachment->priv;
+   int attr = 0;
 
+   if (a->uncached)
+   attr = DMA_ATTR_SKIP_CPU_SYNC;
a->mapped = false;
-   dma_unmap_sgtable(attachment->dev, table, direction, 0);
+   dma_unmap_sgtable(attachment->dev, table, direction, attr);
 }
 
 static int system_heap_dma_buf_begin_cpu_access(st

[PATCH 3/3] dma-buf: cma_heap: Add a cma-uncached heap re-using the cma heap

2021-01-20 Thread John Stultz
From: Bing Song 

This adds a heap that allocates CMA buffers that are
marked as writecombined, so they are not cached by the CPU.

Cc: Daniel Vetter 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Chris Goldsworthy 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: Bing Song 
Signed-off-by: John Stultz 
---
 drivers/dma-buf/heaps/cma_heap.c | 119 +++
 1 file changed, 107 insertions(+), 12 deletions(-)

diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c
index 364fc2f3e499..1b8c6eb0a8ea 100644
--- a/drivers/dma-buf/heaps/cma_heap.c
+++ b/drivers/dma-buf/heaps/cma_heap.c
@@ -38,6 +38,7 @@ struct cma_heap_buffer {
pgoff_t pagecount;
int vmap_cnt;
void *vaddr;
+   bool uncached;
 };
 
 struct dma_heap_attachment {
@@ -45,6 +46,7 @@ struct dma_heap_attachment {
struct sg_table table;
struct list_head list;
bool mapped;
+   bool uncached;
 };
 
 static int cma_heap_attach(struct dma_buf *dmabuf,
@@ -70,6 +72,7 @@ static int cma_heap_attach(struct dma_buf *dmabuf,
a->dev = attachment->dev;
INIT_LIST_HEAD(>list);
a->mapped = false;
+   a->uncached = buffer->uncached;
 
attachment->priv = a;
 
@@ -99,8 +102,12 @@ static struct sg_table *cma_heap_map_dma_buf(struct 
dma_buf_attachment *attachme
 {
struct dma_heap_attachment *a = attachment->priv;
struct sg_table *table = >table;
+   int attr = 0;
int ret;
 
+   if (a->uncached)
+   attr = DMA_ATTR_SKIP_CPU_SYNC;
+
ret = dma_map_sgtable(attachment->dev, table, direction, 0);
if (ret)
return ERR_PTR(-ENOMEM);
@@ -113,7 +120,10 @@ static void cma_heap_unmap_dma_buf(struct 
dma_buf_attachment *attachment,
   enum dma_data_direction direction)
 {
struct dma_heap_attachment *a = attachment->priv;
+   int attr = 0;
 
+   if (a->uncached)
+   attr = DMA_ATTR_SKIP_CPU_SYNC;
a->mapped = false;
dma_unmap_sgtable(attachment->dev, table, direction, 0);
 }
@@ -128,10 +138,12 @@ static int cma_heap_dma_buf_begin_cpu_access(struct 
dma_buf *dmabuf,
invalidate_kernel_vmap_range(buffer->vaddr, buffer->len);
 
mutex_lock(>lock);
-   list_for_each_entry(a, >attachments, list) {
-   if (!a->mapped)
-   continue;
-   dma_sync_sgtable_for_cpu(a->dev, >table, direction);
+   if (!buffer->uncached) {
+   list_for_each_entry(a, >attachments, list) {
+   if (!a->mapped)
+   continue;
+   dma_sync_sgtable_for_cpu(a->dev, >table, direction);
+   }
}
mutex_unlock(>lock);
 
@@ -148,10 +160,12 @@ static int cma_heap_dma_buf_end_cpu_access(struct dma_buf 
*dmabuf,
flush_kernel_vmap_range(buffer->vaddr, buffer->len);
 
mutex_lock(>lock);
-   list_for_each_entry(a, >attachments, list) {
-   if (!a->mapped)
-   continue;
-   dma_sync_sgtable_for_device(a->dev, >table, direction);
+   if (!buffer->uncached) {
+   list_for_each_entry(a, >attachments, list) {
+   if (!a->mapped)
+   continue;
+   dma_sync_sgtable_for_device(a->dev, >table, 
direction);
+   }
}
mutex_unlock(>lock);
 
@@ -183,6 +197,9 @@ static int cma_heap_mmap(struct dma_buf *dmabuf, struct 
vm_area_struct *vma)
if ((vma->vm_flags & (VM_SHARED | VM_MAYSHARE)) == 0)
return -EINVAL;
 
+   if (buffer->uncached)
+   vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
vma->vm_ops = _heap_vm_ops;
vma->vm_private_data = buffer;
 
@@ -191,9 +208,13 @@ static int cma_heap_mmap(struct dma_buf *dmabuf, struct 
vm_area_struct *vma)
 
 static void *cma_heap_do_vmap(struct cma_heap_buffer *buffer)
 {
+   pgprot_t pgprot = PAGE_KERNEL;
void *vaddr;
 
-   vaddr = vmap(buffer->pages, buffer->pagecount, VM_MAP, PAGE_KERNEL);
+   if (buffer->uncached)
+   pgprot = pgprot_writecombine(PAGE_KERNEL);
+
+   vaddr = vmap(buffer->pages, buffer->pagecount, VM_MAP, pgprot);
if (!vaddr)
return ERR_PTR(-ENOMEM);
 
@@ -271,10 +292,11 @@ static const struct dma_buf_ops cma_heap_buf_ops = {
.release = cma_heap_dma_buf_release,
 };
 
-static int cma_heap_allocate(struct dma_heap *heap,
+stat

[PATCH 1/3] dma-buf: dma-heap: Keep track of the heap device struct

2021-01-20 Thread John Stultz
Keep track of the heap device struct.

This will be useful for special DMA allocations
and actions.

Cc: Daniel Vetter 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Chris Goldsworthy 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: Bing Song 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
 drivers/dma-buf/dma-heap.c | 33 +
 include/linux/dma-heap.h   |  9 +
 2 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
index afd22c9dbdcf..72c746755d89 100644
--- a/drivers/dma-buf/dma-heap.c
+++ b/drivers/dma-buf/dma-heap.c
@@ -30,6 +30,7 @@
  * @heap_devt  heap device node
  * @list   list head connecting to list of heaps
  * @heap_cdev  heap char device
+ * @heap_dev   heap device struct
  *
  * Represents a heap of memory from which buffers can be made.
  */
@@ -40,6 +41,7 @@ struct dma_heap {
dev_t heap_devt;
struct list_head list;
struct cdev heap_cdev;
+   struct device *heap_dev;
 };
 
 static LIST_HEAD(heap_list);
@@ -190,10 +192,21 @@ void *dma_heap_get_drvdata(struct dma_heap *heap)
return heap->priv;
 }
 
+/**
+ * dma_heap_get_dev() - get device struct for the heap
+ * @heap: DMA-Heap to retrieve device struct from
+ *
+ * Returns:
+ * The device struct for the heap.
+ */
+struct device *dma_heap_get_dev(struct dma_heap *heap)
+{
+   return heap->heap_dev;
+}
+
 struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info)
 {
struct dma_heap *heap, *h, *err_ret;
-   struct device *dev_ret;
unsigned int minor;
int ret;
 
@@ -247,16 +260,20 @@ struct dma_heap *dma_heap_add(const struct 
dma_heap_export_info *exp_info)
goto err1;
}
 
-   dev_ret = device_create(dma_heap_class,
-   NULL,
-   heap->heap_devt,
-   NULL,
-   heap->name);
-   if (IS_ERR(dev_ret)) {
+   heap->heap_dev = device_create(dma_heap_class,
+  NULL,
+  heap->heap_devt,
+  NULL,
+  heap->name);
+   if (IS_ERR(heap->heap_dev)) {
pr_err("dma_heap: Unable to create device\n");
-   err_ret = ERR_CAST(dev_ret);
+   err_ret = ERR_CAST(heap->heap_dev);
goto err2;
}
+
+   /* Make sure it doesn't disappear on us */
+   heap->heap_dev = get_device(heap->heap_dev);
+
/* Add heap to the list */
mutex_lock(_list_lock);
list_add(>list, _list);
diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h
index 454e354d1ffb..82857e096910 100644
--- a/include/linux/dma-heap.h
+++ b/include/linux/dma-heap.h
@@ -50,6 +50,15 @@ struct dma_heap_export_info {
  */
 void *dma_heap_get_drvdata(struct dma_heap *heap);
 
+/**
+ * dma_heap_get_dev() - get device struct for the heap
+ * @heap: DMA-Heap to retrieve device struct from
+ *
+ * Returns:
+ * The device struct for the heap.
+ */
+struct device *dma_heap_get_dev(struct dma_heap *heap);
+
 /**
  * dma_heap_add - adds a heap to dmabuf heaps
  * @exp_info:  information needed to register this heap
-- 
2.17.1



[RFC][PATCH 0/3] dmabuf heaps: system uncached and cma uncached heaps

2021-01-20 Thread John Stultz
After the last round submitting the system-uncached heap, I got
some feedback that Daniel would like to see it demonstrated with
a mesa based system. I'm still working on such a gralloc
implementation (using the db845c), but along with other work, so
I don't yet have something to share there. 

However, Bing Song reached out and was interested in having a
uncached variant for the CMA heap as well, and he shared this
patch providing an initial implementation.

This gave me some hesitation with regards to the earlier
discussion around what sort of attributes would be useful for
the flags field of the allocation IOCTL.

In earlier discussions, folks seemed happy to provide the
uncached system heap functionality as its own heap chardev, as
it seemed uncertain that the uncached attribute would truely be
generic across all heaps. 

But with Bing's patch, it seems like it may be generically useful,
and utilizing a flag might be a bit cleaner then adding lots of
duplicative heap names postfixed with "-uncached".

So I wanted to re-submit both of these together to reopen that
discussion on the question of if a BUF_FLAG_UNCACHED flag would
make sense, or if folks still think separate heap chardevs is
the way to go.

thanks
-john

Cc: Daniel Vetter 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Chris Goldsworthy 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: Bing Song 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org

Bing Song (1):
  dma-buf: cma_heap: Add a cma-uncached heap re-using the cma heap

John Stultz (2):
  dma-buf: dma-heap: Keep track of the heap device struct
  dma-buf: system_heap: Add a system-uncached heap re-using the system
heap

 drivers/dma-buf/dma-heap.c  |  33 ++--
 drivers/dma-buf/heaps/cma_heap.c| 119 +---
 drivers/dma-buf/heaps/system_heap.c | 111 ++
 include/linux/dma-heap.h|   9 +++
 4 files changed, 236 insertions(+), 36 deletions(-)

-- 
2.17.1



[RESEND][PATCH 2/3] dma-buf: heaps: Add a WARN_ON should the vmap_cnt go negative

2021-01-19 Thread John Stultz
We shouldn't vunmap more then we vmap, but if we do, make
sure we complain loudly.

Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Chris Goldsworthy 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Suggested-by: Suren Baghdasaryan 
Signed-off-by: John Stultz 
---
 drivers/dma-buf/heaps/cma_heap.c| 1 +
 drivers/dma-buf/heaps/system_heap.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c
index 364fc2f3e499..0c76cbc3fb11 100644
--- a/drivers/dma-buf/heaps/cma_heap.c
+++ b/drivers/dma-buf/heaps/cma_heap.c
@@ -232,6 +232,7 @@ static void cma_heap_vunmap(struct dma_buf *dmabuf, struct 
dma_buf_map *map)
struct cma_heap_buffer *buffer = dmabuf->priv;
 
mutex_lock(>lock);
+   WARN_ON(buffer->vmap_cnt == 0);
if (!--buffer->vmap_cnt) {
vunmap(buffer->vaddr);
buffer->vaddr = NULL;
diff --git a/drivers/dma-buf/heaps/system_heap.c 
b/drivers/dma-buf/heaps/system_heap.c
index 405351aad2a8..2321c91891f6 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -273,6 +273,7 @@ static void system_heap_vunmap(struct dma_buf *dmabuf, 
struct dma_buf_map *map)
struct system_heap_buffer *buffer = dmabuf->priv;
 
mutex_lock(>lock);
+   WARN_ON(buffer->vmap_cnt == 0);
if (!--buffer->vmap_cnt) {
vunmap(buffer->vaddr);
buffer->vaddr = NULL;
-- 
2.17.1



[RESEND][PATCH 1/3] dma-buf: system_heap: Make sure to return an error if we abort

2021-01-19 Thread John Stultz
If we abort from the allocation due to a fatal_signal_pending(),
be sure we report an error so any return code paths don't trip
over the fact that the allocation didn't succeed.

Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Chris Goldsworthy 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Suggested-by: Suren Baghdasaryan 
Signed-off-by: John Stultz 
---
 drivers/dma-buf/heaps/system_heap.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/dma-buf/heaps/system_heap.c 
b/drivers/dma-buf/heaps/system_heap.c
index 17e0e9a68baf..405351aad2a8 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -363,8 +363,10 @@ static int system_heap_allocate(struct dma_heap *heap,
 * Avoid trying to allocate memory if the process
 * has been killed by SIGKILL
 */
-   if (fatal_signal_pending(current))
+   if (fatal_signal_pending(current)) {
+   ret = -EINTR;
goto free_buffer;
+   }
 
page = alloc_largest_available(size_remaining, max_order);
if (!page)
-- 
2.17.1



[RESEND][PATCH 3/3] dma-buf: heaps: Rework heep allocation hooks to return struct dma_buf instead of fd

2021-01-19 Thread John Stultz
Every heap needs to create a dmabuf and then export it to a fd
via dma_buf_fd(), so to consolidate things a bit, have the heaps
just return a struct dmabuf * and let the top level
dma_heap_buffer_alloc() call handle creating the fd via
dma_buf_fd().

Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Chris Goldsworthy 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
 drivers/dma-buf/dma-heap.c  | 14 +-
 drivers/dma-buf/heaps/cma_heap.c| 22 +++---
 drivers/dma-buf/heaps/system_heap.c | 21 +++--
 include/linux/dma-heap.h| 12 ++--
 4 files changed, 33 insertions(+), 36 deletions(-)

diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
index afd22c9dbdcf..6b5db954569f 100644
--- a/drivers/dma-buf/dma-heap.c
+++ b/drivers/dma-buf/dma-heap.c
@@ -52,6 +52,9 @@ static int dma_heap_buffer_alloc(struct dma_heap *heap, 
size_t len,
 unsigned int fd_flags,
 unsigned int heap_flags)
 {
+   struct dma_buf *dmabuf;
+   int fd;
+
/*
 * Allocations from all heaps have to begin
 * and end on page boundaries.
@@ -60,7 +63,16 @@ static int dma_heap_buffer_alloc(struct dma_heap *heap, 
size_t len,
if (!len)
return -EINVAL;
 
-   return heap->ops->allocate(heap, len, fd_flags, heap_flags);
+   dmabuf = heap->ops->allocate(heap, len, fd_flags, heap_flags);
+   if (IS_ERR(dmabuf))
+   return PTR_ERR(dmabuf);
+
+   fd = dma_buf_fd(dmabuf, fd_flags);
+   if (fd < 0) {
+   dma_buf_put(dmabuf);
+   /* just return, as put will call release and that will free */
+   }
+   return fd;
 }
 
 static int dma_heap_open(struct inode *inode, struct file *file)
diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c
index 0c76cbc3fb11..985c41ffd85b 100644
--- a/drivers/dma-buf/heaps/cma_heap.c
+++ b/drivers/dma-buf/heaps/cma_heap.c
@@ -272,10 +272,10 @@ static const struct dma_buf_ops cma_heap_buf_ops = {
.release = cma_heap_dma_buf_release,
 };
 
-static int cma_heap_allocate(struct dma_heap *heap,
- unsigned long len,
- unsigned long fd_flags,
- unsigned long heap_flags)
+static struct dma_buf *cma_heap_allocate(struct dma_heap *heap,
+unsigned long len,
+unsigned long fd_flags,
+unsigned long heap_flags)
 {
struct cma_heap *cma_heap = dma_heap_get_drvdata(heap);
struct cma_heap_buffer *buffer;
@@ -290,7 +290,7 @@ static int cma_heap_allocate(struct dma_heap *heap,
 
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
if (!buffer)
-   return -ENOMEM;
+   return ERR_PTR(-ENOMEM);
 
INIT_LIST_HEAD(>attachments);
mutex_init(>lock);
@@ -349,15 +349,7 @@ static int cma_heap_allocate(struct dma_heap *heap,
ret = PTR_ERR(dmabuf);
goto free_pages;
}
-
-   ret = dma_buf_fd(dmabuf, fd_flags);
-   if (ret < 0) {
-   dma_buf_put(dmabuf);
-   /* just return, as put will call release and that will free */
-   return ret;
-   }
-
-   return ret;
+   return dmabuf;
 
 free_pages:
kfree(buffer->pages);
@@ -366,7 +358,7 @@ static int cma_heap_allocate(struct dma_heap *heap,
 free_buffer:
kfree(buffer);
 
-   return ret;
+   return ERR_PTR(ret);
 }
 
 static const struct dma_heap_ops cma_heap_ops = {
diff --git a/drivers/dma-buf/heaps/system_heap.c 
b/drivers/dma-buf/heaps/system_heap.c
index 2321c91891f6..7b154424aeb3 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -332,10 +332,10 @@ static struct page *alloc_largest_available(unsigned long 
size,
return NULL;
 }
 
-static int system_heap_allocate(struct dma_heap *heap,
-   unsigned long len,
-   unsigned long fd_flags,
-   unsigned long heap_flags)
+static struct dma_buf *system_heap_allocate(struct dma_heap *heap,
+   unsigned long len,
+   unsigned long fd_flags,
+   unsigned long heap_flags)
 {
struct system_heap_buffer *buffer;
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
@@ -350,7 +350,7 @@ static int system_heap_allocate(struct dma_heap *heap,
 
buffer = kzalloc(

Re: [PATCH v3 4/4] dma-buf: heaps: add chunk heap to dmabuf heaps

2021-01-19 Thread John Stultz
On Tue, Jan 12, 2021 at 5:22 PM Minchan Kim  wrote:
>
> From: Hyesoo Yu 
>
> This patch supports chunk heap that allocates the buffers that
> arranged into a list a fixed size chunks taken from CMA.
>
> The chunk heap driver is bound directly to a reserved_memory
> node by following Rob Herring's suggestion in [1].
>
> [1] 
> https://lore.kernel.org/lkml/20191025225009.50305-2-john.stu...@linaro.org/T/#m3dc63acd33fea269a584f43bb799a876f0b2b45d
>
> Signed-off-by: Hyesoo Yu 
> Signed-off-by: Hridya Valsaraju 
> Signed-off-by: Minchan Kim 
> ---
...
> +static int register_chunk_heap(struct chunk_heap *chunk_heap_info)
> +{
> +   struct dma_heap_export_info exp_info;
> +
> +   exp_info.name = cma_get_name(chunk_heap_info->cma);

One potential issue here, you're setting the name to the same as the
CMA name. Since the CMA heap uses the CMA name, if one chunk was
registered as a chunk heap but also was the default CMA area, it might
be registered twice. But since both would have the same name it would
be an initialization race as to which one "wins".

So maybe could you postfix the CMA name with "-chunk" or something?

thanks
-john


Re: [PATCH v3 1/2] usb: dwc3: Trigger a GCTL soft reset when switching modes in DRD

2021-01-08 Thread John Stultz
On Fri, Jan 8, 2021 at 4:26 AM Felipe Balbi  wrote:
>
>
> Hi,
>
> John Stultz  writes:
> > From: Yu Chen 
> >
> > Just resending this, as discussion died out a bit and I'm not
> > sure how to make further progress. See here for debug data that
> > was requested last time around:
> >   
> > https://lore.kernel.org/lkml/calaqxlxdnaufjkx0an9xwwtfwvjmwigppy2aqsnj56yvnbu...@mail.gmail.com/
> >
> > With the current dwc3 code on the HiKey960 we often see the
> > COREIDLE flag get stuck off in __dwc3_gadget_start(), which
> > seems to prevent the reset irq and causes the USB gadget to
> > fail to initialize.
> >
> > We had seen occasional initialization failures with older
> > kernels but with recent 5.x era kernels it seemed to be becoming
> > much more common, so I dug back through some older trees and
> > realized I dropped this quirk from Yu Chen during upstreaming
> > as I couldn't provide a proper rational for it and it didn't
> > seem to be necessary. I now realize I was wrong.
> >
> > After resubmitting the quirk, Thinh Nguyen pointed out that it
> > shouldn't be a quirk at all and it is actually mentioned in the
> > programming guide that it should be done when switching modes
> > in DRD.
> >
> > So, to avoid these !COREIDLE lockups seen on HiKey960, this
> > patch issues GCTL soft reset when switching modes if the
> > controller is in DRD mode.
> >
> > Cc: Felipe Balbi 
> > Cc: Tejas Joglekar 
> > Cc: Yang Fei 
> > Cc: YongQin Liu 
> > Cc: Andrzej Pietrasiewicz 
> > Cc: Thinh Nguyen 
> > Cc: Jun Li 
> > Cc: Mauro Carvalho Chehab 
> > Cc: Greg Kroah-Hartman 
> > Cc: linux-...@vger.kernel.org
> > Signed-off-by: Yu Chen 
> > Signed-off-by: John Stultz 
> > ---
> > v2:
> > * Rework to always call the GCTL soft reset in DRD mode,
> >   rather then using a quirk as suggested by Thinh Nguyen
> >
> > v3:
> > * Move GCTL soft reset under the spinlock as suggested by
> >   Thinh Nguyen
>
> Because this is such an invasive change, I would prefer that we get
> Tested-By tags from a good fraction of the users before applying these
> two changes.

I'm happy to reach out to folks to try to get that. Though I'm
wondering if it would be better to put it behind a dts quirk flag, as
originally proposed?
   https://lore.kernel.org/lkml/20201021181803.79650-1-john.stu...@linaro.org/

That way folks can enable it for devices as they need?

Again, I'm not trying to force this in as-is, just mostly sending it
out again for discussion to understand what other approach might work.

thanks
-john


[PATCH v3 2/2] usb: dwc3: Fix DRD mode change sequence following programming guide

2021-01-07 Thread John Stultz
In reviewing the previous patch, Thinh Nguyen pointed out that
the DRD mode change sequence should be like the following when
switching from host -> device according to the programming guide
(for all DRD IPs):
1. Reset controller with GCTL.CoreSoftReset
2. Set GCTL.PrtCapDir(device)
3. Soft reset with DCTL.CSftRst
4. Then follow up with the initializing registers sequence

The current code does:
a. Soft reset with DCTL.CSftRst on driver probe
b. Reset controller with GCTL.CoreSoftReset (added in previous
   patch)
c. Set GCTL.PrtCapDir(device)
d. < missing DCTL.CSftRst >
e. Then follow up with initializing registers sequence

So this patch adds the DCTL.CSftRst soft reset that was currently
missing from the dwc3 mode switching.

Cc: Felipe Balbi 
Cc: Tejas Joglekar 
Cc: Yang Fei 
Cc: YongQin Liu 
Cc: Andrzej Pietrasiewicz 
Cc: Thinh Nguyen 
Cc: Jun Li 
Cc: Mauro Carvalho Chehab 
Cc: Greg Kroah-Hartman 
Cc: linux-...@vger.kernel.org
Signed-off-by: John Stultz 
---
Feedback would be appreciated. I'm a little worried I should be
conditionalizing the DCTL.CSftRst on DRD mode controllers, but
I'm really not sure what the right thing to do is for non-DRD
mode controllers.
---
 drivers/usb/dwc3/core.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index b6a6b90eb2d5..71f8b07ecb99 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -40,6 +40,8 @@
 
 #define DWC3_DEFAULT_AUTOSUSPEND_DELAY 5000 /* ms */
 
+static int dwc3_core_soft_reset(struct dwc3 *dwc);
+
 /**
  * dwc3_get_dr_mode - Validates and sets dr_mode
  * @dwc: pointer to our context structure
@@ -177,6 +179,7 @@ static void __dwc3_set_mode(struct work_struct *work)
 
dwc3_set_prtcap(dwc, dwc->desired_dr_role);
 
+   dwc3_core_soft_reset(dwc);
spin_unlock_irqrestore(>lock, flags);
 
switch (dwc->desired_dr_role) {
-- 
2.17.1



[PATCH v3 1/2] usb: dwc3: Trigger a GCTL soft reset when switching modes in DRD

2021-01-07 Thread John Stultz
From: Yu Chen 

Just resending this, as discussion died out a bit and I'm not
sure how to make further progress. See here for debug data that
was requested last time around:
  
https://lore.kernel.org/lkml/calaqxlxdnaufjkx0an9xwwtfwvjmwigppy2aqsnj56yvnbu...@mail.gmail.com/

With the current dwc3 code on the HiKey960 we often see the
COREIDLE flag get stuck off in __dwc3_gadget_start(), which
seems to prevent the reset irq and causes the USB gadget to
fail to initialize.

We had seen occasional initialization failures with older
kernels but with recent 5.x era kernels it seemed to be becoming
much more common, so I dug back through some older trees and
realized I dropped this quirk from Yu Chen during upstreaming
as I couldn't provide a proper rational for it and it didn't
seem to be necessary. I now realize I was wrong.

After resubmitting the quirk, Thinh Nguyen pointed out that it
shouldn't be a quirk at all and it is actually mentioned in the
programming guide that it should be done when switching modes
in DRD.

So, to avoid these !COREIDLE lockups seen on HiKey960, this
patch issues GCTL soft reset when switching modes if the
controller is in DRD mode.

Cc: Felipe Balbi 
Cc: Tejas Joglekar 
Cc: Yang Fei 
Cc: YongQin Liu 
Cc: Andrzej Pietrasiewicz 
Cc: Thinh Nguyen 
Cc: Jun Li 
Cc: Mauro Carvalho Chehab 
Cc: Greg Kroah-Hartman 
Cc: linux-...@vger.kernel.org
Signed-off-by: Yu Chen 
Signed-off-by: John Stultz 
---
v2:
* Rework to always call the GCTL soft reset in DRD mode,
  rather then using a quirk as suggested by Thinh Nguyen

v3:
* Move GCTL soft reset under the spinlock as suggested by
  Thinh Nguyen
---
 drivers/usb/dwc3/core.c | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 841daec70b6e..b6a6b90eb2d5 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -114,10 +114,24 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode)
dwc->current_dr_role = mode;
 }
 
+static void dwc3_gctl_core_soft_reset(struct dwc3 *dwc)
+{
+   int reg;
+
+   reg = dwc3_readl(dwc->regs, DWC3_GCTL);
+   reg |= (DWC3_GCTL_CORESOFTRESET);
+   dwc3_writel(dwc->regs, DWC3_GCTL, reg);
+
+   reg = dwc3_readl(dwc->regs, DWC3_GCTL);
+   reg &= ~(DWC3_GCTL_CORESOFTRESET);
+   dwc3_writel(dwc->regs, DWC3_GCTL, reg);
+}
+
 static void __dwc3_set_mode(struct work_struct *work)
 {
struct dwc3 *dwc = work_to_dwc(work);
unsigned long flags;
+   int hw_mode;
int ret;
u32 reg;
 
@@ -156,6 +170,11 @@ static void __dwc3_set_mode(struct work_struct *work)
 
spin_lock_irqsave(>lock, flags);
 
+   /* Execute a GCTL Core Soft Reset when switch mode in DRD*/
+   hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
+   if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD)
+   dwc3_gctl_core_soft_reset(dwc);
+
dwc3_set_prtcap(dwc, dwc->desired_dr_role);
 
spin_unlock_irqrestore(>lock, flags);
-- 
2.17.1



[PATCH 3/3] dma-buf: heaps: Rework heep allocation hooks to return struct dma_buf instead of fd

2021-01-07 Thread John Stultz
Every heap needs to create a dmabuf and then export it to a fd
via dma_buf_fd(), so to consolidate things a bit, have the heaps
just return a struct dmabuf * and let the top level
dma_heap_buffer_alloc() call handle creating the fd via
dma_buf_fd().

Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Chris Goldsworthy 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
 drivers/dma-buf/dma-heap.c  | 14 +-
 drivers/dma-buf/heaps/cma_heap.c| 22 +++---
 drivers/dma-buf/heaps/system_heap.c | 21 +++--
 include/linux/dma-heap.h| 12 ++--
 4 files changed, 33 insertions(+), 36 deletions(-)

diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
index afd22c9dbdcf..6b5db954569f 100644
--- a/drivers/dma-buf/dma-heap.c
+++ b/drivers/dma-buf/dma-heap.c
@@ -52,6 +52,9 @@ static int dma_heap_buffer_alloc(struct dma_heap *heap, 
size_t len,
 unsigned int fd_flags,
 unsigned int heap_flags)
 {
+   struct dma_buf *dmabuf;
+   int fd;
+
/*
 * Allocations from all heaps have to begin
 * and end on page boundaries.
@@ -60,7 +63,16 @@ static int dma_heap_buffer_alloc(struct dma_heap *heap, 
size_t len,
if (!len)
return -EINVAL;
 
-   return heap->ops->allocate(heap, len, fd_flags, heap_flags);
+   dmabuf = heap->ops->allocate(heap, len, fd_flags, heap_flags);
+   if (IS_ERR(dmabuf))
+   return PTR_ERR(dmabuf);
+
+   fd = dma_buf_fd(dmabuf, fd_flags);
+   if (fd < 0) {
+   dma_buf_put(dmabuf);
+   /* just return, as put will call release and that will free */
+   }
+   return fd;
 }
 
 static int dma_heap_open(struct inode *inode, struct file *file)
diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c
index 0c76cbc3fb11..985c41ffd85b 100644
--- a/drivers/dma-buf/heaps/cma_heap.c
+++ b/drivers/dma-buf/heaps/cma_heap.c
@@ -272,10 +272,10 @@ static const struct dma_buf_ops cma_heap_buf_ops = {
.release = cma_heap_dma_buf_release,
 };
 
-static int cma_heap_allocate(struct dma_heap *heap,
- unsigned long len,
- unsigned long fd_flags,
- unsigned long heap_flags)
+static struct dma_buf *cma_heap_allocate(struct dma_heap *heap,
+unsigned long len,
+unsigned long fd_flags,
+unsigned long heap_flags)
 {
struct cma_heap *cma_heap = dma_heap_get_drvdata(heap);
struct cma_heap_buffer *buffer;
@@ -290,7 +290,7 @@ static int cma_heap_allocate(struct dma_heap *heap,
 
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
if (!buffer)
-   return -ENOMEM;
+   return ERR_PTR(-ENOMEM);
 
INIT_LIST_HEAD(>attachments);
mutex_init(>lock);
@@ -349,15 +349,7 @@ static int cma_heap_allocate(struct dma_heap *heap,
ret = PTR_ERR(dmabuf);
goto free_pages;
}
-
-   ret = dma_buf_fd(dmabuf, fd_flags);
-   if (ret < 0) {
-   dma_buf_put(dmabuf);
-   /* just return, as put will call release and that will free */
-   return ret;
-   }
-
-   return ret;
+   return dmabuf;
 
 free_pages:
kfree(buffer->pages);
@@ -366,7 +358,7 @@ static int cma_heap_allocate(struct dma_heap *heap,
 free_buffer:
kfree(buffer);
 
-   return ret;
+   return ERR_PTR(ret);
 }
 
 static const struct dma_heap_ops cma_heap_ops = {
diff --git a/drivers/dma-buf/heaps/system_heap.c 
b/drivers/dma-buf/heaps/system_heap.c
index 2321c91891f6..7b154424aeb3 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -332,10 +332,10 @@ static struct page *alloc_largest_available(unsigned long 
size,
return NULL;
 }
 
-static int system_heap_allocate(struct dma_heap *heap,
-   unsigned long len,
-   unsigned long fd_flags,
-   unsigned long heap_flags)
+static struct dma_buf *system_heap_allocate(struct dma_heap *heap,
+   unsigned long len,
+   unsigned long fd_flags,
+   unsigned long heap_flags)
 {
struct system_heap_buffer *buffer;
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
@@ -350,7 +350,7 @@ static int system_heap_allocate(struct dma_heap *heap,
 
buffer = kzalloc(

[PATCH 2/3] dma-buf: heaps: Add a WARN_ON should the vmap_cnt go negative

2021-01-07 Thread John Stultz
We shouldn't vunmap more then we vmap, but if we do, make
sure we complain loudly.

Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Chris Goldsworthy 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Suggested-by: Suren Baghdasaryan 
Signed-off-by: John Stultz 
---
 drivers/dma-buf/heaps/cma_heap.c| 1 +
 drivers/dma-buf/heaps/system_heap.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c
index 364fc2f3e499..0c76cbc3fb11 100644
--- a/drivers/dma-buf/heaps/cma_heap.c
+++ b/drivers/dma-buf/heaps/cma_heap.c
@@ -232,6 +232,7 @@ static void cma_heap_vunmap(struct dma_buf *dmabuf, struct 
dma_buf_map *map)
struct cma_heap_buffer *buffer = dmabuf->priv;
 
mutex_lock(>lock);
+   WARN_ON(buffer->vmap_cnt == 0);
if (!--buffer->vmap_cnt) {
vunmap(buffer->vaddr);
buffer->vaddr = NULL;
diff --git a/drivers/dma-buf/heaps/system_heap.c 
b/drivers/dma-buf/heaps/system_heap.c
index 405351aad2a8..2321c91891f6 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -273,6 +273,7 @@ static void system_heap_vunmap(struct dma_buf *dmabuf, 
struct dma_buf_map *map)
struct system_heap_buffer *buffer = dmabuf->priv;
 
mutex_lock(>lock);
+   WARN_ON(buffer->vmap_cnt == 0);
if (!--buffer->vmap_cnt) {
vunmap(buffer->vaddr);
buffer->vaddr = NULL;
-- 
2.17.1



[PATCH 1/3] dma-buf: system_heap: Make sure to return an error if we abort

2021-01-07 Thread John Stultz
If we abort from the allocation due to a fatal_signal_pending(),
be sure we report an error so any return code paths don't trip
over the fact that the allocation didn't succeed.

Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Chris Goldsworthy 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Suggested-by: Suren Baghdasaryan 
Signed-off-by: John Stultz 
---
 drivers/dma-buf/heaps/system_heap.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/dma-buf/heaps/system_heap.c 
b/drivers/dma-buf/heaps/system_heap.c
index 17e0e9a68baf..405351aad2a8 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -363,8 +363,10 @@ static int system_heap_allocate(struct dma_heap *heap,
 * Avoid trying to allocate memory if the process
 * has been killed by SIGKILL
 */
-   if (fatal_signal_pending(current))
+   if (fatal_signal_pending(current)) {
+   ret = -EINTR;
goto free_buffer;
+   }
 
page = alloc_largest_available(size_remaining, max_order);
if (!page)
-- 
2.17.1



[PATCH] dma-buf: cma_heap: Fix memory leak in CMA heap

2021-01-07 Thread John Stultz
Bing Song noticed the CMA heap was leaking memory due to a flub
I made in commit a5d2d29e24be ("dma-buf: heaps: Move heap-helper
logic into the cma_heap implementation"), and provided this fix
which ensures the pagelist is also freed on release.

Cc: Bing Song 
Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Chris Goldsworthy 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Reported-by: Bing Song 
Fixes: a5d2d29e24be ("dma-buf: heaps: Move heap-helper logic into the cma_heap 
implementation")
Signed-off-by: John Stultz 
---
 drivers/dma-buf/heaps/cma_heap.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c
index 3c4e34301172..364fc2f3e499 100644
--- a/drivers/dma-buf/heaps/cma_heap.c
+++ b/drivers/dma-buf/heaps/cma_heap.c
@@ -251,6 +251,9 @@ static void cma_heap_dma_buf_release(struct dma_buf *dmabuf)
buffer->vaddr = NULL;
}
 
+   /* free page list */
+   kfree(buffer->pages);
+   /* release memory */
cma_release(cma_heap->cma, buffer->cma_pages, buffer->pagecount);
kfree(buffer);
 }
-- 
2.17.1



Re: [PATCH v2 16/18] arm64: dts: hi3660: Harmonize DWC USB3 DT nodes name

2020-12-21 Thread John Stultz
On Sat, Dec 19, 2020 at 3:06 AM Krzysztof Kozlowski  wrote:
> On Fri, Dec 18, 2020 at 09:11:42PM -0800, John Stultz wrote:
> > On Wed, Nov 11, 2020 at 1:22 AM Serge Semin
> >  wrote:
> > >
> > > In accordance with the DWC USB3 bindings the corresponding node
> > > name is suppose to comply with the Generic USB HCD DT schema, which
> > > requires the USB nodes to have the name acceptable by the regexp:
> > > "^usb(@.*)?" . Make sure the "snps,dwc3"-compatible nodes are correctly
> > > named.
> > >
> > > Signed-off-by: Serge Semin 
> > > Acked-by: Krzysztof Kozlowski 
> > > ---
> > >  arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 2 +-
> > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > >
> > > diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi 
> > > b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> > > index d25aac5e0bf8..aea3800029b5 100644
> > > --- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> > > +++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> > > @@ -1166,7 +1166,7 @@ usb_phy: usb-phy {
> > > };
> > > };
> > >
> > > -   dwc3: dwc3@ff10 {
> > > +   dwc3: usb@ff10 {
> > > compatible = "snps,dwc3";
> > > reg = <0x0 0xff10 0x0 0x10>;
> >
> >
> > Oof. So this patch is breaking the usb gadget functionality on HiKey960 w/ 
> > AOSP.
> >
> > In order to choose the right controller for gadget mode with AOSP, one
> > sets the "sys.usb.controller" property, which until now for HiKey960
> > has been "ff10.dwc3".
> > After this patch, the controller isn't found and we would have to
> > change userland to use "ff10.usb", which would then break booting
> > on older kernels (testing various LTS releases on AOSP is one of the
> > key uses of the HiKey960).
> >
> > So while I understand the desire to unify the schema, as HiKey960
> > really isn't likely to be used outside of AOSP, I wonder if reverting
> > this one change is in the best interest of not breaking existing
> > userland?
>
> The node names are not part of an ABI, are they? I expect only
> compatibles and properties to be stable. If user-space looks for
> something by name, it's a user-space's mistake.  Not mentioning that you
> also look for specific address... Imagine remapping of addresses with
> ranges (for whatever reason) - AOSP also would be broken? Addresses are
> definitely not an ABI.

Though that is how it's exported through sysfs.

In AOSP it is then used to setup the configfs gadget by writing that
value into /config/usb_gadget/g1/UDC.

Given there may be multiple controllers on a device, or even if its
just one and the dummy hcd driver is enabled, I'm not sure how folks
reference the "right" one without the node name?

I understand the fuzziness with sysfs ABI, and I get that having
consistent naming is important, but like the eth0 -> enp3s0 changes,
it seems like this is going to break things.

Greg? Is there some better way AOSP should be doing this?

thanks
-john


Re: [PATCH v2 16/18] arm64: dts: hi3660: Harmonize DWC USB3 DT nodes name

2020-12-18 Thread John Stultz
On Wed, Nov 11, 2020 at 1:22 AM Serge Semin
 wrote:
>
> In accordance with the DWC USB3 bindings the corresponding node
> name is suppose to comply with the Generic USB HCD DT schema, which
> requires the USB nodes to have the name acceptable by the regexp:
> "^usb(@.*)?" . Make sure the "snps,dwc3"-compatible nodes are correctly
> named.
>
> Signed-off-by: Serge Semin 
> Acked-by: Krzysztof Kozlowski 
> ---
>  arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi 
> b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> index d25aac5e0bf8..aea3800029b5 100644
> --- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> +++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> @@ -1166,7 +1166,7 @@ usb_phy: usb-phy {
> };
> };
>
> -   dwc3: dwc3@ff10 {
> +   dwc3: usb@ff10 {
> compatible = "snps,dwc3";
> reg = <0x0 0xff10 0x0 0x10>;


Oof. So this patch is breaking the usb gadget functionality on HiKey960 w/ AOSP.

In order to choose the right controller for gadget mode with AOSP, one
sets the "sys.usb.controller" property, which until now for HiKey960
has been "ff10.dwc3".
After this patch, the controller isn't found and we would have to
change userland to use "ff10.usb", which would then break booting
on older kernels (testing various LTS releases on AOSP is one of the
key uses of the HiKey960).

So while I understand the desire to unify the schema, as HiKey960
really isn't likely to be used outside of AOSP, I wonder if reverting
this one change is in the best interest of not breaking existing
userland?

thanks
-john


Re: [RFC][PATCH 2/3] dma-buf: system_heap: Add pagepool support to system heap

2020-12-18 Thread John Stultz
On Fri, Dec 18, 2020 at 6:36 AM Daniel Vetter  wrote:
> On Thu, Dec 17, 2020 at 11:06:11PM +0000, John Stultz wrote:
> > Reuse/abuse the pagepool code from the network 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.
>
> We also have one of these in ttm. I think we should have at most one of
> these for the gpu ecosystem overall, maybe as a helper that can be plugged
> into all the places.
>
> Or I'm kinda missing something, which could be since I only glanced at
> yours for a bit. But it's also called page pool for buffer allocations,
> and I don't think there's that many ways to implement that really :-)

Yea, when I was looking around the ttm one didn't seem quite as
generic as the networking one, which more easily fit in here.

The main benefit for the system heap is not so much the pool itself
(the normal page allocator is pretty good), as it being able to defer
the free and zero the pages in a background thread, so the pool is
effectively filled with pre-zeroed pages.

But I'll take another look at the ttm implementation and see if it can
be re-used or the shared code refactored and pulled out somehow.

thanks
-john


[RFC][PATCH 3/3] dma-buf: system_heap: Add deferred freeing to the system heap

2020-12-17 Thread John Stultz
Utilize the deferred free helper library in the system heap.

This provides a nice performance bump and puts the
system heap performance on par with ION.

Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
 drivers/dma-buf/heaps/Kconfig   |  1 +
 drivers/dma-buf/heaps/system_heap.c | 30 ++---
 2 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index fa5e1c330cce..3c1cdecca9e2 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -5,6 +5,7 @@ config DMABUF_HEAPS_SYSTEM
bool "DMA-BUF System Heap"
depends on DMABUF_HEAPS
select PAGE_POOL
+   select DMABUF_HEAPS_DEFERRED_FREE
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 885e30894b77..905b304ea24b 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -22,6 +22,8 @@
 #include 
 #include 
 
+#include "deferred-free-helper.h"
+
 static struct dma_heap *sys_heap;
 
 struct system_heap_buffer {
@@ -32,6 +34,7 @@ struct system_heap_buffer {
struct sg_table sg_table;
int vmap_cnt;
void *vaddr;
+   struct deferred_freelist_item deferred_free;
 };
 
 struct dma_heap_attachment {
@@ -317,30 +320,43 @@ static int system_heap_zero_buffer(struct 
system_heap_buffer *buffer)
return ret;
 }
 
-static void system_heap_dma_buf_release(struct dma_buf *dmabuf)
+static void system_heap_buf_free(struct deferred_freelist_item *item, bool 
skip_pool)
 {
-   struct system_heap_buffer *buffer = dmabuf->priv;
+   struct system_heap_buffer *buffer = container_of(item, struct 
system_heap_buffer, deferred_free);
struct sg_table *table;
struct scatterlist *sg;
int i, j;
 
/* Zero the buffer pages before adding back to the pool */
-   system_heap_zero_buffer(buffer);
+   if (!skip_pool)
+   if (system_heap_zero_buffer(buffer))
+   skip_pool = true; // On zeroing failure, just free
 
table = >sg_table;
for_each_sg(table->sgl, sg, table->nents, i) {
struct page *page = sg_page(sg);
 
-   for (j = 0; j < NUM_ORDERS; j++) {
-   if (compound_order(page) == orders[j])
-   break;
+   if (skip_pool) {
+   __free_pages(page, compound_order(page));
+   } else {
+   for (j = 0; j < NUM_ORDERS; j++) {
+   if (compound_order(page) == orders[j])
+   break;
+   }
+   page_pool_put_full_page(pools[j], page, false);
}
-   page_pool_put_full_page(pools[j], page, false);
}
sg_free_table(table);
kfree(buffer);
 }
 
+static void system_heap_dma_buf_release(struct dma_buf *dmabuf)
+{
+   struct system_heap_buffer *buffer = dmabuf->priv;
+
+   deferred_free(>deferred_free, system_heap_buf_free, 
buffer->len);
+}
+
 static const struct dma_buf_ops system_heap_buf_ops = {
.attach = system_heap_attach,
.detach = system_heap_detach,
-- 
2.17.1



[RFC][PATCH 1/3] dma-buf: heaps: Add deferred-free-helper library code

2020-12-17 Thread John Stultz
This patch provides infrastructure for deferring buffer frees.

This is a feature ION provided which when used with some form
of a page pool, provides a nice performance boost in an
allocation microbenchmark. The reason it helps is it allows the
page-zeroing to be done out of the normal allocation/free path,
and pushed off to a kthread.

As not all heaps will find this useful, its implemented as
a optional helper library that heaps can utilize.

Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
 drivers/dma-buf/heaps/Kconfig|   3 +
 drivers/dma-buf/heaps/Makefile   |   1 +
 drivers/dma-buf/heaps/deferred-free-helper.c | 136 +++
 drivers/dma-buf/heaps/deferred-free-helper.h |  15 ++
 4 files changed, 155 insertions(+)
 create mode 100644 drivers/dma-buf/heaps/deferred-free-helper.c
 create mode 100644 drivers/dma-buf/heaps/deferred-free-helper.h

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index a5eef06c4226..ecf65204f714 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -1,3 +1,6 @@
+config DMABUF_HEAPS_DEFERRED_FREE
+   bool
+
 config DMABUF_HEAPS_SYSTEM
bool "DMA-BUF System Heap"
depends on DMABUF_HEAPS
diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile
index 974467791032..4e7839875615 100644
--- a/drivers/dma-buf/heaps/Makefile
+++ b/drivers/dma-buf/heaps/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_DMABUF_HEAPS_DEFERRED_FREE) += deferred-free-helper.o
 obj-$(CONFIG_DMABUF_HEAPS_SYSTEM)  += system_heap.o
 obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o
diff --git a/drivers/dma-buf/heaps/deferred-free-helper.c 
b/drivers/dma-buf/heaps/deferred-free-helper.c
new file mode 100644
index ..b8f54860454f
--- /dev/null
+++ b/drivers/dma-buf/heaps/deferred-free-helper.c
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Deferred dmabuf freeing helper
+ *
+ * Copyright (C) 2020 Linaro, Ltd.
+ *
+ * Based on the ION page pool code
+ * Copyright (C) 2011 Google, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "deferred-free-helper.h"
+
+static LIST_HEAD(free_list);
+static size_t list_size;
+wait_queue_head_t freelist_waitqueue;
+struct task_struct *freelist_task;
+static DEFINE_MUTEX(free_list_lock);
+
+enum {
+   USE_POOL = 0,
+   SKIP_POOL = 1,
+};
+
+void deferred_free(struct deferred_freelist_item *item,
+  void (*free)(struct deferred_freelist_item*, bool),
+  size_t size)
+{
+   INIT_LIST_HEAD(>list);
+   item->size = size;
+   item->free = free;
+
+   mutex_lock(_list_lock);
+   list_add(>list, _list);
+   list_size += size;
+   mutex_unlock(_list_lock);
+   wake_up(_waitqueue);
+}
+
+static size_t free_one_item(bool nopool)
+{
+   size_t size = 0;
+   struct deferred_freelist_item *item;
+
+   mutex_lock(_list_lock);
+   if (list_empty(_list)) {
+   mutex_unlock(_list_lock);
+   return 0;
+   }
+   item = list_first_entry(_list, struct deferred_freelist_item, 
list);
+   list_del(>list);
+   size = item->size;
+   list_size -= size;
+   mutex_unlock(_list_lock);
+
+   item->free(item, nopool);
+   return size;
+}
+
+static unsigned long get_freelist_size(void)
+{
+   unsigned long size;
+
+   mutex_lock(_list_lock);
+   size = list_size;
+   mutex_unlock(_list_lock);
+   return size;
+}
+
+static unsigned long freelist_shrink_count(struct shrinker *shrinker,
+  struct shrink_control *sc)
+{
+   return get_freelist_size();
+}
+
+static unsigned long freelist_shrink_scan(struct shrinker *shrinker,
+ struct shrink_control *sc)
+{
+   int total_freed = 0;
+
+   if (sc->nr_to_scan == 0)
+   return 0;
+
+   while (total_freed < sc->nr_to_scan) {
+   int freed = free_one_item(SKIP_POOL);
+
+   if (!freed)
+   break;
+
+   total_freed += freed;
+   }
+
+   return total_freed;
+}
+
+static struct shrinker freelist_shrinker = {
+   .count_objects = freelist_shrink_count,
+   .scan_objects = freelist_shrink_scan,
+   .seeks = DEFAULT_SEEKS,
+   .batch = 0,
+};
+
+static int deferred_free_thread(void *data)
+{
+   while (true) {
+   wait_event_freezable(freelist_waitqueue,
+get_freelist_size() > 0);
+
+   

[RFC][PATCH 2/3] dma-buf: system_heap: Add pagepool support to system heap

2020-12-17 Thread John Stultz
Reuse/abuse the pagepool code from the network 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: Sumit Semwal 
Cc: Liam Mark 
Cc: Chris Goldsworthy 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
 drivers/dma-buf/heaps/Kconfig   |  1 +
 drivers/dma-buf/heaps/system_heap.c | 68 +++--
 2 files changed, 65 insertions(+), 4 deletions(-)

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index ecf65204f714..fa5e1c330cce 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 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..885e30894b77 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 
 static struct dma_heap *sys_heap;
 
@@ -53,6 +54,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 page_pool *pools[NUM_ORDERS];
 
 static struct sg_table *dup_sg_table(struct sg_table *table)
 {
@@ -281,18 +283,59 @@ static void system_heap_vunmap(struct dma_buf *dmabuf, 
struct dma_buf_map *map)
dma_buf_map_clear(map);
 }
 
+static int system_heap_clear_pages(struct page **pages, int num, pgprot_t 
pgprot)
+{
+   void *addr = vmap(pages, num, VM_MAP, pgprot);
+
+   if (!addr)
+   return -ENOMEM;
+   memset(addr, 0, PAGE_SIZE * num);
+   vunmap(addr);
+   return 0;
+}
+
+static int system_heap_zero_buffer(struct system_heap_buffer *buffer)
+{
+   struct sg_table *sgt = >sg_table;
+   struct sg_page_iter piter;
+   struct page *pages[32];
+   int p = 0;
+   int ret = 0;
+
+   for_each_sgtable_page(sgt, , 0) {
+   pages[p++] = sg_page_iter_page();
+   if (p == ARRAY_SIZE(pages)) {
+   ret = system_heap_clear_pages(pages, p, PAGE_KERNEL);
+   if (ret)
+   return ret;
+   p = 0;
+   }
+   }
+   if (p)
+   ret = system_heap_clear_pages(pages, p, PAGE_KERNEL);
+
+   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 = >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;
+   }
+   page_pool_put_full_page(pools[j], page, false);
}
sg_free_table(table);
kfree(buffer);
@@ -322,8 +365,7 @@ static struct page *alloc_largest_available(unsigned long 
size,
continue;
if (max_order < orders[i])
continue;
-
-   page = alloc_pages(order_flags[i], orders[i]);
+   page = page_pool_alloc_pages(pools[i], order_flags[i]);
if (!page)
continue;
return page;
@@ -428,6 +470,24 @@ 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++) {
+   struct page_pool_params pp;
+
+   memset(, 0, sizeof(pp));
+   pp.order = orders[i];
+   pools[i] = page_pool_create();
+
+   if (IS_ERR(pools[i])) {
+   int j;
+
+   pr_err("%s: page pool creation failed!\n", __func__);
+   for (j = 0; j < i; j++)
+   page_pool_destroy(pools[j]);
+   return PTR_ERR(pools[i]);
+ 

Re: [PATCH] cma_heap: fix implicit function declaration

2020-12-17 Thread John Stultz
On Thu, Dec 17, 2020 at 4:31 AM  wrote:
>
> From: siyanteng 
>
> When building cma_heap the following error shows up:
>
> drivers/dma-buf/heaps/cma_heap.c:195:10: error: implicit declaration of 
> function 'vmap'; did you mean 'kmap'? [-Werror=implicit-function-declaration]
> 195 |  vaddr = vmap(buffer->pages, buffer->pagecount, VM_MAP, PAGE_KERNEL);
> |  ^~~~
> |  kmap
>
> Use this include: linux-next/include/linux/vmalloc.h
>
> Signed-off-by: siyanteng 

Thanks for submitting this! My apologies for the trouble!

We already have a similar patch queued here:
  
https://cgit.freedesktop.org/drm/drm-misc/commit/?h=drm-misc-next-fixes=8075c3005e4b1efa12dbbf6e84bc412a713de92c
so hopefully that will land upstream soon.

thanks again!
-john


[PATCH] dma-buf: cma_heap: Include linux/vmalloc.h to fix build failures on MIPS

2020-12-15 Thread John Stultz
We need to include  in order for MIPS to find
vmap(), as it doesn't otherwise get included there.

Without this patch, one can hit the following build error:
  drivers/dma-buf/heaps/cma_heap.c: In function 'cma_heap_do_vmap':
  drivers/dma-buf/heaps/cma_heap.c:195:10: error: implicit declaration of 
function 'vmap'

Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Chris Goldsworthy 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Fixes: a5d2d29e24be ("dma-buf: heaps: Move heap-helper logic into the cma_heap 
implementation")
Reported-by: Guenter Roeck 
Signed-off-by: John Stultz 
---
 drivers/dma-buf/heaps/cma_heap.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c
index 5e7c3436310c..3c4e34301172 100644
--- a/drivers/dma-buf/heaps/cma_heap.c
+++ b/drivers/dma-buf/heaps/cma_heap.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 
 
 struct cma_heap {
-- 
2.17.1



Re: [PATCH v7 2/5] dma-buf: heaps: Move heap-helper logic into the cma_heap implementation

2020-12-15 Thread John Stultz
On Tue, Dec 15, 2020 at 3:53 PM Guenter Roeck  wrote:
>
> On Sat, Nov 21, 2020 at 11:49:59PM +, John Stultz wrote:
> > Since the heap-helpers logic ended up not being as generic as
> > hoped, move the heap-helpers dma_buf_ops implementations into
> > the cma_heap directly.
> >
> > This will allow us to remove the heap_helpers code in a following
> > patch.
> >
>
> mips:allmodconfig:
>
> drivers/dma-buf/heaps/cma_heap.c: In function 'cma_heap_do_vmap':
> drivers/dma-buf/heaps/cma_heap.c:195:10: error: implicit declaration of 
> function 'vmap'
>

Ah. Looks like we need to explicitly include linux/vmalloc.h.

Thanks for the report! I'll spin up a patch, validate it and send it
out here shortly.

thanks
-john


[RFC][PATCH 1/3] dma-buf: system_heap: Make sure to return an error if we abort

2020-12-15 Thread John Stultz
If we abort from the allocation due to a fatal_signal_pending(),
be sure we report an error so any return code paths don't trip
over the fact that the allocation didn't succeed.

Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Chris Goldsworthy 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Suggested-by: Suren Baghdasaryan 
Signed-off-by: John Stultz 
---
 drivers/dma-buf/heaps/system_heap.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/dma-buf/heaps/system_heap.c 
b/drivers/dma-buf/heaps/system_heap.c
index 17e0e9a68baf..405351aad2a8 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -363,8 +363,10 @@ static int system_heap_allocate(struct dma_heap *heap,
 * Avoid trying to allocate memory if the process
 * has been killed by SIGKILL
 */
-   if (fatal_signal_pending(current))
+   if (fatal_signal_pending(current)) {
+   ret = -EINTR;
goto free_buffer;
+   }
 
page = alloc_largest_available(size_remaining, max_order);
if (!page)
-- 
2.17.1



[RFC][PATCH 3/3] dma-buf: heaps: Rework heep allocation hooks to return struct dma_buf instead of fd

2020-12-15 Thread John Stultz
Every heap needs to create a dmabuf and then export it to a fd
via dma_buf_fd(), so to consolidate things a bit, have the heaps
just return a struct dmabuf * and let the top level
dma_heap_buffer_alloc() call handle creating the fd via
dma_buf_fd().

Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Chris Goldsworthy 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: John Stultz 
---
 drivers/dma-buf/dma-heap.c  | 14 +-
 drivers/dma-buf/heaps/cma_heap.c| 22 +++---
 drivers/dma-buf/heaps/system_heap.c | 21 +++--
 include/linux/dma-heap.h| 12 ++--
 4 files changed, 33 insertions(+), 36 deletions(-)

diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
index afd22c9dbdcf..6b5db954569f 100644
--- a/drivers/dma-buf/dma-heap.c
+++ b/drivers/dma-buf/dma-heap.c
@@ -52,6 +52,9 @@ static int dma_heap_buffer_alloc(struct dma_heap *heap, 
size_t len,
 unsigned int fd_flags,
 unsigned int heap_flags)
 {
+   struct dma_buf *dmabuf;
+   int fd;
+
/*
 * Allocations from all heaps have to begin
 * and end on page boundaries.
@@ -60,7 +63,16 @@ static int dma_heap_buffer_alloc(struct dma_heap *heap, 
size_t len,
if (!len)
return -EINVAL;
 
-   return heap->ops->allocate(heap, len, fd_flags, heap_flags);
+   dmabuf = heap->ops->allocate(heap, len, fd_flags, heap_flags);
+   if (IS_ERR(dmabuf))
+   return PTR_ERR(dmabuf);
+
+   fd = dma_buf_fd(dmabuf, fd_flags);
+   if (fd < 0) {
+   dma_buf_put(dmabuf);
+   /* just return, as put will call release and that will free */
+   }
+   return fd;
 }
 
 static int dma_heap_open(struct inode *inode, struct file *file)
diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c
index 877353e8014f..0c7d6430605f 100644
--- a/drivers/dma-buf/heaps/cma_heap.c
+++ b/drivers/dma-buf/heaps/cma_heap.c
@@ -268,10 +268,10 @@ static const struct dma_buf_ops cma_heap_buf_ops = {
.release = cma_heap_dma_buf_release,
 };
 
-static int cma_heap_allocate(struct dma_heap *heap,
- unsigned long len,
- unsigned long fd_flags,
- unsigned long heap_flags)
+static struct dma_buf *cma_heap_allocate(struct dma_heap *heap,
+unsigned long len,
+unsigned long fd_flags,
+unsigned long heap_flags)
 {
struct cma_heap *cma_heap = dma_heap_get_drvdata(heap);
struct cma_heap_buffer *buffer;
@@ -286,7 +286,7 @@ static int cma_heap_allocate(struct dma_heap *heap,
 
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
if (!buffer)
-   return -ENOMEM;
+   return ERR_PTR(-ENOMEM);
 
INIT_LIST_HEAD(>attachments);
mutex_init(>lock);
@@ -345,15 +345,7 @@ static int cma_heap_allocate(struct dma_heap *heap,
ret = PTR_ERR(dmabuf);
goto free_pages;
}
-
-   ret = dma_buf_fd(dmabuf, fd_flags);
-   if (ret < 0) {
-   dma_buf_put(dmabuf);
-   /* just return, as put will call release and that will free */
-   return ret;
-   }
-
-   return ret;
+   return dmabuf;
 
 free_pages:
kfree(buffer->pages);
@@ -362,7 +354,7 @@ static int cma_heap_allocate(struct dma_heap *heap,
 free_buffer:
kfree(buffer);
 
-   return ret;
+   return ERR_PTR(ret);
 }
 
 static const struct dma_heap_ops cma_heap_ops = {
diff --git a/drivers/dma-buf/heaps/system_heap.c 
b/drivers/dma-buf/heaps/system_heap.c
index 2321c91891f6..7b154424aeb3 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -332,10 +332,10 @@ static struct page *alloc_largest_available(unsigned long 
size,
return NULL;
 }
 
-static int system_heap_allocate(struct dma_heap *heap,
-   unsigned long len,
-   unsigned long fd_flags,
-   unsigned long heap_flags)
+static struct dma_buf *system_heap_allocate(struct dma_heap *heap,
+   unsigned long len,
+   unsigned long fd_flags,
+   unsigned long heap_flags)
 {
struct system_heap_buffer *buffer;
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
@@ -350,7 +350,7 @@ static int system_heap_allocate(struct dma_heap *heap,
 
buffer = kzalloc(

[RFC][PATCH 2/3] dma-buf: heaps: Add a WARN_ON should the vmap_cnt go negative

2020-12-15 Thread John Stultz
We shouldn't vunmap more then we vmap, but if we do, make
sure we complain loudly.

Cc: Sumit Semwal 
Cc: Liam Mark 
Cc: Laura Abbott 
Cc: Brian Starkey 
Cc: Hridya Valsaraju 
Cc: Suren Baghdasaryan 
Cc: Sandeep Patil 
Cc: Daniel Mentz 
Cc: Chris Goldsworthy 
Cc: Ørjan Eide 
Cc: Robin Murphy 
Cc: Ezequiel Garcia 
Cc: Simon Ser 
Cc: James Jones 
Cc: linux-me...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Suggested-by: Suren Baghdasaryan 
Signed-off-by: John Stultz 
---
 drivers/dma-buf/heaps/cma_heap.c| 1 +
 drivers/dma-buf/heaps/system_heap.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c
index 5e7c3436310c..877353e8014f 100644
--- a/drivers/dma-buf/heaps/cma_heap.c
+++ b/drivers/dma-buf/heaps/cma_heap.c
@@ -231,6 +231,7 @@ static void cma_heap_vunmap(struct dma_buf *dmabuf, struct 
dma_buf_map *map)
struct cma_heap_buffer *buffer = dmabuf->priv;
 
mutex_lock(>lock);
+   WARN_ON(buffer->vmap_cnt == 0);
if (!--buffer->vmap_cnt) {
vunmap(buffer->vaddr);
buffer->vaddr = NULL;
diff --git a/drivers/dma-buf/heaps/system_heap.c 
b/drivers/dma-buf/heaps/system_heap.c
index 405351aad2a8..2321c91891f6 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -273,6 +273,7 @@ static void system_heap_vunmap(struct dma_buf *dmabuf, 
struct dma_buf_map *map)
struct system_heap_buffer *buffer = dmabuf->priv;
 
mutex_lock(>lock);
+   WARN_ON(buffer->vmap_cnt == 0);
if (!--buffer->vmap_cnt) {
vunmap(buffer->vaddr);
buffer->vaddr = NULL;
-- 
2.17.1



Re: [PATCH v2] usb: dwc3: Trigger a GCTL soft reset when switching modes in DRD

2020-12-11 Thread John Stultz
Hey Felipe,
  Sorry for taking so long to get back to this. :(

On Fri, Oct 23, 2020 at 12:02 AM Felipe Balbi  wrote:
> John Stultz  writes:
> > On Thu, Oct 22, 2020 at 12:55 AM Felipe Balbi  wrote:
> >> The only thing we need to do is verify
> >> which registers are shadowed between host and peripheral roles and cache
> >> only those registers.
> >
> > Sorry, could you explain this a bit more? Again, I don't have access
> > to the hardware docs, so I'm just working with the source and any
> > vendor patches I can find.
>
> Right, initialize it in gadget mode, then take a register dump (I think
> our regdump facility in dwc3's debugfs is enough). Then flip to host
> mode and take the same register dump. Now diff them. You'll see that
> some registers get overwritten. The reason for that is that physically
> some host and peripheral registers map to the same block of memory in
> the IP. In other words, the address decoder in the Register File decodes
> some addresses to the same physical block of memory. This was done, I
> believe, to save die area by reducing gate count.


Ok. So I've taken regdump in gadget mode, and then in host mode
against upstream, and then again with the patches.
Diffs below (along with all the captured regdump files attached).
Note, the problem when it occurs usually at bootup is that the device
doesn't properly enter gadget mode, so in this case things were
working (not exhibiting the failure) when I captured everything. If
you need a regdump when the problem occurs and the IP gets stuck w/
COREIDLE off, I can capture that too. Let me know

Again, I'm without any hw docs here, so I'm at a little bit of a loss
to understand how to use these diffs and your comment above about the
register file using the same memory to generate an alternative
solution to the patch I have (which is still working great in my
testing/usage).

Also, Thinh's recent feedback suggests it really is a programming flow
issue when switching modes, so I'm not sure how to move this forward.

Let me know what you suggest and I'm happy to take a stab at it.

thanks
-john


--- regdump.gadget  2020-12-12 01:08:56.643246612 +
+++ regdump.host2020-12-12 01:16:40.195105355 +
@@ -2,9 +2,9 @@
 GSBUSCFG1 = 0x0300
 GTXTHRCFG = 0x2408
 GRXTHRCFG = 0x0440
-GCTL = 0x00112004
+GCTL = 0x00111004
 GEVTEN = 0x
-GSTS = 0x7e80
+GSTS = 0x7e81
 GUCTL1 = 0x0104018a
 GSNPSID = 0x5533300a
 GGPIO = 0x
@@ -22,9 +22,9 @@
 GHWPARAMS5 = 0x04204108
 GHWPARAMS6 = 0x0feaec20
 GHWPARAMS7 = 0x04881e8d
-GDBGFIFOSPACE = 0x0042
-GDBGLTSSM = 0x41090440
-GDBGBMU = 0x2030
+GDBGFIFOSPACE = 0x0082
+GDBGLTSSM = 0x48c90442
+GDBGBMU = 0x2121
 GPRTBIMAP_HS0 = 0x
 GPRTBIMAP_HS1 = 0x
 GPRTBIMAP_FS0 = 0x
@@ -93,22 +93,22 @@
 GUSB3PIPECTL(13) = 0x
 GUSB3PIPECTL(14) = 0x
 GUSB3PIPECTL(15) = 0x
-GTXFIFOSIZ(0) = 0x0042
-GTXFIFOSIZ(1) = 0x00420286
-GTXFIFOSIZ(2) = 0x02c80286
-GTXFIFOSIZ(3) = 0x054e0286
-GTXFIFOSIZ(4) = 0x07d40286
-GTXFIFOSIZ(5) = 0x0a5a0286
-GTXFIFOSIZ(6) = 0x0ce00286
-GTXFIFOSIZ(7) = 0x0f660286
-GTXFIFOSIZ(8) = 0x11ec0286
-GTXFIFOSIZ(9) = 0x14720286
-GTXFIFOSIZ(10) = 0x16f80286
-GTXFIFOSIZ(11) = 0x197e0103
-GTXFIFOSIZ(12) = 0x1a810103
-GTXFIFOSIZ(13) = 0x1b840103
-GTXFIFOSIZ(14) = 0x1c870103
-GTXFIFOSIZ(15) = 0x1d8a0103
+GTXFIFOSIZ(0) = 0x0082
+GTXFIFOSIZ(1) = 0x00820184
+GTXFIFOSIZ(2) = 0x02060286
+GTXFIFOSIZ(3) = 0x048c
+GTXFIFOSIZ(4) = 0x048c
+GTXFIFOSIZ(5) = 0x048c
+GTXFIFOSIZ(6) = 0x048c
+GTXFIFOSIZ(7) = 0x048c
+GTXFIFOSIZ(8) = 0x048c
+GTXFIFOSIZ(9) = 0x048c
+GTXFIFOSIZ(10) = 0x048c
+GTXFIFOSIZ(11) = 0x048c
+GTXFIFOSIZ(12) = 0x048c
+GTXFIFOSIZ(13) = 0x048c
+GTXFIFOSIZ(14) = 0x048c
+GTXFIFOSIZ(15) = 0x048c
 GTXFIFOSIZ(16) = 0x
 GTXFIFOSIZ(17) = 0x
 GTXFIFOSIZ(18) = 0x
@@ -125,9 +125,9 @@
 GTXFIFOSIZ(29) = 0x
 GTXFIFOSIZ(30) = 0x
 GTXFIFOSIZ(31) = 0x
-GRXFIFOSIZ(0) = 0x0285
-GRXFIFOSIZ(1) = 0x0285
-GRXFIFOSIZ(2) = 0x0285
+GRXFIFOSIZ(0) = 0x0084
+GRXFIFOSIZ(1) = 0x00840184
+GRXFIFOSIZ(2) = 0x02080280
 GRXFIFOSIZ(3) = 0x
 GRXFIFOSIZ(4) = 0x
 GRXFIFOSIZ(5) = 0x
@@ -157,148 +157,148 @@
 GRXFIFOSIZ(29) = 0x
 GRXFIFOSIZ(30) = 0x
 GRXFIFOSIZ(31) = 0x
-GEVNTADRLO(0) = 0x41ae8000
+GEVNTADRLO(0) = 0x
 GEVNTADRHI(0) = 0x
-GEVNTSIZ(0) = 0x1000
+GEVNTSIZ(0) = 0x8000
 GEVNTCOUNT(0) = 0x
 GHWPARAMS8 = 0x0fea
 DCFG = 0x0052082c
-DCTL = 0x8cf00a00
-DEVTEN = 0x1217
-DSTS = 0x0002
+DCTL = 0x0cf0
+DEVTEN = 0x
+DSTS = 0x00cf36ec
 DGCMDPAR = 0x
 DGCMD = 0x
-DALEPENA = 0x000f
+DALEPENA = 0x
 DEPCMDPAR2(0) = 0x
-DEPCMDPAR1(0) = 0x42dac000
-DEPCMDPAR0(0) = 0x
-DEPCMD(0) = 0x0006
+DEPCM

Re: [PATCH] dmabuf: Add the capability to expose DMA-BUF stats in sysfs

2020-12-11 Thread John Stultz
On Thu, Dec 10, 2020 at 5:10 AM Daniel Vetter  wrote:
> On Thu, Dec 10, 2020 at 1:06 PM Greg KH  wrote:
> > On Thu, Dec 10, 2020 at 12:26:01PM +0100, Daniel Vetter wrote:
> > > On Thu, Dec 10, 2020 at 11:55 AM Greg KH  
> > > wrote:
> > > > On Thu, Dec 10, 2020 at 11:27:27AM +0100, Daniel Vetter wrote:
> > > > > This only shows shared memory, so it does smell a lot like 
> > > > > $specific_issue
> > > > > and we're designing a narrow solution for that and then have to carry 
> > > > > it
> > > > > forever.
> > > >
> > > > I think the "issue" is that this was a feature from ion that people
> > > > "missed" in the dmabuf move.  Taking away the ability to see what kind
> > > > of allocations were being made didn't make a lot of debugging tools
> > > > happy :(
> > >
> > > If this is just for dma-heaps then why don't we add the stuff back
> > > over there? It reinforces more that the android gpu stack and the
> > > non-android gpu stack on linux are fairly different in fundamental
> > > ways, but that's not really new.
> >
> > Back "over where"?
> >
> > dma-bufs are not only used for the graphics stack on android from what I
> > can tell, so this shouldn't be a gpu-specific issue.
>
> dma-buf heaps exist because android, mostly because google mandates
> it.

So, I don't think that's fair.

dma-buf heaps and ION before exist because it solves a problem they
have for allocating shared buffers for multiple complicated
multi-device pipelines where the various devices have constraints.
It's not strictly required[1], as your next point makes clear (along
with ChromeOS's Android not using it).

> There's not a whole lot (meaning zero) of actually open gpu stacks
> around that run on android and use dma-buf heaps like approved google
> systems, largely because the gralloc implementation in mesa just
> doesnt.

So yes, db845c currently uses the gbm_gralloc, which doesn't use
dmabuf heaps or ION.

That said, the resulting system still uses quite a number of dmabufs,
as Hridya's patch shows:
==> /sys/kernel/dmabuf/28435/exporter_name <==
drm
==> /sys/kernel/dmabuf/28435/dev_map_info <==
==> /sys/kernel/dmabuf/28435/size <==
16384
==> /sys/kernel/dmabuf/28161/exporter_name <==
drm
==> /sys/kernel/dmabuf/28161/dev_map_info <==
==> /sys/kernel/dmabuf/28161/size <==
524288
==> /sys/kernel/dmabuf/30924/exporter_name <==
drm
==> /sys/kernel/dmabuf/30924/dev_map_info <==
==> /sys/kernel/dmabuf/30924/size <==
8192
==> /sys/kernel/dmabuf/26880/exporter_name <==
drm
==> /sys/kernel/dmabuf/26880/dev_map_info <==
==> /sys/kernel/dmabuf/26880/size <==
262144
...

So even when devices are not using dma-buf heaps (which I get, you
have an axe to grind with :), having some way to collect useful stats
for dmabufs in use can be valuable.

(Also one might note, the db845c also doesn't have many constrained
devices, and we've not yet enabled hw codec support or camera
pipelines, so it avoids much of the complexity that ION/dma-buf heaps
was created to solve)

> So if android needs some quick debug output in sysfs, we can just add
> that in dma-buf heaps, for android only, problem solved. And much less
> annoying review to make sure it actually fits into the wider ecosystem
> because as-is (and I'm not seeing that chance anytime soon), dma-buf
> heaps is for android only. dma-buf at large isn't, so merging a debug
> output sysfs api that's just for android but misses a ton of the more
> generic features and semantics of dma-buf is not great.

The intent behind this patch is *not* to create more Android-specific
logic, but to provide useful information generically.  Indeed, Android
does use dmabufs heavily for passing buffers around, and your point
that not all systems handle graphics buffers that way is valid, and
it's important we don't bake any Android-isms into the interface. But
being able to collect data about the active dmabufs in a system is
useful, regardless of how regardless of how the dma-buf was allocated.

So I'd much rather see your feedback on how we expose other aspects of
dmabufs (dma_resv, exporter devices, attachment links) integrated,
rather then trying to ghettoize it as android-only and limit it to the
dmabuf heaps, where I don't think it makes as much sense to add.

thanks
-john

[1] Out of the box, the codec2 code added a few years back does
directly call to ION (and now dmabuf heaps) for system buffers, but it
can be configured differently as it's used in ChromeOS's Android too.


Re: [PATCH 4/4] dma-heap: Devicetree binding for chunk heap

2020-12-10 Thread John Stultz
On Thu, Dec 10, 2020 at 8:06 AM Minchan Kim  wrote:
> On Thu, Dec 10, 2020 at 12:15:15AM -0800, John Stultz wrote:
> > Well, while I agree that conceptually the dmabuf heaps allow for
> > allocations for multi-device pipelines, and thus are not tied to
> > specific devices. I do think that the memory types exposed are likely
> > to have specific devices/drivers in the pipeline that it matters most
> > to. So I don't see a big issue with the in-kernel driver registering a
> > specific CMA region as a dmabuf heap.
>
> Then, I am worry about that we spread out dma_heap_add_cma to too many
> drivers since kernel doesn't how userspace will use it.
> For example, system 1 could have device A-B-C pipeline so they added
> it A driver. After that, system 2 could have device B-C-D pipeline
> so they add dma_heap_add_cma into B device.

I'm not sure I see this as a major issue? If the drivers add it based
on the dt memory reference, those will be configured to not add
duplicate heaps (and even so the heap driver can also ensure we don't
try to add a heap twice).

> > Yea, an un-upstreamable dummy driver is maybe what it devolves to in
> > the worst case. But I suspect it would be cleaner for a display or ISP
> > driver that benefits most from the heap type to add the reserved
> > memory reference to their DT node, and on init for them to register
> > the region with the dmabuf heap code.
>
> As I mentioned above, it could be a display at this moment but it could
> be different driver next time. If I miss your point, let me know.
>

I guess I just don't see potentially having the registration calls
added to multiple drivers as a big problem.

Ideally, yes, I'd probably rather see a DT node that would allow the
heap driver to register specified regions, but that's been NACKed
multiple times. Given that, having hooks in device drivers to export
the region seems to me like the next best approach, as it avoids DT
ABI ( if ends up its a bad approach, its not something we have to
keep).

The bigger problem right now is not that there are too many places the
registration call would be made from, but that there aren't upstream
drivers which I'm aware of where it would currently make sense to add
specific dma_heap_add_cma() registration hooks to.  We need an
upstream user of Kunihiko Hayashi's patch.

thanks
-john


Re: [PATCH 4/4] dma-heap: Devicetree binding for chunk heap

2020-12-10 Thread John Stultz
On Wed, Dec 9, 2020 at 3:53 PM Minchan Kim  wrote:
> On Wed, Nov 18, 2020 at 07:19:07PM -0800, John Stultz wrote:
> > The CMA heap currently only registers the default CMA heap, as we
> > didn't want to expose all CMA regions and there's otherwise no way to
> > pick and choose.
>
> Yub.
>
> dma-buf really need a way to make exclusive CMA area. Otherwise, default
> CMA would be shared among drivers and introduce fragmentation easily
> since we couldn't control other drivers. In such aspect, I don't think
> current cma-heap works if userspace needs big memory chunk.

Yes, the default CMA region is not always optimal.

That's why I was hopeful for Kunihiko Hayashi's patch to allow for
exposing specific cma regions:
  
https://lore.kernel.org/lkml/1594948208-4739-1-git-send-email-hayashi.kunih...@socionext.com/

I think it would be a good solution, but all we need is *some* driver
which can be considered the primary user/owner of the cma region which
would then explicitly export it via the dmabuf heaps.

> Here, the problem is there is no in-kernel user to bind the specific
> CMA area because the owner will be random in userspace via dma-buf
> interface.

Well, while I agree that conceptually the dmabuf heaps allow for
allocations for multi-device pipelines, and thus are not tied to
specific devices. I do think that the memory types exposed are likely
to have specific devices/drivers in the pipeline that it matters most
to. So I don't see a big issue with the in-kernel driver registering a
specific CMA region as a dmabuf heap.

> > > Is there a reason to use dma-heap framework to add cma-area for specific 
> > > device ?
> > >
> > > Even if some in-tree users register dma-heap with cma-area, the buffers 
> > > could be allocated in user-land and these could be shared among other 
> > > devices.
> > > For exclusive access, I guess, the device don't need to register dma-heap 
> > > for cma area.
> > >
> >
> > It's not really about exclusive access. More just that if you want to
> > bind a memory reservation/region (cma or otherwise), at least for DTS,
> > it needs to bind with some device in DT.
> >
> > Then the device driver can register that region with a heap driver.
> > This avoids adding new Linux-specific software bindings to DT. It
> > becomes a driver implementation detail instead. The primary user of
> > the heap type would probably be a practical pick (ie the display or
> > isp driver).
>
> If it's the only solution, we could create some dummy driver which has
> only module_init and bind it from there but I don't think it's a good
> idea.

Yea, an un-upstreamable dummy driver is maybe what it devolves to in
the worst case. But I suspect it would be cleaner for a display or ISP
driver that benefits most from the heap type to add the reserved
memory reference to their DT node, and on init for them to register
the region with the dmabuf heap code.


> > The other potential solution Rob has suggested is that we create some
> > tag for the memory reservation (ie: like we do with cma: "reusable"),
> > which can be used to register the region to a heap. But this has the
> > problem that each tag has to be well defined and map to a known heap.
>
> Do you think that's the only solution to make progress for this feature?
> Then, could you elaborate it a bit more or any other ideas from dma-buf
> folks?

I'm skeptical of that DT tag approach working out, as we'd need a new
DT binding for the new tag name, and we'd have to do so for each new
heap type that needs this (so non-default cma, your chunk heap,
whatever other similar heap types that use reserved regions folks come
up with).  Having *some* driver take ownership for the reserved region
and register it with the appropriate heap type seems much
cleaner/flexible and avoids mucking with the DT ABI.

thanks
-john


Re: [PATCH v2 4/4] dma-buf: heaps: add chunk heap to dmabuf heaps

2020-12-01 Thread John Stultz
On Tue, Dec 1, 2020 at 4:13 PM Minchan Kim  wrote:
>
> On Tue, Dec 01, 2020 at 03:38:14PM -0800, John Stultz wrote:
> > On Tue, Dec 1, 2020 at 2:55 PM Minchan Kim  wrote:
> > > On Tue, Dec 01, 2020 at 11:48:15AM -0800, John Stultz wrote:
> > > > On Tue, Dec 1, 2020 at 9:51 AM Minchan Kim  wrote:
> > > >
> > > > Thanks for reworking and resending this!
> > > >
> > > > ...
> > > > > +static int __init chunk_heap_init(void)
> > > > > +{
> > > > > +   struct cma *default_cma = dev_get_cma_area(NULL);
> > > > > +   struct dma_heap_export_info exp_info;
> > > > > +   struct chunk_heap *chunk_heap;
> > > > > +
> > > > > +   if (!default_cma)
> > > > > +   return 0;
> > > > > +
> > > > > +   chunk_heap = kzalloc(sizeof(*chunk_heap), GFP_KERNEL);
> > > > > +   if (!chunk_heap)
> > > > > +   return -ENOMEM;
> > > > > +
> > > > > +   chunk_heap->order = CHUNK_HEAP_ORDER;
> > > > > +   chunk_heap->cma = default_cma;
> > > > > +
> > > > > +   exp_info.name = cma_get_name(default_cma);
> > > >
> > > > So, this would create a chunk heap name with the default CMA name,
> > > > which would be indistinguishable from the heap name used for the plain
> > > > CMA heap.
> > > >
> > > > Probably a good idea to prefix it with "chunk-" so the heap device
> > > > names are unique?
> > >
> > > That will give an impression to user that they are using different CMA
> > > area but that's not true. IMHO, let's be honest at this moment.
> >
> > I disagree.  The dmabuf heaps provide an abstraction for allocating a
> > type of memory, and while your heap is pulling from CMA, you aren't
> > "just" allocating CMA as the existing CMA heap would suffice for that.
> >
> > Since you need a slightly different method to allocate high order
> > pages in bulk, we really should have a unique way to name the
> > allocator interface. That's why I'd suggest the "chunk-" prefix to the
> > heap name.
>
> Got it. How about this?
>
> diff --git a/drivers/dma-buf/heaps/chunk_heap.c 
> b/drivers/dma-buf/heaps/chunk_heap.c
> index 0277707a93a9..36e189d0b73d 100644
> --- a/drivers/dma-buf/heaps/chunk_heap.c
> +++ b/drivers/dma-buf/heaps/chunk_heap.c
> @@ -410,7 +410,7 @@ static int __init chunk_heap_init(void)
> chunk_heap->order = CHUNK_HEAP_ORDER;
> chunk_heap->cma = default_cma;
>
> -   exp_info.name = cma_get_name(default_cma);
> +   exp_info.name = "cma-chunk-heap";

That's still a bit general for the default cma (which can be named
differently). I think including cma name is important, just adding the
chunk prefix might be best.

So something like
  sprintf(buf, "chunk-%s", cma_get_name(default_cma));
  exp_info.name = buf;

thanks
-john


  1   2   3   4   5   6   7   8   9   10   >