From 418f9df1f1319f20ff23050bb8e4860202c1fcd5 Mon Sep 17 00:00:00 2001 From: jhb Date: Fri, 4 Nov 2016 21:59:27 +0000 Subject: [PATCH] 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 git-svn-id: svn://svn.freebsd.org/base/stable/10@308321 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- sys/dev/cxgbe/adapter.h | 15 ++ sys/dev/cxgbe/t4_ioctl.h | 28 ++- sys/dev/cxgbe/t4_main.c | 385 +++++++++++++++++++----------- sys/dev/cxgbe/t4_sge.c | 81 +++++++ tools/tools/cxgbetool/cxgbetool.c | 4 +- 5 files changed, 365 insertions(+), 148 deletions(-) diff --git a/sys/dev/cxgbe/adapter.h b/sys/dev/cxgbe/adapter.h index bab20ca09..68a7bceeb 100644 --- a/sys/dev/cxgbe/adapter.h +++ b/sys/dev/cxgbe/adapter.h @@ -48,6 +48,7 @@ #include #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 */ diff --git a/sys/dev/cxgbe/t4_ioctl.h b/sys/dev/cxgbe/t4_ioctl.h index 473cf896a..32e7295e2 100644 --- a/sys/dev/cxgbe/t4_ioctl.h +++ b/sys/dev/cxgbe/t4_ioctl.h @@ -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; }; diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c index 90c4dfa62..f47f6907c 100644 --- a/sys/dev/cxgbe/t4_main.c +++ b/sys/dev/cxgbe/t4_main.c @@ -505,6 +505,7 @@ 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); #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); @@ -4993,6 +5000,29 @@ cxgbe_sysctls(struct port_info *pi) SYSCTL_ADD_INT(ctx, children, OID_AUTO, "max_speed", CTLFLAG_RD, NULL, 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. */ @@ -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,154 +8357,146 @@ 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 (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); - if (fw_subcmd == FW_SCHED_SC_CONFIG) { - /* Vet our parameters ..*/ - if (p->u.config.minmax < 0) { - rc = EINVAL; - 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); - /* And pass the request to the firmware ...*/ - rc = -t4_sched_config(sc, fw_type, p->u.config.minmax, 1); - 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 (fw_subcmd == FW_SCHED_SC_PARAMS) { - int fw_level; - int fw_mode; - int fw_rateunit; - int fw_ratemode; + 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.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; - } + /* Vet our parameters ... */ + if (!in_range(p->channel, 0, sc->chip_params->nchan - 1)) + return (ERANGE); - 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; - } + 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 */ - 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; - } + 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); - 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; - } + /* + * 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); - /* 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 (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) { @@ -8393,11 +8510,6 @@ set_sched_queue(struct adapter *sc, struct t4_sched_queue *p) 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, struct t4_sched_queue *p) /* 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; } diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c index 62702a950..260e25d44 100644 --- a/sys/dev/cxgbe/t4_sge.c +++ b/sys/dev/cxgbe/t4_sge.c @@ -247,6 +247,7 @@ static void drain_wrq_wr_list(struct adapter *, struct sge_wrq *); 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 *txq, int idx, 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_txq *txq, int idx, 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); +} diff --git a/tools/tools/cxgbetool/cxgbetool.c b/tools/tools/cxgbetool/cxgbetool.c index 4f78802e8..3d4cbfbc0 100644 --- a/tools/tools/cxgbetool/cxgbetool.c +++ b/tools/tools/cxgbetool/cxgbetool.c @@ -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 && -- 2.45.0