Introduce single_exporter_match into the dma_buf_ops so that single exporter drivers can simply set it using a static initializer to use the mapping type APIs. Provide a helper macro DMA_BUF_SIMPLE_SGT_EXP_MATCH() that generates the initializer for simple drivers that don't use P2P.
More complex exporters, especially those with P2P, need to implement the match_mapping call back to extract things like their DMA struct device from the dma_buf in order to do the P2P calculations.
Signed-off-by: Jason Gunthorpe jgg@nvidia.com --- drivers/dma-buf/dma-buf.c | 14 +++++++++++--- include/linux/dma-buf-mapping.h | 15 +++++++++++++++ include/linux/dma-buf.h | 9 +++++++++ 3 files changed, 35 insertions(+), 3 deletions(-)
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index 4211ae2b462bdd..ac755f358dc7b3 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -693,10 +693,14 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info) || !exp_info->ops->release)) return ERR_PTR(-EINVAL);
- if (exp_info->ops->match_mapping) { + if (exp_info->ops->match_mapping || + exp_info->ops->single_exporter_match) { if (WARN_ON(exp_info->ops->map_dma_buf || exp_info->ops->unmap_dma_buf)) return ERR_PTR(-EINVAL); + if (WARN_ON(exp_info->ops->match_mapping && + exp_info->ops->single_exporter_match)) + return ERR_PTR(-EINVAL); } else { if (WARN_ON(!exp_info->ops->map_dma_buf || !exp_info->ops->unmap_dma_buf)) @@ -977,8 +981,12 @@ struct dma_buf_attachment *dma_buf_mapping_attach( if (ret) goto err_attach; } else { - ret = dma_buf_match_mapping(&match_args, - &dma_buf_sgt_exp_compat_match, 1); + const struct dma_buf_mapping_match *exp_match = + dmabuf->ops->single_exporter_match; + + if (!exp_match) + exp_match = &dma_buf_sgt_exp_compat_match; + ret = dma_buf_match_mapping(&match_args, exp_match, 1); if (ret) goto err_attach; } diff --git a/include/linux/dma-buf-mapping.h b/include/linux/dma-buf-mapping.h index 360a7fe0b098be..c11e32ef2a684f 100644 --- a/include/linux/dma-buf-mapping.h +++ b/include/linux/dma-buf-mapping.h @@ -191,4 +191,19 @@ DMA_BUF_EMAPPING_SGT_P2P(const struct dma_buf_mapping_sgt_exp_ops *exp_ops,
extern const struct dma_buf_mapping_match dma_buf_sgt_exp_compat_match;
+/* + * dma_buf_ops initializer helper for simple drivers that use a single + * SGT map/unmap operation without P2P. + */ +#define DMA_BUF_SIMPLE_SGT_EXP_MATCH(_map, _unmap) \ + .single_exporter_match = &((const struct dma_buf_mapping_match){ \ + .type = &dma_buf_mapping_sgt_type, \ + .exp_ops = &((const struct dma_buf_mapping_sgt_exp_ops){ \ + .map_dma_buf = _map, \ + .unmap_dma_buf = _unmap, \ + }.ops), \ + .sgt_data = { \ + .exporter_requires_p2p = DMA_SGT_NO_P2P, \ + } }) + #endif diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index 14d556bb022862..a8cfbbafbe31fe 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -317,6 +317,15 @@ struct dma_buf_ops { * struct dma_buf_mapping_match[] and call dma_buf_match_mapping(). */ int (*match_mapping)(struct dma_buf_match_args *args); + + /** + * @single_exporter_match: + * + * Should only be set by the DMA_BUF_SIMPLE_*_EXP_MATCH() helper macros. + * Exactly one of @match_mapping or @single_exporter_match must be + * provided. + */ + const struct dma_buf_mapping_match *single_exporter_match; };
/**