]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.0.8/net-mlx4_en-wake-tx-queues-only-when-there-s-enough-room.patch
5.0-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.0.8 / net-mlx4_en-wake-tx-queues-only-when-there-s-enough-room.patch
CommitLineData
da495922
GKH
1From foo@baz Fri Jul 3 19:59:52 PDT 2015
2From: Ido Shamay <idos@mellanox.com>
3Date: Thu, 25 Jun 2015 11:29:42 +0300
4Subject: net/mlx4_en: Wake TX queues only when there's enough room
5
6From: Ido Shamay <idos@mellanox.com>
7
8[ Upstream commit 488a9b48e398b157703766e2cd91ea45ac6997c5 ]
9
10Indication of a single completed packet, marked by txbbs_skipped
11being bigger then zero, in not enough in order to wake up a
12stopped TX queue. The completed packet may contain a single TXBB,
13while next packet to be sent (after the wake up) may have multiple
14TXBBs (LSO/TSO packets for example), causing overflow in queue followed
15by WQE corruption and TX queue timeout.
16Instead, wake the stopped queue only when there's enough room for the
17worst case (maximum sized WQE) packet that we should need to handle after
18the queue is opened again.
19
20Also created an helper routine - mlx4_en_is_tx_ring_full, which checks
21if the current TX ring is full or not. It provides better code readability
22and removes code duplication.
23
24Signed-off-by: Ido Shamay <idos@mellanox.com>
25Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
26Signed-off-by: David S. Miller <davem@davemloft.net>
27Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
28---
29 drivers/net/ethernet/mellanox/mlx4/en_tx.c | 19 +++++++++++--------
30 drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 1 +
31 2 files changed, 12 insertions(+), 8 deletions(-)
32
33--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c
34+++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
35@@ -66,6 +66,7 @@ int mlx4_en_create_tx_ring(struct mlx4_e
36 ring->size = size;
37 ring->size_mask = size - 1;
38 ring->stride = stride;
39+ ring->full_size = ring->size - HEADROOM - MAX_DESC_TXBBS;
40
41 tmp = size * sizeof(struct mlx4_en_tx_info);
42 ring->tx_info = kmalloc_node(tmp, GFP_KERNEL | __GFP_NOWARN, node);
43@@ -232,6 +233,11 @@ void mlx4_en_deactivate_tx_ring(struct m
44 MLX4_QP_STATE_RST, NULL, 0, 0, &ring->qp);
45 }
46
47+static inline bool mlx4_en_is_tx_ring_full(struct mlx4_en_tx_ring *ring)
48+{
49+ return ring->prod - ring->cons > ring->full_size;
50+}
51+
52 static void mlx4_en_stamp_wqe(struct mlx4_en_priv *priv,
53 struct mlx4_en_tx_ring *ring, int index,
54 u8 owner)
55@@ -474,11 +480,10 @@ static bool mlx4_en_process_tx_cq(struct
56
57 netdev_tx_completed_queue(ring->tx_queue, packets, bytes);
58
59- /*
60- * Wakeup Tx queue if this stopped, and at least 1 packet
61- * was completed
62+ /* Wakeup Tx queue if this stopped, and ring is not full.
63 */
64- if (netif_tx_queue_stopped(ring->tx_queue) && txbbs_skipped > 0) {
65+ if (netif_tx_queue_stopped(ring->tx_queue) &&
66+ !mlx4_en_is_tx_ring_full(ring)) {
67 netif_tx_wake_queue(ring->tx_queue);
68 ring->wake_queue++;
69 }
70@@ -922,8 +927,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff
71 skb_tx_timestamp(skb);
72
73 /* Check available TXBBs And 2K spare for prefetch */
74- stop_queue = (int)(ring->prod - ring_cons) >
75- ring->size - HEADROOM - MAX_DESC_TXBBS;
76+ stop_queue = mlx4_en_is_tx_ring_full(ring);
77 if (unlikely(stop_queue)) {
78 netif_tx_stop_queue(ring->tx_queue);
79 ring->queue_stopped++;
80@@ -992,8 +996,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff
81 smp_rmb();
82
83 ring_cons = ACCESS_ONCE(ring->cons);
84- if (unlikely(((int)(ring->prod - ring_cons)) <=
85- ring->size - HEADROOM - MAX_DESC_TXBBS)) {
86+ if (unlikely(!mlx4_en_is_tx_ring_full(ring))) {
87 netif_tx_wake_queue(ring->tx_queue);
88 ring->wake_queue++;
89 }
90--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
91+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
92@@ -280,6 +280,7 @@ struct mlx4_en_tx_ring {
93 u32 size; /* number of TXBBs */
94 u32 size_mask;
95 u16 stride;
96+ u32 full_size;
97 u16 cqn; /* index of port CQ associated with this ring */
98 u32 buf_size;
99 __be32 doorbell_qpn;