Add support for optional Soft LRO

MFC after:5 days
This commit is contained in:
David C Somayajulu 2017-03-30 22:43:32 +00:00
parent 1c2da02938
commit a7c62c116c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=316309
4 changed files with 151 additions and 5 deletions

View File

@ -440,6 +440,17 @@ ql_hw_add_sysctls(qla_host_t *ha)
OID_AUTO, "enable_9kb", CTLFLAG_RW, &ha->hw.enable_9kb,
ha->hw.enable_9kb, "Enable 9Kbyte Buffers when MTU = 9000");
ha->hw.enable_hw_lro = 1;
SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
OID_AUTO, "enable_hw_lro", CTLFLAG_RW, &ha->hw.enable_hw_lro,
ha->hw.enable_hw_lro, "Enable Hardware LRO; Default is true \n"
"\t 1 : Hardware LRO if LRO is enabled\n"
"\t 0 : Software LRO if LRO is enabled\n"
"\t Any change requires ifconfig down/up to take effect\n"
"\t Note that LRO may be turned off/on via ifconfig\n");
ha->hw.mdump_active = 0;
SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
@ -2255,6 +2266,83 @@ qla_config_rss_ind_table(qla_host_t *ha)
return (0);
}
static int
qla_config_soft_lro(qla_host_t *ha)
{
int i;
qla_hw_t *hw = &ha->hw;
struct lro_ctrl *lro;
for (i = 0; i < hw->num_sds_rings; i++) {
lro = &hw->sds[i].lro;
bzero(lro, sizeof(struct lro_ctrl));
#if (__FreeBSD_version >= 1100101)
if (tcp_lro_init_args(lro, ha->ifp, 0, NUM_RX_DESCRIPTORS)) {
device_printf(ha->pci_dev,
"%s: tcp_lro_init_args [%d] failed\n",
__func__, i);
return (-1);
}
#else
if (tcp_lro_init(lro)) {
device_printf(ha->pci_dev,
"%s: tcp_lro_init [%d] failed\n",
__func__, i);
return (-1);
}
#endif /* #if (__FreeBSD_version >= 1100101) */
lro->ifp = ha->ifp;
}
QL_DPRINT2(ha, (ha->pci_dev, "%s: LRO initialized\n", __func__));
return (0);
}
static void
qla_drain_soft_lro(qla_host_t *ha)
{
int i;
qla_hw_t *hw = &ha->hw;
struct lro_ctrl *lro;
for (i = 0; i < hw->num_sds_rings; i++) {
lro = &hw->sds[i].lro;
#if (__FreeBSD_version >= 1100101)
tcp_lro_flush_all(lro);
#else
struct lro_entry *queued;
while ((!SLIST_EMPTY(&lro->lro_active))) {
queued = SLIST_FIRST(&lro->lro_active);
SLIST_REMOVE_HEAD(&lro->lro_active, next);
tcp_lro_flush(lro, queued);
}
#endif /* #if (__FreeBSD_version >= 1100101) */
}
return;
}
static void
qla_free_soft_lro(qla_host_t *ha)
{
int i;
qla_hw_t *hw = &ha->hw;
struct lro_ctrl *lro;
for (i = 0; i < hw->num_sds_rings; i++) {
lro = &hw->sds[i].lro;
tcp_lro_free(lro);
}
return;
}
/*
* Name: ql_del_hw_if
* Function: Destroys the hardware specific entities corresponding to an
@ -2287,6 +2375,11 @@ ql_del_hw_if(qla_host_t *ha)
ha->hw.flags.init_intr_cnxt = 0;
}
if (ha->hw.enable_soft_lro) {
qla_drain_soft_lro(ha);
qla_free_soft_lro(ha);
}
return;
}
@ -2309,7 +2402,6 @@ qla_confirm_9kb_enable(qla_host_t *ha)
return;
}
/*
* Name: ql_init_hw_if
* Function: Creates the hardware specific entities corresponding to an
@ -2416,8 +2508,19 @@ ql_init_hw_if(qla_host_t *ha)
if (qla_link_event_req(ha, ha->hw.rcv_cntxt_id))
return (-1);
if (qla_config_fw_lro(ha, ha->hw.rcv_cntxt_id))
return (-1);
if (ha->ifp->if_capenable & IFCAP_LRO) {
if (ha->hw.enable_hw_lro) {
ha->hw.enable_soft_lro = 0;
if (qla_config_fw_lro(ha, ha->hw.rcv_cntxt_id))
return (-1);
} else {
ha->hw.enable_soft_lro = 1;
if (qla_config_soft_lro(ha))
return (-1);
}
}
if (qla_init_nic_func(ha))
return (-1);

View File

@ -1674,6 +1674,8 @@ typedef struct _qla_hw {
uint32_t max_tx_segs;
uint32_t min_lro_pkt_size;
uint32_t enable_hw_lro;
uint32_t enable_soft_lro;
uint32_t enable_9kb;
uint32_t user_pri_nic;

View File

@ -68,6 +68,9 @@ qla_rx_intr(qla_host_t *ha, qla_sgl_rcv_t *sgc, uint32_t sds_idx)
uint32_t i, rem_len = 0;
uint32_t r_idx = 0;
qla_rx_ring_t *rx_ring;
struct lro_ctrl *lro;
lro = &ha->hw.sds[sds_idx].lro;
if (ha->hw.num_rds_rings > 1)
r_idx = sds_idx;
@ -166,7 +169,22 @@ qla_rx_intr(qla_host_t *ha, qla_sgl_rcv_t *sgc, uint32_t sds_idx)
M_HASHTYPE_SET(mpf, M_HASHTYPE_NONE);
#endif /* #if __FreeBSD_version >= 1100000 */
(*ifp->if_input)(ifp, mpf);
if (ha->hw.enable_soft_lro) {
#if (__FreeBSD_version >= 1100101)
tcp_lro_queue_mbuf(lro, mpf);
#else
if (tcp_lro_rx(lro, mpf, 0))
(*ifp->if_input)(ifp, mpf);
#endif /* #if (__FreeBSD_version >= 1100101) */
} else {
(*ifp->if_input)(ifp, mpf);
}
if (sdsp->rx_free > ha->std_replenish)
qla_replenish_normal_rx(ha, sdsp, r_idx);
@ -707,6 +725,28 @@ ql_rcv_isr(qla_host_t *ha, uint32_t sds_idx, uint32_t count)
}
}
if (ha->hw.enable_soft_lro) {
struct lro_ctrl *lro;
lro = &ha->hw.sds[sds_idx].lro;
#if (__FreeBSD_version >= 1100101)
tcp_lro_flush_all(lro);
#else
struct lro_entry *queued;
while ((!SLIST_EMPTY(&lro->lro_active))) {
queued = SLIST_FIRST(&lro->lro_active);
SLIST_REMOVE_HEAD(&lro->lro_active, next);
tcp_lro_flush(lro, queued);
}
#endif /* #if (__FreeBSD_version >= 1100101) */
}
if (ha->flags.stop_rcv)
goto ql_rcv_isr_exit;

View File

@ -1072,6 +1072,8 @@ qla_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
if (mask & IFCAP_VLAN_HWTSO)
ifp->if_capenable ^= IFCAP_VLAN_HWTSO;
if (mask & IFCAP_LRO)
ifp->if_capenable ^= IFCAP_LRO;
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
qla_init(ha);
@ -1497,7 +1499,6 @@ qla_qflush(struct ifnet *ifp)
return;
}
static void
qla_stop(qla_host_t *ha)
{