git: 8b59c5f824aa - stable/15 - LinuxKPI: implement dma_sync_sg_for_{cpu, device}()

From: Bjoern A. Zeeb <bz_at_FreeBSD.org>
Date: Thu, 10 Sep 2026 09:48:43 UTC
The branch stable/15 has been updated by bz:

URL: https://cgit.FreeBSD.org/src/commit/?id=8b59c5f824aac748278c3e480094e92c43c49de3

commit 8b59c5f824aac748278c3e480094e92c43c49de3
Author:     Zishun Yi <zis@FreeBSD.org>
AuthorDate: 2026-09-05 20:05:39 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2026-09-10 09:46:54 +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
    Differential Revision: https://reviews.freebsd.org/D57766
    
    (cherry picked from commit 9dec0cd79c693951fc58d82a99918fc5a02cbcd0)
---
 .../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 d32518a4d6ae..f26bb0e6eb99 100644
--- a/sys/compat/linuxkpi/common/include/linux/dma-mapping.h
+++ b/sys/compat/linuxkpi/common/include/linux/dma-mapping.h
@@ -111,6 +111,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)
@@ -290,21 +291,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 9d4d7bba8265..c966daae9507 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)