From owner-svn-src-stable-10@freebsd.org Thu May 25 01:43:30 2017 Return-Path: Delivered-To: svn-src-stable-10@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 39917D8042C; Thu, 25 May 2017 01:43:30 +0000 (UTC) (envelope-from np@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 0A6001C28; Thu, 25 May 2017 01:43:29 +0000 (UTC) (envelope-from np@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v4P1hTQX037730; Thu, 25 May 2017 01:43:29 GMT (envelope-from np@FreeBSD.org) Received: (from np@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v4P1hS67037721; Thu, 25 May 2017 01:43:28 GMT (envelope-from np@FreeBSD.org) Message-Id: <201705250143.v4P1hS67037721@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: np set sender to np@FreeBSD.org using -f From: Navdeep Parhar Date: Thu, 25 May 2017 01:43:28 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r318851 - in stable/10/sys: conf dev/cxgbe dev/cxgbe/common modules/cxgbe/if_cxgbe X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 25 May 2017 01:43:30 -0000 Author: np Date: Thu May 25 01:43:28 2017 New Revision: 318851 URL: https://svnweb.freebsd.org/changeset/base/318851 Log: MFC r317702, r317847, r318307 r317702: cxgbe(4): Support routines for Tx traffic scheduling. - Create a new file, t4_sched.c, and move all of the code related to traffic management from t4_main.c and t4_sge.c to this file. - Track both Channel Rate Limiter (ch_rl) and Class Rate Limiter (cl_rl) parameters in the PF driver. - Initialize all the cl_rl limiters with somewhat arbitrary default rates and provide routines to update them on the fly. - Provide routines to reserve and release traffic classes. r317847: cxgbe(4): The Tx scheduler initialization either works or doesn't. It doesn't need a refresh in either case. r318307: cxgbe(4): Avoid an out of bounds access when an attempt to unbind a tx queue from a traffic class fails. Sponsored by: Chelsio Communications Added: stable/10/sys/dev/cxgbe/t4_sched.c - copied, changed from r317702, head/sys/dev/cxgbe/t4_sched.c Modified: stable/10/sys/conf/files stable/10/sys/dev/cxgbe/adapter.h stable/10/sys/dev/cxgbe/common/common.h stable/10/sys/dev/cxgbe/common/t4_hw.c stable/10/sys/dev/cxgbe/t4_main.c stable/10/sys/dev/cxgbe/t4_sge.c stable/10/sys/dev/cxgbe/t4_vf.c stable/10/sys/modules/cxgbe/if_cxgbe/Makefile Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/conf/files ============================================================================== --- stable/10/sys/conf/files Thu May 25 01:40:40 2017 (r318850) +++ stable/10/sys/conf/files Thu May 25 01:43:28 2017 (r318851) @@ -1151,6 +1151,8 @@ dev/cxgbe/t4_main.c optional cxgbe pci compile-with "${NORMAL_C} -I$S/dev/cxgbe" dev/cxgbe/t4_netmap.c optional cxgbe pci \ compile-with "${NORMAL_C} -I$S/dev/cxgbe" +dev/cxgbe/t4_sched.c optional cxgbe pci \ + compile-with "${NORMAL_C} -I$S/dev/cxgbe" dev/cxgbe/t4_sge.c optional cxgbe pci \ compile-with "${NORMAL_C} -I$S/dev/cxgbe" dev/cxgbe/t4_l2t.c optional cxgbe pci \ Modified: stable/10/sys/dev/cxgbe/adapter.h ============================================================================== --- stable/10/sys/dev/cxgbe/adapter.h Thu May 25 01:40:40 2017 (r318850) +++ stable/10/sys/dev/cxgbe/adapter.h Thu May 25 01:43:28 2017 (r318851) @@ -225,15 +225,36 @@ struct vi_info { uint8_t hw_addr[ETHER_ADDR_LEN]; /* factory MAC address, won't change */ }; +struct tx_ch_rl_params { + enum fw_sched_params_rate ratemode; /* %port (REL) or kbps (ABS) */ + uint32_t maxrate; +}; + enum { - /* tx_sched_class flags */ - TX_SC_OK = (1 << 0), /* Set up in hardware, active. */ + TX_CLRL_REFRESH = (1 << 0), /* Need to update hardware state. */ + TX_CLRL_ERROR = (1 << 1), /* Error, hardware state unknown. */ }; -struct tx_sched_class { +struct tx_cl_rl_params { int refcount; - int flags; - struct t4_sched_class_params params; + u_int 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 */ + uint32_t maxrate; + uint16_t pktsize; +}; + +/* Tx scheduler parameters for a channel/port */ +struct tx_sched_params { + /* Channel Rate Limiter */ + struct tx_ch_rl_params ch_rl; + + /* Class WRR */ + /* XXX */ + + /* Class Rate Limiter */ + struct tx_cl_rl_params cl_rl[]; }; struct port_info { @@ -245,7 +266,7 @@ struct port_info { int up_vis; int uld_vis; - struct tx_sched_class *tc; /* traffic classes for this channel */ + struct tx_sched_params *sched_params; struct mtx pi_lock; char lockname[16]; @@ -817,6 +838,9 @@ struct adapter { struct memwin memwin[NUM_MEMWIN]; /* memory windows */ + struct mtx tc_lock; + struct task tc_task; + const char *last_op; const void *last_op_thr; int last_op_flags; @@ -1098,8 +1122,6 @@ int t4_detach_common(device_t); int t4_filter_rpl(struct sge_iq *, const struct rss_header *, struct mbuf *); int t4_map_bars_0_and_4(struct adapter *); int t4_map_bar_2(struct adapter *); -int t4_set_sched_class(struct adapter *, struct t4_sched_params *); -int t4_set_sched_queue(struct adapter *, struct t4_sched_queue *); int t4_setup_intr_handlers(struct adapter *); void t4_sysctls(struct adapter *); int begin_synchronized_op(struct adapter *, struct vi_info *, int, char *); @@ -1160,6 +1182,15 @@ int t4_set_tracer(struct adapter *, stru int t4_trace_pkt(struct sge_iq *, const struct rss_header *, struct mbuf *); int t5_trace_pkt(struct sge_iq *, const struct rss_header *, struct mbuf *); +/* t4_sched.c */ +int t4_set_sched_class(struct adapter *, struct t4_sched_params *); +int t4_set_sched_queue(struct adapter *, struct t4_sched_queue *); +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); + static inline struct wrqe * alloc_wrqe(int wr_len, struct sge_wrq *wrq) { Modified: stable/10/sys/dev/cxgbe/common/common.h ============================================================================== --- stable/10/sys/dev/cxgbe/common/common.h Thu May 25 01:40:40 2017 (r318850) +++ stable/10/sys/dev/cxgbe/common/common.h Thu May 25 01:43:28 2017 (r318851) @@ -774,6 +774,13 @@ int t4_sched_params(struct adapter *adap int rateunit, int ratemode, int channel, int cl, int minrate, int maxrate, int weight, int pktsize, int sleep_ok); +int t4_sched_params_ch_rl(struct adapter *adapter, int channel, int ratemode, + unsigned int maxrate, int sleep_ok); +int t4_sched_params_cl_wrr(struct adapter *adapter, int channel, int cl, + int weight, int sleep_ok); +int t4_sched_params_cl_rl_kbps(struct adapter *adapter, int channel, int cl, + int mode, unsigned int maxrate, int pktsize, + int sleep_ok); int t4_config_watchdog(struct adapter *adapter, unsigned int mbox, unsigned int pf, unsigned int vf, unsigned int timeout, unsigned int action); Modified: stable/10/sys/dev/cxgbe/common/t4_hw.c ============================================================================== --- stable/10/sys/dev/cxgbe/common/t4_hw.c Thu May 25 01:40:40 2017 (r318850) +++ stable/10/sys/dev/cxgbe/common/t4_hw.c Thu May 25 01:43:28 2017 (r318851) @@ -9393,6 +9393,79 @@ int t4_sched_params(struct adapter *adap NULL, sleep_ok); } +int t4_sched_params_ch_rl(struct adapter *adapter, int channel, int ratemode, + unsigned int maxrate, int sleep_ok) +{ + struct fw_sched_cmd cmd; + + memset(&cmd, 0, sizeof(cmd)); + cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_SCHED_CMD) | + F_FW_CMD_REQUEST | + F_FW_CMD_WRITE); + cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd)); + + cmd.u.params.sc = FW_SCHED_SC_PARAMS; + cmd.u.params.type = FW_SCHED_TYPE_PKTSCHED; + cmd.u.params.level = FW_SCHED_PARAMS_LEVEL_CH_RL; + cmd.u.params.ch = channel; + cmd.u.params.rate = ratemode; /* REL or ABS */ + cmd.u.params.max = cpu_to_be32(maxrate);/* % or kbps */ + + return t4_wr_mbox_meat(adapter,adapter->mbox, &cmd, sizeof(cmd), + NULL, sleep_ok); +} + +int t4_sched_params_cl_wrr(struct adapter *adapter, int channel, int cl, + int weight, int sleep_ok) +{ + struct fw_sched_cmd cmd; + + if (weight < 0 || weight > 100) + return -EINVAL; + + memset(&cmd, 0, sizeof(cmd)); + cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_SCHED_CMD) | + F_FW_CMD_REQUEST | + F_FW_CMD_WRITE); + cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd)); + + cmd.u.params.sc = FW_SCHED_SC_PARAMS; + cmd.u.params.type = FW_SCHED_TYPE_PKTSCHED; + cmd.u.params.level = FW_SCHED_PARAMS_LEVEL_CL_WRR; + cmd.u.params.ch = channel; + cmd.u.params.cl = cl; + cmd.u.params.weight = cpu_to_be16(weight); + + return t4_wr_mbox_meat(adapter,adapter->mbox, &cmd, sizeof(cmd), + NULL, sleep_ok); +} + +int t4_sched_params_cl_rl_kbps(struct adapter *adapter, int channel, int cl, + int mode, unsigned int maxrate, int pktsize, int sleep_ok) +{ + struct fw_sched_cmd cmd; + + memset(&cmd, 0, sizeof(cmd)); + cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_SCHED_CMD) | + F_FW_CMD_REQUEST | + F_FW_CMD_WRITE); + cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd)); + + cmd.u.params.sc = FW_SCHED_SC_PARAMS; + cmd.u.params.type = FW_SCHED_TYPE_PKTSCHED; + cmd.u.params.level = FW_SCHED_PARAMS_LEVEL_CL_RL; + cmd.u.params.mode = mode; + cmd.u.params.ch = channel; + cmd.u.params.cl = cl; + cmd.u.params.unit = FW_SCHED_PARAMS_UNIT_BITRATE; + cmd.u.params.rate = FW_SCHED_PARAMS_RATE_ABS; + cmd.u.params.max = cpu_to_be32(maxrate); + cmd.u.params.pktsize = cpu_to_be16(pktsize); + + return t4_wr_mbox_meat(adapter,adapter->mbox, &cmd, sizeof(cmd), + NULL, sleep_ok); +} + /* * t4_config_watchdog - configure (enable/disable) a watchdog timer * @adapter: the adapter Modified: stable/10/sys/dev/cxgbe/t4_main.c ============================================================================== --- stable/10/sys/dev/cxgbe/t4_main.c Thu May 25 01:40:40 2017 (r318850) +++ stable/10/sys/dev/cxgbe/t4_main.c Thu May 25 01:43:28 2017 (r318851) @@ -998,9 +998,6 @@ 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 (port_top_speed(pi) >= 10) { n10g++; } else { @@ -1088,6 +1085,7 @@ t4_attach(device_t dev) M_ZERO | M_WAITOK); t4_init_l2t(sc, M_WAITOK); + t4_init_tx_sched(sc); /* * Second pass over the ports. This time we know the number of rx and @@ -1251,6 +1249,9 @@ t4_detach_common(device_t dev) for (i = 0; i < sc->intr_count; i++) t4_free_irq(sc, &sc->irq[i]); + if ((sc->flags & (IS_VF | FW_OK)) == FW_OK) + t4_free_tx_sched(sc); + for (i = 0; i < MAX_NPORTS; i++) { pi = sc->port[i]; if (pi) { @@ -1260,7 +1261,6 @@ t4_detach_common(device_t dev) mtx_destroy(&pi->pi_lock); free(pi->vi, M_CXGBE); - free(pi->tc, M_CXGBE); free(pi, M_CXGBE); } } @@ -5204,9 +5204,9 @@ cxgbe_sysctls(struct port_info *pi) * dev.(cxgbe|cxl).X.tc. */ oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "tc", CTLFLAG_RD, NULL, - "Tx scheduler traffic classes"); + "Tx scheduler traffic classes (cl_rl)"); for (i = 0; i < sc->chip_params->nsched_cls; i++) { - struct tx_sched_class *tc = &pi->tc[i]; + struct tx_cl_rl_params *tc = &pi->sched_params->cl_rl[i]; snprintf(name, sizeof(name), "%d", i); children2 = SYSCTL_CHILDREN(SYSCTL_ADD_NODE(ctx, @@ -7722,10 +7722,9 @@ static int sysctl_tc_params(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; - struct tx_sched_class *tc; - struct t4_sched_class_params p; + struct tx_cl_rl_params tc; struct sbuf *sb; - int i, rc, port_id, flags, mbps, gbps; + int i, rc, port_id, mbps, gbps; rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) @@ -7740,52 +7739,34 @@ sysctl_tc_params(SYSCTL_HANDLER_ARGS) 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; - } + mtx_lock(&sc->tc_lock); + tc = sc->port[port_id]->sched_params->cl_rl[i]; + mtx_unlock(&sc->tc_lock); - 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; + if (tc.flags & TX_CLRL_ERROR) { + sbuf_printf(sb, "error"); goto done; } - if (p.ratemode == SCHED_CLASS_RATEMODE_REL) { + if (tc.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) { + sbuf_printf(sb, " %u%% of %uGbps", tc.maxrate, gbps); + } else if (tc.ratemode == SCHED_CLASS_RATEMODE_ABS) { + switch (tc.rateunit) { case SCHED_CLASS_RATEUNIT_BITS: - mbps = p.maxrate / 1000; - gbps = p.maxrate / 1000000; - if (p.maxrate == gbps * 1000000) + mbps = tc.maxrate / 1000; + gbps = tc.maxrate / 1000000; + if (tc.maxrate == gbps * 1000000) sbuf_printf(sb, " %uGbps", gbps); - else if (p.maxrate == mbps * 1000) + else if (tc.maxrate == mbps * 1000) sbuf_printf(sb, " %uMbps", mbps); else - sbuf_printf(sb, " %uKbps", p.maxrate); + sbuf_printf(sb, " %uKbps", tc.maxrate); break; case SCHED_CLASS_RATEUNIT_PKTS: - sbuf_printf(sb, " %upps", p.maxrate); + sbuf_printf(sb, " %upps", tc.maxrate); break; default: rc = ENXIO; @@ -7793,7 +7774,7 @@ sysctl_tc_params(SYSCTL_HANDLER_ARGS) } } - switch (p.mode) { + switch (tc.mode) { case SCHED_CLASS_MODE_CLASS: sbuf_printf(sb, " aggregate"); break; @@ -8695,225 +8676,6 @@ read_i2c(struct adapter *sc, struct t4_i return (rc); } -static int -in_range(int val, int lo, int hi) -{ - - return (val < 0 || (val <= hi && val >= lo)); -} - -static int -set_sched_class_config(struct adapter *sc, int minmax) -{ - int rc; - - if (minmax < 0) - return (EINVAL); - - 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); - - return (rc); -} - -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 (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 (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->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); - - /* Vet our parameters ... */ - if (!in_range(p->channel, 0, sc->chip_params->nchan - 1)) - return (ERANGE); - - 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 (!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 { - /* - * Unknown state at this point, see tc->params for what was - * attempted. - */ - tc->flags &= ~TX_SC_OK; - } - end_synchronized_op(sc, sleep_ok ? 0 : LOCK_HELD); - - return (rc); -} - -int -t4_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); -} - -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; - uint32_t fw_mnem, fw_queue, fw_class; - int i, rc; - - rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4setsq"); - if (rc) - return (rc); - - if (p->port >= sc->params.nports) { - rc = EINVAL; - 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; - 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; - } - - /* - * Create a template for the FW_PARAMS_CMD mnemonic and value (TX - * Scheduling Class in this case). - */ - 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; - - /* - * 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; - } - - /* - * Change the scheduling on all the TX queues for the - * interface. - */ - 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; - } - - rc = 0; -done: - end_synchronized_op(sc, 0); - return (rc); -} - int t4_os_find_pci_capability(struct adapter *sc, int cap) { Copied and modified: stable/10/sys/dev/cxgbe/t4_sched.c (from r317702, head/sys/dev/cxgbe/t4_sched.c) ============================================================================== --- head/sys/dev/cxgbe/t4_sched.c Tue May 2 20:38:10 2017 (r317702, copy source) +++ stable/10/sys/dev/cxgbe/t4_sched.c Thu May 25 01:43:28 2017 (r318851) @@ -357,7 +357,6 @@ t4_init_tx_sched(struct adapter *sc) n * sizeof(*tc), M_CXGBE, M_ZERO | M_WAITOK); tc = &pi->sched_params->cl_rl[0]; for (j = 0; j < n; j++, tc++) { - tc->flags = TX_CLRL_REFRESH; tc->refcount = 0; tc->ratemode = FW_SCHED_PARAMS_RATE_ABS; tc->rateunit = FW_SCHED_PARAMS_UNIT_BITRATE; @@ -365,8 +364,11 @@ t4_init_tx_sched(struct adapter *sc) tc->maxrate = init_kbps[min(j, nitems(init_kbps) - 1)]; tc->pktsize = ETHERMTU; /* XXX */ - t4_sched_params_cl_rl_kbps(sc, pi->tx_chan, j, tc->mode, - tc->maxrate, tc->pktsize, 1); + 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; } } Modified: stable/10/sys/dev/cxgbe/t4_sge.c ============================================================================== --- stable/10/sys/dev/cxgbe/t4_sge.c Thu May 25 01:40:40 2017 (r318850) +++ stable/10/sys/dev/cxgbe/t4_sge.c Thu May 25 01:43:28 2017 (r318851) @@ -5187,7 +5187,7 @@ sysctl_tc(SYSCTL_HANDLER_ARGS) struct port_info *pi; struct adapter *sc; struct sge_txq *txq; - struct tx_sched_class *tc; + struct tx_cl_rl_params *tc; int qidx = arg2, rc, tc_idx; uint32_t fw_queue, fw_class; @@ -5201,14 +5201,14 @@ sysctl_tc(SYSCTL_HANDLER_ARGS) 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); - rc = begin_synchronized_op(sc, vi, SLEEP_OK | INTR_OK, "t4stc"); - if (rc) - return (rc); - + mtx_lock(&sc->tc_lock); if (tc_idx == txq->tc_idx) { rc = 0; /* No change, nothing to do. */ goto done; @@ -5222,35 +5222,45 @@ sysctl_tc(SYSCTL_HANDLER_ARGS) 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. + * Bind to a different class. */ - 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; + 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->tc[txq->tc_idx]; + tc = &pi->sched_params->cl_rl[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; + } else if (tc_idx != -1) { + tc = &pi->sched_params->cl_rl[tc_idx]; + MPASS(tc->refcount > 0); + tc->refcount--; } done: - end_synchronized_op(sc, 0); + mtx_unlock(&sc->tc_lock); return (rc); } Modified: stable/10/sys/dev/cxgbe/t4_vf.c ============================================================================== --- stable/10/sys/dev/cxgbe/t4_vf.c Thu May 25 01:40:40 2017 (r318850) +++ stable/10/sys/dev/cxgbe/t4_vf.c Thu May 25 01:43:28 2017 (r318851) @@ -675,9 +675,6 @@ t4vf_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 (port_top_speed(pi) >= 10) { n10g++; } else { Modified: stable/10/sys/modules/cxgbe/if_cxgbe/Makefile ============================================================================== --- stable/10/sys/modules/cxgbe/if_cxgbe/Makefile Thu May 25 01:40:40 2017 (r318850) +++ stable/10/sys/modules/cxgbe/if_cxgbe/Makefile Thu May 25 01:43:28 2017 (r318851) @@ -20,6 +20,7 @@ SRCS+= t4_l2t.c SRCS+= t4_main.c SRCS+= t4_mp_ring.c SRCS+= t4_netmap.c +SRCS+= t4_sched.c SRCS+= t4_sge.c SRCS+= t4_tracer.c