git: 0a575891211e - main - LinuxKPI: implement dmam_free_coherent()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 25 Jan 2026 12:35:52 UTC
The branch main has been updated by bz:
URL: https://cgit.FreeBSD.org/src/commit/?id=0a575891211eff545bab1e4de5e2b7adf4a4c1da
commit 0a575891211eff545bab1e4de5e2b7adf4a4c1da
Author: Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2026-01-21 13:57:55 +0000
Commit: Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2026-01-25 12:35:22 +0000
LinuxKPI: implement dmam_free_coherent()
dmam_free_coherent() is used by an updated mt76 driver at v6.19-rc6.
We need to surgically find the devres information and destroy it before
calling dma_free_coherent.
Sponsored by: The FreeBSD Foundation
MFC after: 3 days
Reviewed by: emaste
Differential Revision: https://reviews.freebsd.org/D54810
---
.../linuxkpi/common/include/linux/dma-mapping.h | 9 ++++++
sys/compat/linuxkpi/common/src/linux_pci.c | 36 ++++++++++++++++++++++
2 files changed, 45 insertions(+)
diff --git a/sys/compat/linuxkpi/common/include/linux/dma-mapping.h b/sys/compat/linuxkpi/common/include/linux/dma-mapping.h
index 2d8e1196d3d3..76efbfd51074 100644
--- a/sys/compat/linuxkpi/common/include/linux/dma-mapping.h
+++ b/sys/compat/linuxkpi/common/include/linux/dma-mapping.h
@@ -96,6 +96,8 @@ 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);
+void linuxkpi_dmam_free_coherent(struct device *dev, size_t size,
+ void *addr, dma_addr_t dma_handle);
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);
@@ -181,6 +183,13 @@ dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
kmem_free(cpu_addr, size);
}
+static inline void
+dmam_free_coherent(struct device *dev, size_t size, void *addr,
+ dma_addr_t dma_handle)
+{
+ linuxkpi_dmam_free_coherent(dev, size, addr, dma_handle);
+}
+
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 df5255d8a6ca..9e4fad45433a 100644
--- a/sys/compat/linuxkpi/common/src/linux_pci.c
+++ b/sys/compat/linuxkpi/common/src/linux_pci.c
@@ -1796,6 +1796,42 @@ lkpi_dmam_free_coherent(struct device *dev, void *p)
dma_free_coherent(dev, dr->size, dr->mem, *dr->handle);
}
+static int
+lkpi_dmam_coherent_match(struct device *dev, void *dr, void *mp)
+{
+ struct lkpi_devres_dmam_coherent *a, *b;
+
+ a = dr;
+ b = mp;
+
+ if (a->mem != b->mem)
+ return (0);
+ if (a->size != b->size || a->handle != b->handle)
+ dev_WARN(dev, "for mem %p: size %zu != %zu || handle %#jx != %#jx\n",
+ a->mem, a->size, b->size,
+ (uintmax_t)a->handle, (uintmax_t)b->handle);
+ return (1);
+}
+
+void
+linuxkpi_dmam_free_coherent(struct device *dev, size_t size,
+ void *addr, dma_addr_t dma_handle)
+{
+ struct lkpi_devres_dmam_coherent match = {
+ .size = size,
+ .handle = &dma_handle,
+ .mem = addr
+ };
+ int error;
+
+ error = devres_destroy(dev, lkpi_dmam_free_coherent,
+ lkpi_dmam_coherent_match, &match);
+ if (error != 0)
+ dev_WARN(dev, "devres_destroy returned %d, size %zu addr %p "
+ "dma_handle %#jx\n", error, size, addr, (uintmax_t)dma_handle);
+ dma_free_coherent(dev, size, addr, dma_handle);
+}
+
void *
linuxkpi_dmam_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
gfp_t flag)