From: Colin Ian King <colin.king(a)canonical.com>
The -ENOTTY error return path does not free the allocated
kdata as it returns directly. Fix this by returning via the
error handling label err.
Addresses-Coverity: ("Resource leak")
Fixes: c02a81fba74f ("dma-buf: Add dma-buf heaps framework")
Signed-off-by: Colin Ian King <colin.king(a)canonical.com>
---
drivers/dma-buf/dma-heap.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
index 4f04d104ae61..80f2f5eac1e4 100644
--- a/drivers/dma-buf/dma-heap.c
+++ b/drivers/dma-buf/dma-heap.c
@@ -157,7 +157,8 @@ static long dma_heap_ioctl(struct file *file, unsigned int ucmd,
ret = dma_heap_ioctl_allocate(file, kdata);
break;
default:
- return -ENOTTY;
+ ret = -ENOTTY;
+ goto err;
}
if (copy_to_user((void __user *)arg, kdata, out_size) != 0)
--
2.24.0
I've spent a bit too much time reviewing all kinds of users all over
the kernel for this buffer sharing infrastructure. And some of it is
at least questionable.
Make sure we at least see when this stuff flies by.
Acked-by: Dave Airlie <airlied(a)gmail.com>
Signed-off-by: Daniel Vetter <daniel.vetter(a)intel.com>
Cc: Sumit Semwal <sumit.semwal(a)linaro.org>
Cc: Mauro Carvalho Chehab <mchehab+samsung(a)kernel.org>
Cc: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Cc: Rob Herring <robh(a)kernel.org>
Cc: linux-media(a)vger.kernel.org
Cc: linaro-mm-sig(a)lists.linaro.org
---
MAINTAINERS | 1 +
1 file changed, 1 insertion(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 375dbea8bc88..c1e3da2c1947 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4941,6 +4941,7 @@ F: include/linux/dma-buf*
F: include/linux/reservation.h
F: include/linux/*fence.h
F: Documentation/driver-api/dma-buf.rst
+K: dma_(buf|fence|resv)
T: git git://anongit.freedesktop.org/drm/drm-misc
DMA GENERIC OFFLOAD ENGINE SUBSYSTEM
--
2.24.0
All implementations are gone now.
Signed-off-by: Daniel Vetter <daniel.vetter(a)intel.com>
Cc: Sumit Semwal <sumit.semwal(a)linaro.org>
Cc: linux-media(a)vger.kernel.org
Cc: linaro-mm-sig(a)lists.linaro.org
---
include/linux/dma-buf.h | 25 -------------------------
1 file changed, 25 deletions(-)
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
index 7feb9c3805ae..abf5459a5b9d 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -249,31 +249,6 @@ struct dma_buf_ops {
*/
int (*mmap)(struct dma_buf *, struct vm_area_struct *vma);
- /**
- * @map:
- *
- * Maps a page from the buffer into kernel address space. The page is
- * specified by offset into the buffer in PAGE_SIZE units.
- *
- * This callback is optional.
- *
- * Returns:
- *
- * Virtual address pointer where requested page can be accessed. NULL
- * on error or when this function is unimplemented by the exporter.
- */
- void *(*map)(struct dma_buf *, unsigned long);
-
- /**
- * @unmap:
- *
- * Unmaps a page from the buffer. Page offset and address pointer should
- * be the same as the one passed to and returned by matching call to map.
- *
- * This callback is optional.
- */
- void (*unmap)(struct dma_buf *, unsigned long, void *);
-
void *(*vmap)(struct dma_buf *);
void (*vunmap)(struct dma_buf *, void *vaddr);
};
--
2.24.0
Quoting kernel test robot (2019-11-21 07:19:43)
> Greetings,
>
> 0day kernel testing robot got the below dmesg and the first bad commit is
>
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
>
> commit 2989f6451084aed3f8cc9992477f7a9bf57a3716
> Author: Chris Wilson <chris(a)chris-wilson.co.uk>
> AuthorDate: Mon Aug 19 10:59:27 2019 +0100
> Commit: Chris Wilson <chris(a)chris-wilson.co.uk>
> CommitDate: Mon Aug 19 18:09:46 2019 +0100
That's a belated report, fixed by
commit 6ac3a0ebfcc2f0c75ca0ca6974389ce421aa5cbd
Author: Chris Wilson <chris(a)chris-wilson.co.uk>
Date: Tue Aug 20 13:21:18 2019 +0100
dmabuf: Mark up onstack timer for selftests
No?
-Chris
Semnatically it really doesn't matter where we grab the ticket. But
since the ticket is a fake lockdep lock, it matters for lockdep
validation purposes.
This means stuff like grabbing a ticket and then doing
copy_from/to_user isn't allowed anymore. This is a changed compared to
the current ttm fault handler, which doesn't bother with having a full
reservation. Since I'm looking into fixing the TODO entry in
ttm_mem_evict_wait_busy() I think that'll have to change sooner or
later anyway, better get started. A bit more context on why I'm
looking into this: For backwards compat with existing i915 gem code I
think we'll have to do full slowpath locking in the i915 equivalent of
the eviction code. And with dynamic dma-buf that will leak across
drivers, so another thing we need to standardize and make sure it's
done the same way everyway.
Unfortunately this means another full audit of all drivers:
- gem helpers: acquire_init is done right before taking locks, so no
problem. Same for acquire_fini and unlocking, which means nothing
that's not already covered by the dma_resv_lock rules will be caught
with this extension here to the acquire_ctx.
- etnaviv: An absolute massive amount of code is run between the
acquire_init and the first lock acquisition in submit_lock_objects.
But nothing that would touch user memory and could cause a fault.
Furthermore nothing that uses the ticket, so even if I missed
something, it would be easy to fix by pushing the acquire_init right
before the first use. Similar on the unlock/acquire_fini side.
- i915: Right now (and this will likely change a lot rsn) the acquire
ctx and actual locks are right next to each another. No problem.
- msm has a problem: submit_create calls acquire_init, but then
submit_lookup_objects() has a bunch of copy_from_user to do the
object lookups. That's the only thing before submit_lock_objects
call dma_resv_lock(). Despite all the copypasta to etnaviv, etnaviv
does not have this issue since it copies all the userspace structs
earlier. submit_cleanup does not have any such issues.
With the prep patch to pull out the acquire_ctx and reorder it msm
is going to be safe too.
- nouveau: acquire_init is right next to ttm_bo_reserve, so all good.
Similar on the acquire_fini/ttm_bo_unreserve side.
- ttm execbuf utils: acquire context and locking are even in the same
functions here (one function to reserve everything, the other to
unreserve), so all good.
- vc4: Another case where acquire context and locking are handled in
the same functions (one function to lock everything, the other to
unlock).
Cc: Maarten Lankhorst <maarten.lankhorst(a)linux.intel.com>
Cc: Chris Wilson <chris(a)chris-wilson.co.uk>
Cc: Christian König <christian.koenig(a)amd.com>
Cc: Sumit Semwal <sumit.semwal(a)linaro.org>
Cc: linux-media(a)vger.kernel.org
Cc: linaro-mm-sig(a)lists.linaro.org
Cc: Huang Rui <ray.huang(a)amd.com>
Cc: Eric Anholt <eric(a)anholt.net>
Cc: Ben Skeggs <bskeggs(a)redhat.com>
Cc: Alex Deucher <alexander.deucher(a)amd.com>
Cc: Rob Herring <robh(a)kernel.org>
Cc: Lucas Stach <l.stach(a)pengutronix.de>
Cc: Russell King <linux+etnaviv(a)armlinux.org.uk>
Cc: Christian Gmeiner <christian.gmeiner(a)gmail.com>
Cc: Rob Clark <robdclark(a)gmail.com>
Cc: Sean Paul <sean(a)poorly.run>
Signed-off-by: Daniel Vetter <daniel.vetter(a)intel.com>
---
drivers/dma-buf/dma-resv.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c
index d3c760e19991..079e38fde33a 100644
--- a/drivers/dma-buf/dma-resv.c
+++ b/drivers/dma-buf/dma-resv.c
@@ -100,7 +100,9 @@ static void dma_resv_list_free(struct dma_resv_list *list)
static void __init dma_resv_lockdep(void)
{
struct mm_struct *mm = mm_alloc();
+ struct ww_acquire_ctx ctx;
struct dma_resv obj;
+ int ret;
if (!mm)
return;
@@ -108,10 +110,14 @@ static void __init dma_resv_lockdep(void)
dma_resv_init(&obj);
down_read(&mm->mmap_sem);
- ww_mutex_lock(&obj.lock, NULL);
+ ww_acquire_init(&ctx, &reservation_ww_class);
+ ret = dma_resv_lock(&obj, &ctx);
+ if (ret == -EDEADLK)
+ dma_resv_lock_slow(&obj, &ctx);
fs_reclaim_acquire(GFP_KERNEL);
fs_reclaim_release(GFP_KERNEL);
ww_mutex_unlock(&obj.lock);
+ ww_acquire_fini(&ctx);
up_read(&mm->mmap_sem);
mmput(mm);
--
2.24.0
On Mon, Nov 18, 2019 at 4:23 PM kbuild test robot <lkp(a)intel.com> wrote:
>
> Hi Daniel,
>
> I love your patch! Yet something to improve:
>
> [auto build test ERROR on drm-intel/for-linux-next]
> [also build test ERROR on v5.4-rc8 next-20191115]
> [if your patch is applied to the wrong git tree, please drop us a note to help
> improve the system. BTW, we also suggest to use '--base' option to specify the
> base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
Too old tree, on latest drm-tip this compiles since udl has lots its
own dma-buf implementation. Also, the patch set will start to compile
once linux-next is open for 5.6.
Cheers, Daniel
>
> url: https://github.com/0day-ci/linux/commits/Daniel-Vetter/Retire-dma_buf_k-un-…
> base: git://anongit.freedesktop.org/drm-intel for-linux-next
> config: m68k-allmodconfig (attached as .config)
> compiler: m68k-linux-gcc (GCC) 7.4.0
> reproduce:
> wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
> chmod +x ~/bin/make.cross
> # save the attached .config to linux build tree
> GCC_VERSION=7.4.0 make.cross ARCH=m68k
>
> If you fix the issue, kindly add following tag
> Reported-by: kbuild test robot <lkp(a)intel.com>
>
> All errors (new ones prefixed by >>):
>
> >> drivers/dma-buf/udmabuf.c:114:3: error: 'const struct dma_buf_ops' has no member named 'map'; did you mean 'mmap'?
> .map = kmap_udmabuf,
> ^~~
> mmap
> >> drivers/dma-buf/udmabuf.c:114:12: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
> .map = kmap_udmabuf,
> ^~~~~~~~~~~~
> drivers/dma-buf/udmabuf.c:114:12: note: (near initialization for 'udmabuf_ops.begin_cpu_access')
> >> drivers/dma-buf/udmabuf.c:115:3: error: 'const struct dma_buf_ops' has no member named 'unmap'; did you mean 'vunmap'?
> .unmap = kunmap_udmabuf,
> ^~~~~
> vunmap
> drivers/dma-buf/udmabuf.c:115:14: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
> .unmap = kunmap_udmabuf,
> ^~~~~~~~~~~~~~
> drivers/dma-buf/udmabuf.c:115:14: note: (near initialization for 'udmabuf_ops.end_cpu_access')
> cc1: some warnings being treated as errors
> --
> >> drivers/gpu/drm/udl/udl_dmabuf.c:169:3: error: 'const struct dma_buf_ops' has no member named 'map'; did you mean 'mmap'?
> .map = udl_dmabuf_kmap,
> ^~~
> mmap
> >> drivers/gpu/drm/udl/udl_dmabuf.c:169:11: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
> .map = udl_dmabuf_kmap,
> ^~~~~~~~~~~~~~~
> drivers/gpu/drm/udl/udl_dmabuf.c:169:11: note: (near initialization for 'udl_dmabuf_ops.release')
> >> drivers/gpu/drm/udl/udl_dmabuf.c:170:3: error: 'const struct dma_buf_ops' has no member named 'unmap'; did you mean 'vunmap'?
> .unmap = udl_dmabuf_kunmap,
> ^~~~~
> vunmap
> drivers/gpu/drm/udl/udl_dmabuf.c:170:13: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
> .unmap = udl_dmabuf_kunmap,
> ^~~~~~~~~~~~~~~~~
> drivers/gpu/drm/udl/udl_dmabuf.c:170:13: note: (near initialization for 'udl_dmabuf_ops.begin_cpu_access')
> cc1: some warnings being treated as errors
>
> vim +114 drivers/dma-buf/udmabuf.c
>
> fbb0de79507819 Gerd Hoffmann 2018-08-27 109
> a34852891ba45d Gerd Hoffmann 2018-09-11 110 static const struct dma_buf_ops udmabuf_ops = {
> fbb0de79507819 Gerd Hoffmann 2018-08-27 111 .map_dma_buf = map_udmabuf,
> fbb0de79507819 Gerd Hoffmann 2018-08-27 112 .unmap_dma_buf = unmap_udmabuf,
> fbb0de79507819 Gerd Hoffmann 2018-08-27 113 .release = release_udmabuf,
> fbb0de79507819 Gerd Hoffmann 2018-08-27 @114 .map = kmap_udmabuf,
> fbb0de79507819 Gerd Hoffmann 2018-08-27 @115 .unmap = kunmap_udmabuf,
> fbb0de79507819 Gerd Hoffmann 2018-08-27 116 .mmap = mmap_udmabuf,
> fbb0de79507819 Gerd Hoffmann 2018-08-27 117 };
> fbb0de79507819 Gerd Hoffmann 2018-08-27 118
>
> :::::: The code at line 114 was first introduced by commit
> :::::: fbb0de795078190a9834b3409e4b009cfb18a6d4 Add udmabuf misc device
>
> :::::: TO: Gerd Hoffmann <kraxel(a)redhat.com>
> :::::: CC: Gerd Hoffmann <kraxel(a)redhat.com>
>
> ---
> 0-DAY kernel test infrastructure Open Source Technology Center
> https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel Corporation
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
It's unused.
10 years ago, back when 32bit was still fairly common and trying to
not exhaust vmalloc space sounded like a worthwhile goal, adding these
to dma_buf made sense.
Reality is that they simply never caught on, and nowadays everyone who
needs plenty of buffers will run in 64bit mode anyway.
Also update the docs in this area to adjust them to reality.
The actual hooks in dma_buf_ops will be removed once all the
implementations are gone.
Signed-off-by: Daniel Vetter <daniel.vetter(a)intel.com>
Cc: Sumit Semwal <sumit.semwal(a)linaro.org>
Cc: linux-media(a)vger.kernel.org
Cc: linaro-mm-sig(a)lists.linaro.org
---
drivers/dma-buf/dma-buf.c | 63 ++-------------------------------------
include/linux/dma-buf.h | 2 --
2 files changed, 3 insertions(+), 62 deletions(-)
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index d377b4ca66bf..97988ce1d2dc 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -880,29 +880,9 @@ EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment);
* with calls to dma_buf_begin_cpu_access() and dma_buf_end_cpu_access()
* access.
*
- * To support dma_buf objects residing in highmem cpu access is page-based
- * using an api similar to kmap. Accessing a dma_buf is done in aligned chunks
- * of PAGE_SIZE size. Before accessing a chunk it needs to be mapped, which
- * returns a pointer in kernel virtual address space. Afterwards the chunk
- * needs to be unmapped again. There is no limit on how often a given chunk
- * can be mapped and unmapped, i.e. the importer does not need to call
- * begin_cpu_access again before mapping the same chunk again.
- *
- * Interfaces::
- * void \*dma_buf_kmap(struct dma_buf \*, unsigned long);
- * void dma_buf_kunmap(struct dma_buf \*, unsigned long, void \*);
- *
- * Implementing the functions is optional for exporters and for importers all
- * the restrictions of using kmap apply.
- *
- * dma_buf kmap calls outside of the range specified in begin_cpu_access are
- * undefined. If the range is not PAGE_SIZE aligned, kmap needs to succeed on
- * the partial chunks at the beginning and end but may return stale or bogus
- * data outside of the range (in these partial chunks).
- *
- * For some cases the overhead of kmap can be too high, a vmap interface
- * is introduced. This interface should be used very carefully, as vmalloc
- * space is a limited resources on many architectures.
+ * Since for most kernel internal dma-buf accesses need the entire buffer, a
+ * vmap interface is introduced. Note that on very old 32-bit architectures
+ * vmalloc space might be limited and result in vmap calls failing.
*
* Interfaces::
* void \*dma_buf_vmap(struct dma_buf \*dmabuf)
@@ -1052,43 +1032,6 @@ int dma_buf_end_cpu_access(struct dma_buf *dmabuf,
}
EXPORT_SYMBOL_GPL(dma_buf_end_cpu_access);
-/**
- * dma_buf_kmap - Map a page of the buffer object into kernel address space. The
- * same restrictions as for kmap and friends apply.
- * @dmabuf: [in] buffer to map page from.
- * @page_num: [in] page in PAGE_SIZE units to map.
- *
- * This call must always succeed, any necessary preparations that might fail
- * need to be done in begin_cpu_access.
- */
-void *dma_buf_kmap(struct dma_buf *dmabuf, unsigned long page_num)
-{
- WARN_ON(!dmabuf);
-
- if (!dmabuf->ops->map)
- return NULL;
- return dmabuf->ops->map(dmabuf, page_num);
-}
-EXPORT_SYMBOL_GPL(dma_buf_kmap);
-
-/**
- * dma_buf_kunmap - Unmap a page obtained by dma_buf_kmap.
- * @dmabuf: [in] buffer to unmap page from.
- * @page_num: [in] page in PAGE_SIZE units to unmap.
- * @vaddr: [in] kernel space pointer obtained from dma_buf_kmap.
- *
- * This call must always succeed.
- */
-void dma_buf_kunmap(struct dma_buf *dmabuf, unsigned long page_num,
- void *vaddr)
-{
- WARN_ON(!dmabuf);
-
- if (dmabuf->ops->unmap)
- dmabuf->ops->unmap(dmabuf, page_num, vaddr);
-}
-EXPORT_SYMBOL_GPL(dma_buf_kunmap);
-
/**
* dma_buf_mmap - Setup up a userspace mmap with the given vma
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
index af73f835c51c..7feb9c3805ae 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -464,8 +464,6 @@ int dma_buf_begin_cpu_access(struct dma_buf *dma_buf,
enum dma_data_direction dir);
int dma_buf_end_cpu_access(struct dma_buf *dma_buf,
enum dma_data_direction dir);
-void *dma_buf_kmap(struct dma_buf *, unsigned long);
-void dma_buf_kunmap(struct dma_buf *, unsigned long, void *);
int dma_buf_mmap(struct dma_buf *, struct vm_area_struct *,
unsigned long);
--
2.24.0
The value of sync_timeline is only incremented and all reference
usage of it is unsigned. Use unsigned type for value of
synctimeline.
Signed-off-by: Seung-Woo Kim <sw0312.kim(a)samsung.com>
---
drivers/dma-buf/sync_debug.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/dma-buf/sync_debug.h b/drivers/dma-buf/sync_debug.h
index 6176e52..ff07f0b 100644
--- a/drivers/dma-buf/sync_debug.h
+++ b/drivers/dma-buf/sync_debug.h
@@ -36,7 +36,7 @@ struct sync_timeline {
/* protected by lock */
u64 context;
- int value;
+ unsigned int value;
struct rb_root pt_tree;
struct list_head pt_list;
--
1.7.4.1
Hello John Stultz,
The patch 7b87ea704fd9: "dma-buf: heaps: Add heap helpers" from Oct
21, 2019, leads to the following static checker warning:
drivers/dma-buf/heaps/heap-helpers.c:165 dma_heap_vm_fault()
warn: uncapped user index 'buffer->pages[vmf->pgoff]'
drivers/dma-buf/heaps/heap-helpers.c
160 static vm_fault_t dma_heap_vm_fault(struct vm_fault *vmf)
161 {
162 struct vm_area_struct *vma = vmf->vma;
163 struct heap_helper_buffer *buffer = vma->vm_private_data;
164
165 vmf->page = buffer->pages[vmf->pgoff];
^^^^^^^^^^
Smatch for some reason thinks this needs to be checked. Smatch also
gets confused by these fault handlers and thinks there is some recursion
involved...
166 get_page(vmf->page);
167
168 return 0;
169 }
170
171 static const struct vm_operations_struct dma_heap_vm_ops = {
172 .fault = dma_heap_vm_fault,
173 };
174
regards,
dan carpenter
On Wed, Oct 30, 2019 at 8:45 AM Andrew F. Davis <afd(a)ti.com> wrote:
>
> On 10/30/19 11:02 AM, Colin King wrote:
> > From: Colin Ian King <colin.king(a)canonical.com>
> >
> > The variable ret is being assigned with a value that is never
> > read, it is being re-assigned the same value on the err0 exit
> > path. The assignment is redundant and hence can be removed.
> >
> > Addresses-Coverity: ("Unused value")
> > Fixes: 47a32f9c1226 ("dma-buf: heaps: Add system heap to dmabuf heaps")
> > Signed-off-by: Colin Ian King <colin.king(a)canonical.com>
> > ---
>
>
> The root of the issue is that ret is not used in the error path, it
> should be, I suggest this fix:
>
> > --- a/drivers/dma-buf/heaps/system_heap.c
> > +++ b/drivers/dma-buf/heaps/system_heap.c
> > @@ -98,7 +98,7 @@ static int system_heap_allocate(struct dma_heap *heap,
> > err0:
> > kfree(helper_buffer);
> >
> > - return -ENOMEM;
> > + return ret;
> > }
Sounds good! If its ok I'll generate a commit crediting Colin for
reporting the issue and Andrew for the fix and submit it to Sumit.
Many thanks to you both!
-john
Colin King reported a coverity error:
The variable ret is being assigned with a value that is never
read, it is being re-assigned the same value on the err0 exit
path. The assignment is redundant and hence can be removed.
He had a fix, but Andrew Davis suggested a better solution
(actually returning ret), so this patch implements that fix.
Cc: Colin King <colin.king(a)canonical.com>
Cc: Sumit Semwal <sumit.semwal(a)linaro.org>
Cc: Benjamin Gaignard <benjamin.gaignard(a)linaro.org>
Cc: Liam Mark <lmark(a)codeaurora.org>
Cc: Laura Abbott <labbott(a)redhat.com>
Cc: Brian Starkey <brian.starkey(a)arm.com>
Cc: Andrew F. Davis <afd(a)ti.com>
Cc: dri-devel(a)lists.freedesktop.org
Cc: linaro-mm-sig(a)lists.linaro.org
Cc: kernel-janitors(a)vger.kernel.org
Addresses-Coverity: ("Unused value")
Fixes: 47a32f9c1226 ("dma-buf: heaps: Add system heap to dmabuf heaps")
Reported-by: Colin Ian King <colin.king(a)canonical.com>
Suggested-by: Andrew F. Davis <afd(a)ti.com>
Signed-off-by: John Stultz <john.stultz(a)linaro.org>
---
drivers/dma-buf/heaps/system_heap.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c
index 455782efbb32..9a56393e40b4 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -98,7 +98,7 @@ static int system_heap_allocate(struct dma_heap *heap,
err0:
kfree(helper_buffer);
- return -ENOMEM;
+ return ret;
}
static const struct dma_heap_ops system_heap_ops = {
--
2.17.1
The first argument of WARN() is a condition so this will just print the
function name instead of the whole warning message.
Fixes: 7b87ea704fd9 ("dma-buf: heaps: Add heap helpers")
Signed-off-by: Dan Carpenter <dan.carpenter(a)oracle.com>
---
drivers/dma-buf/heaps/heap-helpers.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/dma-buf/heaps/heap-helpers.c b/drivers/dma-buf/heaps/heap-helpers.c
index 750bef4e902d..a31684c0d5b2 100644
--- a/drivers/dma-buf/heaps/heap-helpers.c
+++ b/drivers/dma-buf/heaps/heap-helpers.c
@@ -52,7 +52,7 @@ static void *dma_heap_map_kernel(struct heap_helper_buffer *buffer)
static void dma_heap_buffer_destroy(struct heap_helper_buffer *buffer)
{
if (buffer->vmap_cnt > 0) {
- WARN("%s: buffer still mapped in the kernel\n", __func__);
+ WARN(1, "%s: buffer still mapped in the kernel\n", __func__);
vunmap(buffer->vaddr);
}
--
2.20.1
From: Colin Ian King <colin.king(a)canonical.com>
The variable ret is being assigned with a value that is never
read, it is being re-assigned the same value on the err0 exit
path. The assignment is redundant and hence can be removed.
Addresses-Coverity: ("Unused value")
Fixes: 47a32f9c1226 ("dma-buf: heaps: Add system heap to dmabuf heaps")
Signed-off-by: Colin Ian King <colin.king(a)canonical.com>
---
drivers/dma-buf/heaps/system_heap.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c
index 455782efbb32..817a1667bd57 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -55,10 +55,8 @@ static int system_heap_allocate(struct dma_heap *heap,
helper_buffer->pages = kmalloc_array(helper_buffer->pagecount,
sizeof(*helper_buffer->pages),
GFP_KERNEL);
- if (!helper_buffer->pages) {
- ret = -ENOMEM;
+ if (!helper_buffer->pages)
goto err0;
- }
for (pg = 0; pg < helper_buffer->pagecount; pg++) {
/*
--
2.20.1
This patch is a stripped down version of the locking changes
necessary to support dynamic DMA-buf handling.
It adds a dynamic flag for both importers as well as exporters
so that drivers can choose if they want the reservation object
locked or unlocked during mapping of attachments.
For compatibility between drivers we cache the DMA-buf mapping
during attaching an importer as soon as exporter/importer
disagree on the dynamic handling.
This change has gone through a lengthy discussion on dri-devel
and other mailing lists with at least 3-4 different attempts and
dead-ends until we settled on this solution. Please refer to the
mailing lists archives for full background on the history of
this change.
v2: cleanup set_name merge, improve kerneldoc
Signed-off-by: Christian König <christian.koenig(a)amd.com>
---
drivers/dma-buf/dma-buf.c | 102 +++++++++++++++++++++++++++++++++-----
include/linux/dma-buf.h | 57 +++++++++++++++++++--
2 files changed, 143 insertions(+), 16 deletions(-)
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index 433d91d710e4..753be84b5fd6 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -45,10 +45,10 @@ static char *dmabuffs_dname(struct dentry *dentry, char *buffer, int buflen)
size_t ret = 0;
dmabuf = dentry->d_fsdata;
- mutex_lock(&dmabuf->lock);
+ dma_resv_lock(dmabuf->resv, NULL);
if (dmabuf->name)
ret = strlcpy(name, dmabuf->name, DMA_BUF_NAME_LEN);
- mutex_unlock(&dmabuf->lock);
+ dma_resv_unlock(dmabuf->resv);
return dynamic_dname(dentry, buffer, buflen, "/%s:%s",
dentry->d_name.name, ret > 0 ? name : "");
@@ -334,7 +334,7 @@ static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf)
if (IS_ERR(name))
return PTR_ERR(name);
- mutex_lock(&dmabuf->lock);
+ dma_resv_lock(dmabuf->resv, NULL);
if (!list_empty(&dmabuf->attachments)) {
ret = -EBUSY;
kfree(name);
@@ -344,7 +344,7 @@ static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf)
dmabuf->name = name;
out_unlock:
- mutex_unlock(&dmabuf->lock);
+ dma_resv_unlock(dmabuf->resv);
return ret;
}
@@ -403,10 +403,10 @@ static void dma_buf_show_fdinfo(struct seq_file *m, struct file *file)
/* Don't count the temporary reference taken inside procfs seq_show */
seq_printf(m, "count:\t%ld\n", file_count(dmabuf->file) - 1);
seq_printf(m, "exp_name:\t%s\n", dmabuf->exp_name);
- mutex_lock(&dmabuf->lock);
+ dma_resv_lock(dmabuf->resv, NULL);
if (dmabuf->name)
seq_printf(m, "name:\t%s\n", dmabuf->name);
- mutex_unlock(&dmabuf->lock);
+ dma_resv_unlock(dmabuf->resv);
}
static const struct file_operations dma_buf_fops = {
@@ -525,6 +525,10 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
return ERR_PTR(-EINVAL);
}
+ if (WARN_ON(exp_info->ops->cache_sgt_mapping &&
+ exp_info->ops->dynamic_mapping))
+ return ERR_PTR(-EINVAL);
+
if (!try_module_get(exp_info->owner))
return ERR_PTR(-ENOENT);
@@ -645,10 +649,11 @@ void dma_buf_put(struct dma_buf *dmabuf)
EXPORT_SYMBOL_GPL(dma_buf_put);
/**
- * dma_buf_attach - Add the device to dma_buf's attachments list; optionally,
+ * dma_buf_dynamic_attach - Add the device to dma_buf's attachments list; optionally,
* calls attach() of dma_buf_ops to allow device-specific attach functionality
- * @dmabuf: [in] buffer to attach device to.
- * @dev: [in] device to be attached.
+ * @dmabuf: [in] buffer to attach device to.
+ * @dev: [in] device to be attached.
+ * @dynamic_mapping: [in] calling convention for map/unmap
*
* Returns struct dma_buf_attachment pointer for this attachment. Attachments
* must be cleaned up by calling dma_buf_detach().
@@ -662,8 +667,9 @@ EXPORT_SYMBOL_GPL(dma_buf_put);
* accessible to @dev, and cannot be moved to a more suitable place. This is
* indicated with the error code -EBUSY.
*/
-struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
- struct device *dev)
+struct dma_buf_attachment *
+dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
+ bool dynamic_mapping)
{
struct dma_buf_attachment *attach;
int ret;
@@ -677,6 +683,7 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
attach->dev = dev;
attach->dmabuf = dmabuf;
+ attach->dynamic_mapping = dynamic_mapping;
mutex_lock(&dmabuf->lock);
@@ -685,16 +692,64 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
if (ret)
goto err_attach;
}
+ dma_resv_lock(dmabuf->resv, NULL);
list_add(&attach->node, &dmabuf->attachments);
+ dma_resv_unlock(dmabuf->resv);
mutex_unlock(&dmabuf->lock);
+ /* When either the importer or the exporter can't handle dynamic
+ * mappings we cache the mapping here to avoid issues with the
+ * reservation object lock.
+ */
+ if (dma_buf_attachment_is_dynamic(attach) !=
+ dma_buf_is_dynamic(dmabuf)) {
+ struct sg_table *sgt;
+
+ if (dma_buf_is_dynamic(attach->dmabuf))
+ dma_resv_lock(attach->dmabuf->resv, NULL);
+
+ sgt = dmabuf->ops->map_dma_buf(attach, DMA_BIDIRECTIONAL);
+ if (!sgt)
+ sgt = ERR_PTR(-ENOMEM);
+ if (IS_ERR(sgt)) {
+ ret = PTR_ERR(sgt);
+ goto err_unlock;
+ }
+ if (dma_buf_is_dynamic(attach->dmabuf))
+ dma_resv_unlock(attach->dmabuf->resv);
+ attach->sgt = sgt;
+ attach->dir = DMA_BIDIRECTIONAL;
+ }
+
return attach;
err_attach:
kfree(attach);
mutex_unlock(&dmabuf->lock);
return ERR_PTR(ret);
+
+err_unlock:
+ if (dma_buf_is_dynamic(attach->dmabuf))
+ dma_resv_unlock(attach->dmabuf->resv);
+
+ dma_buf_detach(dmabuf, attach);
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(dma_buf_dynamic_attach);
+
+/**
+ * dma_buf_attach - Wrapper for dma_buf_dynamic_attach
+ * @dmabuf: [in] buffer to attach device to.
+ * @dev: [in] device to be attached.
+ *
+ * Wrapper to call dma_buf_dynamic_attach() for drivers which still use a static
+ * mapping.
+ */
+struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
+ struct device *dev)
+{
+ return dma_buf_dynamic_attach(dmabuf, dev, false);
}
EXPORT_SYMBOL_GPL(dma_buf_attach);
@@ -711,11 +766,20 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
if (WARN_ON(!dmabuf || !attach))
return;
- if (attach->sgt)
+ if (attach->sgt) {
+ if (dma_buf_is_dynamic(attach->dmabuf))
+ dma_resv_lock(attach->dmabuf->resv, NULL);
+
dmabuf->ops->unmap_dma_buf(attach, attach->sgt, attach->dir);
+ if (dma_buf_is_dynamic(attach->dmabuf))
+ dma_resv_unlock(attach->dmabuf->resv);
+ }
+
mutex_lock(&dmabuf->lock);
+ dma_resv_lock(dmabuf->resv, NULL);
list_del(&attach->node);
+ dma_resv_unlock(dmabuf->resv);
if (dmabuf->ops->detach)
dmabuf->ops->detach(dmabuf, attach);
@@ -749,6 +813,9 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
if (WARN_ON(!attach || !attach->dmabuf))
return ERR_PTR(-EINVAL);
+ if (dma_buf_attachment_is_dynamic(attach))
+ dma_resv_assert_held(attach->dmabuf->resv);
+
if (attach->sgt) {
/*
* Two mappings with different directions for the same
@@ -761,6 +828,9 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
return attach->sgt;
}
+ if (dma_buf_is_dynamic(attach->dmabuf))
+ dma_resv_assert_held(attach->dmabuf->resv);
+
sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction);
if (!sg_table)
sg_table = ERR_PTR(-ENOMEM);
@@ -793,9 +863,15 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
return;
+ if (dma_buf_attachment_is_dynamic(attach))
+ dma_resv_assert_held(attach->dmabuf->resv);
+
if (attach->sgt == sg_table)
return;
+ if (dma_buf_is_dynamic(attach->dmabuf))
+ dma_resv_assert_held(attach->dmabuf->resv);
+
attach->dmabuf->ops->unmap_dma_buf(attach, sg_table, direction);
}
EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment);
@@ -1219,10 +1295,12 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
seq_puts(s, "\tAttached Devices:\n");
attach_count = 0;
+ dma_resv_lock(buf_obj->resv, NULL);
list_for_each_entry(attach_obj, &buf_obj->attachments, node) {
seq_printf(s, "\t%s\n", dev_name(attach_obj->dev));
attach_count++;
}
+ dma_resv_unlock(buf_obj->resv);
seq_printf(s, "Total %d devices attached\n\n",
attach_count);
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
index ec212cb27fdc..bcc0f4d0b678 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -42,6 +42,18 @@ struct dma_buf_ops {
*/
bool cache_sgt_mapping;
+ /**
+ * @dynamic_mapping:
+ *
+ * If true the framework makes sure that the map/unmap_dma_buf
+ * callbacks are always called with the dma_resv object locked.
+ *
+ * If false the framework makes ure that the map/unmap_dma_buf
+ * callbacks are always called without the dma_resv object locked.
+ * Mutual exclusive with @cache_sgt_mapping.
+ */
+ bool dynamic_mapping;
+
/**
* @attach:
*
@@ -109,6 +121,9 @@ struct dma_buf_ops {
* any other kind of sharing that the exporter might wish to make
* available to buffer-users.
*
+ * This is always called with the dmabuf->resv object locked when
+ * the dynamic_mapping flag is true.
+ *
* Returns:
*
* A &sg_table scatter list of or the backing storage of the DMA buffer,
@@ -267,7 +282,8 @@ struct dma_buf_ops {
* struct dma_buf - shared buffer object
* @size: size of the buffer
* @file: file pointer used for sharing buffers across, and for refcounting.
- * @attachments: list of dma_buf_attachment that denotes all devices attached.
+ * @attachments: list of dma_buf_attachment that denotes all devices attached,
+ * protected by dma_resv lock.
* @ops: dma_buf_ops associated with this buffer object.
* @lock: used internally to serialize list manipulation, attach/detach and
* vmap/unmap, and accesses to name
@@ -323,10 +339,12 @@ struct dma_buf {
* struct dma_buf_attachment - holds device-buffer attachment data
* @dmabuf: buffer for this attachment.
* @dev: device attached to the buffer.
- * @node: list of dma_buf_attachment.
+ * @node: list of dma_buf_attachment, protected by dma_resv lock of the dmabuf.
* @sgt: cached mapping.
* @dir: direction of cached mapping.
* @priv: exporter specific attachment data.
+ * @dynamic_mapping: true if dma_buf_map/unmap_attachment() is called with the
+ * dma_resv lock held.
*
* This structure holds the attachment information between the dma_buf buffer
* and its user device(s). The list contains one attachment struct per device
@@ -343,6 +361,7 @@ struct dma_buf_attachment {
struct list_head node;
struct sg_table *sgt;
enum dma_data_direction dir;
+ bool dynamic_mapping;
void *priv;
};
@@ -394,10 +413,39 @@ static inline void get_dma_buf(struct dma_buf *dmabuf)
get_file(dmabuf->file);
}
+/**
+ * dma_buf_is_dynamic - check if a DMA-buf uses dynamic mappings.
+ * @dmabuf: the DMA-buf to check
+ *
+ * Returns true if a DMA-buf exporter wants to be called with the dma_resv
+ * locked, false if it doesn't wants to be called with the lock held.
+ */
+static inline bool dma_buf_is_dynamic(struct dma_buf *dmabuf)
+{
+ return dmabuf->ops->dynamic_mapping;
+}
+
+/**
+ * dma_buf_attachment_is_dynamic - check if a DMA-buf attachment uses dynamic
+ * mappinsg
+ * @attach: the DMA-buf attachment to check
+ *
+ * Returns true if a DMA-buf importer wants to call the map/unmap functions with
+ * the dma_resv lock held.
+ */
+static inline bool
+dma_buf_attachment_is_dynamic(struct dma_buf_attachment *attach)
+{
+ return attach->dynamic_mapping;
+}
+
struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
- struct device *dev);
+ struct device *dev);
+struct dma_buf_attachment *
+dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
+ bool dynamic_mapping);
void dma_buf_detach(struct dma_buf *dmabuf,
- struct dma_buf_attachment *dmabuf_attach);
+ struct dma_buf_attachment *attach);
struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info);
@@ -409,6 +457,7 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *,
enum dma_data_direction);
void dma_buf_unmap_attachment(struct dma_buf_attachment *, struct sg_table *,
enum dma_data_direction);
+void dma_buf_move_notify(struct dma_buf *dma_buf);
int dma_buf_begin_cpu_access(struct dma_buf *dma_buf,
enum dma_data_direction dir);
int dma_buf_end_cpu_access(struct dma_buf *dma_buf,
--
2.17.1
Hi everyone,
since upstreaming the full dynamic DMA-buf changes turned out more problematic than previously thought I've reverted back to individual patches and separated out only the locking changes.
So this patch does NOT contain any new callbacks for pinning/unpinning and move notification, but only the locking changes necessary.
As previously discussed when the framework detects that the locking semantics between exporter and importer are different it just falls back to using a cached sgt created during attach time.
While separating the patch set I've most likely stumbled over the problem why this previously raised some lockdep warning with i915, it turned out to be just a might_lock() at the wrong place.
Please review and/or comment,
Christian.
Hi Qiang,
oh, good point. Yes it certainly should.
Looks like I accidentally pushed it to the wrong branch.
Thanks,
Christian.
Am 10.10.19 um 16:27 schrieb Qiang Yu:
> Hi Chris,
>
> This fix has been pushed to drm-misc-next for a while. But Linux
> 5.4-rc kernels still does not have this fix.
> Should it be also pushed to drm-misc-fixes?
>
> Thanks,
> Qiang
>
>
> On Sun, Sep 22, 2019 at 8:50 PM Chris Wilson <chris(a)chris-wilson.co.uk> wrote:
>> Quoting Chris Wilson (2019-09-22 13:17:19)
>>> Quoting Qiang Yu (2019-09-22 08:49:00)
>>>> This causes kernel crash when testing lima driver.
>>>>
>>>> Cc: Christian König <christian.koenig(a)amd.com>
>>>> Fixes: b8c036dfc66f ("dma-buf: simplify reservation_object_get_fences_rcu a bit")
>>>> Signed-off-by: Qiang Yu <yuq825(a)gmail.com>
>>>> ---
>>>> drivers/dma-buf/dma-resv.c | 2 +-
>>>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>>>
>>>> diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c
>>>> index 42a8f3f11681..709002515550 100644
>>>> --- a/drivers/dma-buf/dma-resv.c
>>>> +++ b/drivers/dma-buf/dma-resv.c
>>>> @@ -471,7 +471,7 @@ int dma_resv_get_fences_rcu(struct dma_resv *obj,
>>>> if (pfence_excl)
>>>> *pfence_excl = fence_excl;
>>>> else if (fence_excl)
>>>> - shared[++shared_count] = fence_excl;
>>>> + shared[shared_count++] = fence_excl;
>>> Oops.
>>>
>>> Reviewed-by: Chris Wilson <chris(a)chris-wilson.co.uk>
>> Applied, thanks for the fix.
>> -Chris
On Mon, Sep 30, 2019 at 8:57 AM Ayan Halder <Ayan.Halder(a)arm.com> wrote:
>
> On Mon, Sep 30, 2019 at 09:51:35AM +0000, Brian Starkey wrote:
> > Hi,
> >
> > On Tue, Sep 17, 2019 at 07:36:45PM +0200, Daniel Vetter wrote:
> > > On Tue, Sep 17, 2019 at 6:15 PM Neil Armstrong <narmstrong(a)baylibre.com> wrote:
> > > >
> > > > Hi,
> > > >
> > > > On 17/09/2019 18:07, Liviu Dudau wrote:
> > > > > On Tue, Sep 17, 2019 at 02:53:01PM +0200, Daniel Vetter wrote:
> > > > >> On Mon, Sep 09, 2019 at 01:42:53PM +0000, Ayan Halder wrote:
> > > > >>> Add a modifier 'DRM_FORMAT_MOD_ARM_PROTECTED' which denotes that the framebuffer
> > > > >>> is allocated in a protected system memory.
> > > > >>> Essentially, we want to support EGL_EXT_protected_content in our komeda driver.
> > > > >>>
> > > > >>> Signed-off-by: Ayan Kumar Halder <ayan.halder(a)arm.com>
> > > > >>>
> > > > >>> /-- Note to reviewer
> > > > >>> Komeda driver is capable of rendering DRM (Digital Rights Management) protected
> > > > >>> content. The DRM content is stored in a framebuffer allocated in system memory
> > > > >>> (which needs some special hardware signals for access).
> > > > >>>
> > > > >>> Let us ignore how the protected system memory is allocated and for the scope of
> > > > >>> this discussion, we want to figure out the best way possible for the userspace
> > > > >>> to communicate to the drm driver to turn the protected mode on (for accessing the
> > > > >>> framebuffer with the DRM content) or off.
> > > > >>>
> > > > >>> The possible ways by which the userspace could achieve this is via:-
> > > > >>>
> > > > >>> 1. Modifiers :- This looks to me the best way by which the userspace can
> > > > >>> communicate to the kernel to turn the protected mode on for the komeda driver
> > > > >>> as it is going to access one of the protected framebuffers. The only problem is
> > > > >>> that the current modifiers describe the tiling/compression format. However, it
> > > > >>> does not hurt to extend the meaning of modifiers to denote other attributes of
> > > > >>> the framebuffer as well.
> > > > >>>
> > > > >>> The other reason is that on Android, we get an info from Gralloc
> > > > >>> (GRALLOC_USAGE_PROTECTED) which tells us that the buffer is protected. This can
> > > > >>> be used to set up the modifier/s (AddFB2) during framebuffer creation.
> > > > >>
> > > > >> How does this mesh with other modifiers, like AFBC? That's where I see the
> > > > >> issue here.
> > > > >
> > > > > AFBC modifiers are currently under Arm's namespace, the thought behind the DRM
> > > > > modifiers would be to have it as a "generic" modifier.
> > >
> > > But if it's a generic flag, how do you combine that with other
> > > modifiers? Like if you have a tiled buffer, but also encrypted? Or
> > > afbc compressed, or whatever else. I'd expect for your hw encryption
> > > is orthogonal to the buffer/tiling/compression format used?
> >
> > This bit doesn't overlap with any of the other AFBC modifiers, so as
> > you say it'd be orthogonal, and could be set on AFBC buffers (if we
> > went that route).
> >
> > >
> > > > >>> 2. Framebuffer flags :- As of today, this can be one of the two values
> > > > >>> ie (DRM_MODE_FB_INTERLACED/DRM_MODE_FB_MODIFIERS). Unlike modifiers, the drm
> > > > >>> framebuffer flags are generic to the drm subsystem and ideally we should not
> > > > >>> introduce any driver specific constraint/feature.
> > > > >>>
> > > > >>> 3. Connector property:- I could see the following properties used for DRM
> > > > >>> protected content:-
> > > > >>> DRM_MODE_CONTENT_PROTECTION_DESIRED / ENABLED :- "This property is used by
> > > > >>> userspace to request the kernel protect future content communicated over
> > > > >>> the link". Clearly, we are not concerned with the protection attributes of the
> > > > >>> transmitter. So, we cannot use this property for our case.
> > > > >>>
> > > > >>> 4. DRM plane property:- Again, we want to communicate that the framebuffer(which
> > > > >>> can be attached to any plane) is protected. So introducing a new plane property
> > > > >>> does not help.
> > > > >>>
> > > > >>> 5. DRM crtc property:- For the same reason as above, introducing a new crtc
> > > > >>> property does not help.
> > > > >>
> > > > >> 6. Just track this as part of buffer allocation, i.e. I think it does
> > > > >> matter how you allocate these protected buffers. We could add a "is
> > > > >> protected buffer" flag at the dma_buf level for this.
> >
> > I also like this approach. The protected-ness is a property of the
> > allocation, so makes sense to store it with the allocation IMO.
> >
> > > > >>
> > > > >> So yeah for this stuff here I think we do want the full userspace side,
> > > > >> from allocator to rendering something into this protected buffers (no need
> > > > >> to also have the entire "decode a protected bitstream part" imo, since
> > > > >> that will freak people out). Unfortunately, in my experience, that kills
> > > > >> it for upstream :-/ But also in my experience of looking into this for
> > > > >> other gpu's, we really need to have the full picture here to make sure
> > > > >> we're not screwing this up.
> > > > >
> > > > > Maybe Ayan could've been a bit clearer in his message, but the ask here is for ideas
> > > > > on how userspace "communicates" (stores?) the fact that the buffers are protected to
> > > > > the kernel driver. In our display processor we need to the the hardware that the
> > > > > buffers are protected before it tries to fetch them so that it can 1) enable the
> > > > > additional hardware signaling that sets the protection around the stream; and 2) read
> > > > > the protected buffers in a special mode where there the magic happens.
> > >
> > > That was clear, but for the full picture we also need to know how
> > > these buffers are produced and where they are allocated. One approach
> > > would be to have a dma-buf heap that gives you encrypted buffers back.
> > > With that we need to make sure that only encryption-aware drivers
> > > allow such buffers to be imported, and the entire problem becomes a
> > > kernel-internal one - aside from allocating the right kind of buffer
> > > at the right place.
> > >
> >
> > In our case, we'd be supporting a system like TZMP-1, there's a
> > Linaro connect presentation on it here:
> > https://connect.linaro.org/resources/hkg18/hkg18-408/
> >
> > The simplest way to implement this is for firmware to set up a
> > carveout which it tells linux is secure. A linux allocator (ion, gem,
> > vb2, whatever) can allocate from this carveout, and tag the buffer as
> > secure.
> >
> > In this kind of system, linux doesn't necessarily need to know
> > anything about how buffers are protected, or what HW is capable of -
> > it only needs to carry around the "is_protected" flag.
> >
> > Here, the TEE is ultimately responsible for deciding which HW gets
> > access to a buffer. I don't see a benefit of having linux decide which
> > drivers can or cannot import a buffer, because that decision should be
> > handled by the TEE.
> >
> > For proving out the pipeline, IMO it doesn't matter whether the
> > buffers are protected or not. For our DPU, all that matters is that if
> > the buffer claims to be protected, we have to set our protected
> > control bit. Nothing more. AFAIK it should work the same for other
> > TZMP-1 implementations.
> >
> > > > > So yeah, we know we do want full userspace support, we're prodding the community on
> > > > > answers on how to best let the kernel side know what userspace has done.
> > > >
> > > > Actually this is interesting for other multimedia SoCs implementing secure video decode
> > > > paths where video buffers are allocated and managed by a trusted app.
> > >
> > > Yeah I expect there's more than just arm wanting this. I also wonder
> > > how that interacts with the secure memory allocator that was bobbing
> > > around on dri-devel for a while, but seems to not have gone anywhere.
> > > That thing implemented my idea of "secure memory is only allocated by
> > > a special entity".
> > > -Daniel
> >
> > Like I said, for us all we need is a way to carry around a 1-bit
> > "is_protected" flag with a buffer. Could other folks share what's
> > needed for their systems so we can reason about something that works
> > for all?
>
> To make things a bit more specific, we are thinking of the following
> patch :-
>
> diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
> index ec212cb27fdc..36f0813073a2 100644
> --- a/include/linux/dma-buf.h
> +++ b/include/linux/dma-buf.h
> @@ -279,6 +279,7 @@ struct dma_buf_ops {
> * kernel module.
> * @list_node: node for dma_buf accounting and debugging.
> * @priv: exporter specific private data for this buffer object.
> + * @is_protected: denotes that the buffer is
> secure/protected/encrypted/trusted.
> * @resv: reservation object linked to this dma-buf
> * @poll: for userspace poll support
> * @cb_excl: for userspace poll support
> @@ -306,6 +307,7 @@ struct dma_buf {
> struct module *owner;
> struct list_head list_node;
> void *priv;
> + bool is_protected;
> struct dma_resv *resv;
>
> /* poll support */
>
> @all, @amdgpu-folks :- Is this something you can use of to denote
> secure/protected/encrypted/trusted buffers ?
I suppose. At the moment, we don't really have a need for it since we
only our IPs support our encryption scheme and if we share buffers
between we can get to the secure status when we look up the amdgpu
buffer object internally in the kernel side. Still might be useful
for cases where secure buffers get shared across drivers so we have a
generic check for secure status.
Alex
>
> The way 'is_protected' flag gets used to allocate
> secure/protected/encrypted buffers will be vendor specific.
>
> Please comment to let us know if it looks useful to non Arm folks.
> >
> > Thanks!
> > -Brian
> >
> > >
> > > >
> > > > Neil
> > > >
> > > > >
> > > > > Best regards,
> > > > > Liviu
> > > > >
> > > > >
> > > > >> -Daniel
> > > > >>
> > > > >>>
> > > > >>> --/
> > > > >>>
> > > > >>> ---
> > > > >>> include/uapi/drm/drm_fourcc.h | 9 +++++++++
> > > > >>> 1 file changed, 9 insertions(+)
> > > > >>>
> > > > >>> diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
> > > > >>> index 3feeaa3f987a..38e5e81d11fe 100644
> > > > >>> --- a/include/uapi/drm/drm_fourcc.h
> > > > >>> +++ b/include/uapi/drm/drm_fourcc.h
> > > > >>> @@ -742,6 +742,15 @@ extern "C" {
> > > > >>> */
> > > > >>> #define AFBC_FORMAT_MOD_BCH (1ULL << 11)
> > > > >>>
> > > > >>> +/*
> > > > >>> + * Protected framebuffer
> > > > >>> + *
> > > > >>> + * The framebuffer is allocated in a protected system memory which can be accessed
> > > > >>> + * via some special hardware signals from the dpu. This is used to support
> > > > >>> + * 'GRALLOC_USAGE_PROTECTED' in our framebuffer for EGL_EXT_protected_content.
> > > > >>> + */
> > > > >>> +#define DRM_FORMAT_MOD_ARM_PROTECTED fourcc_mod_code(ARM, (1ULL << 55))
> > > > >>> +
> > > > >>> /*
> > > > >>> * Allwinner tiled modifier
> > > > >>> *
> > > > >>> --
> > > > >>> 2.23.0
> > > > >>>
> > > > >>
> > > > >> --
> > > > >> Daniel Vetter
> > > > >> Software Engineer, Intel Corporation
> > > > >> http://blog.ffwll.ch
> > > > >
> > > >
> > > > _______________________________________________
> > > > dri-devel mailing list
> > > > dri-devel(a)lists.freedesktop.org
> > > > https://lists.freedesktop.org/mailman/listinfo/dri-devel
> > >
> > >
> > >
> > > --
> > > Daniel Vetter
> > > Software Engineer, Intel Corporation
> > > +41 (0) 79 365 57 48 - http://blog.ffwll.ch
On 9/29/19 3:28 AM, jun.zhang(a)intel.com wrote:
> From: zhang jun <jun.zhang(a)intel.com>
>
> we see tons of warning like:
> [ 45.846872] x86/PAT: NDK MediaCodec_:3753 map pfn RAM range req
> write-combining for [mem 0x1e7a80000-0x1e7a87fff], got write-back
> [ 45.848827] x86/PAT: .vorbis.decoder:4088 map pfn RAM range req
> write-combining for [mem 0x1e7a58000-0x1e7a58fff], got write-back
> [ 45.848875] x86/PAT: NDK MediaCodec_:3753 map pfn RAM range req
> write-combining for [mem 0x1e7a48000-0x1e7a4ffff], got write-back
> [ 45.849403] x86/PAT: .vorbis.decoder:4088 map pfn RAM range
> req write-combining for [mem 0x1e7a70000-0x1e7a70fff], got write-back
>
> check the kernel Documentation/x86/pat.txt, it says:
> A. Exporting pages to users with remap_pfn_range, io_remap_pfn_range,
> vm_insert_pfn
> Drivers wanting to export some pages to userspace do it by using
> mmap interface and a combination of
> 1) pgprot_noncached()
> 2) io_remap_pfn_range() or remap_pfn_range() or vm_insert_pfn()
> With PAT support, a new API pgprot_writecombine is being added.
> So, drivers can continue to use the above sequence, with either
> pgprot_noncached() or pgprot_writecombine() in step 1, followed by step 2.
>
> In addition, step 2 internally tracks the region as UC or WC in
> memtype list in order to ensure no conflicting mapping.
>
> Note that this set of APIs only works with IO (non RAM) regions.
> If driver ants to export a RAM region, it has to do set_memory_uc() or
> set_memory_wc() as step 0 above and also track the usage of those pages
> and use set_memory_wb() before the page is freed to free pool.
>
> the fix follow the pat document, do set_memory_wc() as step 0 and
> use the set_memory_wb() before the page is freed.
>
All this work needs to be done on the new dma-buf heap rework and I
don't think it makes sense to put it on the staging version
https://lore.kernel.org/lkml/20190906184712.91980-1-john.stultz@linaro.org/
(I also continue to question the value of uncached buffers, especially on
x86)
> Signed-off-by: he, bo <bo.he(a)intel.com>
> Signed-off-by: zhang jun <jun.zhang(a)intel.com>
> Signed-off-by: Bai, Jie A <jie.a.bai(a)intel.com>
> ---
> drivers/staging/android/ion/ion_system_heap.c | 28 ++++++++++++++++++-
> 1 file changed, 27 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c
> index b83a1d16bd89..d298b8194820 100644
> --- a/drivers/staging/android/ion/ion_system_heap.c
> +++ b/drivers/staging/android/ion/ion_system_heap.c
> @@ -13,6 +13,7 @@
> #include <linux/scatterlist.h>
> #include <linux/slab.h>
> #include <linux/vmalloc.h>
> +#include <asm/set_memory.h>
>
> #include "ion.h"
>
> @@ -134,6 +135,13 @@ static int ion_system_heap_allocate(struct ion_heap *heap,
> sg = table->sgl;
> list_for_each_entry_safe(page, tmp_page, &pages, lru) {
> sg_set_page(sg, page, page_size(page), 0);
> +
> +#ifdef CONFIG_X86
> + if (!(buffer->flags & ION_FLAG_CACHED))
> + set_memory_wc((unsigned long)page_address(sg_page(sg)),
> + PAGE_ALIGN(sg->length) >> PAGE_SHIFT);
> +#endif
> +
> sg = sg_next(sg);
> list_del(&page->lru);
> }
> @@ -162,8 +170,15 @@ static void ion_system_heap_free(struct ion_buffer *buffer)
> if (!(buffer->private_flags & ION_PRIV_FLAG_SHRINKER_FREE))
> ion_heap_buffer_zero(buffer);
>
> - for_each_sg(table->sgl, sg, table->nents, i)
> + for_each_sg(table->sgl, sg, table->nents, i) {
> +#ifdef CONFIG_X86
> + if (!(buffer->flags & ION_FLAG_CACHED))
> + set_memory_wb((unsigned long)page_address(sg_page(sg)),
> + PAGE_ALIGN(sg->length) >> PAGE_SHIFT);
> +#endif
> +
> free_buffer_page(sys_heap, buffer, sg_page(sg));
> + }
> sg_free_table(table);
> kfree(table);
> }
> @@ -316,6 +331,12 @@ static int ion_system_contig_heap_allocate(struct ion_heap *heap,
>
> buffer->sg_table = table;
>
> +#ifdef CONFIG_X86
> + if (!(buffer->flags & ION_FLAG_CACHED))
> + set_memory_wc((unsigned long)page_address(page),
> + PAGE_ALIGN(len) >> PAGE_SHIFT);
> +#endif
> +
> return 0;
>
> free_table:
> @@ -334,6 +355,11 @@ static void ion_system_contig_heap_free(struct ion_buffer *buffer)
> unsigned long pages = PAGE_ALIGN(buffer->size) >> PAGE_SHIFT;
> unsigned long i;
>
> +#ifdef CONFIG_X86
> + if (!(buffer->flags & ION_FLAG_CACHED))
> + set_memory_wb((unsigned long)page_address(page), pages);
> +#endif
> +
> for (i = 0; i < pages; i++)
> __free_page(page + i);
> sg_free_table(table);
>
On Sun, Sep 29, 2019 at 03:28:41PM +0800, jun.zhang(a)intel.com wrote:
> From: zhang jun <jun.zhang(a)intel.com>
>
> we see tons of warning like:
> [ 45.846872] x86/PAT: NDK MediaCodec_:3753 map pfn RAM range req
> write-combining for [mem 0x1e7a80000-0x1e7a87fff], got write-back
> [ 45.848827] x86/PAT: .vorbis.decoder:4088 map pfn RAM range req
> write-combining for [mem 0x1e7a58000-0x1e7a58fff], got write-back
> [ 45.848875] x86/PAT: NDK MediaCodec_:3753 map pfn RAM range req
> write-combining for [mem 0x1e7a48000-0x1e7a4ffff], got write-back
> [ 45.849403] x86/PAT: .vorbis.decoder:4088 map pfn RAM range
> req write-combining for [mem 0x1e7a70000-0x1e7a70fff], got write-back
>
> check the kernel Documentation/x86/pat.txt, it says:
> A. Exporting pages to users with remap_pfn_range, io_remap_pfn_range,
> vm_insert_pfn
> Drivers wanting to export some pages to userspace do it by using
> mmap interface and a combination of
> 1) pgprot_noncached()
> 2) io_remap_pfn_range() or remap_pfn_range() or vm_insert_pfn()
> With PAT support, a new API pgprot_writecombine is being added.
> So, drivers can continue to use the above sequence, with either
> pgprot_noncached() or pgprot_writecombine() in step 1, followed by step 2.
>
> In addition, step 2 internally tracks the region as UC or WC in
> memtype list in order to ensure no conflicting mapping.
>
> Note that this set of APIs only works with IO (non RAM) regions.
> If driver ants to export a RAM region, it has to do set_memory_uc() or
> set_memory_wc() as step 0 above and also track the usage of those pages
> and use set_memory_wb() before the page is freed to free pool.
>
> the fix follow the pat document, do set_memory_wc() as step 0 and
> use the set_memory_wb() before the page is freed.
>
> Signed-off-by: he, bo <bo.he(a)intel.com>
> Signed-off-by: zhang jun <jun.zhang(a)intel.com>
> Signed-off-by: Bai, Jie A <jie.a.bai(a)intel.com>
> ---
> drivers/staging/android/ion/ion_system_heap.c | 28 ++++++++++++++++++-
> 1 file changed, 27 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c
> index b83a1d16bd89..d298b8194820 100644
> --- a/drivers/staging/android/ion/ion_system_heap.c
> +++ b/drivers/staging/android/ion/ion_system_heap.c
> @@ -13,6 +13,7 @@
> #include <linux/scatterlist.h>
> #include <linux/slab.h>
> #include <linux/vmalloc.h>
> +#include <asm/set_memory.h>
>
> #include "ion.h"
>
> @@ -134,6 +135,13 @@ static int ion_system_heap_allocate(struct ion_heap *heap,
> sg = table->sgl;
> list_for_each_entry_safe(page, tmp_page, &pages, lru) {
> sg_set_page(sg, page, page_size(page), 0);
> +
> +#ifdef CONFIG_X86
> + if (!(buffer->flags & ION_FLAG_CACHED))
> + set_memory_wc((unsigned long)page_address(sg_page(sg)),
> + PAGE_ALIGN(sg->length) >> PAGE_SHIFT);
> +#endif
There is no way to do this without these #ifdefs? That feels odd, why
can't you just always test for this?
thanks,
greg k-h
On Sun, Sep 08, 2019 at 02:34:50PM +1000, Adam Zerella wrote:
> Using strncpy() does not always terminate the destination string.
> stracpy() is a alternative function that does, by using this new
> function we will no longer need to insert a null separator.
>
> Signed-off-by: Adam Zerella <adam.zerella(a)gmail.com>
> ---
> drivers/staging/android/ion/ion.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
> index e6b1ca141b93..17901bd626be 100644
> --- a/drivers/staging/android/ion/ion.c
> +++ b/drivers/staging/android/ion/ion.c
> @@ -433,8 +433,7 @@ static int ion_query_heaps(struct ion_heap_query *query)
> max_cnt = query->cnt;
>
> plist_for_each_entry(heap, &dev->heaps, node) {
> - strncpy(hdata.name, heap->name, MAX_HEAP_NAME);
> - hdata.name[sizeof(hdata.name) - 1] = '\0';
> + stracpy(hdata.name, heap->name, MAX_HEAP_NAME);
stracpy() only takes two arguments. This doesn't compile.
regards,
dan carpenter