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 | |
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')
-rw-r--r-- | drivers/infiniband/hw/nes/Kconfig | 1 | ||||
-rw-r--r-- | drivers/infiniband/hw/nes/nes.c | 4 | ||||
-rw-r--r-- | drivers/infiniband/hw/nes/nes.h | 1 | ||||
-rw-r--r-- | drivers/infiniband/hw/nes/nes_hw.c | 53 | ||||
-rw-r--r-- | drivers/infiniband/hw/nes/nes_hw.h | 11 | ||||
-rw-r--r-- | drivers/infiniband/hw/nes/nes_nic.c | 12 |
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; | |||
91 | module_param_named(debug_level, nes_debug_level, uint, 0644); | 91 | module_param_named(debug_level, nes_debug_level, uint, 0644); |
92 | MODULE_PARM_DESC(debug_level, "Enable debug output level"); | 92 | MODULE_PARM_DESC(debug_level, "Enable debug output level"); |
93 | 93 | ||
94 | unsigned int nes_lro_max_aggr = NES_LRO_MAX_AGGR; | ||
95 | module_param(nes_lro_max_aggr, int, NES_LRO_MAX_AGGR); | ||
96 | MODULE_PARM_DESC(nes_mro_max_aggr, " nic LRO MAX packet aggregation"); | ||
97 | |||
94 | LIST_HEAD(nes_adapter_list); | 98 | LIST_HEAD(nes_adapter_list); |
95 | static LIST_HEAD(nes_dev_list); | 99 | static 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; | |||
173 | extern unsigned int send_first; | 173 | extern unsigned int send_first; |
174 | extern unsigned int nes_drv_opt; | 174 | extern unsigned int nes_drv_opt; |
175 | extern unsigned int nes_debug_level; | 175 | extern unsigned int nes_debug_level; |
176 | extern unsigned int nes_lro_max_aggr; | ||
176 | 177 | ||
177 | extern struct list_head nes_adapter_list; | 178 | extern 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 | ||
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 | /** |
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 | ||
988 | struct nes_adapter { | 992 | struct 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 | ||
1188 | struct nes_ib_device { | 1195 | struct 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 | 939 | static const char nes_ethtool_stringset[][ETH_GSTRING_LEN] = { |
940 | static 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 | ||