aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSathya Perla <sathya.perla@emulex.com>2010-11-30 20:04:17 -0500
committerDavid S. Miller <davem@davemloft.net>2010-12-06 15:59:08 -0500
commit6464281161e46254ac39505ad41d21dbe7d1738f (patch)
treea85efd96c46bada5c8226b2a02944295e9bec800 /drivers
parent359a972fae84242efa26b86bf09c3ac3784405ba (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')
-rw-r--r--drivers/net/benet/be.h4
-rw-r--r--drivers/net/benet/be_main.c55
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
226struct be_vf_cfg { 228struct 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
1700static inline bool do_gro(struct be_adapter *adapter, struct be_rx_obj *rxo, 1702static 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 }