[PATCH v2 4/6] dmaengine: plx_dma: add dma_rmb() after observing write-back status

From: Logan Gunthorpe

Date: Tue Nov 10 2026 - 12:46:10 EST


Completing a descriptor involves two loads that must be ordered:

1. Reading desc->hw->flags_and_size and checking that VALID is clear.
2. Reading the destination buffer, which may happen in:
a. dma_unmap_page() via dmaengine_unmap(), when a bounce buffer
is in use.
b. The client's callback, or its processing after polling with
tx_status().

On a weakly ordered CPU like arm64, nothing forces load 2 to happen
after load 1, even though load 2 is only reached when load 1 says the
transfer is done. The CPU can predict that the VALID check won't
break out of the loop and issue load 2 early. If the device hadn't
finished writing at that moment, load 2 returns stale data, and when
load 1 then confirms the prediction nothing is redone, so the stale
data is used. This is the load-load control dependency case described
in Documentation/memory-barriers.txt.

Add a dma_rmb() after the status check so loads after it can't be
satisfied before the status read.

Reported-by: Sashiko <sashiko-bot@xxxxxxxxxx>
Link: https://lore.kernel.org/dmaengine/20260717223217.B6FBF1F000E9@xxxxxxxxxxxxxxx
Signed-off-by: Logan Gunthorpe <logang@xxxxxxxxxxxx>
---
drivers/dma/plx_dma.c | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/drivers/dma/plx_dma.c b/drivers/dma/plx_dma.c
index 1c995f0c4463..83c920eb173d 100644
--- a/drivers/dma/plx_dma.c
+++ b/drivers/dma/plx_dma.c
@@ -148,6 +148,13 @@ static void plx_dma_process_desc(struct plx_dma_dev *plxdev)
if (flags & PLX_DESC_FLAG_VALID)
break;

+ /*
+ * Don't allow any read of the data the device wrote to be
+ * performed before the status read above shows the
+ * descriptor is complete.
+ */
+ dma_rmb();
+
res.residue = desc->orig_size - (flags & PLX_DESC_SIZE_MASK);

if (flags & PLX_DESC_WB_SUCCESS)
--
2.47.3