All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chris Wilson <chris@chris-wilson.co.uk>
To: dri-devel@lists.freedesktop.org
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>,
	intel-gfx@lists.freedesktop.org,
	Sean Paul <seanpaul@chromium.org>,
	Laura Abbott <labbott@redhat.com>,
	Sumit Semwal <sumit.semwal@linaro.org>
Subject: [PATCH] dma-buf: Implement simple read/write vfs ops
Date: Thu, 19 Sep 2019 16:08:53 +0100	[thread overview]
Message-ID: <20190919150853.18181-1-chris@chris-wilson.co.uk> (raw)

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.

"It is easier to add synchronisation later, than it is to take it away."

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@chris-wilson.co.uk>
Cc: Laura Abbott <labbott@redhat.com>
Cc: Sumit Semwal <sumit.semwal@linaro.org>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Sean Paul <seanpaul@chromium.org>
Cc: Janusz Krzysztofik <janusz.krzysztofik@linux.intel.com>
Tested-by: Laura Abbott <labbott@redhat.com>
---
Dusting this off again as it would be nice as a user to operate on dmabuf
agnostic to the underyling driver. We have mmap, so naturally we would
like to have read/write as well!
---
 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 433d91d710e4..a19fc881a99c 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -135,28 +135,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;
 }
 
 /**
@@ -413,6 +489,8 @@ static const struct file_operations dma_buf_fops = {
 	.release	= dma_buf_release,
 	.mmap		= dma_buf_mmap_internal,
 	.llseek		= dma_buf_llseek,
+	.read		= dma_buf_read,
+	.write		= dma_buf_write,
 	.poll		= dma_buf_poll,
 	.unlocked_ioctl	= dma_buf_ioctl,
 #ifdef CONFIG_COMPAT
-- 
2.23.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

             reply	other threads:[~2019-09-19 15:08 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-09-19 15:08 Chris Wilson [this message]
2019-09-19 15:28 ` [PATCH] dma-buf: Implement simple read/write vfs ops Daniel Vetter
2019-09-19 15:52   ` Chris Wilson
2019-09-19 16:18     ` Daniel Vetter
2019-09-19 20:22 ` ✗ Fi.CI.BAT: failure for " Patchwork
  -- strict thread matches above, loose matches on Subject: below --
2017-04-07 19:32 [PATCH] " Chris Wilson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190919150853.18181-1-chris@chris-wilson.co.uk \
    --to=chris@chris-wilson.co.uk \
    --cc=daniel.vetter@ffwll.ch \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=labbott@redhat.com \
    --cc=seanpaul@chromium.org \
    --cc=sumit.semwal@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.