John Lo | 23650e6 | 2016-03-29 16:14:35 -0400 | [diff] [blame^] | 1 | commit 67c4432ec364ce21f5059ba0696a9d0f3393356c |
| 2 | Author: John Daley <johndale@cisco.com> |
| 3 | Date: Thu Mar 24 14:00:39 2016 -0700 |
| 4 | |
| 5 | enic: fix TX hang when number of packets > queue size |
| 6 | |
| 7 | If the nb_pkts parameter to rte_eth_tx_burst() was greater than |
| 8 | the TX descriptor count, a completion was not being requested |
| 9 | from the NIC, so descriptors would not be released back to the |
| 10 | host causing a lock-up. |
| 11 | |
| 12 | Introduce a limit of how many TX descriptors can be used in a single |
| 13 | call to the enic PMD burst TX function before requesting a completion. |
| 14 | |
| 15 | Fixes: d739ba4c6abf ("enic: improve Tx packet rate") |
| 16 | |
| 17 | Signed-off-by: John Daley <johndale@cisco.com> |
| 18 | |
| 19 | diff --git a/drivers/net/enic/enic_ethdev.c b/drivers/net/enic/enic_ethdev.c |
| 20 | index 4969476..6bea940 100644 |
| 21 | --- a/drivers/net/enic/enic_ethdev.c |
| 22 | +++ b/drivers/net/enic/enic_ethdev.c |
| 23 | @@ -523,7 +523,7 @@ static void enicpmd_remove_mac_addr(struct rte_eth_dev *eth_dev, __rte_unused ui |
| 24 | static uint16_t enicpmd_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, |
| 25 | uint16_t nb_pkts) |
| 26 | { |
| 27 | - unsigned int index; |
| 28 | + uint16_t index; |
| 29 | unsigned int frags; |
| 30 | unsigned int pkt_len; |
| 31 | unsigned int seg_len; |
| 32 | @@ -535,6 +535,7 @@ static uint16_t enicpmd_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, |
| 33 | unsigned short vlan_id; |
| 34 | unsigned short ol_flags; |
| 35 | uint8_t last_seg, eop; |
| 36 | + unsigned int host_tx_descs = 0; |
| 37 | |
| 38 | for (index = 0; index < nb_pkts; index++) { |
| 39 | tx_pkt = *tx_pkts++; |
| 40 | @@ -550,6 +551,7 @@ static uint16_t enicpmd_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, |
| 41 | return index; |
| 42 | } |
| 43 | } |
| 44 | + |
| 45 | pkt_len = tx_pkt->pkt_len; |
| 46 | vlan_id = tx_pkt->vlan_tci; |
| 47 | ol_flags = tx_pkt->ol_flags; |
| 48 | @@ -559,9 +561,19 @@ static uint16_t enicpmd_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, |
| 49 | next_tx_pkt = tx_pkt->next; |
| 50 | seg_len = tx_pkt->data_len; |
| 51 | inc_len += seg_len; |
| 52 | - eop = (pkt_len == inc_len) || (!next_tx_pkt); |
| 53 | - last_seg = eop && |
| 54 | - (index == ((unsigned int)nb_pkts - 1)); |
| 55 | + |
| 56 | + host_tx_descs++; |
| 57 | + last_seg = 0; |
| 58 | + eop = 0; |
| 59 | + if ((pkt_len == inc_len) || !next_tx_pkt) { |
| 60 | + eop = 1; |
| 61 | + /* post if last packet in batch or > thresh */ |
| 62 | + if ((index == (nb_pkts - 1)) || |
| 63 | + (host_tx_descs > ENIC_TX_POST_THRESH)) { |
| 64 | + last_seg = 1; |
| 65 | + host_tx_descs = 0; |
| 66 | + } |
| 67 | + } |
| 68 | enic_send_pkt(enic, wq, tx_pkt, (unsigned short)seg_len, |
| 69 | !frags, eop, last_seg, ol_flags, vlan_id); |
| 70 | tx_pkt = next_tx_pkt; |
| 71 | diff --git a/drivers/net/enic/enic_res.h b/drivers/net/enic/enic_res.h |
| 72 | index 33f2e84..00fa71d 100644 |
| 73 | --- a/drivers/net/enic/enic_res.h |
| 74 | +++ b/drivers/net/enic/enic_res.h |
| 75 | @@ -53,6 +53,7 @@ |
| 76 | |
| 77 | #define ENIC_NON_TSO_MAX_DESC 16 |
| 78 | #define ENIC_DEFAULT_RX_FREE_THRESH 32 |
| 79 | +#define ENIC_TX_POST_THRESH (ENIC_MIN_WQ_DESCS / 2) |
| 80 | |
| 81 | #define ENIC_SETTING(enic, f) ((enic->config.flags & VENETF_##f) ? 1 : 0) |
| 82 | |