1 /*- 2 * Copyright (C) 2013 Emulex 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 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 * 3. Neither the name of the Emulex Corporation nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 * 31 * Contact Information: 32 * freebsd-drivers@emulex.com 33 * 34 * Emulex 35 * 3333 Susan Street 36 * Costa Mesa, CA 92626 37 */ 38 39 /* $FreeBSD$ */ 40 41 #include "oce_if.h" 42 extern uint32_t sfp_vpd_dump_buffer[TRANSCEIVER_DATA_NUM_ELE]; 43 44 /** 45 * @brief Reset (firmware) common function 46 * @param sc software handle to the device 47 * @returns 0 on success, ETIMEDOUT on failure 48 */ 49 int 50 oce_reset_fun(POCE_SOFTC sc) 51 { 52 struct oce_mbx *mbx; 53 struct oce_bmbx *mb; 54 struct ioctl_common_function_reset *fwcmd; 55 int rc = 0; 56 57 if (sc->flags & OCE_FLAGS_FUNCRESET_RQD) { 58 mb = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx); 59 mbx = &mb->mbx; 60 bzero(mbx, sizeof(struct oce_mbx)); 61 62 fwcmd = (struct ioctl_common_function_reset *)&mbx->payload; 63 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 64 MBX_SUBSYSTEM_COMMON, 65 OPCODE_COMMON_FUNCTION_RESET, 66 10, /* MBX_TIMEOUT_SEC */ 67 sizeof(struct 68 ioctl_common_function_reset), 69 OCE_MBX_VER_V0); 70 71 mbx->u0.s.embedded = 1; 72 mbx->payload_length = 73 sizeof(struct ioctl_common_function_reset); 74 75 rc = oce_mbox_dispatch(sc, 2); 76 } 77 78 return rc; 79 } 80 81 82 /** 83 * @brief This funtions tells firmware we are 84 * done with commands. 85 * @param sc software handle to the device 86 * @returns 0 on success, ETIMEDOUT on failure 87 */ 88 int 89 oce_fw_clean(POCE_SOFTC sc) 90 { 91 struct oce_bmbx *mbx; 92 uint8_t *ptr; 93 int ret = 0; 94 95 mbx = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx); 96 ptr = (uint8_t *) &mbx->mbx; 97 98 /* Endian Signature */ 99 *ptr++ = 0xff; 100 *ptr++ = 0xaa; 101 *ptr++ = 0xbb; 102 *ptr++ = 0xff; 103 *ptr++ = 0xff; 104 *ptr++ = 0xcc; 105 *ptr++ = 0xdd; 106 *ptr = 0xff; 107 108 ret = oce_mbox_dispatch(sc, 2); 109 110 return ret; 111 } 112 113 114 /** 115 * @brief Mailbox wait 116 * @param sc software handle to the device 117 * @param tmo_sec timeout in seconds 118 */ 119 static int 120 oce_mbox_wait(POCE_SOFTC sc, uint32_t tmo_sec) 121 { 122 tmo_sec *= 10000; 123 pd_mpu_mbox_db_t mbox_db; 124 125 for (;;) { 126 if (tmo_sec != 0) { 127 if (--tmo_sec == 0) 128 break; 129 } 130 131 mbox_db.dw0 = OCE_READ_REG32(sc, db, PD_MPU_MBOX_DB); 132 133 if (mbox_db.bits.ready) 134 return 0; 135 136 DELAY(100); 137 } 138 139 device_printf(sc->dev, "Mailbox timed out\n"); 140 141 return ETIMEDOUT; 142 } 143 144 145 /** 146 * @brief Mailbox dispatch 147 * @param sc software handle to the device 148 * @param tmo_sec timeout in seconds 149 */ 150 int 151 oce_mbox_dispatch(POCE_SOFTC sc, uint32_t tmo_sec) 152 { 153 pd_mpu_mbox_db_t mbox_db; 154 uint32_t pa; 155 int rc; 156 157 oce_dma_sync(&sc->bsmbx, BUS_DMASYNC_PREWRITE); 158 pa = (uint32_t) ((uint64_t) sc->bsmbx.paddr >> 34); 159 bzero(&mbox_db, sizeof(pd_mpu_mbox_db_t)); 160 mbox_db.bits.ready = 0; 161 mbox_db.bits.hi = 1; 162 mbox_db.bits.address = pa; 163 164 rc = oce_mbox_wait(sc, tmo_sec); 165 if (rc == 0) { 166 OCE_WRITE_REG32(sc, db, PD_MPU_MBOX_DB, mbox_db.dw0); 167 168 pa = (uint32_t) ((uint64_t) sc->bsmbx.paddr >> 4) & 0x3fffffff; 169 mbox_db.bits.ready = 0; 170 mbox_db.bits.hi = 0; 171 mbox_db.bits.address = pa; 172 173 rc = oce_mbox_wait(sc, tmo_sec); 174 175 if (rc == 0) { 176 OCE_WRITE_REG32(sc, db, PD_MPU_MBOX_DB, mbox_db.dw0); 177 178 rc = oce_mbox_wait(sc, tmo_sec); 179 180 oce_dma_sync(&sc->bsmbx, BUS_DMASYNC_POSTWRITE); 181 } 182 } 183 184 return rc; 185 } 186 187 188 189 /** 190 * @brief Mailbox common request header initialization 191 * @param hdr mailbox header 192 * @param dom domain 193 * @param port port 194 * @param subsys subsystem 195 * @param opcode opcode 196 * @param timeout timeout 197 * @param pyld_len payload length 198 */ 199 void 200 mbx_common_req_hdr_init(struct mbx_hdr *hdr, 201 uint8_t dom, uint8_t port, 202 uint8_t subsys, uint8_t opcode, 203 uint32_t timeout, uint32_t pyld_len, 204 uint8_t version) 205 { 206 hdr->u0.req.opcode = opcode; 207 hdr->u0.req.subsystem = subsys; 208 hdr->u0.req.port_number = port; 209 hdr->u0.req.domain = dom; 210 211 hdr->u0.req.timeout = timeout; 212 hdr->u0.req.request_length = pyld_len - sizeof(struct mbx_hdr); 213 hdr->u0.req.version = version; 214 } 215 216 217 218 /** 219 * @brief Function to initialize the hw with host endian information 220 * @param sc software handle to the device 221 * @returns 0 on success, ETIMEDOUT on failure 222 */ 223 int 224 oce_mbox_init(POCE_SOFTC sc) 225 { 226 struct oce_bmbx *mbx; 227 uint8_t *ptr; 228 int ret = 0; 229 230 if (sc->flags & OCE_FLAGS_MBOX_ENDIAN_RQD) { 231 mbx = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx); 232 ptr = (uint8_t *) &mbx->mbx; 233 234 /* Endian Signature */ 235 *ptr++ = 0xff; 236 *ptr++ = 0x12; 237 *ptr++ = 0x34; 238 *ptr++ = 0xff; 239 *ptr++ = 0xff; 240 *ptr++ = 0x56; 241 *ptr++ = 0x78; 242 *ptr = 0xff; 243 244 ret = oce_mbox_dispatch(sc, 0); 245 } 246 247 return ret; 248 } 249 250 251 /** 252 * @brief Function to get the firmware version 253 * @param sc software handle to the device 254 * @returns 0 on success, EIO on failure 255 */ 256 int 257 oce_get_fw_version(POCE_SOFTC sc) 258 { 259 struct oce_mbx mbx; 260 struct mbx_get_common_fw_version *fwcmd; 261 int ret = 0; 262 263 bzero(&mbx, sizeof(struct oce_mbx)); 264 265 fwcmd = (struct mbx_get_common_fw_version *)&mbx.payload; 266 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 267 MBX_SUBSYSTEM_COMMON, 268 OPCODE_COMMON_GET_FW_VERSION, 269 MBX_TIMEOUT_SEC, 270 sizeof(struct mbx_get_common_fw_version), 271 OCE_MBX_VER_V0); 272 273 mbx.u0.s.embedded = 1; 274 mbx.payload_length = sizeof(struct mbx_get_common_fw_version); 275 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 276 277 ret = oce_mbox_post(sc, &mbx, NULL); 278 if (!ret) 279 ret = fwcmd->hdr.u0.rsp.status; 280 if (ret) { 281 device_printf(sc->dev, 282 "%s failed - cmd status: %d addi status: %d\n", 283 __FUNCTION__, ret, 284 fwcmd->hdr.u0.rsp.additional_status); 285 goto error; 286 } 287 288 bcopy(fwcmd->params.rsp.fw_ver_str, sc->fw_version, 32); 289 error: 290 return ret; 291 } 292 293 294 /** 295 * @brief Firmware will send gracious notifications during 296 * attach only after sending first mcc commnad. We 297 * use MCC queue only for getting async and mailbox 298 * for sending cmds. So to get gracious notifications 299 * atleast send one dummy command on mcc. 300 */ 301 int 302 oce_first_mcc_cmd(POCE_SOFTC sc) 303 { 304 struct oce_mbx *mbx; 305 struct oce_mq *mq = sc->mq; 306 struct mbx_get_common_fw_version *fwcmd; 307 uint32_t reg_value; 308 309 mbx = RING_GET_PRODUCER_ITEM_VA(mq->ring, struct oce_mbx); 310 bzero(mbx, sizeof(struct oce_mbx)); 311 312 fwcmd = (struct mbx_get_common_fw_version *)&mbx->payload; 313 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 314 MBX_SUBSYSTEM_COMMON, 315 OPCODE_COMMON_GET_FW_VERSION, 316 MBX_TIMEOUT_SEC, 317 sizeof(struct mbx_get_common_fw_version), 318 OCE_MBX_VER_V0); 319 mbx->u0.s.embedded = 1; 320 mbx->payload_length = sizeof(struct mbx_get_common_fw_version); 321 bus_dmamap_sync(mq->ring->dma.tag, mq->ring->dma.map, 322 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 323 RING_PUT(mq->ring, 1); 324 reg_value = (1 << 16) | mq->mq_id; 325 OCE_WRITE_REG32(sc, db, PD_MQ_DB, reg_value); 326 327 return 0; 328 } 329 330 /** 331 * @brief Function to post a MBX to the mbox 332 * @param sc software handle to the device 333 * @param mbx pointer to the MBX to send 334 * @param mbxctx pointer to the mbx context structure 335 * @returns 0 on success, error on failure 336 */ 337 int 338 oce_mbox_post(POCE_SOFTC sc, struct oce_mbx *mbx, struct oce_mbx_ctx *mbxctx) 339 { 340 struct oce_mbx *mb_mbx = NULL; 341 struct oce_mq_cqe *mb_cqe = NULL; 342 struct oce_bmbx *mb = NULL; 343 int rc = 0; 344 uint32_t tmo = 0; 345 uint32_t cstatus = 0; 346 uint32_t xstatus = 0; 347 348 LOCK(&sc->bmbx_lock); 349 350 mb = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx); 351 mb_mbx = &mb->mbx; 352 353 /* get the tmo */ 354 tmo = mbx->tag[0]; 355 mbx->tag[0] = 0; 356 357 /* copy mbx into mbox */ 358 bcopy(mbx, mb_mbx, sizeof(struct oce_mbx)); 359 360 /* now dispatch */ 361 rc = oce_mbox_dispatch(sc, tmo); 362 if (rc == 0) { 363 /* 364 * the command completed successfully. Now get the 365 * completion queue entry 366 */ 367 mb_cqe = &mb->cqe; 368 DW_SWAP(u32ptr(&mb_cqe->u0.dw[0]), sizeof(struct oce_mq_cqe)); 369 370 /* copy mbox mbx back */ 371 bcopy(mb_mbx, mbx, sizeof(struct oce_mbx)); 372 373 /* pick up the mailbox status */ 374 cstatus = mb_cqe->u0.s.completion_status; 375 xstatus = mb_cqe->u0.s.extended_status; 376 377 /* 378 * store the mbx context in the cqe tag section so that 379 * the upper layer handling the cqe can associate the mbx 380 * with the response 381 */ 382 if (cstatus == 0 && mbxctx) { 383 /* save context */ 384 mbxctx->mbx = mb_mbx; 385 bcopy(&mbxctx, mb_cqe->u0.s.mq_tag, 386 sizeof(struct oce_mbx_ctx *)); 387 } 388 } 389 390 UNLOCK(&sc->bmbx_lock); 391 392 return rc; 393 } 394 395 /** 396 * @brief Function to read the mac address associated with an interface 397 * @param sc software handle to the device 398 * @param if_id interface id to read the address from 399 * @param perm set to 1 if reading the factory mac address. 400 * In this case if_id is ignored 401 * @param type type of the mac address, whether network or storage 402 * @param[out] mac [OUTPUT] pointer to a buffer containing the 403 * mac address when the command succeeds. 404 * @returns 0 on success, EIO on failure 405 */ 406 int 407 oce_read_mac_addr(POCE_SOFTC sc, uint32_t if_id, 408 uint8_t perm, uint8_t type, struct mac_address_format *mac) 409 { 410 struct oce_mbx mbx; 411 struct mbx_query_common_iface_mac *fwcmd; 412 int ret = 0; 413 414 bzero(&mbx, sizeof(struct oce_mbx)); 415 416 fwcmd = (struct mbx_query_common_iface_mac *)&mbx.payload; 417 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 418 MBX_SUBSYSTEM_COMMON, 419 OPCODE_COMMON_QUERY_IFACE_MAC, 420 MBX_TIMEOUT_SEC, 421 sizeof(struct mbx_query_common_iface_mac), 422 OCE_MBX_VER_V0); 423 424 fwcmd->params.req.permanent = perm; 425 if (!perm) 426 fwcmd->params.req.if_id = (uint16_t) if_id; 427 else 428 fwcmd->params.req.if_id = 0; 429 430 fwcmd->params.req.type = type; 431 432 mbx.u0.s.embedded = 1; 433 mbx.payload_length = sizeof(struct mbx_query_common_iface_mac); 434 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 435 436 ret = oce_mbox_post(sc, &mbx, NULL); 437 if (!ret) 438 ret = fwcmd->hdr.u0.rsp.status; 439 if (ret) { 440 device_printf(sc->dev, 441 "%s failed - cmd status: %d addi status: %d\n", 442 __FUNCTION__, ret, 443 fwcmd->hdr.u0.rsp.additional_status); 444 goto error; 445 } 446 447 /* copy the mac addres in the output parameter */ 448 mac->size_of_struct = fwcmd->params.rsp.mac.size_of_struct; 449 bcopy(&fwcmd->params.rsp.mac.mac_addr[0], &mac->mac_addr[0], 450 mac->size_of_struct); 451 error: 452 return ret; 453 } 454 455 /** 456 * @brief Function to query the fw attributes from the hw 457 * @param sc software handle to the device 458 * @returns 0 on success, EIO on failure 459 */ 460 int 461 oce_get_fw_config(POCE_SOFTC sc) 462 { 463 struct oce_mbx mbx; 464 struct mbx_common_query_fw_config *fwcmd; 465 int ret = 0; 466 467 bzero(&mbx, sizeof(struct oce_mbx)); 468 469 fwcmd = (struct mbx_common_query_fw_config *)&mbx.payload; 470 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 471 MBX_SUBSYSTEM_COMMON, 472 OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, 473 MBX_TIMEOUT_SEC, 474 sizeof(struct mbx_common_query_fw_config), 475 OCE_MBX_VER_V0); 476 477 mbx.u0.s.embedded = 1; 478 mbx.payload_length = sizeof(struct mbx_common_query_fw_config); 479 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 480 481 ret = oce_mbox_post(sc, &mbx, NULL); 482 if (!ret) 483 ret = fwcmd->hdr.u0.rsp.status; 484 if (ret) { 485 device_printf(sc->dev, 486 "%s failed - cmd status: %d addi status: %d\n", 487 __FUNCTION__, ret, 488 fwcmd->hdr.u0.rsp.additional_status); 489 goto error; 490 } 491 492 DW_SWAP(u32ptr(fwcmd), sizeof(struct mbx_common_query_fw_config)); 493 494 sc->config_number = HOST_32(fwcmd->params.rsp.config_number); 495 sc->asic_revision = HOST_32(fwcmd->params.rsp.asic_revision); 496 sc->port_id = HOST_32(fwcmd->params.rsp.port_id); 497 sc->function_mode = HOST_32(fwcmd->params.rsp.function_mode); 498 if ((sc->function_mode & (ULP_NIC_MODE | ULP_RDMA_MODE)) == 499 (ULP_NIC_MODE | ULP_RDMA_MODE)) { 500 sc->rdma_flags = OCE_RDMA_FLAG_SUPPORTED; 501 } 502 sc->function_caps = HOST_32(fwcmd->params.rsp.function_caps); 503 504 if (fwcmd->params.rsp.ulp[0].ulp_mode & ULP_NIC_MODE) { 505 sc->max_tx_rings = HOST_32(fwcmd->params.rsp.ulp[0].nic_wq_tot); 506 sc->max_rx_rings = HOST_32(fwcmd->params.rsp.ulp[0].lro_rqid_tot); 507 } else { 508 sc->max_tx_rings = HOST_32(fwcmd->params.rsp.ulp[1].nic_wq_tot); 509 sc->max_rx_rings = HOST_32(fwcmd->params.rsp.ulp[1].lro_rqid_tot); 510 } 511 512 error: 513 return ret; 514 515 } 516 517 /** 518 * 519 * @brief function to create a device interface 520 * @param sc software handle to the device 521 * @param cap_flags capability flags 522 * @param en_flags enable capability flags 523 * @param vlan_tag optional vlan tag to associate with the if 524 * @param mac_addr pointer to a buffer containing the mac address 525 * @param[out] if_id [OUTPUT] pointer to an integer to hold the ID of the 526 interface created 527 * @returns 0 on success, EIO on failure 528 */ 529 int 530 oce_if_create(POCE_SOFTC sc, 531 uint32_t cap_flags, 532 uint32_t en_flags, 533 uint16_t vlan_tag, 534 uint8_t *mac_addr, 535 uint32_t *if_id) 536 { 537 struct oce_mbx mbx; 538 struct mbx_create_common_iface *fwcmd; 539 int rc = 0; 540 541 bzero(&mbx, sizeof(struct oce_mbx)); 542 543 fwcmd = (struct mbx_create_common_iface *)&mbx.payload; 544 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 545 MBX_SUBSYSTEM_COMMON, 546 OPCODE_COMMON_CREATE_IFACE, 547 MBX_TIMEOUT_SEC, 548 sizeof(struct mbx_create_common_iface), 549 OCE_MBX_VER_V0); 550 DW_SWAP(u32ptr(&fwcmd->hdr), sizeof(struct mbx_hdr)); 551 552 fwcmd->params.req.version = 0; 553 fwcmd->params.req.cap_flags = LE_32(cap_flags); 554 fwcmd->params.req.enable_flags = LE_32(en_flags); 555 if (mac_addr != NULL) { 556 bcopy(mac_addr, &fwcmd->params.req.mac_addr[0], 6); 557 fwcmd->params.req.vlan_tag.u0.normal.vtag = LE_16(vlan_tag); 558 fwcmd->params.req.mac_invalid = 0; 559 } else { 560 fwcmd->params.req.mac_invalid = 1; 561 } 562 563 mbx.u0.s.embedded = 1; 564 mbx.payload_length = sizeof(struct mbx_create_common_iface); 565 DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ); 566 567 rc = oce_mbox_post(sc, &mbx, NULL); 568 if (!rc) 569 rc = fwcmd->hdr.u0.rsp.status; 570 if (rc) { 571 device_printf(sc->dev, 572 "%s failed - cmd status: %d addi status: %d\n", 573 __FUNCTION__, rc, 574 fwcmd->hdr.u0.rsp.additional_status); 575 goto error; 576 } 577 578 *if_id = HOST_32(fwcmd->params.rsp.if_id); 579 580 if (mac_addr != NULL) 581 sc->pmac_id = HOST_32(fwcmd->params.rsp.pmac_id); 582 error: 583 return rc; 584 } 585 586 /** 587 * @brief Function to delete an interface 588 * @param sc software handle to the device 589 * @param if_id ID of the interface to delete 590 * @returns 0 on success, EIO on failure 591 */ 592 int 593 oce_if_del(POCE_SOFTC sc, uint32_t if_id) 594 { 595 struct oce_mbx mbx; 596 struct mbx_destroy_common_iface *fwcmd; 597 int rc = 0; 598 599 bzero(&mbx, sizeof(struct oce_mbx)); 600 601 fwcmd = (struct mbx_destroy_common_iface *)&mbx.payload; 602 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 603 MBX_SUBSYSTEM_COMMON, 604 OPCODE_COMMON_DESTROY_IFACE, 605 MBX_TIMEOUT_SEC, 606 sizeof(struct mbx_destroy_common_iface), 607 OCE_MBX_VER_V0); 608 609 fwcmd->params.req.if_id = if_id; 610 611 mbx.u0.s.embedded = 1; 612 mbx.payload_length = sizeof(struct mbx_destroy_common_iface); 613 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 614 615 rc = oce_mbox_post(sc, &mbx, NULL); 616 if (!rc) 617 rc = fwcmd->hdr.u0.rsp.status; 618 if (rc) 619 device_printf(sc->dev, 620 "%s failed - cmd status: %d addi status: %d\n", 621 __FUNCTION__, rc, 622 fwcmd->hdr.u0.rsp.additional_status); 623 return rc; 624 } 625 626 /** 627 * @brief Function to send the mbx command to configure vlan 628 * @param sc software handle to the device 629 * @param if_id interface identifier index 630 * @param vtag_arr array of vlan tags 631 * @param vtag_cnt number of elements in array 632 * @param untagged boolean TRUE/FLASE 633 * @param enable_promisc flag to enable/disable VLAN promiscuous mode 634 * @returns 0 on success, EIO on failure 635 */ 636 int 637 oce_config_vlan(POCE_SOFTC sc, 638 uint32_t if_id, 639 struct normal_vlan *vtag_arr, 640 uint8_t vtag_cnt, uint32_t untagged, uint32_t enable_promisc) 641 { 642 struct oce_mbx mbx; 643 struct mbx_common_config_vlan *fwcmd; 644 int rc = 0; 645 646 if (sc->vlans_added > sc->max_vlans) 647 goto vlan_promisc; 648 649 bzero(&mbx, sizeof(struct oce_mbx)); 650 fwcmd = (struct mbx_common_config_vlan *)&mbx.payload; 651 652 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 653 MBX_SUBSYSTEM_COMMON, 654 OPCODE_COMMON_CONFIG_IFACE_VLAN, 655 MBX_TIMEOUT_SEC, 656 sizeof(struct mbx_common_config_vlan), 657 OCE_MBX_VER_V0); 658 659 fwcmd->params.req.if_id = (uint8_t) if_id; 660 fwcmd->params.req.promisc = (uint8_t) enable_promisc; 661 fwcmd->params.req.untagged = (uint8_t) untagged; 662 fwcmd->params.req.num_vlans = vtag_cnt; 663 664 if (!enable_promisc) { 665 bcopy(vtag_arr, fwcmd->params.req.tags.normal_vlans, 666 vtag_cnt * sizeof(struct normal_vlan)); 667 } 668 mbx.u0.s.embedded = 1; 669 mbx.payload_length = sizeof(struct mbx_common_config_vlan); 670 DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + mbx.payload_length)); 671 672 rc = oce_mbox_post(sc, &mbx, NULL); 673 if (!rc) 674 rc = fwcmd->hdr.u0.rsp.status; 675 if (rc) 676 device_printf(sc->dev, 677 "%s failed - cmd status: %d addi status: %d\n", 678 __FUNCTION__, rc, 679 fwcmd->hdr.u0.rsp.additional_status); 680 681 goto done; 682 683 vlan_promisc: 684 /* Enable Vlan Promis */ 685 oce_rxf_set_promiscuous(sc, (1 << 1)); 686 device_printf(sc->dev,"Enabling Vlan Promisc Mode\n"); 687 done: 688 return rc; 689 690 } 691 692 /** 693 * @brief Function to set flow control capability in the hardware 694 * @param sc software handle to the device 695 * @param flow_control flow control flags to set 696 * @returns 0 on success, EIO on failure 697 */ 698 int 699 oce_set_flow_control(POCE_SOFTC sc, uint32_t flow_control) 700 { 701 struct oce_mbx mbx; 702 struct mbx_common_get_set_flow_control *fwcmd = 703 (struct mbx_common_get_set_flow_control *)&mbx.payload; 704 int rc; 705 706 bzero(&mbx, sizeof(struct oce_mbx)); 707 708 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 709 MBX_SUBSYSTEM_COMMON, 710 OPCODE_COMMON_SET_FLOW_CONTROL, 711 MBX_TIMEOUT_SEC, 712 sizeof(struct mbx_common_get_set_flow_control), 713 OCE_MBX_VER_V0); 714 715 if (flow_control & OCE_FC_TX) 716 fwcmd->tx_flow_control = 1; 717 718 if (flow_control & OCE_FC_RX) 719 fwcmd->rx_flow_control = 1; 720 721 mbx.u0.s.embedded = 1; 722 mbx.payload_length = sizeof(struct mbx_common_get_set_flow_control); 723 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 724 725 rc = oce_mbox_post(sc, &mbx, NULL); 726 if (!rc) 727 rc = fwcmd->hdr.u0.rsp.status; 728 if (rc) 729 device_printf(sc->dev, 730 "%s failed - cmd status: %d addi status: %d\n", 731 __FUNCTION__, rc, 732 fwcmd->hdr.u0.rsp.additional_status); 733 return rc; 734 } 735 736 /** 737 * @brief Initialize the RSS CPU indirection table 738 * 739 * The table is used to choose the queue to place the incomming packets. 740 * Incomming packets are hashed. The lowest bits in the hash result 741 * are used as the index into the CPU indirection table. 742 * Each entry in the table contains the RSS CPU-ID returned by the NIC 743 * create. Based on the CPU ID, the receive completion is routed to 744 * the corresponding RSS CQs. (Non-RSS packets are always completed 745 * on the default (0) CQ). 746 * 747 * @param sc software handle to the device 748 * @param *fwcmd pointer to the rss mbox command 749 * @returns none 750 */ 751 static int 752 oce_rss_itbl_init(POCE_SOFTC sc, struct mbx_config_nic_rss *fwcmd) 753 { 754 int i = 0, j = 0, rc = 0; 755 uint8_t *tbl = fwcmd->params.req.cputable; 756 struct oce_rq *rq = NULL; 757 758 759 for (j = 0; j < INDIRECTION_TABLE_ENTRIES ; j += (sc->nrqs - 1)) { 760 for_all_rss_queues(sc, rq, i) { 761 if ((j + i) >= INDIRECTION_TABLE_ENTRIES) 762 break; 763 tbl[j + i] = rq->rss_cpuid; 764 } 765 } 766 if (i == 0) { 767 device_printf(sc->dev, "error: Invalid number of RSS RQ's\n"); 768 rc = ENXIO; 769 770 } 771 772 /* fill log2 value indicating the size of the CPU table */ 773 if (rc == 0) 774 fwcmd->params.req.cpu_tbl_sz_log2 = LE_16(OCE_LOG2(INDIRECTION_TABLE_ENTRIES)); 775 776 return rc; 777 } 778 779 /** 780 * @brief Function to set flow control capability in the hardware 781 * @param sc software handle to the device 782 * @param if_id interface id to read the address from 783 * @param enable_rss 0=disable, RSS_ENABLE_xxx flags otherwise 784 * @returns 0 on success, EIO on failure 785 */ 786 int 787 oce_config_nic_rss(POCE_SOFTC sc, uint32_t if_id, uint16_t enable_rss) 788 { 789 int rc; 790 struct oce_mbx mbx; 791 struct mbx_config_nic_rss *fwcmd = 792 (struct mbx_config_nic_rss *)&mbx.payload; 793 int version; 794 795 bzero(&mbx, sizeof(struct oce_mbx)); 796 797 if (IS_XE201(sc) || IS_SH(sc)) { 798 version = OCE_MBX_VER_V1; 799 fwcmd->params.req.enable_rss = RSS_ENABLE_UDP_IPV4 | 800 RSS_ENABLE_UDP_IPV6; 801 } else 802 version = OCE_MBX_VER_V0; 803 804 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 805 MBX_SUBSYSTEM_NIC, 806 NIC_CONFIG_RSS, 807 MBX_TIMEOUT_SEC, 808 sizeof(struct mbx_config_nic_rss), 809 version); 810 if (enable_rss) 811 fwcmd->params.req.enable_rss |= (RSS_ENABLE_IPV4 | 812 RSS_ENABLE_TCP_IPV4 | 813 RSS_ENABLE_IPV6 | 814 RSS_ENABLE_TCP_IPV6); 815 816 if(!sc->enable_hwlro) 817 fwcmd->params.req.flush = OCE_FLUSH; 818 else 819 fwcmd->params.req.flush = 0; 820 821 fwcmd->params.req.if_id = LE_32(if_id); 822 823 srandom(arc4random()); /* random entropy seed */ 824 read_random(fwcmd->params.req.hash, sizeof(fwcmd->params.req.hash)); 825 826 rc = oce_rss_itbl_init(sc, fwcmd); 827 if (rc == 0) { 828 mbx.u0.s.embedded = 1; 829 mbx.payload_length = sizeof(struct mbx_config_nic_rss); 830 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 831 832 rc = oce_mbox_post(sc, &mbx, NULL); 833 if (!rc) 834 rc = fwcmd->hdr.u0.rsp.status; 835 if (rc) 836 device_printf(sc->dev, 837 "%s failed - cmd status: %d addi status: %d\n", 838 __FUNCTION__, rc, 839 fwcmd->hdr.u0.rsp.additional_status); 840 } 841 return rc; 842 } 843 844 /** 845 * @brief RXF function to enable/disable device promiscuous mode 846 * @param sc software handle to the device 847 * @param enable enable/disable flag 848 * @returns 0 on success, EIO on failure 849 * @note 850 * The NIC_CONFIG_PROMISCUOUS command deprecated for Lancer. 851 * This function uses the COMMON_SET_IFACE_RX_FILTER command instead. 852 */ 853 int 854 oce_rxf_set_promiscuous(POCE_SOFTC sc, uint8_t enable) 855 { 856 struct mbx_set_common_iface_rx_filter *fwcmd; 857 int sz = sizeof(struct mbx_set_common_iface_rx_filter); 858 iface_rx_filter_ctx_t *req; 859 OCE_DMA_MEM sgl; 860 int rc; 861 862 /* allocate mbx payload's dma scatter/gather memory */ 863 rc = oce_dma_alloc(sc, sz, &sgl, 0); 864 if (rc) 865 return rc; 866 867 fwcmd = OCE_DMAPTR(&sgl, struct mbx_set_common_iface_rx_filter); 868 869 req = &fwcmd->params.req; 870 req->iface_flags_mask = MBX_RX_IFACE_FLAGS_PROMISCUOUS | 871 MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS; 872 /* Bit 0 Mac promisc, Bit 1 Vlan promisc */ 873 if (enable & 0x01) 874 req->iface_flags = MBX_RX_IFACE_FLAGS_PROMISCUOUS; 875 876 if (enable & 0x02) 877 req->iface_flags |= MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS; 878 879 req->if_id = sc->if_id; 880 881 rc = oce_set_common_iface_rx_filter(sc, &sgl); 882 oce_dma_free(sc, &sgl); 883 884 return rc; 885 } 886 887 888 /** 889 * @brief Function modify and select rx filter options 890 * @param sc software handle to the device 891 * @param sgl scatter/gather request/response 892 * @returns 0 on success, error code on failure 893 */ 894 int 895 oce_set_common_iface_rx_filter(POCE_SOFTC sc, POCE_DMA_MEM sgl) 896 { 897 struct oce_mbx mbx; 898 int mbx_sz = sizeof(struct mbx_set_common_iface_rx_filter); 899 struct mbx_set_common_iface_rx_filter *fwcmd; 900 int rc; 901 902 bzero(&mbx, sizeof(struct oce_mbx)); 903 fwcmd = OCE_DMAPTR(sgl, struct mbx_set_common_iface_rx_filter); 904 905 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 906 MBX_SUBSYSTEM_COMMON, 907 OPCODE_COMMON_SET_IFACE_RX_FILTER, 908 MBX_TIMEOUT_SEC, 909 mbx_sz, 910 OCE_MBX_VER_V0); 911 912 oce_dma_sync(sgl, BUS_DMASYNC_PREWRITE); 913 mbx.u0.s.embedded = 0; 914 mbx.u0.s.sge_count = 1; 915 mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(sgl->paddr); 916 mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(sgl->paddr); 917 mbx.payload.u0.u1.sgl[0].length = mbx_sz; 918 mbx.payload_length = mbx_sz; 919 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 920 921 rc = oce_mbox_post(sc, &mbx, NULL); 922 if (!rc) 923 rc = fwcmd->hdr.u0.rsp.status; 924 if (rc) 925 device_printf(sc->dev, 926 "%s failed - cmd status: %d addi status: %d\n", 927 __FUNCTION__, rc, 928 fwcmd->hdr.u0.rsp.additional_status); 929 return rc; 930 } 931 932 /** 933 * @brief Function to query the link status from the hardware 934 * @param sc software handle to the device 935 * @param[out] link pointer to the structure returning link attributes 936 * @returns 0 on success, EIO on failure 937 */ 938 int 939 oce_get_link_status(POCE_SOFTC sc, struct link_status *link) 940 { 941 struct oce_mbx mbx; 942 struct mbx_query_common_link_config *fwcmd; 943 int rc = 0, version; 944 945 bzero(&mbx, sizeof(struct oce_mbx)); 946 947 IS_BE2(sc) ? (version = OCE_MBX_VER_V0) : (version = OCE_MBX_VER_V1); 948 949 fwcmd = (struct mbx_query_common_link_config *)&mbx.payload; 950 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 951 MBX_SUBSYSTEM_COMMON, 952 OPCODE_COMMON_QUERY_LINK_CONFIG, 953 MBX_TIMEOUT_SEC, 954 sizeof(struct mbx_query_common_link_config), 955 version); 956 957 mbx.u0.s.embedded = 1; 958 mbx.payload_length = sizeof(struct mbx_query_common_link_config); 959 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 960 961 rc = oce_mbox_post(sc, &mbx, NULL); 962 963 if (!rc) 964 rc = fwcmd->hdr.u0.rsp.status; 965 if (rc) { 966 device_printf(sc->dev, 967 "%s failed - cmd status: %d addi status: %d\n", 968 __FUNCTION__, rc, 969 fwcmd->hdr.u0.rsp.additional_status); 970 goto error; 971 } 972 /* interpret response */ 973 link->qos_link_speed = HOST_16(fwcmd->params.rsp.qos_link_speed); 974 link->phys_port_speed = fwcmd->params.rsp.physical_port_speed; 975 link->logical_link_status = fwcmd->params.rsp.logical_link_status; 976 error: 977 return rc; 978 } 979 980 981 /** 982 * @brief Function to get NIC statistics 983 * @param sc software handle to the device 984 * @param *stats pointer to where to store statistics 985 * @param reset_stats resets statistics of set 986 * @returns 0 on success, EIO on failure 987 * @note command depricated in Lancer 988 */ 989 #define OCE_MBOX_GET_NIC_STATS(sc, pstats_dma_mem, version) \ 990 int \ 991 oce_mbox_get_nic_stats_v##version(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem) \ 992 { \ 993 struct oce_mbx mbx; \ 994 struct mbx_get_nic_stats_v##version *fwcmd; \ 995 int rc = 0; \ 996 \ 997 bzero(&mbx, sizeof(struct oce_mbx)); \ 998 fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_nic_stats_v##version); \ 999 bzero(fwcmd, sizeof(*fwcmd)); \ 1000 \ 1001 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, \ 1002 MBX_SUBSYSTEM_NIC, \ 1003 NIC_GET_STATS, \ 1004 MBX_TIMEOUT_SEC, \ 1005 sizeof(*fwcmd), \ 1006 OCE_MBX_VER_V##version); \ 1007 \ 1008 mbx.u0.s.embedded = 0; /* stats too large for embedded mbx rsp */ \ 1009 mbx.u0.s.sge_count = 1; /* using scatter gather instead */ \ 1010 \ 1011 oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE); \ 1012 mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr); \ 1013 mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr); \ 1014 mbx.payload.u0.u1.sgl[0].length = sizeof(*fwcmd); \ 1015 mbx.payload_length = sizeof(*fwcmd); \ 1016 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); \ 1017 \ 1018 rc = oce_mbox_post(sc, &mbx, NULL); \ 1019 oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE); \ 1020 if (!rc) \ 1021 rc = fwcmd->hdr.u0.rsp.status; \ 1022 if (rc) \ 1023 device_printf(sc->dev, \ 1024 "%s failed - cmd status: %d addi status: %d\n", \ 1025 __FUNCTION__, rc, \ 1026 fwcmd->hdr.u0.rsp.additional_status); \ 1027 return rc; \ 1028 } 1029 1030 OCE_MBOX_GET_NIC_STATS(sc, pstats_dma_mem, 0); 1031 OCE_MBOX_GET_NIC_STATS(sc, pstats_dma_mem, 1); 1032 OCE_MBOX_GET_NIC_STATS(sc, pstats_dma_mem, 2); 1033 1034 1035 /** 1036 * @brief Function to get pport (physical port) statistics 1037 * @param sc software handle to the device 1038 * @param *stats pointer to where to store statistics 1039 * @param reset_stats resets statistics of set 1040 * @returns 0 on success, EIO on failure 1041 */ 1042 int 1043 oce_mbox_get_pport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem, 1044 uint32_t reset_stats) 1045 { 1046 struct oce_mbx mbx; 1047 struct mbx_get_pport_stats *fwcmd; 1048 int rc = 0; 1049 1050 bzero(&mbx, sizeof(struct oce_mbx)); 1051 fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_pport_stats); 1052 bzero(fwcmd, sizeof(struct mbx_get_pport_stats)); 1053 1054 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 1055 MBX_SUBSYSTEM_NIC, 1056 NIC_GET_PPORT_STATS, 1057 MBX_TIMEOUT_SEC, 1058 sizeof(struct mbx_get_pport_stats), 1059 OCE_MBX_VER_V0); 1060 1061 fwcmd->params.req.reset_stats = reset_stats; 1062 fwcmd->params.req.port_number = sc->port_id; 1063 1064 mbx.u0.s.embedded = 0; /* stats too large for embedded mbx rsp */ 1065 mbx.u0.s.sge_count = 1; /* using scatter gather instead */ 1066 1067 oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE); 1068 mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr); 1069 mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr); 1070 mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_pport_stats); 1071 1072 mbx.payload_length = sizeof(struct mbx_get_pport_stats); 1073 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 1074 1075 rc = oce_mbox_post(sc, &mbx, NULL); 1076 oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE); 1077 1078 if (!rc) 1079 rc = fwcmd->hdr.u0.rsp.status; 1080 if (rc) 1081 device_printf(sc->dev, 1082 "%s failed - cmd status: %d addi status: %d\n", 1083 __FUNCTION__, rc, 1084 fwcmd->hdr.u0.rsp.additional_status); 1085 return rc; 1086 } 1087 1088 1089 /** 1090 * @brief Function to get vport (virtual port) statistics 1091 * @param sc software handle to the device 1092 * @param *stats pointer to where to store statistics 1093 * @param reset_stats resets statistics of set 1094 * @returns 0 on success, EIO on failure 1095 */ 1096 int 1097 oce_mbox_get_vport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem, 1098 uint32_t req_size, uint32_t reset_stats) 1099 { 1100 struct oce_mbx mbx; 1101 struct mbx_get_vport_stats *fwcmd; 1102 int rc = 0; 1103 1104 bzero(&mbx, sizeof(struct oce_mbx)); 1105 1106 fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_vport_stats); 1107 bzero(fwcmd, sizeof(struct mbx_get_vport_stats)); 1108 1109 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 1110 MBX_SUBSYSTEM_NIC, 1111 NIC_GET_VPORT_STATS, 1112 MBX_TIMEOUT_SEC, 1113 sizeof(struct mbx_get_vport_stats), 1114 OCE_MBX_VER_V0); 1115 1116 fwcmd->params.req.reset_stats = reset_stats; 1117 fwcmd->params.req.vport_number = sc->if_id; 1118 1119 mbx.u0.s.embedded = 0; /* stats too large for embedded mbx rsp */ 1120 mbx.u0.s.sge_count = 1; /* using scatter gather instead */ 1121 1122 oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE); 1123 mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr); 1124 mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr); 1125 mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_vport_stats); 1126 1127 mbx.payload_length = sizeof(struct mbx_get_vport_stats); 1128 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 1129 1130 rc = oce_mbox_post(sc, &mbx, NULL); 1131 oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE); 1132 1133 if (!rc) 1134 rc = fwcmd->hdr.u0.rsp.status; 1135 if (rc) 1136 device_printf(sc->dev, 1137 "%s failed - cmd status: %d addi status: %d\n", 1138 __FUNCTION__, rc, 1139 fwcmd->hdr.u0.rsp.additional_status); 1140 return rc; 1141 } 1142 1143 1144 /** 1145 * @brief Function to update the muticast filter with 1146 * values in dma_mem 1147 * @param sc software handle to the device 1148 * @param dma_mem pointer to dma memory region 1149 * @returns 0 on success, EIO on failure 1150 */ 1151 int 1152 oce_update_multicast(POCE_SOFTC sc, POCE_DMA_MEM pdma_mem) 1153 { 1154 struct oce_mbx mbx; 1155 struct oce_mq_sge *sgl; 1156 struct mbx_set_common_iface_multicast *req = NULL; 1157 int rc = 0; 1158 1159 req = OCE_DMAPTR(pdma_mem, struct mbx_set_common_iface_multicast); 1160 mbx_common_req_hdr_init(&req->hdr, 0, 0, 1161 MBX_SUBSYSTEM_COMMON, 1162 OPCODE_COMMON_SET_IFACE_MULTICAST, 1163 MBX_TIMEOUT_SEC, 1164 sizeof(struct mbx_set_common_iface_multicast), 1165 OCE_MBX_VER_V0); 1166 1167 bzero(&mbx, sizeof(struct oce_mbx)); 1168 1169 mbx.u0.s.embedded = 0; /*Non embeded*/ 1170 mbx.payload_length = sizeof(struct mbx_set_common_iface_multicast); 1171 mbx.u0.s.sge_count = 1; 1172 sgl = &mbx.payload.u0.u1.sgl[0]; 1173 sgl->pa_hi = htole32(upper_32_bits(pdma_mem->paddr)); 1174 sgl->pa_lo = htole32((pdma_mem->paddr) & 0xFFFFFFFF); 1175 sgl->length = htole32(mbx.payload_length); 1176 1177 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 1178 1179 rc = oce_mbox_post(sc, &mbx, NULL); 1180 if (!rc) 1181 rc = req->hdr.u0.rsp.status; 1182 if (rc) 1183 device_printf(sc->dev, 1184 "%s failed - cmd status: %d addi status: %d\n", 1185 __FUNCTION__, rc, 1186 req->hdr.u0.rsp.additional_status); 1187 return rc; 1188 } 1189 1190 1191 /** 1192 * @brief Function to send passthrough Ioctls 1193 * @param sc software handle to the device 1194 * @param dma_mem pointer to dma memory region 1195 * @param req_size size of dma_mem 1196 * @returns 0 on success, EIO on failure 1197 */ 1198 int 1199 oce_pass_through_mbox(POCE_SOFTC sc, POCE_DMA_MEM dma_mem, uint32_t req_size) 1200 { 1201 struct oce_mbx mbx; 1202 struct oce_mq_sge *sgl; 1203 int rc = 0; 1204 1205 bzero(&mbx, sizeof(struct oce_mbx)); 1206 1207 mbx.u0.s.embedded = 0; /*Non embeded*/ 1208 mbx.payload_length = req_size; 1209 mbx.u0.s.sge_count = 1; 1210 sgl = &mbx.payload.u0.u1.sgl[0]; 1211 sgl->pa_hi = htole32(upper_32_bits(dma_mem->paddr)); 1212 sgl->pa_lo = htole32((dma_mem->paddr) & 0xFFFFFFFF); 1213 sgl->length = htole32(req_size); 1214 1215 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 1216 1217 rc = oce_mbox_post(sc, &mbx, NULL); 1218 return rc; 1219 } 1220 1221 1222 int 1223 oce_mbox_macaddr_add(POCE_SOFTC sc, uint8_t *mac_addr, 1224 uint32_t if_id, uint32_t *pmac_id) 1225 { 1226 struct oce_mbx mbx; 1227 struct mbx_add_common_iface_mac *fwcmd; 1228 int rc = 0; 1229 1230 bzero(&mbx, sizeof(struct oce_mbx)); 1231 1232 fwcmd = (struct mbx_add_common_iface_mac *)&mbx.payload; 1233 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 1234 MBX_SUBSYSTEM_COMMON, 1235 OPCODE_COMMON_ADD_IFACE_MAC, 1236 MBX_TIMEOUT_SEC, 1237 sizeof(struct mbx_add_common_iface_mac), 1238 OCE_MBX_VER_V0); 1239 1240 fwcmd->params.req.if_id = (uint16_t) if_id; 1241 bcopy(mac_addr, fwcmd->params.req.mac_address, 6); 1242 1243 mbx.u0.s.embedded = 1; 1244 mbx.payload_length = sizeof(struct mbx_add_common_iface_mac); 1245 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 1246 rc = oce_mbox_post(sc, &mbx, NULL); 1247 if (!rc) 1248 rc = fwcmd->hdr.u0.rsp.status; 1249 if (rc) { 1250 device_printf(sc->dev, 1251 "%s failed - cmd status: %d addi status: %d\n", 1252 __FUNCTION__, rc, 1253 fwcmd->hdr.u0.rsp.additional_status); 1254 goto error; 1255 } 1256 *pmac_id = fwcmd->params.rsp.pmac_id; 1257 error: 1258 return rc; 1259 } 1260 1261 1262 int 1263 oce_mbox_macaddr_del(POCE_SOFTC sc, uint32_t if_id, uint32_t pmac_id) 1264 { 1265 struct oce_mbx mbx; 1266 struct mbx_del_common_iface_mac *fwcmd; 1267 int rc = 0; 1268 1269 bzero(&mbx, sizeof(struct oce_mbx)); 1270 1271 fwcmd = (struct mbx_del_common_iface_mac *)&mbx.payload; 1272 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 1273 MBX_SUBSYSTEM_COMMON, 1274 OPCODE_COMMON_DEL_IFACE_MAC, 1275 MBX_TIMEOUT_SEC, 1276 sizeof(struct mbx_del_common_iface_mac), 1277 OCE_MBX_VER_V0); 1278 1279 fwcmd->params.req.if_id = (uint16_t)if_id; 1280 fwcmd->params.req.pmac_id = pmac_id; 1281 1282 mbx.u0.s.embedded = 1; 1283 mbx.payload_length = sizeof(struct mbx_del_common_iface_mac); 1284 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 1285 1286 rc = oce_mbox_post(sc, &mbx, NULL); 1287 if (!rc) 1288 rc = fwcmd->hdr.u0.rsp.status; 1289 if (rc) 1290 device_printf(sc->dev, 1291 "%s failed - cmd status: %d addi status: %d\n", 1292 __FUNCTION__, rc, 1293 fwcmd->hdr.u0.rsp.additional_status); 1294 return rc; 1295 } 1296 1297 1298 1299 int 1300 oce_mbox_check_native_mode(POCE_SOFTC sc) 1301 { 1302 struct oce_mbx mbx; 1303 struct mbx_common_set_function_cap *fwcmd; 1304 int rc = 0; 1305 1306 bzero(&mbx, sizeof(struct oce_mbx)); 1307 1308 fwcmd = (struct mbx_common_set_function_cap *)&mbx.payload; 1309 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 1310 MBX_SUBSYSTEM_COMMON, 1311 OPCODE_COMMON_SET_FUNCTIONAL_CAPS, 1312 MBX_TIMEOUT_SEC, 1313 sizeof(struct mbx_common_set_function_cap), 1314 OCE_MBX_VER_V0); 1315 1316 fwcmd->params.req.valid_capability_flags = CAP_SW_TIMESTAMPS | 1317 CAP_BE3_NATIVE_ERX_API; 1318 1319 fwcmd->params.req.capability_flags = CAP_BE3_NATIVE_ERX_API; 1320 1321 mbx.u0.s.embedded = 1; 1322 mbx.payload_length = sizeof(struct mbx_common_set_function_cap); 1323 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 1324 1325 rc = oce_mbox_post(sc, &mbx, NULL); 1326 if (!rc) 1327 rc = fwcmd->hdr.u0.rsp.status; 1328 if (rc) { 1329 device_printf(sc->dev, 1330 "%s failed - cmd status: %d addi status: %d\n", 1331 __FUNCTION__, rc, 1332 fwcmd->hdr.u0.rsp.additional_status); 1333 goto error; 1334 } 1335 sc->be3_native = HOST_32(fwcmd->params.rsp.capability_flags) 1336 & CAP_BE3_NATIVE_ERX_API; 1337 1338 error: 1339 return 0; 1340 } 1341 1342 1343 1344 int 1345 oce_mbox_cmd_set_loopback(POCE_SOFTC sc, uint8_t port_num, 1346 uint8_t loopback_type, uint8_t enable) 1347 { 1348 struct oce_mbx mbx; 1349 struct mbx_lowlevel_set_loopback_mode *fwcmd; 1350 int rc = 0; 1351 1352 1353 bzero(&mbx, sizeof(struct oce_mbx)); 1354 1355 fwcmd = (struct mbx_lowlevel_set_loopback_mode *)&mbx.payload; 1356 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 1357 MBX_SUBSYSTEM_LOWLEVEL, 1358 OPCODE_LOWLEVEL_SET_LOOPBACK_MODE, 1359 MBX_TIMEOUT_SEC, 1360 sizeof(struct mbx_lowlevel_set_loopback_mode), 1361 OCE_MBX_VER_V0); 1362 1363 fwcmd->params.req.src_port = port_num; 1364 fwcmd->params.req.dest_port = port_num; 1365 fwcmd->params.req.loopback_type = loopback_type; 1366 fwcmd->params.req.loopback_state = enable; 1367 1368 mbx.u0.s.embedded = 1; 1369 mbx.payload_length = sizeof(struct mbx_lowlevel_set_loopback_mode); 1370 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 1371 1372 rc = oce_mbox_post(sc, &mbx, NULL); 1373 if (!rc) 1374 rc = fwcmd->hdr.u0.rsp.status; 1375 if (rc) 1376 device_printf(sc->dev, 1377 "%s failed - cmd status: %d addi status: %d\n", 1378 __FUNCTION__, rc, 1379 fwcmd->hdr.u0.rsp.additional_status); 1380 1381 return rc; 1382 1383 } 1384 1385 int 1386 oce_mbox_cmd_test_loopback(POCE_SOFTC sc, uint32_t port_num, 1387 uint32_t loopback_type, uint32_t pkt_size, uint32_t num_pkts, 1388 uint64_t pattern) 1389 { 1390 1391 struct oce_mbx mbx; 1392 struct mbx_lowlevel_test_loopback_mode *fwcmd; 1393 int rc = 0; 1394 1395 1396 bzero(&mbx, sizeof(struct oce_mbx)); 1397 1398 fwcmd = (struct mbx_lowlevel_test_loopback_mode *)&mbx.payload; 1399 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 1400 MBX_SUBSYSTEM_LOWLEVEL, 1401 OPCODE_LOWLEVEL_TEST_LOOPBACK, 1402 MBX_TIMEOUT_SEC, 1403 sizeof(struct mbx_lowlevel_test_loopback_mode), 1404 OCE_MBX_VER_V0); 1405 1406 fwcmd->params.req.pattern = pattern; 1407 fwcmd->params.req.src_port = port_num; 1408 fwcmd->params.req.dest_port = port_num; 1409 fwcmd->params.req.pkt_size = pkt_size; 1410 fwcmd->params.req.num_pkts = num_pkts; 1411 fwcmd->params.req.loopback_type = loopback_type; 1412 1413 mbx.u0.s.embedded = 1; 1414 mbx.payload_length = sizeof(struct mbx_lowlevel_test_loopback_mode); 1415 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 1416 1417 rc = oce_mbox_post(sc, &mbx, NULL); 1418 if (!rc) 1419 rc = fwcmd->hdr.u0.rsp.status; 1420 if (rc) 1421 device_printf(sc->dev, 1422 "%s failed - cmd status: %d addi status: %d\n", 1423 __FUNCTION__, rc, 1424 fwcmd->hdr.u0.rsp.additional_status); 1425 1426 return rc; 1427 } 1428 1429 int 1430 oce_mbox_write_flashrom(POCE_SOFTC sc, uint32_t optype,uint32_t opcode, 1431 POCE_DMA_MEM pdma_mem, uint32_t num_bytes) 1432 { 1433 1434 struct oce_mbx mbx; 1435 struct oce_mq_sge *sgl = NULL; 1436 struct mbx_common_read_write_flashrom *fwcmd = NULL; 1437 int rc = 0, payload_len = 0; 1438 1439 bzero(&mbx, sizeof(struct oce_mbx)); 1440 fwcmd = OCE_DMAPTR(pdma_mem, struct mbx_common_read_write_flashrom); 1441 payload_len = sizeof(struct mbx_common_read_write_flashrom) + 32*1024; 1442 1443 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 1444 MBX_SUBSYSTEM_COMMON, 1445 OPCODE_COMMON_WRITE_FLASHROM, 1446 LONG_TIMEOUT, 1447 payload_len, 1448 OCE_MBX_VER_V0); 1449 1450 fwcmd->flash_op_type = LE_32(optype); 1451 fwcmd->flash_op_code = LE_32(opcode); 1452 fwcmd->data_buffer_size = LE_32(num_bytes); 1453 1454 mbx.u0.s.embedded = 0; /*Non embeded*/ 1455 mbx.payload_length = payload_len; 1456 mbx.u0.s.sge_count = 1; 1457 1458 sgl = &mbx.payload.u0.u1.sgl[0]; 1459 sgl->pa_hi = upper_32_bits(pdma_mem->paddr); 1460 sgl->pa_lo = pdma_mem->paddr & 0xFFFFFFFF; 1461 sgl->length = payload_len; 1462 1463 /* post the command */ 1464 rc = oce_mbox_post(sc, &mbx, NULL); 1465 if (!rc) 1466 rc = fwcmd->hdr.u0.rsp.status; 1467 if (rc) 1468 device_printf(sc->dev, 1469 "%s failed - cmd status: %d addi status: %d\n", 1470 __FUNCTION__, rc, 1471 fwcmd->hdr.u0.rsp.additional_status); 1472 1473 return rc; 1474 1475 } 1476 1477 int 1478 oce_mbox_get_flashrom_crc(POCE_SOFTC sc, uint8_t *flash_crc, 1479 uint32_t offset, uint32_t optype) 1480 { 1481 1482 int rc = 0, payload_len = 0; 1483 struct oce_mbx mbx; 1484 struct mbx_common_read_write_flashrom *fwcmd; 1485 1486 bzero(&mbx, sizeof(struct oce_mbx)); 1487 1488 fwcmd = (struct mbx_common_read_write_flashrom *)&mbx.payload; 1489 1490 /* Firmware requires extra 4 bytes with this ioctl. Since there 1491 is enough room in the mbx payload it should be good enough 1492 Reference: Bug 14853 1493 */ 1494 payload_len = sizeof(struct mbx_common_read_write_flashrom) + 4; 1495 1496 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 1497 MBX_SUBSYSTEM_COMMON, 1498 OPCODE_COMMON_READ_FLASHROM, 1499 MBX_TIMEOUT_SEC, 1500 payload_len, 1501 OCE_MBX_VER_V0); 1502 1503 fwcmd->flash_op_type = optype; 1504 fwcmd->flash_op_code = FLASHROM_OPER_REPORT; 1505 fwcmd->data_offset = offset; 1506 fwcmd->data_buffer_size = 0x4; 1507 1508 mbx.u0.s.embedded = 1; 1509 mbx.payload_length = payload_len; 1510 1511 /* post the command */ 1512 rc = oce_mbox_post(sc, &mbx, NULL); 1513 if (!rc) 1514 rc = fwcmd->hdr.u0.rsp.status; 1515 if (rc) { 1516 device_printf(sc->dev, 1517 "%s failed - cmd status: %d addi status: %d\n", 1518 __FUNCTION__, rc, 1519 fwcmd->hdr.u0.rsp.additional_status); 1520 goto error; 1521 } 1522 bcopy(fwcmd->data_buffer, flash_crc, 4); 1523 error: 1524 return rc; 1525 } 1526 1527 int 1528 oce_mbox_get_phy_info(POCE_SOFTC sc, struct oce_phy_info *phy_info) 1529 { 1530 1531 struct oce_mbx mbx; 1532 struct mbx_common_phy_info *fwcmd; 1533 int rc = 0; 1534 1535 bzero(&mbx, sizeof(struct oce_mbx)); 1536 1537 fwcmd = (struct mbx_common_phy_info *)&mbx.payload; 1538 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 1539 MBX_SUBSYSTEM_COMMON, 1540 OPCODE_COMMON_GET_PHY_CONFIG, 1541 MBX_TIMEOUT_SEC, 1542 sizeof(struct mbx_common_phy_info), 1543 OCE_MBX_VER_V0); 1544 1545 mbx.u0.s.embedded = 1; 1546 mbx.payload_length = sizeof(struct mbx_common_phy_info); 1547 1548 /* now post the command */ 1549 rc = oce_mbox_post(sc, &mbx, NULL); 1550 if (!rc) 1551 rc = fwcmd->hdr.u0.rsp.status; 1552 if (rc) { 1553 device_printf(sc->dev, 1554 "%s failed - cmd status: %d addi status: %d\n", 1555 __FUNCTION__, rc, 1556 fwcmd->hdr.u0.rsp.additional_status); 1557 goto error; 1558 } 1559 phy_info->phy_type = HOST_16(fwcmd->params.rsp.phy_info.phy_type); 1560 phy_info->interface_type = 1561 HOST_16(fwcmd->params.rsp.phy_info.interface_type); 1562 phy_info->auto_speeds_supported = 1563 HOST_16(fwcmd->params.rsp.phy_info.auto_speeds_supported); 1564 phy_info->fixed_speeds_supported = 1565 HOST_16(fwcmd->params.rsp.phy_info.fixed_speeds_supported); 1566 phy_info->misc_params = HOST_32(fwcmd->params.rsp.phy_info.misc_params); 1567 error: 1568 return rc; 1569 1570 } 1571 1572 1573 int 1574 oce_mbox_lancer_write_flashrom(POCE_SOFTC sc, uint32_t data_size, 1575 uint32_t data_offset, POCE_DMA_MEM pdma_mem, 1576 uint32_t *written_data, uint32_t *additional_status) 1577 { 1578 1579 struct oce_mbx mbx; 1580 struct mbx_lancer_common_write_object *fwcmd = NULL; 1581 int rc = 0, payload_len = 0; 1582 1583 bzero(&mbx, sizeof(struct oce_mbx)); 1584 payload_len = sizeof(struct mbx_lancer_common_write_object); 1585 1586 mbx.u0.s.embedded = 1;/* Embedded */ 1587 mbx.payload_length = payload_len; 1588 fwcmd = (struct mbx_lancer_common_write_object *)&mbx.payload; 1589 1590 /* initialize the ioctl header */ 1591 mbx_common_req_hdr_init(&fwcmd->params.req.hdr, 0, 0, 1592 MBX_SUBSYSTEM_COMMON, 1593 OPCODE_COMMON_WRITE_OBJECT, 1594 LONG_TIMEOUT, 1595 payload_len, 1596 OCE_MBX_VER_V0); 1597 1598 fwcmd->params.req.write_length = data_size; 1599 if (data_size == 0) 1600 fwcmd->params.req.eof = 1; 1601 else 1602 fwcmd->params.req.eof = 0; 1603 1604 strcpy(fwcmd->params.req.object_name, "/prg"); 1605 fwcmd->params.req.descriptor_count = 1; 1606 fwcmd->params.req.write_offset = data_offset; 1607 fwcmd->params.req.buffer_length = data_size; 1608 fwcmd->params.req.address_lower = pdma_mem->paddr & 0xFFFFFFFF; 1609 fwcmd->params.req.address_upper = upper_32_bits(pdma_mem->paddr); 1610 1611 /* post the command */ 1612 rc = oce_mbox_post(sc, &mbx, NULL); 1613 if (!rc) 1614 rc = fwcmd->params.rsp.status; 1615 if (rc) { 1616 device_printf(sc->dev, 1617 "%s failed - cmd status: %d addi status: %d\n", 1618 __FUNCTION__, rc, 1619 fwcmd->params.rsp.additional_status); 1620 goto error; 1621 } 1622 *written_data = HOST_32(fwcmd->params.rsp.actual_write_length); 1623 *additional_status = fwcmd->params.rsp.additional_status; 1624 error: 1625 return rc; 1626 1627 } 1628 1629 1630 1631 int 1632 oce_mbox_create_rq(struct oce_rq *rq) 1633 { 1634 1635 struct oce_mbx mbx; 1636 struct mbx_create_nic_rq *fwcmd; 1637 POCE_SOFTC sc = rq->parent; 1638 int rc, num_pages = 0; 1639 1640 if (rq->qstate == QCREATED) 1641 return 0; 1642 1643 bzero(&mbx, sizeof(struct oce_mbx)); 1644 1645 fwcmd = (struct mbx_create_nic_rq *)&mbx.payload; 1646 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 1647 MBX_SUBSYSTEM_NIC, 1648 NIC_CREATE_RQ, MBX_TIMEOUT_SEC, 1649 sizeof(struct mbx_create_nic_rq), 1650 OCE_MBX_VER_V0); 1651 1652 /* oce_page_list will also prepare pages */ 1653 num_pages = oce_page_list(rq->ring, &fwcmd->params.req.pages[0]); 1654 1655 if (IS_XE201(sc)) { 1656 fwcmd->params.req.frag_size = rq->cfg.frag_size/2048; 1657 fwcmd->params.req.page_size = 1; 1658 fwcmd->hdr.u0.req.version = OCE_MBX_VER_V1; 1659 } else 1660 fwcmd->params.req.frag_size = OCE_LOG2(rq->cfg.frag_size); 1661 fwcmd->params.req.num_pages = num_pages; 1662 fwcmd->params.req.cq_id = rq->cq->cq_id; 1663 fwcmd->params.req.if_id = sc->if_id; 1664 fwcmd->params.req.max_frame_size = rq->cfg.mtu; 1665 fwcmd->params.req.is_rss_queue = rq->cfg.is_rss_queue; 1666 1667 mbx.u0.s.embedded = 1; 1668 mbx.payload_length = sizeof(struct mbx_create_nic_rq); 1669 1670 rc = oce_mbox_post(sc, &mbx, NULL); 1671 if (!rc) 1672 rc = fwcmd->hdr.u0.rsp.status; 1673 if (rc) { 1674 device_printf(sc->dev, 1675 "%s failed - cmd status: %d addi status: %d\n", 1676 __FUNCTION__, rc, 1677 fwcmd->hdr.u0.rsp.additional_status); 1678 goto error; 1679 } 1680 rq->rq_id = HOST_16(fwcmd->params.rsp.rq_id); 1681 rq->rss_cpuid = fwcmd->params.rsp.rss_cpuid; 1682 error: 1683 return rc; 1684 1685 } 1686 1687 1688 1689 int 1690 oce_mbox_create_wq(struct oce_wq *wq) 1691 { 1692 struct oce_mbx mbx; 1693 struct mbx_create_nic_wq *fwcmd; 1694 POCE_SOFTC sc = wq->parent; 1695 int rc = 0, version, num_pages; 1696 1697 bzero(&mbx, sizeof(struct oce_mbx)); 1698 1699 fwcmd = (struct mbx_create_nic_wq *)&mbx.payload; 1700 if (IS_XE201(sc)) 1701 version = OCE_MBX_VER_V1; 1702 else if(IS_BE(sc)) 1703 IS_PROFILE_SUPER_NIC(sc) ? (version = OCE_MBX_VER_V2) 1704 : (version = OCE_MBX_VER_V0); 1705 else 1706 version = OCE_MBX_VER_V2; 1707 1708 if (version > OCE_MBX_VER_V0) 1709 fwcmd->params.req.if_id = sc->if_id; 1710 1711 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 1712 MBX_SUBSYSTEM_NIC, 1713 NIC_CREATE_WQ, MBX_TIMEOUT_SEC, 1714 sizeof(struct mbx_create_nic_wq), 1715 version); 1716 1717 num_pages = oce_page_list(wq->ring, &fwcmd->params.req.pages[0]); 1718 1719 fwcmd->params.req.nic_wq_type = wq->cfg.wq_type; 1720 fwcmd->params.req.num_pages = num_pages; 1721 fwcmd->params.req.wq_size = OCE_LOG2(wq->cfg.q_len) + 1; 1722 fwcmd->params.req.cq_id = wq->cq->cq_id; 1723 fwcmd->params.req.ulp_num = 1; 1724 1725 mbx.u0.s.embedded = 1; 1726 mbx.payload_length = sizeof(struct mbx_create_nic_wq); 1727 1728 rc = oce_mbox_post(sc, &mbx, NULL); 1729 if (!rc) 1730 rc = fwcmd->hdr.u0.rsp.status; 1731 if (rc) { 1732 device_printf(sc->dev, 1733 "%s failed - cmd status: %d addi status: %d\n", 1734 __FUNCTION__, rc, 1735 fwcmd->hdr.u0.rsp.additional_status); 1736 goto error; 1737 } 1738 wq->wq_id = HOST_16(fwcmd->params.rsp.wq_id); 1739 if (version == OCE_MBX_VER_V2) 1740 wq->db_offset = HOST_32(fwcmd->params.rsp.db_offset); 1741 else 1742 wq->db_offset = PD_TXULP_DB; 1743 error: 1744 return rc; 1745 1746 } 1747 1748 1749 1750 int 1751 oce_mbox_create_eq(struct oce_eq *eq) 1752 { 1753 struct oce_mbx mbx; 1754 struct mbx_create_common_eq *fwcmd; 1755 POCE_SOFTC sc = eq->parent; 1756 int rc = 0; 1757 uint32_t num_pages; 1758 1759 bzero(&mbx, sizeof(struct oce_mbx)); 1760 1761 fwcmd = (struct mbx_create_common_eq *)&mbx.payload; 1762 1763 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 1764 MBX_SUBSYSTEM_COMMON, 1765 OPCODE_COMMON_CREATE_EQ, MBX_TIMEOUT_SEC, 1766 sizeof(struct mbx_create_common_eq), 1767 OCE_MBX_VER_V0); 1768 1769 num_pages = oce_page_list(eq->ring, &fwcmd->params.req.pages[0]); 1770 fwcmd->params.req.ctx.num_pages = num_pages; 1771 fwcmd->params.req.ctx.valid = 1; 1772 fwcmd->params.req.ctx.size = (eq->eq_cfg.item_size == 4) ? 0 : 1; 1773 fwcmd->params.req.ctx.count = OCE_LOG2(eq->eq_cfg.q_len / 256); 1774 fwcmd->params.req.ctx.armed = 0; 1775 fwcmd->params.req.ctx.delay_mult = eq->eq_cfg.cur_eqd; 1776 1777 1778 mbx.u0.s.embedded = 1; 1779 mbx.payload_length = sizeof(struct mbx_create_common_eq); 1780 1781 rc = oce_mbox_post(sc, &mbx, NULL); 1782 if (!rc) 1783 rc = fwcmd->hdr.u0.rsp.status; 1784 if (rc) { 1785 device_printf(sc->dev, 1786 "%s failed - cmd status: %d addi status: %d\n", 1787 __FUNCTION__, rc, 1788 fwcmd->hdr.u0.rsp.additional_status); 1789 goto error; 1790 } 1791 eq->eq_id = HOST_16(fwcmd->params.rsp.eq_id); 1792 error: 1793 return rc; 1794 } 1795 1796 1797 1798 int 1799 oce_mbox_cq_create(struct oce_cq *cq, uint32_t ncoalesce, uint32_t is_eventable) 1800 { 1801 struct oce_mbx mbx; 1802 struct mbx_create_common_cq *fwcmd; 1803 POCE_SOFTC sc = cq->parent; 1804 uint8_t version; 1805 oce_cq_ctx_t *ctx; 1806 uint32_t num_pages, page_size; 1807 int rc = 0; 1808 1809 1810 bzero(&mbx, sizeof(struct oce_mbx)); 1811 1812 fwcmd = (struct mbx_create_common_cq *)&mbx.payload; 1813 1814 if (IS_XE201(sc)) 1815 version = OCE_MBX_VER_V2; 1816 else 1817 version = OCE_MBX_VER_V0; 1818 1819 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 1820 MBX_SUBSYSTEM_COMMON, 1821 OPCODE_COMMON_CREATE_CQ, 1822 MBX_TIMEOUT_SEC, 1823 sizeof(struct mbx_create_common_cq), 1824 version); 1825 1826 ctx = &fwcmd->params.req.cq_ctx; 1827 1828 num_pages = oce_page_list(cq->ring, &fwcmd->params.req.pages[0]); 1829 page_size = 1; /* 1 for 4K */ 1830 1831 if (version == OCE_MBX_VER_V2) { 1832 ctx->v2.num_pages = LE_16(num_pages); 1833 ctx->v2.page_size = page_size; 1834 ctx->v2.eventable = is_eventable; 1835 ctx->v2.valid = 1; 1836 ctx->v2.count = OCE_LOG2(cq->cq_cfg.q_len / 256); 1837 ctx->v2.nodelay = cq->cq_cfg.nodelay; 1838 ctx->v2.coalesce_wm = ncoalesce; 1839 ctx->v2.armed = 0; 1840 ctx->v2.eq_id = cq->eq->eq_id; 1841 if (ctx->v2.count == 3) { 1842 if ((u_int)cq->cq_cfg.q_len > (4*1024)-1) 1843 ctx->v2.cqe_count = (4*1024)-1; 1844 else 1845 ctx->v2.cqe_count = cq->cq_cfg.q_len; 1846 } 1847 } else { 1848 ctx->v0.num_pages = LE_16(num_pages); 1849 ctx->v0.eventable = is_eventable; 1850 ctx->v0.valid = 1; 1851 ctx->v0.count = OCE_LOG2(cq->cq_cfg.q_len / 256); 1852 ctx->v0.nodelay = cq->cq_cfg.nodelay; 1853 ctx->v0.coalesce_wm = ncoalesce; 1854 ctx->v0.armed = 0; 1855 ctx->v0.eq_id = cq->eq->eq_id; 1856 } 1857 1858 mbx.u0.s.embedded = 1; 1859 mbx.payload_length = sizeof(struct mbx_create_common_cq); 1860 1861 rc = oce_mbox_post(sc, &mbx, NULL); 1862 if (!rc) 1863 rc = fwcmd->hdr.u0.rsp.status; 1864 if (rc) { 1865 device_printf(sc->dev, 1866 "%s failed - cmd status: %d addi status: %d\n", 1867 __FUNCTION__, rc, 1868 fwcmd->hdr.u0.rsp.additional_status); 1869 goto error; 1870 } 1871 cq->cq_id = HOST_16(fwcmd->params.rsp.cq_id); 1872 error: 1873 return rc; 1874 1875 } 1876 1877 int 1878 oce_mbox_read_transrecv_data(POCE_SOFTC sc, uint32_t page_num) 1879 { 1880 int rc = 0; 1881 struct oce_mbx mbx; 1882 struct mbx_read_common_transrecv_data *fwcmd; 1883 struct oce_mq_sge *sgl; 1884 OCE_DMA_MEM dma; 1885 1886 /* Allocate DMA mem*/ 1887 if (oce_dma_alloc(sc, sizeof(struct mbx_read_common_transrecv_data), 1888 &dma, 0)) 1889 return ENOMEM; 1890 1891 fwcmd = OCE_DMAPTR(&dma, struct mbx_read_common_transrecv_data); 1892 bzero(fwcmd, sizeof(struct mbx_read_common_transrecv_data)); 1893 1894 bzero(&mbx, sizeof(struct oce_mbx)); 1895 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 1896 MBX_SUBSYSTEM_COMMON, 1897 OPCODE_COMMON_READ_TRANSRECEIVER_DATA, 1898 MBX_TIMEOUT_SEC, 1899 sizeof(struct mbx_read_common_transrecv_data), 1900 OCE_MBX_VER_V0); 1901 1902 /* fill rest of mbx */ 1903 mbx.u0.s.embedded = 0; 1904 mbx.payload_length = sizeof(struct mbx_read_common_transrecv_data); 1905 mbx.u0.s.sge_count = 1; 1906 sgl = &mbx.payload.u0.u1.sgl[0]; 1907 sgl->pa_hi = htole32(upper_32_bits(dma.paddr)); 1908 sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF); 1909 sgl->length = htole32(mbx.payload_length); 1910 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 1911 1912 fwcmd->params.req.port = LE_32(sc->port_id); 1913 fwcmd->params.req.page_num = LE_32(page_num); 1914 1915 /* command post */ 1916 rc = oce_mbox_post(sc, &mbx, NULL); 1917 if (!rc) 1918 rc = fwcmd->hdr.u0.rsp.status; 1919 if (rc) { 1920 device_printf(sc->dev, 1921 "%s failed - cmd status: %d addi status: %d\n", 1922 __FUNCTION__, rc, 1923 fwcmd->hdr.u0.rsp.additional_status); 1924 goto error; 1925 } 1926 if(fwcmd->params.rsp.page_num == PAGE_NUM_A0) 1927 { 1928 bcopy((char *)fwcmd->params.rsp.page_data, 1929 (char *)&sfp_vpd_dump_buffer[0], 1930 TRANSCEIVER_A0_SIZE); 1931 } 1932 1933 if(fwcmd->params.rsp.page_num == PAGE_NUM_A2) 1934 { 1935 bcopy((char *)fwcmd->params.rsp.page_data, 1936 (char *)&sfp_vpd_dump_buffer[32], 1937 TRANSCEIVER_A2_SIZE); 1938 } 1939 error: 1940 oce_dma_free(sc, &dma); 1941 return rc; 1942 } 1943 1944 void 1945 oce_mbox_eqd_modify_periodic(POCE_SOFTC sc, struct oce_set_eqd *set_eqd, 1946 int num) 1947 { 1948 struct oce_mbx mbx; 1949 struct mbx_modify_common_eq_delay *fwcmd; 1950 int rc = 0; 1951 int i = 0; 1952 1953 bzero(&mbx, sizeof(struct oce_mbx)); 1954 1955 /* Initialize MODIFY_EQ_DELAY ioctl header */ 1956 fwcmd = (struct mbx_modify_common_eq_delay *)&mbx.payload; 1957 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 1958 MBX_SUBSYSTEM_COMMON, 1959 OPCODE_COMMON_MODIFY_EQ_DELAY, 1960 MBX_TIMEOUT_SEC, 1961 sizeof(struct mbx_modify_common_eq_delay), 1962 OCE_MBX_VER_V0); 1963 /* fill rest of mbx */ 1964 mbx.u0.s.embedded = 1; 1965 mbx.payload_length = sizeof(struct mbx_modify_common_eq_delay); 1966 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 1967 1968 fwcmd->params.req.num_eq = num; 1969 for (i = 0; i < num; i++) { 1970 fwcmd->params.req.delay[i].eq_id = 1971 htole32(set_eqd[i].eq_id); 1972 fwcmd->params.req.delay[i].phase = 0; 1973 fwcmd->params.req.delay[i].dm = 1974 htole32(set_eqd[i].delay_multiplier); 1975 } 1976 1977 1978 /* command post */ 1979 rc = oce_mbox_post(sc, &mbx, NULL); 1980 1981 if (!rc) 1982 rc = fwcmd->hdr.u0.rsp.status; 1983 if (rc) 1984 device_printf(sc->dev, 1985 "%s failed - cmd status: %d addi status: %d\n", 1986 __FUNCTION__, rc, 1987 fwcmd->hdr.u0.rsp.additional_status); 1988 } 1989 1990 int 1991 oce_get_profile_config(POCE_SOFTC sc, uint32_t max_rss) 1992 { 1993 struct oce_mbx mbx; 1994 struct mbx_common_get_profile_config *fwcmd; 1995 int rc = 0; 1996 int version = 0; 1997 struct oce_mq_sge *sgl; 1998 OCE_DMA_MEM dma; 1999 uint32_t desc_count = 0; 2000 struct oce_nic_resc_desc *nic_desc = NULL; 2001 int i; 2002 boolean_t nic_desc_valid = FALSE; 2003 2004 if (IS_BE2(sc)) 2005 return -1; 2006 2007 /* Allocate DMA mem*/ 2008 if (oce_dma_alloc(sc, sizeof(struct mbx_common_get_profile_config), 2009 &dma, 0)) 2010 return ENOMEM; 2011 2012 /* Initialize MODIFY_EQ_DELAY ioctl header */ 2013 fwcmd = OCE_DMAPTR(&dma, struct mbx_common_get_profile_config); 2014 bzero(fwcmd, sizeof(struct mbx_common_get_profile_config)); 2015 2016 if (!IS_XE201(sc)) 2017 version = OCE_MBX_VER_V1; 2018 else 2019 version = OCE_MBX_VER_V0; 2020 2021 bzero(&mbx, sizeof(struct oce_mbx)); 2022 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 2023 MBX_SUBSYSTEM_COMMON, 2024 OPCODE_COMMON_GET_PROFILE_CONFIG, 2025 MBX_TIMEOUT_SEC, 2026 sizeof(struct mbx_common_get_profile_config), 2027 version); 2028 /* fill rest of mbx */ 2029 mbx.u0.s.embedded = 0; 2030 mbx.payload_length = sizeof(struct mbx_common_get_profile_config); 2031 mbx.u0.s.sge_count = 1; 2032 sgl = &mbx.payload.u0.u1.sgl[0]; 2033 sgl->pa_hi = htole32(upper_32_bits(dma.paddr)); 2034 sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF); 2035 sgl->length = htole32(mbx.payload_length); 2036 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 2037 2038 fwcmd->params.req.type = ACTIVE_PROFILE; 2039 2040 /* command post */ 2041 rc = oce_mbox_post(sc, &mbx, NULL); 2042 if (!rc) 2043 rc = fwcmd->hdr.u0.rsp.status; 2044 if (rc) { 2045 device_printf(sc->dev, 2046 "%s failed - cmd status: %d addi status: %d\n", 2047 __FUNCTION__, rc, 2048 fwcmd->hdr.u0.rsp.additional_status); 2049 goto error; 2050 } 2051 2052 nic_desc = (struct oce_nic_resc_desc *) fwcmd->params.rsp.resources; 2053 desc_count = HOST_32(fwcmd->params.rsp.desc_count); 2054 for (i = 0; i < desc_count; i++) { 2055 if ((nic_desc->desc_type == NIC_RESC_DESC_TYPE_V0) || 2056 (nic_desc->desc_type == NIC_RESC_DESC_TYPE_V1)) { 2057 nic_desc_valid = TRUE; 2058 break; 2059 } 2060 nic_desc = (struct oce_nic_resc_desc *) \ 2061 ((char *)nic_desc + nic_desc->desc_len); 2062 } 2063 if (!nic_desc_valid) { 2064 rc = -1; 2065 goto error; 2066 } 2067 else { 2068 sc->max_vlans = HOST_16(nic_desc->vlan_count); 2069 sc->nwqs = HOST_16(nic_desc->txq_count); 2070 if (sc->nwqs) 2071 sc->nwqs = MIN(sc->nwqs, OCE_MAX_WQ); 2072 else 2073 sc->nwqs = OCE_MAX_WQ; 2074 2075 sc->nrssqs = HOST_16(nic_desc->rssq_count); 2076 if (sc->nrssqs) 2077 sc->nrssqs = MIN(sc->nrssqs, max_rss); 2078 else 2079 sc->nrssqs = max_rss; 2080 sc->nrqs = sc->nrssqs + 1; /* 1 for def RX */ 2081 2082 } 2083 error: 2084 oce_dma_free(sc, &dma); 2085 return rc; 2086 2087 } 2088 2089 int 2090 oce_get_func_config(POCE_SOFTC sc) 2091 { 2092 struct oce_mbx mbx; 2093 struct mbx_common_get_func_config *fwcmd; 2094 int rc = 0; 2095 int version = 0; 2096 struct oce_mq_sge *sgl; 2097 OCE_DMA_MEM dma; 2098 uint32_t desc_count = 0; 2099 struct oce_nic_resc_desc *nic_desc = NULL; 2100 int i; 2101 boolean_t nic_desc_valid = FALSE; 2102 uint32_t max_rss = 0; 2103 2104 if ((IS_BE(sc) || IS_SH(sc)) && (!sc->be3_native)) 2105 max_rss = OCE_LEGACY_MODE_RSS; 2106 else 2107 max_rss = OCE_MAX_RSS; 2108 2109 /* Allocate DMA mem*/ 2110 if (oce_dma_alloc(sc, sizeof(struct mbx_common_get_func_config), 2111 &dma, 0)) 2112 return ENOMEM; 2113 2114 /* Initialize MODIFY_EQ_DELAY ioctl header */ 2115 fwcmd = OCE_DMAPTR(&dma, struct mbx_common_get_func_config); 2116 bzero(fwcmd, sizeof(struct mbx_common_get_func_config)); 2117 2118 if (IS_SH(sc)) 2119 version = OCE_MBX_VER_V1; 2120 else 2121 version = OCE_MBX_VER_V0; 2122 2123 bzero(&mbx, sizeof(struct oce_mbx)); 2124 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 2125 MBX_SUBSYSTEM_COMMON, 2126 OPCODE_COMMON_GET_FUNCTION_CONFIG, 2127 MBX_TIMEOUT_SEC, 2128 sizeof(struct mbx_common_get_func_config), 2129 version); 2130 /* fill rest of mbx */ 2131 mbx.u0.s.embedded = 0; 2132 mbx.payload_length = sizeof(struct mbx_common_get_func_config); 2133 mbx.u0.s.sge_count = 1; 2134 sgl = &mbx.payload.u0.u1.sgl[0]; 2135 sgl->pa_hi = htole32(upper_32_bits(dma.paddr)); 2136 sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF); 2137 sgl->length = htole32(mbx.payload_length); 2138 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 2139 2140 /* command post */ 2141 rc = oce_mbox_post(sc, &mbx, NULL); 2142 if (!rc) 2143 rc = fwcmd->hdr.u0.rsp.status; 2144 if (rc) { 2145 device_printf(sc->dev, 2146 "%s failed - cmd status: %d addi status: %d\n", 2147 __FUNCTION__, rc, 2148 fwcmd->hdr.u0.rsp.additional_status); 2149 goto error; 2150 } 2151 2152 nic_desc = (struct oce_nic_resc_desc *) fwcmd->params.rsp.resources; 2153 desc_count = HOST_32(fwcmd->params.rsp.desc_count); 2154 for (i = 0; i < desc_count; i++) { 2155 if ((nic_desc->desc_type == NIC_RESC_DESC_TYPE_V0) || 2156 (nic_desc->desc_type == NIC_RESC_DESC_TYPE_V1)) { 2157 nic_desc_valid = TRUE; 2158 break; 2159 } 2160 nic_desc = (struct oce_nic_resc_desc *) \ 2161 ((char *)nic_desc + nic_desc->desc_len); 2162 } 2163 if (!nic_desc_valid) { 2164 rc = -1; 2165 goto error; 2166 } 2167 else { 2168 sc->max_vlans = nic_desc->vlan_count; 2169 sc->nwqs = HOST_32(nic_desc->txq_count); 2170 if (sc->nwqs) 2171 sc->nwqs = MIN(sc->nwqs, OCE_MAX_WQ); 2172 else 2173 sc->nwqs = OCE_MAX_WQ; 2174 2175 sc->nrssqs = HOST_32(nic_desc->rssq_count); 2176 if (sc->nrssqs) 2177 sc->nrssqs = MIN(sc->nrssqs, max_rss); 2178 else 2179 sc->nrssqs = max_rss; 2180 sc->nrqs = sc->nrssqs + 1; /* 1 for def RX */ 2181 } 2182 error: 2183 oce_dma_free(sc, &dma); 2184 return rc; 2185 2186 } 2187 2188 /* hw lro functions */ 2189 2190 int 2191 oce_mbox_nic_query_lro_capabilities(POCE_SOFTC sc, uint32_t *lro_rq_cnt, uint32_t *lro_flags) 2192 { 2193 struct oce_mbx mbx; 2194 struct mbx_nic_query_lro_capabilities *fwcmd; 2195 int rc = 0; 2196 2197 bzero(&mbx, sizeof(struct oce_mbx)); 2198 2199 fwcmd = (struct mbx_nic_query_lro_capabilities *)&mbx.payload; 2200 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 2201 MBX_SUBSYSTEM_NIC, 2202 0x20,MBX_TIMEOUT_SEC, 2203 sizeof(struct mbx_nic_query_lro_capabilities), 2204 OCE_MBX_VER_V0); 2205 2206 mbx.u0.s.embedded = 1; 2207 mbx.payload_length = sizeof(struct mbx_nic_query_lro_capabilities); 2208 2209 rc = oce_mbox_post(sc, &mbx, NULL); 2210 if (!rc) 2211 rc = fwcmd->hdr.u0.rsp.status; 2212 if (rc) { 2213 device_printf(sc->dev, 2214 "%s failed - cmd status: %d addi status: %d\n", 2215 __FUNCTION__, rc, 2216 fwcmd->hdr.u0.rsp.additional_status); 2217 2218 return rc; 2219 } 2220 if(lro_flags) 2221 *lro_flags = HOST_32(fwcmd->params.rsp.lro_flags); 2222 2223 if(lro_rq_cnt) 2224 *lro_rq_cnt = HOST_16(fwcmd->params.rsp.lro_rq_cnt); 2225 2226 return rc; 2227 } 2228 2229 int 2230 oce_mbox_nic_set_iface_lro_config(POCE_SOFTC sc, int enable) 2231 { 2232 struct oce_mbx mbx; 2233 struct mbx_nic_set_iface_lro_config *fwcmd; 2234 int rc = 0; 2235 2236 bzero(&mbx, sizeof(struct oce_mbx)); 2237 2238 fwcmd = (struct mbx_nic_set_iface_lro_config *)&mbx.payload; 2239 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 2240 MBX_SUBSYSTEM_NIC, 2241 0x26,MBX_TIMEOUT_SEC, 2242 sizeof(struct mbx_nic_set_iface_lro_config), 2243 OCE_MBX_VER_V0); 2244 2245 mbx.u0.s.embedded = 1; 2246 mbx.payload_length = sizeof(struct mbx_nic_set_iface_lro_config); 2247 2248 fwcmd->params.req.iface_id = sc->if_id; 2249 fwcmd->params.req.lro_flags = 0; 2250 2251 if(enable) { 2252 fwcmd->params.req.lro_flags = LRO_FLAGS_HASH_MODE | LRO_FLAGS_RSS_MODE; 2253 fwcmd->params.req.lro_flags |= LRO_FLAGS_CLSC_IPV4 | LRO_FLAGS_CLSC_IPV6; 2254 2255 fwcmd->params.req.max_clsc_byte_cnt = 64*1024; /* min = 2974, max = 0xfa59 */ 2256 fwcmd->params.req.max_clsc_seg_cnt = 43; /* min = 2, max = 64 */ 2257 fwcmd->params.req.max_clsc_usec_delay = 18; /* min = 1, max = 256 */ 2258 fwcmd->params.req.min_clsc_frame_byte_cnt = 0; /* min = 1, max = 9014 */ 2259 } 2260 2261 rc = oce_mbox_post(sc, &mbx, NULL); 2262 if (!rc) 2263 rc = fwcmd->hdr.u0.rsp.status; 2264 if (rc) { 2265 device_printf(sc->dev, 2266 "%s failed - cmd status: %d addi status: %d\n", 2267 __FUNCTION__, rc, 2268 fwcmd->hdr.u0.rsp.additional_status); 2269 2270 return rc; 2271 } 2272 return rc; 2273 } 2274 2275 int 2276 oce_mbox_create_rq_v2(struct oce_rq *rq) 2277 { 2278 struct oce_mbx mbx; 2279 struct mbx_create_nic_rq_v2 *fwcmd; 2280 POCE_SOFTC sc = rq->parent; 2281 int rc = 0, num_pages = 0; 2282 2283 if (rq->qstate == QCREATED) 2284 return 0; 2285 2286 bzero(&mbx, sizeof(struct oce_mbx)); 2287 2288 fwcmd = (struct mbx_create_nic_rq_v2 *)&mbx.payload; 2289 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 2290 MBX_SUBSYSTEM_NIC, 2291 0x08, MBX_TIMEOUT_SEC, 2292 sizeof(struct mbx_create_nic_rq_v2), 2293 OCE_MBX_VER_V2); 2294 2295 /* oce_page_list will also prepare pages */ 2296 num_pages = oce_page_list(rq->ring, &fwcmd->params.req.pages[0]); 2297 2298 fwcmd->params.req.cq_id = rq->cq->cq_id; 2299 fwcmd->params.req.frag_size = rq->cfg.frag_size/2048; 2300 fwcmd->params.req.num_pages = num_pages; 2301 2302 fwcmd->params.req.if_id = sc->if_id; 2303 2304 fwcmd->params.req.max_frame_size = rq->cfg.mtu; 2305 fwcmd->params.req.page_size = 1; 2306 if(rq->cfg.is_rss_queue) { 2307 fwcmd->params.req.rq_flags = (NIC_RQ_FLAGS_RSS | NIC_RQ_FLAGS_LRO); 2308 }else { 2309 device_printf(sc->dev, 2310 "non rss lro queue should not be created \n"); 2311 goto error; 2312 } 2313 mbx.u0.s.embedded = 1; 2314 mbx.payload_length = sizeof(struct mbx_create_nic_rq_v2); 2315 2316 rc = oce_mbox_post(sc, &mbx, NULL); 2317 if (!rc) 2318 rc = fwcmd->hdr.u0.rsp.status; 2319 if (rc) { 2320 device_printf(sc->dev, 2321 "%s failed - cmd status: %d addi status: %d\n", 2322 __FUNCTION__, rc, 2323 fwcmd->hdr.u0.rsp.additional_status); 2324 goto error; 2325 } 2326 rq->rq_id = HOST_16(fwcmd->params.rsp.rq_id); 2327 rq->rss_cpuid = fwcmd->params.rsp.rss_cpuid; 2328 2329 error: 2330 return rc; 2331 } 2332 2333