1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Copyright (C) 2019 Chelsio Communications. All rights reserved. */ 3 4 #include "cxgb4.h" 5 #include "cxgb4_tc_mqprio.h" 6 #include "sched.h" 7 8 static int cxgb4_mqprio_validate(struct net_device *dev, 9 struct tc_mqprio_qopt_offload *mqprio) 10 { 11 u64 min_rate = 0, max_rate = 0, max_link_rate; 12 struct port_info *pi = netdev2pinfo(dev); 13 struct adapter *adap = netdev2adap(dev); 14 u32 qcount = 0, qoffset = 0; 15 u32 link_ok, speed, mtu; 16 int ret; 17 u8 i; 18 19 if (!mqprio->qopt.num_tc) 20 return 0; 21 22 if (mqprio->qopt.hw != TC_MQPRIO_HW_OFFLOAD_TCS) { 23 netdev_err(dev, "Only full TC hardware offload is supported\n"); 24 return -EINVAL; 25 } else if (mqprio->mode != TC_MQPRIO_MODE_CHANNEL) { 26 netdev_err(dev, "Only channel mode offload is supported\n"); 27 return -EINVAL; 28 } else if (mqprio->shaper != TC_MQPRIO_SHAPER_BW_RATE) { 29 netdev_err(dev, "Only bandwidth rate shaper supported\n"); 30 return -EINVAL; 31 } else if (mqprio->qopt.num_tc > adap->params.nsched_cls) { 32 netdev_err(dev, 33 "Only %u traffic classes supported by hardware\n", 34 adap->params.nsched_cls); 35 return -ERANGE; 36 } 37 38 ret = t4_get_link_params(pi, &link_ok, &speed, &mtu); 39 if (ret) { 40 netdev_err(dev, "Failed to get link speed, ret: %d\n", ret); 41 return -EINVAL; 42 } 43 44 /* Convert from Mbps to bps */ 45 max_link_rate = (u64)speed * 1000 * 1000; 46 47 for (i = 0; i < mqprio->qopt.num_tc; i++) { 48 qoffset = max_t(u16, mqprio->qopt.offset[i], qoffset); 49 qcount += mqprio->qopt.count[i]; 50 51 /* Convert byte per second to bits per second */ 52 min_rate += (mqprio->min_rate[i] * 8); 53 max_rate += (mqprio->max_rate[i] * 8); 54 } 55 56 if (qoffset >= adap->tids.neotids || qcount > adap->tids.neotids) 57 return -ENOMEM; 58 59 if (min_rate > max_link_rate || max_rate > max_link_rate) { 60 netdev_err(dev, 61 "Total Min/Max (%llu/%llu) Rate > supported (%llu)\n", 62 min_rate, max_rate, max_link_rate); 63 return -EINVAL; 64 } 65 66 return 0; 67 } 68 69 static int cxgb4_init_eosw_txq(struct net_device *dev, 70 struct sge_eosw_txq *eosw_txq, 71 u32 eotid, u32 hwqid) 72 { 73 struct adapter *adap = netdev2adap(dev); 74 struct sge_eosw_desc *ring; 75 76 memset(eosw_txq, 0, sizeof(*eosw_txq)); 77 78 ring = kcalloc(CXGB4_EOSW_TXQ_DEFAULT_DESC_NUM, 79 sizeof(*ring), GFP_KERNEL); 80 if (!ring) 81 return -ENOMEM; 82 83 eosw_txq->desc = ring; 84 eosw_txq->ndesc = CXGB4_EOSW_TXQ_DEFAULT_DESC_NUM; 85 spin_lock_init(&eosw_txq->lock); 86 eosw_txq->state = CXGB4_EO_STATE_CLOSED; 87 eosw_txq->eotid = eotid; 88 eosw_txq->hwtid = adap->tids.eotid_base + eosw_txq->eotid; 89 eosw_txq->cred = adap->params.ofldq_wr_cred; 90 eosw_txq->hwqid = hwqid; 91 eosw_txq->netdev = dev; 92 tasklet_init(&eosw_txq->qresume_tsk, cxgb4_ethofld_restart, 93 (unsigned long)eosw_txq); 94 return 0; 95 } 96 97 static void cxgb4_clean_eosw_txq(struct net_device *dev, 98 struct sge_eosw_txq *eosw_txq) 99 { 100 struct adapter *adap = netdev2adap(dev); 101 102 cxgb4_eosw_txq_free_desc(adap, eosw_txq, eosw_txq->ndesc); 103 eosw_txq->pidx = 0; 104 eosw_txq->last_pidx = 0; 105 eosw_txq->cidx = 0; 106 eosw_txq->last_cidx = 0; 107 eosw_txq->flowc_idx = 0; 108 eosw_txq->inuse = 0; 109 eosw_txq->cred = adap->params.ofldq_wr_cred; 110 eosw_txq->ncompl = 0; 111 eosw_txq->last_compl = 0; 112 eosw_txq->state = CXGB4_EO_STATE_CLOSED; 113 } 114 115 static void cxgb4_free_eosw_txq(struct net_device *dev, 116 struct sge_eosw_txq *eosw_txq) 117 { 118 spin_lock_bh(&eosw_txq->lock); 119 cxgb4_clean_eosw_txq(dev, eosw_txq); 120 kfree(eosw_txq->desc); 121 spin_unlock_bh(&eosw_txq->lock); 122 tasklet_kill(&eosw_txq->qresume_tsk); 123 } 124 125 static int cxgb4_mqprio_alloc_hw_resources(struct net_device *dev) 126 { 127 struct port_info *pi = netdev2pinfo(dev); 128 struct adapter *adap = netdev2adap(dev); 129 struct sge_ofld_rxq *eorxq; 130 struct sge_eohw_txq *eotxq; 131 int ret, msix = 0; 132 u32 i; 133 134 /* Allocate ETHOFLD hardware queue structures if not done already */ 135 if (!refcount_read(&adap->tc_mqprio->refcnt)) { 136 adap->sge.eohw_rxq = kcalloc(adap->sge.eoqsets, 137 sizeof(struct sge_ofld_rxq), 138 GFP_KERNEL); 139 if (!adap->sge.eohw_rxq) 140 return -ENOMEM; 141 142 adap->sge.eohw_txq = kcalloc(adap->sge.eoqsets, 143 sizeof(struct sge_eohw_txq), 144 GFP_KERNEL); 145 if (!adap->sge.eohw_txq) { 146 kfree(adap->sge.eohw_rxq); 147 return -ENOMEM; 148 } 149 } 150 151 if (!(adap->flags & CXGB4_USING_MSIX)) 152 msix = -((int)adap->sge.intrq.abs_id + 1); 153 154 for (i = 0; i < pi->nqsets; i++) { 155 eorxq = &adap->sge.eohw_rxq[pi->first_qset + i]; 156 eotxq = &adap->sge.eohw_txq[pi->first_qset + i]; 157 158 /* Allocate Rxqs for receiving ETHOFLD Tx completions */ 159 if (msix >= 0) { 160 msix = cxgb4_get_msix_idx_from_bmap(adap); 161 if (msix < 0) { 162 ret = msix; 163 goto out_free_queues; 164 } 165 166 eorxq->msix = &adap->msix_info[msix]; 167 snprintf(eorxq->msix->desc, 168 sizeof(eorxq->msix->desc), 169 "%s-eorxq%d", dev->name, i); 170 } 171 172 init_rspq(adap, &eorxq->rspq, 173 CXGB4_EOHW_RXQ_DEFAULT_INTR_USEC, 174 CXGB4_EOHW_RXQ_DEFAULT_PKT_CNT, 175 CXGB4_EOHW_RXQ_DEFAULT_DESC_NUM, 176 CXGB4_EOHW_RXQ_DEFAULT_DESC_SIZE); 177 178 eorxq->fl.size = CXGB4_EOHW_FLQ_DEFAULT_DESC_NUM; 179 180 ret = t4_sge_alloc_rxq(adap, &eorxq->rspq, false, 181 dev, msix, &eorxq->fl, 182 cxgb4_ethofld_rx_handler, 183 NULL, 0); 184 if (ret) 185 goto out_free_queues; 186 187 /* Allocate ETHOFLD hardware Txqs */ 188 eotxq->q.size = CXGB4_EOHW_TXQ_DEFAULT_DESC_NUM; 189 ret = t4_sge_alloc_ethofld_txq(adap, eotxq, dev, 190 eorxq->rspq.cntxt_id); 191 if (ret) 192 goto out_free_queues; 193 194 /* Allocate IRQs, set IRQ affinity, and start Rx */ 195 if (adap->flags & CXGB4_USING_MSIX) { 196 ret = request_irq(eorxq->msix->vec, t4_sge_intr_msix, 0, 197 eorxq->msix->desc, &eorxq->rspq); 198 if (ret) 199 goto out_free_msix; 200 201 cxgb4_set_msix_aff(adap, eorxq->msix->vec, 202 &eorxq->msix->aff_mask, i); 203 } 204 205 if (adap->flags & CXGB4_FULL_INIT_DONE) 206 cxgb4_enable_rx(adap, &eorxq->rspq); 207 } 208 209 refcount_inc(&adap->tc_mqprio->refcnt); 210 return 0; 211 212 out_free_msix: 213 while (i-- > 0) { 214 eorxq = &adap->sge.eohw_rxq[pi->first_qset + i]; 215 216 if (adap->flags & CXGB4_FULL_INIT_DONE) 217 cxgb4_quiesce_rx(&eorxq->rspq); 218 219 if (adap->flags & CXGB4_USING_MSIX) { 220 cxgb4_clear_msix_aff(eorxq->msix->vec, 221 eorxq->msix->aff_mask); 222 free_irq(eorxq->msix->vec, &eorxq->rspq); 223 } 224 } 225 226 out_free_queues: 227 for (i = 0; i < pi->nqsets; i++) { 228 eorxq = &adap->sge.eohw_rxq[pi->first_qset + i]; 229 eotxq = &adap->sge.eohw_txq[pi->first_qset + i]; 230 231 if (eorxq->rspq.desc) 232 free_rspq_fl(adap, &eorxq->rspq, &eorxq->fl); 233 if (eorxq->msix) 234 cxgb4_free_msix_idx_in_bmap(adap, eorxq->msix->idx); 235 t4_sge_free_ethofld_txq(adap, eotxq); 236 } 237 238 kfree(adap->sge.eohw_txq); 239 kfree(adap->sge.eohw_rxq); 240 241 return ret; 242 } 243 244 static void cxgb4_mqprio_free_hw_resources(struct net_device *dev) 245 { 246 struct port_info *pi = netdev2pinfo(dev); 247 struct adapter *adap = netdev2adap(dev); 248 struct sge_ofld_rxq *eorxq; 249 struct sge_eohw_txq *eotxq; 250 u32 i; 251 252 /* Return if no ETHOFLD structures have been allocated yet */ 253 if (!refcount_read(&adap->tc_mqprio->refcnt)) 254 return; 255 256 /* Return if no hardware queues have been allocated */ 257 if (!adap->sge.eohw_rxq[pi->first_qset].rspq.desc) 258 return; 259 260 for (i = 0; i < pi->nqsets; i++) { 261 eorxq = &adap->sge.eohw_rxq[pi->first_qset + i]; 262 eotxq = &adap->sge.eohw_txq[pi->first_qset + i]; 263 264 /* Device removal path will already disable NAPI 265 * before unregistering netdevice. So, only disable 266 * NAPI if we're not in device removal path 267 */ 268 if (!(adap->flags & CXGB4_SHUTTING_DOWN)) 269 cxgb4_quiesce_rx(&eorxq->rspq); 270 271 if (adap->flags & CXGB4_USING_MSIX) { 272 cxgb4_clear_msix_aff(eorxq->msix->vec, 273 eorxq->msix->aff_mask); 274 free_irq(eorxq->msix->vec, &eorxq->rspq); 275 } 276 277 free_rspq_fl(adap, &eorxq->rspq, &eorxq->fl); 278 t4_sge_free_ethofld_txq(adap, eotxq); 279 } 280 281 /* Free up ETHOFLD structures if there are no users */ 282 if (refcount_dec_and_test(&adap->tc_mqprio->refcnt)) { 283 kfree(adap->sge.eohw_txq); 284 kfree(adap->sge.eohw_rxq); 285 } 286 } 287 288 static int cxgb4_mqprio_alloc_tc(struct net_device *dev, 289 struct tc_mqprio_qopt_offload *mqprio) 290 { 291 struct ch_sched_params p = { 292 .type = SCHED_CLASS_TYPE_PACKET, 293 .u.params.level = SCHED_CLASS_LEVEL_CL_RL, 294 .u.params.mode = SCHED_CLASS_MODE_FLOW, 295 .u.params.rateunit = SCHED_CLASS_RATEUNIT_BITS, 296 .u.params.ratemode = SCHED_CLASS_RATEMODE_ABS, 297 .u.params.class = SCHED_CLS_NONE, 298 .u.params.weight = 0, 299 .u.params.pktsize = dev->mtu, 300 }; 301 struct cxgb4_tc_port_mqprio *tc_port_mqprio; 302 struct port_info *pi = netdev2pinfo(dev); 303 struct adapter *adap = netdev2adap(dev); 304 struct sched_class *e; 305 int ret; 306 u8 i; 307 308 tc_port_mqprio = &adap->tc_mqprio->port_mqprio[pi->port_id]; 309 p.u.params.channel = pi->tx_chan; 310 for (i = 0; i < mqprio->qopt.num_tc; i++) { 311 /* Convert from bytes per second to Kbps */ 312 p.u.params.minrate = div_u64(mqprio->min_rate[i] * 8, 1000); 313 p.u.params.maxrate = div_u64(mqprio->max_rate[i] * 8, 1000); 314 315 e = cxgb4_sched_class_alloc(dev, &p); 316 if (!e) { 317 ret = -ENOMEM; 318 goto out_err; 319 } 320 321 tc_port_mqprio->tc_hwtc_map[i] = e->idx; 322 } 323 324 return 0; 325 326 out_err: 327 while (i--) 328 cxgb4_sched_class_free(dev, tc_port_mqprio->tc_hwtc_map[i]); 329 330 return ret; 331 } 332 333 static void cxgb4_mqprio_free_tc(struct net_device *dev) 334 { 335 struct cxgb4_tc_port_mqprio *tc_port_mqprio; 336 struct port_info *pi = netdev2pinfo(dev); 337 struct adapter *adap = netdev2adap(dev); 338 u8 i; 339 340 tc_port_mqprio = &adap->tc_mqprio->port_mqprio[pi->port_id]; 341 for (i = 0; i < tc_port_mqprio->mqprio.qopt.num_tc; i++) 342 cxgb4_sched_class_free(dev, tc_port_mqprio->tc_hwtc_map[i]); 343 } 344 345 static int cxgb4_mqprio_class_bind(struct net_device *dev, 346 struct sge_eosw_txq *eosw_txq, 347 u8 tc) 348 { 349 struct ch_sched_flowc fe; 350 int ret; 351 352 init_completion(&eosw_txq->completion); 353 354 fe.tid = eosw_txq->eotid; 355 fe.class = tc; 356 357 ret = cxgb4_sched_class_bind(dev, &fe, SCHED_FLOWC); 358 if (ret) 359 return ret; 360 361 ret = wait_for_completion_timeout(&eosw_txq->completion, 362 CXGB4_FLOWC_WAIT_TIMEOUT); 363 if (!ret) 364 return -ETIMEDOUT; 365 366 return 0; 367 } 368 369 static void cxgb4_mqprio_class_unbind(struct net_device *dev, 370 struct sge_eosw_txq *eosw_txq, 371 u8 tc) 372 { 373 struct adapter *adap = netdev2adap(dev); 374 struct ch_sched_flowc fe; 375 376 /* If we're shutting down, interrupts are disabled and no completions 377 * come back. So, skip waiting for completions in this scenario. 378 */ 379 if (!(adap->flags & CXGB4_SHUTTING_DOWN)) 380 init_completion(&eosw_txq->completion); 381 382 fe.tid = eosw_txq->eotid; 383 fe.class = tc; 384 cxgb4_sched_class_unbind(dev, &fe, SCHED_FLOWC); 385 386 if (!(adap->flags & CXGB4_SHUTTING_DOWN)) 387 wait_for_completion_timeout(&eosw_txq->completion, 388 CXGB4_FLOWC_WAIT_TIMEOUT); 389 } 390 391 static int cxgb4_mqprio_enable_offload(struct net_device *dev, 392 struct tc_mqprio_qopt_offload *mqprio) 393 { 394 struct cxgb4_tc_port_mqprio *tc_port_mqprio; 395 u32 qoffset, qcount, tot_qcount, qid, hwqid; 396 struct port_info *pi = netdev2pinfo(dev); 397 struct adapter *adap = netdev2adap(dev); 398 struct sge_eosw_txq *eosw_txq; 399 int eotid, ret; 400 u16 i, j; 401 u8 hwtc; 402 403 ret = cxgb4_mqprio_alloc_hw_resources(dev); 404 if (ret) 405 return -ENOMEM; 406 407 tc_port_mqprio = &adap->tc_mqprio->port_mqprio[pi->port_id]; 408 for (i = 0; i < mqprio->qopt.num_tc; i++) { 409 qoffset = mqprio->qopt.offset[i]; 410 qcount = mqprio->qopt.count[i]; 411 for (j = 0; j < qcount; j++) { 412 eotid = cxgb4_get_free_eotid(&adap->tids); 413 if (eotid < 0) { 414 ret = -ENOMEM; 415 goto out_free_eotids; 416 } 417 418 qid = qoffset + j; 419 hwqid = pi->first_qset + (eotid % pi->nqsets); 420 eosw_txq = &tc_port_mqprio->eosw_txq[qid]; 421 ret = cxgb4_init_eosw_txq(dev, eosw_txq, 422 eotid, hwqid); 423 if (ret) 424 goto out_free_eotids; 425 426 cxgb4_alloc_eotid(&adap->tids, eotid, eosw_txq); 427 428 hwtc = tc_port_mqprio->tc_hwtc_map[i]; 429 ret = cxgb4_mqprio_class_bind(dev, eosw_txq, hwtc); 430 if (ret) 431 goto out_free_eotids; 432 } 433 } 434 435 memcpy(&tc_port_mqprio->mqprio, mqprio, 436 sizeof(struct tc_mqprio_qopt_offload)); 437 438 /* Inform the stack about the configured tc params. 439 * 440 * Set the correct queue map. If no queue count has been 441 * specified, then send the traffic through default NIC 442 * queues; instead of ETHOFLD queues. 443 */ 444 ret = netdev_set_num_tc(dev, mqprio->qopt.num_tc); 445 if (ret) 446 goto out_free_eotids; 447 448 tot_qcount = pi->nqsets; 449 for (i = 0; i < mqprio->qopt.num_tc; i++) { 450 qcount = mqprio->qopt.count[i]; 451 if (qcount) { 452 qoffset = mqprio->qopt.offset[i] + pi->nqsets; 453 } else { 454 qcount = pi->nqsets; 455 qoffset = 0; 456 } 457 458 ret = netdev_set_tc_queue(dev, i, qcount, qoffset); 459 if (ret) 460 goto out_reset_tc; 461 462 tot_qcount += mqprio->qopt.count[i]; 463 } 464 465 ret = netif_set_real_num_tx_queues(dev, tot_qcount); 466 if (ret) 467 goto out_reset_tc; 468 469 tc_port_mqprio->state = CXGB4_MQPRIO_STATE_ACTIVE; 470 return 0; 471 472 out_reset_tc: 473 netdev_reset_tc(dev); 474 i = mqprio->qopt.num_tc; 475 476 out_free_eotids: 477 while (i-- > 0) { 478 qoffset = mqprio->qopt.offset[i]; 479 qcount = mqprio->qopt.count[i]; 480 for (j = 0; j < qcount; j++) { 481 eosw_txq = &tc_port_mqprio->eosw_txq[qoffset + j]; 482 483 hwtc = tc_port_mqprio->tc_hwtc_map[i]; 484 cxgb4_mqprio_class_unbind(dev, eosw_txq, hwtc); 485 486 cxgb4_free_eotid(&adap->tids, eosw_txq->eotid); 487 cxgb4_free_eosw_txq(dev, eosw_txq); 488 } 489 } 490 491 cxgb4_mqprio_free_hw_resources(dev); 492 return ret; 493 } 494 495 static void cxgb4_mqprio_disable_offload(struct net_device *dev) 496 { 497 struct cxgb4_tc_port_mqprio *tc_port_mqprio; 498 struct port_info *pi = netdev2pinfo(dev); 499 struct adapter *adap = netdev2adap(dev); 500 struct sge_eosw_txq *eosw_txq; 501 u32 qoffset, qcount; 502 u16 i, j; 503 u8 hwtc; 504 505 tc_port_mqprio = &adap->tc_mqprio->port_mqprio[pi->port_id]; 506 if (tc_port_mqprio->state != CXGB4_MQPRIO_STATE_ACTIVE) 507 return; 508 509 netdev_reset_tc(dev); 510 netif_set_real_num_tx_queues(dev, pi->nqsets); 511 512 for (i = 0; i < tc_port_mqprio->mqprio.qopt.num_tc; i++) { 513 qoffset = tc_port_mqprio->mqprio.qopt.offset[i]; 514 qcount = tc_port_mqprio->mqprio.qopt.count[i]; 515 for (j = 0; j < qcount; j++) { 516 eosw_txq = &tc_port_mqprio->eosw_txq[qoffset + j]; 517 518 hwtc = tc_port_mqprio->tc_hwtc_map[i]; 519 cxgb4_mqprio_class_unbind(dev, eosw_txq, hwtc); 520 521 cxgb4_free_eotid(&adap->tids, eosw_txq->eotid); 522 cxgb4_free_eosw_txq(dev, eosw_txq); 523 } 524 } 525 526 cxgb4_mqprio_free_hw_resources(dev); 527 528 /* Free up the traffic classes */ 529 cxgb4_mqprio_free_tc(dev); 530 531 memset(&tc_port_mqprio->mqprio, 0, 532 sizeof(struct tc_mqprio_qopt_offload)); 533 534 tc_port_mqprio->state = CXGB4_MQPRIO_STATE_DISABLED; 535 } 536 537 int cxgb4_setup_tc_mqprio(struct net_device *dev, 538 struct tc_mqprio_qopt_offload *mqprio) 539 { 540 bool needs_bring_up = false; 541 int ret; 542 543 ret = cxgb4_mqprio_validate(dev, mqprio); 544 if (ret) 545 return ret; 546 547 /* To configure tc params, the current allocated EOTIDs must 548 * be freed up. However, they can't be freed up if there's 549 * traffic running on the interface. So, ensure interface is 550 * down before configuring tc params. 551 */ 552 if (netif_running(dev)) { 553 cxgb_close(dev); 554 needs_bring_up = true; 555 } 556 557 cxgb4_mqprio_disable_offload(dev); 558 559 /* If requested for clear, then just return since resources are 560 * already freed up by now. 561 */ 562 if (!mqprio->qopt.num_tc) 563 goto out; 564 565 /* Allocate free available traffic classes and configure 566 * their rate parameters. 567 */ 568 ret = cxgb4_mqprio_alloc_tc(dev, mqprio); 569 if (ret) 570 goto out; 571 572 ret = cxgb4_mqprio_enable_offload(dev, mqprio); 573 if (ret) { 574 cxgb4_mqprio_free_tc(dev); 575 goto out; 576 } 577 578 out: 579 if (needs_bring_up) 580 cxgb_open(dev); 581 582 return ret; 583 } 584 585 int cxgb4_init_tc_mqprio(struct adapter *adap) 586 { 587 struct cxgb4_tc_port_mqprio *tc_port_mqprio, *port_mqprio; 588 struct cxgb4_tc_mqprio *tc_mqprio; 589 struct sge_eosw_txq *eosw_txq; 590 int ret = 0; 591 u8 i; 592 593 tc_mqprio = kzalloc(sizeof(*tc_mqprio), GFP_KERNEL); 594 if (!tc_mqprio) 595 return -ENOMEM; 596 597 tc_port_mqprio = kcalloc(adap->params.nports, sizeof(*tc_port_mqprio), 598 GFP_KERNEL); 599 if (!tc_port_mqprio) { 600 ret = -ENOMEM; 601 goto out_free_mqprio; 602 } 603 604 tc_mqprio->port_mqprio = tc_port_mqprio; 605 for (i = 0; i < adap->params.nports; i++) { 606 port_mqprio = &tc_mqprio->port_mqprio[i]; 607 eosw_txq = kcalloc(adap->tids.neotids, sizeof(*eosw_txq), 608 GFP_KERNEL); 609 if (!eosw_txq) { 610 ret = -ENOMEM; 611 goto out_free_ports; 612 } 613 port_mqprio->eosw_txq = eosw_txq; 614 } 615 616 adap->tc_mqprio = tc_mqprio; 617 refcount_set(&adap->tc_mqprio->refcnt, 0); 618 return 0; 619 620 out_free_ports: 621 for (i = 0; i < adap->params.nports; i++) { 622 port_mqprio = &tc_mqprio->port_mqprio[i]; 623 kfree(port_mqprio->eosw_txq); 624 } 625 kfree(tc_port_mqprio); 626 627 out_free_mqprio: 628 kfree(tc_mqprio); 629 return ret; 630 } 631 632 void cxgb4_cleanup_tc_mqprio(struct adapter *adap) 633 { 634 struct cxgb4_tc_port_mqprio *port_mqprio; 635 u8 i; 636 637 if (adap->tc_mqprio) { 638 if (adap->tc_mqprio->port_mqprio) { 639 for (i = 0; i < adap->params.nports; i++) { 640 struct net_device *dev = adap->port[i]; 641 642 if (dev) 643 cxgb4_mqprio_disable_offload(dev); 644 port_mqprio = &adap->tc_mqprio->port_mqprio[i]; 645 kfree(port_mqprio->eosw_txq); 646 } 647 kfree(adap->tc_mqprio->port_mqprio); 648 } 649 kfree(adap->tc_mqprio); 650 } 651 } 652