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>
This commit is contained in:
parent
b4132efa1a
commit
37dab4112d
|
@ -2,6 +2,7 @@ config INFINIBAND_NES
|
||||||
tristate "NetEffect RNIC Driver"
|
tristate "NetEffect RNIC Driver"
|
||||||
depends on PCI && INET && INFINIBAND
|
depends on PCI && INET && INFINIBAND
|
||||||
select LIBCRC32C
|
select LIBCRC32C
|
||||||
|
select INET_LRO
|
||||||
---help---
|
---help---
|
||||||
This is a low-level driver for NetEffect RDMA enabled
|
This is a low-level driver for NetEffect RDMA enabled
|
||||||
Network Interface Cards (RNIC).
|
Network Interface Cards (RNIC).
|
||||||
|
|
|
@ -91,6 +91,10 @@ unsigned int nes_debug_level = 0;
|
||||||
module_param_named(debug_level, nes_debug_level, uint, 0644);
|
module_param_named(debug_level, nes_debug_level, uint, 0644);
|
||||||
MODULE_PARM_DESC(debug_level, "Enable debug output level");
|
MODULE_PARM_DESC(debug_level, "Enable debug output level");
|
||||||
|
|
||||||
|
unsigned int nes_lro_max_aggr = NES_LRO_MAX_AGGR;
|
||||||
|
module_param(nes_lro_max_aggr, int, NES_LRO_MAX_AGGR);
|
||||||
|
MODULE_PARM_DESC(nes_mro_max_aggr, " nic LRO MAX packet aggregation");
|
||||||
|
|
||||||
LIST_HEAD(nes_adapter_list);
|
LIST_HEAD(nes_adapter_list);
|
||||||
static LIST_HEAD(nes_dev_list);
|
static LIST_HEAD(nes_dev_list);
|
||||||
|
|
||||||
|
|
|
@ -173,6 +173,7 @@ extern int disable_mpa_crc;
|
||||||
extern unsigned int send_first;
|
extern unsigned int send_first;
|
||||||
extern unsigned int nes_drv_opt;
|
extern unsigned int nes_drv_opt;
|
||||||
extern unsigned int nes_debug_level;
|
extern unsigned int nes_debug_level;
|
||||||
|
extern unsigned int nes_lro_max_aggr;
|
||||||
|
|
||||||
extern struct list_head nes_adapter_list;
|
extern struct list_head nes_adapter_list;
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include <linux/ip.h>
|
#include <linux/ip.h>
|
||||||
#include <linux/tcp.h>
|
#include <linux/tcp.h>
|
||||||
#include <linux/if_vlan.h>
|
#include <linux/if_vlan.h>
|
||||||
|
#include <linux/inet_lro.h>
|
||||||
|
|
||||||
#include "nes.h"
|
#include "nes.h"
|
||||||
|
|
||||||
|
@ -1375,6 +1376,25 @@ static void nes_rq_wqes_timeout(unsigned long parm)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int nes_lro_get_skb_hdr(struct sk_buff *skb, void **iphdr,
|
||||||
|
void **tcph, u64 *hdr_flags, void *priv)
|
||||||
|
{
|
||||||
|
unsigned int ip_len;
|
||||||
|
struct iphdr *iph;
|
||||||
|
skb_reset_network_header(skb);
|
||||||
|
iph = ip_hdr(skb);
|
||||||
|
if (iph->protocol != IPPROTO_TCP)
|
||||||
|
return -1;
|
||||||
|
ip_len = ip_hdrlen(skb);
|
||||||
|
skb_set_transport_header(skb, ip_len);
|
||||||
|
*tcph = tcp_hdr(skb);
|
||||||
|
|
||||||
|
*hdr_flags = LRO_IPV4 | LRO_TCP;
|
||||||
|
*iphdr = iph;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nes_init_nic_qp
|
* nes_init_nic_qp
|
||||||
*/
|
*/
|
||||||
|
@ -1592,15 +1612,21 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
|
||||||
nesvnic->rq_wqes_timer.function = nes_rq_wqes_timeout;
|
nesvnic->rq_wqes_timer.function = nes_rq_wqes_timeout;
|
||||||
nesvnic->rq_wqes_timer.data = (unsigned long)nesvnic;
|
nesvnic->rq_wqes_timer.data = (unsigned long)nesvnic;
|
||||||
nes_debug(NES_DBG_INIT, "NAPI support Enabled\n");
|
nes_debug(NES_DBG_INIT, "NAPI support Enabled\n");
|
||||||
|
|
||||||
if (nesdev->nesadapter->et_use_adaptive_rx_coalesce)
|
if (nesdev->nesadapter->et_use_adaptive_rx_coalesce)
|
||||||
{
|
{
|
||||||
nes_nic_init_timer(nesdev);
|
nes_nic_init_timer(nesdev);
|
||||||
if (netdev->mtu > 1500)
|
if (netdev->mtu > 1500)
|
||||||
jumbomode = 1;
|
jumbomode = 1;
|
||||||
nes_nic_init_timer_defaults(nesdev, jumbomode);
|
nes_nic_init_timer_defaults(nesdev, jumbomode);
|
||||||
}
|
}
|
||||||
|
nesvnic->lro_mgr.max_aggr = NES_LRO_MAX_AGGR;
|
||||||
|
nesvnic->lro_mgr.max_desc = NES_MAX_LRO_DESCRIPTORS;
|
||||||
|
nesvnic->lro_mgr.lro_arr = nesvnic->lro_desc;
|
||||||
|
nesvnic->lro_mgr.get_skb_header = nes_lro_get_skb_hdr;
|
||||||
|
nesvnic->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID;
|
||||||
|
nesvnic->lro_mgr.dev = netdev;
|
||||||
|
nesvnic->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
|
||||||
|
nesvnic->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2254,10 +2280,13 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
|
||||||
u16 pkt_type;
|
u16 pkt_type;
|
||||||
u16 rqes_processed = 0;
|
u16 rqes_processed = 0;
|
||||||
u8 sq_cqes = 0;
|
u8 sq_cqes = 0;
|
||||||
|
u8 nes_use_lro = 0;
|
||||||
|
|
||||||
head = cq->cq_head;
|
head = cq->cq_head;
|
||||||
cq_size = cq->cq_size;
|
cq_size = cq->cq_size;
|
||||||
cq->cqes_pending = 1;
|
cq->cqes_pending = 1;
|
||||||
|
if (nesvnic->netdev->features & NETIF_F_LRO)
|
||||||
|
nes_use_lro = 1;
|
||||||
do {
|
do {
|
||||||
if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX]) &
|
if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX]) &
|
||||||
NES_NIC_CQE_VALID) {
|
NES_NIC_CQE_VALID) {
|
||||||
|
@ -2379,9 +2408,16 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
|
||||||
>> 16);
|
>> 16);
|
||||||
nes_debug(NES_DBG_CQ, "%s: Reporting stripped VLAN packet. Tag = 0x%04X\n",
|
nes_debug(NES_DBG_CQ, "%s: Reporting stripped VLAN packet. Tag = 0x%04X\n",
|
||||||
nesvnic->netdev->name, vlan_tag);
|
nesvnic->netdev->name, vlan_tag);
|
||||||
nes_vlan_rx(rx_skb, nesvnic->vlan_grp, vlan_tag);
|
if (nes_use_lro)
|
||||||
|
lro_vlan_hwaccel_receive_skb(&nesvnic->lro_mgr, rx_skb,
|
||||||
|
nesvnic->vlan_grp, vlan_tag, NULL);
|
||||||
|
else
|
||||||
|
nes_vlan_rx(rx_skb, nesvnic->vlan_grp, vlan_tag);
|
||||||
} else {
|
} else {
|
||||||
nes_netif_rx(rx_skb);
|
if (nes_use_lro)
|
||||||
|
lro_receive_skb(&nesvnic->lro_mgr, rx_skb, NULL);
|
||||||
|
else
|
||||||
|
nes_netif_rx(rx_skb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2413,13 +2449,14 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
|
||||||
|
|
||||||
} while (1);
|
} while (1);
|
||||||
|
|
||||||
|
if (nes_use_lro)
|
||||||
|
lro_flush_all(&nesvnic->lro_mgr);
|
||||||
if (sq_cqes) {
|
if (sq_cqes) {
|
||||||
barrier();
|
barrier();
|
||||||
/* restart the queue if it had been stopped */
|
/* restart the queue if it had been stopped */
|
||||||
if (netif_queue_stopped(nesvnic->netdev))
|
if (netif_queue_stopped(nesvnic->netdev))
|
||||||
netif_wake_queue(nesvnic->netdev);
|
netif_wake_queue(nesvnic->netdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
cq->cq_head = head;
|
cq->cq_head = head;
|
||||||
/* nes_debug(NES_DBG_CQ, "CQ%u Processed = %u cqes, new head = %u.\n",
|
/* nes_debug(NES_DBG_CQ, "CQ%u Processed = %u cqes, new head = %u.\n",
|
||||||
cq->cq_number, cqe_count, cq->cq_head); */
|
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)
|
||||||
}
|
}
|
||||||
if (atomic_read(&nesvnic->rx_skbs_needed))
|
if (atomic_read(&nesvnic->rx_skbs_needed))
|
||||||
nes_replenish_nic_rq(nesvnic);
|
nes_replenish_nic_rq(nesvnic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -33,6 +33,8 @@
|
||||||
#ifndef __NES_HW_H
|
#ifndef __NES_HW_H
|
||||||
#define __NES_HW_H
|
#define __NES_HW_H
|
||||||
|
|
||||||
|
#include <linux/inet_lro.h>
|
||||||
|
|
||||||
#define NES_PHY_TYPE_1G 2
|
#define NES_PHY_TYPE_1G 2
|
||||||
#define NES_PHY_TYPE_IRIS 3
|
#define NES_PHY_TYPE_IRIS 3
|
||||||
#define NES_PHY_TYPE_PUMA_10G 6
|
#define NES_PHY_TYPE_PUMA_10G 6
|
||||||
|
@ -982,8 +984,10 @@ struct nes_hw_tune_timer {
|
||||||
#define NES_TIMER_INT_LIMIT 2
|
#define NES_TIMER_INT_LIMIT 2
|
||||||
#define NES_TIMER_INT_LIMIT_DYNAMIC 10
|
#define NES_TIMER_INT_LIMIT_DYNAMIC 10
|
||||||
#define NES_TIMER_ENABLE_LIMIT 4
|
#define NES_TIMER_ENABLE_LIMIT 4
|
||||||
#define NES_MAX_LINK_INTERRUPTS 128
|
#define NES_MAX_LINK_INTERRUPTS 128
|
||||||
#define NES_MAX_LINK_CHECK 200
|
#define NES_MAX_LINK_CHECK 200
|
||||||
|
#define NES_MAX_LRO_DESCRIPTORS 32
|
||||||
|
#define NES_LRO_MAX_AGGR 64
|
||||||
|
|
||||||
struct nes_adapter {
|
struct nes_adapter {
|
||||||
u64 fw_ver;
|
u64 fw_ver;
|
||||||
|
@ -1183,6 +1187,9 @@ struct nes_vnic {
|
||||||
u8 of_device_registered;
|
u8 of_device_registered;
|
||||||
u8 rdma_enabled;
|
u8 rdma_enabled;
|
||||||
u8 rx_checksum_disabled;
|
u8 rx_checksum_disabled;
|
||||||
|
u32 lro_max_aggr;
|
||||||
|
struct net_lro_mgr lro_mgr;
|
||||||
|
struct net_lro_desc lro_desc[NES_MAX_LRO_DESCRIPTORS];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nes_ib_device {
|
struct nes_ib_device {
|
||||||
|
|
|
@ -936,8 +936,7 @@ static int nes_netdev_change_mtu(struct net_device *netdev, int new_mtu)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NES_ETHTOOL_STAT_COUNT 55
|
static const char nes_ethtool_stringset[][ETH_GSTRING_LEN] = {
|
||||||
static const char nes_ethtool_stringset[NES_ETHTOOL_STAT_COUNT][ETH_GSTRING_LEN] = {
|
|
||||||
"Link Change Interrupts",
|
"Link Change Interrupts",
|
||||||
"Linearized SKBs",
|
"Linearized SKBs",
|
||||||
"T/GSO Requests",
|
"T/GSO Requests",
|
||||||
|
@ -993,8 +992,12 @@ static const char nes_ethtool_stringset[NES_ETHTOOL_STAT_COUNT][ETH_GSTRING_LEN]
|
||||||
"CQ Depth 32",
|
"CQ Depth 32",
|
||||||
"CQ Depth 128",
|
"CQ Depth 128",
|
||||||
"CQ Depth 256",
|
"CQ Depth 256",
|
||||||
|
"LRO aggregated",
|
||||||
|
"LRO flushed",
|
||||||
|
"LRO no_desc",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define NES_ETHTOOL_STAT_COUNT ARRAY_SIZE(nes_ethtool_stringset)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nes_netdev_get_rx_csum
|
* nes_netdev_get_rx_csum
|
||||||
|
@ -1189,6 +1192,9 @@ static void nes_netdev_get_ethtool_stats(struct net_device *netdev,
|
||||||
target_stat_values[52] = int_mod_cq_depth_32;
|
target_stat_values[52] = int_mod_cq_depth_32;
|
||||||
target_stat_values[53] = int_mod_cq_depth_128;
|
target_stat_values[53] = int_mod_cq_depth_128;
|
||||||
target_stat_values[54] = int_mod_cq_depth_256;
|
target_stat_values[54] = int_mod_cq_depth_256;
|
||||||
|
target_stat_values[55] = nesvnic->lro_mgr.stats.aggregated;
|
||||||
|
target_stat_values[56] = nesvnic->lro_mgr.stats.flushed;
|
||||||
|
target_stat_values[57] = nesvnic->lro_mgr.stats.no_desc;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1454,6 +1460,8 @@ static struct ethtool_ops nes_ethtool_ops = {
|
||||||
.set_sg = ethtool_op_set_sg,
|
.set_sg = ethtool_op_set_sg,
|
||||||
.get_tso = ethtool_op_get_tso,
|
.get_tso = ethtool_op_get_tso,
|
||||||
.set_tso = ethtool_op_set_tso,
|
.set_tso = ethtool_op_set_tso,
|
||||||
|
.get_flags = ethtool_op_get_flags,
|
||||||
|
.set_flags = ethtool_op_set_flags,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue