From: Paul Cercueil <paul@crapouillou.net>
To: Jonathan Cameron <jic23@kernel.org>
Cc: "Alexandru Ardelean" <ardeleanalex@gmail.com>,
"Lars-Peter Clausen" <lars@metafoo.de>,
"Michael Hennerich" <Michael.Hennerich@analog.com>,
"Sumit Semwal" <sumit.semwal@linaro.org>,
"Christian König" <christian.koenig@amd.com>,
linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org,
linaro-mm-sig@lists.linaro.org,
"Paul Cercueil" <paul@crapouillou.net>
Subject: [PATCH 09/15] iio: buffer-dma: Use DMABUFs instead of custom solution
Date: Mon, 15 Nov 2021 14:19:19 +0000 [thread overview]
Message-ID: <20211115141925.60164-10-paul@crapouillou.net> (raw)
In-Reply-To: <20211115141925.60164-1-paul@crapouillou.net>
Enhance the current fileio code by using DMABUF objects instead of
custom buffers.
This adds more code than it removes, but:
- a lot of the complexity can be dropped, e.g. custom kref and
iio_buffer_block_put_atomic() are not needed anymore;
- it will be much easier to introduce an API to export these DMABUF
objects to userspace in a following patch.
Signed-off-by: Paul Cercueil <paul@crapouillou.net>
---
drivers/iio/buffer/industrialio-buffer-dma.c | 196 ++++++++++++-------
include/linux/iio/buffer-dma.h | 8 +-
2 files changed, 127 insertions(+), 77 deletions(-)
diff --git a/drivers/iio/buffer/industrialio-buffer-dma.c b/drivers/iio/buffer/industrialio-buffer-dma.c
index eb8cfd3af030..adb20434f2d2 100644
--- a/drivers/iio/buffer/industrialio-buffer-dma.c
+++ b/drivers/iio/buffer/industrialio-buffer-dma.c
@@ -14,6 +14,7 @@
#include <linux/poll.h>
#include <linux/iio/buffer_impl.h>
#include <linux/iio/buffer-dma.h>
+#include <linux/dma-buf.h>
#include <linux/dma-mapping.h>
#include <linux/sizes.h>
@@ -90,104 +91,150 @@
* callback is called from within the custom callback.
*/
-static void iio_buffer_block_release(struct kref *kref)
-{
- struct iio_dma_buffer_block *block = container_of(kref,
- struct iio_dma_buffer_block, kref);
-
- WARN_ON(block->state != IIO_BLOCK_STATE_DEAD);
-
- dma_free_coherent(block->queue->dev, PAGE_ALIGN(block->size),
- block->vaddr, block->phys_addr);
-
- iio_buffer_put(&block->queue->buffer);
- kfree(block);
-}
-
-static void iio_buffer_block_get(struct iio_dma_buffer_block *block)
-{
- kref_get(&block->kref);
-}
-
-static void iio_buffer_block_put(struct iio_dma_buffer_block *block)
-{
- kref_put(&block->kref, iio_buffer_block_release);
-}
-
-/*
- * dma_free_coherent can sleep, hence we need to take some special care to be
- * able to drop a reference from an atomic context.
- */
-static LIST_HEAD(iio_dma_buffer_dead_blocks);
-static DEFINE_SPINLOCK(iio_dma_buffer_dead_blocks_lock);
-
-static void iio_dma_buffer_cleanup_worker(struct work_struct *work)
-{
- struct iio_dma_buffer_block *block, *_block;
- LIST_HEAD(block_list);
-
- spin_lock_irq(&iio_dma_buffer_dead_blocks_lock);
- list_splice_tail_init(&iio_dma_buffer_dead_blocks, &block_list);
- spin_unlock_irq(&iio_dma_buffer_dead_blocks_lock);
-
- list_for_each_entry_safe(block, _block, &block_list, head)
- iio_buffer_block_release(&block->kref);
-}
-static DECLARE_WORK(iio_dma_buffer_cleanup_work, iio_dma_buffer_cleanup_worker);
-
-static void iio_buffer_block_release_atomic(struct kref *kref)
-{
+struct iio_buffer_dma_buf_attachment {
+ struct scatterlist sgl;
+ struct sg_table sg_table;
struct iio_dma_buffer_block *block;
- unsigned long flags;
-
- block = container_of(kref, struct iio_dma_buffer_block, kref);
-
- spin_lock_irqsave(&iio_dma_buffer_dead_blocks_lock, flags);
- list_add_tail(&block->head, &iio_dma_buffer_dead_blocks);
- spin_unlock_irqrestore(&iio_dma_buffer_dead_blocks_lock, flags);
-
- schedule_work(&iio_dma_buffer_cleanup_work);
-}
-
-/*
- * Version of iio_buffer_block_put() that can be called from atomic context
- */
-static void iio_buffer_block_put_atomic(struct iio_dma_buffer_block *block)
-{
- kref_put(&block->kref, iio_buffer_block_release_atomic);
-}
+};
static struct iio_dma_buffer_queue *iio_buffer_to_queue(struct iio_buffer *buf)
{
return container_of(buf, struct iio_dma_buffer_queue, buffer);
}
+static struct iio_buffer_dma_buf_attachment *
+to_iio_buffer_dma_buf_attachment(struct sg_table *table)
+{
+ return container_of(table, struct iio_buffer_dma_buf_attachment, sg_table);
+}
+
+static void iio_buffer_block_get(struct iio_dma_buffer_block *block)
+{
+ get_dma_buf(block->dmabuf);
+}
+
+static void iio_buffer_block_put(struct iio_dma_buffer_block *block)
+{
+ dma_buf_put(block->dmabuf);
+}
+
+static int iio_buffer_dma_buf_attach(struct dma_buf *dbuf,
+ struct dma_buf_attachment *at)
+{
+ at->priv = dbuf->priv;
+
+ return 0;
+}
+
+static struct sg_table *iio_buffer_dma_buf_map(struct dma_buf_attachment *at,
+ enum dma_data_direction dma_dir)
+{
+ struct iio_dma_buffer_block *block = at->priv;
+ struct iio_buffer_dma_buf_attachment *dba;
+ int ret;
+
+ dba = kzalloc(sizeof(*dba), GFP_KERNEL);
+ if (!dba)
+ return ERR_PTR(-ENOMEM);
+
+ sg_init_one(&dba->sgl, block->vaddr, PAGE_ALIGN(block->size));
+ dba->sg_table.sgl = &dba->sgl;
+ dba->sg_table.nents = 1;
+ dba->block = block;
+
+ ret = dma_map_sgtable(at->dev, &dba->sg_table, dma_dir, 0);
+ if (ret) {
+ kfree(dba);
+ return ERR_PTR(ret);
+ }
+
+ return &dba->sg_table;
+}
+
+static void iio_buffer_dma_buf_unmap(struct dma_buf_attachment *at,
+ struct sg_table *sg_table,
+ enum dma_data_direction dma_dir)
+{
+ struct iio_buffer_dma_buf_attachment *dba =
+ to_iio_buffer_dma_buf_attachment(sg_table);
+
+ dma_unmap_sgtable(at->dev, &dba->sg_table, dma_dir, 0);
+ kfree(dba);
+}
+
+static void iio_buffer_dma_buf_release(struct dma_buf *dbuf)
+{
+ struct iio_dma_buffer_block *block = dbuf->priv;
+ struct iio_dma_buffer_queue *queue = block->queue;
+
+ WARN_ON(block->state != IIO_BLOCK_STATE_DEAD);
+
+ mutex_lock(&queue->lock);
+
+ dma_free_coherent(queue->dev, PAGE_ALIGN(block->size),
+ block->vaddr, block->phys_addr);
+
+ kfree(block);
+
+ mutex_unlock(&queue->lock);
+ iio_buffer_put(&queue->buffer);
+}
+
+
+static const struct dma_buf_ops iio_dma_buffer_dmabuf_ops = {
+ .attach = iio_buffer_dma_buf_attach,
+ .map_dma_buf = iio_buffer_dma_buf_map,
+ .unmap_dma_buf = iio_buffer_dma_buf_unmap,
+ .release = iio_buffer_dma_buf_release,
+};
+
static struct iio_dma_buffer_block *iio_dma_buffer_alloc_block(
struct iio_dma_buffer_queue *queue, size_t size)
{
struct iio_dma_buffer_block *block;
+ DEFINE_DMA_BUF_EXPORT_INFO(einfo);
+ struct dma_buf *dmabuf;
+ int err;
block = kzalloc(sizeof(*block), GFP_KERNEL);
if (!block)
- return NULL;
+ return ERR_PTR(-ENOMEM);
block->vaddr = dma_alloc_coherent(queue->dev, PAGE_ALIGN(size),
&block->phys_addr, GFP_KERNEL);
if (!block->vaddr) {
- kfree(block);
- return NULL;
+ err = -ENOMEM;
+ goto err_free_block;
}
+ einfo.ops = &iio_dma_buffer_dmabuf_ops;
+ einfo.size = PAGE_ALIGN(size);
+ einfo.priv = block;
+ einfo.flags = O_RDWR;
+
+ dmabuf = dma_buf_export(&einfo);
+ if (IS_ERR(dmabuf)) {
+ err = PTR_ERR(dmabuf);
+ goto err_free_dma;
+ }
+
+ block->dmabuf = dmabuf;
block->size = size;
block->bytes_used = size;
block->state = IIO_BLOCK_STATE_DONE;
block->queue = queue;
INIT_LIST_HEAD(&block->head);
- kref_init(&block->kref);
iio_buffer_get(&queue->buffer);
return block;
+
+err_free_dma:
+ dma_free_coherent(queue->dev, PAGE_ALIGN(size),
+ block->vaddr, block->phys_addr);
+err_free_block:
+ kfree(block);
+ return ERR_PTR(err);
}
static void _iio_dma_buffer_block_done(struct iio_dma_buffer_block *block)
@@ -224,7 +271,7 @@ void iio_dma_buffer_block_done(struct iio_dma_buffer_block *block)
_iio_dma_buffer_block_done(block);
spin_unlock_irqrestore(&queue->list_lock, flags);
- iio_buffer_block_put_atomic(block);
+ iio_buffer_block_put(block);
iio_dma_buffer_queue_wake(queue);
}
EXPORT_SYMBOL_GPL(iio_dma_buffer_block_done);
@@ -250,7 +297,8 @@ void iio_dma_buffer_block_list_abort(struct iio_dma_buffer_queue *queue,
list_del(&block->head);
block->bytes_used = 0;
_iio_dma_buffer_block_done(block);
- iio_buffer_block_put_atomic(block);
+
+ iio_buffer_block_put(block);
}
spin_unlock_irqrestore(&queue->list_lock, flags);
@@ -340,11 +388,13 @@ int iio_dma_buffer_request_update(struct iio_buffer *buffer)
if (!block) {
block = iio_dma_buffer_alloc_block(queue, size);
- if (!block) {
- ret = -ENOMEM;
+ if (IS_ERR(block)) {
+ ret = PTR_ERR(block);
goto out_unlock;
}
queue->fileio.blocks[i] = block;
+
+ iio_buffer_block_get(block);
}
if (queue->buffer.direction == IIO_BUFFER_DIRECTION_IN)
diff --git a/include/linux/iio/buffer-dma.h b/include/linux/iio/buffer-dma.h
index 09c07d5563c0..22effd6cfbb6 100644
--- a/include/linux/iio/buffer-dma.h
+++ b/include/linux/iio/buffer-dma.h
@@ -8,7 +8,6 @@
#define __INDUSTRIALIO_DMA_BUFFER_H__
#include <linux/list.h>
-#include <linux/kref.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/iio/buffer_impl.h>
@@ -16,6 +15,7 @@
struct iio_dma_buffer_queue;
struct iio_dma_buffer_ops;
struct device;
+struct dma_buf;
/**
* enum iio_block_state - State of a struct iio_dma_buffer_block
@@ -41,8 +41,8 @@ enum iio_block_state {
* @vaddr: Virutal address of the blocks memory
* @phys_addr: Physical address of the blocks memory
* @queue: Parent DMA buffer queue
- * @kref: kref used to manage the lifetime of block
* @state: Current state of the block
+ * @dmabuf: Underlying DMABUF object
*/
struct iio_dma_buffer_block {
/* May only be accessed by the owner of the block */
@@ -58,13 +58,13 @@ struct iio_dma_buffer_block {
size_t size;
struct iio_dma_buffer_queue *queue;
- /* Must not be accessed outside the core. */
- struct kref kref;
/*
* Must not be accessed outside the core. Access needs to hold
* queue->list_lock if the block is not owned by the core.
*/
enum iio_block_state state;
+
+ struct dma_buf *dmabuf;
};
/**
--
2.33.0
next prev parent reply other threads:[~2021-11-15 14:25 UTC|newest]
Thread overview: 59+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-11-15 14:19 [PATCH 00/15] iio: buffer-dma: write() and new DMABUF based API Paul Cercueil
2021-11-15 14:19 ` [PATCH 01/15] iio: buffer-dma: Get rid of incoming/outgoing queues Paul Cercueil
2021-11-16 8:23 ` Alexandru Ardelean
2021-11-21 14:05 ` Jonathan Cameron
2021-11-21 16:23 ` Lars-Peter Clausen
2021-11-21 17:52 ` Paul Cercueil
2021-11-21 18:49 ` Lars-Peter Clausen
2021-11-21 20:08 ` Paul Cercueil
2021-11-22 15:08 ` Lars-Peter Clausen
2021-11-22 15:16 ` Paul Cercueil
2021-11-22 15:17 ` Lars-Peter Clausen
2021-11-22 15:27 ` Paul Cercueil
2021-11-15 14:19 ` [PATCH 02/15] iio: buffer-dma: Remove unused iio_buffer_block struct Paul Cercueil
2021-11-16 8:22 ` Alexandru Ardelean
2021-11-15 14:19 ` [PATCH 03/15] iio: buffer-dma: Use round_down() instead of rounddown() Paul Cercueil
2021-11-16 8:26 ` Alexandru Ardelean
2021-11-21 14:08 ` Jonathan Cameron
2021-11-22 10:00 ` Paul Cercueil
2021-11-27 15:15 ` Jonathan Cameron
2021-11-15 14:19 ` [PATCH 04/15] iio: buffer-dma: Enable buffer write support Paul Cercueil
2021-11-16 8:52 ` Alexandru Ardelean
2021-11-21 14:20 ` Jonathan Cameron
2021-11-21 17:19 ` Paul Cercueil
2021-11-27 15:17 ` Jonathan Cameron
2021-11-15 14:19 ` [PATCH 05/15] iio: buffer-dmaengine: Support specifying buffer direction Paul Cercueil
2021-11-16 8:53 ` Alexandru Ardelean
2021-11-15 14:19 ` [PATCH 06/15] iio: buffer-dmaengine: Enable write support Paul Cercueil
2021-11-16 8:55 ` Alexandru Ardelean
2021-11-15 14:19 ` [PATCH 07/15] iio: core: Add new DMABUF interface infrastructure Paul Cercueil
2021-11-21 14:31 ` Jonathan Cameron
2021-11-15 14:19 ` [PATCH 08/15] iio: buffer-dma: split iio_dma_buffer_fileio_free() function Paul Cercueil
2021-11-16 10:59 ` Alexandru Ardelean
2021-11-21 13:49 ` Jonathan Cameron
2021-11-15 14:19 ` Paul Cercueil [this message]
2021-11-15 14:19 ` [PATCH 10/15] iio: buffer-dma: Implement new DMABUF based userspace API Paul Cercueil
2021-11-15 14:19 ` [PATCH 11/15] iio: buffer-dma: Boost performance using write-combine cache setting Paul Cercueil
2021-11-18 11:45 ` Paul Cercueil
2021-11-21 15:00 ` Jonathan Cameron
2021-11-21 17:43 ` Paul Cercueil
2021-11-25 17:29 ` Paul Cercueil
2021-11-27 16:05 ` Jonathan Cameron
2021-11-28 13:25 ` Lars-Peter Clausen
2021-11-27 15:20 ` Jonathan Cameron
2021-11-15 14:22 ` [PATCH 12/15] iio: buffer-dmaengine: Support new DMABUF based userspace API Paul Cercueil
2021-11-15 14:22 ` [PATCH 13/15] iio: core: Add support for cyclic buffers Paul Cercueil
2021-11-16 9:50 ` Alexandru Ardelean
2021-11-15 14:22 ` [PATCH 14/15] iio: buffer-dmaengine: " Paul Cercueil
2021-11-16 9:50 ` Alexandru Ardelean
2021-11-15 14:22 ` [PATCH 15/15] Documentation: iio: Document high-speed DMABUF based API Paul Cercueil
2021-11-21 15:10 ` Jonathan Cameron
2021-11-21 17:46 ` Paul Cercueil
2021-11-15 14:37 ` [PATCH 00/15] iio: buffer-dma: write() and new " Daniel Vetter
2021-11-15 14:57 ` Paul Cercueil
2021-11-16 16:02 ` Daniel Vetter
2021-11-16 16:31 ` Laurent Pinchart
2021-11-17 8:48 ` Christian König
2021-11-17 12:50 ` Paul Cercueil
2021-11-17 13:42 ` Hennerich, Michael
2021-11-21 13:57 ` Jonathan Cameron
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=20211115141925.60164-10-paul@crapouillou.net \
--to=paul@crapouillou.net \
--cc=Michael.Hennerich@analog.com \
--cc=ardeleanalex@gmail.com \
--cc=christian.koenig@amd.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=jic23@kernel.org \
--cc=lars@metafoo.de \
--cc=linaro-mm-sig@lists.linaro.org \
--cc=linux-iio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).