diff options
author | Ajit Khaparde <ajitk@serverengines.com> | 2009-07-21 15:36:19 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-07-23 21:00:59 -0400 |
commit | 5be93b9a865344cf69958777c8d7c6f758cba416 (patch) | |
tree | 77c85b7b47d5c9e136666927cef2f6d21280ae60 /drivers | |
parent | 2eee40c7f7c3734b28456169b2945e07d5ac0e2d (diff) |
be2net: Add GRO support to the be2net driver. LRO is not supported anymore.
This patch removes support for INET_LRO and switches over to GRO.
Signed-off-by: Ajit Khaparde <ajitk@serverengines.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/benet/Kconfig | 1 | ||||
-rw-r--r-- | drivers/net/benet/be.h | 11 | ||||
-rw-r--r-- | drivers/net/benet/be_ethtool.c | 9 | ||||
-rw-r--r-- | drivers/net/benet/be_main.c | 104 |
4 files changed, 31 insertions, 94 deletions
diff --git a/drivers/net/benet/Kconfig b/drivers/net/benet/Kconfig index c6934f179c09..fdb6e81a4374 100644 --- a/drivers/net/benet/Kconfig +++ b/drivers/net/benet/Kconfig | |||
@@ -1,7 +1,6 @@ | |||
1 | config BE2NET | 1 | config BE2NET |
2 | tristate "ServerEngines' 10Gbps NIC - BladeEngine 2" | 2 | tristate "ServerEngines' 10Gbps NIC - BladeEngine 2" |
3 | depends on PCI && INET | 3 | depends on PCI && INET |
4 | select INET_LRO | ||
5 | help | 4 | help |
6 | This driver implements the NIC functionality for ServerEngines' | 5 | This driver implements the NIC functionality for ServerEngines' |
7 | 10Gbps network adapter - BladeEngine 2. | 6 | 10Gbps network adapter - BladeEngine 2. |
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 5b4bf3d2cdc2..41cddbedbf2b 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h | |||
@@ -28,11 +28,10 @@ | |||
28 | #include <linux/if_vlan.h> | 28 | #include <linux/if_vlan.h> |
29 | #include <linux/workqueue.h> | 29 | #include <linux/workqueue.h> |
30 | #include <linux/interrupt.h> | 30 | #include <linux/interrupt.h> |
31 | #include <linux/inet_lro.h> | ||
32 | 31 | ||
33 | #include "be_hw.h" | 32 | #include "be_hw.h" |
34 | 33 | ||
35 | #define DRV_VER "2.0.348" | 34 | #define DRV_VER "2.0.400" |
36 | #define DRV_NAME "be2net" | 35 | #define DRV_NAME "be2net" |
37 | #define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC" | 36 | #define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC" |
38 | #define OC_NAME "Emulex OneConnect 10Gbps NIC" | 37 | #define OC_NAME "Emulex OneConnect 10Gbps NIC" |
@@ -72,9 +71,6 @@ static inline char *nic_name(struct pci_dev *pdev) | |||
72 | #define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */ | 71 | #define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */ |
73 | #define RX_FRAGS_REFILL_WM (RX_Q_LEN - MAX_RX_POST) | 72 | #define RX_FRAGS_REFILL_WM (RX_Q_LEN - MAX_RX_POST) |
74 | 73 | ||
75 | #define BE_MAX_LRO_DESCRIPTORS 16 | ||
76 | #define BE_MAX_FRAGS_PER_FRAME (min((u32) 16, (u32) MAX_SKB_FRAGS)) | ||
77 | |||
78 | struct be_dma_mem { | 74 | struct be_dma_mem { |
79 | void *va; | 75 | void *va; |
80 | dma_addr_t dma; | 76 | dma_addr_t dma; |
@@ -189,8 +185,6 @@ struct be_drvr_stats { | |||
189 | u32 be_polls; /* number of times NAPI called poll function */ | 185 | u32 be_polls; /* number of times NAPI called poll function */ |
190 | u32 be_rx_events; /* number of ucast rx completion events */ | 186 | u32 be_rx_events; /* number of ucast rx completion events */ |
191 | u32 be_rx_compl; /* number of rx completion entries processed */ | 187 | u32 be_rx_compl; /* number of rx completion entries processed */ |
192 | u32 be_lro_hgram_data[8]; /* histogram of LRO data packets */ | ||
193 | u32 be_lro_hgram_ack[8]; /* histogram of LRO ACKs */ | ||
194 | ulong be_rx_jiffies; | 188 | ulong be_rx_jiffies; |
195 | u64 be_rx_bytes; | 189 | u64 be_rx_bytes; |
196 | u64 be_rx_bytes_prev; | 190 | u64 be_rx_bytes_prev; |
@@ -233,8 +227,6 @@ struct be_rx_obj { | |||
233 | struct be_queue_info q; | 227 | struct be_queue_info q; |
234 | struct be_queue_info cq; | 228 | struct be_queue_info cq; |
235 | struct be_rx_page_info page_info_tbl[RX_Q_LEN]; | 229 | struct be_rx_page_info page_info_tbl[RX_Q_LEN]; |
236 | struct net_lro_mgr lro_mgr; | ||
237 | struct net_lro_desc lro_desc[BE_MAX_LRO_DESCRIPTORS]; | ||
238 | }; | 230 | }; |
239 | 231 | ||
240 | #define BE_NUM_MSIX_VECTORS 2 /* 1 each for Tx and Rx */ | 232 | #define BE_NUM_MSIX_VECTORS 2 /* 1 each for Tx and Rx */ |
@@ -271,7 +263,6 @@ struct be_adapter { | |||
271 | 263 | ||
272 | /* Ethtool knobs and info */ | 264 | /* Ethtool knobs and info */ |
273 | bool rx_csum; /* BE card must perform rx-checksumming */ | 265 | bool rx_csum; /* BE card must perform rx-checksumming */ |
274 | u32 max_rx_coal; | ||
275 | char fw_ver[FW_VER_LEN]; | 266 | char fw_ver[FW_VER_LEN]; |
276 | u32 if_handle; /* Used to configure filtering */ | 267 | u32 if_handle; /* Used to configure filtering */ |
277 | u32 pmac_id; /* MAC addr handle used by BE card */ | 268 | u32 pmac_id; /* MAC addr handle used by BE card */ |
diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index cccc5419ad72..f3f0f91e38c4 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c | |||
@@ -127,8 +127,6 @@ be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) | |||
127 | struct be_eq_obj *rx_eq = &adapter->rx_eq; | 127 | struct be_eq_obj *rx_eq = &adapter->rx_eq; |
128 | struct be_eq_obj *tx_eq = &adapter->tx_eq; | 128 | struct be_eq_obj *tx_eq = &adapter->tx_eq; |
129 | 129 | ||
130 | coalesce->rx_max_coalesced_frames = adapter->max_rx_coal; | ||
131 | |||
132 | coalesce->rx_coalesce_usecs = rx_eq->cur_eqd; | 130 | coalesce->rx_coalesce_usecs = rx_eq->cur_eqd; |
133 | coalesce->rx_coalesce_usecs_high = rx_eq->max_eqd; | 131 | coalesce->rx_coalesce_usecs_high = rx_eq->max_eqd; |
134 | coalesce->rx_coalesce_usecs_low = rx_eq->min_eqd; | 132 | coalesce->rx_coalesce_usecs_low = rx_eq->min_eqd; |
@@ -144,8 +142,7 @@ be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) | |||
144 | } | 142 | } |
145 | 143 | ||
146 | /* | 144 | /* |
147 | * This routine is used to set interrup coalescing delay *as well as* | 145 | * This routine is used to set interrup coalescing delay |
148 | * the number of pkts to coalesce for LRO. | ||
149 | */ | 146 | */ |
150 | static int | 147 | static int |
151 | be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) | 148 | be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) |
@@ -161,10 +158,6 @@ be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) | |||
161 | if (coalesce->use_adaptive_tx_coalesce == 1) | 158 | if (coalesce->use_adaptive_tx_coalesce == 1) |
162 | return -EINVAL; | 159 | return -EINVAL; |
163 | 160 | ||
164 | adapter->max_rx_coal = coalesce->rx_max_coalesced_frames; | ||
165 | if (adapter->max_rx_coal > BE_MAX_FRAGS_PER_FRAME) | ||
166 | adapter->max_rx_coal = BE_MAX_FRAGS_PER_FRAME; | ||
167 | |||
168 | /* if AIC is being turned on now, start with an EQD of 0 */ | 161 | /* if AIC is being turned on now, start with an EQD of 0 */ |
169 | if (rx_eq->enable_aic == 0 && | 162 | if (rx_eq->enable_aic == 0 && |
170 | coalesce->use_adaptive_rx_coalesce == 1) { | 163 | coalesce->use_adaptive_rx_coalesce == 1) { |
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index c43f6a119295..45df8e2d0921 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c | |||
@@ -742,7 +742,7 @@ done: | |||
742 | return; | 742 | return; |
743 | } | 743 | } |
744 | 744 | ||
745 | /* Process the RX completion indicated by rxcp when LRO is disabled */ | 745 | /* Process the RX completion indicated by rxcp when GRO is disabled */ |
746 | static void be_rx_compl_process(struct be_adapter *adapter, | 746 | static void be_rx_compl_process(struct be_adapter *adapter, |
747 | struct be_eth_rx_compl *rxcp) | 747 | struct be_eth_rx_compl *rxcp) |
748 | { | 748 | { |
@@ -789,13 +789,14 @@ static void be_rx_compl_process(struct be_adapter *adapter, | |||
789 | return; | 789 | return; |
790 | } | 790 | } |
791 | 791 | ||
792 | /* Process the RX completion indicated by rxcp when LRO is enabled */ | 792 | /* Process the RX completion indicated by rxcp when GRO is enabled */ |
793 | static void be_rx_compl_process_lro(struct be_adapter *adapter, | 793 | static void be_rx_compl_process_gro(struct be_adapter *adapter, |
794 | struct be_eth_rx_compl *rxcp) | 794 | struct be_eth_rx_compl *rxcp) |
795 | { | 795 | { |
796 | struct be_rx_page_info *page_info; | 796 | struct be_rx_page_info *page_info; |
797 | struct skb_frag_struct rx_frags[BE_MAX_FRAGS_PER_FRAME]; | 797 | struct sk_buff *skb = NULL; |
798 | struct be_queue_info *rxq = &adapter->rx_obj.q; | 798 | struct be_queue_info *rxq = &adapter->rx_obj.q; |
799 | struct be_eq_obj *eq_obj = &adapter->rx_eq; | ||
799 | u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len; | 800 | u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len; |
800 | u16 i, rxq_idx = 0, vid, j; | 801 | u16 i, rxq_idx = 0, vid, j; |
801 | 802 | ||
@@ -804,6 +805,12 @@ static void be_rx_compl_process_lro(struct be_adapter *adapter, | |||
804 | vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); | 805 | vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); |
805 | rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); | 806 | rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); |
806 | 807 | ||
808 | skb = napi_get_frags(&eq_obj->napi); | ||
809 | if (!skb) { | ||
810 | be_rx_compl_discard(adapter, rxcp); | ||
811 | return; | ||
812 | } | ||
813 | |||
807 | remaining = pkt_size; | 814 | remaining = pkt_size; |
808 | for (i = 0, j = -1; i < num_rcvd; i++) { | 815 | for (i = 0, j = -1; i < num_rcvd; i++) { |
809 | page_info = get_rx_page_info(adapter, rxq_idx); | 816 | page_info = get_rx_page_info(adapter, rxq_idx); |
@@ -814,13 +821,14 @@ static void be_rx_compl_process_lro(struct be_adapter *adapter, | |||
814 | if (i == 0 || page_info->page_offset == 0) { | 821 | if (i == 0 || page_info->page_offset == 0) { |
815 | /* First frag or Fresh page */ | 822 | /* First frag or Fresh page */ |
816 | j++; | 823 | j++; |
817 | rx_frags[j].page = page_info->page; | 824 | skb_shinfo(skb)->frags[j].page = page_info->page; |
818 | rx_frags[j].page_offset = page_info->page_offset; | 825 | skb_shinfo(skb)->frags[j].page_offset = |
819 | rx_frags[j].size = 0; | 826 | page_info->page_offset; |
827 | skb_shinfo(skb)->frags[j].size = 0; | ||
820 | } else { | 828 | } else { |
821 | put_page(page_info->page); | 829 | put_page(page_info->page); |
822 | } | 830 | } |
823 | rx_frags[j].size += curr_frag_len; | 831 | skb_shinfo(skb)->frags[j].size += curr_frag_len; |
824 | 832 | ||
825 | remaining -= curr_frag_len; | 833 | remaining -= curr_frag_len; |
826 | index_inc(&rxq_idx, rxq->len); | 834 | index_inc(&rxq_idx, rxq->len); |
@@ -828,9 +836,14 @@ static void be_rx_compl_process_lro(struct be_adapter *adapter, | |||
828 | } | 836 | } |
829 | BUG_ON(j > MAX_SKB_FRAGS); | 837 | BUG_ON(j > MAX_SKB_FRAGS); |
830 | 838 | ||
839 | skb_shinfo(skb)->nr_frags = j + 1; | ||
840 | skb->len = pkt_size; | ||
841 | skb->data_len = pkt_size; | ||
842 | skb->truesize += pkt_size; | ||
843 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
844 | |||
831 | if (likely(!vlanf)) { | 845 | if (likely(!vlanf)) { |
832 | lro_receive_frags(&adapter->rx_obj.lro_mgr, rx_frags, pkt_size, | 846 | napi_gro_frags(&eq_obj->napi); |
833 | pkt_size, NULL, 0); | ||
834 | } else { | 847 | } else { |
835 | vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp); | 848 | vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp); |
836 | vid = be16_to_cpu(vid); | 849 | vid = be16_to_cpu(vid); |
@@ -838,9 +851,7 @@ static void be_rx_compl_process_lro(struct be_adapter *adapter, | |||
838 | if (!adapter->vlan_grp || adapter->num_vlans == 0) | 851 | if (!adapter->vlan_grp || adapter->num_vlans == 0) |
839 | return; | 852 | return; |
840 | 853 | ||
841 | lro_vlan_hwaccel_receive_frags(&adapter->rx_obj.lro_mgr, | 854 | vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp, vid); |
842 | rx_frags, pkt_size, pkt_size, adapter->vlan_grp, | ||
843 | vid, NULL, 0); | ||
844 | } | 855 | } |
845 | 856 | ||
846 | be_rx_stats_update(adapter, pkt_size, num_rcvd); | 857 | be_rx_stats_update(adapter, pkt_size, num_rcvd); |
@@ -1183,7 +1194,6 @@ static int be_rx_queues_create(struct be_adapter *adapter) | |||
1183 | struct be_queue_info *eq, *q, *cq; | 1194 | struct be_queue_info *eq, *q, *cq; |
1184 | int rc; | 1195 | int rc; |
1185 | 1196 | ||
1186 | adapter->max_rx_coal = BE_MAX_FRAGS_PER_FRAME; | ||
1187 | adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE; | 1197 | adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE; |
1188 | adapter->rx_eq.max_eqd = BE_MAX_EQD; | 1198 | adapter->rx_eq.max_eqd = BE_MAX_EQD; |
1189 | adapter->rx_eq.min_eqd = 0; | 1199 | adapter->rx_eq.min_eqd = 0; |
@@ -1305,7 +1315,7 @@ static irqreturn_t be_msix_tx_mcc(int irq, void *dev) | |||
1305 | return IRQ_HANDLED; | 1315 | return IRQ_HANDLED; |
1306 | } | 1316 | } |
1307 | 1317 | ||
1308 | static inline bool do_lro(struct be_adapter *adapter, | 1318 | static inline bool do_gro(struct be_adapter *adapter, |
1309 | struct be_eth_rx_compl *rxcp) | 1319 | struct be_eth_rx_compl *rxcp) |
1310 | { | 1320 | { |
1311 | int err = AMAP_GET_BITS(struct amap_eth_rx_compl, err, rxcp); | 1321 | int err = AMAP_GET_BITS(struct amap_eth_rx_compl, err, rxcp); |
@@ -1314,8 +1324,7 @@ static inline bool do_lro(struct be_adapter *adapter, | |||
1314 | if (err) | 1324 | if (err) |
1315 | drvr_stats(adapter)->be_rxcp_err++; | 1325 | drvr_stats(adapter)->be_rxcp_err++; |
1316 | 1326 | ||
1317 | return (!tcp_frame || err || (adapter->max_rx_coal <= 1)) ? | 1327 | return (tcp_frame && !err) ? true : false; |
1318 | false : true; | ||
1319 | } | 1328 | } |
1320 | 1329 | ||
1321 | int be_poll_rx(struct napi_struct *napi, int budget) | 1330 | int be_poll_rx(struct napi_struct *napi, int budget) |
@@ -1332,16 +1341,14 @@ int be_poll_rx(struct napi_struct *napi, int budget) | |||
1332 | if (!rxcp) | 1341 | if (!rxcp) |
1333 | break; | 1342 | break; |
1334 | 1343 | ||
1335 | if (do_lro(adapter, rxcp)) | 1344 | if (do_gro(adapter, rxcp)) |
1336 | be_rx_compl_process_lro(adapter, rxcp); | 1345 | be_rx_compl_process_gro(adapter, rxcp); |
1337 | else | 1346 | else |
1338 | be_rx_compl_process(adapter, rxcp); | 1347 | be_rx_compl_process(adapter, rxcp); |
1339 | 1348 | ||
1340 | be_rx_compl_reset(rxcp); | 1349 | be_rx_compl_reset(rxcp); |
1341 | } | 1350 | } |
1342 | 1351 | ||
1343 | lro_flush_all(&adapter->rx_obj.lro_mgr); | ||
1344 | |||
1345 | /* Refill the queue */ | 1352 | /* Refill the queue */ |
1346 | if (atomic_read(&adapter->rx_obj.q.used) < RX_FRAGS_REFILL_WM) | 1353 | if (atomic_read(&adapter->rx_obj.q.used) < RX_FRAGS_REFILL_WM) |
1347 | be_post_rx_frags(adapter); | 1354 | be_post_rx_frags(adapter); |
@@ -1656,57 +1663,6 @@ static int be_close(struct net_device *netdev) | |||
1656 | return 0; | 1663 | return 0; |
1657 | } | 1664 | } |
1658 | 1665 | ||
1659 | static int be_get_frag_header(struct skb_frag_struct *frag, void **mac_hdr, | ||
1660 | void **ip_hdr, void **tcpudp_hdr, | ||
1661 | u64 *hdr_flags, void *priv) | ||
1662 | { | ||
1663 | struct ethhdr *eh; | ||
1664 | struct vlan_ethhdr *veh; | ||
1665 | struct iphdr *iph; | ||
1666 | u8 *va = page_address(frag->page) + frag->page_offset; | ||
1667 | unsigned long ll_hlen; | ||
1668 | |||
1669 | prefetch(va); | ||
1670 | eh = (struct ethhdr *)va; | ||
1671 | *mac_hdr = eh; | ||
1672 | ll_hlen = ETH_HLEN; | ||
1673 | if (eh->h_proto != htons(ETH_P_IP)) { | ||
1674 | if (eh->h_proto == htons(ETH_P_8021Q)) { | ||
1675 | veh = (struct vlan_ethhdr *)va; | ||
1676 | if (veh->h_vlan_encapsulated_proto != htons(ETH_P_IP)) | ||
1677 | return -1; | ||
1678 | |||
1679 | ll_hlen += VLAN_HLEN; | ||
1680 | } else { | ||
1681 | return -1; | ||
1682 | } | ||
1683 | } | ||
1684 | *hdr_flags = LRO_IPV4; | ||
1685 | iph = (struct iphdr *)(va + ll_hlen); | ||
1686 | *ip_hdr = iph; | ||
1687 | if (iph->protocol != IPPROTO_TCP) | ||
1688 | return -1; | ||
1689 | *hdr_flags |= LRO_TCP; | ||
1690 | *tcpudp_hdr = (u8 *) (*ip_hdr) + (iph->ihl << 2); | ||
1691 | |||
1692 | return 0; | ||
1693 | } | ||
1694 | |||
1695 | static void be_lro_init(struct be_adapter *adapter, struct net_device *netdev) | ||
1696 | { | ||
1697 | struct net_lro_mgr *lro_mgr; | ||
1698 | |||
1699 | lro_mgr = &adapter->rx_obj.lro_mgr; | ||
1700 | lro_mgr->dev = netdev; | ||
1701 | lro_mgr->features = LRO_F_NAPI; | ||
1702 | lro_mgr->ip_summed = CHECKSUM_UNNECESSARY; | ||
1703 | lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY; | ||
1704 | lro_mgr->max_desc = BE_MAX_LRO_DESCRIPTORS; | ||
1705 | lro_mgr->lro_arr = adapter->rx_obj.lro_desc; | ||
1706 | lro_mgr->get_frag_header = be_get_frag_header; | ||
1707 | lro_mgr->max_aggr = BE_MAX_FRAGS_PER_FRAME; | ||
1708 | } | ||
1709 | |||
1710 | static struct net_device_ops be_netdev_ops = { | 1666 | static struct net_device_ops be_netdev_ops = { |
1711 | .ndo_open = be_open, | 1667 | .ndo_open = be_open, |
1712 | .ndo_stop = be_close, | 1668 | .ndo_stop = be_close, |
@@ -1727,7 +1683,7 @@ static void be_netdev_init(struct net_device *netdev) | |||
1727 | 1683 | ||
1728 | netdev->features |= NETIF_F_SG | NETIF_F_HW_VLAN_RX | NETIF_F_TSO | | 1684 | netdev->features |= NETIF_F_SG | NETIF_F_HW_VLAN_RX | NETIF_F_TSO | |
1729 | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_IP_CSUM | | 1685 | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_IP_CSUM | |
1730 | NETIF_F_IPV6_CSUM; | 1686 | NETIF_F_IPV6_CSUM | NETIF_F_GRO; |
1731 | 1687 | ||
1732 | netdev->flags |= IFF_MULTICAST; | 1688 | netdev->flags |= IFF_MULTICAST; |
1733 | 1689 | ||
@@ -1737,8 +1693,6 @@ static void be_netdev_init(struct net_device *netdev) | |||
1737 | 1693 | ||
1738 | SET_ETHTOOL_OPS(netdev, &be_ethtool_ops); | 1694 | SET_ETHTOOL_OPS(netdev, &be_ethtool_ops); |
1739 | 1695 | ||
1740 | be_lro_init(adapter, netdev); | ||
1741 | |||
1742 | netif_napi_add(netdev, &adapter->rx_eq.napi, be_poll_rx, | 1696 | netif_napi_add(netdev, &adapter->rx_eq.napi, be_poll_rx, |
1743 | BE_NAPI_WEIGHT); | 1697 | BE_NAPI_WEIGHT); |
1744 | netif_napi_add(netdev, &adapter->tx_eq.napi, be_poll_tx_mcc, | 1698 | netif_napi_add(netdev, &adapter->tx_eq.napi, be_poll_tx_mcc, |