On Fri, Mar 16, 2012 at 12:24 PM, Tom Cooksey <tom.cooksey(a)arm.com> wrote:
>
>> From: Rob Clark <rob(a)ti.com>
>>
>> Enable optional userspace access to dma-buf buffers via mmap() on the
>> dma-buf file descriptor. Userspace access to the buffer should be
>> bracketed with DMA_BUF_IOCTL_{PREPARE,FINISH}_ACCESS ioctl calls to
>> give the exporting driver a chance to deal with cache synchronization
>> and such for cached userspace mappings without resorting to page
>> faulting tricks. The reasoning behind this is that, while drm
>> drivers tend to have all the mechanisms in place for dealing with
>> page faulting tricks, other driver subsystems may not. And in
>> addition, while page faulting tricks make userspace simpler, there
>> are some associated overheads.
>
> Speaking for the ARM Mali T6xx driver point of view, this API looks
> good for us. Our use-case for mmap is glReadPixels and
> glTex[Sub]Image2D on buffers the driver has imported via dma_buf. In
> the case of glReadPixels, the finish ioctl isn't strictly necessary
> as the CPU won't have written to the buffer and so doesn't need
> flushing. As such, we'd get an additional cache flush which isn't
> really necessary. But hey, it's glReadPixels - it's supposed to be
> slow. :-)
>
> I think requiring the finish ioctl in the API contract is a good
> idea, even if the CPU has only done a ro access as it allows future
> enhancements*. To "fix" the unnecessary flush in glReadPixels, I
> think we'd like to keep the finish but see an "access type"
> parameter added to prepare ioctl indicating if the access is ro or
> rw to allow the cache flush in finish to be skipped if the access
> was ro. As Rebecca says, a debug feature could even be added to
> re-map the pages as ro in prepare(ro) to catch naughty accesses. I'd
> also go as far as to say the debug feature should completely unmap
> the pages after finish too. Though for us, both the access-type
> parameter and debug features are "nice to haves" - we can make
> progress with the code as it currently stands (assuming exporters
> start using the API that is).
Perhaps it isn't a bad idea to include access-type bitmask in the
first version. It would help optimize a bit the cache operations.
> Something which also came up when discussing internally is the topic
> of mmap APIs of the importing device driver. For example, I believe
> DRM has an mmap API on GEM buffer objects. If a new dma_buf import
> ioctl was added to GEM (maybe the PRIME patches already add this),
> how would GEM's bo mmap API work?
My first thought is maybe we should just dis-allow this for now until
we have a chance to see if there are any possible issues with an
importer mmap'ing the buffer to userspace. We could possible have a
helper dma_buf_mmap() fxn which in turn calls dmabuf ops->mmap() so
the mmap'ing is actually performed by the exporter on behalf of the
importer.
>
> * Future enhancements: The prepare/finish bracketing could be used
> as part of a wider synchronization scheme with other devices.
> E.g. If another device was writing to the buffer, the prepare ioctl
> could block until that device had finished accessing that buffer.
> In the same way, another device could be blocked from accessing that
> buffer until the client process called finish. We have already
> started playing with such a scheme in the T6xx driver stack we're
> terming "kernel dependency system". In this scheme each buffer has a
> FIFO of "buffer consumers" waiting to access a buffer. The idea
> being that a "buffer consumer" is fairly abstract and could be any
> device or userspace process participating in the synchronization
> scheme. Examples would be GPU jobs, display controller "scan-out"
> jobs, etc.
>
> So for example, a userspace application could dispatch a GPU
> fragment shading job into the GPU's kernel driver which will write
> to a KMS scanout buffer. The application then immediately issues a
> drm_mode_crtc_page_flip ioctl on the display controller's DRM driver
> to display the soon-to-be-rendered buffer. Inside the kernel, the
> GPU driver adds the fragment job to the dma_buf's FIFO. As the FIFO
> was empty, dma_buf calls into the GPU kernel driver to tell it it
> "owns" access to the buffer and the GPU driver schedules the job to
> run on the GPU. Upon receiving the drm_mode_crtc_page_flip ioctl,
> the DRM/KMS driver adds a scan-out job to the buffer's FIFO.
> However, the FIFO already has the GPU's fragment shading job in it
> so nothing happens until the GPU job completes. When the GPU job
> completes, the GPU driver calls into dma_buf to mark its job
> complete. dma_buf then takes the next job in its FIFO which the KMS
> driver's scanout job, calls into the KMS driver to schedule the
> pageflip. The result? A buffer gets scanned out as soon as it has
> finished being rendered without needing a round-trip to userspace.
> Sure, there are easier ways to achieve that goal, but the idea is
> that the mechanism can be used to synchronize access across multiple
> devices, which makes it useful for lots of other use-cases too.
>
>
> As I say, we have already implemented something which works as I
> describe but where the buffers are abstract resources not linked to
> dma_buf. I'd like to discuss the finer points of the mechanisms
> further, but if it's looking like there's interest in this approach
> we'll start re-writing the code we have to sit on-top of dma_buf
> and posting it as RFCs to the various lists. The intention is to get
> this to mainline, if mainline wants it. :-)
I think we do need some sort of 'sync object' (which might really just
be a 'synchronization queue' object) in the kernel. It probably
shouldn't be built-in to dma-buf, but I expect we'd want the dma_buf
struct to have a 'struct sync_queue *' (or whatever it ends up being
called).
The sync-queue seems like a reasonable approach for pure cpu-sw based
synchronization. The only thing I'm not sure is how to also deal with
hw that supports any sort of auto synchronization without cpu sw
involvement.
BR,
-R
> Personally, what I particularly like about this approach to
> synchronization is that it doesn't require any interfaces to be
> modified. I think/hope that makes it easier to port existing drivers
> and sub-systems to take advantage of it. The buffer itself is the
> synchronization object and interfaces already pass buffers around so
> don't need modification. There are of course some limitations with
> this approach, the main one we can think of being that it can't
> really be used for A/V sync. It kinda assumes "jobs" in the FIFO
> should be run as soon as the preceding job completes, which isn't
> the case when streaming real-time video. Though nothing precludes
> more explicit sync objects being used in conjunction with this
> approach.
>
>
> Cheers,
>
> Tom
>
>
>
>
>
> _______________________________________________
> dri-devel mailing list
> dri-devel(a)lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
From: Rob Clark <rob(a)ti.com>
Enable optional userspace access to dma-buf buffers via mmap() on the
dma-buf file descriptor. Userspace access to the buffer should be
bracketed with DMA_BUF_IOCTL_{PREPARE,FINISH}_ACCESS ioctl calls to
give the exporting driver a chance to deal with cache synchronization
and such for cached userspace mappings without resorting to page
faulting tricks. The reasoning behind this is that, while drm
drivers tend to have all the mechanisms in place for dealing with
page faulting tricks, other driver subsystems may not. And in
addition, while page faulting tricks make userspace simpler, there
are some associated overheads.
In all cases, the mmap() call is allowed to fail, and the associated
dma_buf_ops are optional (mmap() will fail if at least the mmap()
op is not implemented by the exporter, but in either case the
{prepare,finish}_access() ops are optional).
For now the prepare/finish access ioctls are kept simple with no
argument, although there is possibility to add additional ioctls
(or simply change the existing ioctls from _IO() to _IOW()) later
to provide optimization to allow userspace to specify a region of
interest.
For a final patch, dma-buf.h would need to be split into what is
exported to userspace, and what is kernel private, but I wanted to
get feedback on the idea of requiring userspace to bracket access
first (vs. limiting this to coherent mappings or exporters who play
page faltings plus PTE shoot-down games) before I split the header
which would cause conflicts with other pending dma-buf patches. So
flame-on!
---
drivers/base/dma-buf.c | 42 ++++++++++++++++++++++++++++++++++++++++++
include/linux/dma-buf.h | 22 ++++++++++++++++++++++
2 files changed, 64 insertions(+), 0 deletions(-)
diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c
index c9a945f..382b78a 100644
--- a/drivers/base/dma-buf.c
+++ b/drivers/base/dma-buf.c
@@ -30,6 +30,46 @@
static inline int is_dma_buf_file(struct file *);
+static int dma_buf_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct dma_buf *dmabuf;
+
+ if (!is_dma_buf_file(file))
+ return -EINVAL;
+
+ dmabuf = file->private_data;
+
+ if (dmabuf->ops->mmap)
+ return dmabuf->ops->mmap(dmabuf, file, vma);
+
+ return -ENODEV;
+}
+
+static long dma_buf_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct dma_buf *dmabuf;
+
+ if (!is_dma_buf_file(file))
+ return -EINVAL;
+
+ dmabuf = file->private_data;
+
+ switch (_IOC_NR(cmd)) {
+ case _IOC_NR(DMA_BUF_IOCTL_PREPARE_ACCESS):
+ if (dmabuf->ops->prepare_access)
+ return dmabuf->ops->prepare_access(dmabuf);
+ return 0;
+ case _IOC_NR(DMA_BUF_IOCTL_FINISH_ACCESS):
+ if (dmabuf->ops->finish_access)
+ return dmabuf->ops->finish_access(dmabuf);
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+
static int dma_buf_release(struct inode *inode, struct file *file)
{
struct dma_buf *dmabuf;
@@ -45,6 +85,8 @@ static int dma_buf_release(struct inode *inode, struct file *file)
}
static const struct file_operations dma_buf_fops = {
+ .mmap = dma_buf_mmap,
+ .unlocked_ioctl = dma_buf_ioctl,
.release = dma_buf_release,
};
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
index a885b26..cbdff81 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -34,6 +34,17 @@
struct dma_buf;
struct dma_buf_attachment;
+/* TODO: dma-buf.h should be the userspace visible header, and dma-buf-priv.h (?)
+ * the kernel internal header.. for now just stuff these here to avoid conflicting
+ * with other patches..
+ *
+ * For now, no arg to keep things simple, but we could consider adding an
+ * optional region of interest later.
+ */
+#define DMA_BUF_IOCTL_PREPARE_ACCESS _IO('Z', 0)
+#define DMA_BUF_IOCTL_FINISH_ACCESS _IO('Z', 1)
+
+
/**
* struct dma_buf_ops - operations possible on struct dma_buf
* @attach: [optional] allows different devices to 'attach' themselves to the
@@ -49,6 +60,13 @@ struct dma_buf_attachment;
* @unmap_dma_buf: decreases usecount of buffer, might deallocate scatter
* pages.
* @release: release this buffer; to be called after the last dma_buf_put.
+ * @mmap: [optional, allowed to fail] operation called if userspace calls
+ * mmap() on the dmabuf fd. Note that userspace should use the
+ * DMA_BUF_PREPARE_ACCESS / DMA_BUF_FINISH_ACCESS ioctls before/after
+ * sw access to the buffer, to give the exporter an opportunity to
+ * deal with cache maintenance.
+ * @prepare_access: [optional] handler for PREPARE_ACCESS ioctl.
+ * @finish_access: [optional] handler for FINISH_ACCESS ioctl.
*/
struct dma_buf_ops {
int (*attach)(struct dma_buf *, struct device *,
@@ -72,6 +90,10 @@ struct dma_buf_ops {
/* after final dma_buf_put() */
void (*release)(struct dma_buf *);
+ int (*mmap)(struct dma_buf *, struct file *, struct vm_area_struct *);
+ int (*prepare_access)(struct dma_buf *);
+ int (*finish_access)(struct dma_buf *);
+
};
/**
--
1.7.5.4
Just wondering how we expect userspace to use dma-buf/prime interfaces.
Currently I see one driver in sharing the buffer with handle->fd, then
passing the fd to the other driver and it using fd->handle, do we then
expect the importing driver to close the fd?
Dave.
From: benjamin gaignard <benjamin.gaignard(a)linaro.org>
The goal of those patches is to allow ION clients (drivers or userland applications)
to use Contiguous Memory Allocator (CMA).
To get more info about CMA:
http://lists.linaro.org/pipermail/linaro-mm-sig/2012-February/001328.html
patches version 3:
- add a private field in ion_heap structure instead of expose ion_device
structure to all heaps
- ion_cma_heap is no more a platform driver
- ion_cma_heap use ion_heap private field to store the device pointer and
make the link with reserved CMA regions
- provide ux500-ion driver and configuration file for snowball board to give
an example of how use CMA heaps
patches version 2:
- fix comments done by Andy Green
Benjamin Gaignard (1):
fix ion_platform_data definition
add private field in ion_heap structure
add CMA heap
add test/example driver for ux500 platform
arch/arm/mach-ux500/board-mop500.c | 80 +++++++++++++++++++
drivers/gpu/ion/Kconfig | 6 ++
drivers/gpu/ion/Makefile | 2 +
drivers/gpu/ion/cma/Makefile | 1 +
drivers/gpu/ion/cma/ion_cma_heap.c | 126 ++++++++++++++++++++++++++++++
drivers/gpu/ion/cma/ion_cma_heap.h | 11 +++
drivers/gpu/ion/ion_priv.h | 2 +
drivers/gpu/ion/ux500/Makefile | 1 +
drivers/gpu/ion/ux500/ux500_ion.c | 147 ++++++++++++++++++++++++++++++++++++
include/linux/ion.h | 2 +-
10 files changed, 377 insertions(+), 1 deletions(-)
create mode 100644 drivers/gpu/ion/cma/Makefile
create mode 100644 drivers/gpu/ion/cma/ion_cma_heap.c
create mode 100644 drivers/gpu/ion/cma/ion_cma_heap.h
create mode 100644 drivers/gpu/ion/ux500/Makefile
create mode 100644 drivers/gpu/ion/ux500/ux500_ion.c
From: benjamin gaignard <benjamin.gaignard(a)linaro.org>
The goal of those patches is to allow ION clients (drivers or userland applications)
to use Contiguous Memory Allocator (CMA).
To get more info about CMA:
http://lists.linaro.org/pipermail/linaro-mm-sig/2012-February/001328.html
patches version 2:
fix comments done by Andy Green
Benjamin Gaignard (3):
make struct ion_device available for other heap
fix ion_platform_data definition
add CMA heap
drivers/gpu/ion/Kconfig | 5 +
drivers/gpu/ion/Makefile | 1 +
drivers/gpu/ion/cma/Makefile | 1 +
drivers/gpu/ion/cma/ion_cma_heap.c | 217 ++++++++++++++++++++++++++++++++++++
drivers/gpu/ion/ion.c | 20 ----
drivers/gpu/ion/ion_priv.h | 22 ++++
include/linux/ion.h | 2 +-
7 files changed, 247 insertions(+), 21 deletions(-)
create mode 100644 drivers/gpu/ion/cma/Makefile
create mode 100644 drivers/gpu/ion/cma/ion_cma_heap.c
Hi Stephen,
May I request you to please add the dma-buf buffer sharing framework
tree to linux-next?
It is hosted here
git://git.linaro.org/people/sumitsemwal/linux-dma-buf.git
branch: for-next
--
Thanks and nest regards,
Sumit Semwal.
Hi all,
This series here implements an interface to enable cpu access from the kernel
context to dma_buf objects. The main design goal of this interface proposal is
to enable buffer objects that reside in highmem.
Comments, flames, ideas and questions highly welcome. Althouhg I might be a bit
slow in responding - I'm on conferences and vacation the next 2 weeks.
Cheers, Daniel
Daniel Vetter (3):
dma-buf: don't hold the mutex around map/unmap calls
dma-buf: add support for kernel cpu access
dma_buf: Add documentation for the new cpu access support
Documentation/dma-buf-sharing.txt | 102 +++++++++++++++++++++++++++++-
drivers/base/dma-buf.c | 124 +++++++++++++++++++++++++++++++++++-
include/linux/dma-buf.h | 62 ++++++++++++++++++-
3 files changed, 280 insertions(+), 8 deletions(-)
--
1.7.7.5
Hi all,
Since the inclusion of dma-buf buffer sharing framework in 3.3 (thanks
to Dave Airlie primarily), I have been volunteered to be its
maintainer.
Obviously there is a need for some simple rules about the dma-buf
feature tree, so here we are:
- there will be a 'for-next' branch for (N+1), which will open around
-Nrc1, and close about 1-2 weeks before the (N+1)merge opens.
- there will be a 'fixes' branch, which will take fixes after the
for-next pull request is sent upstream.
- after -rc2, regression fixes only.
- after -rc4/5, only revert and disable patches. The real fix should
then be targeted at for-next.
- to stop me from pushing useless stuff, I will merge my own patches
only after sufficient review on our mailing lists. If you see me
breaking this rule, please shout out at me _publicly_ at the top of
your voice.
Being a 'first-time-maintainer', I am very willing to learn
on-the-job, though I might still take cover under the
'first-time-maintainer' umbrella [for sometime :)] for any stupid acts
I might commit.
The tree resides at: git://git.linaro.org/people/sumitsemwal/linux-dma-buf.git
At present, the mailing lists are: linux-media(a)vger.kernel.org,
dri-devel(a)lists.freedesktop.org, linaro-mm-sig(a)lists.linaro.org, in
addition to lkml.
Comments, flames and suggestions highly welcome.
(I have been 'influenced' quite a bit from Daniel Vetter's model for
the drm/i915 -next tree [thank you, DanVet!], but any errors/omissions
are entirely mine.)
Thanks and regards,
~Sumit.