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 -- Chris Wilson, Intel Open Source Technology Centre _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel