Skip to content

Commit 5370c31

Browse files
prabhakarladkuba-moo
authored andcommitted
net: ravb: Enforce descriptor type ordering
Ensure the TX descriptor type fields are published in a safe order so the DMA engine never begins processing a descriptor chain before all descriptor fields are fully initialised. For multi-descriptor transmits the driver writes DT_FEND into the last descriptor and DT_FSTART into the first. The DMA engine begins processing when it observes DT_FSTART. Move the dma_wmb() barrier so it executes immediately after DT_FEND and immediately before writing DT_FSTART (and before DT_FSINGLE in the single-descriptor case). This guarantees that all prior CPU writes to the descriptor memory are visible to the device before DT_FSTART is seen. This avoids a situation where compiler/CPU reordering could publish DT_FSTART ahead of DT_FEND or other descriptor fields, allowing the DMA to start on a partially initialised chain and causing corrupted transmissions or TX timeouts. Such a failure was observed on RZ/G2L with an RT kernel as transmit queue timeouts and device resets. Fixes: 2f45d19 ("ravb: minimize TX data copying") Cc: stable@vger.kernel.org Co-developed-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com> Signed-off-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> Link: https://patch.msgid.link/20251017151830.171062-4-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent d63f039 commit 5370c31

1 file changed

Lines changed: 14 additions & 2 deletions

File tree

drivers/net/ethernet/renesas/ravb_main.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2211,13 +2211,25 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev)
22112211

22122212
skb_tx_timestamp(skb);
22132213
}
2214-
/* Descriptor type must be set after all the above writes */
2215-
dma_wmb();
2214+
22162215
if (num_tx_desc > 1) {
22172216
desc->die_dt = DT_FEND;
22182217
desc--;
2218+
/* When using multi-descriptors, DT_FEND needs to get written
2219+
* before DT_FSTART, but the compiler may reorder the memory
2220+
* writes in an attempt to optimize the code.
2221+
* Use a dma_wmb() barrier to make sure DT_FEND and DT_FSTART
2222+
* are written exactly in the order shown in the code.
2223+
* This is particularly important for cases where the DMA engine
2224+
* is already running when we are running this code. If the DMA
2225+
* sees DT_FSTART without the corresponding DT_FEND it will enter
2226+
* an error condition.
2227+
*/
2228+
dma_wmb();
22192229
desc->die_dt = DT_FSTART;
22202230
} else {
2231+
/* Descriptor type must be set after all the above writes */
2232+
dma_wmb();
22212233
desc->die_dt = DT_FSINGLE;
22222234
}
22232235
ravb_modify(ndev, TCCR, TCCR_TSRQ0 << q, TCCR_TSRQ0 << q);

0 commit comments

Comments
 (0)