summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorVishal Kulkarni <vishal@chelsio.com>2018-01-18 21:23:39 +0000
committerRobert Mustacchi <rm@joyent.com>2018-05-23 23:50:04 +0000
commit06b05760eff34bfc45a97eaaebf16471244d9c12 (patch)
tree7241e61f7ecfa7c60a29092292d3c7768b016cea /usr/src
parentdcdf0a4270013e35559ba57aacd3119ffc6b3921 (diff)
downloadillumos-joyent-06b05760eff34bfc45a97eaaebf16471244d9c12.tar.gz
9484 cxgbe should clean TX descriptors in timely manner
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com> Reviewed by: Ryan Zezeski <rpz@joyent.com> Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Reviewed by: Toomas Soome <tsoome@me.com> Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/io/cxgbe/t4nex/adapter.h1
-rw-r--r--usr/src/uts/common/io/cxgbe/t4nex/t4_nexus.c21
-rw-r--r--usr/src/uts/common/io/cxgbe/t4nex/t4_sge.c19
3 files changed, 39 insertions, 2 deletions
diff --git a/usr/src/uts/common/io/cxgbe/t4nex/adapter.h b/usr/src/uts/common/io/cxgbe/t4nex/adapter.h
index cf6fd497fd..7aedd30c6a 100644
--- a/usr/src/uts/common/io/cxgbe/t4nex/adapter.h
+++ b/usr/src/uts/common/io/cxgbe/t4nex/adapter.h
@@ -507,6 +507,7 @@ struct adapter {
struct sge sge;
struct port_info *port[MAX_NPORTS];
+ ddi_taskq_t *tq[NCHAN];
uint8_t chan_map[NCHAN];
uint32_t filter_mode;
diff --git a/usr/src/uts/common/io/cxgbe/t4nex/t4_nexus.c b/usr/src/uts/common/io/cxgbe/t4nex/t4_nexus.c
index 5607385283..6de5af0e30 100644
--- a/usr/src/uts/common/io/cxgbe/t4nex/t4_nexus.c
+++ b/usr/src/uts/common/io/cxgbe/t4nex/t4_nexus.c
@@ -369,6 +369,20 @@ t4_devo_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
sc->fw_msg_handler[i] = fw_msg_not_handled;
}
+ for (i = 0; i < NCHAN; i++) {
+ (void) snprintf(name, sizeof (name), "%s-%d",
+ "reclaim", i);
+ sc->tq[i] = ddi_taskq_create(sc->dip,
+ name, 1, TASKQ_DEFAULTPRI, 0);
+
+ if (sc->tq[i] == NULL) {
+ cxgb_printf(dip, CE_WARN,
+ "failed to create task queues");
+ rc = DDI_FAILURE;
+ goto done;
+ }
+ }
+
/*
* Prepare the adapter for operation.
*/
@@ -836,6 +850,13 @@ t4_devo_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
ddi_prop_remove_all(dip);
ddi_remove_minor_node(dip, NULL);
+ for (i = 0; i < NCHAN; i++) {
+ if (sc->tq[i]) {
+ ddi_taskq_wait(sc->tq[i]);
+ ddi_taskq_destroy(sc->tq[i]);
+ }
+ }
+
if (sc->ksp != NULL)
kstat_delete(sc->ksp);
if (sc->ksp_stat != NULL)
diff --git a/usr/src/uts/common/io/cxgbe/t4nex/t4_sge.c b/usr/src/uts/common/io/cxgbe/t4nex/t4_sge.c
index 6f68670bc9..2109c6fcf2 100644
--- a/usr/src/uts/common/io/cxgbe/t4nex/t4_sge.c
+++ b/usr/src/uts/common/io/cxgbe/t4nex/t4_sge.c
@@ -693,7 +693,6 @@ t4_intr_rx_work(struct sge_iq *iq)
uint_t
t4_intr(caddr_t arg1, caddr_t arg2)
{
- /* LINTED: E_BAD_PTR_CAST_ALIGN */
struct sge_iq *iq = (struct sge_iq *)arg2;
int state;
@@ -1687,7 +1686,8 @@ eth_eq_alloc(struct adapter *sc, struct port_info *pi, struct sge_eq *eq)
V_FW_EQ_ETH_CMD_VFN(0));
c.alloc_to_len16 = BE_32(F_FW_EQ_ETH_CMD_ALLOC |
F_FW_EQ_ETH_CMD_EQSTART | FW_LEN16(c));
- c.autoequiqe_to_viid = BE_32(V_FW_EQ_ETH_CMD_VIID(pi->viid));
+ c.autoequiqe_to_viid = BE_32(F_FW_EQ_ETH_CMD_AUTOEQUIQE |
+ F_FW_EQ_ETH_CMD_AUTOEQUEQE | V_FW_EQ_ETH_CMD_VIID(pi->viid));
c.fetchszm_to_iqid =
BE_32(V_FW_EQ_ETH_CMD_HOSTFCMODE(X_HOSTFCMODE_STATUS_PAGE) |
V_FW_EQ_ETH_CMD_PCIECHN(eq->tx_chan) | F_FW_EQ_ETH_CMD_FETCHRO |
@@ -3346,6 +3346,16 @@ ring_fl_db(struct adapter *sc, struct sge_fl *fl)
fl->pending -= ndesc * 8;
}
+static void
+tx_reclaim_task(void *arg)
+{
+ struct sge_txq *txq = arg;
+
+ TXQ_LOCK(txq);
+ reclaim_tx_descs(txq, txq->eq.qsize);
+ TXQ_UNLOCK(txq);
+}
+
/* ARGSUSED */
static int
handle_sge_egr_update(struct sge_iq *iq, const struct rss_header *rss,
@@ -3355,12 +3365,17 @@ handle_sge_egr_update(struct sge_iq *iq, const struct rss_header *rss,
unsigned int qid = G_EGR_QID(ntohl(cpl->opcode_qid));
struct adapter *sc = iq->adapter;
struct sge *s = &sc->sge;
+ struct sge_eq *eq;
struct sge_txq *txq;
txq = (void *)s->eqmap[qid - s->eq_start];
+ eq = &txq->eq;
txq->qflush++;
t4_mac_tx_update(txq->port, txq);
+ ddi_taskq_dispatch(sc->tq[eq->tx_chan], tx_reclaim_task,
+ (void *)txq, DDI_NOSLEEP);
+
return (0);
}