aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFaisal Latif <flatif@neteffect.com>2008-04-29 16:46:54 -0400
committerRoland Dreier <rolandd@cisco.com>2008-04-29 16:46:54 -0400
commit37dab4112d7b53c3574426ef7bdd92a78d32ac3e (patch)
treec6d8e9e04a35baa6a0669281a923c4aa07542c7e
parentb4132efa1a47858d741ecb05b8735e6fcb603bc8 (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>
-rw-r--r--drivers/infiniband/hw/nes/Kconfig1
-rw-r--r--drivers/infiniband/hw/nes/nes.c4
-rw-r--r--drivers/infiniband/hw/nes/nes.h1
-rw-r--r--drivers/infiniband/hw/nes/nes_hw.c53
-rw-r--r--drivers/infiniband/hw/nes/nes_hw.h11
-rw-r--r--drivers/infiniband/hw/nes/nes_nic.c12
6 files changed, 70 insertions, 12 deletions
diff --git a/drivers/infiniband/hw/nes/Kconfig b/drivers/infiniband/hw/nes/Kconfig
index 2aeb7ac972a9..d449eb6ec78e 100644
--- a/drivers/infiniband/hw/nes/Kconfig
+++ b/drivers/infiniband/hw/nes/Kconfig
@@ -2,6 +2,7 @@ config INFINIBAND_NES
2 tristate "NetEffect RNIC Driver" 2 tristate "NetEffect RNIC Driver"
3 depends on PCI && INET && INFINIBAND 3 depends on PCI && INET && INFINIBAND
4 select LIBCRC32C 4 select LIBCRC32C
5 select INET_LRO
5 ---help--- 6 ---help---
6 This is a low-level driver for NetEffect RDMA enabled 7 This is a low-level driver for NetEffect RDMA enabled
7 Network Interface Cards (RNIC). 8 Network Interface Cards (RNIC).
diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c
index a4e9269a29bd..9f7364a9096d 100644
--- a/drivers/infiniband/hw/nes/nes.c
+++ b/drivers/infiniband/hw/nes/nes.c
@@ -91,6 +91,10 @@ unsigned int nes_debug_level = 0;
91module_param_named(debug_level, nes_debug_level, uint, 0644); 91module_param_named(debug_level, nes_debug_level, uint, 0644);
92MODULE_PARM_DESC(debug_level, "Enable debug output level"); 92MODULE_PARM_DESC(debug_level, "Enable debug output level");
93 93
94unsigned int nes_lro_max_aggr = NES_LRO_MAX_AGGR;
95module_param(nes_lro_max_aggr, int, NES_LRO_MAX_AGGR);
96MODULE_PARM_DESC(nes_mro_max_aggr, " nic LRO MAX packet aggregation");
97
94LIST_HEAD(nes_adapter_list); 98LIST_HEAD(nes_adapter_list);
95static LIST_HEAD(nes_dev_list); 99static LIST_HEAD(nes_dev_list);
96 100
diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h
index cdf2e9ad62f7..484b5e30badd 100644
--- a/drivers/infiniband/hw/nes/nes.h
+++ b/drivers/infiniband/hw/nes/nes.h
@@ -173,6 +173,7 @@ extern int disable_mpa_crc;
173extern unsigned int send_first; 173extern unsigned int send_first;
174extern unsigned int nes_drv_opt; 174extern unsigned int nes_drv_opt;
175extern unsigned int nes_debug_level; 175extern unsigned int nes_debug_level;
176extern unsigned int nes_lro_max_aggr;
176 177
177extern struct list_head nes_adapter_list; 178extern struct list_head nes_adapter_list;
178 179
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/**
diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h
index 8f36e231bdf5..6a0f94cc9f0c 100644
--- a/drivers/infiniband/hw/nes/nes_hw.h
+++ b/drivers/infiniband/hw/nes/nes_hw.h
@@ -33,6 +33,8 @@
33#ifndef __NES_HW_H 33#ifndef __NES_HW_H
34#define __NES_HW_H 34#define __NES_HW_H
35 35
36#include <linux/inet_lro.h>
37
36#define NES_PHY_TYPE_1G 2 38#define NES_PHY_TYPE_1G 2
37#define NES_PHY_TYPE_IRIS 3 39#define NES_PHY_TYPE_IRIS 3
38#define NES_PHY_TYPE_PUMA_10G 6 40#define NES_PHY_TYPE_PUMA_10G 6
@@ -982,8 +984,10 @@ struct nes_hw_tune_timer {
982#define NES_TIMER_INT_LIMIT 2 984#define NES_TIMER_INT_LIMIT 2
983#define NES_TIMER_INT_LIMIT_DYNAMIC 10 985#define NES_TIMER_INT_LIMIT_DYNAMIC 10
984#define NES_TIMER_ENABLE_LIMIT 4 986#define NES_TIMER_ENABLE_LIMIT 4
985#define NES_MAX_LINK_INTERRUPTS 128 987#define NES_MAX_LINK_INTERRUPTS 128
986#define NES_MAX_LINK_CHECK 200 988#define NES_MAX_LINK_CHECK 200
989#define NES_MAX_LRO_DESCRIPTORS 32
990#define NES_LRO_MAX_AGGR 64
987 991
988struct nes_adapter { 992struct nes_adapter {
989 u64 fw_ver; 993 u64 fw_ver;
@@ -1183,6 +1187,9 @@ struct nes_vnic {
1183 u8 of_device_registered; 1187 u8 of_device_registered;
1184 u8 rdma_enabled; 1188 u8 rdma_enabled;
1185 u8 rx_checksum_disabled; 1189 u8 rx_checksum_disabled;
1190 u32 lro_max_aggr;
1191 struct net_lro_mgr lro_mgr;
1192 struct net_lro_desc lro_desc[NES_MAX_LRO_DESCRIPTORS];
1186}; 1193};
1187 1194
1188struct nes_ib_device { 1195struct nes_ib_device {
diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
index e5366b013c1a..6998af0172ab 100644
--- a/drivers/infiniband/hw/nes/nes_nic.c
+++ b/drivers/infiniband/hw/nes/nes_nic.c
@@ -936,8 +936,7 @@ static int nes_netdev_change_mtu(struct net_device *netdev, int new_mtu)
936 return ret; 936 return ret;
937} 937}
938 938
939#define NES_ETHTOOL_STAT_COUNT 55 939static const char nes_ethtool_stringset[][ETH_GSTRING_LEN] = {
940static const char nes_ethtool_stringset[NES_ETHTOOL_STAT_COUNT][ETH_GSTRING_LEN] = {
941 "Link Change Interrupts", 940 "Link Change Interrupts",
942 "Linearized SKBs", 941 "Linearized SKBs",
943 "T/GSO Requests", 942 "T/GSO Requests",
@@ -993,8 +992,12 @@ static const char nes_ethtool_stringset[NES_ETHTOOL_STAT_COUNT][ETH_GSTRING_LEN]
993 "CQ Depth 32", 992 "CQ Depth 32",
994 "CQ Depth 128", 993 "CQ Depth 128",
995 "CQ Depth 256", 994 "CQ Depth 256",
995 "LRO aggregated",
996 "LRO flushed",
997 "LRO no_desc",
996}; 998};
997 999
1000#define NES_ETHTOOL_STAT_COUNT ARRAY_SIZE(nes_ethtool_stringset)
998 1001
999/** 1002/**
1000 * nes_netdev_get_rx_csum 1003 * nes_netdev_get_rx_csum
@@ -1189,6 +1192,9 @@ static void nes_netdev_get_ethtool_stats(struct net_device *netdev,
1189 target_stat_values[52] = int_mod_cq_depth_32; 1192 target_stat_values[52] = int_mod_cq_depth_32;
1190 target_stat_values[53] = int_mod_cq_depth_128; 1193 target_stat_values[53] = int_mod_cq_depth_128;
1191 target_stat_values[54] = int_mod_cq_depth_256; 1194 target_stat_values[54] = int_mod_cq_depth_256;
1195 target_stat_values[55] = nesvnic->lro_mgr.stats.aggregated;
1196 target_stat_values[56] = nesvnic->lro_mgr.stats.flushed;
1197 target_stat_values[57] = nesvnic->lro_mgr.stats.no_desc;
1192 1198
1193} 1199}
1194 1200
@@ -1454,6 +1460,8 @@ static struct ethtool_ops nes_ethtool_ops = {
1454 .set_sg = ethtool_op_set_sg, 1460 .set_sg = ethtool_op_set_sg,
1455 .get_tso = ethtool_op_get_tso, 1461 .get_tso = ethtool_op_get_tso,
1456 .set_tso = ethtool_op_set_tso, 1462 .set_tso = ethtool_op_set_tso,
1463 .get_flags = ethtool_op_get_flags,
1464 .set_flags = ethtool_op_set_flags,
1457}; 1465};
1458 1466
1459 1467