[Bug 297155] LinuxKPI: swapped busdma sync operations in the DMA_TO_DEVICE / DMA_FROM_DEVICE PRE-sync path break streaming DMA when a mapping bounces (breaks ath10k QCA6174 on >4GB machines)
Date: Thu, 30 Jul 2026 03:19:52 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=297155
Bug ID: 297155
Summary: LinuxKPI: swapped busdma sync operations in the
DMA_TO_DEVICE / DMA_FROM_DEVICE PRE-sync path break
streaming DMA when a mapping bounces (breaks ath10k
QCA6174 on >4GB machines)
Product: Base System
Version: CURRENT
Hardware: amd64
OS: Any
Status: New
Severity: Affects Some People
Priority: ---
Component: kern
Assignee: bugs@FreeBSD.org
Reporter: fbsdbugs@westryn.net
Created attachment 273303
--> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=273303&action=edit
swapped busdma sync operations in the DMA_TO_DEVICE / DMA_FROM_DEVICE
LinuxKPI: fix swapped busdma sync ops in DMA_TO_DEVICE/FROM_DEVICE PRE-sync
dma_sync_single_for_device() and the PRE-sync switch in
linux_dma_map_sg_attrs() transpose the busdma sync operations for the
DMA_TO_DEVICE and DMA_FROM_DEVICE directions.
Per the Linux DMA API, dma_sync_single_for_device() on a DMA_TO_DEVICE
mapping must make the CPU's writes visible to the device before it reads
the buffer. For a bounce buffer that means copying the client buffer into
the bounce page, which busdma performs on BUS_DMASYNC_PREWRITE (see
bounce_bus_dmamap_sync() in sys/x86/x86/busdma_bounce.c: PREWRITE does
bcopy(client -> bounce); PREREAD moves no data). The code instead issued
BUS_DMASYNC_PREREAD for DMA_TO_DEVICE (a no-op) and BUS_DMASYNC_PREWRITE
for DMA_FROM_DEVICE.
The bug is only observable when a streaming mapping actually bounces,
i.e. a device with a sub-64-bit DMA mask on a machine with RAM above the
mask limit. Most LinuxKPI drivers use a 64-bit mask and never bounce, so
the wrong op was a harmless no-op. ath10k(4) (QCA6174) forces a 32-bit
mask via dma_set_mask_and_coherent(DMA_BIT_MASK(32)); on a >4GB machine
its BMI request buffer (DMA_TO_DEVICE) is never copied into the bounce
page, the target never sees the command, and firmware probe fails with:
ath10k0: bmi cmd took 3009 jiffies hz 1000 ret -60
ath10k0: could not get target info (-60)
ath10k0: could not probe fw (-60)
Capping physmem below 4GB (no bounce) or applying this patch both resolve
it; with the patch ath10k attaches and scans normally at full 16GB.
The POST-sync paths (dma_sync_single_for_cpu(), linux_dma_unmap_sg_attrs())
already use the conventional DMA_TO_DEVICE->POSTWRITE /
DMA_FROM_DEVICE->POSTREAD mapping; only the two PRE switches were swapped.
This change makes PRE match. DMA_BIDIRECTIONAL (PREWRITE) is unchanged.
--
You are receiving this mail because:
You are the assignee for the bug.