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