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:
parent
fdf71aeb54
commit
eff62dba61
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=333698
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user