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