git: 0b1dea8f51e4 - stable/15 - LinuxKPI: implement dma_{alloc,free}_{noncoherent,attrs}
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 19 Sep 2026 14:40:28 UTC
The branch stable/15 has been updated by bz:
URL: https://cgit.FreeBSD.org/src/commit/?id=0b1dea8f51e41fa602294cf2526481c49123e2da
commit 0b1dea8f51e41fa602294cf2526481c49123e2da
Author: Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2026-08-16 21:54:36 +0000
Commit: Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2026-09-19 09:34:10 +0000
LinuxKPI: implement dma_{alloc,free}_{noncoherent,attrs}
We use one to implement the other given direction stays unused.
This is needed by an upcoming wifi driver.
Reviewed by: dumbbell
Differential Revision: https://reviews.freebsd.org/D58880
(cherry picked from commit c3fa17a6a331db8aad03e9cb89ba97e1811ab381)
---
.../linuxkpi/common/include/linux/dma-mapping.h | 36 ++++++++++++++++
sys/compat/linuxkpi/common/src/linux_pci.c | 50 ++++++++++++++++++++++
2 files changed, 86 insertions(+)
diff --git a/sys/compat/linuxkpi/common/include/linux/dma-mapping.h b/sys/compat/linuxkpi/common/include/linux/dma-mapping.h
index 173b3e8d3c96..bb1ef678e621 100644
--- a/sys/compat/linuxkpi/common/include/linux/dma-mapping.h
+++ b/sys/compat/linuxkpi/common/include/linux/dma-mapping.h
@@ -98,6 +98,14 @@ void *linuxkpi_dmam_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag);
void linuxkpi_dmam_free_coherent(struct device *dev, size_t size,
void *addr, dma_addr_t dma_handle);
+void *linuxkpi_dma_alloc_noncoherent(struct device *, size_t, dma_addr_t *,
+ enum dma_data_direction, gfp_t);
+void linuxkpi_dma_free_noncoherent(struct device *, size_t, void *,
+ dma_addr_t, enum dma_data_direction);
+void *linuxkpi_dma_alloc_attrs(struct device *, size_t, dma_addr_t *,
+ gfp_t, unsigned long);
+void linuxkpi_dma_free_attrs(struct device *, size_t, void *,
+ dma_addr_t, unsigned long);
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);
@@ -191,6 +199,34 @@ dmam_free_coherent(struct device *dev, size_t size, void *addr,
linuxkpi_dmam_free_coherent(dev, size, addr, dma_handle);
}
+static inline void *
+dma_alloc_noncoherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
+ enum dma_data_direction direction, gfp_t gfp)
+{
+ return (linuxkpi_dma_alloc_noncoherent(dev, size, dma_handle, direction, gfp));
+}
+
+static inline void
+dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
+ dma_addr_t dma_handle, enum dma_data_direction direction)
+{
+ linuxkpi_dma_free_noncoherent(dev, size, vaddr, dma_handle, direction);
+}
+
+static inline void *
+dma_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle,
+ gfp_t gfp, unsigned long attrs)
+{
+ return (linuxkpi_dma_alloc_attrs(dev, size, dma_handle, gfp, attrs));
+}
+
+static inline void
+dma_free_attrs(struct device *dev, size_t size, void *vaddr,
+ dma_addr_t dma_handle, unsigned long attrs)
+{
+ linuxkpi_dma_free_attrs(dev, size, vaddr, dma_handle, attrs);
+}
+
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 direction, unsigned long attrs)
diff --git a/sys/compat/linuxkpi/common/src/linux_pci.c b/sys/compat/linuxkpi/common/src/linux_pci.c
index 4909b52150ae..ab8d5cf98534 100644
--- a/sys/compat/linuxkpi/common/src/linux_pci.c
+++ b/sys/compat/linuxkpi/common/src/linux_pci.c
@@ -1989,6 +1989,56 @@ linuxkpi_dmam_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_ha
return (dr->mem);
}
+void *
+linuxkpi_dma_alloc_noncoherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
+ enum dma_data_direction direction, gfp_t gfp)
+{
+ struct linux_dma_priv *priv;
+ size_t align;
+ void *mem;
+
+ size = PAGE_ALIGN(size);
+ align = PAGE_SIZE << get_order(size);
+ mem = kmem_alloc_contig(size, gfp & GFP_NATIVE_MASK, 0, BUS_SPACE_MAXADDR,
+ align, 0, VM_MEMATTR_DEFAULT);
+ if (mem == NULL) {
+ *dma_handle = 0;
+ return (NULL);
+ }
+
+ priv = dev->dma_priv;
+ *dma_handle = linux_dma_map_phys_common(dev, vtophys(mem), size, priv->dmat);
+ if (*dma_handle == 0) {
+ kmem_free(mem, size);
+ mem = NULL;
+ }
+ return (mem);
+}
+
+void
+linuxkpi_dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
+ dma_addr_t dma_handle, enum dma_data_direction direction)
+{
+ lkpi_dma_unmap(dev, dma_handle, size, direction, 0);
+ kmem_free(vaddr, size);
+}
+
+void *
+linuxkpi_dma_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle,
+ gfp_t gfp, unsigned long attrs)
+{
+ return (linuxkpi_dma_alloc_noncoherent(dev, size, dma_handle,
+ DMA_BIDIRECTIONAL, gfp));
+}
+
+void
+linuxkpi_dma_free_attrs(struct device *dev, size_t size, void *vaddr,
+ dma_addr_t dma_handle, unsigned long attrs)
+{
+ linuxkpi_dma_free_noncoherent(dev, size, vaddr, dma_handle,
+ DMA_BIDIRECTIONAL);
+}
+
void
linuxkpi_dma_sync(struct device *dev, dma_addr_t dma_addr, size_t size,
bus_dmasync_op_t op)