Add basic dmabuf helpers and structures for io_uring, which will be used for dmabuf buffer registration. That can also be reused in other places in io_uring, which is ommited from the series. Signed-off-by: Pavel Begunkov <asml.silence@xxxxxxxxx> --- io_uring/Makefile | 1 + io_uring/dmabuf.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++ io_uring/dmabuf.h | 34 +++++++++++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100644 io_uring/dmabuf.c create mode 100644 io_uring/dmabuf.h diff --git a/io_uring/Makefile b/io_uring/Makefile index d97c6b51d584..0f5a7ec38452 100644 --- a/io_uring/Makefile +++ b/io_uring/Makefile @@ -21,3 +21,4 @@ obj-$(CONFIG_EPOLL) += epoll.o obj-$(CONFIG_NET_RX_BUSY_POLL) += napi.o obj-$(CONFIG_NET) += net.o cmd_net.o obj-$(CONFIG_PROC_FS) += fdinfo.o +obj-$(CONFIG_DMA_SHARED_BUFFER) += dmabuf.o diff --git a/io_uring/dmabuf.c b/io_uring/dmabuf.c new file mode 100644 index 000000000000..cb9d8bb5d5b3 --- /dev/null +++ b/io_uring/dmabuf.c @@ -0,0 +1,60 @@ +#include "dmabuf.h" + +void io_dmabuf_release(struct io_dmabuf *buf) +{ + if (buf->sgt) + dma_buf_unmap_attachment_unlocked(buf->attach, buf->sgt, + buf->dir); + if (buf->attach) + dma_buf_detach(buf->dmabuf, buf->attach); + if (buf->dmabuf) + dma_buf_put(buf->dmabuf); + if (buf->dev) + put_device(buf->dev); + + memset(buf, 0, sizeof(*buf)); +} + +int io_dmabuf_import(struct io_dmabuf *buf, int dmabuf_fd, + struct device *dev, enum dma_data_direction dir) +{ + unsigned long total_size = 0; + struct scatterlist *sg; + int i, ret; + + if (WARN_ON_ONCE(!dev)) + return -EFAULT; + + buf->dir = dir; + buf->dmabuf = dma_buf_get(dmabuf_fd); + if (IS_ERR(buf->dmabuf)) { + ret = PTR_ERR(buf->dmabuf); + buf->dmabuf = NULL; + goto err; + } + + buf->attach = dma_buf_attach(buf->dmabuf, dev); + if (IS_ERR(buf->attach)) { + ret = PTR_ERR(buf->attach); + buf->attach = NULL; + goto err; + } + + buf->sgt = dma_buf_map_attachment_unlocked(buf->attach, dir); + if (IS_ERR(buf->sgt)) { + ret = PTR_ERR(buf->sgt); + buf->sgt = NULL; + goto err; + } + + for_each_sgtable_dma_sg(buf->sgt, sg, i) + total_size += sg_dma_len(sg); + + buf->dir = dir; + buf->dev = get_device(dev); + buf->len = total_size; + return 0; +err: + io_dmabuf_release(buf); + return ret; +} diff --git a/io_uring/dmabuf.h b/io_uring/dmabuf.h new file mode 100644 index 000000000000..c785ccfe0b9e --- /dev/null +++ b/io_uring/dmabuf.h @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0 +#ifndef IOU_DMABUF_H +#define IOU_DMABUF_H + +#include <linux/io_uring_types.h> +#include <linux/dma-buf.h> + +struct io_dmabuf { + size_t len; + struct dma_buf_attachment *attach; + struct dma_buf *dmabuf; + struct sg_table *sgt; + struct device *dev; + enum dma_data_direction dir; +}; + +#ifdef CONFIG_DMA_SHARED_BUFFER +void io_dmabuf_release(struct io_dmabuf *buf); +int io_dmabuf_import(struct io_dmabuf *buf, int dmabuf_fd, + struct device *dev, enum dma_data_direction dir); + +#else +static inline void io_dmabuf_release(struct io_dmabuf *buf) +{ +} + +static inline int io_dmabuf_import(struct io_dmabuf *buf, int dmabuf_fd, + struct device *dev, enum dma_data_direction dir) +{ + return -EOPNOTSUPP; +} +#endif + +#endif -- 2.49.0