mirror of https://gitee.com/openkylin/linux.git
net: stmmac: ensure that the MSS desc is the last desc to set the own bit
A dma_wmb() is used to guarantee the ordering, with respect to other writes, to cache coherent DMA memory. There is a dma_wmb() in prepare_tx_desc()/prepare_tso_tx_desc() which ensures that TDES0/1/2 is written before TDES3 (which contains the own bit), for First Desc. However, in the rare case that MSS changes, there will be a MSS context descriptor in front of the regular DMA descriptors: <MSS desc> <- DMA Next Descriptor <First Desc> <desc n> <Last Desc> Thus, for this special case, we need a dma_wmb() after prepare_tso_tx_desc()/before writing the own bit to the MSS desc, so that we flush the write to TDES3 for First Desc, in order to ensure that the MSS descriptor is the last descriptor to set the own bit. Signed-off-by: Niklas Cassel <niklas.cassel@axis.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
f4155eff1f
commit
15d2ee42a3
|
@ -2983,8 +2983,15 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
tcp_hdrlen(skb) / 4, (skb->len - proto_hdr_len));
|
||||
|
||||
/* If context desc is used to change MSS */
|
||||
if (mss_desc)
|
||||
if (mss_desc) {
|
||||
/* Make sure that first descriptor has been completely
|
||||
* written, including its own bit. This is because MSS is
|
||||
* actually before first descriptor, so we need to make
|
||||
* sure that MSS's own bit is the last thing written.
|
||||
*/
|
||||
dma_wmb();
|
||||
priv->hw->desc->set_tx_owner(mss_desc);
|
||||
}
|
||||
|
||||
/* The own bit must be the latest setting done when prepare the
|
||||
* descriptor and then barrier is needed to make sure that
|
||||
|
|
Loading…
Reference in New Issue