1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (C) 2013 Emulex 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright notice, 11 * this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Emulex Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived from 19 * this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 * 33 * Contact Information: 34 * freebsd-drivers@emulex.com 35 * 36 * Emulex 37 * 3333 Susan Street 38 * Costa Mesa, CA 92626 39 */ 40 41 /* $FreeBSD$ */ 42 43 #include "oce_if.h" 44 45 /***************************************************** 46 * local queue functions 47 *****************************************************/ 48 49 static struct oce_wq *oce_wq_init(POCE_SOFTC sc, 50 uint32_t q_len, uint32_t wq_type); 51 static int oce_wq_create(struct oce_wq *wq, struct oce_eq *eq); 52 static void oce_wq_free(struct oce_wq *wq); 53 static void oce_wq_del(struct oce_wq *wq); 54 static struct oce_rq *oce_rq_init(POCE_SOFTC sc, 55 uint32_t q_len, 56 uint32_t frag_size, 57 uint32_t mtu, uint32_t rss); 58 static int oce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq); 59 static void oce_rq_free(struct oce_rq *rq); 60 static void oce_rq_del(struct oce_rq *rq); 61 static struct oce_eq *oce_eq_create(POCE_SOFTC sc, 62 uint32_t q_len, 63 uint32_t item_size, 64 uint32_t eq_delay, 65 uint32_t vector); 66 static void oce_eq_del(struct oce_eq *eq); 67 static struct oce_mq *oce_mq_create(POCE_SOFTC sc, 68 struct oce_eq *eq, uint32_t q_len); 69 static void oce_mq_free(struct oce_mq *mq); 70 static int oce_destroy_q(POCE_SOFTC sc, struct oce_mbx 71 *mbx, size_t req_size, enum qtype qtype, int version); 72 struct oce_cq *oce_cq_create(POCE_SOFTC sc, 73 struct oce_eq *eq, 74 uint32_t q_len, 75 uint32_t item_size, 76 uint32_t sol_event, 77 uint32_t is_eventable, 78 uint32_t nodelay, uint32_t ncoalesce); 79 static void oce_cq_del(POCE_SOFTC sc, struct oce_cq *cq); 80 81 82 83 /** 84 * @brief Create and initialize all the queues on the board 85 * @param sc software handle to the device 86 * @returns 0 if successful, or error 87 **/ 88 int 89 oce_queue_init_all(POCE_SOFTC sc) 90 { 91 int rc = 0, i, vector; 92 struct oce_wq *wq; 93 struct oce_rq *rq; 94 struct oce_aic_obj *aic; 95 96 /* alloc TX/RX queues */ 97 for_all_wq_queues(sc, wq, i) { 98 sc->wq[i] = oce_wq_init(sc, sc->tx_ring_size, 99 NIC_WQ_TYPE_STANDARD); 100 if (!sc->wq[i]) 101 goto error; 102 103 } 104 105 for_all_rq_queues(sc, rq, i) { 106 sc->rq[i] = oce_rq_init(sc, sc->rx_ring_size, sc->rq_frag_size, 107 OCE_MAX_JUMBO_FRAME_SIZE, 108 (i == 0) ? 0 : is_rss_enabled(sc)); 109 if (!sc->rq[i]) 110 goto error; 111 } 112 113 /* Create network interface on card */ 114 if (oce_create_nw_interface(sc)) 115 goto error; 116 117 /* create all of the event queues */ 118 for (vector = 0; vector < sc->intr_count; vector++) { 119 /* setup aic defaults for each event queue */ 120 aic = &sc->aic_obj[vector]; 121 aic->max_eqd = OCE_MAX_EQD; 122 aic->min_eqd = OCE_MIN_EQD; 123 aic->et_eqd = OCE_MIN_EQD; 124 aic->enable = TRUE; 125 126 sc->eq[vector] = oce_eq_create(sc, sc->enable_hwlro ? EQ_LEN_2048 : EQ_LEN_1024, 127 EQE_SIZE_4,0, vector); 128 129 if (!sc->eq[vector]) 130 goto error; 131 } 132 133 /* create Tx, Rx and mcc queues */ 134 for_all_wq_queues(sc, wq, i) { 135 rc = oce_wq_create(wq, sc->eq[i]); 136 if (rc) 137 goto error; 138 wq->queue_index = i; 139 TASK_INIT(&wq->txtask, 1, oce_tx_task, wq); 140 } 141 142 for_all_rq_queues(sc, rq, i) { 143 rc = oce_rq_create(rq, sc->if_id, 144 sc->eq[(i == 0) ? 0:(i-1)]); 145 if (rc) 146 goto error; 147 rq->queue_index = i; 148 } 149 150 sc->mq = oce_mq_create(sc, sc->eq[0], 64); 151 if (!sc->mq) 152 goto error; 153 154 return rc; 155 156 error: 157 oce_queue_release_all(sc); 158 return 1; 159 } 160 161 162 163 /** 164 * @brief Releases all mailbox queues created 165 * @param sc software handle to the device 166 */ 167 void 168 oce_queue_release_all(POCE_SOFTC sc) 169 { 170 int i = 0; 171 struct oce_wq *wq; 172 struct oce_rq *rq; 173 struct oce_eq *eq; 174 175 /* before deleting lro queues, we have to disable hwlro */ 176 if(sc->enable_hwlro) 177 oce_mbox_nic_set_iface_lro_config(sc, 0); 178 179 for_all_rq_queues(sc, rq, i) { 180 if (rq) { 181 oce_rq_del(sc->rq[i]); 182 oce_rq_free(sc->rq[i]); 183 } 184 } 185 186 for_all_wq_queues(sc, wq, i) { 187 if (wq) { 188 oce_wq_del(sc->wq[i]); 189 oce_wq_free(sc->wq[i]); 190 } 191 } 192 193 if (sc->mq) 194 oce_mq_free(sc->mq); 195 196 for_all_evnt_queues(sc, eq, i) { 197 if (eq) 198 oce_eq_del(sc->eq[i]); 199 } 200 } 201 202 203 204 /** 205 * @brief Function to create a WQ for NIC Tx 206 * @param sc software handle to the device 207 * @param qlen number of entries in the queue 208 * @param wq_type work queue type 209 * @returns the pointer to the WQ created or NULL on failure 210 */ 211 static struct 212 oce_wq *oce_wq_init(POCE_SOFTC sc, uint32_t q_len, uint32_t wq_type) 213 { 214 struct oce_wq *wq; 215 int rc = 0, i; 216 217 /* q_len must be min 256 and max 2k */ 218 if (q_len < 256 || q_len > 2048) { 219 device_printf(sc->dev, 220 "Invalid q length. Must be " 221 "[256, 2000]: 0x%x\n", q_len); 222 return NULL; 223 } 224 225 /* allocate wq */ 226 wq = malloc(sizeof(struct oce_wq), M_DEVBUF, M_NOWAIT | M_ZERO); 227 if (!wq) 228 return NULL; 229 230 /* Set the wq config */ 231 wq->cfg.q_len = q_len; 232 wq->cfg.wq_type = (uint8_t) wq_type; 233 wq->cfg.eqd = OCE_DEFAULT_WQ_EQD; 234 wq->cfg.nbufs = 2 * wq->cfg.q_len; 235 wq->cfg.nhdl = 2 * wq->cfg.q_len; 236 237 wq->parent = (void *)sc; 238 239 rc = bus_dma_tag_create(bus_get_dma_tag(sc->dev), 240 1, 0, 241 BUS_SPACE_MAXADDR, 242 BUS_SPACE_MAXADDR, 243 NULL, NULL, 244 OCE_MAX_TX_SIZE, 245 OCE_MAX_TX_ELEMENTS, 246 PAGE_SIZE, 0, NULL, NULL, &wq->tag); 247 248 if (rc) 249 goto free_wq; 250 251 252 for (i = 0; i < OCE_WQ_PACKET_ARRAY_SIZE; i++) { 253 rc = bus_dmamap_create(wq->tag, 0, &wq->pckts[i].map); 254 if (rc) 255 goto free_wq; 256 } 257 258 wq->ring = oce_create_ring_buffer(sc, q_len, NIC_WQE_SIZE); 259 if (!wq->ring) 260 goto free_wq; 261 262 263 LOCK_CREATE(&wq->tx_lock, "TX_lock"); 264 LOCK_CREATE(&wq->tx_compl_lock, "WQ_HANDLER_LOCK"); 265 266 #if __FreeBSD_version >= 800000 267 /* Allocate buf ring for multiqueue*/ 268 wq->br = buf_ring_alloc(4096, M_DEVBUF, 269 M_WAITOK, &wq->tx_lock.mutex); 270 if (!wq->br) 271 goto free_wq; 272 #endif 273 return wq; 274 275 276 free_wq: 277 device_printf(sc->dev, "Create WQ failed\n"); 278 oce_wq_free(wq); 279 return NULL; 280 } 281 282 283 284 /** 285 * @brief Frees the work queue 286 * @param wq pointer to work queue to free 287 */ 288 static void 289 oce_wq_free(struct oce_wq *wq) 290 { 291 POCE_SOFTC sc = (POCE_SOFTC) wq->parent; 292 int i; 293 294 taskqueue_drain(taskqueue_swi, &wq->txtask); 295 296 if (wq->ring != NULL) { 297 oce_destroy_ring_buffer(sc, wq->ring); 298 wq->ring = NULL; 299 } 300 301 for (i = 0; i < OCE_WQ_PACKET_ARRAY_SIZE; i++) { 302 if (wq->pckts[i].map != NULL) { 303 bus_dmamap_unload(wq->tag, wq->pckts[i].map); 304 bus_dmamap_destroy(wq->tag, wq->pckts[i].map); 305 wq->pckts[i].map = NULL; 306 } 307 } 308 309 if (wq->tag != NULL) 310 bus_dma_tag_destroy(wq->tag); 311 if (wq->br != NULL) 312 buf_ring_free(wq->br, M_DEVBUF); 313 314 LOCK_DESTROY(&wq->tx_lock); 315 LOCK_DESTROY(&wq->tx_compl_lock); 316 free(wq, M_DEVBUF); 317 } 318 319 320 321 /** 322 * @brief Create a work queue 323 * @param wq pointer to work queue 324 * @param eq pointer to associated event queue 325 */ 326 static int 327 oce_wq_create(struct oce_wq *wq, struct oce_eq *eq) 328 { 329 POCE_SOFTC sc = wq->parent; 330 struct oce_cq *cq; 331 int rc = 0; 332 333 /* create the CQ */ 334 cq = oce_cq_create(sc, 335 eq, 336 CQ_LEN_1024, 337 sizeof(struct oce_nic_tx_cqe), 0, 1, 0, 3); 338 if (!cq) 339 return ENXIO; 340 341 342 wq->cq = cq; 343 344 rc = oce_mbox_create_wq(wq); 345 if (rc) 346 goto error; 347 348 wq->qstate = QCREATED; 349 wq->wq_free = wq->cfg.q_len; 350 wq->ring->cidx = 0; 351 wq->ring->pidx = 0; 352 353 eq->cq[eq->cq_valid] = cq; 354 eq->cq_valid++; 355 cq->cb_arg = wq; 356 cq->cq_handler = oce_wq_handler; 357 358 return 0; 359 360 error: 361 device_printf(sc->dev, "WQ create failed\n"); 362 oce_wq_del(wq); 363 return rc; 364 } 365 366 367 368 369 /** 370 * @brief Delete a work queue 371 * @param wq pointer to work queue 372 */ 373 static void 374 oce_wq_del(struct oce_wq *wq) 375 { 376 struct oce_mbx mbx; 377 struct mbx_delete_nic_wq *fwcmd; 378 POCE_SOFTC sc = (POCE_SOFTC) wq->parent; 379 380 if (wq->qstate == QCREATED) { 381 bzero(&mbx, sizeof(struct oce_mbx)); 382 /* now fill the command */ 383 fwcmd = (struct mbx_delete_nic_wq *)&mbx.payload; 384 fwcmd->params.req.wq_id = wq->wq_id; 385 (void)oce_destroy_q(sc, &mbx, 386 sizeof(struct mbx_delete_nic_wq), QTYPE_WQ, 0); 387 wq->qstate = QDELETED; 388 } 389 390 if (wq->cq != NULL) { 391 oce_cq_del(sc, wq->cq); 392 wq->cq = NULL; 393 } 394 } 395 396 397 398 /** 399 * @brief function to allocate receive queue resources 400 * @param sc software handle to the device 401 * @param q_len length of receive queue 402 * @param frag_size size of an receive queue fragment 403 * @param mtu maximum transmission unit 404 * @param rss is-rss-queue flag 405 * @returns the pointer to the RQ created or NULL on failure 406 */ 407 static struct 408 oce_rq *oce_rq_init(POCE_SOFTC sc, 409 uint32_t q_len, 410 uint32_t frag_size, 411 uint32_t mtu, uint32_t rss) 412 { 413 struct oce_rq *rq; 414 int rc = 0, i; 415 416 if (OCE_LOG2(frag_size) <= 0) 417 return NULL; 418 419 if ((q_len == 0) || (q_len > 1024)) 420 return NULL; 421 422 /* allocate the rq */ 423 rq = malloc(sizeof(struct oce_rq), M_DEVBUF, M_NOWAIT | M_ZERO); 424 if (!rq) 425 return NULL; 426 427 428 rq->cfg.q_len = q_len; 429 rq->cfg.frag_size = frag_size; 430 rq->cfg.mtu = mtu; 431 rq->cfg.eqd = 0; 432 rq->lro_pkts_queued = 0; 433 rq->cfg.is_rss_queue = rss; 434 rq->pending = 0; 435 436 rq->parent = (void *)sc; 437 438 rc = bus_dma_tag_create(bus_get_dma_tag(sc->dev), 439 1, 0, 440 BUS_SPACE_MAXADDR, 441 BUS_SPACE_MAXADDR, 442 NULL, NULL, 443 oce_rq_buf_size, 444 1, oce_rq_buf_size, 0, NULL, NULL, &rq->tag); 445 if (rc) 446 goto free_rq; 447 448 for (i = 0; i < OCE_RQ_PACKET_ARRAY_SIZE; i++) { 449 rc = bus_dmamap_create(rq->tag, 0, &rq->pckts[i].map); 450 if (rc) 451 goto free_rq; 452 } 453 454 /* create the ring buffer */ 455 rq->ring = oce_create_ring_buffer(sc, q_len, 456 sizeof(struct oce_nic_rqe)); 457 if (!rq->ring) 458 goto free_rq; 459 460 LOCK_CREATE(&rq->rx_lock, "RX_lock"); 461 462 return rq; 463 464 free_rq: 465 device_printf(sc->dev, "Create RQ failed\n"); 466 oce_rq_free(rq); 467 return NULL; 468 } 469 470 471 472 473 /** 474 * @brief Free a receive queue 475 * @param rq pointer to receive queue 476 */ 477 static void 478 oce_rq_free(struct oce_rq *rq) 479 { 480 POCE_SOFTC sc = (POCE_SOFTC) rq->parent; 481 int i = 0 ; 482 483 if (rq->ring != NULL) { 484 oce_destroy_ring_buffer(sc, rq->ring); 485 rq->ring = NULL; 486 } 487 for (i = 0; i < OCE_RQ_PACKET_ARRAY_SIZE; i++) { 488 if (rq->pckts[i].map != NULL) { 489 bus_dmamap_unload(rq->tag, rq->pckts[i].map); 490 bus_dmamap_destroy(rq->tag, rq->pckts[i].map); 491 rq->pckts[i].map = NULL; 492 } 493 if (rq->pckts[i].mbuf) { 494 m_free(rq->pckts[i].mbuf); 495 rq->pckts[i].mbuf = NULL; 496 } 497 } 498 499 if (rq->tag != NULL) 500 bus_dma_tag_destroy(rq->tag); 501 502 LOCK_DESTROY(&rq->rx_lock); 503 free(rq, M_DEVBUF); 504 } 505 506 507 508 509 /** 510 * @brief Create a receive queue 511 * @param rq receive queue 512 * @param if_id interface identifier index` 513 * @param eq pointer to event queue 514 */ 515 static int 516 oce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq) 517 { 518 POCE_SOFTC sc = rq->parent; 519 struct oce_cq *cq; 520 521 cq = oce_cq_create(sc, eq, 522 sc->enable_hwlro ? CQ_LEN_2048 : CQ_LEN_1024, 523 sizeof(struct oce_nic_rx_cqe), 0, 1, 0, 3); 524 525 if (!cq) 526 return ENXIO; 527 528 rq->cq = cq; 529 rq->cfg.if_id = if_id; 530 531 /* Dont create RQ here. Create in if_activate */ 532 rq->qstate = 0; 533 rq->ring->cidx = 0; 534 rq->ring->pidx = 0; 535 eq->cq[eq->cq_valid] = cq; 536 eq->cq_valid++; 537 cq->cb_arg = rq; 538 cq->cq_handler = oce_rq_handler; 539 540 return 0; 541 542 } 543 544 545 546 547 /** 548 * @brief Delete a receive queue 549 * @param rq receive queue 550 */ 551 static void 552 oce_rq_del(struct oce_rq *rq) 553 { 554 POCE_SOFTC sc = (POCE_SOFTC) rq->parent; 555 struct oce_mbx mbx; 556 struct mbx_delete_nic_rq *fwcmd; 557 struct mbx_delete_nic_rq_v1 *fwcmd1; 558 559 if (rq->qstate == QCREATED) { 560 bzero(&mbx, sizeof(mbx)); 561 if(!rq->islro) { 562 fwcmd = (struct mbx_delete_nic_rq *)&mbx.payload; 563 fwcmd->params.req.rq_id = rq->rq_id; 564 (void)oce_destroy_q(sc, &mbx, sizeof(struct mbx_delete_nic_rq), QTYPE_RQ, 0); 565 }else { 566 fwcmd1 = (struct mbx_delete_nic_rq_v1 *)&mbx.payload; 567 fwcmd1->params.req.rq_id = rq->rq_id; 568 fwcmd1->params.req.rq_flags = (NIC_RQ_FLAGS_RSS | NIC_RQ_FLAGS_LRO); 569 (void)oce_destroy_q(sc, &mbx, sizeof(struct mbx_delete_nic_rq_v1), QTYPE_RQ, 1); 570 } 571 rq->qstate = QDELETED; 572 } 573 574 if (rq->cq != NULL) { 575 oce_cq_del(sc, rq->cq); 576 rq->cq = NULL; 577 } 578 } 579 580 581 582 /** 583 * @brief function to create an event queue 584 * @param sc software handle to the device 585 * @param q_len length of event queue 586 * @param item_size size of an event queue item 587 * @param eq_delay event queue delay 588 * @retval eq success, pointer to event queue 589 * @retval NULL failure 590 */ 591 static struct 592 oce_eq *oce_eq_create(POCE_SOFTC sc, uint32_t q_len, 593 uint32_t item_size, 594 uint32_t eq_delay, 595 uint32_t vector) 596 { 597 struct oce_eq *eq; 598 int rc = 0; 599 600 /* allocate an eq */ 601 eq = malloc(sizeof(struct oce_eq), M_DEVBUF, M_NOWAIT | M_ZERO); 602 if (eq == NULL) 603 return NULL; 604 605 eq->parent = (void *)sc; 606 eq->eq_id = 0xffff; 607 eq->ring = oce_create_ring_buffer(sc, q_len, item_size); 608 if (!eq->ring) 609 goto free_eq; 610 611 eq->eq_cfg.q_len = q_len; 612 eq->eq_cfg.item_size = item_size; 613 eq->eq_cfg.cur_eqd = (uint8_t) eq_delay; 614 615 rc = oce_mbox_create_eq(eq); 616 if (rc) 617 goto free_eq; 618 619 sc->intrs[sc->neqs++].eq = eq; 620 621 return eq; 622 623 free_eq: 624 oce_eq_del(eq); 625 return NULL; 626 } 627 628 629 630 631 /** 632 * @brief Function to delete an event queue 633 * @param eq pointer to an event queue 634 */ 635 static void 636 oce_eq_del(struct oce_eq *eq) 637 { 638 struct oce_mbx mbx; 639 struct mbx_destroy_common_eq *fwcmd; 640 POCE_SOFTC sc = (POCE_SOFTC) eq->parent; 641 642 if (eq->eq_id != 0xffff) { 643 bzero(&mbx, sizeof(mbx)); 644 fwcmd = (struct mbx_destroy_common_eq *)&mbx.payload; 645 fwcmd->params.req.id = eq->eq_id; 646 (void)oce_destroy_q(sc, &mbx, 647 sizeof(struct mbx_destroy_common_eq), QTYPE_EQ, 0); 648 } 649 650 if (eq->ring != NULL) { 651 oce_destroy_ring_buffer(sc, eq->ring); 652 eq->ring = NULL; 653 } 654 655 free(eq, M_DEVBUF); 656 657 } 658 659 660 661 662 /** 663 * @brief Function to create an MQ 664 * @param sc software handle to the device 665 * @param eq the EQ to associate with the MQ for event notification 666 * @param q_len the number of entries to create in the MQ 667 * @returns pointer to the created MQ, failure otherwise 668 */ 669 static struct oce_mq * 670 oce_mq_create(POCE_SOFTC sc, struct oce_eq *eq, uint32_t q_len) 671 { 672 struct oce_mbx mbx; 673 struct mbx_create_common_mq_ex *fwcmd = NULL; 674 struct oce_mq *mq = NULL; 675 int rc = 0; 676 struct oce_cq *cq; 677 oce_mq_ext_ctx_t *ctx; 678 uint32_t num_pages; 679 uint32_t page_size; 680 int version; 681 682 cq = oce_cq_create(sc, eq, CQ_LEN_256, 683 sizeof(struct oce_mq_cqe), 1, 1, 0, 0); 684 if (!cq) 685 return NULL; 686 687 /* allocate the mq */ 688 mq = malloc(sizeof(struct oce_mq), M_DEVBUF, M_NOWAIT | M_ZERO); 689 if (!mq) { 690 oce_cq_del(sc, cq); 691 goto error; 692 } 693 694 mq->parent = sc; 695 696 mq->ring = oce_create_ring_buffer(sc, q_len, sizeof(struct oce_mbx)); 697 if (!mq->ring) 698 goto error; 699 700 bzero(&mbx, sizeof(struct oce_mbx)); 701 702 IS_XE201(sc) ? (version = OCE_MBX_VER_V1) : (version = OCE_MBX_VER_V0); 703 fwcmd = (struct mbx_create_common_mq_ex *)&mbx.payload; 704 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 705 MBX_SUBSYSTEM_COMMON, 706 OPCODE_COMMON_CREATE_MQ_EXT, 707 MBX_TIMEOUT_SEC, 708 sizeof(struct mbx_create_common_mq_ex), 709 version); 710 711 num_pages = oce_page_list(mq->ring, &fwcmd->params.req.pages[0]); 712 page_size = mq->ring->num_items * mq->ring->item_size; 713 714 ctx = &fwcmd->params.req.context; 715 716 if (IS_XE201(sc)) { 717 ctx->v1.num_pages = num_pages; 718 ctx->v1.ring_size = OCE_LOG2(q_len) + 1; 719 ctx->v1.cq_id = cq->cq_id; 720 ctx->v1.valid = 1; 721 ctx->v1.async_cq_id = cq->cq_id; 722 ctx->v1.async_cq_valid = 1; 723 /* Subscribe to Link State and Group 5 Events(bits 1 & 5 set) */ 724 ctx->v1.async_evt_bitmap |= LE_32(0x00000022); 725 ctx->v1.async_evt_bitmap |= LE_32(1 << ASYNC_EVENT_CODE_DEBUG); 726 ctx->v1.async_evt_bitmap |= 727 LE_32(1 << ASYNC_EVENT_CODE_SLIPORT); 728 } 729 else { 730 ctx->v0.num_pages = num_pages; 731 ctx->v0.cq_id = cq->cq_id; 732 ctx->v0.ring_size = OCE_LOG2(q_len) + 1; 733 ctx->v0.valid = 1; 734 /* Subscribe to Link State and Group5 Events(bits 1 & 5 set) */ 735 ctx->v0.async_evt_bitmap = 0xffffffff; 736 } 737 738 mbx.u0.s.embedded = 1; 739 mbx.payload_length = sizeof(struct mbx_create_common_mq_ex); 740 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 741 742 rc = oce_mbox_post(sc, &mbx, NULL); 743 if (!rc) 744 rc = fwcmd->hdr.u0.rsp.status; 745 if (rc) { 746 device_printf(sc->dev,"%s failed - cmd status: %d\n", 747 __FUNCTION__, rc); 748 goto error; 749 } 750 mq->mq_id = LE_16(fwcmd->params.rsp.mq_id); 751 mq->cq = cq; 752 eq->cq[eq->cq_valid] = cq; 753 eq->cq_valid++; 754 mq->cq->eq = eq; 755 mq->cfg.q_len = (uint8_t) q_len; 756 mq->cfg.eqd = 0; 757 mq->qstate = QCREATED; 758 759 mq->cq->cb_arg = mq; 760 mq->cq->cq_handler = oce_mq_handler; 761 762 return mq; 763 764 error: 765 device_printf(sc->dev, "MQ create failed\n"); 766 oce_mq_free(mq); 767 mq = NULL; 768 return mq; 769 } 770 771 772 773 774 775 /** 776 * @brief Function to free a mailbox queue 777 * @param mq pointer to a mailbox queue 778 */ 779 static void 780 oce_mq_free(struct oce_mq *mq) 781 { 782 POCE_SOFTC sc = (POCE_SOFTC) mq->parent; 783 struct oce_mbx mbx; 784 struct mbx_destroy_common_mq *fwcmd; 785 786 if (!mq) 787 return; 788 789 if (mq->ring != NULL) { 790 oce_destroy_ring_buffer(sc, mq->ring); 791 mq->ring = NULL; 792 if (mq->qstate == QCREATED) { 793 bzero(&mbx, sizeof (struct oce_mbx)); 794 fwcmd = (struct mbx_destroy_common_mq *)&mbx.payload; 795 fwcmd->params.req.id = mq->mq_id; 796 (void) oce_destroy_q(sc, &mbx, 797 sizeof (struct mbx_destroy_common_mq), 798 QTYPE_MQ, 0); 799 } 800 mq->qstate = QDELETED; 801 } 802 803 if (mq->cq != NULL) { 804 oce_cq_del(sc, mq->cq); 805 mq->cq = NULL; 806 } 807 808 free(mq, M_DEVBUF); 809 mq = NULL; 810 } 811 812 813 814 /** 815 * @brief Function to delete a EQ, CQ, MQ, WQ or RQ 816 * @param sc sofware handle to the device 817 * @param mbx mailbox command to send to the fw to delete the queue 818 * (mbx contains the queue information to delete) 819 * @param req_size the size of the mbx payload dependent on the qtype 820 * @param qtype the type of queue i.e. EQ, CQ, MQ, WQ or RQ 821 * @returns 0 on success, failure otherwise 822 */ 823 static int 824 oce_destroy_q(POCE_SOFTC sc, struct oce_mbx *mbx, size_t req_size, 825 enum qtype qtype, int version) 826 { 827 struct mbx_hdr *hdr = (struct mbx_hdr *)&mbx->payload; 828 int opcode; 829 int subsys; 830 int rc = 0; 831 832 switch (qtype) { 833 case QTYPE_EQ: 834 opcode = OPCODE_COMMON_DESTROY_EQ; 835 subsys = MBX_SUBSYSTEM_COMMON; 836 break; 837 case QTYPE_CQ: 838 opcode = OPCODE_COMMON_DESTROY_CQ; 839 subsys = MBX_SUBSYSTEM_COMMON; 840 break; 841 case QTYPE_MQ: 842 opcode = OPCODE_COMMON_DESTROY_MQ; 843 subsys = MBX_SUBSYSTEM_COMMON; 844 break; 845 case QTYPE_WQ: 846 opcode = NIC_DELETE_WQ; 847 subsys = MBX_SUBSYSTEM_NIC; 848 break; 849 case QTYPE_RQ: 850 opcode = NIC_DELETE_RQ; 851 subsys = MBX_SUBSYSTEM_NIC; 852 break; 853 default: 854 return EINVAL; 855 } 856 857 mbx_common_req_hdr_init(hdr, 0, 0, subsys, 858 opcode, MBX_TIMEOUT_SEC, req_size, 859 version); 860 861 mbx->u0.s.embedded = 1; 862 mbx->payload_length = (uint32_t) req_size; 863 DW_SWAP(u32ptr(mbx), mbx->payload_length + OCE_BMBX_RHDR_SZ); 864 865 rc = oce_mbox_post(sc, mbx, NULL); 866 if (!rc) 867 rc = hdr->u0.rsp.status; 868 if (rc) 869 device_printf(sc->dev,"%s failed - cmd status: %d\n", 870 __FUNCTION__, rc); 871 return rc; 872 } 873 874 875 876 /** 877 * @brief Function to create a completion queue 878 * @param sc software handle to the device 879 * @param eq optional eq to be associated with to the cq 880 * @param q_len length of completion queue 881 * @param item_size size of completion queue items 882 * @param sol_event command context event 883 * @param is_eventable event table 884 * @param nodelay no delay flag 885 * @param ncoalesce no coalescence flag 886 * @returns pointer to the cq created, NULL on failure 887 */ 888 struct oce_cq * 889 oce_cq_create(POCE_SOFTC sc, struct oce_eq *eq, 890 uint32_t q_len, 891 uint32_t item_size, 892 uint32_t sol_event, 893 uint32_t is_eventable, 894 uint32_t nodelay, uint32_t ncoalesce) 895 { 896 struct oce_cq *cq = NULL; 897 int rc = 0; 898 899 cq = malloc(sizeof(struct oce_cq), M_DEVBUF, M_NOWAIT | M_ZERO); 900 if (!cq) 901 return NULL; 902 903 cq->ring = oce_create_ring_buffer(sc, q_len, item_size); 904 if (!cq->ring) 905 goto error; 906 907 cq->parent = sc; 908 cq->eq = eq; 909 cq->cq_cfg.q_len = q_len; 910 cq->cq_cfg.item_size = item_size; 911 cq->cq_cfg.nodelay = (uint8_t) nodelay; 912 913 rc = oce_mbox_cq_create(cq, ncoalesce, is_eventable); 914 if (rc) 915 goto error; 916 917 sc->cq[sc->ncqs++] = cq; 918 919 return cq; 920 921 error: 922 device_printf(sc->dev, "CQ create failed\n"); 923 oce_cq_del(sc, cq); 924 return NULL; 925 } 926 927 928 929 /** 930 * @brief Deletes the completion queue 931 * @param sc software handle to the device 932 * @param cq pointer to a completion queue 933 */ 934 static void 935 oce_cq_del(POCE_SOFTC sc, struct oce_cq *cq) 936 { 937 struct oce_mbx mbx; 938 struct mbx_destroy_common_cq *fwcmd; 939 940 if (cq->ring != NULL) { 941 942 bzero(&mbx, sizeof(struct oce_mbx)); 943 /* now fill the command */ 944 fwcmd = (struct mbx_destroy_common_cq *)&mbx.payload; 945 fwcmd->params.req.id = cq->cq_id; 946 (void)oce_destroy_q(sc, &mbx, 947 sizeof(struct mbx_destroy_common_cq), QTYPE_CQ, 0); 948 /*NOW destroy the ring */ 949 oce_destroy_ring_buffer(sc, cq->ring); 950 cq->ring = NULL; 951 } 952 953 free(cq, M_DEVBUF); 954 cq = NULL; 955 } 956 957 958 959 /** 960 * @brief Start a receive queue 961 * @param rq pointer to a receive queue 962 */ 963 int 964 oce_start_rq(struct oce_rq *rq) 965 { 966 POCE_SOFTC sc = (POCE_SOFTC) rq->parent; 967 int rc; 968 969 if(sc->enable_hwlro) 970 rc = oce_alloc_rx_bufs(rq, 960); 971 else 972 rc = oce_alloc_rx_bufs(rq, rq->cfg.q_len - 1); 973 974 if (rc == 0) 975 oce_arm_cq(rq->parent, rq->cq->cq_id, 0, TRUE); 976 977 return rc; 978 } 979 980 981 982 /** 983 * @brief Start a work queue 984 * @param wq pointer to a work queue 985 */ 986 int 987 oce_start_wq(struct oce_wq *wq) 988 { 989 oce_arm_cq(wq->parent, wq->cq->cq_id, 0, TRUE); 990 return 0; 991 } 992 993 994 995 /** 996 * @brief Start a mailbox queue 997 * @param mq pointer to a mailbox queue 998 */ 999 int 1000 oce_start_mq(struct oce_mq *mq) 1001 { 1002 oce_arm_cq(mq->parent, mq->cq->cq_id, 0, TRUE); 1003 return 0; 1004 } 1005 1006 1007 1008 /** 1009 * @brief Function to arm an EQ so that it can generate events 1010 * @param sc software handle to the device 1011 * @param qid id of the EQ returned by the fw at the time of creation 1012 * @param npopped number of EQEs to arm 1013 * @param rearm rearm bit enable/disable 1014 * @param clearint bit to clear the interrupt condition because of which 1015 * EQEs are generated 1016 */ 1017 void 1018 oce_arm_eq(POCE_SOFTC sc, 1019 int16_t qid, int npopped, uint32_t rearm, uint32_t clearint) 1020 { 1021 eq_db_t eq_db = { 0 }; 1022 1023 eq_db.bits.rearm = rearm; 1024 eq_db.bits.event = 1; 1025 eq_db.bits.num_popped = npopped; 1026 eq_db.bits.clrint = clearint; 1027 eq_db.bits.qid = qid; 1028 OCE_WRITE_REG32(sc, db, PD_EQ_DB, eq_db.dw0); 1029 1030 } 1031 1032 1033 1034 1035 /** 1036 * @brief Function to arm a CQ with CQEs 1037 * @param sc software handle to the device 1038 * @param qid id of the CQ returned by the fw at the time of creation 1039 * @param npopped number of CQEs to arm 1040 * @param rearm rearm bit enable/disable 1041 */ 1042 void oce_arm_cq(POCE_SOFTC sc, int16_t qid, int npopped, uint32_t rearm) 1043 { 1044 cq_db_t cq_db = { 0 }; 1045 1046 cq_db.bits.rearm = rearm; 1047 cq_db.bits.num_popped = npopped; 1048 cq_db.bits.event = 0; 1049 cq_db.bits.qid = qid; 1050 OCE_WRITE_REG32(sc, db, PD_CQ_DB, cq_db.dw0); 1051 1052 } 1053 1054 1055 1056 1057 /* 1058 * @brief function to cleanup the eqs used during stop 1059 * @param eq pointer to event queue structure 1060 * @returns the number of EQs processed 1061 */ 1062 void 1063 oce_drain_eq(struct oce_eq *eq) 1064 { 1065 1066 struct oce_eqe *eqe; 1067 uint16_t num_eqe = 0; 1068 POCE_SOFTC sc = eq->parent; 1069 1070 do { 1071 eqe = RING_GET_CONSUMER_ITEM_VA(eq->ring, struct oce_eqe); 1072 if (eqe->evnt == 0) 1073 break; 1074 eqe->evnt = 0; 1075 bus_dmamap_sync(eq->ring->dma.tag, eq->ring->dma.map, 1076 BUS_DMASYNC_POSTWRITE); 1077 num_eqe++; 1078 RING_GET(eq->ring, 1); 1079 1080 } while (TRUE); 1081 1082 oce_arm_eq(sc, eq->eq_id, num_eqe, FALSE, TRUE); 1083 1084 } 1085 1086 1087 1088 void 1089 oce_drain_wq_cq(struct oce_wq *wq) 1090 { 1091 POCE_SOFTC sc = wq->parent; 1092 struct oce_cq *cq = wq->cq; 1093 struct oce_nic_tx_cqe *cqe; 1094 int num_cqes = 0; 1095 1096 bus_dmamap_sync(cq->ring->dma.tag, cq->ring->dma.map, 1097 BUS_DMASYNC_POSTWRITE); 1098 1099 do { 1100 cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_tx_cqe); 1101 if (cqe->u0.dw[3] == 0) 1102 break; 1103 cqe->u0.dw[3] = 0; 1104 bus_dmamap_sync(cq->ring->dma.tag, cq->ring->dma.map, 1105 BUS_DMASYNC_POSTWRITE); 1106 RING_GET(cq->ring, 1); 1107 num_cqes++; 1108 1109 } while (TRUE); 1110 1111 oce_arm_cq(sc, cq->cq_id, num_cqes, FALSE); 1112 1113 } 1114 1115 1116 /* 1117 * @brief function to drain a MCQ and process its CQEs 1118 * @param dev software handle to the device 1119 * @param cq pointer to the cq to drain 1120 * @returns the number of CQEs processed 1121 */ 1122 void 1123 oce_drain_mq_cq(void *arg) 1124 { 1125 /* TODO: additional code. */ 1126 return; 1127 } 1128 1129 1130 1131 /** 1132 * @brief function to process a Recieve queue 1133 * @param arg pointer to the RQ to charge 1134 * @return number of cqes processed 1135 */ 1136 void 1137 oce_drain_rq_cq(struct oce_rq *rq) 1138 { 1139 struct oce_nic_rx_cqe *cqe; 1140 uint16_t num_cqe = 0; 1141 struct oce_cq *cq; 1142 POCE_SOFTC sc; 1143 1144 sc = rq->parent; 1145 cq = rq->cq; 1146 cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_rx_cqe); 1147 /* dequeue till you reach an invalid cqe */ 1148 while (RQ_CQE_VALID(cqe)) { 1149 RQ_CQE_INVALIDATE(cqe); 1150 RING_GET(cq->ring, 1); 1151 cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, 1152 struct oce_nic_rx_cqe); 1153 num_cqe++; 1154 } 1155 oce_arm_cq(sc, cq->cq_id, num_cqe, FALSE); 1156 1157 return; 1158 } 1159 1160 1161 void 1162 oce_free_posted_rxbuf(struct oce_rq *rq) 1163 { 1164 struct oce_packet_desc *pd; 1165 1166 while (rq->pending) { 1167 1168 pd = &rq->pckts[rq->ring->cidx]; 1169 bus_dmamap_sync(rq->tag, pd->map, BUS_DMASYNC_POSTWRITE); 1170 bus_dmamap_unload(rq->tag, pd->map); 1171 if (pd->mbuf != NULL) { 1172 m_freem(pd->mbuf); 1173 pd->mbuf = NULL; 1174 } 1175 1176 RING_GET(rq->ring,1); 1177 rq->pending--; 1178 } 1179 1180 } 1181 1182 void 1183 oce_rx_cq_clean_hwlro(struct oce_rq *rq) 1184 { 1185 struct oce_cq *cq = rq->cq; 1186 POCE_SOFTC sc = rq->parent; 1187 struct nic_hwlro_singleton_cqe *cqe; 1188 struct nic_hwlro_cqe_part2 *cqe2; 1189 int flush_wait = 0; 1190 int flush_compl = 0; 1191 int num_frags = 0; 1192 1193 for (;;) { 1194 bus_dmamap_sync(cq->ring->dma.tag,cq->ring->dma.map, BUS_DMASYNC_POSTWRITE); 1195 cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct nic_hwlro_singleton_cqe); 1196 if(cqe->valid) { 1197 if(cqe->cqe_type == 0) { /* singleton cqe */ 1198 /* we should not get singleton cqe after cqe1 on same rq */ 1199 if(rq->cqe_firstpart != NULL) { 1200 device_printf(sc->dev, "Got singleton cqe after cqe1 \n"); 1201 goto exit_rx_cq_clean_hwlro; 1202 } 1203 num_frags = cqe->pkt_size / rq->cfg.frag_size; 1204 if(cqe->pkt_size % rq->cfg.frag_size) 1205 num_frags++; 1206 oce_discard_rx_comp(rq, num_frags); 1207 /* Check if CQE is flush completion */ 1208 if(!cqe->pkt_size) 1209 flush_compl = 1; 1210 cqe->valid = 0; 1211 RING_GET(cq->ring, 1); 1212 }else if(cqe->cqe_type == 0x1) { /* first part */ 1213 /* we should not get cqe1 after cqe1 on same rq */ 1214 if(rq->cqe_firstpart != NULL) { 1215 device_printf(sc->dev, "Got cqe1 after cqe1 \n"); 1216 goto exit_rx_cq_clean_hwlro; 1217 } 1218 rq->cqe_firstpart = (struct nic_hwlro_cqe_part1 *)cqe; 1219 RING_GET(cq->ring, 1); 1220 }else if(cqe->cqe_type == 0x2) { /* second part */ 1221 cqe2 = (struct nic_hwlro_cqe_part2 *)cqe; 1222 /* We should not get cqe2 without cqe1 */ 1223 if(rq->cqe_firstpart == NULL) { 1224 device_printf(sc->dev, "Got cqe2 without cqe1 \n"); 1225 goto exit_rx_cq_clean_hwlro; 1226 } 1227 num_frags = cqe2->coalesced_size / rq->cfg.frag_size; 1228 if(cqe2->coalesced_size % rq->cfg.frag_size) 1229 num_frags++; 1230 1231 /* Flush completion will always come in singleton CQE */ 1232 oce_discard_rx_comp(rq, num_frags); 1233 1234 rq->cqe_firstpart->valid = 0; 1235 cqe2->valid = 0; 1236 rq->cqe_firstpart = NULL; 1237 RING_GET(cq->ring, 1); 1238 } 1239 oce_arm_cq(sc, cq->cq_id, 1, FALSE); 1240 if(flush_compl) 1241 break; 1242 }else { 1243 if (flush_wait++ > 100) { 1244 device_printf(sc->dev, "did not receive hwlro flush compl\n"); 1245 break; 1246 } 1247 oce_arm_cq(sc, cq->cq_id, 0, TRUE); 1248 DELAY(1000); 1249 } 1250 } 1251 1252 /* After cleanup, leave the CQ in unarmed state */ 1253 oce_arm_cq(sc, cq->cq_id, 0, FALSE); 1254 1255 exit_rx_cq_clean_hwlro: 1256 return; 1257 } 1258 1259 1260 void 1261 oce_rx_cq_clean(struct oce_rq *rq) 1262 { 1263 struct oce_nic_rx_cqe *cqe; 1264 struct oce_cq *cq; 1265 POCE_SOFTC sc; 1266 int flush_wait = 0; 1267 int flush_compl = 0; 1268 sc = rq->parent; 1269 cq = rq->cq; 1270 1271 for (;;) { 1272 bus_dmamap_sync(cq->ring->dma.tag, 1273 cq->ring->dma.map, BUS_DMASYNC_POSTWRITE); 1274 cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_rx_cqe); 1275 if(RQ_CQE_VALID(cqe)) { 1276 DW_SWAP((uint32_t *) cqe, sizeof(oce_rq_cqe)); 1277 oce_discard_rx_comp(rq, cqe->u0.s.num_fragments); 1278 /* Check if CQE is flush completion */ 1279 if((cqe->u0.s.num_fragments==0)&&(cqe->u0.s.pkt_size == 0)&&(cqe->u0.s.error == 0)) 1280 flush_compl = 1; 1281 1282 RQ_CQE_INVALIDATE(cqe); 1283 RING_GET(cq->ring, 1); 1284 #if defined(INET6) || defined(INET) 1285 if (IF_LRO_ENABLED(sc)) 1286 oce_rx_flush_lro(rq); 1287 #endif 1288 oce_arm_cq(sc, cq->cq_id, 1, FALSE); 1289 if(flush_compl) 1290 break; 1291 }else { 1292 if (flush_wait++ > 100) { 1293 device_printf(sc->dev, "did not receive flush compl\n"); 1294 break; 1295 } 1296 oce_arm_cq(sc, cq->cq_id, 0, TRUE); 1297 DELAY(1000); 1298 } 1299 } 1300 1301 /* After cleanup, leave the CQ in unarmed state */ 1302 oce_arm_cq(sc, cq->cq_id, 0, FALSE); 1303 } 1304 1305 void 1306 oce_stop_rx(POCE_SOFTC sc) 1307 { 1308 struct oce_mbx mbx; 1309 struct mbx_delete_nic_rq *fwcmd; 1310 struct mbx_delete_nic_rq_v1 *fwcmd1; 1311 struct oce_rq *rq; 1312 int i = 0; 1313 1314 /* before deleting disable hwlro */ 1315 if(sc->enable_hwlro) 1316 oce_mbox_nic_set_iface_lro_config(sc, 0); 1317 1318 for_all_rq_queues(sc, rq, i) { 1319 if (rq->qstate == QCREATED) { 1320 /* Delete rxq in firmware */ 1321 LOCK(&rq->rx_lock); 1322 1323 bzero(&mbx, sizeof(mbx)); 1324 if(!rq->islro) { 1325 fwcmd = (struct mbx_delete_nic_rq *)&mbx.payload; 1326 fwcmd->params.req.rq_id = rq->rq_id; 1327 (void)oce_destroy_q(sc, &mbx, sizeof(struct mbx_delete_nic_rq), QTYPE_RQ, 0); 1328 }else { 1329 fwcmd1 = (struct mbx_delete_nic_rq_v1 *)&mbx.payload; 1330 fwcmd1->params.req.rq_id = rq->rq_id; 1331 fwcmd1->params.req.rq_flags = (NIC_RQ_FLAGS_RSS | NIC_RQ_FLAGS_LRO); 1332 1333 (void)oce_destroy_q(sc,&mbx,sizeof(struct mbx_delete_nic_rq_v1),QTYPE_RQ,1); 1334 } 1335 rq->qstate = QDELETED; 1336 1337 DELAY(1000); 1338 1339 if(!rq->islro) 1340 oce_rx_cq_clean(rq); 1341 else 1342 oce_rx_cq_clean_hwlro(rq); 1343 1344 /* Free posted RX buffers that are not used */ 1345 oce_free_posted_rxbuf(rq); 1346 UNLOCK(&rq->rx_lock); 1347 } 1348 } 1349 } 1350 1351 1352 1353 int 1354 oce_start_rx(POCE_SOFTC sc) 1355 { 1356 struct oce_rq *rq; 1357 int rc = 0, i; 1358 1359 for_all_rq_queues(sc, rq, i) { 1360 if (rq->qstate == QCREATED) 1361 continue; 1362 if((i == 0) || (!sc->enable_hwlro)) { 1363 rc = oce_mbox_create_rq(rq); 1364 if (rc) 1365 goto error; 1366 rq->islro = 0; 1367 }else { 1368 rc = oce_mbox_create_rq_v2(rq); 1369 if (rc) 1370 goto error; 1371 rq->islro = 1; 1372 } 1373 /* reset queue pointers */ 1374 rq->qstate = QCREATED; 1375 rq->pending = 0; 1376 rq->ring->cidx = 0; 1377 rq->ring->pidx = 0; 1378 } 1379 1380 if(sc->enable_hwlro) { 1381 rc = oce_mbox_nic_set_iface_lro_config(sc, 1); 1382 if (rc) 1383 goto error; 1384 } 1385 1386 DELAY(1); 1387 1388 /* RSS config */ 1389 if (is_rss_enabled(sc)) { 1390 rc = oce_config_nic_rss(sc, (uint8_t) sc->if_id, RSS_ENABLE); 1391 if (rc) 1392 goto error; 1393 1394 } 1395 1396 DELAY(1); 1397 return rc; 1398 error: 1399 device_printf(sc->dev, "Start RX failed\n"); 1400 return rc; 1401 1402 } 1403 1404 1405 1406