Page MenuHomeFreeBSD

linuxkpi: Fix DMA_BIDIRECTIONAL mapping
Needs ReviewPublic

Authored by zishun.yi.dev_gmail.com on Feb 25 2026, 5:28 AM.
Tags
None
Referenced Files
Unknown Object (File)
Thu, Jun 25, 5:49 AM
Unknown Object (File)
Thu, Jun 25, 4:05 AM
Unknown Object (File)
Wed, Jun 24, 4:01 AM
Unknown Object (File)
Fri, Jun 5, 1:11 AM
Unknown Object (File)
May 17 2026, 2:45 PM
Unknown Object (File)
May 14 2026, 3:51 AM
Unknown Object (File)
May 14 2026, 1:41 AM
Unknown Object (File)
May 12 2026, 12:54 PM
Subscribers

Details

Reviewers
bz
Group Reviewers
linuxkpi
Summary

In dma_sync_single_for_cpu(), the DMA_BIDIRECTIONAL direction currently
performs BUS_DMASYNC_POSTREAD followed by BUS_DMASYNC_PREREAD. This
patch corrects the mapping to use BUS_DMASYNC_POSTREAD |
BUS_DMASYNC_POSTWRITE.

When ownership of the DMA area is transferred to the CPU, we must assume
the previous device access was bidirectional. Both POST operations are
necessary to ensure the CPU sees a consistent view of memory after
potential device reads and writes. A PREREAD is unnecessary here because
the device will no longer access the memory since ownership has been
transferred to the CPU.

Conversely, for dma_sync_single_for_device(), ownership is being
transferred back to the hardware. The buffer must be prepared for
potential bidirectional access by the device, requiring
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE.

PR: 293381
Reported by: Zishun Yi <zishun.yi.dev@gmail.com>
Fixes: 95edb10b47fc ("LinuxKPI: implement dma_sync_single_for_*, apply to (un)map single/sg")
Signed-off-by: Zishun Yi <zishun.yi.dev@gmail.com>

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 74140
Build 71023: arc lint + arc unit

Event Timeline

Isn't this closer to what I once had and hselasky said I should change?
Hah. I came back to this reivew to find the above question unsubmitted. I guess I left it for myself and lost the window.

Bumping this that I may have a look the next days hopefully.

In D55497#1320154, @bz wrote:

Isn't this closer to what I once had and hselasky said I should change?

IMO, hselasky said we cannot pass multiple flags to the non-bidirectional DMA cases. I think that is correct.
But I guess his thought was that some USB controllers might access the DMA buffer after the dma_sync_single_for_cpu, so he added the PREREAD flag. However, under Linux semantics, the device should not access the DMA buffer after the dma_sync_single_for_cpu.

I re-read the manual today:

BUS_DMASYNC_PREREAD    Perform any synchronization required prior
                       to an update of host memory by the device.

BUS_DMASYNC_PREWRITE   Perform any synchronization required after
                       an update of host memory by the CPU and
                       prior to device access to host memory.

BUS_DMASYNC_POSTREAD   Perform any synchronization required after
                       an update of host memory by the device and
                       prior to CPU access to host memory.

BUS_DMASYNC_POSTWRITE  Perform any synchronization required after
                       device access to host memory.

I think the code flow should be similar to:

preread -> device update memory -> postread-> cpu can read memory
cpu update memory -> prewrite -> device read memory -> postwrite

So, for dma_sync_single_for_cpu with DMA_BIDIRECTIONAL, it should use the two operations after device update memory and device read memory (i.e., POSTREAD and POSTWRITE).

Based on the code flow I mentioned above, I found that the DMA_TO_DEVICE and
DMA_FROM_DEVICE directions in dma_sync_single_for_device might be reversed.