<p style="color:rgb(0,0,0)">do we need to pass the dmabuf object to dmabuf->ops->mmap(dmabuf, file,
vma)?</p><p style="color:rgb(0,0,0)">as <span style="line-height:115%;font-family:'Calibri','sans-serif';font-size:11pt">file->private_data
can retrieve the dmabuf object.</span></p>
<p style="color:rgb(0,0,0)"><span style="line-height:115%;font-family:'Calibri','sans-serif';font-size:11pt"><i style><span style="line-height:115%;font-family:'Calibri','sans-serif';font-size:11pt">"dmabuf
= file->private_data"</span></i></span></p>
<p style="color:rgb(0,0,0)"><span style="line-height:115%;font-family:'Calibri','sans-serif';font-size:11pt"><i style><span style="line-height:115%;font-family:'Calibri','sans-serif';font-size:11pt">removing
dmabuf from the function arguments will keep it consistent with basic "mmap"
definitions: </span></i></span></p>
<p style="color:rgb(0,0,0)"><span style="line-height:115%;font-family:'Calibri','sans-serif';font-size:11pt"><i style><span style="line-height:115%;font-family:'Calibri','sans-serif';font-size:11pt">"static
int xxxx_mmap(struct file *file, struct vm_area_struct
*vma)"</span></i></span></p><span style="color:rgb(0,0,0)"><span style="line-height:115%;font-family:'Calibri','sans-serif';font-size:11pt"><i style><span style="line-height:115%;font-family:'Calibri','sans-serif';font-size:11pt"></span></i></span></span><br>
<div class="gmail_quote">On Thu, Mar 15, 2012 at 10:32 AM, Rob Clark <span dir="ltr"><<a href="mailto:rob.clark@linaro.org">rob.clark@linaro.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
From: Rob Clark <<a href="mailto:rob@ti.com">rob@ti.com</a>><br>
<br>
Enable optional userspace access to dma-buf buffers via mmap() on the<br>
dma-buf file descriptor. Userspace access to the buffer should be<br>
bracketed with DMA_BUF_IOCTL_{PREPARE,FINISH}_ACCESS ioctl calls to<br>
give the exporting driver a chance to deal with cache synchronization<br>
and such for cached userspace mappings without resorting to page<br>
faulting tricks. The reasoning behind this is that, while drm<br>
drivers tend to have all the mechanisms in place for dealing with<br>
page faulting tricks, other driver subsystems may not. And in<br>
addition, while page faulting tricks make userspace simpler, there<br>
are some associated overheads.<br>
<br>
In all cases, the mmap() call is allowed to fail, and the associated<br>
dma_buf_ops are optional (mmap() will fail if at least the mmap()<br>
op is not implemented by the exporter, but in either case the<br>
{prepare,finish}_access() ops are optional).<br>
<br>
For now the prepare/finish access ioctls are kept simple with no<br>
argument, although there is possibility to add additional ioctls<br>
(or simply change the existing ioctls from _IO() to _IOW()) later<br>
to provide optimization to allow userspace to specify a region of<br>
interest.<br>
<br>
For a final patch, dma-buf.h would need to be split into what is<br>
exported to userspace, and what is kernel private, but I wanted to<br>
get feedback on the idea of requiring userspace to bracket access<br>
first (vs. limiting this to coherent mappings or exporters who play<br>
page faltings plus PTE shoot-down games) before I split the header<br>
which would cause conflicts with other pending dma-buf patches. So<br>
flame-on!<br>
---<br>
drivers/base/dma-buf.c | 42 ++++++++++++++++++++++++++++++++++++++++++<br>
include/linux/dma-buf.h | 22 ++++++++++++++++++++++<br>
2 files changed, 64 insertions(+), 0 deletions(-)<br>
<br>
diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c<br>
index c9a945f..382b78a 100644<br>
--- a/drivers/base/dma-buf.c<br>
+++ b/drivers/base/dma-buf.c<br>
@@ -30,6 +30,46 @@<br>
<br>
static inline int is_dma_buf_file(struct file *);<br>
<br>
+static int dma_buf_mmap(struct file *file, struct vm_area_struct *vma)<br>
+{<br>
+ struct dma_buf *dmabuf;<br>
+<br>
+ if (!is_dma_buf_file(file))<br>
+ return -EINVAL;<br>
+<br>
+ dmabuf = file->private_data;<br>
+<br>
+ if (dmabuf->ops->mmap)<br>
+ return dmabuf->ops->mmap(dmabuf, file, vma);<br>
+<br>
+ return -ENODEV;<br>
+}<br>
+<br>
+static long dma_buf_ioctl(struct file *file, unsigned int cmd,<br>
+ unsigned long arg)<br>
+{<br>
+ struct dma_buf *dmabuf;<br>
+<br>
+ if (!is_dma_buf_file(file))<br>
+ return -EINVAL;<br>
+<br>
+ dmabuf = file->private_data;<br>
+<br>
+ switch (_IOC_NR(cmd)) {<br>
+ case _IOC_NR(DMA_BUF_IOCTL_PREPARE_ACCESS):<br>
+ if (dmabuf->ops->prepare_access)<br>
+ return dmabuf->ops->prepare_access(dmabuf);<br>
+ return 0;<br>
+ case _IOC_NR(DMA_BUF_IOCTL_FINISH_ACCESS):<br>
+ if (dmabuf->ops->finish_access)<br>
+ return dmabuf->ops->finish_access(dmabuf);<br>
+ return 0;<br>
+ default:<br>
+ return -EINVAL;<br>
+ }<br>
+}<br>
+<br>
+<br>
static int dma_buf_release(struct inode *inode, struct file *file)<br>
{<br>
struct dma_buf *dmabuf;<br>
@@ -45,6 +85,8 @@ static int dma_buf_release(struct inode *inode, struct file *file)<br>
}<br>
<br>
static const struct file_operations dma_buf_fops = {<br>
+ .mmap = dma_buf_mmap,<br>
+ .unlocked_ioctl = dma_buf_ioctl,<br>
.release = dma_buf_release,<br>
};<br>
<br>
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h<br>
index a885b26..cbdff81 100644<br>
--- a/include/linux/dma-buf.h<br>
+++ b/include/linux/dma-buf.h<br>
@@ -34,6 +34,17 @@<br>
struct dma_buf;<br>
struct dma_buf_attachment;<br>
<br>
+/* TODO: dma-buf.h should be the userspace visible header, and dma-buf-priv.h (?)<br>
+ * the kernel internal header.. for now just stuff these here to avoid conflicting<br>
+ * with other patches..<br>
+ *<br>
+ * For now, no arg to keep things simple, but we could consider adding an<br>
+ * optional region of interest later.<br>
+ */<br>
+#define DMA_BUF_IOCTL_PREPARE_ACCESS _IO('Z', 0)<br>
+#define DMA_BUF_IOCTL_FINISH_ACCESS _IO('Z', 1)<br>
+<br>
+<br>
/**<br>
* struct dma_buf_ops - operations possible on struct dma_buf<br>
* @attach: [optional] allows different devices to 'attach' themselves to the<br>
@@ -49,6 +60,13 @@ struct dma_buf_attachment;<br>
* @unmap_dma_buf: decreases usecount of buffer, might deallocate scatter<br>
* pages.<br>
* @release: release this buffer; to be called after the last dma_buf_put.<br>
+ * @mmap: [optional, allowed to fail] operation called if userspace calls<br>
+ * mmap() on the dmabuf fd. Note that userspace should use the<br>
+ * DMA_BUF_PREPARE_ACCESS / DMA_BUF_FINISH_ACCESS ioctls before/after<br>
+ * sw access to the buffer, to give the exporter an opportunity to<br>
+ * deal with cache maintenance.<br>
+ * @prepare_access: [optional] handler for PREPARE_ACCESS ioctl.<br>
+ * @finish_access: [optional] handler for FINISH_ACCESS ioctl.<br>
*/<br>
struct dma_buf_ops {<br>
int (*attach)(struct dma_buf *, struct device *,<br>
@@ -72,6 +90,10 @@ struct dma_buf_ops {<br>
/* after final dma_buf_put() */<br>
void (*release)(struct dma_buf *);<br>
<br>
+ int (*mmap)(struct dma_buf *, struct file *, struct vm_area_struct *);<br>
+ int (*prepare_access)(struct dma_buf *);<br>
+ int (*finish_access)(struct dma_buf *);<br>
+<br>
};<br>
<br>
/**<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.7.5.4<br>
<br>
<br>
_______________________________________________<br>
Linaro-mm-sig mailing list<br>
<a href="mailto:Linaro-mm-sig@lists.linaro.org">Linaro-mm-sig@lists.linaro.org</a><br>
<a href="http://lists.linaro.org/mailman/listinfo/linaro-mm-sig" target="_blank">http://lists.linaro.org/mailman/listinfo/linaro-mm-sig</a><br>
</font></span></blockquote></div><br>