diff options
author | Sathya Perla <sathyap@serverengines.com> | 2009-08-09 23:42:43 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-08-13 01:13:16 -0400 |
commit | a8e9179a7de196d37410fd3e9528081f22c70a4e (patch) | |
tree | b7ad488a9493feab8babdb5c00165cc5fa57a76e /drivers/net/benet | |
parent | f2341641766af3de18502abb6ac9b98e0e4c6bdb (diff) |
be2net: Clear pending tx completions before destroying tx queue
Clear pending tx completions in be_close() (ndo.stop method) so that after
unregister_netdev() calls be_close(), all tx skbs are freed and there are
no more tx completions when txq is destroyed.
Signed-off-by: Sathya Perla <sathyap@serverengines.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/benet')
-rw-r--r-- | drivers/net/benet/be_main.c | 52 |
1 files changed, 33 insertions, 19 deletions
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index d20235b16800..acce6a639324 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c | |||
@@ -1018,21 +1018,35 @@ static void be_rx_q_clean(struct be_adapter *adapter) | |||
1018 | BUG_ON(atomic_read(&rxq->used)); | 1018 | BUG_ON(atomic_read(&rxq->used)); |
1019 | } | 1019 | } |
1020 | 1020 | ||
1021 | static void be_tx_q_clean(struct be_adapter *adapter) | 1021 | static void be_tx_compl_clean(struct be_adapter *adapter) |
1022 | { | 1022 | { |
1023 | struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list; | 1023 | struct be_queue_info *tx_cq = &adapter->tx_obj.cq; |
1024 | struct sk_buff *sent_skb; | ||
1025 | struct be_queue_info *txq = &adapter->tx_obj.q; | 1024 | struct be_queue_info *txq = &adapter->tx_obj.q; |
1026 | u16 last_index; | 1025 | struct be_eth_tx_compl *txcp; |
1027 | bool dummy_wrb; | 1026 | u16 end_idx, cmpl = 0, timeo = 0; |
1028 | 1027 | ||
1029 | while (atomic_read(&txq->used)) { | 1028 | /* Wait for a max of 200ms for all the tx-completions to arrive. */ |
1030 | sent_skb = sent_skbs[txq->tail]; | 1029 | do { |
1031 | last_index = txq->tail; | 1030 | while ((txcp = be_tx_compl_get(tx_cq))) { |
1032 | index_adv(&last_index, | 1031 | end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl, |
1033 | wrb_cnt_for_skb(sent_skb, &dummy_wrb) - 1, txq->len); | 1032 | wrb_index, txcp); |
1034 | be_tx_compl_process(adapter, last_index); | 1033 | be_tx_compl_process(adapter, end_idx); |
1035 | } | 1034 | cmpl++; |
1035 | } | ||
1036 | if (cmpl) { | ||
1037 | be_cq_notify(adapter, tx_cq->id, false, cmpl); | ||
1038 | cmpl = 0; | ||
1039 | } | ||
1040 | |||
1041 | if (atomic_read(&txq->used) == 0 || ++timeo > 200) | ||
1042 | break; | ||
1043 | |||
1044 | mdelay(1); | ||
1045 | } while (true); | ||
1046 | |||
1047 | if (atomic_read(&txq->used)) | ||
1048 | dev_err(&adapter->pdev->dev, "%d pending tx-completions\n", | ||
1049 | atomic_read(&txq->used)); | ||
1036 | } | 1050 | } |
1037 | 1051 | ||
1038 | static void be_mcc_queues_destroy(struct be_adapter *adapter) | 1052 | static void be_mcc_queues_destroy(struct be_adapter *adapter) |
@@ -1091,13 +1105,8 @@ static void be_tx_queues_destroy(struct be_adapter *adapter) | |||
1091 | struct be_queue_info *q; | 1105 | struct be_queue_info *q; |
1092 | 1106 | ||
1093 | q = &adapter->tx_obj.q; | 1107 | q = &adapter->tx_obj.q; |
1094 | if (q->created) { | 1108 | if (q->created) |
1095 | be_cmd_q_destroy(adapter, q, QTYPE_TXQ); | 1109 | be_cmd_q_destroy(adapter, q, QTYPE_TXQ); |
1096 | |||
1097 | /* No more tx completions can be rcvd now; clean up if there | ||
1098 | * are any pending completions or pending tx requests */ | ||
1099 | be_tx_q_clean(adapter); | ||
1100 | } | ||
1101 | be_queue_free(adapter, q); | 1110 | be_queue_free(adapter, q); |
1102 | 1111 | ||
1103 | q = &adapter->tx_obj.cq; | 1112 | q = &adapter->tx_obj.cq; |
@@ -1645,6 +1654,11 @@ static int be_close(struct net_device *netdev) | |||
1645 | napi_disable(&rx_eq->napi); | 1654 | napi_disable(&rx_eq->napi); |
1646 | napi_disable(&tx_eq->napi); | 1655 | napi_disable(&tx_eq->napi); |
1647 | 1656 | ||
1657 | /* Wait for all pending tx completions to arrive so that | ||
1658 | * all tx skbs are freed. | ||
1659 | */ | ||
1660 | be_tx_compl_clean(adapter); | ||
1661 | |||
1648 | return 0; | 1662 | return 0; |
1649 | } | 1663 | } |
1650 | 1664 | ||