Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 3 Jun 2025 18:37:37 GMT
From:      "Bjoern A. Zeeb" <bz@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: f99d393f7f78 - main - LinuxKPI: add missing bus_dmamap_sync() calls or exclude them
Message-ID:  <202506031837.553IbbVZ000334@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by bz:

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

commit f99d393f7f787ff080c12b92243adcc310ac7c58
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2024-05-21 22:32:19 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2025-06-03 18:35:09 +0000

    LinuxKPI: add missing bus_dmamap_sync() calls or exclude them
    
    Rename linux_dma_unmap() to lkpi_dma_unmap(), and linux_dma_map_phys()
    to lkpi_dma_map_phys() so that we get the full set of function
    arguments (direction and attributes were missing).
    Leave the old functions as wrappers as they are called from drm-kmod
    linuxkpi/bsd still, and leaving them also allows us to MFC this
    change.
    
    Add missing bus_dmamap_sync() calls.  Rather than inlining them
    in each inline function push them down to the actual implementation.
    From there do not inline them either but call the appropriate
    function dealing with the sync so that we do not have the same
    code splattered in many places.
    
    Adhere to the DMA_ATTR_SKIP_CPU_SYNC attribute and skip synching
    when requested.
    
    A previous, less complete version of this change already allowed
    me to load firmware on arm64 for iwlwifi (again).
    
    There are four more places which are not currently done as the
    functions which came with an OFED sync a long time ago seem to be
    unused these days.  Leaving a pr_debug("TODO") call there.
    
    Also dma_[un]map_resource() when brought in from drm-kmod/linuxkpi/bsd
    (D30933) should be adjusted to pass the full arguments as the amdgpu
    callers are requesting to skip synching.
    
    Sponsored by:   The FreeBSD Foundation
    MFC after:      3 days
    Differential Revision: https://reviews.freebsd.org/D45294
---
 .../linuxkpi/common/include/linux/dma-mapping.h    | 50 ++++++++++++----------
 sys/compat/linuxkpi/common/src/linux_pci.c         | 49 ++++++++++++++++++---
 2 files changed, 70 insertions(+), 29 deletions(-)

diff --git a/sys/compat/linuxkpi/common/include/linux/dma-mapping.h b/sys/compat/linuxkpi/common/include/linux/dma-mapping.h
index 84f0361de765..09d5e4b6bc22 100644
--- a/sys/compat/linuxkpi/common/include/linux/dma-mapping.h
+++ b/sys/compat/linuxkpi/common/include/linux/dma-mapping.h
@@ -96,13 +96,17 @@ void *linux_dma_alloc_coherent(struct device *dev, size_t size,
     dma_addr_t *dma_handle, gfp_t flag);
 void *linuxkpi_dmam_alloc_coherent(struct device *dev, size_t size,
     dma_addr_t *dma_handle, gfp_t flag);
-dma_addr_t linux_dma_map_phys(struct device *dev, vm_paddr_t phys, size_t len);
-void linux_dma_unmap(struct device *dev, dma_addr_t dma_addr, size_t size);
+dma_addr_t linux_dma_map_phys(struct device *dev, vm_paddr_t phys, size_t len);	/* backward compat */
+dma_addr_t lkpi_dma_map_phys(struct device *, vm_paddr_t, size_t,
+    enum dma_data_direction, unsigned long);
+void linux_dma_unmap(struct device *dev, dma_addr_t dma_addr, size_t size);	/* backward compat */
+void lkpi_dma_unmap(struct device *, dma_addr_t, size_t,
+    enum dma_data_direction, unsigned long);
 int linux_dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
-    int nents, enum dma_data_direction dir __unused,
+    int nents, enum dma_data_direction direction,
     unsigned long attrs __unused);
 void linux_dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg,
-    int nents __unused, enum dma_data_direction dir __unused,
+    int nents __unused, enum dma_data_direction direction,
     unsigned long attrs __unused);
 void linuxkpi_dma_sync(struct device *, dma_addr_t, size_t, bus_dmasync_op_t);
 
@@ -173,16 +177,17 @@ dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
     dma_addr_t dma_addr)
 {
 
-	linux_dma_unmap(dev, dma_addr, size);
+	lkpi_dma_unmap(dev, dma_addr, size, DMA_BIDIRECTIONAL, 0);
 	kmem_free(cpu_addr, size);
 }
 
 static inline dma_addr_t
 dma_map_page_attrs(struct device *dev, struct page *page, size_t offset,
-    size_t size, enum dma_data_direction dir, unsigned long attrs)
+    size_t size, enum dma_data_direction direction, unsigned long attrs)
 {
 
-	return (linux_dma_map_phys(dev, page_to_phys(page) + offset, size));
+	return (lkpi_dma_map_phys(dev, page_to_phys(page) + offset, size,
+	    direction, attrs));
 }
 
 /* linux_dma_(un)map_sg_attrs does not support attrs yet */
@@ -197,7 +202,8 @@ dma_map_page(struct device *dev, struct page *page,
     unsigned long offset, size_t size, enum dma_data_direction direction)
 {
 
-	return (linux_dma_map_phys(dev, page_to_phys(page) + offset, size));
+	return (lkpi_dma_map_phys(dev, page_to_phys(page) + offset, size,
+	    direction, 0));
 }
 
 static inline void
@@ -205,7 +211,7 @@ dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
     enum dma_data_direction direction)
 {
 
-	linux_dma_unmap(dev, dma_address, size);
+	lkpi_dma_unmap(dev, dma_address, size, direction, 0);
 }
 
 static inline void
@@ -263,28 +269,33 @@ 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);
 }
 
 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);
 }
 
 static inline void
 dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
-    unsigned long offset, size_t size, int direction)
+    unsigned long offset, size_t size, enum dma_data_direction direction)
 {
+	pr_debug("%s:%d: TODO dir %d\n", __func__, __LINE__, direction);
 }
 
 static inline void
 dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
-    unsigned long offset, size_t size, int direction)
+    unsigned long offset, size_t size, enum dma_data_direction direction)
 {
+	pr_debug("%s:%d: TODO dir %d\n", __func__, __LINE__, direction);
 }
 
 #define	DMA_MAPPING_ERROR	(~(dma_addr_t)0)
@@ -306,24 +317,17 @@ static inline unsigned int dma_set_max_seg_size(struct device *dev,
 
 static inline dma_addr_t
 _dma_map_single_attrs(struct device *dev, void *ptr, size_t size,
-    enum dma_data_direction direction, unsigned long attrs __unused)
+    enum dma_data_direction direction, unsigned long attrs)
 {
-	dma_addr_t dma;
-
-	dma = linux_dma_map_phys(dev, vtophys(ptr), size);
-	if (!dma_mapping_error(dev, dma))
-		dma_sync_single_for_device(dev, dma, size, direction);
-
-	return (dma);
+	return (lkpi_dma_map_phys(dev, vtophys(ptr), size,
+	    direction, attrs));
 }
 
 static inline void
 _dma_unmap_single_attrs(struct device *dev, dma_addr_t dma, size_t size,
-    enum dma_data_direction direction, unsigned long attrs __unused)
+    enum dma_data_direction direction, unsigned long attrs)
 {
-
-	dma_sync_single_for_cpu(dev, dma, size, direction);
-	linux_dma_unmap(dev, dma, size);
+	lkpi_dma_unmap(dev, dma, size, direction, attrs);
 }
 
 static inline size_t
diff --git a/sys/compat/linuxkpi/common/src/linux_pci.c b/sys/compat/linuxkpi/common/src/linux_pci.c
index 5cf7c601d615..fe99c0ecf050 100644
--- a/sys/compat/linuxkpi/common/src/linux_pci.c
+++ b/sys/compat/linuxkpi/common/src/linux_pci.c
@@ -1530,17 +1530,34 @@ linux_dma_map_phys_common(struct device *dev __unused, vm_paddr_t phys,
 #endif
 
 dma_addr_t
-linux_dma_map_phys(struct device *dev, vm_paddr_t phys, size_t len)
+lkpi_dma_map_phys(struct device *dev, vm_paddr_t phys, size_t len,
+    enum dma_data_direction direction, unsigned long attrs)
 {
 	struct linux_dma_priv *priv;
+	dma_addr_t dma;
 
 	priv = dev->dma_priv;
-	return (linux_dma_map_phys_common(dev, phys, len, priv->dmat));
+	dma = linux_dma_map_phys_common(dev, phys, len, priv->dmat);
+	if (dma_mapping_error(dev, dma))
+		return (dma);
+
+	if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)
+		dma_sync_single_for_device(dev, dma, len, direction);
+
+	return (dma);
+}
+
+/* For backward compat only so we can MFC this. Remove before 15. */
+dma_addr_t
+linux_dma_map_phys(struct device *dev, vm_paddr_t phys, size_t len)
+{
+	return (lkpi_dma_map_phys(dev, phys, len, DMA_NONE, 0));
 }
 
 #if defined(__i386__) || defined(__amd64__) || defined(__aarch64__)
 void
-linux_dma_unmap(struct device *dev, dma_addr_t dma_addr, size_t len)
+lkpi_dma_unmap(struct device *dev, dma_addr_t dma_addr, size_t len,
+    enum dma_data_direction direction, unsigned long attrs)
 {
 	struct linux_dma_priv *priv;
 	struct linux_dma_obj *obj;
@@ -1557,6 +1574,10 @@ linux_dma_unmap(struct device *dev, dma_addr_t dma_addr, size_t len)
 		return;
 	}
 	LINUX_DMA_PCTRIE_REMOVE(&priv->ptree, dma_addr);
+
+	if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)
+		dma_sync_single_for_cpu(dev, dma_addr, len, direction);
+
 	bus_dmamap_unload(obj->dmat, obj->dmamap);
 	bus_dmamap_destroy(obj->dmat, obj->dmamap);
 	DMA_PRIV_UNLOCK(priv);
@@ -1565,11 +1586,19 @@ linux_dma_unmap(struct device *dev, dma_addr_t dma_addr, size_t len)
 }
 #else
 void
-linux_dma_unmap(struct device *dev, dma_addr_t dma_addr, size_t len)
+lkpi_dma_unmap(struct device *dev, dma_addr_t dma_addr, size_t len,
+    enum dma_data_direction direction, unsigned long attrs)
 {
 }
 #endif
 
+/* For backward compat only so we can MFC this. Remove before 15. */
+void
+linux_dma_unmap(struct device *dev, dma_addr_t dma_addr, size_t len)
+{
+	lkpi_dma_unmap(dev, dma_addr, len, DMA_NONE, 0);
+}
+
 void *
 linux_dma_alloc_coherent(struct device *dev, size_t size,
     dma_addr_t *dma_handle, gfp_t flag)
@@ -1671,7 +1700,7 @@ linuxkpi_dma_sync(struct device *dev, dma_addr_t dma_addr, size_t size,
 
 int
 linux_dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl, int nents,
-    enum dma_data_direction direction, unsigned long attrs __unused)
+    enum dma_data_direction direction, unsigned long attrs)
 {
 	struct linux_dma_priv *priv;
 	struct scatterlist *sg;
@@ -1705,6 +1734,9 @@ linux_dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl, int nents,
 		sg_dma_address(sg) = seg.ds_addr;
 	}
 
+	if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) != 0)
+		goto skip_sync;
+
 	switch (direction) {
 	case DMA_BIDIRECTIONAL:
 		bus_dmamap_sync(priv->dmat, sgl->dma_map, BUS_DMASYNC_PREWRITE);
@@ -1718,6 +1750,7 @@ linux_dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl, int nents,
 	default:
 		break;
 	}
+skip_sync:
 
 	DMA_PRIV_UNLOCK(priv);
 
@@ -1727,7 +1760,7 @@ linux_dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl, int nents,
 void
 linux_dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sgl,
     int nents __unused, enum dma_data_direction direction,
-    unsigned long attrs __unused)
+    unsigned long attrs)
 {
 	struct linux_dma_priv *priv;
 
@@ -1735,6 +1768,9 @@ linux_dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sgl,
 
 	DMA_PRIV_LOCK(priv);
 
+	if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) != 0)
+		goto skip_sync;
+
 	switch (direction) {
 	case DMA_BIDIRECTIONAL:
 		bus_dmamap_sync(priv->dmat, sgl->dma_map, BUS_DMASYNC_POSTREAD);
@@ -1749,6 +1785,7 @@ linux_dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sgl,
 	default:
 		break;
 	}
+skip_sync:
 
 	bus_dmamap_unload(priv->dmat, sgl->dma_map);
 	bus_dmamap_destroy(priv->dmat, sgl->dma_map);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202506031837.553IbbVZ000334>