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 44 #include "oce_if.h" 45 46 static int oce_POST(POCE_SOFTC sc); 47 48 /** 49 * @brief Function to post status 50 * @param sc software handle to the device 51 */ 52 static int 53 oce_POST(POCE_SOFTC sc) 54 { 55 mpu_ep_semaphore_t post_status; 56 int tmo = 60000; 57 58 /* read semaphore CSR */ 59 post_status.dw0 = OCE_READ_CSR_MPU(sc, csr, MPU_EP_SEMAPHORE(sc)); 60 61 /* if host is ready then wait for fw ready else send POST */ 62 if (post_status.bits.stage <= POST_STAGE_AWAITING_HOST_RDY) { 63 post_status.bits.stage = POST_STAGE_CHIP_RESET; 64 OCE_WRITE_CSR_MPU(sc, csr, MPU_EP_SEMAPHORE(sc), post_status.dw0); 65 } 66 67 /* wait for FW ready */ 68 for (;;) { 69 if (--tmo == 0) 70 break; 71 72 DELAY(1000); 73 74 post_status.dw0 = OCE_READ_CSR_MPU(sc, csr, MPU_EP_SEMAPHORE(sc)); 75 if (post_status.bits.error) { 76 device_printf(sc->dev, 77 "POST failed: %x\n", post_status.dw0); 78 return ENXIO; 79 } 80 if (post_status.bits.stage == POST_STAGE_ARMFW_READY) 81 return 0; 82 } 83 84 device_printf(sc->dev, "POST timed out: %x\n", post_status.dw0); 85 86 return ENXIO; 87 } 88 89 /** 90 * @brief Function for hardware initialization 91 * @param sc software handle to the device 92 */ 93 int 94 oce_hw_init(POCE_SOFTC sc) 95 { 96 int rc = 0; 97 98 rc = oce_POST(sc); 99 if (rc) 100 return rc; 101 102 /* create the bootstrap mailbox */ 103 rc = oce_dma_alloc(sc, sizeof(struct oce_bmbx), &sc->bsmbx, 0); 104 if (rc) { 105 device_printf(sc->dev, "Mailbox alloc failed\n"); 106 return rc; 107 } 108 109 rc = oce_reset_fun(sc); 110 if (rc) 111 goto error; 112 113 114 rc = oce_mbox_init(sc); 115 if (rc) 116 goto error; 117 118 119 rc = oce_get_fw_version(sc); 120 if (rc) 121 goto error; 122 123 124 rc = oce_get_fw_config(sc); 125 if (rc) 126 goto error; 127 128 129 sc->macaddr.size_of_struct = 6; 130 rc = oce_read_mac_addr(sc, 0, 1, MAC_ADDRESS_TYPE_NETWORK, 131 &sc->macaddr); 132 if (rc) 133 goto error; 134 135 if ((IS_BE(sc) && (sc->flags & OCE_FLAGS_BE3)) || IS_SH(sc)) { 136 rc = oce_mbox_check_native_mode(sc); 137 if (rc) 138 goto error; 139 } else 140 sc->be3_native = 0; 141 142 return rc; 143 144 error: 145 oce_dma_free(sc, &sc->bsmbx); 146 device_printf(sc->dev, "Hardware initialisation failed\n"); 147 return rc; 148 } 149 150 151 152 /** 153 * @brief Releases the obtained pci resources 154 * @param sc software handle to the device 155 */ 156 void 157 oce_hw_pci_free(POCE_SOFTC sc) 158 { 159 int pci_cfg_barnum = 0; 160 161 if (IS_BE(sc) && (sc->flags & OCE_FLAGS_BE2)) 162 pci_cfg_barnum = OCE_DEV_BE2_CFG_BAR; 163 else 164 pci_cfg_barnum = OCE_DEV_CFG_BAR; 165 166 if (sc->devcfg_res != NULL) { 167 bus_release_resource(sc->dev, 168 SYS_RES_MEMORY, 169 PCIR_BAR(pci_cfg_barnum), sc->devcfg_res); 170 sc->devcfg_res = (struct resource *)NULL; 171 sc->devcfg_btag = (bus_space_tag_t) 0; 172 sc->devcfg_bhandle = (bus_space_handle_t)0; 173 sc->devcfg_vhandle = (void *)NULL; 174 } 175 176 if (sc->csr_res != NULL) { 177 bus_release_resource(sc->dev, 178 SYS_RES_MEMORY, 179 PCIR_BAR(OCE_PCI_CSR_BAR), sc->csr_res); 180 sc->csr_res = (struct resource *)NULL; 181 sc->csr_btag = (bus_space_tag_t)0; 182 sc->csr_bhandle = (bus_space_handle_t)0; 183 sc->csr_vhandle = (void *)NULL; 184 } 185 186 if (sc->db_res != NULL) { 187 bus_release_resource(sc->dev, 188 SYS_RES_MEMORY, 189 PCIR_BAR(OCE_PCI_DB_BAR), sc->db_res); 190 sc->db_res = (struct resource *)NULL; 191 sc->db_btag = (bus_space_tag_t)0; 192 sc->db_bhandle = (bus_space_handle_t)0; 193 sc->db_vhandle = (void *)NULL; 194 } 195 } 196 197 198 199 200 /** 201 * @brief Function to get the PCI capabilities 202 * @param sc software handle to the device 203 */ 204 static 205 void oce_get_pci_capabilities(POCE_SOFTC sc) 206 { 207 uint32_t val; 208 209 #if __FreeBSD_version >= 1000000 210 #define pci_find_extcap pci_find_cap 211 #endif 212 213 if (pci_find_extcap(sc->dev, PCIY_PCIX, &val) == 0) { 214 if (val != 0) 215 sc->flags |= OCE_FLAGS_PCIX; 216 } 217 218 if (pci_find_extcap(sc->dev, PCIY_EXPRESS, &val) == 0) { 219 if (val != 0) { 220 uint16_t link_status = 221 pci_read_config(sc->dev, val + 0x12, 2); 222 223 sc->flags |= OCE_FLAGS_PCIE; 224 sc->pcie_link_speed = link_status & 0xf; 225 sc->pcie_link_width = (link_status >> 4) & 0x3f; 226 } 227 } 228 229 if (pci_find_extcap(sc->dev, PCIY_MSI, &val) == 0) { 230 if (val != 0) 231 sc->flags |= OCE_FLAGS_MSI_CAPABLE; 232 } 233 234 if (pci_find_extcap(sc->dev, PCIY_MSIX, &val) == 0) { 235 if (val != 0) { 236 val = pci_msix_count(sc->dev); 237 sc->flags |= OCE_FLAGS_MSIX_CAPABLE; 238 } 239 } 240 } 241 242 /** 243 * @brief Allocate PCI resources. 244 * 245 * @param sc software handle to the device 246 * @returns 0 if successful, or error 247 */ 248 int 249 oce_hw_pci_alloc(POCE_SOFTC sc) 250 { 251 int rr, pci_cfg_barnum = 0; 252 pci_sli_intf_t intf; 253 254 pci_enable_busmaster(sc->dev); 255 256 oce_get_pci_capabilities(sc); 257 258 sc->fn = pci_get_function(sc->dev); 259 260 /* setup the device config region */ 261 if (IS_BE(sc) && (sc->flags & OCE_FLAGS_BE2)) 262 pci_cfg_barnum = OCE_DEV_BE2_CFG_BAR; 263 else 264 pci_cfg_barnum = OCE_DEV_CFG_BAR; 265 266 rr = PCIR_BAR(pci_cfg_barnum); 267 268 if (IS_BE(sc) || IS_SH(sc)) 269 sc->devcfg_res = bus_alloc_resource_any(sc->dev, 270 SYS_RES_MEMORY, &rr, 271 RF_ACTIVE|RF_SHAREABLE); 272 else 273 sc->devcfg_res = bus_alloc_resource_anywhere(sc->dev, 274 SYS_RES_MEMORY, &rr, 32768, 275 RF_ACTIVE|RF_SHAREABLE); 276 277 if (!sc->devcfg_res) 278 goto error; 279 280 sc->devcfg_btag = rman_get_bustag(sc->devcfg_res); 281 sc->devcfg_bhandle = rman_get_bushandle(sc->devcfg_res); 282 sc->devcfg_vhandle = rman_get_virtual(sc->devcfg_res); 283 284 /* Read the SLI_INTF register and determine whether we 285 * can use this port and its features 286 */ 287 intf.dw0 = pci_read_config((sc)->dev,OCE_INTF_REG_OFFSET,4); 288 289 if (intf.bits.sli_valid != OCE_INTF_VALID_SIG) 290 goto error; 291 292 if (intf.bits.sli_rev != OCE_INTF_SLI_REV4) { 293 device_printf(sc->dev, "Adapter doesnt support SLI4\n"); 294 goto error; 295 } 296 297 if (intf.bits.sli_if_type == OCE_INTF_IF_TYPE_1) 298 sc->flags |= OCE_FLAGS_MBOX_ENDIAN_RQD; 299 300 if (intf.bits.sli_hint1 == OCE_INTF_FUNC_RESET_REQD) 301 sc->flags |= OCE_FLAGS_FUNCRESET_RQD; 302 303 if (intf.bits.sli_func_type == OCE_INTF_VIRT_FUNC) 304 sc->flags |= OCE_FLAGS_VIRTUAL_PORT; 305 306 /* Lancer has one BAR (CFG) but BE3 has three (CFG, CSR, DB) */ 307 if (IS_BE(sc) || IS_SH(sc)) { 308 /* set up CSR region */ 309 rr = PCIR_BAR(OCE_PCI_CSR_BAR); 310 sc->csr_res = bus_alloc_resource_any(sc->dev, 311 SYS_RES_MEMORY, &rr, RF_ACTIVE|RF_SHAREABLE); 312 if (!sc->csr_res) 313 goto error; 314 sc->csr_btag = rman_get_bustag(sc->csr_res); 315 sc->csr_bhandle = rman_get_bushandle(sc->csr_res); 316 sc->csr_vhandle = rman_get_virtual(sc->csr_res); 317 318 /* set up DB doorbell region */ 319 rr = PCIR_BAR(OCE_PCI_DB_BAR); 320 sc->db_res = bus_alloc_resource_any(sc->dev, 321 SYS_RES_MEMORY, &rr, RF_ACTIVE|RF_SHAREABLE); 322 if (!sc->db_res) 323 goto error; 324 sc->db_btag = rman_get_bustag(sc->db_res); 325 sc->db_bhandle = rman_get_bushandle(sc->db_res); 326 sc->db_vhandle = rman_get_virtual(sc->db_res); 327 } 328 329 return 0; 330 331 error: 332 oce_hw_pci_free(sc); 333 return ENXIO; 334 } 335 336 337 /** 338 * @brief Function for device shutdown 339 * @param sc software handle to the device 340 * @returns 0 on success, error otherwise 341 */ 342 void 343 oce_hw_shutdown(POCE_SOFTC sc) 344 { 345 346 oce_stats_free(sc); 347 /* disable hardware interrupts */ 348 oce_hw_intr_disable(sc); 349 #if defined(INET6) || defined(INET) 350 /* Free LRO resources */ 351 oce_free_lro(sc); 352 #endif 353 /* Release queue*/ 354 oce_queue_release_all(sc); 355 /*Delete Network Interface*/ 356 oce_delete_nw_interface(sc); 357 /* After fw clean we dont send any cmds to fw.*/ 358 oce_fw_clean(sc); 359 /* release intr resources */ 360 oce_intr_free(sc); 361 /* release PCI resources */ 362 oce_hw_pci_free(sc); 363 /* free mbox specific resources */ 364 LOCK_DESTROY(&sc->bmbx_lock); 365 LOCK_DESTROY(&sc->dev_lock); 366 367 oce_dma_free(sc, &sc->bsmbx); 368 } 369 370 371 /** 372 * @brief Function for creating nw interface. 373 * @param sc software handle to the device 374 * @returns 0 on success, error otherwise 375 */ 376 int 377 oce_create_nw_interface(POCE_SOFTC sc) 378 { 379 int rc; 380 uint32_t capab_flags; 381 uint32_t capab_en_flags; 382 383 /* interface capabilities to give device when creating interface */ 384 capab_flags = OCE_CAPAB_FLAGS; 385 386 /* capabilities to enable by default (others set dynamically) */ 387 capab_en_flags = OCE_CAPAB_ENABLE; 388 389 if (IS_XE201(sc)) { 390 /* LANCER A0 workaround */ 391 capab_en_flags &= ~MBX_RX_IFACE_FLAGS_PASS_L3L4_ERR; 392 capab_flags &= ~MBX_RX_IFACE_FLAGS_PASS_L3L4_ERR; 393 } 394 395 if (IS_SH(sc) || IS_XE201(sc)) 396 capab_flags |= MBX_RX_IFACE_FLAGS_MULTICAST; 397 398 if (sc->enable_hwlro) { 399 capab_flags |= MBX_RX_IFACE_FLAGS_LRO; 400 capab_en_flags |= MBX_RX_IFACE_FLAGS_LRO; 401 } 402 403 /* enable capabilities controlled via driver startup parameters */ 404 if (is_rss_enabled(sc)) 405 capab_en_flags |= MBX_RX_IFACE_FLAGS_RSS; 406 else { 407 capab_en_flags &= ~MBX_RX_IFACE_FLAGS_RSS; 408 capab_flags &= ~MBX_RX_IFACE_FLAGS_RSS; 409 } 410 411 rc = oce_if_create(sc, 412 capab_flags, 413 capab_en_flags, 414 0, &sc->macaddr.mac_addr[0], &sc->if_id); 415 if (rc) 416 return rc; 417 418 atomic_inc_32(&sc->nifs); 419 420 sc->if_cap_flags = capab_en_flags; 421 422 /* set default flow control */ 423 rc = oce_set_flow_control(sc, sc->flow_control); 424 if (rc) 425 goto error; 426 427 rc = oce_rxf_set_promiscuous(sc, sc->promisc); 428 if (rc) 429 goto error; 430 431 return rc; 432 433 error: 434 oce_delete_nw_interface(sc); 435 return rc; 436 437 } 438 439 /** 440 * @brief Function to delete a nw interface. 441 * @param sc software handle to the device 442 */ 443 void 444 oce_delete_nw_interface(POCE_SOFTC sc) 445 { 446 /* currently only single interface is implmeneted */ 447 if (sc->nifs > 0) { 448 oce_if_del(sc, sc->if_id); 449 atomic_dec_32(&sc->nifs); 450 } 451 } 452 453 /** 454 * @brief Soft reset. 455 * @param sc software handle to the device 456 * @returns 0 on success, error otherwise 457 */ 458 int 459 oce_pci_soft_reset(POCE_SOFTC sc) 460 { 461 int rc; 462 mpu_ep_control_t ctrl; 463 464 ctrl.dw0 = OCE_READ_CSR_MPU(sc, csr, MPU_EP_CONTROL); 465 ctrl.bits.cpu_reset = 1; 466 OCE_WRITE_CSR_MPU(sc, csr, MPU_EP_CONTROL, ctrl.dw0); 467 DELAY(50); 468 rc=oce_POST(sc); 469 470 return rc; 471 } 472 473 /** 474 * @brief Function for hardware start 475 * @param sc software handle to the device 476 * @returns 0 on success, error otherwise 477 */ 478 int 479 oce_hw_start(POCE_SOFTC sc) 480 { 481 struct link_status link = { 0 }; 482 int rc = 0; 483 484 rc = oce_get_link_status(sc, &link); 485 if (rc) 486 return 1; 487 488 if (link.logical_link_status == NTWK_LOGICAL_LINK_UP) { 489 sc->link_status = NTWK_LOGICAL_LINK_UP; 490 if_link_state_change(sc->ifp, LINK_STATE_UP); 491 } else { 492 sc->link_status = NTWK_LOGICAL_LINK_DOWN; 493 if_link_state_change(sc->ifp, LINK_STATE_DOWN); 494 } 495 496 sc->link_speed = link.phys_port_speed; 497 sc->qos_link_speed = (uint32_t )link.qos_link_speed * 10; 498 499 rc = oce_start_mq(sc->mq); 500 501 /* we need to get MCC aync events. So enable intrs and arm 502 first EQ, Other EQs will be armed after interface is UP 503 */ 504 oce_hw_intr_enable(sc); 505 oce_arm_eq(sc, sc->eq[0]->eq_id, 0, TRUE, FALSE); 506 507 /* Send first mcc cmd and after that we get gracious 508 MCC notifications from FW 509 */ 510 oce_first_mcc_cmd(sc); 511 512 return rc; 513 } 514 515 516 /** 517 * @brief Function for hardware enable interupts. 518 * @param sc software handle to the device 519 */ 520 void 521 oce_hw_intr_enable(POCE_SOFTC sc) 522 { 523 uint32_t reg; 524 525 reg = OCE_READ_REG32(sc, devcfg, PCICFG_INTR_CTRL); 526 reg |= HOSTINTR_MASK; 527 OCE_WRITE_REG32(sc, devcfg, PCICFG_INTR_CTRL, reg); 528 529 } 530 531 532 /** 533 * @brief Function for hardware disable interupts 534 * @param sc software handle to the device 535 */ 536 void 537 oce_hw_intr_disable(POCE_SOFTC sc) 538 { 539 uint32_t reg; 540 541 reg = OCE_READ_REG32(sc, devcfg, PCICFG_INTR_CTRL); 542 reg &= ~HOSTINTR_MASK; 543 OCE_WRITE_REG32(sc, devcfg, PCICFG_INTR_CTRL, reg); 544 } 545 546 547 548 /** 549 * @brief Function for hardware update multicast filter 550 * @param sc software handle to the device 551 */ 552 int 553 oce_hw_update_multicast(POCE_SOFTC sc) 554 { 555 struct ifnet *ifp = sc->ifp; 556 struct ifmultiaddr *ifma; 557 struct mbx_set_common_iface_multicast *req = NULL; 558 OCE_DMA_MEM dma; 559 int rc = 0; 560 561 /* Allocate DMA mem*/ 562 if (oce_dma_alloc(sc, sizeof(struct mbx_set_common_iface_multicast), 563 &dma, 0)) 564 return ENOMEM; 565 566 req = OCE_DMAPTR(&dma, struct mbx_set_common_iface_multicast); 567 bzero(req, sizeof(struct mbx_set_common_iface_multicast)); 568 569 #if __FreeBSD_version > 800000 570 if_maddr_rlock(ifp); 571 #endif 572 CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 573 if (ifma->ifma_addr->sa_family != AF_LINK) 574 continue; 575 576 if (req->params.req.num_mac == OCE_MAX_MC_FILTER_SIZE) { 577 /*More multicast addresses than our hardware table 578 So Enable multicast promiscus in our hardware to 579 accept all multicat packets 580 */ 581 req->params.req.promiscuous = 1; 582 break; 583 } 584 bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), 585 &req->params.req.mac[req->params.req.num_mac], 586 ETH_ADDR_LEN); 587 req->params.req.num_mac = req->params.req.num_mac + 1; 588 } 589 #if __FreeBSD_version > 800000 590 if_maddr_runlock(ifp); 591 #endif 592 req->params.req.if_id = sc->if_id; 593 rc = oce_update_multicast(sc, &dma); 594 oce_dma_free(sc, &dma); 595 return rc; 596 } 597 598