On 04/12/2017 12:38 PM, Chris Wilson wrote: > On Wed, Apr 12, 2017 at 11:29:18AM -0700, Laura Abbott wrote: >> On 04/07/2017 02:25 PM, Chris Wilson wrote: >>> It is expected that processes will pass dma-buf fd between drivers, and >>> only using the fd themselves for mmaping and synchronisation ioctls. >>> However, it may be convenient for an application to read/write into the >>> dma-buf, for instance a test case to check the internal >>> dma_buf->ops->kmap interface. There may also be a small advantage to >>> avoiding the mmap() for very simple/small operations. >>> >>> Note in particular, synchronisation with the device is left to the >>> caller with an explicit DMA_BUF_IOCTL_SYNC, rather than done implicitly >>> inside the read/write, so that the user can avoid synchronisation if >>> they so choose. >>> >>> v2: Lots of little fixes, plus a real llseek() implements so that the >>> first basic little test cases work! >>> >>> Testcase: igt/prime_rw >>> Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> >>> Cc: Laura Abbott <labbott@xxxxxxxxxx> >>> Cc: Sumit Semwal <sumit.semwal@xxxxxxxxxx> >>> Cc: Daniel Vetter <daniel.vetter@xxxxxxxx> >>> Cc: Sean Paul <seanpaul@xxxxxxxxxxxx> >>> --- >>> drivers/dma-buf/dma-buf.c | 108 +++++++++++++++++++++++++++++++++++++++------- >>> 1 file changed, 93 insertions(+), 15 deletions(-) >>> >>> diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c >>> index 1ce7974a28a3..6e6e35c660c7 100644 >>> --- a/drivers/dma-buf/dma-buf.c >>> +++ b/drivers/dma-buf/dma-buf.c >>> @@ -100,28 +100,104 @@ static int dma_buf_mmap_internal(struct file *file, struct vm_area_struct *vma) >>> >>> static loff_t dma_buf_llseek(struct file *file, loff_t offset, int whence) >>> { >>> - struct dma_buf *dmabuf; >>> - loff_t base; >>> + struct dma_buf *dmabuf = file->private_data; >>> >>> if (!is_dma_buf_file(file)) >>> return -EBADF; >>> >>> - dmabuf = file->private_data; >>> + return fixed_size_llseek(file, offset, whence, dmabuf->size); >>> +} >>> >>> - /* only support discovering the end of the buffer, >>> - but also allow SEEK_SET to maintain the idiomatic >>> - SEEK_END(0), SEEK_CUR(0) pattern */ >>> - if (whence == SEEK_END) >>> - base = dmabuf->size; >>> - else if (whence == SEEK_SET) >>> - base = 0; >>> - else >>> - return -EINVAL; >>> +static ssize_t dma_buf_read(struct file *file, >>> + char __user *ubuf, size_t remain, >>> + loff_t *offset) >>> +{ >>> + struct dma_buf *dmabuf = file->private_data; >>> + unsigned long idx; >>> + unsigned int start; >>> + size_t total; >>> >>> - if (offset != 0) >>> - return -EINVAL; >>> + if (!is_dma_buf_file(file)) >>> + return -EBADF; >>> + >>> + total = 0; >>> + idx = *offset >> PAGE_SHIFT; >>> + start = offset_in_page(*offset); >>> + while (remain) { >>> + unsigned int len = min_t(size_t, remain, PAGE_SIZE - start); >>> + unsigned int copied; >>> + void *vaddr; >>> + >>> + if (*offset >= dmabuf->size) >>> + return total; >>> + >>> + vaddr = dma_buf_kmap(dmabuf, idx); >>> + if (!vaddr) >>> + return total ?: -EIO; >>> + >>> + copied = copy_to_user(ubuf, vaddr + start, len); >>> + dma_buf_kunmap(dmabuf, idx, vaddr); >>> + >>> + total += copied ?: len; >>> + if (copied) { >>> + *offset += copied; >>> + return total ?: -EFAULT; >>> + } >>> + >>> + remain -= len; >>> + *offset += len; >>> + ubuf += len; >>> + start = 0; >>> + idx++; >>> + } >>> + >>> + return total; >>> +} >>> + >>> +static ssize_t dma_buf_write(struct file *file, >>> + const char __user *ubuf, size_t remain, >>> + loff_t *offset) >>> +{ >>> + struct dma_buf *dmabuf = file->private_data; >>> + unsigned long idx; >>> + unsigned int start; >>> + size_t total; >>> + >>> + if (!is_dma_buf_file(file)) >>> + return -EBADF; >>> + >>> + total = 0; >>> + idx = *offset >> PAGE_SHIFT; >>> + start = offset_in_page(*offset); >>> + while (remain) { >>> + unsigned int len = min_t(size_t, remain, PAGE_SIZE - start); >>> + unsigned int copied; >>> + void *vaddr; >>> + >>> + if (*offset >= dmabuf->size) >>> + return total; >>> + >>> + vaddr = dma_buf_kmap(dmabuf, idx); >>> + if (!vaddr) >>> + return total ?: -EIO; >>> + >>> + copied = copy_from_user(vaddr + start, ubuf, len); >>> + dma_buf_kunmap(dmabuf, idx, vaddr); >>> + >>> + total += copied ?: len; >>> + if (copied) { >>> + *offset += copied; >>> + return total ?: -EFAULT; >>> + } >>> + >>> + remain -= len; >>> + *offset += len; >>> + ubuf += len; >>> + start = 0; >>> + idx++; >>> + } >>> >>> - return base + offset; >>> + return total; >>> } >>> >> >> Both the read/write are missing the dma_buf_begin_cpu_access calls. >> When I add those these seem to work well enough for a simple >> test. I can add a real Tested-by for the next version. > > Correct, that was intentional to leave synchronisation to be managed by > the caller. It is easier to add synchronisation than take it away. > -Chris > Ah yes, that makes sense. This is what the sync ioctls were for in the first place :). You can add Tested-by: Laura Abbott <labbott@xxxxxxxxxx> Thanks, Laura _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel