diff options
| -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 | ||
