diff options
| author | Bjoern A. Zeeb <bz@FreeBSD.org> | 2026-01-23 19:14:18 +0000 |
|---|---|---|
| committer | Bjoern A. Zeeb <bz@FreeBSD.org> | 2026-02-09 21:40:47 +0000 |
| commit | b615b4805a9ce83b9b86dd66d46a9f220f9f89c6 (patch) | |
| tree | 444558a1465b7394ad0cb33e8aaff51b99fffe71 | |
| parent | 840f478eed2ab18abd1088aa12587bb708a46b56 (diff) | |
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
| -rw-r--r-- | sys/compat/linuxkpi/common/src/linux_pci.c | 21 |
1 files 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); |
