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 <ch...@chris-wilson.co.uk>
> > Cc: Laura Abbott <labb...@redhat.com>
> > Cc: Sumit Semwal <sumit.sem...@linaro.org>
> > Cc: Daniel Vetter <daniel.vet...@ffwll.ch>
> > Cc: Sean Paul <seanp...@chromium.org>
> > ---
> >  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@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to