From: Emmanuel Grumbach iwl_pcie_rx_handle() reads the last closed RB index from rb_stts and then reads the completion descriptor and the RB contents that this index makes visible. Nothing orders those two reads: there is no barrier, the descriptor address derives from rxq->read rather than from the index just read, so there is no address dependency, and the "while (i != r)" test is only a control dependency, which does not order loads on arm64. The CPU can therefore speculate past the loop test, perform the completion descriptor load early and sample the value from before the device's DMA, then resolve the rb_stts load to the value from after it. On arm64 (Jetson AGX Orin) this showed up as recurring "Invalid rxb from HW " naming an in-range rbid the driver still owned, and "frame on invalid queue" for an RB tagged with the queue that used it before the wrap. Both force an NMI and a firmware restart. x86 never shows it because loads are not reordered with loads there. Add a dma_rmb() after reading the write pointer, as other NIC drivers do when consuming a DMA descriptor ring. It is a no-op on x86 and a dmb on arm64. Verified to stop the warnings on Orin. Signed-off-by: Emmanuel Grumbach Assisted-by: GitHub-Copilot:claude-opus-5 Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index eb70922cf516..d1ef0365b932 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -1519,6 +1519,11 @@ static int iwl_pcie_rx_handle(struct iwl_trans *trans, int queue, int budget) r = iwl_get_closed_rb_stts(trans, rxq); i = rxq->read; + /* Order the read of the write pointer before any read of the + * completion descriptors and of the RB contents it makes visible. + */ + dma_rmb(); + /* W/A 9000 device step A0 wrap-around bug */ r &= (rxq->queue_size - 1); -- 2.34.1