aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/nes/nes_hw.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/hw/nes/nes_hw.c')
-rw-r--r--drivers/infiniband/hw/nes/nes_hw.c53
1 files changed, 45 insertions, 8 deletions
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c
index 08964cc7e98a..f824ecb9f879 100644
--- a/drivers/infiniband/hw/nes/nes_hw.c
+++ b/drivers/infiniband/hw/nes/nes_hw.c
@@ -38,6 +38,7 @@
38#include <linux/ip.h> 38#include <linux/ip.h>
39#include <linux/tcp.h> 39#include <linux/tcp.h>
40#include <linux/if_vlan.h> 40#include <linux/if_vlan.h>
41#include <linux/inet_lro.h>
41 42
42#include "nes.h" 43#include "nes.h"
43 44
@@ -1375,6 +1376,25 @@ static void nes_rq_wqes_timeout(unsigned long parm)
1375} 1376}
1376 1377
1377 1378
1379static int nes_lro_get_skb_hdr(struct sk_buff *skb, void **iphdr,
1380 void **tcph, u64 *hdr_flags, void *priv)
1381{
1382 unsigned int ip_len;
1383 struct iphdr *iph;
1384 skb_reset_network_header(skb);
1385 iph = ip_hdr(skb);
1386 if (iph->protocol != IPPROTO_TCP)
1387 return -1;
1388 ip_len = ip_hdrlen(skb);
1389 skb_set_transport_header(skb, ip_len);
1390 *tcph = tcp_hdr(skb);
1391
1392 *hdr_flags = LRO_IPV4 | LRO_TCP;
1393 *iphdr = iph;
1394 return 0;
1395}
1396
1397
1378/** 1398/**
1379 * nes_init_nic_qp 1399 * nes_init_nic_qp
1380 */ 1400 */
@@ -1592,15 +1612,21 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
1592 nesvnic->rq_wqes_timer.function = nes_rq_wqes_timeout; 1612 nesvnic->rq_wqes_timer.function = nes_rq_wqes_timeout;
1593 nesvnic->rq_wqes_timer.data = (unsigned long)nesvnic; 1613 nesvnic->rq_wqes_timer.data = (unsigned long)nesvnic;
1594 nes_debug(NES_DBG_INIT, "NAPI support Enabled\n"); 1614 nes_debug(NES_DBG_INIT, "NAPI support Enabled\n");
1595
1596 if (nesdev->nesadapter->et_use_adaptive_rx_coalesce) 1615 if (nesdev->nesadapter->et_use_adaptive_rx_coalesce)
1597 { 1616 {
1598 nes_nic_init_timer(nesdev); 1617 nes_nic_init_timer(nesdev);
1599 if (netdev->mtu > 1500) 1618 if (netdev->mtu > 1500)
1600 jumbomode = 1; 1619 jumbomode = 1;
1601 nes_nic_init_timer_defaults(nesdev, jumbomode); 1620 nes_nic_init_timer_defaults(nesdev, jumbomode);
1602 } 1621 }
1603 1622 nesvnic->lro_mgr.max_aggr = NES_LRO_MAX_AGGR;
1623 nesvnic->lro_mgr.max_desc = NES_MAX_LRO_DESCRIPTORS;
1624 nesvnic->lro_mgr.lro_arr = nesvnic->lro_desc;
1625 nesvnic->lro_mgr.get_skb_header = nes_lro_get_skb_hdr;
1626 nesvnic->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID;
1627 nesvnic->lro_mgr.dev = netdev;
1628 nesvnic->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
1629 nesvnic->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
1604 return 0; 1630 return 0;
1605} 1631}
1606 1632
@@ -2254,10 +2280,13 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
2254 u16 pkt_type; 2280 u16 pkt_type;
2255 u16 rqes_processed = 0; 2281 u16 rqes_processed = 0;
2256 u8 sq_cqes = 0; 2282 u8 sq_cqes = 0;
2283 u8 nes_use_lro = 0;
2257 2284
2258 head = cq->cq_head; 2285 head = cq->cq_head;
2259 cq_size = cq->cq_size; 2286 cq_size = cq->cq_size;
2260 cq->cqes_pending = 1; 2287 cq->cqes_pending = 1;
2288 if (nesvnic->netdev->features & NETIF_F_LRO)
2289 nes_use_lro = 1;
2261 do { 2290 do {
2262 if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX]) & 2291 if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX]) &
2263 NES_NIC_CQE_VALID) { 2292 NES_NIC_CQE_VALID) {
@@ -2379,9 +2408,16 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
2379 >> 16); 2408 >> 16);
2380 nes_debug(NES_DBG_CQ, "%s: Reporting stripped VLAN packet. Tag = 0x%04X\n", 2409 nes_debug(NES_DBG_CQ, "%s: Reporting stripped VLAN packet. Tag = 0x%04X\n",
2381 nesvnic->netdev->name, vlan_tag); 2410 nesvnic->netdev->name, vlan_tag);
2382 nes_vlan_rx(rx_skb, nesvnic->vlan_grp, vlan_tag); 2411 if (nes_use_lro)
2412 lro_vlan_hwaccel_receive_skb(&nesvnic->lro_mgr, rx_skb,
2413 nesvnic->vlan_grp, vlan_tag, NULL);
2414 else
2415 nes_vlan_rx(rx_skb, nesvnic->vlan_grp, vlan_tag);
2383 } else { 2416 } else {
2384 nes_netif_rx(rx_skb); 2417 if (nes_use_lro)
2418 lro_receive_skb(&nesvnic->lro_mgr, rx_skb, NULL);
2419 else
2420 nes_netif_rx(rx_skb);
2385 } 2421 }
2386 } 2422 }
2387 2423
@@ -2413,13 +2449,14 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
2413 2449
2414 } while (1); 2450 } while (1);
2415 2451
2452 if (nes_use_lro)
2453 lro_flush_all(&nesvnic->lro_mgr);
2416 if (sq_cqes) { 2454 if (sq_cqes) {
2417 barrier(); 2455 barrier();
2418 /* restart the queue if it had been stopped */ 2456 /* restart the queue if it had been stopped */
2419 if (netif_queue_stopped(nesvnic->netdev)) 2457 if (netif_queue_stopped(nesvnic->netdev))
2420 netif_wake_queue(nesvnic->netdev); 2458 netif_wake_queue(nesvnic->netdev);
2421 } 2459 }
2422
2423 cq->cq_head = head; 2460 cq->cq_head = head;
2424 /* nes_debug(NES_DBG_CQ, "CQ%u Processed = %u cqes, new head = %u.\n", 2461 /* nes_debug(NES_DBG_CQ, "CQ%u Processed = %u cqes, new head = %u.\n",
2425 cq->cq_number, cqe_count, cq->cq_head); */ 2462 cq->cq_number, cqe_count, cq->cq_head); */
@@ -2432,7 +2469,7 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
2432 } 2469 }
2433 if (atomic_read(&nesvnic->rx_skbs_needed)) 2470 if (atomic_read(&nesvnic->rx_skbs_needed))
2434 nes_replenish_nic_rq(nesvnic); 2471 nes_replenish_nic_rq(nesvnic);
2435 } 2472}
2436 2473
2437 2474
2438/** 2475/**