Skip to content

Commit 0791e68

Browse files
prabhakarladgregkh
authored andcommitted
net: ravb: Enforce descriptor type ordering
[ Upstream commit 5370c31 ] 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: [email protected] Co-developed-by: Fabrizio Castro <[email protected]> Signed-off-by: Fabrizio Castro <[email protected]> Signed-off-by: Lad Prabhakar <[email protected]> Reviewed-by: Niklas Söderlund <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]> [ kept unconditional skb_tx_timestamp() ] Signed-off-by: Sasha Levin <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent ad36e20 commit 0791e68

File tree

1 file changed

+14
-2
lines changed

1 file changed

+14
-2
lines changed

drivers/net/ethernet/renesas/ravb_main.c

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

15981598
skb_tx_timestamp(skb);
1599-
/* Descriptor type must be set after all the above writes */
1600-
dma_wmb();
1599+
16011600
if (num_tx_desc > 1) {
16021601
desc->die_dt = DT_FEND;
16031602
desc--;
1603+
/* When using multi-descriptors, DT_FEND needs to get written
1604+
* before DT_FSTART, but the compiler may reorder the memory
1605+
* writes in an attempt to optimize the code.
1606+
* Use a dma_wmb() barrier to make sure DT_FEND and DT_FSTART
1607+
* are written exactly in the order shown in the code.
1608+
* This is particularly important for cases where the DMA engine
1609+
* is already running when we are running this code. If the DMA
1610+
* sees DT_FSTART without the corresponding DT_FEND it will enter
1611+
* an error condition.
1612+
*/
1613+
dma_wmb();
16041614
desc->die_dt = DT_FSTART;
16051615
} else {
1616+
/* Descriptor type must be set after all the above writes */
1617+
dma_wmb();
16061618
desc->die_dt = DT_FSINGLE;
16071619
}
16081620

0 commit comments

Comments
 (0)