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