ibmvnic: Fix TX descriptor tracking again
authorThomas Falcon <tlfalcon@linux.vnet.ibm.com>
Tue, 27 Feb 2018 00:10:55 +0000 (18:10 -0600)
committerDavid S. Miller <davem@davemloft.net>
Tue, 27 Feb 2018 19:31:19 +0000 (14:31 -0500)
Sorry, the previous change introduced a race condition between
transmit completion processing and tracking TX descriptors. If a
completion is received before the number of descriptors is logged,
the number of descriptors will be add but not removed. After enough
times, this could halt the transmit queue forever.

Log the number of descriptors used by a transmit before sending.
I stress tested the fix on two different systems running over the
weekend without any issues.

Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/ibm/ibmvnic.c

index 5a86a916492cc2f6d3301097fab008d2a6e31399..32ee202de13abda4fb195629148184042f752ca3 100644 (file)
@@ -1482,6 +1482,7 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
        if ((*hdrs >> 7) & 1) {
                build_hdr_descs_arr(tx_buff, &num_entries, *hdrs);
                tx_crq.v1.n_crq_elem = num_entries;
+               tx_buff->num_entries = num_entries;
                tx_buff->indir_arr[0] = tx_crq;
                tx_buff->indir_dma = dma_map_single(dev, tx_buff->indir_arr,
                                                    sizeof(tx_buff->indir_arr),
@@ -1500,6 +1501,7 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
                                               (u64)tx_buff->indir_dma,
                                               (u64)num_entries);
        } else {
+               tx_buff->num_entries = num_entries;
                lpar_rc = send_subcrq(adapter, handle_array[queue_num],
                                      &tx_crq);
        }
@@ -1536,7 +1538,6 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
                netif_stop_subqueue(netdev, queue_num);
        }
 
-       tx_buff->num_entries = num_entries;
        tx_packets++;
        tx_bytes += skb->len;
        txq->trans_start = jiffies;