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