git: b615b4805a9c - main - LinuxKPI: expand dma_sync_single_for_cpu() in lkpi_dma_unmap()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 10 Feb 2026 00:46:42 UTC
The branch main has been updated by bz:
URL: https://cgit.FreeBSD.org/src/commit/?id=b615b4805a9ce83b9b86dd66d46a9f220f9f89c6
commit b615b4805a9ce83b9b86dd66d46a9f220f9f89c6
Author: Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2026-01-23 19:14:18 +0000
Commit: Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2026-02-09 21:40:47 +0000
LinuxKPI: expand dma_sync_single_for_cpu() in lkpi_dma_unmap()
In case lkpi_dma_unmap() would call dma_sync_single_for_cpu() we get
into a lock recursion which will trigger a panic with debug kernels.
It would be hard to provide an internal "locked" version for
dma_sync_single_for_cpu(). In the old days this would not have
been a problem but (long before we added the missing sync calls)
some locks got folded into one in a6619e8d9c1a3.
Sponsored by: The FreeBSD Foundation
MFC after: 3 days
Observed with: iwlwifi mld
Reviewed by: dumbbell
Differential Revision: https://reviews.freebsd.org/D54841
---
sys/compat/linuxkpi/common/src/linux_pci.c | 21 +++++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/sys/compat/linuxkpi/common/src/linux_pci.c b/sys/compat/linuxkpi/common/src/linux_pci.c
index 9e4fad45433a..612a2cb5f46b 100644
--- a/sys/compat/linuxkpi/common/src/linux_pci.c
+++ b/sys/compat/linuxkpi/common/src/linux_pci.c
@@ -1720,9 +1720,26 @@ lkpi_dma_unmap(struct device *dev, dma_addr_t dma_addr, size_t len,
}
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);
+ if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) != 0)
+ goto skip_sync;
+ /* dma_sync_single_for_cpu() unrolled to avoid lock recursicn. */
+ switch (direction) {
+ case DMA_BIDIRECTIONAL:
+ bus_dmamap_sync(obj->dmat, obj->dmamap, BUS_DMASYNC_POSTREAD);
+ bus_dmamap_sync(obj->dmat, obj->dmamap, BUS_DMASYNC_PREREAD);
+ break;
+ case DMA_TO_DEVICE:
+ bus_dmamap_sync(obj->dmat, obj->dmamap, BUS_DMASYNC_POSTWRITE);
+ break;
+ case DMA_FROM_DEVICE:
+ bus_dmamap_sync(obj->dmat, obj->dmamap, BUS_DMASYNC_POSTREAD);
+ break;
+ default:
+ break;
+ }
+
+skip_sync:
bus_dmamap_unload(obj->dmat, obj->dmamap);
bus_dmamap_destroy(obj->dmat, obj->dmamap);
DMA_PRIV_UNLOCK(priv);