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