On Thu, Mar 15, 2012 at 2:16 AM, Abhinav Kochhar
<kochhar.abhinav at gmail.com> wrote:
> do we need to pass the dmabuf object to dmabuf->ops->mmap(dmabuf, file,
> vma)?
>
> as file->private_data can retrieve the dmabuf object.
>
> "dmabuf = file->private_data"
>
> removing dmabuf from the function arguments will keep it consistent with
> basic "mmap" definitions:
>
> "static int xxxx_mmap(struct file *file, struct vm_area_struct *vma)"
>

This was intentional to deviate from standard mmap fxn signature..  it
was to avoid encouraging incorrect use.

What I mean is, most subsystems interested in participating in dmabuf
support mmap'ing multiple buffers on a single chrdev, with some
offset->object mapping mechanism.  But in the case of a dmabuf fd, the
buffer userspace would mmap would be at offset=0.  So you wouldn't get
the expected results if you just directly plugged v4l2_mmap or
drm_gem_mmap, etc, into your dmabuf-ops.  Not to mention the
file->file_private wouldn't be what you expected.  So basically I was
just trying to follow principle-of-least-surprise ;-)

BR,
-R

> On Thu, Mar 15, 2012 at 10:32 AM, Rob Clark <rob.clark at linaro.org> wrote:
>>
>> From: Rob Clark <rob at 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
>>
>>
>> _______________________________________________
>> Linaro-mm-sig mailing list
>> Linaro-mm-sig at lists.linaro.org
>> http://lists.linaro.org/mailman/listinfo/linaro-mm-sig
>
>

Reply via email to