cxgbe(4): Allocate offload Tx queues when a card has resources

provisioned for NIC_ETHOFLD and the kernel has option RATELIMIT.

It is possible to use the chip's offload queues for normal NIC Tx and
not just TOE Tx.  The difference is that these queues support out of
order processing of work requests and have a per-"flowid" mechanism for
tracking credits between the driver and hardware.  This allows Tx for
any number of flows bound to different rate limits to be submitted to a
single Tx queue and the work requests for slow flows won't cause HOL
blocking for the rest.

Sponsored by:	Chelsio Communications
This commit is contained in:
Navdeep Parhar 2018-05-17 01:42:18 +00:00
parent fdf71aeb54
commit eff62dba61
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=333698
3 changed files with 58 additions and 24 deletions

View File

@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include "opt_inet.h"
#include "opt_inet6.h"
#include "opt_ratelimit.h"
#include "opt_rss.h"
#include <sys/param.h>
@ -269,7 +270,7 @@ TUNABLE_INT("hw.cxgbe.nrxq_vi", &t4_nrxq_vi);
static int t4_rsrv_noflowq = 0;
TUNABLE_INT("hw.cxgbe.rsrv_noflowq", &t4_rsrv_noflowq);
#ifdef TCP_OFFLOAD
#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
#define NOFLDTXQ 8
static int t4_nofldtxq = -NOFLDTXQ;
TUNABLE_INT("hw.cxgbe.nofldtxq", &t4_nofldtxq);
@ -499,7 +500,7 @@ struct intrs_and_queues {
uint16_t nirq; /* Total # of vectors */
uint16_t ntxq; /* # of NIC txq's for each port */
uint16_t nrxq; /* # of NIC rxq's for each port */
uint16_t nofldtxq; /* # of TOE txq's for each port */
uint16_t nofldtxq; /* # of TOE/ETHOFLD txq's for each port */
uint16_t nofldrxq; /* # of TOE rxq's for each port */
/* The vcxgbe/vcxl interfaces use these and not the ones above. */
@ -834,8 +835,11 @@ t4_attach(device_t dev)
struct intrs_and_queues iaq;
struct sge *s;
uint32_t *buf;
#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
int ofld_tqidx;
#endif
#ifdef TCP_OFFLOAD
int ofld_rqidx, ofld_tqidx;
int ofld_rqidx;
#endif
#ifdef DEV_NETMAP
int nm_rqidx, nm_tqidx;
@ -1048,21 +1052,26 @@ t4_attach(device_t dev)
s->neq = s->ntxq + s->nrxq; /* the free list in an rxq is an eq */
s->neq += nports + 1;/* ctrl queues: 1 per port + 1 mgmt */
s->niq = s->nrxq + 1; /* 1 extra for firmware event queue */
#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
if (is_offload(sc) || is_ethoffload(sc)) {
s->nofldtxq = nports * iaq.nofldtxq;
if (num_vis > 1)
s->nofldtxq += nports * (num_vis - 1) * iaq.nofldtxq_vi;
s->neq += s->nofldtxq + s->nofldrxq;
s->ofld_txq = malloc(s->nofldtxq * sizeof(struct sge_wrq),
M_CXGBE, M_ZERO | M_WAITOK);
}
#endif
#ifdef TCP_OFFLOAD
if (is_offload(sc)) {
s->nofldrxq = nports * iaq.nofldrxq;
s->nofldtxq = nports * iaq.nofldtxq;
if (num_vis > 1) {
s->nofldrxq += nports * (num_vis - 1) * iaq.nofldrxq_vi;
s->nofldtxq += nports * (num_vis - 1) * iaq.nofldtxq_vi;
}
s->neq += s->nofldtxq + s->nofldrxq;
s->niq += s->nofldrxq;
s->ofld_rxq = malloc(s->nofldrxq * sizeof(struct sge_ofld_rxq),
M_CXGBE, M_ZERO | M_WAITOK);
s->ofld_txq = malloc(s->nofldtxq * sizeof(struct sge_wrq),
M_CXGBE, M_ZERO | M_WAITOK);
}
#endif
#ifdef DEV_NETMAP
@ -1101,8 +1110,11 @@ t4_attach(device_t dev)
* tx queues that each port should get.
*/
rqidx = tqidx = 0;
#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
ofld_tqidx = 0;
#endif
#ifdef TCP_OFFLOAD
ofld_rqidx = ofld_tqidx = 0;
ofld_rqidx = 0;
#endif
#ifdef DEV_NETMAP
nm_rqidx = nm_tqidx = 0;
@ -1135,16 +1147,18 @@ t4_attach(device_t dev)
else
vi->rsrv_noflowq = 0;
#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
vi->first_ofld_txq = ofld_tqidx;
vi->nofldtxq = j == 0 ? iaq.nofldtxq : iaq.nofldtxq_vi;
ofld_tqidx += vi->nofldtxq;
#endif
#ifdef TCP_OFFLOAD
vi->ofld_tmr_idx = t4_tmr_idx_ofld;
vi->ofld_pktc_idx = t4_pktc_idx_ofld;
vi->first_ofld_rxq = ofld_rqidx;
vi->first_ofld_txq = ofld_tqidx;
vi->nofldrxq = j == 0 ? iaq.nofldrxq : iaq.nofldrxq_vi;
vi->nofldtxq = j == 0 ? iaq.nofldtxq : iaq.nofldtxq_vi;
ofld_rqidx += vi->nofldrxq;
ofld_tqidx += vi->nofldtxq;
#endif
#ifdef DEV_NETMAP
if (j > 0) {
@ -1361,9 +1375,11 @@ t4_detach_common(device_t dev)
if (sc->l2t)
t4_free_l2t(sc->l2t);
#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
free(sc->sge.ofld_txq, M_CXGBE);
#endif
#ifdef TCP_OFFLOAD
free(sc->sge.ofld_rxq, M_CXGBE);
free(sc->sge.ofld_txq, M_CXGBE);
#endif
#ifdef DEV_NETMAP
free(sc->sge.nm_rxq, M_CXGBE);
@ -2793,10 +2809,14 @@ calculate_iaq(struct adapter *sc, struct intrs_and_queues *iaq, int itype,
iaq->ntxq_vi = t4_ntxq_vi;
iaq->nrxq = t4_nrxq;
iaq->nrxq_vi = t4_nrxq_vi;
#ifdef TCP_OFFLOAD
if (is_offload(sc)) {
#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
if (is_offload(sc) || is_ethoffload(sc)) {
iaq->nofldtxq = t4_nofldtxq;
iaq->nofldtxq_vi = t4_nofldtxq_vi;
}
#endif
#ifdef TCP_OFFLOAD
if (is_offload(sc)) {
iaq->nofldrxq = t4_nofldrxq;
iaq->nofldrxq_vi = t4_nofldrxq_vi;
}
@ -9657,9 +9677,11 @@ tweak_tunables(void)
calculate_nqueues(&t4_nrxq_vi, nc, NRXQ_VI);
#ifdef TCP_OFFLOAD
#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
calculate_nqueues(&t4_nofldtxq, nc, NOFLDTXQ);
calculate_nqueues(&t4_nofldtxq_vi, nc, NOFLDTXQ_VI);
#endif
#ifdef TCP_OFFLOAD
calculate_nqueues(&t4_nofldrxq, nc, NOFLDRXQ);
calculate_nqueues(&t4_nofldrxq_vi, nc, NOFLDRXQ_VI);

View File

@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include "opt_inet.h"
#include "opt_inet6.h"
#include "opt_ratelimit.h"
#include <sys/types.h>
#include <sys/eventhandler.h>
@ -224,7 +225,7 @@ static int free_nm_txq(struct vi_info *, struct sge_nm_txq *);
#endif
static int ctrl_eq_alloc(struct adapter *, struct sge_eq *);
static int eth_eq_alloc(struct adapter *, struct vi_info *, struct sge_eq *);
#ifdef TCP_OFFLOAD
#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
static int ofld_eq_alloc(struct adapter *, struct vi_info *, struct sge_eq *);
#endif
static int alloc_eq(struct adapter *, struct vi_info *, struct sge_eq *);
@ -1045,6 +1046,8 @@ t4_setup_vi_queues(struct vi_info *vi)
struct sge_wrq *ctrlq;
#ifdef TCP_OFFLOAD
struct sge_ofld_rxq *ofld_rxq;
#endif
#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
struct sge_wrq *ofld_txq;
#endif
#ifdef DEV_NETMAP
@ -1160,17 +1163,23 @@ t4_setup_vi_queues(struct vi_info *vi)
if (rc != 0)
goto done;
}
#ifdef TCP_OFFLOAD
#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
oid = SYSCTL_ADD_NODE(&vi->ctx, children, OID_AUTO, "ofld_txq",
CTLFLAG_RD, NULL, "tx queues for offloaded TCP connections");
CTLFLAG_RD, NULL, "tx queues for TOE/ETHOFLD");
for_each_ofld_txq(vi, i, ofld_txq) {
struct sysctl_oid *oid2;
iqidx = vi->first_ofld_rxq + (i % vi->nofldrxq);
snprintf(name, sizeof(name), "%s ofld_txq%d",
device_get_nameunit(vi->dev), i);
#ifdef TCP_OFFLOAD
iqidx = vi->first_ofld_rxq + (i % vi->nofldrxq);
init_eq(sc, &ofld_txq->eq, EQ_OFLD, vi->qsize_txq, pi->tx_chan,
sc->sge.ofld_rxq[iqidx].iq.cntxt_id, name);
#else
iqidx = vi->first_rxq + (i % vi->nrxq);
init_eq(sc, &ofld_txq->eq, EQ_OFLD, vi->qsize_txq, pi->tx_chan,
sc->sge.rxq[iqidx].iq.cntxt_id, name);
#endif
snprintf(name, sizeof(name), "%d", i);
oid2 = SYSCTL_ADD_NODE(&vi->ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
@ -1215,6 +1224,8 @@ t4_teardown_vi_queues(struct vi_info *vi)
struct sge_txq *txq;
#ifdef TCP_OFFLOAD
struct sge_ofld_rxq *ofld_rxq;
#endif
#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
struct sge_wrq *ofld_txq;
#endif
#ifdef DEV_NETMAP
@ -1251,7 +1262,7 @@ t4_teardown_vi_queues(struct vi_info *vi)
for_each_txq(vi, i, txq) {
free_txq(vi, txq);
}
#ifdef TCP_OFFLOAD
#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
for_each_ofld_txq(vi, i, ofld_txq) {
free_wrq(sc, ofld_txq);
}
@ -3388,7 +3399,7 @@ eth_eq_alloc(struct adapter *sc, struct vi_info *vi, struct sge_eq *eq)
return (rc);
}
#ifdef TCP_OFFLOAD
#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
static int
ofld_eq_alloc(struct adapter *sc, struct vi_info *vi, struct sge_eq *eq)
{
@ -3460,7 +3471,7 @@ alloc_eq(struct adapter *sc, struct vi_info *vi, struct sge_eq *eq)
rc = eth_eq_alloc(sc, vi, eq);
break;
#ifdef TCP_OFFLOAD
#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
case EQ_OFLD:
rc = ofld_eq_alloc(sc, vi, eq);
break;
@ -3515,7 +3526,7 @@ free_eq(struct adapter *sc, struct sge_eq *eq)
eq->cntxt_id);
break;
#ifdef TCP_OFFLOAD
#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
case EQ_OFLD:
rc = -t4_ofld_eq_free(sc, sc->mbox, sc->pf, 0,
eq->cntxt_id);

View File

@ -12,6 +12,7 @@ SRCS+= opt_ddb.h
SRCS+= opt_inet.h
SRCS+= opt_inet6.h
SRCS+= opt_ofed.h
SRCS+= opt_ratelimit.h
SRCS+= opt_rss.h
SRCS+= pci_if.h pci_iov_if.h
SRCS+= t4_filter.c