diff options
author | Faisal Latif <flatif@neteffect.com> | 2008-04-29 16:46:54 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2008-04-29 16:46:54 -0400 |
commit | 37dab4112d7b53c3574426ef7bdd92a78d32ac3e (patch) | |
tree | c6d8e9e04a35baa6a0669281a923c4aa07542c7e /drivers/infiniband/hw/nes/nes_hw.c | |
parent | b4132efa1a47858d741ecb05b8735e6fcb603bc8 (diff) |
RDMA/nes: Use LRO
Signed-off-by: Faisal Latif <flatif@neteffect.com.
Signed-off-by: Glenn Streiff <gstreiff@neteffect.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw/nes/nes_hw.c')
-rw-r--r-- | drivers/infiniband/hw/nes/nes_hw.c | 53 |
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 | ||
1379 | static 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 | /** |