On Thu, Mar 15, 2012 at 2:16 AM, Abhinav Kochhar <kochhar.abhinav@xxxxxxxxx> 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@xxxxxxxxxx> wrote: >> >> From: Rob Clark <rob@xxxxxx> >> >> 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@xxxxxxxxxxxxxxxx >> http://lists.linaro.org/mailman/listinfo/linaro-mm-sig > > _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel