dpaa2-eth: fix race condition with bql frame accounting
It might happen that Tx conf acknowledges a frame before it was
subscribed in bql, as subscribing was previously done after the enqueue
operation.
This patch moves the netdev_tx_sent_queue call before the actual frame
enqueue, so that this can never happen.
Fixes: 569dac6a5a
("dpaa2-eth: bql support")
Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
047a013f8d
commit
8c838f53e1
|
@ -815,6 +815,14 @@ static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev)
|
||||||
*/
|
*/
|
||||||
queue_mapping = skb_get_queue_mapping(skb);
|
queue_mapping = skb_get_queue_mapping(skb);
|
||||||
fq = &priv->fq[queue_mapping];
|
fq = &priv->fq[queue_mapping];
|
||||||
|
|
||||||
|
fd_len = dpaa2_fd_get_len(&fd);
|
||||||
|
nq = netdev_get_tx_queue(net_dev, queue_mapping);
|
||||||
|
netdev_tx_sent_queue(nq, fd_len);
|
||||||
|
|
||||||
|
/* Everything that happens after this enqueues might race with
|
||||||
|
* the Tx confirmation callback for this frame
|
||||||
|
*/
|
||||||
for (i = 0; i < DPAA2_ETH_ENQUEUE_RETRIES; i++) {
|
for (i = 0; i < DPAA2_ETH_ENQUEUE_RETRIES; i++) {
|
||||||
err = priv->enqueue(priv, fq, &fd, 0);
|
err = priv->enqueue(priv, fq, &fd, 0);
|
||||||
if (err != -EBUSY)
|
if (err != -EBUSY)
|
||||||
|
@ -825,13 +833,10 @@ static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev)
|
||||||
percpu_stats->tx_errors++;
|
percpu_stats->tx_errors++;
|
||||||
/* Clean up everything, including freeing the skb */
|
/* Clean up everything, including freeing the skb */
|
||||||
free_tx_fd(priv, fq, &fd, false);
|
free_tx_fd(priv, fq, &fd, false);
|
||||||
|
netdev_tx_completed_queue(nq, 1, fd_len);
|
||||||
} else {
|
} else {
|
||||||
fd_len = dpaa2_fd_get_len(&fd);
|
|
||||||
percpu_stats->tx_packets++;
|
percpu_stats->tx_packets++;
|
||||||
percpu_stats->tx_bytes += fd_len;
|
percpu_stats->tx_bytes += fd_len;
|
||||||
|
|
||||||
nq = netdev_get_tx_queue(net_dev, queue_mapping);
|
|
||||||
netdev_tx_sent_queue(nq, fd_len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
|
|
Loading…
Reference in New Issue