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)
Summary: LinuxKPI: swapped busdma sync operations in the DMA_TO_DEVICE / DMA_FROM_DEVI...
Status: New
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 16.0-CURRENT
Hardware: amd64 Any
: --- Affects Some People
Assignee: freebsd-emulation (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2026-07-30 03:19 UTC by Kim Shrier
Modified: 2026-07-30 13:17 UTC (History)
0 users

See Also:


Attachments
swapped busdma sync operations in the DMA_TO_DEVICE / DMA_FROM_DEVICE (1.34 KB, patch)
2026-07-30 03:19 UTC, Kim Shrier
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Kim Shrier 2026-07-30 03:19:52 UTC
Created attachment 273303 [details]
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.