The branch stable/15 has been updated by bz: URL: https://cgit.FreeBSD.org/src/commit/?id=9c0f88c33ce02d8b842e7e75ba7b0beb7edebcbc
commit 9c0f88c33ce02d8b842e7e75ba7b0beb7edebcbc Author: Bjoern A. Zeeb <[email protected]> AuthorDate: 2026-01-23 19:14:18 +0000 Commit: Bjoern A. Zeeb <[email protected]> CommitDate: 2026-02-26 23:02:27 +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 Observed with: iwlwifi mld Reviewed by: dumbbell Differential Revision: https://reviews.freebsd.org/D54841 (cherry picked from commit b615b4805a9ce83b9b86dd66d46a9f220f9f89c6) --- 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 cf8a6ffeb46c..c8d1989f669b 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);
