diff options
author | Sathya Perla <sathyap@serverengines.com> | 2010-02-16 20:35:26 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-17 16:35:39 -0500 |
commit | 89420424fce28769c338909393518087befe8b37 (patch) | |
tree | 1f3f40831ff18d40200bb8ff808d87ab5dbe9f48 /drivers/net/benet | |
parent | 7a1e9b2059d147461cff3dfbabbfb43f296a1eef (diff) |
be2net: fix rx-path to ignore a flush completion
The flush compl (compl with numfrags == 0; no data) is rcvd
from hw to indicate completion of RXQ destory operation. Fix
the RX path to not process it as RX data.
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 | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 43dbe288a5ef..2c3deadd2d83 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c | |||
@@ -680,17 +680,17 @@ static void be_rx_compl_discard(struct be_adapter *adapter, | |||
680 | * indicated by rxcp. | 680 | * indicated by rxcp. |
681 | */ | 681 | */ |
682 | static void skb_fill_rx_data(struct be_adapter *adapter, | 682 | static void skb_fill_rx_data(struct be_adapter *adapter, |
683 | struct sk_buff *skb, struct be_eth_rx_compl *rxcp) | 683 | struct sk_buff *skb, struct be_eth_rx_compl *rxcp, |
684 | u16 num_rcvd) | ||
684 | { | 685 | { |
685 | struct be_queue_info *rxq = &adapter->rx_obj.q; | 686 | struct be_queue_info *rxq = &adapter->rx_obj.q; |
686 | struct be_rx_page_info *page_info; | 687 | struct be_rx_page_info *page_info; |
687 | u16 rxq_idx, i, num_rcvd, j; | 688 | u16 rxq_idx, i, j; |
688 | u32 pktsize, hdr_len, curr_frag_len, size; | 689 | u32 pktsize, hdr_len, curr_frag_len, size; |
689 | u8 *start; | 690 | u8 *start; |
690 | 691 | ||
691 | rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); | 692 | rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); |
692 | pktsize = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); | 693 | pktsize = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); |
693 | num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); | ||
694 | 694 | ||
695 | page_info = get_rx_page_info(adapter, rxq_idx); | 695 | page_info = get_rx_page_info(adapter, rxq_idx); |
696 | 696 | ||
@@ -766,8 +766,14 @@ static void be_rx_compl_process(struct be_adapter *adapter, | |||
766 | { | 766 | { |
767 | struct sk_buff *skb; | 767 | struct sk_buff *skb; |
768 | u32 vlanf, vid; | 768 | u32 vlanf, vid; |
769 | u16 num_rcvd; | ||
769 | u8 vtm; | 770 | u8 vtm; |
770 | 771 | ||
772 | num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); | ||
773 | /* Is it a flush compl that has no data */ | ||
774 | if (unlikely(num_rcvd == 0)) | ||
775 | return; | ||
776 | |||
771 | skb = netdev_alloc_skb_ip_align(adapter->netdev, BE_HDR_LEN); | 777 | skb = netdev_alloc_skb_ip_align(adapter->netdev, BE_HDR_LEN); |
772 | if (unlikely(!skb)) { | 778 | if (unlikely(!skb)) { |
773 | if (net_ratelimit()) | 779 | if (net_ratelimit()) |
@@ -776,7 +782,7 @@ static void be_rx_compl_process(struct be_adapter *adapter, | |||
776 | return; | 782 | return; |
777 | } | 783 | } |
778 | 784 | ||
779 | skb_fill_rx_data(adapter, skb, rxcp); | 785 | skb_fill_rx_data(adapter, skb, rxcp, num_rcvd); |
780 | 786 | ||
781 | if (do_pkt_csum(rxcp, adapter->rx_csum)) | 787 | if (do_pkt_csum(rxcp, adapter->rx_csum)) |
782 | skb->ip_summed = CHECKSUM_NONE; | 788 | skb->ip_summed = CHECKSUM_NONE; |
@@ -823,6 +829,10 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, | |||
823 | u8 vtm; | 829 | u8 vtm; |
824 | 830 | ||
825 | num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); | 831 | num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); |
832 | /* Is it a flush compl that has no data */ | ||
833 | if (unlikely(num_rcvd == 0)) | ||
834 | return; | ||
835 | |||
826 | pkt_size = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); | 836 | pkt_size = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); |
827 | vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); | 837 | vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); |
828 | rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); | 838 | rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); |
@@ -1273,6 +1283,11 @@ static void be_rx_queues_destroy(struct be_adapter *adapter) | |||
1273 | q = &adapter->rx_obj.q; | 1283 | q = &adapter->rx_obj.q; |
1274 | if (q->created) { | 1284 | if (q->created) { |
1275 | be_cmd_q_destroy(adapter, q, QTYPE_RXQ); | 1285 | be_cmd_q_destroy(adapter, q, QTYPE_RXQ); |
1286 | |||
1287 | /* After the rxq is invalidated, wait for a grace time | ||
1288 | * of 1ms for all dma to end and the flush compl to arrive | ||
1289 | */ | ||
1290 | mdelay(1); | ||
1276 | be_rx_q_clean(adapter); | 1291 | be_rx_q_clean(adapter); |
1277 | } | 1292 | } |
1278 | be_queue_free(adapter, q); | 1293 | be_queue_free(adapter, q); |