summaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorAmir Vadai <amirv@mellanox.com>2013-01-24 01:54:18 +0000
committerDavid S. Miller <davem@davemloft.net>2013-01-28 00:14:24 -0500
commit7225922558f04f25a22683ce08454dae8dd4b9f4 (patch)
tree2a3871ca8287e5f197c39d170375df8fe3c93b03 /drivers/net
parentf356fcbe12c1174713e83651b630330f8f0f8415 (diff)
downloadlinux-7225922558f04f25a22683ce08454dae8dd4b9f4.tar.bz2
net/mlx4_en: Fix a race when closing TX queue
There is a possible race where the TX completion handler can clean the entire TX queue between the decision that the queue is full and actually closing it. To avoid this situation, check again if the queue is really full, if not, reopen the transmit and continue with sending the packet. CC: Eric Dumazet <edumazet@google.com> Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.com> Signed-off-by: Eugenia Emantayev <eugenia@mellanox.com> Signed-off-by: Amir Vadai <amirv@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_tx.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
index 16af338880c3..3c5ffd2f5c6f 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
@@ -588,7 +588,21 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
netif_tx_stop_queue(ring->tx_queue);
priv->port_stats.queue_stopped++;
- return NETDEV_TX_BUSY;
+ /* If queue was emptied after the if, and before the
+ * stop_queue - need to wake the queue, or else it will remain
+ * stopped forever.
+ * Need a memory barrier to make sure ring->cons was not
+ * updated before queue was stopped.
+ */
+ wmb();
+
+ if (unlikely(((int)(ring->prod - ring->cons)) <=
+ ring->size - HEADROOM - MAX_DESC_TXBBS)) {
+ netif_tx_wake_queue(ring->tx_queue);
+ priv->port_stats.wake_queue++;
+ } else {
+ return NETDEV_TX_BUSY;
+ }
}
/* Track current inflight packets for performance analysis */