diff options
author | Ioana Ciornei <ioana.ciornei@nxp.com> | 2019-03-25 09:06:22 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-03-26 14:43:49 -0400 |
commit | 8c838f53e149871561a9261ac768a9c7071b43d0 (patch) | |
tree | a9d0da277442fb698f59afdc7f0b40901bb1c19e | |
parent | 047a013f8d0af8299ce2d02af152de6a30165ccc (diff) |
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: 569dac6a5a0d ("dpaa2-eth: bql support")
Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 13 |
1 files changed, 9 insertions, 4 deletions
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c index 1a68052abb94..dc339dc1adb2 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | |||
@@ -815,6 +815,14 @@ static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev) | |||
815 | */ | 815 | */ |
816 | queue_mapping = skb_get_queue_mapping(skb); | 816 | queue_mapping = skb_get_queue_mapping(skb); |
817 | fq = &priv->fq[queue_mapping]; | 817 | fq = &priv->fq[queue_mapping]; |
818 | |||
819 | fd_len = dpaa2_fd_get_len(&fd); | ||
820 | nq = netdev_get_tx_queue(net_dev, queue_mapping); | ||
821 | netdev_tx_sent_queue(nq, fd_len); | ||
822 | |||
823 | /* Everything that happens after this enqueues might race with | ||
824 | * the Tx confirmation callback for this frame | ||
825 | */ | ||
818 | for (i = 0; i < DPAA2_ETH_ENQUEUE_RETRIES; i++) { | 826 | for (i = 0; i < DPAA2_ETH_ENQUEUE_RETRIES; i++) { |
819 | err = priv->enqueue(priv, fq, &fd, 0); | 827 | err = priv->enqueue(priv, fq, &fd, 0); |
820 | if (err != -EBUSY) | 828 | if (err != -EBUSY) |
@@ -825,13 +833,10 @@ static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev) | |||
825 | percpu_stats->tx_errors++; | 833 | percpu_stats->tx_errors++; |
826 | /* Clean up everything, including freeing the skb */ | 834 | /* Clean up everything, including freeing the skb */ |
827 | free_tx_fd(priv, fq, &fd, false); | 835 | free_tx_fd(priv, fq, &fd, false); |
836 | netdev_tx_completed_queue(nq, 1, fd_len); | ||
828 | } else { | 837 | } else { |
829 | fd_len = dpaa2_fd_get_len(&fd); | ||
830 | percpu_stats->tx_packets++; | 838 | percpu_stats->tx_packets++; |
831 | percpu_stats->tx_bytes += fd_len; | 839 | percpu_stats->tx_bytes += fd_len; |
832 | |||
833 | nq = netdev_get_tx_queue(net_dev, queue_mapping); | ||
834 | netdev_tx_sent_queue(nq, fd_len); | ||
835 | } | 840 | } |
836 | 841 | ||
837 | return NETDEV_TX_OK; | 842 | return NETDEV_TX_OK; |