1231437Sluigi/*- 2252869Sdelphij * Copyright (C) 2013 Emulex 3231437Sluigi * All rights reserved. 4231437Sluigi * 5231437Sluigi * Redistribution and use in source and binary forms, with or without 6231437Sluigi * modification, are permitted provided that the following conditions are met: 7231437Sluigi * 8231437Sluigi * 1. Redistributions of source code must retain the above copyright notice, 9231437Sluigi * this list of conditions and the following disclaimer. 10231437Sluigi * 11231437Sluigi * 2. Redistributions in binary form must reproduce the above copyright 12231437Sluigi * notice, this list of conditions and the following disclaimer in the 13231437Sluigi * documentation and/or other materials provided with the distribution. 14231437Sluigi * 15231437Sluigi * 3. Neither the name of the Emulex Corporation nor the names of its 16231437Sluigi * contributors may be used to endorse or promote products derived from 17231437Sluigi * this software without specific prior written permission. 18231437Sluigi * 19231437Sluigi * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20231437Sluigi * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21231437Sluigi * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22231437Sluigi * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23231437Sluigi * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24231437Sluigi * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25231437Sluigi * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26231437Sluigi * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27231437Sluigi * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28231437Sluigi * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29231437Sluigi * POSSIBILITY OF SUCH DAMAGE. 30231437Sluigi * 31231437Sluigi * Contact Information: 32231437Sluigi * freebsd-drivers@emulex.com 33231437Sluigi * 34231437Sluigi * Emulex 35231437Sluigi * 3333 Susan Street 36231437Sluigi * Costa Mesa, CA 92626 37231437Sluigi */ 38231437Sluigi 39231437Sluigi/* $FreeBSD$ */ 40231437Sluigi 41257187Sdelphij 42231437Sluigi#include "oce_if.h" 43231437Sluigi 44231437Sluigistatic int oce_POST(POCE_SOFTC sc); 45231437Sluigi 46231437Sluigi/** 47231437Sluigi * @brief Function to post status 48231437Sluigi * @param sc software handle to the device 49231437Sluigi */ 50231437Sluigistatic int 51231437Sluigioce_POST(POCE_SOFTC sc) 52231437Sluigi{ 53231437Sluigi mpu_ep_semaphore_t post_status; 54231437Sluigi int tmo = 60000; 55231437Sluigi 56231437Sluigi /* read semaphore CSR */ 57252869Sdelphij post_status.dw0 = OCE_READ_CSR_MPU(sc, csr, MPU_EP_SEMAPHORE(sc)); 58231437Sluigi 59231437Sluigi /* if host is ready then wait for fw ready else send POST */ 60231437Sluigi if (post_status.bits.stage <= POST_STAGE_AWAITING_HOST_RDY) { 61231437Sluigi post_status.bits.stage = POST_STAGE_CHIP_RESET; 62252869Sdelphij OCE_WRITE_CSR_MPU(sc, csr, MPU_EP_SEMAPHORE(sc), post_status.dw0); 63231437Sluigi } 64231437Sluigi 65231437Sluigi /* wait for FW ready */ 66231437Sluigi for (;;) { 67231437Sluigi if (--tmo == 0) 68231437Sluigi break; 69231437Sluigi 70231437Sluigi DELAY(1000); 71231437Sluigi 72252869Sdelphij post_status.dw0 = OCE_READ_CSR_MPU(sc, csr, MPU_EP_SEMAPHORE(sc)); 73231437Sluigi if (post_status.bits.error) { 74231437Sluigi device_printf(sc->dev, 75231437Sluigi "POST failed: %x\n", post_status.dw0); 76231437Sluigi return ENXIO; 77231437Sluigi } 78231437Sluigi if (post_status.bits.stage == POST_STAGE_ARMFW_READY) 79231437Sluigi return 0; 80231437Sluigi } 81231437Sluigi 82231437Sluigi device_printf(sc->dev, "POST timed out: %x\n", post_status.dw0); 83231437Sluigi 84231437Sluigi return ENXIO; 85231437Sluigi} 86231437Sluigi 87231437Sluigi/** 88231437Sluigi * @brief Function for hardware initialization 89231437Sluigi * @param sc software handle to the device 90231437Sluigi */ 91231437Sluigiint 92231437Sluigioce_hw_init(POCE_SOFTC sc) 93231437Sluigi{ 94231437Sluigi int rc = 0; 95231437Sluigi 96231437Sluigi rc = oce_POST(sc); 97231437Sluigi if (rc) 98231437Sluigi return rc; 99231437Sluigi 100231437Sluigi /* create the bootstrap mailbox */ 101231437Sluigi rc = oce_dma_alloc(sc, sizeof(struct oce_bmbx), &sc->bsmbx, 0); 102231437Sluigi if (rc) { 103231437Sluigi device_printf(sc->dev, "Mailbox alloc failed\n"); 104231437Sluigi return rc; 105231437Sluigi } 106231437Sluigi 107231437Sluigi rc = oce_reset_fun(sc); 108231437Sluigi if (rc) 109231437Sluigi goto error; 110231437Sluigi 111231437Sluigi 112231437Sluigi rc = oce_mbox_init(sc); 113231437Sluigi if (rc) 114231437Sluigi goto error; 115231437Sluigi 116231437Sluigi 117231437Sluigi rc = oce_get_fw_version(sc); 118231437Sluigi if (rc) 119231437Sluigi goto error; 120231437Sluigi 121231437Sluigi 122231437Sluigi rc = oce_get_fw_config(sc); 123231437Sluigi if (rc) 124231437Sluigi goto error; 125231437Sluigi 126231437Sluigi 127231437Sluigi sc->macaddr.size_of_struct = 6; 128231437Sluigi rc = oce_read_mac_addr(sc, 0, 1, MAC_ADDRESS_TYPE_NETWORK, 129231437Sluigi &sc->macaddr); 130231437Sluigi if (rc) 131231437Sluigi goto error; 132231437Sluigi 133252869Sdelphij if ((IS_BE(sc) && (sc->flags & OCE_FLAGS_BE3)) || IS_SH(sc)) { 134231437Sluigi rc = oce_mbox_check_native_mode(sc); 135231437Sluigi if (rc) 136231437Sluigi goto error; 137231437Sluigi } else 138231437Sluigi sc->be3_native = 0; 139231437Sluigi 140231437Sluigi return rc; 141231437Sluigi 142231437Sluigierror: 143231437Sluigi oce_dma_free(sc, &sc->bsmbx); 144231437Sluigi device_printf(sc->dev, "Hardware initialisation failed\n"); 145231437Sluigi return rc; 146231437Sluigi} 147231437Sluigi 148231437Sluigi 149231437Sluigi 150231437Sluigi/** 151231437Sluigi * @brief Releases the obtained pci resources 152231437Sluigi * @param sc software handle to the device 153231437Sluigi */ 154231437Sluigivoid 155231437Sluigioce_hw_pci_free(POCE_SOFTC sc) 156231437Sluigi{ 157231437Sluigi int pci_cfg_barnum = 0; 158231437Sluigi 159231437Sluigi if (IS_BE(sc) && (sc->flags & OCE_FLAGS_BE2)) 160231437Sluigi pci_cfg_barnum = OCE_DEV_BE2_CFG_BAR; 161231437Sluigi else 162231437Sluigi pci_cfg_barnum = OCE_DEV_CFG_BAR; 163231437Sluigi 164231437Sluigi if (sc->devcfg_res != NULL) { 165231437Sluigi bus_release_resource(sc->dev, 166231437Sluigi SYS_RES_MEMORY, 167231437Sluigi PCIR_BAR(pci_cfg_barnum), sc->devcfg_res); 168231437Sluigi sc->devcfg_res = (struct resource *)NULL; 169231437Sluigi sc->devcfg_btag = (bus_space_tag_t) 0; 170231437Sluigi sc->devcfg_bhandle = (bus_space_handle_t)0; 171231437Sluigi sc->devcfg_vhandle = (void *)NULL; 172231437Sluigi } 173231437Sluigi 174231437Sluigi if (sc->csr_res != NULL) { 175231437Sluigi bus_release_resource(sc->dev, 176231437Sluigi SYS_RES_MEMORY, 177231437Sluigi PCIR_BAR(OCE_PCI_CSR_BAR), sc->csr_res); 178231437Sluigi sc->csr_res = (struct resource *)NULL; 179231437Sluigi sc->csr_btag = (bus_space_tag_t)0; 180231437Sluigi sc->csr_bhandle = (bus_space_handle_t)0; 181231437Sluigi sc->csr_vhandle = (void *)NULL; 182231437Sluigi } 183231437Sluigi 184231437Sluigi if (sc->db_res != NULL) { 185231437Sluigi bus_release_resource(sc->dev, 186231437Sluigi SYS_RES_MEMORY, 187231437Sluigi PCIR_BAR(OCE_PCI_DB_BAR), sc->db_res); 188231437Sluigi sc->db_res = (struct resource *)NULL; 189231437Sluigi sc->db_btag = (bus_space_tag_t)0; 190231437Sluigi sc->db_bhandle = (bus_space_handle_t)0; 191231437Sluigi sc->db_vhandle = (void *)NULL; 192231437Sluigi } 193231437Sluigi} 194231437Sluigi 195231437Sluigi 196231437Sluigi 197231437Sluigi 198231437Sluigi/** 199231437Sluigi * @brief Function to get the PCI capabilities 200231437Sluigi * @param sc software handle to the device 201231437Sluigi */ 202231437Sluigistatic 203231437Sluigivoid oce_get_pci_capabilities(POCE_SOFTC sc) 204231437Sluigi{ 205231437Sluigi uint32_t val; 206231437Sluigi 207257187Sdelphij#if __FreeBSD_version >= 1000000 208257187Sdelphij #define pci_find_extcap pci_find_cap 209257187Sdelphij#endif 210257187Sdelphij 211257187Sdelphij if (pci_find_extcap(sc->dev, PCIY_PCIX, &val) == 0) { 212231437Sluigi if (val != 0) 213231437Sluigi sc->flags |= OCE_FLAGS_PCIX; 214231437Sluigi } 215231437Sluigi 216257187Sdelphij if (pci_find_extcap(sc->dev, PCIY_EXPRESS, &val) == 0) { 217231437Sluigi if (val != 0) { 218231437Sluigi uint16_t link_status = 219231437Sluigi pci_read_config(sc->dev, val + 0x12, 2); 220231437Sluigi 221231437Sluigi sc->flags |= OCE_FLAGS_PCIE; 222231437Sluigi sc->pcie_link_speed = link_status & 0xf; 223231437Sluigi sc->pcie_link_width = (link_status >> 4) & 0x3f; 224231437Sluigi } 225231437Sluigi } 226231437Sluigi 227257187Sdelphij if (pci_find_extcap(sc->dev, PCIY_MSI, &val) == 0) { 228231437Sluigi if (val != 0) 229231437Sluigi sc->flags |= OCE_FLAGS_MSI_CAPABLE; 230231437Sluigi } 231231437Sluigi 232257187Sdelphij if (pci_find_extcap(sc->dev, PCIY_MSIX, &val) == 0) { 233231437Sluigi if (val != 0) { 234231437Sluigi val = pci_msix_count(sc->dev); 235231437Sluigi sc->flags |= OCE_FLAGS_MSIX_CAPABLE; 236231437Sluigi } 237231437Sluigi } 238231437Sluigi} 239231437Sluigi 240231437Sluigi/** 241231437Sluigi * @brief Allocate PCI resources. 242231437Sluigi * 243231437Sluigi * @param sc software handle to the device 244231437Sluigi * @returns 0 if successful, or error 245231437Sluigi */ 246231437Sluigiint 247231437Sluigioce_hw_pci_alloc(POCE_SOFTC sc) 248231437Sluigi{ 249231437Sluigi int rr, pci_cfg_barnum = 0; 250231437Sluigi pci_sli_intf_t intf; 251231437Sluigi 252231437Sluigi pci_enable_busmaster(sc->dev); 253231437Sluigi 254231437Sluigi oce_get_pci_capabilities(sc); 255231437Sluigi 256231437Sluigi sc->fn = pci_get_function(sc->dev); 257231437Sluigi 258231437Sluigi /* setup the device config region */ 259231437Sluigi if (IS_BE(sc) && (sc->flags & OCE_FLAGS_BE2)) 260231437Sluigi pci_cfg_barnum = OCE_DEV_BE2_CFG_BAR; 261231437Sluigi else 262231437Sluigi pci_cfg_barnum = OCE_DEV_CFG_BAR; 263231437Sluigi 264231437Sluigi rr = PCIR_BAR(pci_cfg_barnum); 265231437Sluigi 266252869Sdelphij if (IS_BE(sc) || IS_SH(sc)) 267231437Sluigi sc->devcfg_res = bus_alloc_resource_any(sc->dev, 268231437Sluigi SYS_RES_MEMORY, &rr, 269231437Sluigi RF_ACTIVE|RF_SHAREABLE); 270231437Sluigi else 271231437Sluigi sc->devcfg_res = bus_alloc_resource(sc->dev, 272231437Sluigi SYS_RES_MEMORY, &rr, 273231437Sluigi 0ul, ~0ul, 32768, 274231437Sluigi RF_ACTIVE|RF_SHAREABLE); 275231437Sluigi 276231437Sluigi if (!sc->devcfg_res) 277231437Sluigi goto error; 278231437Sluigi 279231437Sluigi sc->devcfg_btag = rman_get_bustag(sc->devcfg_res); 280231437Sluigi sc->devcfg_bhandle = rman_get_bushandle(sc->devcfg_res); 281231437Sluigi sc->devcfg_vhandle = rman_get_virtual(sc->devcfg_res); 282231437Sluigi 283231437Sluigi /* Read the SLI_INTF register and determine whether we 284231437Sluigi * can use this port and its features 285231437Sluigi */ 286231437Sluigi intf.dw0 = pci_read_config((sc)->dev,OCE_INTF_REG_OFFSET,4); 287231437Sluigi 288231437Sluigi if (intf.bits.sli_valid != OCE_INTF_VALID_SIG) 289231437Sluigi goto error; 290231437Sluigi 291231437Sluigi if (intf.bits.sli_rev != OCE_INTF_SLI_REV4) { 292231437Sluigi device_printf(sc->dev, "Adapter doesnt support SLI4\n"); 293231437Sluigi goto error; 294231437Sluigi } 295231437Sluigi 296231437Sluigi if (intf.bits.sli_if_type == OCE_INTF_IF_TYPE_1) 297231437Sluigi sc->flags |= OCE_FLAGS_MBOX_ENDIAN_RQD; 298231437Sluigi 299231437Sluigi if (intf.bits.sli_hint1 == OCE_INTF_FUNC_RESET_REQD) 300231437Sluigi sc->flags |= OCE_FLAGS_FUNCRESET_RQD; 301231437Sluigi 302231437Sluigi if (intf.bits.sli_func_type == OCE_INTF_VIRT_FUNC) 303231437Sluigi sc->flags |= OCE_FLAGS_VIRTUAL_PORT; 304231437Sluigi 305231437Sluigi /* Lancer has one BAR (CFG) but BE3 has three (CFG, CSR, DB) */ 306252869Sdelphij if (IS_BE(sc) || IS_SH(sc)) { 307231437Sluigi /* set up CSR region */ 308231437Sluigi rr = PCIR_BAR(OCE_PCI_CSR_BAR); 309231437Sluigi sc->csr_res = bus_alloc_resource_any(sc->dev, 310231437Sluigi SYS_RES_MEMORY, &rr, RF_ACTIVE|RF_SHAREABLE); 311231437Sluigi if (!sc->csr_res) 312231437Sluigi goto error; 313231437Sluigi sc->csr_btag = rman_get_bustag(sc->csr_res); 314231437Sluigi sc->csr_bhandle = rman_get_bushandle(sc->csr_res); 315231437Sluigi sc->csr_vhandle = rman_get_virtual(sc->csr_res); 316231437Sluigi 317231437Sluigi /* set up DB doorbell region */ 318231437Sluigi rr = PCIR_BAR(OCE_PCI_DB_BAR); 319231437Sluigi sc->db_res = bus_alloc_resource_any(sc->dev, 320231437Sluigi SYS_RES_MEMORY, &rr, RF_ACTIVE|RF_SHAREABLE); 321231437Sluigi if (!sc->db_res) 322231437Sluigi goto error; 323231437Sluigi sc->db_btag = rman_get_bustag(sc->db_res); 324231437Sluigi sc->db_bhandle = rman_get_bushandle(sc->db_res); 325231437Sluigi sc->db_vhandle = rman_get_virtual(sc->db_res); 326231437Sluigi } 327231437Sluigi 328231437Sluigi return 0; 329231437Sluigi 330231437Sluigierror: 331231437Sluigi oce_hw_pci_free(sc); 332231437Sluigi return ENXIO; 333231437Sluigi} 334231437Sluigi 335231437Sluigi 336231437Sluigi/** 337231437Sluigi * @brief Function for device shutdown 338231437Sluigi * @param sc software handle to the device 339231437Sluigi * @returns 0 on success, error otherwise 340231437Sluigi */ 341231437Sluigivoid 342231437Sluigioce_hw_shutdown(POCE_SOFTC sc) 343231437Sluigi{ 344231437Sluigi 345231437Sluigi oce_stats_free(sc); 346231437Sluigi /* disable hardware interrupts */ 347231437Sluigi oce_hw_intr_disable(sc); 348231879Sluigi#if defined(INET6) || defined(INET) 349231437Sluigi /* Free LRO resources */ 350231437Sluigi oce_free_lro(sc); 351231879Sluigi#endif 352231437Sluigi /* Release queue*/ 353231437Sluigi oce_queue_release_all(sc); 354231437Sluigi /*Delete Network Interface*/ 355231437Sluigi oce_delete_nw_interface(sc); 356231437Sluigi /* After fw clean we dont send any cmds to fw.*/ 357231437Sluigi oce_fw_clean(sc); 358231437Sluigi /* release intr resources */ 359231437Sluigi oce_intr_free(sc); 360231437Sluigi /* release PCI resources */ 361231437Sluigi oce_hw_pci_free(sc); 362231437Sluigi /* free mbox specific resources */ 363231437Sluigi LOCK_DESTROY(&sc->bmbx_lock); 364231437Sluigi LOCK_DESTROY(&sc->dev_lock); 365231437Sluigi 366231437Sluigi oce_dma_free(sc, &sc->bsmbx); 367231437Sluigi} 368231437Sluigi 369231437Sluigi 370231437Sluigi/** 371231437Sluigi * @brief Function for creating nw interface. 372231437Sluigi * @param sc software handle to the device 373231437Sluigi * @returns 0 on success, error otherwise 374231437Sluigi */ 375231437Sluigiint 376231437Sluigioce_create_nw_interface(POCE_SOFTC sc) 377231437Sluigi{ 378231437Sluigi int rc; 379231437Sluigi uint32_t capab_flags; 380231437Sluigi uint32_t capab_en_flags; 381231437Sluigi 382231437Sluigi /* interface capabilities to give device when creating interface */ 383231437Sluigi capab_flags = OCE_CAPAB_FLAGS; 384231437Sluigi 385231437Sluigi /* capabilities to enable by default (others set dynamically) */ 386231437Sluigi capab_en_flags = OCE_CAPAB_ENABLE; 387231437Sluigi 388231437Sluigi if (IS_XE201(sc)) { 389231437Sluigi /* LANCER A0 workaround */ 390231437Sluigi capab_en_flags &= ~MBX_RX_IFACE_FLAGS_PASS_L3L4_ERR; 391231437Sluigi capab_flags &= ~MBX_RX_IFACE_FLAGS_PASS_L3L4_ERR; 392231437Sluigi } 393231437Sluigi 394257187Sdelphij if (IS_SH(sc) || IS_XE201(sc)) 395257187Sdelphij capab_flags |= MBX_RX_IFACE_FLAGS_MULTICAST; 396257187Sdelphij 397231437Sluigi /* enable capabilities controlled via driver startup parameters */ 398252869Sdelphij if (is_rss_enabled(sc)) 399231437Sluigi capab_en_flags |= MBX_RX_IFACE_FLAGS_RSS; 400231437Sluigi else { 401231437Sluigi capab_en_flags &= ~MBX_RX_IFACE_FLAGS_RSS; 402231437Sluigi capab_flags &= ~MBX_RX_IFACE_FLAGS_RSS; 403231437Sluigi } 404231437Sluigi 405231437Sluigi rc = oce_if_create(sc, 406231437Sluigi capab_flags, 407231437Sluigi capab_en_flags, 408231437Sluigi 0, &sc->macaddr.mac_addr[0], &sc->if_id); 409231437Sluigi if (rc) 410231437Sluigi return rc; 411231437Sluigi 412231437Sluigi atomic_inc_32(&sc->nifs); 413231437Sluigi 414231437Sluigi sc->if_cap_flags = capab_en_flags; 415231437Sluigi 416231437Sluigi /* set default flow control */ 417231437Sluigi rc = oce_set_flow_control(sc, sc->flow_control); 418231437Sluigi if (rc) 419231437Sluigi goto error; 420231437Sluigi 421231437Sluigi rc = oce_rxf_set_promiscuous(sc, sc->promisc); 422231437Sluigi if (rc) 423231437Sluigi goto error; 424231437Sluigi 425231437Sluigi return rc; 426231437Sluigi 427231437Sluigierror: 428231437Sluigi oce_delete_nw_interface(sc); 429231437Sluigi return rc; 430231437Sluigi 431231437Sluigi} 432231437Sluigi 433231437Sluigi/** 434231437Sluigi * @brief Function to delete a nw interface. 435231437Sluigi * @param sc software handle to the device 436231437Sluigi */ 437231437Sluigivoid 438231437Sluigioce_delete_nw_interface(POCE_SOFTC sc) 439231437Sluigi{ 440231437Sluigi /* currently only single interface is implmeneted */ 441231437Sluigi if (sc->nifs > 0) { 442231437Sluigi oce_if_del(sc, sc->if_id); 443231437Sluigi atomic_dec_32(&sc->nifs); 444231437Sluigi } 445231437Sluigi} 446231437Sluigi 447231437Sluigi/** 448231437Sluigi * @brief Soft reset. 449231437Sluigi * @param sc software handle to the device 450231437Sluigi * @returns 0 on success, error otherwise 451231437Sluigi */ 452231437Sluigiint 453231437Sluigioce_pci_soft_reset(POCE_SOFTC sc) 454231437Sluigi{ 455231437Sluigi int rc; 456231437Sluigi mpu_ep_control_t ctrl; 457231437Sluigi 458252869Sdelphij ctrl.dw0 = OCE_READ_CSR_MPU(sc, csr, MPU_EP_CONTROL); 459231437Sluigi ctrl.bits.cpu_reset = 1; 460252869Sdelphij OCE_WRITE_CSR_MPU(sc, csr, MPU_EP_CONTROL, ctrl.dw0); 461231437Sluigi DELAY(50); 462231437Sluigi rc=oce_POST(sc); 463231437Sluigi 464231437Sluigi return rc; 465231437Sluigi} 466231437Sluigi 467231437Sluigi/** 468231437Sluigi * @brief Function for hardware start 469231437Sluigi * @param sc software handle to the device 470231437Sluigi * @returns 0 on success, error otherwise 471231437Sluigi */ 472231437Sluigiint 473231437Sluigioce_hw_start(POCE_SOFTC sc) 474231437Sluigi{ 475231437Sluigi struct link_status link = { 0 }; 476231437Sluigi int rc = 0; 477231437Sluigi 478231437Sluigi rc = oce_get_link_status(sc, &link); 479231437Sluigi if (rc) 480231437Sluigi return 1; 481231437Sluigi 482231437Sluigi if (link.logical_link_status == NTWK_LOGICAL_LINK_UP) { 483231437Sluigi sc->link_status = NTWK_LOGICAL_LINK_UP; 484231437Sluigi if_link_state_change(sc->ifp, LINK_STATE_UP); 485231437Sluigi } else { 486231437Sluigi sc->link_status = NTWK_LOGICAL_LINK_DOWN; 487231437Sluigi if_link_state_change(sc->ifp, LINK_STATE_DOWN); 488231437Sluigi } 489231437Sluigi 490268046Sdelphij sc->link_speed = link.phys_port_speed; 491231437Sluigi sc->qos_link_speed = (uint32_t )link.qos_link_speed * 10; 492231437Sluigi 493231437Sluigi rc = oce_start_mq(sc->mq); 494231437Sluigi 495231879Sluigi /* we need to get MCC aync events. So enable intrs and arm 496231879Sluigi first EQ, Other EQs will be armed after interface is UP 497231437Sluigi */ 498231437Sluigi oce_hw_intr_enable(sc); 499231437Sluigi oce_arm_eq(sc, sc->eq[0]->eq_id, 0, TRUE, FALSE); 500231437Sluigi 501231879Sluigi /* Send first mcc cmd and after that we get gracious 502231879Sluigi MCC notifications from FW 503231879Sluigi */ 504231879Sluigi oce_first_mcc_cmd(sc); 505231879Sluigi 506231437Sluigi return rc; 507231437Sluigi} 508231437Sluigi 509231437Sluigi 510231437Sluigi/** 511231437Sluigi * @brief Function for hardware enable interupts. 512231437Sluigi * @param sc software handle to the device 513231437Sluigi */ 514231437Sluigivoid 515231437Sluigioce_hw_intr_enable(POCE_SOFTC sc) 516231437Sluigi{ 517231437Sluigi uint32_t reg; 518231437Sluigi 519231437Sluigi reg = OCE_READ_REG32(sc, devcfg, PCICFG_INTR_CTRL); 520231437Sluigi reg |= HOSTINTR_MASK; 521231437Sluigi OCE_WRITE_REG32(sc, devcfg, PCICFG_INTR_CTRL, reg); 522231437Sluigi 523231437Sluigi} 524231437Sluigi 525231437Sluigi 526231437Sluigi/** 527231437Sluigi * @brief Function for hardware disable interupts 528231437Sluigi * @param sc software handle to the device 529231437Sluigi */ 530231437Sluigivoid 531231437Sluigioce_hw_intr_disable(POCE_SOFTC sc) 532231437Sluigi{ 533231437Sluigi uint32_t reg; 534231437Sluigi 535231437Sluigi reg = OCE_READ_REG32(sc, devcfg, PCICFG_INTR_CTRL); 536231437Sluigi reg &= ~HOSTINTR_MASK; 537231437Sluigi OCE_WRITE_REG32(sc, devcfg, PCICFG_INTR_CTRL, reg); 538231437Sluigi} 539231437Sluigi 540231437Sluigi 541231437Sluigi 542231437Sluigi/** 543231879Sluigi * @brief Function for hardware update multicast filter 544231879Sluigi * @param sc software handle to the device 545231437Sluigi */ 546231437Sluigiint 547231437Sluigioce_hw_update_multicast(POCE_SOFTC sc) 548231437Sluigi{ 549231437Sluigi struct ifnet *ifp = sc->ifp; 550231437Sluigi struct ifmultiaddr *ifma; 551231437Sluigi struct mbx_set_common_iface_multicast *req = NULL; 552231437Sluigi OCE_DMA_MEM dma; 553231437Sluigi int rc = 0; 554231437Sluigi 555231437Sluigi /* Allocate DMA mem*/ 556231437Sluigi if (oce_dma_alloc(sc, sizeof(struct mbx_set_common_iface_multicast), 557231437Sluigi &dma, 0)) 558231437Sluigi return ENOMEM; 559231437Sluigi 560231437Sluigi req = OCE_DMAPTR(&dma, struct mbx_set_common_iface_multicast); 561231437Sluigi bzero(req, sizeof(struct mbx_set_common_iface_multicast)); 562231437Sluigi 563231437Sluigi#if __FreeBSD_version > 800000 564231603Sjhb if_maddr_rlock(ifp); 565231437Sluigi#endif 566231437Sluigi TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 567231437Sluigi if (ifma->ifma_addr->sa_family != AF_LINK) 568231437Sluigi continue; 569231437Sluigi 570231437Sluigi if (req->params.req.num_mac == OCE_MAX_MC_FILTER_SIZE) { 571231437Sluigi /*More multicast addresses than our hardware table 572231437Sluigi So Enable multicast promiscus in our hardware to 573231437Sluigi accept all multicat packets 574231437Sluigi */ 575231437Sluigi req->params.req.promiscuous = 1; 576231437Sluigi break; 577231437Sluigi } 578231437Sluigi bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), 579231437Sluigi &req->params.req.mac[req->params.req.num_mac], 580231437Sluigi ETH_ADDR_LEN); 581231437Sluigi req->params.req.num_mac = req->params.req.num_mac + 1; 582231437Sluigi } 583231437Sluigi#if __FreeBSD_version > 800000 584231603Sjhb if_maddr_runlock(ifp); 585231437Sluigi#endif 586231437Sluigi req->params.req.if_id = sc->if_id; 587231437Sluigi rc = oce_update_multicast(sc, &dma); 588231437Sluigi oce_dma_free(sc, &dma); 589231437Sluigi return rc; 590231437Sluigi} 591231437Sluigi 592