1 /*- 2 * Copyright (c) 2017 Chelsio Communications, Inc. 3 * All rights reserved. 4 * Written by: Navdeep Parhar <np@FreeBSD.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 #include "opt_inet.h" 32 #include "opt_inet6.h" 33 #include "opt_ratelimit.h" 34 35 #include <sys/types.h> 36 #include <sys/malloc.h> 37 #include <sys/queue.h> 38 #include <sys/sbuf.h> 39 #include <sys/taskqueue.h> 40 #include <sys/sysctl.h> 41 42 #include "common/common.h" 43 #include "common/t4_regs.h" 44 #include "common/t4_regs_values.h" 45 #include "common/t4_msg.h" 46 47 48 static int 49 in_range(int val, int lo, int hi) 50 { 51 52 return (val < 0 || (val <= hi && val >= lo)); 53 } 54 55 static int 56 set_sched_class_config(struct adapter *sc, int minmax) 57 { 58 int rc; 59 60 if (minmax < 0) 61 return (EINVAL); 62 63 rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4sscc"); 64 if (rc) 65 return (rc); 66 rc = -t4_sched_config(sc, FW_SCHED_TYPE_PKTSCHED, minmax, 1); 67 end_synchronized_op(sc, 0); 68 69 return (rc); 70 } 71 72 static int 73 set_sched_class_params(struct adapter *sc, struct t4_sched_class_params *p, 74 int sleep_ok) 75 { 76 int rc, top_speed, fw_level, fw_mode, fw_rateunit, fw_ratemode; 77 struct port_info *pi; 78 struct tx_cl_rl_params *tc; 79 80 if (p->level == SCHED_CLASS_LEVEL_CL_RL) 81 fw_level = FW_SCHED_PARAMS_LEVEL_CL_RL; 82 else if (p->level == SCHED_CLASS_LEVEL_CL_WRR) 83 fw_level = FW_SCHED_PARAMS_LEVEL_CL_WRR; 84 else if (p->level == SCHED_CLASS_LEVEL_CH_RL) 85 fw_level = FW_SCHED_PARAMS_LEVEL_CH_RL; 86 else 87 return (EINVAL); 88 89 if (p->mode == SCHED_CLASS_MODE_CLASS) 90 fw_mode = FW_SCHED_PARAMS_MODE_CLASS; 91 else if (p->mode == SCHED_CLASS_MODE_FLOW) 92 fw_mode = FW_SCHED_PARAMS_MODE_FLOW; 93 else 94 return (EINVAL); 95 96 if (p->rateunit == SCHED_CLASS_RATEUNIT_BITS) 97 fw_rateunit = FW_SCHED_PARAMS_UNIT_BITRATE; 98 else if (p->rateunit == SCHED_CLASS_RATEUNIT_PKTS) 99 fw_rateunit = FW_SCHED_PARAMS_UNIT_PKTRATE; 100 else 101 return (EINVAL); 102 103 if (p->ratemode == SCHED_CLASS_RATEMODE_REL) 104 fw_ratemode = FW_SCHED_PARAMS_RATE_REL; 105 else if (p->ratemode == SCHED_CLASS_RATEMODE_ABS) 106 fw_ratemode = FW_SCHED_PARAMS_RATE_ABS; 107 else 108 return (EINVAL); 109 110 /* Vet our parameters ... */ 111 if (!in_range(p->channel, 0, sc->chip_params->nchan - 1)) 112 return (ERANGE); 113 114 pi = sc->port[sc->chan_map[p->channel]]; 115 if (pi == NULL) 116 return (ENXIO); 117 MPASS(pi->tx_chan == p->channel); 118 top_speed = port_top_speed(pi) * 1000000; /* Gbps -> Kbps */ 119 120 if (!in_range(p->cl, 0, sc->chip_params->nsched_cls) || 121 !in_range(p->minrate, 0, top_speed) || 122 !in_range(p->maxrate, 0, top_speed) || 123 !in_range(p->weight, 0, 100)) 124 return (ERANGE); 125 126 /* 127 * Translate any unset parameters into the firmware's 128 * nomenclature and/or fail the call if the parameters 129 * are required ... 130 */ 131 if (p->rateunit < 0 || p->ratemode < 0 || p->channel < 0 || p->cl < 0) 132 return (EINVAL); 133 134 if (p->minrate < 0) 135 p->minrate = 0; 136 if (p->maxrate < 0) { 137 if (p->level == SCHED_CLASS_LEVEL_CL_RL || 138 p->level == SCHED_CLASS_LEVEL_CH_RL) 139 return (EINVAL); 140 else 141 p->maxrate = 0; 142 } 143 if (p->weight < 0) { 144 if (p->level == SCHED_CLASS_LEVEL_CL_WRR) 145 return (EINVAL); 146 else 147 p->weight = 0; 148 } 149 if (p->pktsize < 0) { 150 if (p->level == SCHED_CLASS_LEVEL_CL_RL || 151 p->level == SCHED_CLASS_LEVEL_CH_RL) 152 return (EINVAL); 153 else 154 p->pktsize = 0; 155 } 156 157 rc = begin_synchronized_op(sc, NULL, 158 sleep_ok ? (SLEEP_OK | INTR_OK) : HOLD_LOCK, "t4sscp"); 159 if (rc) 160 return (rc); 161 if (p->level == SCHED_CLASS_LEVEL_CL_RL) { 162 tc = &pi->sched_params->cl_rl[p->cl]; 163 if (tc->refcount > 0) { 164 rc = EBUSY; 165 goto done; 166 } else { 167 tc->ratemode = fw_ratemode; 168 tc->rateunit = fw_rateunit; 169 tc->mode = fw_mode; 170 tc->maxrate = p->maxrate; 171 tc->pktsize = p->pktsize; 172 } 173 } 174 rc = -t4_sched_params(sc, FW_SCHED_TYPE_PKTSCHED, fw_level, fw_mode, 175 fw_rateunit, fw_ratemode, p->channel, p->cl, p->minrate, p->maxrate, 176 p->weight, p->pktsize, sleep_ok); 177 if (p->level == SCHED_CLASS_LEVEL_CL_RL && rc != 0) { 178 /* 179 * Unknown state at this point, see parameters in tc for what 180 * was attempted. 181 */ 182 tc->flags |= TX_CLRL_ERROR; 183 } 184 done: 185 end_synchronized_op(sc, sleep_ok ? 0 : LOCK_HELD); 186 187 return (rc); 188 } 189 190 static void 191 update_tx_sched(void *context, int pending) 192 { 193 int i, j, mode, rateunit, ratemode, maxrate, pktsize, rc; 194 struct port_info *pi; 195 struct tx_cl_rl_params *tc; 196 struct adapter *sc = context; 197 const int n = sc->chip_params->nsched_cls; 198 199 mtx_lock(&sc->tc_lock); 200 for_each_port(sc, i) { 201 pi = sc->port[i]; 202 tc = &pi->sched_params->cl_rl[0]; 203 for (j = 0; j < n; j++, tc++) { 204 MPASS(mtx_owned(&sc->tc_lock)); 205 if ((tc->flags & TX_CLRL_REFRESH) == 0) 206 continue; 207 208 mode = tc->mode; 209 rateunit = tc->rateunit; 210 ratemode = tc->ratemode; 211 maxrate = tc->maxrate; 212 pktsize = tc->pktsize; 213 mtx_unlock(&sc->tc_lock); 214 215 if (begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, 216 "t4utxs") != 0) { 217 mtx_lock(&sc->tc_lock); 218 continue; 219 } 220 rc = t4_sched_params(sc, FW_SCHED_TYPE_PKTSCHED, 221 FW_SCHED_PARAMS_LEVEL_CL_RL, mode, rateunit, 222 ratemode, pi->tx_chan, j, 0, maxrate, 0, pktsize, 223 1); 224 end_synchronized_op(sc, 0); 225 226 mtx_lock(&sc->tc_lock); 227 if (rc != 0) { 228 tc->flags |= TX_CLRL_ERROR; 229 } else if (tc->mode == mode && 230 tc->rateunit == rateunit && 231 tc->maxrate == maxrate && 232 tc->pktsize == tc->pktsize) { 233 tc->flags &= ~(TX_CLRL_REFRESH | TX_CLRL_ERROR); 234 } 235 } 236 } 237 mtx_unlock(&sc->tc_lock); 238 } 239 240 int 241 t4_set_sched_class(struct adapter *sc, struct t4_sched_params *p) 242 { 243 244 if (p->type != SCHED_CLASS_TYPE_PACKET) 245 return (EINVAL); 246 247 if (p->subcmd == SCHED_CLASS_SUBCMD_CONFIG) 248 return (set_sched_class_config(sc, p->u.config.minmax)); 249 250 if (p->subcmd == SCHED_CLASS_SUBCMD_PARAMS) 251 return (set_sched_class_params(sc, &p->u.params, 1)); 252 253 return (EINVAL); 254 } 255 256 int 257 t4_set_sched_queue(struct adapter *sc, struct t4_sched_queue *p) 258 { 259 struct port_info *pi = NULL; 260 struct vi_info *vi; 261 struct sge_txq *txq; 262 uint32_t fw_mnem, fw_queue, fw_class; 263 int i, rc; 264 265 rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4setsq"); 266 if (rc) 267 return (rc); 268 269 if (p->port >= sc->params.nports) { 270 rc = EINVAL; 271 goto done; 272 } 273 274 /* XXX: Only supported for the main VI. */ 275 pi = sc->port[p->port]; 276 vi = &pi->vi[0]; 277 if (!(vi->flags & VI_INIT_DONE)) { 278 /* tx queues not set up yet */ 279 rc = EAGAIN; 280 goto done; 281 } 282 283 if (!in_range(p->queue, 0, vi->ntxq - 1) || 284 !in_range(p->cl, 0, sc->chip_params->nsched_cls - 1)) { 285 rc = EINVAL; 286 goto done; 287 } 288 289 /* 290 * Create a template for the FW_PARAMS_CMD mnemonic and value (TX 291 * Scheduling Class in this case). 292 */ 293 fw_mnem = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DMAQ) | 294 V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DMAQ_EQ_SCHEDCLASS_ETH)); 295 fw_class = p->cl < 0 ? 0xffffffff : p->cl; 296 297 /* 298 * If op.queue is non-negative, then we're only changing the scheduling 299 * on a single specified TX queue. 300 */ 301 if (p->queue >= 0) { 302 txq = &sc->sge.txq[vi->first_txq + p->queue]; 303 fw_queue = (fw_mnem | V_FW_PARAMS_PARAM_YZ(txq->eq.cntxt_id)); 304 rc = -t4_set_params(sc, sc->mbox, sc->pf, 0, 1, &fw_queue, 305 &fw_class); 306 goto done; 307 } 308 309 /* 310 * Change the scheduling on all the TX queues for the 311 * interface. 312 */ 313 for_each_txq(vi, i, txq) { 314 fw_queue = (fw_mnem | V_FW_PARAMS_PARAM_YZ(txq->eq.cntxt_id)); 315 rc = -t4_set_params(sc, sc->mbox, sc->pf, 0, 1, &fw_queue, 316 &fw_class); 317 if (rc) 318 goto done; 319 } 320 321 rc = 0; 322 done: 323 end_synchronized_op(sc, 0); 324 return (rc); 325 } 326 327 int 328 t4_init_tx_sched(struct adapter *sc) 329 { 330 int i, j; 331 const int n = sc->chip_params->nsched_cls; 332 struct port_info *pi; 333 struct tx_cl_rl_params *tc; 334 static const uint32_t init_kbps[] = { 335 100 * 1000, 336 200 * 1000, 337 400 * 1000, 338 500 * 1000, 339 800 * 1000, 340 1000 * 1000, 341 1200 * 1000, 342 1500 * 1000, 343 1800 * 1000, 344 2000 * 1000, 345 2500 * 1000, 346 3000 * 1000, 347 3500 * 1000, 348 4000 * 1000, 349 5000 * 1000, 350 10000 * 1000 351 }; 352 353 mtx_init(&sc->tc_lock, "tx_sched lock", NULL, MTX_DEF); 354 TASK_INIT(&sc->tc_task, 0, update_tx_sched, sc); 355 for_each_port(sc, i) { 356 pi = sc->port[i]; 357 pi->sched_params = malloc(sizeof(*pi->sched_params) + 358 n * sizeof(*tc), M_CXGBE, M_ZERO | M_WAITOK); 359 tc = &pi->sched_params->cl_rl[0]; 360 for (j = 0; j < n; j++, tc++) { 361 tc->refcount = 0; 362 tc->ratemode = FW_SCHED_PARAMS_RATE_ABS; 363 tc->rateunit = FW_SCHED_PARAMS_UNIT_BITRATE; 364 tc->mode = FW_SCHED_PARAMS_MODE_FLOW; 365 tc->maxrate = init_kbps[min(j, nitems(init_kbps) - 1)]; 366 tc->pktsize = ETHERMTU; /* XXX */ 367 368 if (t4_sched_params_cl_rl_kbps(sc, pi->tx_chan, j, 369 tc->mode, tc->maxrate, tc->pktsize, 1) == 0) 370 tc->flags = 0; 371 else 372 tc->flags = TX_CLRL_ERROR; 373 } 374 } 375 376 return (0); 377 } 378 379 int 380 t4_free_tx_sched(struct adapter *sc) 381 { 382 int i; 383 384 taskqueue_drain(taskqueue_thread, &sc->tc_task); 385 386 for_each_port(sc, i) { 387 if (sc->port[i] != NULL) 388 free(sc->port[i]->sched_params, M_CXGBE); 389 } 390 391 if (mtx_initialized(&sc->tc_lock)) 392 mtx_destroy(&sc->tc_lock); 393 394 return (0); 395 } 396 397 void 398 t4_update_tx_sched(struct adapter *sc) 399 { 400 401 taskqueue_enqueue(taskqueue_thread, &sc->tc_task); 402 } 403 404 int 405 t4_reserve_cl_rl_kbps(struct adapter *sc, int port_id, u_int maxrate, 406 int *tc_idx) 407 { 408 int rc = 0, fa = -1, i; 409 struct tx_cl_rl_params *tc; 410 411 MPASS(port_id >= 0 && port_id < sc->params.nports); 412 413 tc = &sc->port[port_id]->sched_params->cl_rl[0]; 414 mtx_lock(&sc->tc_lock); 415 for (i = 0; i < sc->chip_params->nsched_cls; i++, tc++) { 416 if (fa < 0 && tc->refcount == 0) 417 fa = i; 418 419 if (tc->ratemode == FW_SCHED_PARAMS_RATE_ABS && 420 tc->rateunit == FW_SCHED_PARAMS_UNIT_BITRATE && 421 tc->mode == FW_SCHED_PARAMS_MODE_FLOW && 422 tc->maxrate == maxrate) { 423 tc->refcount++; 424 *tc_idx = i; 425 goto done; 426 } 427 } 428 /* Not found */ 429 MPASS(i == sc->chip_params->nsched_cls); 430 if (fa != -1) { 431 tc = &sc->port[port_id]->sched_params->cl_rl[fa]; 432 tc->flags = TX_CLRL_REFRESH; 433 tc->refcount = 1; 434 tc->ratemode = FW_SCHED_PARAMS_RATE_ABS; 435 tc->rateunit = FW_SCHED_PARAMS_UNIT_BITRATE; 436 tc->mode = FW_SCHED_PARAMS_MODE_FLOW; 437 tc->maxrate = maxrate; 438 tc->pktsize = ETHERMTU; /* XXX */ 439 *tc_idx = fa; 440 t4_update_tx_sched(sc); 441 } else { 442 *tc_idx = -1; 443 rc = ENOSPC; 444 } 445 done: 446 mtx_unlock(&sc->tc_lock); 447 return (rc); 448 } 449 450 void 451 t4_release_cl_rl_kbps(struct adapter *sc, int port_id, int tc_idx) 452 { 453 struct tx_cl_rl_params *tc; 454 455 MPASS(port_id >= 0 && port_id < sc->params.nports); 456 MPASS(tc_idx >= 0 && tc_idx < sc->chip_params->nsched_cls); 457 458 mtx_lock(&sc->tc_lock); 459 tc = &sc->port[port_id]->sched_params->cl_rl[tc_idx]; 460 MPASS(tc->refcount > 0); 461 MPASS(tc->ratemode == FW_SCHED_PARAMS_RATE_ABS); 462 MPASS(tc->rateunit == FW_SCHED_PARAMS_UNIT_BITRATE); 463 MPASS(tc->mode == FW_SCHED_PARAMS_MODE_FLOW); 464 tc->refcount--; 465 mtx_unlock(&sc->tc_lock); 466 } 467 468 #ifdef RATELIMIT 469 void 470 t4_init_etid_table(struct adapter *sc) 471 { 472 int i; 473 struct tid_info *t; 474 475 if (!is_ethoffload(sc)) 476 return; 477 478 t = &sc->tids; 479 MPASS(t->netids > 0); 480 481 mtx_init(&t->etid_lock, "etid lock", NULL, MTX_DEF); 482 t->etid_tab = malloc(sizeof(*t->etid_tab) * t->netids, M_CXGBE, 483 M_ZERO | M_WAITOK); 484 t->efree = t->etid_tab; 485 t->etids_in_use = 0; 486 for (i = 1; i < t->netids; i++) 487 t->etid_tab[i - 1].next = &t->etid_tab[i]; 488 t->etid_tab[t->netids - 1].next = NULL; 489 } 490 491 void 492 t4_free_etid_table(struct adapter *sc) 493 { 494 struct tid_info *t; 495 496 if (!is_ethoffload(sc)) 497 return; 498 499 t = &sc->tids; 500 MPASS(t->netids > 0); 501 502 free(t->etid_tab, M_CXGBE); 503 t->etid_tab = NULL; 504 505 if (mtx_initialized(&t->etid_lock)) 506 mtx_destroy(&t->etid_lock); 507 } 508 509 /* etid services */ 510 static int alloc_etid(struct adapter *, struct cxgbe_snd_tag *); 511 static void free_etid(struct adapter *, int); 512 513 static int 514 alloc_etid(struct adapter *sc, struct cxgbe_snd_tag *cst) 515 { 516 struct tid_info *t = &sc->tids; 517 int etid = -1; 518 519 mtx_lock(&t->etid_lock); 520 if (t->efree) { 521 union etid_entry *p = t->efree; 522 523 etid = p - t->etid_tab + t->etid_base; 524 t->efree = p->next; 525 p->cst = cst; 526 t->etids_in_use++; 527 } 528 mtx_unlock(&t->etid_lock); 529 return (etid); 530 } 531 532 struct cxgbe_snd_tag * 533 lookup_etid(struct adapter *sc, int etid) 534 { 535 struct tid_info *t = &sc->tids; 536 537 return (t->etid_tab[etid - t->etid_base].cst); 538 } 539 540 static void 541 free_etid(struct adapter *sc, int etid) 542 { 543 struct tid_info *t = &sc->tids; 544 union etid_entry *p = &t->etid_tab[etid - t->etid_base]; 545 546 mtx_lock(&t->etid_lock); 547 p->next = t->efree; 548 t->efree = p; 549 t->etids_in_use--; 550 mtx_unlock(&t->etid_lock); 551 } 552 553 int 554 cxgbe_snd_tag_alloc(struct ifnet *ifp, union if_snd_tag_alloc_params *params, 555 struct m_snd_tag **pt) 556 { 557 int rc, schedcl; 558 struct vi_info *vi = ifp->if_softc; 559 struct port_info *pi = vi->pi; 560 struct adapter *sc = pi->adapter; 561 struct cxgbe_snd_tag *cst; 562 563 if (params->hdr.type != IF_SND_TAG_TYPE_RATE_LIMIT) 564 return (ENOTSUP); 565 566 rc = t4_reserve_cl_rl_kbps(sc, pi->port_id, 567 (params->rate_limit.max_rate * 8ULL / 1000), &schedcl); 568 if (rc != 0) 569 return (rc); 570 MPASS(schedcl >= 0 && schedcl < sc->chip_params->nsched_cls); 571 572 cst = malloc(sizeof(*cst), M_CXGBE, M_ZERO | M_NOWAIT); 573 if (cst == NULL) { 574 failed: 575 t4_release_cl_rl_kbps(sc, pi->port_id, schedcl); 576 return (ENOMEM); 577 } 578 579 cst->etid = alloc_etid(sc, cst); 580 if (cst->etid < 0) { 581 free(cst, M_CXGBE); 582 goto failed; 583 } 584 585 mtx_init(&cst->lock, "cst_lock", NULL, MTX_DEF); 586 mbufq_init(&cst->pending_tx, INT_MAX); 587 mbufq_init(&cst->pending_fwack, INT_MAX); 588 cst->com.ifp = ifp; 589 cst->flags |= EO_FLOWC_PENDING | EO_SND_TAG_REF; 590 cst->adapter = sc; 591 cst->port_id = pi->port_id; 592 cst->schedcl = schedcl; 593 cst->max_rate = params->rate_limit.max_rate; 594 cst->tx_credits = sc->params.ofldq_wr_cred; 595 cst->tx_total = cst->tx_credits; 596 cst->plen = 0; 597 cst->ctrl0 = htobe32(V_TXPKT_OPCODE(CPL_TX_PKT) | 598 V_TXPKT_INTF(pi->tx_chan) | V_TXPKT_PF(G_FW_VIID_PFN(vi->viid)) | 599 V_TXPKT_VF(G_FW_VIID_VIN(vi->viid)) | 600 V_TXPKT_VF_VLD(G_FW_VIID_VIVLD(vi->viid))); 601 602 /* 603 * Queues will be selected later when the connection flowid is available. 604 */ 605 606 *pt = &cst->com; 607 return (0); 608 } 609 610 /* 611 * Change in parameters, no change in ifp. 612 */ 613 int 614 cxgbe_snd_tag_modify(struct m_snd_tag *mst, 615 union if_snd_tag_modify_params *params) 616 { 617 int rc, schedcl; 618 struct cxgbe_snd_tag *cst = mst_to_cst(mst); 619 struct adapter *sc = cst->adapter; 620 621 /* XXX: is schedcl -1 ok here? */ 622 MPASS(cst->schedcl >= 0 && cst->schedcl < sc->chip_params->nsched_cls); 623 624 mtx_lock(&cst->lock); 625 MPASS(cst->flags & EO_SND_TAG_REF); 626 rc = t4_reserve_cl_rl_kbps(sc, cst->port_id, 627 (params->rate_limit.max_rate * 8ULL / 1000), &schedcl); 628 if (rc != 0) 629 return (rc); 630 MPASS(schedcl >= 0 && schedcl < sc->chip_params->nsched_cls); 631 t4_release_cl_rl_kbps(sc, cst->port_id, cst->schedcl); 632 cst->schedcl = schedcl; 633 cst->max_rate = params->rate_limit.max_rate; 634 mtx_unlock(&cst->lock); 635 636 return (0); 637 } 638 639 int 640 cxgbe_snd_tag_query(struct m_snd_tag *mst, 641 union if_snd_tag_query_params *params) 642 { 643 struct cxgbe_snd_tag *cst = mst_to_cst(mst); 644 645 params->rate_limit.max_rate = cst->max_rate; 646 647 #define CST_TO_MST_QLEVEL_SCALE (IF_SND_QUEUE_LEVEL_MAX / cst->tx_total) 648 params->rate_limit.queue_level = 649 (cst->tx_total - cst->tx_credits) * CST_TO_MST_QLEVEL_SCALE; 650 651 return (0); 652 } 653 654 /* 655 * Unlocks cst and frees it. 656 */ 657 void 658 cxgbe_snd_tag_free_locked(struct cxgbe_snd_tag *cst) 659 { 660 struct adapter *sc = cst->adapter; 661 662 mtx_assert(&cst->lock, MA_OWNED); 663 MPASS((cst->flags & EO_SND_TAG_REF) == 0); 664 MPASS(cst->tx_credits == cst->tx_total); 665 MPASS(cst->plen == 0); 666 MPASS(mbufq_first(&cst->pending_tx) == NULL); 667 MPASS(mbufq_first(&cst->pending_fwack) == NULL); 668 669 if (cst->etid >= 0) 670 free_etid(sc, cst->etid); 671 if (cst->schedcl != -1) 672 t4_release_cl_rl_kbps(sc, cst->port_id, cst->schedcl); 673 mtx_unlock(&cst->lock); 674 mtx_destroy(&cst->lock); 675 free(cst, M_CXGBE); 676 } 677 678 void 679 cxgbe_snd_tag_free(struct m_snd_tag *mst) 680 { 681 struct cxgbe_snd_tag *cst = mst_to_cst(mst); 682 683 mtx_lock(&cst->lock); 684 685 /* The kernel is done with the snd_tag. Remove its reference. */ 686 MPASS(cst->flags & EO_SND_TAG_REF); 687 cst->flags &= ~EO_SND_TAG_REF; 688 689 if (cst->ncompl == 0) { 690 /* 691 * No fw4_ack in flight. Free the tag right away if there are 692 * no outstanding credits. Request the firmware to return all 693 * credits for the etid otherwise. 694 */ 695 if (cst->tx_credits == cst->tx_total) { 696 cxgbe_snd_tag_free_locked(cst); 697 return; /* cst is gone. */ 698 } 699 send_etid_flush_wr(cst); 700 } 701 mtx_unlock(&cst->lock); 702 } 703 #endif 704