]>
Commit | Line | Data |
---|---|---|
da495922 GKH |
1 | From foo@baz Fri Jul 3 19:59:52 PDT 2015 |
2 | From: Ido Shamay <idos@mellanox.com> | |
3 | Date: Thu, 25 Jun 2015 11:29:42 +0300 | |
4 | Subject: net/mlx4_en: Wake TX queues only when there's enough room | |
5 | ||
6 | From: Ido Shamay <idos@mellanox.com> | |
7 | ||
8 | [ Upstream commit 488a9b48e398b157703766e2cd91ea45ac6997c5 ] | |
9 | ||
10 | Indication of a single completed packet, marked by txbbs_skipped | |
11 | being bigger then zero, in not enough in order to wake up a | |
12 | stopped TX queue. The completed packet may contain a single TXBB, | |
13 | while next packet to be sent (after the wake up) may have multiple | |
14 | TXBBs (LSO/TSO packets for example), causing overflow in queue followed | |
15 | by WQE corruption and TX queue timeout. | |
16 | Instead, wake the stopped queue only when there's enough room for the | |
17 | worst case (maximum sized WQE) packet that we should need to handle after | |
18 | the queue is opened again. | |
19 | ||
20 | Also created an helper routine - mlx4_en_is_tx_ring_full, which checks | |
21 | if the current TX ring is full or not. It provides better code readability | |
22 | and removes code duplication. | |
23 | ||
24 | Signed-off-by: Ido Shamay <idos@mellanox.com> | |
25 | Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> | |
26 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
27 | Signed-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; |