diff options
author | Sathya Perla <sathya.perla@emulex.com> | 2010-11-30 20:04:17 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-12-06 15:59:08 -0500 |
commit | 6464281161e46254ac39505ad41d21dbe7d1738f (patch) | |
tree | a85efd96c46bada5c8226b2a02944295e9bec800 /drivers/net | |
parent | 359a972fae84242efa26b86bf09c3ac3784405ba (diff) |
be2net: Handle out of buffer completions for lancer
If Lancer chip does not have posted RX buffers, it posts an RX completion entry
with the same frag_index as the last valid completion. The Error bit is also
set. In BE, a flush completion is indicated with a zero value for num_rcvd in
the completion.
Such completions don't carry any data and are not processed.
This patch refactors code to handle both cases with the same code.
Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/benet/be.h | 4 | ||||
-rw-r--r-- | drivers/net/benet/be_main.c | 55 |
2 files changed, 38 insertions, 21 deletions
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index b61a1dfebcaf..9cab32328bba 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h | |||
@@ -220,7 +220,9 @@ struct be_rx_obj { | |||
220 | struct be_rx_stats stats; | 220 | struct be_rx_stats stats; |
221 | u8 rss_id; | 221 | u8 rss_id; |
222 | bool rx_post_starved; /* Zero rx frags have been posted to BE */ | 222 | bool rx_post_starved; /* Zero rx frags have been posted to BE */ |
223 | u32 cache_line_barrier[16]; | 223 | u16 last_frag_index; |
224 | u16 rsvd; | ||
225 | u32 cache_line_barrier[15]; | ||
224 | }; | 226 | }; |
225 | 227 | ||
226 | struct be_vf_cfg { | 228 | struct be_vf_cfg { |
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index ea8cf690a072..0b35e4a8bf19 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c | |||
@@ -911,11 +911,17 @@ static void be_rx_compl_discard(struct be_adapter *adapter, | |||
911 | rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); | 911 | rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); |
912 | num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); | 912 | num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); |
913 | 913 | ||
914 | for (i = 0; i < num_rcvd; i++) { | 914 | /* Skip out-of-buffer compl(lancer) or flush compl(BE) */ |
915 | page_info = get_rx_page_info(adapter, rxo, rxq_idx); | 915 | if (likely(rxq_idx != rxo->last_frag_index && num_rcvd != 0)) { |
916 | put_page(page_info->page); | 916 | |
917 | memset(page_info, 0, sizeof(*page_info)); | 917 | rxo->last_frag_index = rxq_idx; |
918 | index_inc(&rxq_idx, rxq->len); | 918 | |
919 | for (i = 0; i < num_rcvd; i++) { | ||
920 | page_info = get_rx_page_info(adapter, rxo, rxq_idx); | ||
921 | put_page(page_info->page); | ||
922 | memset(page_info, 0, sizeof(*page_info)); | ||
923 | index_inc(&rxq_idx, rxq->len); | ||
924 | } | ||
919 | } | 925 | } |
920 | } | 926 | } |
921 | 927 | ||
@@ -1016,9 +1022,6 @@ static void be_rx_compl_process(struct be_adapter *adapter, | |||
1016 | u8 vtm; | 1022 | u8 vtm; |
1017 | 1023 | ||
1018 | num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); | 1024 | num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); |
1019 | /* Is it a flush compl that has no data */ | ||
1020 | if (unlikely(num_rcvd == 0)) | ||
1021 | return; | ||
1022 | 1025 | ||
1023 | skb = netdev_alloc_skb_ip_align(adapter->netdev, BE_HDR_LEN); | 1026 | skb = netdev_alloc_skb_ip_align(adapter->netdev, BE_HDR_LEN); |
1024 | if (unlikely(!skb)) { | 1027 | if (unlikely(!skb)) { |
@@ -1075,10 +1078,6 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, | |||
1075 | u8 pkt_type; | 1078 | u8 pkt_type; |
1076 | 1079 | ||
1077 | num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); | 1080 | num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); |
1078 | /* Is it a flush compl that has no data */ | ||
1079 | if (unlikely(num_rcvd == 0)) | ||
1080 | return; | ||
1081 | |||
1082 | pkt_size = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); | 1081 | pkt_size = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); |
1083 | vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); | 1082 | vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); |
1084 | rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); | 1083 | rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); |
@@ -1349,7 +1348,7 @@ static void be_rx_q_clean(struct be_adapter *adapter, struct be_rx_obj *rxo) | |||
1349 | while ((rxcp = be_rx_compl_get(rxo)) != NULL) { | 1348 | while ((rxcp = be_rx_compl_get(rxo)) != NULL) { |
1350 | be_rx_compl_discard(adapter, rxo, rxcp); | 1349 | be_rx_compl_discard(adapter, rxo, rxcp); |
1351 | be_rx_compl_reset(rxcp); | 1350 | be_rx_compl_reset(rxcp); |
1352 | be_cq_notify(adapter, rx_cq->id, true, 1); | 1351 | be_cq_notify(adapter, rx_cq->id, false, 1); |
1353 | } | 1352 | } |
1354 | 1353 | ||
1355 | /* Then free posted rx buffer that were not used */ | 1354 | /* Then free posted rx buffer that were not used */ |
@@ -1576,6 +1575,9 @@ static int be_rx_queues_create(struct be_adapter *adapter) | |||
1576 | adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE; | 1575 | adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE; |
1577 | for_all_rx_queues(adapter, rxo, i) { | 1576 | for_all_rx_queues(adapter, rxo, i) { |
1578 | rxo->adapter = adapter; | 1577 | rxo->adapter = adapter; |
1578 | /* Init last_frag_index so that the frag index in the first | ||
1579 | * completion will never match */ | ||
1580 | rxo->last_frag_index = 0xffff; | ||
1579 | rxo->rx_eq.max_eqd = BE_MAX_EQD; | 1581 | rxo->rx_eq.max_eqd = BE_MAX_EQD; |
1580 | rxo->rx_eq.enable_aic = true; | 1582 | rxo->rx_eq.enable_aic = true; |
1581 | 1583 | ||
@@ -1697,10 +1699,9 @@ static irqreturn_t be_msix_tx_mcc(int irq, void *dev) | |||
1697 | return IRQ_HANDLED; | 1699 | return IRQ_HANDLED; |
1698 | } | 1700 | } |
1699 | 1701 | ||
1700 | static inline bool do_gro(struct be_adapter *adapter, struct be_rx_obj *rxo, | 1702 | static inline bool do_gro(struct be_rx_obj *rxo, |
1701 | struct be_eth_rx_compl *rxcp) | 1703 | struct be_eth_rx_compl *rxcp, u8 err) |
1702 | { | 1704 | { |
1703 | int err = AMAP_GET_BITS(struct amap_eth_rx_compl, err, rxcp); | ||
1704 | int tcp_frame = AMAP_GET_BITS(struct amap_eth_rx_compl, tcpf, rxcp); | 1705 | int tcp_frame = AMAP_GET_BITS(struct amap_eth_rx_compl, tcpf, rxcp); |
1705 | 1706 | ||
1706 | if (err) | 1707 | if (err) |
@@ -1717,6 +1718,8 @@ static int be_poll_rx(struct napi_struct *napi, int budget) | |||
1717 | struct be_queue_info *rx_cq = &rxo->cq; | 1718 | struct be_queue_info *rx_cq = &rxo->cq; |
1718 | struct be_eth_rx_compl *rxcp; | 1719 | struct be_eth_rx_compl *rxcp; |
1719 | u32 work_done; | 1720 | u32 work_done; |
1721 | u16 frag_index, num_rcvd; | ||
1722 | u8 err; | ||
1720 | 1723 | ||
1721 | rxo->stats.rx_polls++; | 1724 | rxo->stats.rx_polls++; |
1722 | for (work_done = 0; work_done < budget; work_done++) { | 1725 | for (work_done = 0; work_done < budget; work_done++) { |
@@ -1724,10 +1727,22 @@ static int be_poll_rx(struct napi_struct *napi, int budget) | |||
1724 | if (!rxcp) | 1727 | if (!rxcp) |
1725 | break; | 1728 | break; |
1726 | 1729 | ||
1727 | if (do_gro(adapter, rxo, rxcp)) | 1730 | err = AMAP_GET_BITS(struct amap_eth_rx_compl, err, rxcp); |
1728 | be_rx_compl_process_gro(adapter, rxo, rxcp); | 1731 | frag_index = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, |
1729 | else | 1732 | rxcp); |
1730 | be_rx_compl_process(adapter, rxo, rxcp); | 1733 | num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, |
1734 | rxcp); | ||
1735 | |||
1736 | /* Skip out-of-buffer compl(lancer) or flush compl(BE) */ | ||
1737 | if (likely(frag_index != rxo->last_frag_index && | ||
1738 | num_rcvd != 0)) { | ||
1739 | rxo->last_frag_index = frag_index; | ||
1740 | |||
1741 | if (do_gro(rxo, rxcp, err)) | ||
1742 | be_rx_compl_process_gro(adapter, rxo, rxcp); | ||
1743 | else | ||
1744 | be_rx_compl_process(adapter, rxo, rxcp); | ||
1745 | } | ||
1731 | 1746 | ||
1732 | be_rx_compl_reset(rxcp); | 1747 | be_rx_compl_reset(rxcp); |
1733 | } | 1748 | } |