Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 10 Feb 2026 00:46:42 +0000
From:      Bjoern A. Zeeb <bz@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: b615b4805a9c - main - LinuxKPI: expand dma_sync_single_for_cpu() in lkpi_dma_unmap()
Message-ID:  <698a7ff2.31b05.13e51dcf@gitrepo.freebsd.org>

index | next in thread | raw e-mail

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);


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?698a7ff2.31b05.13e51dcf>