Le 28/09/2026 à 15:32, Pavel Begunkov a écrit :
Enable BIO_DMABUF_MAP backed requests. On registration we map the
dma-buf and store it as a prp list, which is then used to initialise
requests. All attached contexts are stored in a new list dmabuf_ctxs,
and additions/removals are synchronised with dmabuf_lock.

Suggested-by: Keith Busch <[email protected]>
Signed-off-by: Pavel Begunkov <[email protected]>

Hi,

a few nitpick below, should it help.

---
  drivers/nvme/host/core.c |  12 ++
  drivers/nvme/host/nvme.h |   2 +
  drivers/nvme/host/pci.c  | 308 +++++++++++++++++++++++++++++++++++++++
  3 files changed, 322 insertions(+)


[...]

diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index a953c0697f99..e58bdd9a4098 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -27,6 +27,8 @@
  #include <linux/io-64-nonatomic-lo-hi.h>
  #include <linux/io-64-nonatomic-hi-lo.h>
  #include <linux/sed-opal.h>
+#include <linux/dma-buf-io.h>
+#include <linux/dma-resv.h>

Move up, to keep better alphabetical order ?

#include "trace.h"
  #include "nvme.h"
@@ -318,6 +320,8 @@ struct nvme_dev {
        bool hmb;
        struct sg_table *hmb_sgt;
        mempool_t *dmavec_mempool;
+       struct list_head dmabuf_ctxs;
+       struct mutex dmabuf_lock;
/* shadow doorbell buffer support: */
        __le32 *dbbuf_dbs;
@@ -397,6 +401,13 @@ struct nvme_queue {
        struct completion delete_done;
  };
+struct nvme_dmabuf_map {
+       struct dma_buf_io_map base;
+       struct sg_table *sgt;
+       unsigned nr_entries;
+       dma_addr_t dma_list[];

Add __counted_by(nr_entries) and update nvme_dma_buf_io_map() so that nr_entries is set at the right time ?

+};
+
  /* bits for iod->flags */
  enum nvme_iod_flags {
        /* this command has been aborted by the timeout handler */

...

+static struct dma_buf_io_map *nvme_dma_buf_io_map(struct dma_buf_io_ctx *ctx)
+{
+       unsigned nr_entries = ctx->dmabuf->size / NVME_CTRL_PAGE_SIZE;
+       struct nvme_dma_buf_io_ctx *nvme_ctx = ctx->dev_priv;
+       struct dma_buf_attachment *attach = nvme_ctx->attach;
+       unsigned long tmp, i = 0;
+       struct nvme_dmabuf_map *map;
+       struct scatterlist *sg;
+       struct sg_table *sgt;
+       int ret;
+
+       dma_resv_assert_held(ctx->dmabuf->resv);
+
+       map = kvmalloc_flex(*map, dma_list, nr_entries);
+       if (!map)
+               return ERR_PTR(-ENOMEM);
+
+       sgt = dma_buf_map_attachment(attach, ctx->dir);
+       if (IS_ERR(sgt)) {
+               ret = PTR_ERR(sgt);
+               sgt = NULL;
+               goto err;
+       }
+
+       for_each_sgtable_dma_sg(sgt, sg, tmp) {
+               dma_addr_t dma_addr = sg_dma_address(sg);
+               unsigned long sg_len = sg_dma_len(sg);
+
+               if ((sg_len % NVME_CTRL_PAGE_SIZE) ||
+                   (dma_addr % NVME_CTRL_PAGE_SIZE)) {
+                       ret = -EINVAL;
+                       goto err;
+               }
+               while (sg_len) {
+                       map->dma_list[i++] = dma_addr;
+                       dma_addr += NVME_CTRL_PAGE_SIZE;
+                       sg_len -= NVME_CTRL_PAGE_SIZE;
+               }
+       }
+
+       ret = dma_buf_io_init_map(ctx, &map->base, sgt);
+       if (ret)
+               goto err;
+       map->nr_entries = nr_entries;
+       map->sgt = sgt;
+       return &map->base;
+err:
+       if (sgt)
+               dma_buf_unmap_attachment(attach, sgt, ctx->dir);
+       kfree(map);

kvfree()?

+       return ERR_PTR(ret);
+}
...

CJ

Reply via email to