The branch main has been updated by bz: URL: https://cgit.FreeBSD.org/src/commit/?id=9dec0cd79c693951fc58d82a99918fc5a02cbcd0
commit 9dec0cd79c693951fc58d82a99918fc5a02cbcd0 Author: Zishun Yi <[email protected]> AuthorDate: 2026-09-05 20:05:39 +0000 Commit: Bjoern A. Zeeb <[email protected]> CommitDate: 2026-09-06 00:12:48 +0000 LinuxKPI: implement dma_sync_sg_for_{cpu, device}() Implement dma_sync_sg_for_{cpu, device}() and dma_sync_sgtable_for_device(). These functions are useful for my GSoC 2026 project, udmabuf. Reviewed by: bz MFC after: 3 days Differential Revision: https://reviews.freebsd.org/D57766 --- .../linuxkpi/common/include/linux/dma-mapping.h | 51 ++++++++++++++++++++-- sys/compat/linuxkpi/common/src/linux_pci.c | 11 +++++ 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/sys/compat/linuxkpi/common/include/linux/dma-mapping.h b/sys/compat/linuxkpi/common/include/linux/dma-mapping.h index ce0703bd7999..e7589056ae46 100644 --- a/sys/compat/linuxkpi/common/include/linux/dma-mapping.h +++ b/sys/compat/linuxkpi/common/include/linux/dma-mapping.h @@ -121,6 +121,7 @@ void linux_dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg, int nents __unused, enum dma_data_direction direction, unsigned long attrs); void linuxkpi_dma_sync(struct device *, dma_addr_t, size_t, bus_dmasync_op_t); +void lkpi_dma_sync_sg(struct device *, struct scatterlist *, bus_dmasync_op_t); static inline int dma_supported(struct device *dev, u64 dma_mask) @@ -307,21 +308,65 @@ dma_sync_single_for_device(struct device *dev, dma_addr_t dma, linuxkpi_dma_sync(dev, dma, size, op); } -/* (20250329) These four seem to be unused code. */ static inline void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, enum dma_data_direction direction) { - pr_debug("%s:%d: TODO dir %d\n", __func__, __LINE__, direction); + bus_dmasync_op_t op; + + switch (direction) { + case DMA_BIDIRECTIONAL: + op = BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE; + break; + case DMA_TO_DEVICE: + op = BUS_DMASYNC_POSTWRITE; + break; + case DMA_FROM_DEVICE: + op = BUS_DMASYNC_POSTREAD; + break; + default: + return; + } + + lkpi_dma_sync_sg(dev, sg, op); +} + +static inline void dma_sync_sgtable_for_cpu(struct device *dev, + struct sg_table *sgt, enum dma_data_direction dir) +{ + dma_sync_sg_for_cpu(dev, sgt->sgl, sgt->orig_nents, dir); } static inline void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems, enum dma_data_direction direction) { - pr_debug("%s:%d: TODO dir %d\n", __func__, __LINE__, direction); + bus_dmasync_op_t op; + + switch (direction) { + case DMA_BIDIRECTIONAL: + op = BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD; + break; + case DMA_TO_DEVICE: + op = BUS_DMASYNC_PREWRITE; + break; + case DMA_FROM_DEVICE: + op = BUS_DMASYNC_PREREAD; + break; + default: + return; + } + + lkpi_dma_sync_sg(dev, sg, op); +} + +static inline void dma_sync_sgtable_for_device(struct device *dev, + struct sg_table *sgt, enum dma_data_direction dir) +{ + dma_sync_sg_for_device(dev, sgt->sgl, sgt->orig_nents, dir); } +/* (20250329) These two seem to be unused code. */ static inline void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle, unsigned long offset, size_t size, enum dma_data_direction direction) diff --git a/sys/compat/linuxkpi/common/src/linux_pci.c b/sys/compat/linuxkpi/common/src/linux_pci.c index 9e11f53cb299..44082e6ecaa6 100644 --- a/sys/compat/linuxkpi/common/src/linux_pci.c +++ b/sys/compat/linuxkpi/common/src/linux_pci.c @@ -2012,6 +2012,17 @@ linuxkpi_dma_sync(struct device *dev, dma_addr_t dma_addr, size_t size, DMA_PRIV_UNLOCK(priv); } +void +lkpi_dma_sync_sg(struct device *dev, struct scatterlist *sgl, bus_dmasync_op_t op) +{ + struct linux_dma_priv *priv; + + priv = dev->dma_priv; + DMA_PRIV_LOCK(priv); + bus_dmamap_sync(priv->dmat, sgl->dma_map, op); + DMA_PRIV_UNLOCK(priv); +} + int linux_dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl, int nents, enum dma_data_direction direction, unsigned long attrs)
