svn commit: r308321 - in stable/10: sys/dev/cxgbe tools/tools/cxgbetool
John Baldwin
jhb at FreeBSD.org
Fri Nov 4 21:59:28 UTC 2016
Author: jhb
Date: Fri Nov 4 21:59:27 2016
New Revision: 308321
URL: https://svnweb.freebsd.org/changeset/base/308321
Log:
MFC 301516,301520,301531,301535,301540,301542,301628: Traffic scheduling
updates.
301516:
cxgbetool: Allow max-rate > 10Gbps for rate-limited traffic.
301520:
cxgbe(4): Create a reusable struct type for scheduling class parameters.
301531:
cxgbe(4): Break up set_sched_class. Validate the channel number and
min/max rates against their actual limits (which are chip and port
specific) instead of hardcoded constants.
301535:
cxgbe(4): Track the state of the hardware traffic schedulers in the
driver. This works as long as everyone uses set_sched_class_params
to program them.
301540:
cxgbe(4): Provide information about traffic classes in the sysctl mib.
301542:
cxgbe(4): A couple of fixes to set_sched_queue.
- Validate the scheduling class against the actual limit (which is chip
specific) instead of a magic number.
- Return an error if an attempt is made to manipulate the tx queues of a
VI that hasn't been initialized.
301628:
cxgbe(4): Add a sysctl to manage the binding of a txq to a traffic class.
Sponsored by: Chelsio Communications
Modified:
stable/10/sys/dev/cxgbe/adapter.h
stable/10/sys/dev/cxgbe/t4_ioctl.h
stable/10/sys/dev/cxgbe/t4_main.c
stable/10/sys/dev/cxgbe/t4_sge.c
stable/10/tools/tools/cxgbetool/cxgbetool.c
Directory Properties:
stable/10/ (props changed)
Modified: stable/10/sys/dev/cxgbe/adapter.h
==============================================================================
--- stable/10/sys/dev/cxgbe/adapter.h Fri Nov 4 21:52:48 2016 (r308320)
+++ stable/10/sys/dev/cxgbe/adapter.h Fri Nov 4 21:59:27 2016 (r308321)
@@ -48,6 +48,7 @@
#include <netinet/tcp_lro.h>
#include "offload.h"
+#include "t4_ioctl.h"
#include "common/t4_msg.h"
#include "firmware/t4fw_interface.h"
@@ -261,6 +262,17 @@ struct vi_info {
uint8_t hw_addr[ETHER_ADDR_LEN]; /* factory MAC address, won't change */
};
+enum {
+ /* tx_sched_class flags */
+ TX_SC_OK = (1 << 0), /* Set up in hardware, active. */
+};
+
+struct tx_sched_class {
+ int refcount;
+ int flags;
+ struct t4_sched_class_params params;
+};
+
struct port_info {
device_t dev;
struct adapter *adapter;
@@ -270,6 +282,8 @@ struct port_info {
int up_vis;
int uld_vis;
+ struct tx_sched_class *tc; /* traffic classes for this channel */
+
struct mtx pi_lock;
char lockname[16];
unsigned long flags;
@@ -523,6 +537,7 @@ struct sge_txq {
struct tx_sdesc *sdesc; /* KVA of software descriptor ring */
struct sglist *gl;
__be32 cpl_ctrl0; /* for convenience */
+ int tc_idx; /* traffic class */
struct task tx_reclaim_task;
/* stats for common events first */
Modified: stable/10/sys/dev/cxgbe/t4_ioctl.h
==============================================================================
--- stable/10/sys/dev/cxgbe/t4_ioctl.h Fri Nov 4 21:52:48 2016 (r308320)
+++ stable/10/sys/dev/cxgbe/t4_ioctl.h Fri Nov 4 21:59:27 2016 (r308321)
@@ -215,6 +215,20 @@ struct t4_filter {
struct t4_filter_specification fs;
};
+/* Tx Scheduling Class parameters */
+struct t4_sched_class_params {
+ int8_t level; /* scheduler hierarchy level */
+ int8_t mode; /* per-class or per-flow */
+ int8_t rateunit; /* bit or packet rate */
+ int8_t ratemode; /* %port relative or kbps absolute */
+ int8_t channel; /* scheduler channel [0..N] */
+ int8_t cl; /* scheduler class [0..N] */
+ int32_t minrate; /* minimum rate */
+ int32_t maxrate; /* maximum rate */
+ int16_t weight; /* percent weight */
+ int16_t pktsize; /* average packet size */
+};
+
/*
* Support for "sched-class" command to allow a TX Scheduling Class to be
* programmed with various parameters.
@@ -226,19 +240,7 @@ struct t4_sched_params {
struct { /* sub-command SCHED_CLASS_CONFIG */
int8_t minmax; /* minmax enable */
} config;
- struct { /* sub-command SCHED_CLASS_PARAMS */
- int8_t level; /* scheduler hierarchy level */
- int8_t mode; /* per-class or per-flow */
- int8_t rateunit; /* bit or packet rate */
- int8_t ratemode; /* %port relative or kbps
- absolute */
- int8_t channel; /* scheduler channel [0..N] */
- int8_t cl; /* scheduler class [0..N] */
- int32_t minrate; /* minimum rate */
- int32_t maxrate; /* maximum rate */
- int16_t weight; /* percent weight */
- int16_t pktsize; /* average packet size */
- } params;
+ struct t4_sched_class_params params;
uint8_t reserved[6 + 8 * 8];
} u;
};
Modified: stable/10/sys/dev/cxgbe/t4_main.c
==============================================================================
--- stable/10/sys/dev/cxgbe/t4_main.c Fri Nov 4 21:52:48 2016 (r308320)
+++ stable/10/sys/dev/cxgbe/t4_main.c Fri Nov 4 21:59:27 2016 (r308321)
@@ -505,6 +505,7 @@ static int sysctl_tp_la(SYSCTL_HANDLER_A
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);
#endif
#ifdef TCP_OFFLOAD
static int sysctl_tp_tick(SYSCTL_HANDLER_ARGS);
@@ -883,6 +884,9 @@ t4_attach(device_t dev)
mtx_init(&pi->pi_lock, pi->lockname, 0, MTX_DEF);
sc->chan_map[pi->tx_chan] = i;
+ pi->tc = malloc(sizeof(struct tx_sched_class) *
+ sc->chip_params->nsched_cls, M_CXGBE, M_ZERO | M_WAITOK);
+
if (is_10G_port(pi) || is_40G_port(pi)) {
n10g++;
} else {
@@ -1130,6 +1134,7 @@ t4_detach(device_t dev)
mtx_destroy(&pi->pi_lock);
free(pi->vi, M_CXGBE);
+ free(pi->tc, M_CXGBE);
free(pi, M_CXGBE);
}
}
@@ -4964,8 +4969,10 @@ cxgbe_sysctls(struct port_info *pi)
{
struct sysctl_ctx_list *ctx;
struct sysctl_oid *oid;
- struct sysctl_oid_list *children;
+ struct sysctl_oid_list *children, *children2;
struct adapter *sc = pi->adapter;
+ int i;
+ char name[16];
ctx = device_get_sysctl_ctx(pi->dev);
@@ -4994,6 +5001,29 @@ cxgbe_sysctls(struct port_info *pi)
port_top_speed(pi), "max speed (in Gbps)");
/*
+ * dev.(cxgbe|cxl).X.tc.
+ */
+ oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "tc", CTLFLAG_RD, NULL,
+ "Tx scheduler traffic classes");
+ for (i = 0; i < sc->chip_params->nsched_cls; i++) {
+ struct tx_sched_class *tc = &pi->tc[i];
+
+ snprintf(name, sizeof(name), "%d", i);
+ 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_UINT(ctx, children2, OID_AUTO, "refcount",
+ CTLFLAG_RD, &tc->refcount, 0, "references to this class");
+#ifdef SBUF_DRAIN
+ SYSCTL_ADD_PROC(ctx, children2, OID_AUTO, "params",
+ CTLTYPE_STRING | CTLFLAG_RD, sc, (pi->port_id << 16) | i,
+ sysctl_tc_params, "A", "traffic class parameters");
+#endif
+ }
+
+ /*
* dev.cxgbe.X.stats.
*/
oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats", CTLFLAG_RD,
@@ -7387,6 +7417,101 @@ sysctl_wcwr_stats(SYSCTL_HANDLER_ARGS)
return (rc);
}
+
+static int
+sysctl_tc_params(SYSCTL_HANDLER_ARGS)
+{
+ struct adapter *sc = arg1;
+ struct tx_sched_class *tc;
+ struct t4_sched_class_params p;
+ struct sbuf *sb;
+ int i, rc, port_id, flags, 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);
+ tc = &sc->port[port_id]->tc[i];
+
+ rc = begin_synchronized_op(sc, NULL, HOLD_LOCK | SLEEP_OK | INTR_OK,
+ "t4tc_p");
+ if (rc)
+ goto done;
+ flags = tc->flags;
+ p = tc->params;
+ end_synchronized_op(sc, LOCK_HELD);
+
+ if ((flags & TX_SC_OK) == 0) {
+ sbuf_printf(sb, "none");
+ goto done;
+ }
+
+ if (p.level == SCHED_CLASS_LEVEL_CL_WRR) {
+ sbuf_printf(sb, "cl-wrr weight %u", p.weight);
+ goto done;
+ } else if (p.level == SCHED_CLASS_LEVEL_CL_RL)
+ sbuf_printf(sb, "cl-rl");
+ else if (p.level == SCHED_CLASS_LEVEL_CH_RL)
+ sbuf_printf(sb, "ch-rl");
+ else {
+ rc = ENXIO;
+ goto done;
+ }
+
+ if (p.ratemode == 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", p.maxrate, gbps);
+ }
+ else if (p.ratemode == SCHED_CLASS_RATEMODE_ABS) {
+ switch (p.rateunit) {
+ case SCHED_CLASS_RATEUNIT_BITS:
+ mbps = p.maxrate / 1000;
+ gbps = p.maxrate / 1000000;
+ if (p.maxrate == gbps * 1000000)
+ sbuf_printf(sb, " %uGbps", gbps);
+ else if (p.maxrate == mbps * 1000)
+ sbuf_printf(sb, " %uMbps", mbps);
+ else
+ sbuf_printf(sb, " %uKbps", p.maxrate);
+ break;
+ case SCHED_CLASS_RATEUNIT_PKTS:
+ sbuf_printf(sb, " %upps", p.maxrate);
+ break;
+ default:
+ rc = ENXIO;
+ goto done;
+ }
+ }
+
+ switch (p.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);
+}
#endif
#ifdef TCP_OFFLOAD
@@ -8232,155 +8357,147 @@ in_range(int val, int lo, int hi)
}
static int
-set_sched_class(struct adapter *sc, struct t4_sched_params *p)
+set_sched_class_config(struct adapter *sc, int minmax)
{
- int fw_subcmd, fw_type, rc;
+ int rc;
+
+ if (minmax < 0)
+ return (EINVAL);
- rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4setsc");
+ rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4sscc");
if (rc)
return (rc);
+ rc = -t4_sched_config(sc, FW_SCHED_TYPE_PKTSCHED, minmax, 1);
+ end_synchronized_op(sc, 0);
- if (!(sc->flags & FULL_INIT_DONE)) {
- rc = EAGAIN;
- goto done;
- }
+ return (rc);
+}
- /*
- * Translate the cxgbetool parameters into T4 firmware parameters. (The
- * sub-command and type are in common locations.)
- */
- if (p->subcmd == SCHED_CLASS_SUBCMD_CONFIG)
- fw_subcmd = FW_SCHED_SC_CONFIG;
- else if (p->subcmd == SCHED_CLASS_SUBCMD_PARAMS)
- fw_subcmd = FW_SCHED_SC_PARAMS;
- else {
- rc = EINVAL;
- goto done;
- }
- if (p->type == SCHED_CLASS_TYPE_PACKET)
- fw_type = FW_SCHED_TYPE_PKTSCHED;
- else {
- rc = EINVAL;
- goto done;
- }
+static int
+set_sched_class_params(struct adapter *sc, struct t4_sched_class_params *p,
+ int sleep_ok)
+{
+ int rc, top_speed, fw_level, fw_mode, fw_rateunit, fw_ratemode;
+ struct port_info *pi;
+ struct tx_sched_class *tc;
- if (fw_subcmd == FW_SCHED_SC_CONFIG) {
- /* Vet our parameters ..*/
- if (p->u.config.minmax < 0) {
- rc = EINVAL;
- goto done;
- }
+ if (p->level == SCHED_CLASS_LEVEL_CL_RL)
+ fw_level = FW_SCHED_PARAMS_LEVEL_CL_RL;
+ else if (p->level == SCHED_CLASS_LEVEL_CL_WRR)
+ fw_level = FW_SCHED_PARAMS_LEVEL_CL_WRR;
+ else if (p->level == SCHED_CLASS_LEVEL_CH_RL)
+ fw_level = FW_SCHED_PARAMS_LEVEL_CH_RL;
+ else
+ return (EINVAL);
- /* And pass the request to the firmware ...*/
- rc = -t4_sched_config(sc, fw_type, p->u.config.minmax, 1);
- goto done;
- }
+ if (p->mode == SCHED_CLASS_MODE_CLASS)
+ fw_mode = FW_SCHED_PARAMS_MODE_CLASS;
+ else if (p->mode == SCHED_CLASS_MODE_FLOW)
+ fw_mode = FW_SCHED_PARAMS_MODE_FLOW;
+ else
+ return (EINVAL);
- if (fw_subcmd == FW_SCHED_SC_PARAMS) {
- int fw_level;
- int fw_mode;
- int fw_rateunit;
- int fw_ratemode;
-
- if (p->u.params.level == SCHED_CLASS_LEVEL_CL_RL)
- fw_level = FW_SCHED_PARAMS_LEVEL_CL_RL;
- else if (p->u.params.level == SCHED_CLASS_LEVEL_CL_WRR)
- fw_level = FW_SCHED_PARAMS_LEVEL_CL_WRR;
- else if (p->u.params.level == SCHED_CLASS_LEVEL_CH_RL)
- fw_level = FW_SCHED_PARAMS_LEVEL_CH_RL;
- else {
- rc = EINVAL;
- goto done;
- }
+ if (p->rateunit == SCHED_CLASS_RATEUNIT_BITS)
+ fw_rateunit = FW_SCHED_PARAMS_UNIT_BITRATE;
+ else if (p->rateunit == SCHED_CLASS_RATEUNIT_PKTS)
+ fw_rateunit = FW_SCHED_PARAMS_UNIT_PKTRATE;
+ else
+ return (EINVAL);
- if (p->u.params.mode == SCHED_CLASS_MODE_CLASS)
- fw_mode = FW_SCHED_PARAMS_MODE_CLASS;
- else if (p->u.params.mode == SCHED_CLASS_MODE_FLOW)
- fw_mode = FW_SCHED_PARAMS_MODE_FLOW;
- else {
- rc = EINVAL;
- goto done;
- }
+ if (p->ratemode == SCHED_CLASS_RATEMODE_REL)
+ fw_ratemode = FW_SCHED_PARAMS_RATE_REL;
+ else if (p->ratemode == SCHED_CLASS_RATEMODE_ABS)
+ fw_ratemode = FW_SCHED_PARAMS_RATE_ABS;
+ else
+ return (EINVAL);
- if (p->u.params.rateunit == SCHED_CLASS_RATEUNIT_BITS)
- fw_rateunit = FW_SCHED_PARAMS_UNIT_BITRATE;
- else if (p->u.params.rateunit == SCHED_CLASS_RATEUNIT_PKTS)
- fw_rateunit = FW_SCHED_PARAMS_UNIT_PKTRATE;
- else {
- rc = EINVAL;
- goto done;
- }
+ /* Vet our parameters ... */
+ if (!in_range(p->channel, 0, sc->chip_params->nchan - 1))
+ return (ERANGE);
- if (p->u.params.ratemode == SCHED_CLASS_RATEMODE_REL)
- fw_ratemode = FW_SCHED_PARAMS_RATE_REL;
- else if (p->u.params.ratemode == SCHED_CLASS_RATEMODE_ABS)
- fw_ratemode = FW_SCHED_PARAMS_RATE_ABS;
- else {
- rc = EINVAL;
- goto done;
- }
+ pi = sc->port[sc->chan_map[p->channel]];
+ if (pi == NULL)
+ return (ENXIO);
+ MPASS(pi->tx_chan == p->channel);
+ top_speed = port_top_speed(pi) * 1000000; /* Gbps -> Kbps */
- /* Vet our parameters ... */
- if (!in_range(p->u.params.channel, 0, 3) ||
- !in_range(p->u.params.cl, 0, sc->chip_params->nsched_cls) ||
- !in_range(p->u.params.minrate, 0, 10000000) ||
- !in_range(p->u.params.maxrate, 0, 10000000) ||
- !in_range(p->u.params.weight, 0, 100)) {
- rc = ERANGE;
- goto done;
- }
+ if (!in_range(p->cl, 0, sc->chip_params->nsched_cls) ||
+ !in_range(p->minrate, 0, top_speed) ||
+ !in_range(p->maxrate, 0, top_speed) ||
+ !in_range(p->weight, 0, 100))
+ return (ERANGE);
+
+ /*
+ * Translate any unset parameters into the firmware's
+ * nomenclature and/or fail the call if the parameters
+ * are required ...
+ */
+ if (p->rateunit < 0 || p->ratemode < 0 || p->channel < 0 || p->cl < 0)
+ return (EINVAL);
+
+ if (p->minrate < 0)
+ p->minrate = 0;
+ if (p->maxrate < 0) {
+ if (p->level == SCHED_CLASS_LEVEL_CL_RL ||
+ p->level == SCHED_CLASS_LEVEL_CH_RL)
+ return (EINVAL);
+ else
+ p->maxrate = 0;
+ }
+ if (p->weight < 0) {
+ if (p->level == SCHED_CLASS_LEVEL_CL_WRR)
+ return (EINVAL);
+ else
+ p->weight = 0;
+ }
+ if (p->pktsize < 0) {
+ if (p->level == SCHED_CLASS_LEVEL_CL_RL ||
+ p->level == SCHED_CLASS_LEVEL_CH_RL)
+ return (EINVAL);
+ else
+ p->pktsize = 0;
+ }
+ rc = begin_synchronized_op(sc, NULL,
+ sleep_ok ? (SLEEP_OK | INTR_OK) : HOLD_LOCK, "t4sscp");
+ if (rc)
+ return (rc);
+ tc = &pi->tc[p->cl];
+ tc->params = *p;
+ 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 (rc == 0)
+ tc->flags |= TX_SC_OK;
+ else {
/*
- * Translate any unset parameters into the firmware's
- * nomenclature and/or fail the call if the parameters
- * are required ...
+ * Unknown state at this point, see tc->params for what was
+ * attempted.
*/
- if (p->u.params.rateunit < 0 || p->u.params.ratemode < 0 ||
- p->u.params.channel < 0 || p->u.params.cl < 0) {
- rc = EINVAL;
- goto done;
- }
- if (p->u.params.minrate < 0)
- p->u.params.minrate = 0;
- if (p->u.params.maxrate < 0) {
- if (p->u.params.level == SCHED_CLASS_LEVEL_CL_RL ||
- p->u.params.level == SCHED_CLASS_LEVEL_CH_RL) {
- rc = EINVAL;
- goto done;
- } else
- p->u.params.maxrate = 0;
- }
- if (p->u.params.weight < 0) {
- if (p->u.params.level == SCHED_CLASS_LEVEL_CL_WRR) {
- rc = EINVAL;
- goto done;
- } else
- p->u.params.weight = 0;
- }
- if (p->u.params.pktsize < 0) {
- if (p->u.params.level == SCHED_CLASS_LEVEL_CL_RL ||
- p->u.params.level == SCHED_CLASS_LEVEL_CH_RL) {
- rc = EINVAL;
- goto done;
- } else
- p->u.params.pktsize = 0;
- }
-
- /* See what the firmware thinks of the request ... */
- rc = -t4_sched_params(sc, fw_type, fw_level, fw_mode,
- fw_rateunit, fw_ratemode, p->u.params.channel,
- p->u.params.cl, p->u.params.minrate, p->u.params.maxrate,
- p->u.params.weight, p->u.params.pktsize, 1);
- goto done;
+ tc->flags &= ~TX_SC_OK;
}
+ end_synchronized_op(sc, sleep_ok ? 0 : LOCK_HELD);
- rc = EINVAL;
-done:
- end_synchronized_op(sc, 0);
return (rc);
}
static int
+set_sched_class(struct adapter *sc, struct t4_sched_params *p)
+{
+
+ if (p->type != SCHED_CLASS_TYPE_PACKET)
+ return (EINVAL);
+
+ if (p->subcmd == SCHED_CLASS_SUBCMD_CONFIG)
+ return (set_sched_class_config(sc, p->u.config.minmax));
+
+ if (p->subcmd == SCHED_CLASS_SUBCMD_PARAMS)
+ return (set_sched_class_params(sc, &p->u.params, 1));
+
+ return (EINVAL);
+}
+
+static int
set_sched_queue(struct adapter *sc, struct t4_sched_queue *p)
{
struct port_info *pi = NULL;
@@ -8393,11 +8510,6 @@ set_sched_queue(struct adapter *sc, stru
if (rc)
return (rc);
- if (!(sc->flags & FULL_INIT_DONE)) {
- rc = EAGAIN;
- goto done;
- }
-
if (p->port >= sc->params.nports) {
rc = EINVAL;
goto done;
@@ -8406,7 +8518,14 @@ set_sched_queue(struct adapter *sc, stru
/* XXX: Only supported for the main VI. */
pi = sc->port[p->port];
vi = &pi->vi[0];
- if (!in_range(p->queue, 0, vi->ntxq - 1) || !in_range(p->cl, 0, 7)) {
+ if (!(vi->flags & VI_INIT_DONE)) {
+ /* tx queues not set up yet */
+ rc = EAGAIN;
+ 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;
}
Modified: stable/10/sys/dev/cxgbe/t4_sge.c
==============================================================================
--- stable/10/sys/dev/cxgbe/t4_sge.c Fri Nov 4 21:52:48 2016 (r308320)
+++ stable/10/sys/dev/cxgbe/t4_sge.c Fri Nov 4 21:59:27 2016 (r308321)
@@ -247,6 +247,7 @@ static void drain_wrq_wr_list(struct ada
static int sysctl_uint16(SYSCTL_HANDLER_ARGS);
static int sysctl_bufsizes(SYSCTL_HANDLER_ARGS);
+static int sysctl_tc(SYSCTL_HANDLER_ARGS);
static counter_u64_t extfree_refs;
static counter_u64_t extfree_rels;
@@ -3458,6 +3459,7 @@ alloc_txq(struct vi_info *vi, struct sge
txq->cpl_ctrl0 = htobe32(V_TXPKT_OPCODE(CPL_TX_PKT) |
V_TXPKT_INTF(pi->tx_chan) | V_TXPKT_VF_VLD(1) |
V_TXPKT_VF(vi->viid));
+ txq->tc_idx = -1;
txq->sdesc = malloc(eq->sidx * sizeof(struct tx_sdesc), M_CXGBE,
M_ZERO | M_WAITOK);
@@ -3475,6 +3477,10 @@ alloc_txq(struct vi_info *vi, struct sge
CTLTYPE_INT | CTLFLAG_RD, &eq->pidx, 0, sysctl_uint16, "I",
"producer index");
+ SYSCTL_ADD_PROC(&vi->ctx, children, OID_AUTO, "tc",
+ CTLTYPE_INT | CTLFLAG_RW, vi, idx, sysctl_tc, "I",
+ "traffic class (-1 means none)");
+
SYSCTL_ADD_UQUAD(&vi->ctx, children, OID_AUTO, "txcsum", CTLFLAG_RD,
&txq->txcsum, "# of times hardware assisted with checksum");
SYSCTL_ADD_UQUAD(&vi->ctx, children, OID_AUTO, "vlan_insertion",
@@ -4708,3 +4714,78 @@ sysctl_bufsizes(SYSCTL_HANDLER_ARGS)
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_sched_class *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);
+
+ /* Note that -1 is legitimate input (it means unbind). */
+ if (tc_idx < -1 || tc_idx >= sc->chip_params->nsched_cls)
+ return (EINVAL);
+
+ rc = begin_synchronized_op(sc, vi, SLEEP_OK | INTR_OK, "t4stc");
+ if (rc)
+ return (rc);
+
+ 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. Ethernet txq's are only allowed
+ * to bind to cl-rl mode-class for now. XXX: too restrictive.
+ */
+ tc = &pi->tc[tc_idx];
+ if (tc->flags & TX_SC_OK &&
+ tc->params.level == SCHED_CLASS_LEVEL_CL_RL &&
+ tc->params.mode == SCHED_CLASS_MODE_CLASS) {
+ /* Ok to proceed. */
+ fw_class = tc_idx;
+ } else {
+ rc = tc->flags & TX_SC_OK ? EBUSY : ENXIO;
+ goto done;
+ }
+ }
+
+ rc = -t4_set_params(sc, sc->mbox, sc->pf, 0, 1, &fw_queue, &fw_class);
+ if (rc == 0) {
+ if (txq->tc_idx != -1) {
+ tc = &pi->tc[txq->tc_idx];
+ MPASS(tc->refcount > 0);
+ tc->refcount--;
+ }
+ if (tc_idx != -1) {
+ tc = &pi->tc[tc_idx];
+ tc->refcount++;
+ }
+ txq->tc_idx = tc_idx;
+ }
+done:
+ end_synchronized_op(sc, 0);
+ return (rc);
+}
Modified: stable/10/tools/tools/cxgbetool/cxgbetool.c
==============================================================================
--- stable/10/tools/tools/cxgbetool/cxgbetool.c Fri Nov 4 21:52:48 2016 (r308320)
+++ stable/10/tools/tools/cxgbetool/cxgbetool.c Fri Nov 4 21:59:27 2016 (r308321)
@@ -2526,9 +2526,9 @@ sched_class(int argc, const char *argv[]
errs++;
}
if (op.u.params.ratemode == SCHED_CLASS_RATEMODE_ABS &&
- !in_range(op.u.params.maxrate, 1, 10000000)) {
+ !in_range(op.u.params.maxrate, 1, 100000000)) {
warnx("sched params \"max-rate\" takes "
- "value(1-10000000) for rate-mode absolute");
+ "value(1-100000000) for rate-mode absolute");
errs++;
}
if (op.u.params.maxrate > 0 &&
More information about the svn-src-stable
mailing list