|
@@ -227,7 +227,7 @@ static DEFINE_MUTEX(uld_mutex);
|
|
static LIST_HEAD(adap_rcu_list);
|
|
static LIST_HEAD(adap_rcu_list);
|
|
static DEFINE_SPINLOCK(adap_rcu_lock);
|
|
static DEFINE_SPINLOCK(adap_rcu_lock);
|
|
static struct cxgb4_uld_info ulds[CXGB4_ULD_MAX];
|
|
static struct cxgb4_uld_info ulds[CXGB4_ULD_MAX];
|
|
-static const char *uld_str[] = { "RDMA", "iSCSI" };
|
|
|
|
|
|
+static const char *const uld_str[] = { "RDMA", "iSCSI", "iSCSIT" };
|
|
|
|
|
|
static void link_report(struct net_device *dev)
|
|
static void link_report(struct net_device *dev)
|
|
{
|
|
{
|
|
@@ -664,6 +664,13 @@ out:
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/* Flush the aggregated lro sessions */
|
|
|
|
+static void uldrx_flush_handler(struct sge_rspq *q)
|
|
|
|
+{
|
|
|
|
+ if (ulds[q->uld].lro_flush)
|
|
|
|
+ ulds[q->uld].lro_flush(&q->lro_mgr);
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* uldrx_handler - response queue handler for ULD queues
|
|
* uldrx_handler - response queue handler for ULD queues
|
|
* @q: the response queue that received the packet
|
|
* @q: the response queue that received the packet
|
|
@@ -677,6 +684,7 @@ static int uldrx_handler(struct sge_rspq *q, const __be64 *rsp,
|
|
const struct pkt_gl *gl)
|
|
const struct pkt_gl *gl)
|
|
{
|
|
{
|
|
struct sge_ofld_rxq *rxq = container_of(q, struct sge_ofld_rxq, rspq);
|
|
struct sge_ofld_rxq *rxq = container_of(q, struct sge_ofld_rxq, rspq);
|
|
|
|
+ int ret;
|
|
|
|
|
|
/* FW can send CPLs encapsulated in a CPL_FW4_MSG.
|
|
/* FW can send CPLs encapsulated in a CPL_FW4_MSG.
|
|
*/
|
|
*/
|
|
@@ -684,10 +692,19 @@ static int uldrx_handler(struct sge_rspq *q, const __be64 *rsp,
|
|
((const struct cpl_fw4_msg *)(rsp + 1))->type == FW_TYPE_RSSCPL)
|
|
((const struct cpl_fw4_msg *)(rsp + 1))->type == FW_TYPE_RSSCPL)
|
|
rsp += 2;
|
|
rsp += 2;
|
|
|
|
|
|
- if (ulds[q->uld].rx_handler(q->adap->uld_handle[q->uld], rsp, gl)) {
|
|
|
|
|
|
+ if (q->flush_handler)
|
|
|
|
+ ret = ulds[q->uld].lro_rx_handler(q->adap->uld_handle[q->uld],
|
|
|
|
+ rsp, gl, &q->lro_mgr,
|
|
|
|
+ &q->napi);
|
|
|
|
+ else
|
|
|
|
+ ret = ulds[q->uld].rx_handler(q->adap->uld_handle[q->uld],
|
|
|
|
+ rsp, gl);
|
|
|
|
+
|
|
|
|
+ if (ret) {
|
|
rxq->stats.nomem++;
|
|
rxq->stats.nomem++;
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
+
|
|
if (gl == NULL)
|
|
if (gl == NULL)
|
|
rxq->stats.imm++;
|
|
rxq->stats.imm++;
|
|
else if (gl == CXGB4_MSG_AN)
|
|
else if (gl == CXGB4_MSG_AN)
|
|
@@ -754,6 +771,10 @@ static void name_msix_vecs(struct adapter *adap)
|
|
snprintf(adap->msix_info[msi_idx++].desc, n, "%s-iscsi%d",
|
|
snprintf(adap->msix_info[msi_idx++].desc, n, "%s-iscsi%d",
|
|
adap->port[0]->name, i);
|
|
adap->port[0]->name, i);
|
|
|
|
|
|
|
|
+ for_each_iscsitrxq(&adap->sge, i)
|
|
|
|
+ snprintf(adap->msix_info[msi_idx++].desc, n, "%s-iSCSIT%d",
|
|
|
|
+ adap->port[0]->name, i);
|
|
|
|
+
|
|
for_each_rdmarxq(&adap->sge, i)
|
|
for_each_rdmarxq(&adap->sge, i)
|
|
snprintf(adap->msix_info[msi_idx++].desc, n, "%s-rdma%d",
|
|
snprintf(adap->msix_info[msi_idx++].desc, n, "%s-rdma%d",
|
|
adap->port[0]->name, i);
|
|
adap->port[0]->name, i);
|
|
@@ -767,6 +788,7 @@ static int request_msix_queue_irqs(struct adapter *adap)
|
|
{
|
|
{
|
|
struct sge *s = &adap->sge;
|
|
struct sge *s = &adap->sge;
|
|
int err, ethqidx, iscsiqidx = 0, rdmaqidx = 0, rdmaciqqidx = 0;
|
|
int err, ethqidx, iscsiqidx = 0, rdmaqidx = 0, rdmaciqqidx = 0;
|
|
|
|
+ int iscsitqidx = 0;
|
|
int msi_index = 2;
|
|
int msi_index = 2;
|
|
|
|
|
|
err = request_irq(adap->msix_info[1].vec, t4_sge_intr_msix, 0,
|
|
err = request_irq(adap->msix_info[1].vec, t4_sge_intr_msix, 0,
|
|
@@ -792,6 +814,15 @@ static int request_msix_queue_irqs(struct adapter *adap)
|
|
goto unwind;
|
|
goto unwind;
|
|
msi_index++;
|
|
msi_index++;
|
|
}
|
|
}
|
|
|
|
+ for_each_iscsitrxq(s, iscsitqidx) {
|
|
|
|
+ err = request_irq(adap->msix_info[msi_index].vec,
|
|
|
|
+ t4_sge_intr_msix, 0,
|
|
|
|
+ adap->msix_info[msi_index].desc,
|
|
|
|
+ &s->iscsitrxq[iscsitqidx].rspq);
|
|
|
|
+ if (err)
|
|
|
|
+ goto unwind;
|
|
|
|
+ msi_index++;
|
|
|
|
+ }
|
|
for_each_rdmarxq(s, rdmaqidx) {
|
|
for_each_rdmarxq(s, rdmaqidx) {
|
|
err = request_irq(adap->msix_info[msi_index].vec,
|
|
err = request_irq(adap->msix_info[msi_index].vec,
|
|
t4_sge_intr_msix, 0,
|
|
t4_sge_intr_msix, 0,
|
|
@@ -819,6 +850,9 @@ unwind:
|
|
while (--rdmaqidx >= 0)
|
|
while (--rdmaqidx >= 0)
|
|
free_irq(adap->msix_info[--msi_index].vec,
|
|
free_irq(adap->msix_info[--msi_index].vec,
|
|
&s->rdmarxq[rdmaqidx].rspq);
|
|
&s->rdmarxq[rdmaqidx].rspq);
|
|
|
|
+ while (--iscsitqidx >= 0)
|
|
|
|
+ free_irq(adap->msix_info[--msi_index].vec,
|
|
|
|
+ &s->iscsitrxq[iscsitqidx].rspq);
|
|
while (--iscsiqidx >= 0)
|
|
while (--iscsiqidx >= 0)
|
|
free_irq(adap->msix_info[--msi_index].vec,
|
|
free_irq(adap->msix_info[--msi_index].vec,
|
|
&s->iscsirxq[iscsiqidx].rspq);
|
|
&s->iscsirxq[iscsiqidx].rspq);
|
|
@@ -840,6 +874,9 @@ static void free_msix_queue_irqs(struct adapter *adap)
|
|
for_each_iscsirxq(s, i)
|
|
for_each_iscsirxq(s, i)
|
|
free_irq(adap->msix_info[msi_index++].vec,
|
|
free_irq(adap->msix_info[msi_index++].vec,
|
|
&s->iscsirxq[i].rspq);
|
|
&s->iscsirxq[i].rspq);
|
|
|
|
+ for_each_iscsitrxq(s, i)
|
|
|
|
+ free_irq(adap->msix_info[msi_index++].vec,
|
|
|
|
+ &s->iscsitrxq[i].rspq);
|
|
for_each_rdmarxq(s, i)
|
|
for_each_rdmarxq(s, i)
|
|
free_irq(adap->msix_info[msi_index++].vec, &s->rdmarxq[i].rspq);
|
|
free_irq(adap->msix_info[msi_index++].vec, &s->rdmarxq[i].rspq);
|
|
for_each_rdmaciq(s, i)
|
|
for_each_rdmaciq(s, i)
|
|
@@ -984,7 +1021,7 @@ static void enable_rx(struct adapter *adap)
|
|
|
|
|
|
static int alloc_ofld_rxqs(struct adapter *adap, struct sge_ofld_rxq *q,
|
|
static int alloc_ofld_rxqs(struct adapter *adap, struct sge_ofld_rxq *q,
|
|
unsigned int nq, unsigned int per_chan, int msi_idx,
|
|
unsigned int nq, unsigned int per_chan, int msi_idx,
|
|
- u16 *ids)
|
|
|
|
|
|
+ u16 *ids, bool lro)
|
|
{
|
|
{
|
|
int i, err;
|
|
int i, err;
|
|
|
|
|
|
@@ -994,7 +1031,9 @@ static int alloc_ofld_rxqs(struct adapter *adap, struct sge_ofld_rxq *q,
|
|
err = t4_sge_alloc_rxq(adap, &q->rspq, false,
|
|
err = t4_sge_alloc_rxq(adap, &q->rspq, false,
|
|
adap->port[i / per_chan],
|
|
adap->port[i / per_chan],
|
|
msi_idx, q->fl.size ? &q->fl : NULL,
|
|
msi_idx, q->fl.size ? &q->fl : NULL,
|
|
- uldrx_handler, 0);
|
|
|
|
|
|
+ uldrx_handler,
|
|
|
|
+ lro ? uldrx_flush_handler : NULL,
|
|
|
|
+ 0);
|
|
if (err)
|
|
if (err)
|
|
return err;
|
|
return err;
|
|
memset(&q->stats, 0, sizeof(q->stats));
|
|
memset(&q->stats, 0, sizeof(q->stats));
|
|
@@ -1024,7 +1063,7 @@ static int setup_sge_queues(struct adapter *adap)
|
|
msi_idx = 1; /* vector 0 is for non-queue interrupts */
|
|
msi_idx = 1; /* vector 0 is for non-queue interrupts */
|
|
else {
|
|
else {
|
|
err = t4_sge_alloc_rxq(adap, &s->intrq, false, adap->port[0], 0,
|
|
err = t4_sge_alloc_rxq(adap, &s->intrq, false, adap->port[0], 0,
|
|
- NULL, NULL, -1);
|
|
|
|
|
|
+ NULL, NULL, NULL, -1);
|
|
if (err)
|
|
if (err)
|
|
return err;
|
|
return err;
|
|
msi_idx = -((int)s->intrq.abs_id + 1);
|
|
msi_idx = -((int)s->intrq.abs_id + 1);
|
|
@@ -1044,7 +1083,7 @@ static int setup_sge_queues(struct adapter *adap)
|
|
* new/deleted queues.
|
|
* new/deleted queues.
|
|
*/
|
|
*/
|
|
err = t4_sge_alloc_rxq(adap, &s->fw_evtq, true, adap->port[0],
|
|
err = t4_sge_alloc_rxq(adap, &s->fw_evtq, true, adap->port[0],
|
|
- msi_idx, NULL, fwevtq_handler, -1);
|
|
|
|
|
|
+ msi_idx, NULL, fwevtq_handler, NULL, -1);
|
|
if (err) {
|
|
if (err) {
|
|
freeout: t4_free_sge_resources(adap);
|
|
freeout: t4_free_sge_resources(adap);
|
|
return err;
|
|
return err;
|
|
@@ -1062,6 +1101,7 @@ freeout: t4_free_sge_resources(adap);
|
|
err = t4_sge_alloc_rxq(adap, &q->rspq, false, dev,
|
|
err = t4_sge_alloc_rxq(adap, &q->rspq, false, dev,
|
|
msi_idx, &q->fl,
|
|
msi_idx, &q->fl,
|
|
t4_ethrx_handler,
|
|
t4_ethrx_handler,
|
|
|
|
+ NULL,
|
|
t4_get_mps_bg_map(adap,
|
|
t4_get_mps_bg_map(adap,
|
|
pi->tx_chan));
|
|
pi->tx_chan));
|
|
if (err)
|
|
if (err)
|
|
@@ -1087,18 +1127,19 @@ freeout: t4_free_sge_resources(adap);
|
|
goto freeout;
|
|
goto freeout;
|
|
}
|
|
}
|
|
|
|
|
|
-#define ALLOC_OFLD_RXQS(firstq, nq, per_chan, ids) do { \
|
|
|
|
- err = alloc_ofld_rxqs(adap, firstq, nq, per_chan, msi_idx, ids); \
|
|
|
|
|
|
+#define ALLOC_OFLD_RXQS(firstq, nq, per_chan, ids, lro) do { \
|
|
|
|
+ err = alloc_ofld_rxqs(adap, firstq, nq, per_chan, msi_idx, ids, lro); \
|
|
if (err) \
|
|
if (err) \
|
|
goto freeout; \
|
|
goto freeout; \
|
|
if (msi_idx > 0) \
|
|
if (msi_idx > 0) \
|
|
msi_idx += nq; \
|
|
msi_idx += nq; \
|
|
} while (0)
|
|
} while (0)
|
|
|
|
|
|
- ALLOC_OFLD_RXQS(s->iscsirxq, s->iscsiqsets, j, s->iscsi_rxq);
|
|
|
|
- ALLOC_OFLD_RXQS(s->rdmarxq, s->rdmaqs, 1, s->rdma_rxq);
|
|
|
|
|
|
+ ALLOC_OFLD_RXQS(s->iscsirxq, s->iscsiqsets, j, s->iscsi_rxq, false);
|
|
|
|
+ ALLOC_OFLD_RXQS(s->iscsitrxq, s->niscsitq, j, s->iscsit_rxq, true);
|
|
|
|
+ ALLOC_OFLD_RXQS(s->rdmarxq, s->rdmaqs, 1, s->rdma_rxq, false);
|
|
j = s->rdmaciqs / adap->params.nports; /* rdmaq queues per channel */
|
|
j = s->rdmaciqs / adap->params.nports; /* rdmaq queues per channel */
|
|
- ALLOC_OFLD_RXQS(s->rdmaciq, s->rdmaciqs, j, s->rdma_ciq);
|
|
|
|
|
|
+ ALLOC_OFLD_RXQS(s->rdmaciq, s->rdmaciqs, j, s->rdma_ciq, false);
|
|
|
|
|
|
#undef ALLOC_OFLD_RXQS
|
|
#undef ALLOC_OFLD_RXQS
|
|
|
|
|
|
@@ -2430,6 +2471,9 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
|
|
} else if (uld == CXGB4_ULD_ISCSI) {
|
|
} else if (uld == CXGB4_ULD_ISCSI) {
|
|
lli.rxq_ids = adap->sge.iscsi_rxq;
|
|
lli.rxq_ids = adap->sge.iscsi_rxq;
|
|
lli.nrxq = adap->sge.iscsiqsets;
|
|
lli.nrxq = adap->sge.iscsiqsets;
|
|
|
|
+ } else if (uld == CXGB4_ULD_ISCSIT) {
|
|
|
|
+ lli.rxq_ids = adap->sge.iscsit_rxq;
|
|
|
|
+ lli.nrxq = adap->sge.niscsitq;
|
|
}
|
|
}
|
|
lli.ntxq = adap->sge.iscsiqsets;
|
|
lli.ntxq = adap->sge.iscsiqsets;
|
|
lli.nchan = adap->params.nports;
|
|
lli.nchan = adap->params.nports;
|
|
@@ -2437,6 +2481,10 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
|
|
lli.wr_cred = adap->params.ofldq_wr_cred;
|
|
lli.wr_cred = adap->params.ofldq_wr_cred;
|
|
lli.adapter_type = adap->params.chip;
|
|
lli.adapter_type = adap->params.chip;
|
|
lli.iscsi_iolen = MAXRXDATA_G(t4_read_reg(adap, TP_PARA_REG2_A));
|
|
lli.iscsi_iolen = MAXRXDATA_G(t4_read_reg(adap, TP_PARA_REG2_A));
|
|
|
|
+ lli.iscsi_tagmask = t4_read_reg(adap, ULP_RX_ISCSI_TAGMASK_A);
|
|
|
|
+ lli.iscsi_pgsz_order = t4_read_reg(adap, ULP_RX_ISCSI_PSZ_A);
|
|
|
|
+ lli.iscsi_llimit = t4_read_reg(adap, ULP_RX_ISCSI_LLIMIT_A);
|
|
|
|
+ lli.iscsi_ppm = &adap->iscsi_ppm;
|
|
lli.cclk_ps = 1000000000 / adap->params.vpd.cclk;
|
|
lli.cclk_ps = 1000000000 / adap->params.vpd.cclk;
|
|
lli.udb_density = 1 << adap->params.sge.eq_qpp;
|
|
lli.udb_density = 1 << adap->params.sge.eq_qpp;
|
|
lli.ucq_density = 1 << adap->params.sge.iq_qpp;
|
|
lli.ucq_density = 1 << adap->params.sge.iq_qpp;
|
|
@@ -4336,6 +4384,9 @@ static void cfg_queues(struct adapter *adap)
|
|
s->rdmaciqs = (s->rdmaciqs / adap->params.nports) *
|
|
s->rdmaciqs = (s->rdmaciqs / adap->params.nports) *
|
|
adap->params.nports;
|
|
adap->params.nports;
|
|
s->rdmaciqs = max_t(int, s->rdmaciqs, adap->params.nports);
|
|
s->rdmaciqs = max_t(int, s->rdmaciqs, adap->params.nports);
|
|
|
|
+
|
|
|
|
+ if (!is_t4(adap->params.chip))
|
|
|
|
+ s->niscsitq = s->iscsiqsets;
|
|
}
|
|
}
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(s->ethrxq); i++) {
|
|
for (i = 0; i < ARRAY_SIZE(s->ethrxq); i++) {
|
|
@@ -4362,6 +4413,16 @@ static void cfg_queues(struct adapter *adap)
|
|
r->fl.size = 72;
|
|
r->fl.size = 72;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (!is_t4(adap->params.chip)) {
|
|
|
|
+ for (i = 0; i < ARRAY_SIZE(s->iscsitrxq); i++) {
|
|
|
|
+ struct sge_ofld_rxq *r = &s->iscsitrxq[i];
|
|
|
|
+
|
|
|
|
+ init_rspq(adap, &r->rspq, 5, 1, 1024, 64);
|
|
|
|
+ r->rspq.uld = CXGB4_ULD_ISCSIT;
|
|
|
|
+ r->fl.size = 72;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
for (i = 0; i < ARRAY_SIZE(s->rdmarxq); i++) {
|
|
for (i = 0; i < ARRAY_SIZE(s->rdmarxq); i++) {
|
|
struct sge_ofld_rxq *r = &s->rdmarxq[i];
|
|
struct sge_ofld_rxq *r = &s->rdmarxq[i];
|
|
|
|
|
|
@@ -4436,9 +4497,13 @@ static int enable_msix(struct adapter *adap)
|
|
|
|
|
|
want = s->max_ethqsets + EXTRA_VECS;
|
|
want = s->max_ethqsets + EXTRA_VECS;
|
|
if (is_offload(adap)) {
|
|
if (is_offload(adap)) {
|
|
- want += s->rdmaqs + s->rdmaciqs + s->iscsiqsets;
|
|
|
|
|
|
+ want += s->rdmaqs + s->rdmaciqs + s->iscsiqsets +
|
|
|
|
+ s->niscsitq;
|
|
/* need nchan for each possible ULD */
|
|
/* need nchan for each possible ULD */
|
|
- ofld_need = 3 * nchan;
|
|
|
|
|
|
+ if (is_t4(adap->params.chip))
|
|
|
|
+ ofld_need = 3 * nchan;
|
|
|
|
+ else
|
|
|
|
+ ofld_need = 4 * nchan;
|
|
}
|
|
}
|
|
#ifdef CONFIG_CHELSIO_T4_DCB
|
|
#ifdef CONFIG_CHELSIO_T4_DCB
|
|
/* For Data Center Bridging we need 8 Ethernet TX Priority Queues for
|
|
/* For Data Center Bridging we need 8 Ethernet TX Priority Queues for
|
|
@@ -4470,12 +4535,16 @@ static int enable_msix(struct adapter *adap)
|
|
if (allocated < want) {
|
|
if (allocated < want) {
|
|
s->rdmaqs = nchan;
|
|
s->rdmaqs = nchan;
|
|
s->rdmaciqs = nchan;
|
|
s->rdmaciqs = nchan;
|
|
|
|
+
|
|
|
|
+ if (!is_t4(adap->params.chip))
|
|
|
|
+ s->niscsitq = nchan;
|
|
}
|
|
}
|
|
|
|
|
|
/* leftovers go to OFLD */
|
|
/* leftovers go to OFLD */
|
|
i = allocated - EXTRA_VECS - s->max_ethqsets -
|
|
i = allocated - EXTRA_VECS - s->max_ethqsets -
|
|
- s->rdmaqs - s->rdmaciqs;
|
|
|
|
|
|
+ s->rdmaqs - s->rdmaciqs - s->niscsitq;
|
|
s->iscsiqsets = (i / nchan) * nchan; /* round down */
|
|
s->iscsiqsets = (i / nchan) * nchan; /* round down */
|
|
|
|
+
|
|
}
|
|
}
|
|
for (i = 0; i < allocated; ++i)
|
|
for (i = 0; i < allocated; ++i)
|
|
adap->msix_info[i].vec = entries[i].vector;
|
|
adap->msix_info[i].vec = entries[i].vector;
|