Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 6 Aug 2018 23:21:13 +0000 (UTC)
From:      Navdeep Parhar <np@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r337398 - in head/sys/dev/cxgbe: . tom
Message-ID:  <201808062321.w76NLDO6092038@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: np
Date: Mon Aug  6 23:21:13 2018
New Revision: 337398
URL: https://svnweb.freebsd.org/changeset/base/337398

Log:
  cxgbe(4): Allow user-configured and driver-configured traffic classes to
  be used simultaneously.  Move sysctl_tc and sysctl_tc_params to
  t4_sched.c while here.
  
  MFC after:	3 weeks
  Sponsored by:	Chelsio Communications

Modified:
  head/sys/dev/cxgbe/adapter.h
  head/sys/dev/cxgbe/t4_main.c
  head/sys/dev/cxgbe/t4_sched.c
  head/sys/dev/cxgbe/t4_sge.c
  head/sys/dev/cxgbe/tom/t4_cpl_io.c
  head/sys/dev/cxgbe/tom/t4_tom.c

Modified: head/sys/dev/cxgbe/adapter.h
==============================================================================
--- head/sys/dev/cxgbe/adapter.h	Mon Aug  6 21:54:51 2018	(r337397)
+++ head/sys/dev/cxgbe/adapter.h	Mon Aug  6 23:21:13 2018	(r337398)
@@ -235,13 +235,15 @@ struct tx_ch_rl_params {
 };
 
 enum {
-	TX_CLRL_REFRESH	= (1 << 0),	/* Need to update hardware state. */
-	TX_CLRL_ERROR	= (1 << 1),	/* Error, hardware state unknown. */
+	CLRL_USER	= (1 << 0),	/* allocated manually. */
+	CLRL_SYNC	= (1 << 1),	/* sync hw update in progress. */
+	CLRL_ASYNC	= (1 << 2),	/* async hw update requested. */
+	CLRL_ERR	= (1 << 3),	/* last hw setup ended in error. */
 };
 
 struct tx_cl_rl_params {
 	int refcount;
-	u_int flags;
+	uint8_t flags;
 	enum fw_sched_params_rate ratemode;	/* %port REL or ABS value */
 	enum fw_sched_params_unit rateunit;	/* kbps or pps (when ABS) */
 	enum fw_sched_params_mode mode;		/* aggr or per-flow */
@@ -1237,7 +1239,9 @@ int t4_init_tx_sched(struct adapter *);
 int t4_free_tx_sched(struct adapter *);
 void t4_update_tx_sched(struct adapter *);
 int t4_reserve_cl_rl_kbps(struct adapter *, int, u_int, int *);
-void t4_release_cl_rl_kbps(struct adapter *, int, int);
+void t4_release_cl_rl(struct adapter *, int, int);
+int sysctl_tc(SYSCTL_HANDLER_ARGS);
+int sysctl_tc_params(SYSCTL_HANDLER_ARGS);
 #ifdef RATELIMIT
 void t4_init_etid_table(struct adapter *);
 void t4_free_etid_table(struct adapter *);

Modified: head/sys/dev/cxgbe/t4_main.c
==============================================================================
--- head/sys/dev/cxgbe/t4_main.c	Mon Aug  6 21:54:51 2018	(r337397)
+++ head/sys/dev/cxgbe/t4_main.c	Mon Aug  6 23:21:13 2018	(r337398)
@@ -589,7 +589,6 @@ static int sysctl_tp_la(SYSCTL_HANDLER_ARGS);
 static int sysctl_tx_rate(SYSCTL_HANDLER_ARGS);
 static int sysctl_ulprx_la(SYSCTL_HANDLER_ARGS);
 static int sysctl_wcwr_stats(SYSCTL_HANDLER_ARGS);
-static int sysctl_tc_params(SYSCTL_HANDLER_ARGS);
 static int sysctl_cpus(SYSCTL_HANDLER_ARGS);
 #ifdef TCP_OFFLOAD
 static int sysctl_tls_rx_ports(SYSCTL_HANDLER_ARGS);
@@ -5963,6 +5962,7 @@ cxgbe_sysctls(struct port_info *pi)
 	struct adapter *sc = pi->adapter;
 	int i;
 	char name[16];
+	static char *tc_flags = {"\20\1USER\2SYNC\3ASYNC\4ERR"};
 
 	ctx = device_get_sysctl_ctx(pi->dev);
 
@@ -6015,8 +6015,9 @@ cxgbe_sysctls(struct port_info *pi)
 		children2 = SYSCTL_CHILDREN(SYSCTL_ADD_NODE(ctx,
 		    SYSCTL_CHILDREN(oid), OID_AUTO, name, CTLFLAG_RD, NULL,
 		    "traffic class"));
-		SYSCTL_ADD_UINT(ctx, children2, OID_AUTO, "flags", CTLFLAG_RD,
-		    &tc->flags, 0, "flags");
+		SYSCTL_ADD_PROC(ctx, children2, OID_AUTO, "flags",
+		    CTLTYPE_STRING | CTLFLAG_RD, tc_flags, (uintptr_t)&tc->flags,
+		    sysctl_bitfield_8b, "A", "flags");
 		SYSCTL_ADD_UINT(ctx, children2, OID_AUTO, "refcount",
 		    CTLFLAG_RD, &tc->refcount, 0, "references to this class");
 		SYSCTL_ADD_PROC(ctx, children2, OID_AUTO, "params",
@@ -8607,83 +8608,6 @@ sysctl_wcwr_stats(SYSCTL_HANDLER_ARGS)
 		}
 	}
 	rc = sbuf_finish(sb);
-	sbuf_delete(sb);
-
-	return (rc);
-}
-
-static int
-sysctl_tc_params(SYSCTL_HANDLER_ARGS)
-{
-	struct adapter *sc = arg1;
-	struct tx_cl_rl_params tc;
-	struct sbuf *sb;
-	int i, rc, port_id, mbps, gbps;
-
-	rc = sysctl_wire_old_buffer(req, 0);
-	if (rc != 0)
-		return (rc);
-
-	sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req);
-	if (sb == NULL)
-		return (ENOMEM);
-
-	port_id = arg2 >> 16;
-	MPASS(port_id < sc->params.nports);
-	MPASS(sc->port[port_id] != NULL);
-	i = arg2 & 0xffff;
-	MPASS(i < sc->chip_params->nsched_cls);
-
-	mtx_lock(&sc->tc_lock);
-	tc = sc->port[port_id]->sched_params->cl_rl[i];
-	mtx_unlock(&sc->tc_lock);
-
-	switch (tc.rateunit) {
-	case SCHED_CLASS_RATEUNIT_BITS:
-		switch (tc.ratemode) {
-		case SCHED_CLASS_RATEMODE_REL:
-			/* XXX: top speed or actual link speed? */
-			gbps = port_top_speed(sc->port[port_id]);
-			sbuf_printf(sb, "%u%% of %uGbps", tc.maxrate, gbps);
-			break;
-		case SCHED_CLASS_RATEMODE_ABS:
-			mbps = tc.maxrate / 1000;
-			gbps = tc.maxrate / 1000000;
-			if (tc.maxrate == gbps * 1000000)
-				sbuf_printf(sb, "%uGbps", gbps);
-			else if (tc.maxrate == mbps * 1000)
-				sbuf_printf(sb, "%uMbps", mbps);
-			else
-				sbuf_printf(sb, "%uKbps", tc.maxrate);
-			break;
-		default:
-			rc = ENXIO;
-			goto done;
-		}
-		break;
-	case SCHED_CLASS_RATEUNIT_PKTS:
-		sbuf_printf(sb, "%upps", tc.maxrate);
-		break;
-	default:
-		rc = ENXIO;
-		goto done;
-	}
-
-	switch (tc.mode) {
-	case SCHED_CLASS_MODE_CLASS:
-		sbuf_printf(sb, " aggregate");
-		break;
-	case SCHED_CLASS_MODE_FLOW:
-		sbuf_printf(sb, " per-flow");
-		break;
-	default:
-		rc = ENXIO;
-		goto done;
-	}
-
-done:
-	if (rc == 0)
-		rc = sbuf_finish(sb);
 	sbuf_delete(sb);
 
 	return (rc);

Modified: head/sys/dev/cxgbe/t4_sched.c
==============================================================================
--- head/sys/dev/cxgbe/t4_sched.c	Mon Aug  6 21:54:51 2018	(r337397)
+++ head/sys/dev/cxgbe/t4_sched.c	Mon Aug  6 23:21:13 2018	(r337398)
@@ -75,7 +75,7 @@ set_sched_class_params(struct adapter *sc, struct t4_s
 {
 	int rc, top_speed, fw_level, fw_mode, fw_rateunit, fw_ratemode;
 	struct port_info *pi;
-	struct tx_cl_rl_params *tc;
+	struct tx_cl_rl_params *tc, old;
 	bool check_pktsize = false;
 
 	if (p->level == SCHED_CLASS_LEVEL_CL_RL)
@@ -179,43 +179,62 @@ set_sched_class_params(struct adapter *sc, struct t4_s
 			return (ERANGE);
 	}
 
-	rc = begin_synchronized_op(sc, NULL,
-	    sleep_ok ? (SLEEP_OK | INTR_OK) : HOLD_LOCK, "t4sscp");
-	if (rc)
-		return (rc);
 	if (p->level == SCHED_CLASS_LEVEL_CL_RL) {
 		tc = &pi->sched_params->cl_rl[p->cl];
-		if (tc->refcount > 0) {
+		mtx_lock(&sc->tc_lock);
+		if (tc->refcount > 0 || tc->flags & (CLRL_SYNC | CLRL_ASYNC))
 			rc = EBUSY;
-			goto done;
-		} else {
+		else {
+			tc->flags |= CLRL_SYNC | CLRL_USER;
 			tc->ratemode = fw_ratemode;
 			tc->rateunit = fw_rateunit;
 			tc->mode = fw_mode;
 			tc->maxrate = p->maxrate;
 			tc->pktsize = p->pktsize;
+			rc = 0;
+			old= *tc;
 		}
+		mtx_unlock(&sc->tc_lock);
+		if (rc != 0)
+			return (rc);
 	}
+
+	rc = begin_synchronized_op(sc, NULL,
+	    sleep_ok ? (SLEEP_OK | INTR_OK) : HOLD_LOCK, "t4sscp");
+	if (rc != 0) {
+		if (p->level == SCHED_CLASS_LEVEL_CL_RL) {
+			mtx_lock(&sc->tc_lock);
+			*tc = old;
+			mtx_unlock(&sc->tc_lock);
+		}
+		return (rc);
+	}
 	rc = -t4_sched_params(sc, FW_SCHED_TYPE_PKTSCHED, fw_level, fw_mode,
 	    fw_rateunit, fw_ratemode, p->channel, p->cl, p->minrate, p->maxrate,
 	    p->weight, p->pktsize, sleep_ok);
-	if (p->level == SCHED_CLASS_LEVEL_CL_RL && rc != 0) {
-		/*
-		 * Unknown state at this point, see parameters in tc for what
-		 * was attempted.
-		 */
-		tc->flags |= TX_CLRL_ERROR;
-	}
-done:
 	end_synchronized_op(sc, sleep_ok ? 0 : LOCK_HELD);
 
+	if (p->level == SCHED_CLASS_LEVEL_CL_RL) {
+		mtx_lock(&sc->tc_lock);
+		MPASS(tc->flags & CLRL_SYNC);
+		MPASS(tc->flags & CLRL_USER);
+		MPASS(tc->refcount == 0);
+
+		tc->flags &= ~CLRL_SYNC;
+		if (rc == 0)
+			tc->flags &= ~CLRL_ERR;
+		else
+			tc->flags |= CLRL_ERR;
+		mtx_unlock(&sc->tc_lock);
+	}
+
 	return (rc);
 }
 
 static void
 update_tx_sched(void *context, int pending)
 {
-	int i, j, mode, rateunit, ratemode, maxrate, pktsize, rc;
+	int i, j, rc;
 	struct port_info *pi;
 	struct tx_cl_rl_params *tc;
 	struct adapter *sc = context;
@@ -227,14 +246,8 @@ update_tx_sched(void *context, int pending)
 		tc = &pi->sched_params->cl_rl[0];
 		for (j = 0; j < n; j++, tc++) {
 			MPASS(mtx_owned(&sc->tc_lock));
-			if ((tc->flags & TX_CLRL_REFRESH) == 0)
+			if ((tc->flags & CLRL_ASYNC) == 0)
 				continue;
-
-			mode = tc->mode;
-			rateunit = tc->rateunit;
-			ratemode = tc->ratemode;
-			maxrate = tc->maxrate;
-			pktsize = tc->pktsize;
 			mtx_unlock(&sc->tc_lock);
 
 			if (begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK,
@@ -242,21 +255,19 @@ update_tx_sched(void *context, int pending)
 				mtx_lock(&sc->tc_lock);
 				continue;
 			}
-			rc = t4_sched_params(sc, FW_SCHED_TYPE_PKTSCHED,
-			    FW_SCHED_PARAMS_LEVEL_CL_RL, mode, rateunit,
-			    ratemode, pi->tx_chan, j, 0, maxrate, 0, pktsize,
-			    1);
+			rc = -t4_sched_params(sc, FW_SCHED_TYPE_PKTSCHED,
+			    FW_SCHED_PARAMS_LEVEL_CL_RL, tc->mode, tc->rateunit,
+			    tc->ratemode, pi->tx_chan, j, 0, tc->maxrate, 0,
+			    tc->pktsize, 1);
 			end_synchronized_op(sc, 0);
 
 			mtx_lock(&sc->tc_lock);
-			if (rc != 0) {
-				tc->flags |= TX_CLRL_ERROR;
-			} else if (tc->mode == mode &&
-			    tc->rateunit == rateunit &&
-			    tc->maxrate == maxrate &&
-			    tc->pktsize == tc->pktsize) {
-				tc->flags &= ~(TX_CLRL_REFRESH | TX_CLRL_ERROR);
-			}
+			MPASS(tc->flags & CLRL_ASYNC);
+			tc->flags &= ~CLRL_ASYNC;
+			if (rc == 0)
+				tc->flags &= ~CLRL_ERR;
+			else
+				tc->flags |= CLRL_ERR;
 		}
 	}
 	mtx_unlock(&sc->tc_lock);
@@ -278,74 +289,135 @@ t4_set_sched_class(struct adapter *sc, struct t4_sched
 	return (EINVAL);
 }
 
-int
-t4_set_sched_queue(struct adapter *sc, struct t4_sched_queue *p)
+static int
+bind_txq_to_traffic_class(struct adapter *sc, struct sge_txq *txq, int idx)
 {
-	struct port_info *pi = NULL;
-	struct vi_info *vi;
-	struct sge_txq *txq;
-	uint32_t fw_mnem, fw_queue, fw_class;
-	int i, rc;
+	struct tx_cl_rl_params *tc0, *tc;
+	int rc, old_idx;
+	uint32_t fw_mnem, fw_class;
 
-	rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4setsq");
-	if (rc)
-		return (rc);
+	if (!(txq->eq.flags & EQ_ALLOCATED))
+		return (EAGAIN);
 
-	if (p->port >= sc->params.nports) {
-		rc = EINVAL;
+	mtx_lock(&sc->tc_lock);
+	if (txq->tc_idx == -2) {
+		rc = EBUSY;	/* Another bind/unbind in progress already. */
 		goto done;
 	}
-
-	/* XXX: Only supported for the main VI. */
-	pi = sc->port[p->port];
-	vi = &pi->vi[0];
-	if (!(vi->flags & VI_INIT_DONE)) {
-		/* tx queues not set up yet */
-		rc = EAGAIN;
+	if (idx == txq->tc_idx) {
+		rc = 0;		/* No change, nothing to do. */
 		goto done;
 	}
 
-	if (!in_range(p->queue, 0, vi->ntxq - 1) ||
-	    !in_range(p->cl, 0, sc->chip_params->nsched_cls - 1)) {
-		rc = EINVAL;
-		goto done;
+	tc0 = &sc->port[txq->eq.tx_chan]->sched_params->cl_rl[0];
+	if (idx != -1) {
+		/*
+		 * Bind to a different class at index idx.
+		 */
+		tc = &tc0[idx];
+		if (tc->flags & CLRL_ERR) {
+			rc = ENXIO;
+			goto done;
+		} else {
+			/*
+			 * Ok to proceed.  Place a reference on the new class
+			 * while still holding on to the reference on the
+			 * previous class, if any.
+			 */
+			tc->refcount++;
+		}
 	}
+	/* Mark as busy before letting go of the lock. */
+	old_idx = txq->tc_idx;
+	txq->tc_idx = -2;
+	mtx_unlock(&sc->tc_lock);
 
-	/*
-	 * Create a template for the FW_PARAMS_CMD mnemonic and value (TX
-	 * Scheduling Class in this case).
-	 */
+	rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4btxq");
+	if (rc != 0)
+		return (rc);
 	fw_mnem = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DMAQ) |
-	    V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DMAQ_EQ_SCHEDCLASS_ETH));
-	fw_class = p->cl < 0 ? 0xffffffff : p->cl;
+	    V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DMAQ_EQ_SCHEDCLASS_ETH) |
+	    V_FW_PARAMS_PARAM_YZ(txq->eq.cntxt_id));
+	fw_class = idx < 0 ? 0xffffffff : idx;
+	rc = -t4_set_params(sc, sc->mbox, sc->pf, 0, 1, &fw_mnem, &fw_class);
+	end_synchronized_op(sc, 0);
 
-	/*
-	 * If op.queue is non-negative, then we're only changing the scheduling
-	 * on a single specified TX queue.
-	 */
-	if (p->queue >= 0) {
-		txq = &sc->sge.txq[vi->first_txq + p->queue];
-		fw_queue = (fw_mnem | V_FW_PARAMS_PARAM_YZ(txq->eq.cntxt_id));
-		rc = -t4_set_params(sc, sc->mbox, sc->pf, 0, 1, &fw_queue,
-		    &fw_class);
-		goto done;
+	mtx_lock(&sc->tc_lock);
+	MPASS(txq->tc_idx == -2);
+	if (rc == 0) {
+		/*
+		 * Unbind, bind, or bind to a different class succeeded.  Remove
+		 * the reference on the old traffic class, if any.
+		 */
+		if (old_idx != -1) {
+			tc = &tc0[old_idx];
+			MPASS(tc->refcount > 0);
+			tc->refcount--;
+		}
+		txq->tc_idx = idx;
+	} else {
+		/*
+		 * Unbind, bind, or bind to a different class failed.  Remove
+		 * the anticipatory reference on the new traffic class, if any.
+		 */
+		if (idx != -1) {
+			tc = &tc0[idx];
+			MPASS(tc->refcount > 0);
+			tc->refcount--;
+		}
+		txq->tc_idx = old_idx;
 	}
+done:
+	MPASS(txq->tc_idx >= -1 && txq->tc_idx < sc->chip_params->nsched_cls);
+	mtx_unlock(&sc->tc_lock);
+	return (rc);
+}
 
+int
+t4_set_sched_queue(struct adapter *sc, struct t4_sched_queue *p)
+{
+	struct port_info *pi = NULL;
+	struct vi_info *vi;
+	struct sge_txq *txq;
+	int i, rc;
+
+	if (p->port >= sc->params.nports)
+		return (EINVAL);
+
 	/*
-	 * Change the scheduling on all the TX queues for the
-	 * interface.
+	 * XXX: cxgbetool allows the user to specify the physical port only.  So
+	 * we always operate on the main VI.
 	 */
-	for_each_txq(vi, i, txq) {
-		fw_queue = (fw_mnem | V_FW_PARAMS_PARAM_YZ(txq->eq.cntxt_id));
-		rc = -t4_set_params(sc, sc->mbox, sc->pf, 0, 1, &fw_queue,
-		    &fw_class);
-		if (rc)
-			goto done;
+	pi = sc->port[p->port];
+	vi = &pi->vi[0];
+
+	/* Checking VI_INIT_DONE outside a synch-op is a harmless race here. */
+	if (!(vi->flags & VI_INIT_DONE))
+		return (EAGAIN);
+
+	if (!in_range(p->queue, 0, vi->ntxq - 1) ||
+	    !in_range(p->cl, 0, sc->chip_params->nsched_cls - 1))
+		return (EINVAL);
+
+	if (p->queue < 0) {
+		/*
+		 * Change the scheduling on all the TX queues for the
+		 * interface.
+		 */
+		for_each_txq(vi, i, txq) {
+			rc = bind_txq_to_traffic_class(sc, txq, p->cl);
+			if (rc != 0)
+				break;
+		}
+	} else {
+		/*
+		 * If op.queue is non-negative, then we're only changing the
+		 * scheduling on a single specified TX queue.
+		 */
+		txq = &sc->sge.txq[vi->first_txq + p->queue];
+		rc = bind_txq_to_traffic_class(sc, txq, p->cl);
 	}
 
-	rc = 0;
-done:
-	end_synchronized_op(sc, 0);
 	return (rc);
 }
 
@@ -372,10 +444,8 @@ t4_init_tx_sched(struct adapter *sc)
 			tc->maxrate = 1000 * 1000;	/* 1 Gbps.  Arbitrary */
 
 			if (t4_sched_params_cl_rl_kbps(sc, pi->tx_chan, j,
-			    tc->mode, tc->maxrate, tc->pktsize, 1) == 0)
-				tc->flags = 0;
-			else
-				tc->flags = TX_CLRL_ERROR;
+			    tc->mode, tc->maxrate, tc->pktsize, 1) != 0)
+				tc->flags = CLRL_ERR;
 		}
 	}
 
@@ -412,49 +482,61 @@ t4_reserve_cl_rl_kbps(struct adapter *sc, int port_id,
     int *tc_idx)
 {
 	int rc = 0, fa = -1, i;
+	bool update;
 	struct tx_cl_rl_params *tc;
+	struct port_info *pi;
 
 	MPASS(port_id >= 0 && port_id < sc->params.nports);
 
-	tc = &sc->port[port_id]->sched_params->cl_rl[0];
+	pi = sc->port[port_id];
+	tc = &pi->sched_params->cl_rl[0];
+	update = false;
 	mtx_lock(&sc->tc_lock);
 	for (i = 0; i < sc->chip_params->nsched_cls; i++, tc++) {
-		if (fa < 0 && tc->refcount == 0)
-			fa = i;
+		if (fa < 0 && tc->refcount == 0 && !(tc->flags & CLRL_USER))
+			fa = i;		/* first available */
 
 		if (tc->ratemode == FW_SCHED_PARAMS_RATE_ABS &&
 		    tc->rateunit == FW_SCHED_PARAMS_UNIT_BITRATE &&
 		    tc->mode == FW_SCHED_PARAMS_MODE_FLOW &&
-		    tc->maxrate == maxrate) {
+		    tc->maxrate == maxrate &&
+		    tc->pktsize == pi->vi[0].ifp->if_mtu) {
 			tc->refcount++;
 			*tc_idx = i;
+			if ((tc->flags & (CLRL_ERR | CLRL_ASYNC | CLRL_SYNC)) ==
+			    CLRL_ERR) {
+				update = true;
+			}
 			goto done;
 		}
 	}
 	/* Not found */
 	MPASS(i == sc->chip_params->nsched_cls);
 	if (fa != -1) {
-		tc = &sc->port[port_id]->sched_params->cl_rl[fa];
-		tc->flags = TX_CLRL_REFRESH;
+		tc = &pi->sched_params->cl_rl[fa];
 		tc->refcount = 1;
 		tc->ratemode = FW_SCHED_PARAMS_RATE_ABS;
 		tc->rateunit = FW_SCHED_PARAMS_UNIT_BITRATE;
 		tc->mode = FW_SCHED_PARAMS_MODE_FLOW;
 		tc->maxrate = maxrate;
-		tc->pktsize = ETHERMTU;	/* XXX */
+		tc->pktsize = pi->vi[0].ifp->if_mtu;
 		*tc_idx = fa;
-		t4_update_tx_sched(sc);
+		update = true;
 	} else {
 		*tc_idx = -1;
 		rc = ENOSPC;
 	}
 done:
 	mtx_unlock(&sc->tc_lock);
+	if (update) {
+		tc->flags |= CLRL_ASYNC;
+		t4_update_tx_sched(sc);
+	}
 	return (rc);
 }
 
 void
-t4_release_cl_rl_kbps(struct adapter *sc, int port_id, int tc_idx)
+t4_release_cl_rl(struct adapter *sc, int port_id, int tc_idx)
 {
 	struct tx_cl_rl_params *tc;
 
@@ -464,13 +546,114 @@ t4_release_cl_rl_kbps(struct adapter *sc, int port_id,
 	mtx_lock(&sc->tc_lock);
 	tc = &sc->port[port_id]->sched_params->cl_rl[tc_idx];
 	MPASS(tc->refcount > 0);
-	MPASS(tc->ratemode == FW_SCHED_PARAMS_RATE_ABS);
-	MPASS(tc->rateunit == FW_SCHED_PARAMS_UNIT_BITRATE);
-	MPASS(tc->mode == FW_SCHED_PARAMS_MODE_FLOW);
 	tc->refcount--;
 	mtx_unlock(&sc->tc_lock);
 }
 
+int
+sysctl_tc(SYSCTL_HANDLER_ARGS)
+{
+	struct vi_info *vi = arg1;
+	struct port_info *pi;
+	struct adapter *sc;
+	struct sge_txq *txq;
+	int qidx = arg2, rc, tc_idx;
+
+	MPASS(qidx >= 0 && qidx < vi->ntxq);
+	pi = vi->pi;
+	sc = pi->adapter;
+	txq = &sc->sge.txq[vi->first_txq + qidx];
+
+	tc_idx = txq->tc_idx;
+	rc = sysctl_handle_int(oidp, &tc_idx, 0, req);
+	if (rc != 0 || req->newptr == NULL)
+		return (rc);
+
+	if (sc->flags & IS_VF)
+		return (EPERM);
+	if (!in_range(tc_idx, 0, sc->chip_params->nsched_cls - 1))
+		return (EINVAL);
+
+	return (bind_txq_to_traffic_class(sc, txq, tc_idx));
+}
+
+int
+sysctl_tc_params(SYSCTL_HANDLER_ARGS)
+{
+	struct adapter *sc = arg1;
+	struct tx_cl_rl_params tc;
+	struct sbuf *sb;
+	int i, rc, port_id, mbps, gbps;
+
+	rc = sysctl_wire_old_buffer(req, 0);
+	if (rc != 0)
+		return (rc);
+
+	sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req);
+	if (sb == NULL)
+		return (ENOMEM);
+
+	port_id = arg2 >> 16;
+	MPASS(port_id < sc->params.nports);
+	MPASS(sc->port[port_id] != NULL);
+	i = arg2 & 0xffff;
+	MPASS(i < sc->chip_params->nsched_cls);
+
+	mtx_lock(&sc->tc_lock);
+	tc = sc->port[port_id]->sched_params->cl_rl[i];
+	mtx_unlock(&sc->tc_lock);
+
+	switch (tc.rateunit) {
+	case SCHED_CLASS_RATEUNIT_BITS:
+		switch (tc.ratemode) {
+		case SCHED_CLASS_RATEMODE_REL:
+			/* XXX: top speed or actual link speed? */
+			gbps = port_top_speed(sc->port[port_id]);
+			sbuf_printf(sb, "%u%% of %uGbps", tc.maxrate, gbps);
+			break;
+		case SCHED_CLASS_RATEMODE_ABS:
+			mbps = tc.maxrate / 1000;
+			gbps = tc.maxrate / 1000000;
+			if (tc.maxrate == gbps * 1000000)
+				sbuf_printf(sb, "%uGbps", gbps);
+			else if (tc.maxrate == mbps * 1000)
+				sbuf_printf(sb, "%uMbps", mbps);
+			else
+				sbuf_printf(sb, "%uKbps", tc.maxrate);
+			break;
+		default:
+			rc = ENXIO;
+			goto done;
+		}
+		break;
+	case SCHED_CLASS_RATEUNIT_PKTS:
+		sbuf_printf(sb, "%upps", tc.maxrate);
+		break;
+	default:
+		rc = ENXIO;
+		goto done;
+	}
+
+	switch (tc.mode) {
+	case SCHED_CLASS_MODE_CLASS:
+		sbuf_printf(sb, " aggregate");
+		break;
+	case SCHED_CLASS_MODE_FLOW:
+		sbuf_printf(sb, " per-flow");
+		break;
+	default:
+		rc = ENXIO;
+		goto done;
+	}
+
+done:
+	if (rc == 0)
+		rc = sbuf_finish(sb);
+	sbuf_delete(sb);
+
+	return (rc);
+}
+
 #ifdef RATELIMIT
 void
 t4_init_etid_table(struct adapter *sc)
@@ -578,7 +761,7 @@ cxgbe_snd_tag_alloc(struct ifnet *ifp, union if_snd_ta
 	cst = malloc(sizeof(*cst), M_CXGBE, M_ZERO | M_NOWAIT);
 	if (cst == NULL) {
 failed:
-		t4_release_cl_rl_kbps(sc, pi->port_id, schedcl);
+		t4_release_cl_rl(sc, pi->port_id, schedcl);
 		return (ENOMEM);
 	}
 
@@ -634,7 +817,7 @@ cxgbe_snd_tag_modify(struct m_snd_tag *mst,
 	if (rc != 0)
 		return (rc);
 	MPASS(schedcl >= 0 && schedcl < sc->chip_params->nsched_cls);
-	t4_release_cl_rl_kbps(sc, cst->port_id, cst->schedcl);
+	t4_release_cl_rl(sc, cst->port_id, cst->schedcl);
 	cst->schedcl = schedcl;
 	cst->max_rate = params->rate_limit.max_rate;
 	mtx_unlock(&cst->lock);
@@ -675,7 +858,7 @@ cxgbe_snd_tag_free_locked(struct cxgbe_snd_tag *cst)
 	if (cst->etid >= 0)
 		free_etid(sc, cst->etid);
 	if (cst->schedcl != -1)
-		t4_release_cl_rl_kbps(sc, cst->port_id, cst->schedcl);
+		t4_release_cl_rl(sc, cst->port_id, cst->schedcl);
 	mtx_unlock(&cst->lock);
 	mtx_destroy(&cst->lock);
 	free(cst, M_CXGBE);

Modified: head/sys/dev/cxgbe/t4_sge.c
==============================================================================
--- head/sys/dev/cxgbe/t4_sge.c	Mon Aug  6 21:54:51 2018	(r337397)
+++ head/sys/dev/cxgbe/t4_sge.c	Mon Aug  6 23:21:13 2018	(r337398)
@@ -296,7 +296,6 @@ static void drain_wrq_wr_list(struct adapter *, struct
 
 static int sysctl_uint16(SYSCTL_HANDLER_ARGS);
 static int sysctl_bufsizes(SYSCTL_HANDLER_ARGS);
-static int sysctl_tc(SYSCTL_HANDLER_ARGS);
 #ifdef RATELIMIT
 static inline u_int txpkt_eo_len16(u_int, u_int, u_int);
 static int ethofld_fw4_ack(struct sge_iq *, const struct rss_header *,
@@ -5365,91 +5364,6 @@ sysctl_bufsizes(SYSCTL_HANDLER_ARGS)
 	sbuf_finish(&sb);
 	rc = sysctl_handle_string(oidp, sbuf_data(&sb), sbuf_len(&sb), req);
 	sbuf_delete(&sb);
-	return (rc);
-}
-
-static int
-sysctl_tc(SYSCTL_HANDLER_ARGS)
-{
-	struct vi_info *vi = arg1;
-	struct port_info *pi;
-	struct adapter *sc;
-	struct sge_txq *txq;
-	struct tx_cl_rl_params *tc;
-	int qidx = arg2, rc, tc_idx;
-	uint32_t fw_queue, fw_class;
-
-	MPASS(qidx >= 0 && qidx < vi->ntxq);
-	pi = vi->pi;
-	sc = pi->adapter;
-	txq = &sc->sge.txq[vi->first_txq + qidx];
-
-	tc_idx = txq->tc_idx;
-	rc = sysctl_handle_int(oidp, &tc_idx, 0, req);
-	if (rc != 0 || req->newptr == NULL)
-		return (rc);
-
-	if (sc->flags & IS_VF)
-		return (EPERM);
-
-	/* Note that -1 is legitimate input (it means unbind). */
-	if (tc_idx < -1 || tc_idx >= sc->chip_params->nsched_cls)
-		return (EINVAL);
-
-	mtx_lock(&sc->tc_lock);
-	if (tc_idx == txq->tc_idx) {
-		rc = 0;		/* No change, nothing to do. */
-		goto done;
-	}
-
-	fw_queue = V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DMAQ) |
-	    V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DMAQ_EQ_SCHEDCLASS_ETH) |
-	    V_FW_PARAMS_PARAM_YZ(txq->eq.cntxt_id);
-
-	if (tc_idx == -1)
-		fw_class = 0xffffffff;	/* Unbind. */
-	else {
-		/*
-		 * Bind to a different class.
-		 */
-		tc = &pi->sched_params->cl_rl[tc_idx];
-		if (tc->flags & TX_CLRL_ERROR) {
-			/* Previous attempt to set the cl-rl params failed. */
-			rc = EIO;
-			goto done;
-		} else {
-			/*
-			 * Ok to proceed.  Place a reference on the new class
-			 * while still holding on to the reference on the
-			 * previous class, if any.
-			 */
-			fw_class = tc_idx;
-			tc->refcount++;
-		}
-	}
-	mtx_unlock(&sc->tc_lock);
-
-	rc = begin_synchronized_op(sc, vi, SLEEP_OK | INTR_OK, "t4stc");
-	if (rc)
-		return (rc);
-	rc = -t4_set_params(sc, sc->mbox, sc->pf, 0, 1, &fw_queue, &fw_class);
-	end_synchronized_op(sc, 0);
-
-	mtx_lock(&sc->tc_lock);
-	if (rc == 0) {
-		if (txq->tc_idx != -1) {
-			tc = &pi->sched_params->cl_rl[txq->tc_idx];
-			MPASS(tc->refcount > 0);
-			tc->refcount--;
-		}
-		txq->tc_idx = tc_idx;
-	} else if (tc_idx != -1) {
-		tc = &pi->sched_params->cl_rl[tc_idx];
-		MPASS(tc->refcount > 0);
-		tc->refcount--;
-	}
-done:
-	mtx_unlock(&sc->tc_lock);
 	return (rc);
 }
 

Modified: head/sys/dev/cxgbe/tom/t4_cpl_io.c
==============================================================================
--- head/sys/dev/cxgbe/tom/t4_cpl_io.c	Mon Aug  6 21:54:51 2018	(r337397)
+++ head/sys/dev/cxgbe/tom/t4_cpl_io.c	Mon Aug  6 23:21:13 2018	(r337398)
@@ -231,7 +231,7 @@ update_tx_rate_limit(struct adapter *sc, struct toepcb
 		if (toep->tx_credits < flowclen16 || toep->txsd_avail == 0 ||
 		    (wr = alloc_wrqe(roundup2(flowclen, 16), toep->ofld_txq)) == NULL) {
 			if (tc_idx >= 0)
-				t4_release_cl_rl_kbps(sc, port_id, tc_idx);
+				t4_release_cl_rl(sc, port_id, tc_idx);
 			return (ENOMEM);
 		}
 
@@ -259,7 +259,7 @@ update_tx_rate_limit(struct adapter *sc, struct toepcb
 	}
 
 	if (toep->tc_idx >= 0)
-		t4_release_cl_rl_kbps(sc, port_id, toep->tc_idx);
+		t4_release_cl_rl(sc, port_id, toep->tc_idx);
 	toep->tc_idx = tc_idx;
 
 	return (0);

Modified: head/sys/dev/cxgbe/tom/t4_tom.c
==============================================================================
--- head/sys/dev/cxgbe/tom/t4_tom.c	Mon Aug  6 21:54:51 2018	(r337397)
+++ head/sys/dev/cxgbe/tom/t4_tom.c	Mon Aug  6 23:21:13 2018	(r337398)
@@ -317,10 +317,9 @@ release_offload_resources(struct toepcb *toep)
 	if (toep->ce)
 		release_lip(td, toep->ce);
 
-#ifdef RATELIMIT
 	if (toep->tc_idx != -1)
-		t4_release_cl_rl_kbps(sc, toep->vi->pi->port_id, toep->tc_idx);
-#endif
+		t4_release_cl_rl(sc, toep->vi->pi->port_id, toep->tc_idx);
+
 	mtx_lock(&td->toep_list_lock);
 	TAILQ_REMOVE(&td->toep_list, toep, link);
 	mtx_unlock(&td->toep_list_lock);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201808062321.w76NLDO6092038>