[PATCH RFC 01/26] dma-buf: Introduce DMA-buf mapping types
From: Jason Gunthorpe <jgg@nvidia.com>
Date: 2026-02-18 00:12:06
Also in:
intel-xe, linux-iommu, linux-media
Subsystem:
dma buffer sharing framework, the rest · Maintainers:
Sumit Semwal, Christian König, Linus Torvalds
DMA-buf mapping types allow the importer and exporter to negotiate the
format of the map/unmap to be used during the attachment.
Currently DMA-buf only supports struct scatterlist as the attachment map
operation. This is not sufficient for all use cases as dma_addr_t is a
very specific and limited type.
With mapping types the importing driver can declare what it supports. For
example:
struct dma_buf_mapping_match imp_match[] = {
DMA_BUF_IMAPPING_MY_DRIVER(dev, ...),
DMA_BUF_IMAPPING_SGT(dev, false),
};
attach = dma_buf_mapping_attach(dmabuf, imp_match, ...)
And the exporting driver can declare what it supports:
int exporter_match_mapping(struct dma_buf_match_args *args)
{
struct dma_buf_mapping_match exp_match[] = {
DMA_BUF_EMAPPING_MY_DRIVER(my_ops, dev, ...),
DMA_BUF_EMAPPING_SGT(sgt_ops, dev, false),
DMA_BUF_EMAPPING_PAL(PAL_ops),
};
return dma_buf_match_mapping(args, exp_match, ...);
}
During dma_buf_mapping_attach() the core code will select a mutual match
between the importer and exporter and record it in the attach->map_type.
Add the basic types:
struct dma_buf_mapping_type
Type tag and ops for each mapping type.
struct dma_buf_mapping_match
Entry in a list of importer or exporter match specifications.
The match specification can be extended by the mapping type with
unique data.
dma_buf_match_mapping() / struct dma_buf_match_args
Helper to do the matching. Called by the exporting driver
via a dma_buf_ops callback.
struct dma_buf_mapping_exp_ops
Base type for the per-mapping type exporter provided functions. This
would be the map/unmap callbacks. Each mapping type can provide its own
functions for map/unmap type operations with optimal type signatures.
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
---
drivers/dma-buf/dma-buf-mapping.c | 46 +++++++++++++++++++
include/linux/dma-buf-mapping.h | 76 +++++++++++++++++++++++++++++++
include/linux/dma-buf.h | 18 ++++++++
3 files changed, 140 insertions(+)
diff --git a/drivers/dma-buf/dma-buf-mapping.c b/drivers/dma-buf/dma-buf-mapping.c
index b7352e609fbdfa..459c204cabb803 100644
--- a/drivers/dma-buf/dma-buf-mapping.c
+++ b/drivers/dma-buf/dma-buf-mapping.c@@ -5,6 +5,7 @@ */ #include <linux/dma-buf-mapping.h> #include <linux/dma-resv.h> +#include <linux/dma-buf.h> static struct scatterlist *fill_sg_entry(struct scatterlist *sgl, size_t length, dma_addr_t addr)
@@ -246,3 +247,48 @@ void dma_buf_free_sgt(struct dma_buf_attachment *attach, struct sg_table *sgt, } EXPORT_SYMBOL_NS_GPL(dma_buf_free_sgt, "DMA_BUF"); + +/** + * dma_buf_match_mapping - Select a mapping type agreed upon by exporter and + * importer + * @args: Match arguments from attach. On success this is updated with the + * matched exporter and importer entries. + * @exp: Array of mapping types supported by the exporter, in priority order + * @exp_len: Number of entries in @exp + * + * Iterate over the exporter's supported mapping types and for each one search + * the importer's list for a compatible matching type. args and args->attach are + * populated with the resulting match. + * + * Because the exporter list is walked in order, the exporter controls the + * priority of mapping types. + */ +int dma_buf_match_mapping(struct dma_buf_match_args *args, + const struct dma_buf_mapping_match *exp, + size_t exp_len) +{ + const struct dma_buf_mapping_match *exp_end = exp + exp_len; + const struct dma_buf_mapping_match *imp_end = + args->imp_matches + args->imp_len; + int ret; + + for (; exp != exp_end; exp++) { + const struct dma_buf_mapping_match *imp = args->imp_matches; + + for (; imp != imp_end; imp++) { + if (exp->type != imp->type) + continue; + if (exp->type->match) { + ret = exp->type->match(args->dmabuf, exp, imp); + if (ret == -EOPNOTSUPP) + continue; + if (ret != 0) + return ret; + } + exp->type->finish_match(args, exp, imp); + return 0; + } + } + return -EINVAL; +} +EXPORT_SYMBOL_NS_GPL(dma_buf_match_mapping, "DMA_BUF");
diff --git a/include/linux/dma-buf-mapping.h b/include/linux/dma-buf-mapping.h
index a3c0ce2d3a42fe..080ccbf3a3f8b8 100644
--- a/include/linux/dma-buf-mapping.h
+++ b/include/linux/dma-buf-mapping.h@@ -7,6 +7,77 @@ #define __DMA_BUF_MAPPING_H__ #include <linux/dma-buf.h> +struct device; +struct dma_buf; +struct dma_buf_attachment; +struct dma_buf_mapping_exp_ops; + +/* Type tag for all mapping operations */ +struct dma_buf_mapping_exp_ops {}; + +/* + * Internal struct to pass arguments from the attach function to the matching + * function + */ +struct dma_buf_match_args { + struct dma_buf *dmabuf; + struct dma_buf_attachment *attach; + const struct dma_buf_mapping_match *imp_matches; + size_t imp_len; +}; + +/** + * struct dma_buf_mapping_type - Operations for a DMA-buf mapping type + * + * Each mapping type provides a singleton instance of this struct to describe + * the mapping type and its operations. + */ +struct dma_buf_mapping_type { + /** + * @name: Human-readable name for this mapping type, used in debugfs + * output + */ + const char *name; + + /** + * @match: + * + * Called during attach from dma_buf_match_mapping(). &exp and &imp are + * single items from the importer and exporter mapping match lists. + * Both will have the same instance of this struct as their type member. + * + * It determines if the exporter/importer are compatible. + * + * Returns: 0 on success + * -EOPNOTSUPP means ignore the failure and continue + * Everything else aborts the search and returns the -errno + */ + int (*match)(struct dma_buf *dmabuf, + const struct dma_buf_mapping_match *exp, + const struct dma_buf_mapping_match *imp); + + /** + * @finish_match: + * + * Called by dma_buf_match_mapping() after a successful match to store + * the negotiated result in @args->attach. The matched @exp and @imp + * entries are provided so the callback can copy type-specific data into + * the attachment. + */ + void (*finish_match)(struct dma_buf_match_args *args, + const struct dma_buf_mapping_match *exp, + const struct dma_buf_mapping_match *imp); + + /** + * @debugfs_dump: + * + * Optional callback to write mapping-type-specific diagnostic + * information about @attach to the debugfs seq_file @s. + */ + void (*debugfs_dump)(struct seq_file *s, + struct dma_buf_attachment *attach); +}; + struct sg_table *dma_buf_phys_vec_to_sgt(struct dma_buf_attachment *attach, struct p2pdma_provider *provider, struct dma_buf_phys_vec *phys_vec,
@@ -14,4 +85,9 @@ struct sg_table *dma_buf_phys_vec_to_sgt(struct dma_buf_attachment *attach, enum dma_data_direction dir); void dma_buf_free_sgt(struct dma_buf_attachment *attach, struct sg_table *sgt, enum dma_data_direction dir); + +int dma_buf_match_mapping(struct dma_buf_match_args *args, + const struct dma_buf_mapping_match *exp_mappings, + size_t exp_len); + #endif
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
index 0bc492090237ed..a2b01b13026810 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h@@ -27,6 +27,21 @@ struct device; struct dma_buf; struct dma_buf_attachment; +struct dma_buf_mapping_type; +struct dma_buf_mapping_exp_ops; + +/* + * Match items are generated by the importer using the DMA_BUF_IMAPPING_*() and + * the exporter using the DMA_BUF_EMAPPING_*() functions. Each mapping type + * defines its own signature with its own data to make the match and attachment. + */ +struct dma_buf_mapping_match { + const struct dma_buf_mapping_type *type; + const struct dma_buf_mapping_exp_ops *exp_ops; + union { + /* Each mapping_type has unique match parameters here */ + }; +}; /** * struct dma_buf_ops - operations possible on struct dma_buf
@@ -488,6 +503,8 @@ struct dma_buf_attach_ops { * @importer_ops: importer operations for this attachment, if provided * dma_buf_map/unmap_attachment() must be called with the dma_resv lock held. * @importer_priv: importer specific attachment data. + * @map_type: The match that defines the mutually compatible mapping type to use + * for this attachment. * * This structure holds the attachment information between the dma_buf buffer * and its user device(s). The list contains one attachment struct per device
@@ -506,6 +523,7 @@ struct dma_buf_attachment { const struct dma_buf_attach_ops *importer_ops; void *importer_priv; void *priv; + struct dma_buf_mapping_match map_type; }; /**
--
2.43.0