7096 vioif should not log to the console on boot, or ever
[unleashed.git] / usr / src / uts / common / io / bnxe / bnxe_main.c
blob8dc40ded8a8d515d2c9afb3ffdd4cce648f9a8de
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2014 QLogic Corporation
24 * The contents of this file are subject to the terms of the
25 * QLogic End User License (the "License").
26 * You may not use this file except in compliance with the License.
28 * You can obtain a copy of the License at
29 * http://www.qlogic.com/Resources/Documents/DriverDownloadHelp/
30 * QLogic_End_User_Software_License.txt
31 * See the License for the specific language governing permissions
32 * and limitations under the License.
36 * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
39 #include "bnxe.h"
41 #ifndef STRINGIFY
42 #define XSTRINGIFY(x) #x
43 #define STRINGIFY(x) XSTRINGIFY(x)
44 #endif
46 #define BNXE_PRODUCT_BANNER "QLogic NetXtreme II 10 Gigabit Ethernet Driver v" STRINGIFY(MAJVERSION) "." STRINGIFY(MINVERSION) "." STRINGIFY(REVVERSION)
47 #define BNXE_PRODUCT_INFO "QLogic NXII 10 GbE v" STRINGIFY(MAJVERSION) "." STRINGIFY(MINVERSION) "." STRINGIFY(REVVERSION)
49 #define BNXE_REGISTER_BAR_NUM 1
50 #define BNXE_REGS_MAP_OFFSET 0
51 #define BNXE_L2_MEMORY_WINDOW_SIZE 0x40000 /* 256K for PCI Config Registers */
53 u32_t dbg_code_path = CP_ALL;
54 u8_t dbg_trace_level = LV_VERBOSE;
55 u32_t g_dbg_flags = 0;
57 kmutex_t bnxeLoaderMutex;
58 u32_t bnxeNumPlumbed;
60 extern ddi_dma_attr_t bnxeDmaPageAttrib;
61 extern ddi_dma_attr_t bnxeRxDmaAttrib;
62 extern ddi_dma_attr_t bnxeTxDmaAttrib;
63 extern ddi_dma_attr_t bnxeTxCbDmaAttrib;
66 u8_t BnxeInstance(void * pDev)
68 um_device_t * pUM = (um_device_t *)pDev;
69 return (pUM == NULL) ? 0xf : pUM->instance;
73 /* pass in pointer to either lm_device_t or um_device_t */
74 char * BnxeDevName(void * pDev)
76 um_device_t * pUM = (um_device_t *)pDev;
77 return ((pUM == NULL) || (*pUM->devName == 0)) ? "(bnxe)" : pUM->devName;
81 char * BnxeChipName(um_device_t * pUM)
83 switch (CHIP_NUM(&pUM->lm_dev) >> 16)
85 case 0x164e: return "BCM57710";
86 case 0x164f: return "BCM57711";
87 case 0x1650: return "BCM57711E";
88 case 0x1662: return "BCM57712";
89 case 0x1663: return "BCM57712NP";
90 case 0x16a1: return "BCM57840";
91 case 0x168d: return "BCM57840";
92 case 0x16a4: return "BCM57840NP";
93 case 0x16ab: return "BCM57840NP";
94 case 0x168e: return "BCM57810";
95 case 0x16ae: return "BCM57810NP";
96 case 0x168a: return "BCM57800";
97 case 0x16a5: return "BCM57800NP";
98 default: return "UNKNOWN";
103 boolean_t BnxeProtoSupport(um_device_t * pUM, int proto)
105 boolean_t do_eth;
106 boolean_t do_fcoe;
107 uint32_t port_feature_config_sf;
109 if (IS_MULTI_VNIC(&pUM->lm_dev))
111 do_eth = B_FALSE;
112 do_fcoe = B_FALSE;
114 if (pUM->lm_dev.hw_info.mcp_detected == 1)
116 if (pUM->lm_dev.params.mf_proto_support_flags &
117 LM_PROTO_SUPPORT_ETHERNET)
119 do_eth = B_TRUE;
122 if (pUM->lm_dev.params.mf_proto_support_flags &
123 LM_PROTO_SUPPORT_FCOE)
125 do_fcoe = B_TRUE;
128 else
130 /* mcp is not present so allow enumeration */
131 do_eth = B_TRUE;
132 do_fcoe = B_TRUE;
135 else /* SF */
137 do_eth = B_TRUE;
138 do_fcoe = B_FALSE;
140 /* check per port storage personality config from NVRAM */
141 port_feature_config_sf = (pUM->lm_dev.hw_info.port_feature_config &
142 PORT_FEAT_CFG_STORAGE_PERSONALITY_MASK);
144 switch (port_feature_config_sf)
146 case PORT_FEAT_CFG_STORAGE_PERSONALITY_ISCSI:
147 break;
149 case PORT_FEAT_CFG_STORAGE_PERSONALITY_FCOE:
150 case PORT_FEAT_CFG_STORAGE_PERSONALITY_BOTH:
151 case PORT_FEAT_CFG_STORAGE_PERSONALITY_DEFAULT:
152 default:
153 do_fcoe = B_TRUE;
154 break;
158 if (pUM->lm_dev.params.max_func_fcoe_cons == 0)
160 do_fcoe = B_FALSE;
163 return (((proto == LM_PROTO_SUPPORT_ETHERNET) && do_eth) ||
164 ((proto == LM_PROTO_SUPPORT_FCOE) && do_fcoe));
168 boolean_t BnxeProtoFcoeAfex(um_device_t * pUM)
170 return ((pUM->lm_dev.params.mf_mode == MULTI_FUNCTION_AFEX) &&
171 BnxeProtoSupport(pUM, LM_PROTO_SUPPORT_FCOE)) ? B_TRUE : B_FALSE;
175 static boolean_t BnxePciInit(um_device_t * pUM)
177 /* setup resources needed for accessing the PCI configuration space */
178 if (pci_config_setup(pUM->pDev, &pUM->pPciCfg) != DDI_SUCCESS)
180 BnxeLogWarn(pUM, "Failed to setup PCI config");
181 return B_FALSE;
184 return B_TRUE;
188 static void BnxePciDestroy(um_device_t * pUM)
190 if (pUM->pPciCfg)
192 pci_config_teardown(&pUM->pPciCfg);
193 pUM->pPciCfg = NULL;
198 static void BnxeBarMemDestroy(um_device_t * pUM)
200 BnxeMemRegion * pMemRegion;
202 /* free the BAR mappings */
203 while (!d_list_is_empty(&pUM->memRegionList))
205 pMemRegion = (BnxeMemRegion *)d_list_peek_head(&pUM->memRegionList);
206 mm_unmap_io_space(&pUM->lm_dev,
207 pMemRegion->pRegAddr,
208 pMemRegion->size);
213 static void BnxeMutexInit(um_device_t * pUM)
215 lm_device_t * pLM = &pUM->lm_dev;
216 int idx;
218 for (idx = 0; idx < (MAX_RSS_CHAINS + 1); idx++)
220 mutex_init(&pUM->intrMutex[idx], NULL,
221 MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
222 mutex_init(&pUM->intrFlipMutex[idx], NULL,
223 MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
224 mutex_init(&pUM->sbMutex[idx], NULL,
225 MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
228 for (idx = 0; idx < MAX_ETH_CONS; idx++)
230 mutex_init(&pUM->txq[idx].txMutex, NULL,
231 MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
232 mutex_init(&pUM->txq[idx].freeTxDescMutex, NULL,
233 MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
234 pUM->txq[idx].pUM = pUM;
235 pUM->txq[idx].idx = idx;
238 for (idx = 0; idx < MAX_ETH_CONS; idx++)
240 mutex_init(&pUM->rxq[idx].rxMutex, NULL,
241 MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
242 mutex_init(&pUM->rxq[idx].doneRxMutex, NULL,
243 MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
244 pUM->rxq[idx].pUM = pUM;
245 pUM->rxq[idx].idx = idx;
248 for (idx = 0; idx < USER_OPTION_RX_RING_GROUPS_MAX; idx++)
250 pUM->rxqGroup[idx].pUM = pUM;
251 pUM->rxqGroup[idx].idx = idx;
254 mutex_init(&pUM->ethConMutex, NULL,
255 MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
256 mutex_init(&pUM->mcpMutex, NULL,
257 MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
258 mutex_init(&pUM->phyMutex, NULL,
259 MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
260 mutex_init(&pUM->indMutex, NULL,
261 MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
262 mutex_init(&pUM->cidMutex, NULL,
263 MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
264 mutex_init(&pUM->spqMutex, NULL,
265 MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
266 mutex_init(&pUM->spReqMutex, NULL,
267 MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
268 mutex_init(&pUM->rrReqMutex, NULL,
269 MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
270 mutex_init(&pUM->islesCtrlMutex, NULL,
271 MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
272 mutex_init(&pUM->toeMutex, NULL,
273 MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
274 mutex_init(&pUM->memMutex, NULL,
275 MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
276 mutex_init(&pUM->offloadMutex, NULL,
277 MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
278 mutex_init(&pUM->hwInitMutex, NULL,
279 MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
280 mutex_init(&pUM->gldMutex, NULL,
281 MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
282 rw_init(&pUM->gldTxMutex, NULL, RW_DRIVER, NULL);
283 mutex_init(&pUM->timerMutex, NULL,
284 MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
285 mutex_init(&pUM->kstatMutex, NULL,
286 MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
290 static void BnxeMutexDestroy(um_device_t * pUM)
292 lm_device_t * pLM = &pUM->lm_dev;
293 int idx;
295 for (idx = 0; idx < (MAX_RSS_CHAINS + 1); idx++)
297 mutex_destroy(&pUM->intrMutex[idx]);
298 mutex_destroy(&pUM->intrFlipMutex[idx]);
299 mutex_destroy(&pUM->sbMutex[idx]);
302 for (idx = 0; idx < MAX_ETH_CONS; idx++)
304 mutex_destroy(&pUM->txq[idx].txMutex);
305 mutex_destroy(&pUM->txq[idx].freeTxDescMutex);
308 for (idx = 0; idx < MAX_ETH_CONS; idx++)
310 mutex_destroy(&pUM->rxq[idx].rxMutex);
311 mutex_destroy(&pUM->rxq[idx].doneRxMutex);
314 mutex_destroy(&pUM->ethConMutex);
315 mutex_destroy(&pUM->mcpMutex);
316 mutex_destroy(&pUM->phyMutex);
317 mutex_destroy(&pUM->indMutex);
318 mutex_destroy(&pUM->cidMutex);
319 mutex_destroy(&pUM->spqMutex);
320 mutex_destroy(&pUM->spReqMutex);
321 mutex_destroy(&pUM->rrReqMutex);
322 mutex_destroy(&pUM->islesCtrlMutex);
323 mutex_destroy(&pUM->toeMutex);
324 mutex_destroy(&pUM->memMutex); /* not until all mem deleted */
325 mutex_destroy(&pUM->offloadMutex);
326 mutex_destroy(&pUM->hwInitMutex);
327 mutex_destroy(&pUM->gldMutex);
328 rw_destroy(&pUM->gldTxMutex);
329 mutex_destroy(&pUM->timerMutex);
330 mutex_destroy(&pUM->kstatMutex);
334 /* FMA support */
336 int BnxeCheckAccHandle(ddi_acc_handle_t handle)
338 ddi_fm_error_t de;
340 ddi_fm_acc_err_get(handle, &de, DDI_FME_VERSION);
341 ddi_fm_acc_err_clear(handle, DDI_FME_VERSION);
343 return (de.fme_status);
347 int BnxeCheckDmaHandle(ddi_dma_handle_t handle)
349 ddi_fm_error_t de;
351 ddi_fm_dma_err_get(handle, &de, DDI_FME_VERSION);
353 return (de.fme_status);
357 /* The IO fault service error handling callback function */
358 static int BnxeFmErrorCb(dev_info_t * pDev,
359 ddi_fm_error_t * err,
360 const void * impl_data)
363 * As the driver can always deal with an error in any dma or
364 * access handle, we can just return the fme_status value.
366 pci_ereport_post(pDev, err, NULL);
368 return (err->fme_status);
372 static void BnxeFmInit(um_device_t * pUM)
374 ddi_iblock_cookie_t iblk;
375 int fma_acc_flag;
376 int fma_dma_flag;
378 /* Only register with IO Fault Services if we have some capability */
379 if (pUM->fmCapabilities & DDI_FM_ACCCHK_CAPABLE)
381 bnxeAccessAttribBAR.devacc_attr_version = DDI_DEVICE_ATTR_V1;
382 bnxeAccessAttribBAR.devacc_attr_access = DDI_FLAGERR_ACC;
385 if (pUM->fmCapabilities & DDI_FM_DMACHK_CAPABLE)
387 bnxeDmaPageAttrib.dma_attr_flags = DDI_DMA_FLAGERR;
388 bnxeRxDmaAttrib.dma_attr_flags = DDI_DMA_FLAGERR;
389 bnxeTxDmaAttrib.dma_attr_flags = DDI_DMA_FLAGERR;
390 bnxeTxCbDmaAttrib.dma_attr_flags = DDI_DMA_FLAGERR;
393 if (pUM->fmCapabilities)
395 /* Register capabilities with IO Fault Services */
396 ddi_fm_init(pUM->pDev, &pUM->fmCapabilities, &iblk);
398 /* Initialize pci ereport capabilities if ereport capable */
399 if (DDI_FM_EREPORT_CAP(pUM->fmCapabilities) ||
400 DDI_FM_ERRCB_CAP(pUM->fmCapabilities))
402 pci_ereport_setup(pUM->pDev);
405 /* Register error callback if error callback capable */
406 if (DDI_FM_ERRCB_CAP(pUM->fmCapabilities))
408 ddi_fm_handler_register(pUM->pDev, BnxeFmErrorCb, (void *)pUM);
414 static void BnxeFmFini(um_device_t * pUM)
416 /* Only unregister FMA capabilities if we registered some */
417 if (pUM->fmCapabilities)
419 /* Release any resources allocated by pci_ereport_setup() */
420 if (DDI_FM_EREPORT_CAP(pUM->fmCapabilities) ||
421 DDI_FM_ERRCB_CAP(pUM->fmCapabilities))
423 pci_ereport_teardown(pUM->pDev);
426 /* Un-register error callback if error callback capable */
427 if (DDI_FM_ERRCB_CAP(pUM->fmCapabilities))
429 ddi_fm_handler_unregister(pUM->pDev);
432 /* Unregister from IO Fault Services */
433 ddi_fm_fini(pUM->pDev);
438 void BnxeFmErrorReport(um_device_t * pUM,
439 char * detail)
441 uint64_t ena;
442 char buf[FM_MAX_CLASS];
444 (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail);
446 ena = fm_ena_generate(0, FM_ENA_FMT1);
448 if (DDI_FM_EREPORT_CAP(pUM->fmCapabilities))
450 ddi_fm_ereport_post(pUM->pDev, buf, ena, DDI_NOSLEEP,
451 FM_VERSION, DATA_TYPE_UINT8,
452 FM_EREPORT_VERS0, NULL);
457 static boolean_t BnxeAttachDevice(um_device_t * pUM)
459 int rc;
460 int * props = NULL;
461 uint_t numProps;
462 u32_t vendor_id;
463 u32_t device_id;
465 /* fm-capable in bnxe.conf can be used to set fmCapabilities. */
466 pUM->fmCapabilities = ddi_prop_get_int(DDI_DEV_T_ANY,
467 pUM->pDev,
468 DDI_PROP_DONTPASS,
469 "fm-capable",
470 (DDI_FM_EREPORT_CAPABLE |
471 DDI_FM_ACCCHK_CAPABLE |
472 DDI_FM_DMACHK_CAPABLE |
473 DDI_FM_ERRCB_CAPABLE));
475 /* Register capabilities with IO Fault Services. */
476 BnxeFmInit(pUM);
478 if (!BnxePciInit(pUM))
480 BnxeFmFini(pUM);
482 return B_FALSE;
485 BnxeMutexInit(pUM);
487 if (!BnxeWorkQueueInit(pUM))
489 return B_FALSE;
492 rc = lm_get_dev_info(&pUM->lm_dev);
494 if (pUM->fmCapabilities &&
495 BnxeCheckAccHandle(pUM->pPciCfg) != DDI_FM_OK)
497 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_LOST);
498 BnxeWorkQueueWaitAndDestroy(pUM);
499 BnxeMutexDestroy(pUM);
500 BnxePciDestroy(pUM);
501 BnxeFmFini(pUM);
503 return B_FALSE;
506 if (pUM->fmCapabilities &&
507 BnxeCheckAccHandle(pUM->lm_dev.vars.reg_handle[BAR_0]) != DDI_FM_OK)
509 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_LOST);
510 BnxeWorkQueueWaitAndDestroy(pUM);
511 BnxeMutexDestroy(pUM);
512 BnxePciDestroy(pUM);
513 BnxeFmFini(pUM);
515 return B_FALSE;
518 if (rc != LM_STATUS_SUCCESS)
520 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE);
521 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_LOST);
522 BnxeWorkQueueWaitAndDestroy(pUM);
523 BnxeMutexDestroy(pUM);
524 BnxePciDestroy(pUM);
525 BnxeFmFini(pUM);
527 BnxeLogWarn(pUM, "Failed to get device information");
528 return B_FALSE;
531 #if 0
532 if (IS_PFDEV(&pUM->lm_dev) && lm_check_if_pf_assigned_to_vm(&pUM->lm_dev))
534 lm_set_virt_mode(&pUM->lm_dev, DEVICE_TYPE_PF, VT_ASSIGNED_TO_VM_PF);
536 #endif
538 /* check if FCoE is enabled on this function */
539 #if 0
540 pUM->do_fcoe =
541 ((CHIP_IS_E2(&pUM->lm_dev) || CHIP_IS_E3(&pUM->lm_dev)) &&
542 BnxeProtoSupport(pUM, LM_PROTO_SUPPORT_FCOE)) ? B_TRUE :
543 B_FALSE;
544 #else
545 pUM->do_fcoe = B_FALSE;
546 #endif
548 lm_get_iscsi_boot_info_block(&pUM->lm_dev, &pUM->iscsiInfo);
549 if (pUM->iscsiInfo.signature != 0)
551 BnxeLogInfo(pUM, "MBA FCoE boot occurred on this interface.");
554 if (!BnxeIntrInit(pUM))
556 BnxeBarMemDestroy(pUM);
557 BnxeWorkQueueWaitAndDestroy(pUM);
558 BnxeMutexDestroy(pUM);
559 BnxePciDestroy(pUM);
560 BnxeFmFini(pUM);
562 return B_FALSE;
565 if (!BnxeKstatInit(pUM))
567 BnxeIntrFini(pUM);
568 BnxeBarMemDestroy(pUM);
569 BnxeWorkQueueWaitAndDestroy(pUM);
570 BnxeMutexDestroy(pUM);
571 BnxePciDestroy(pUM);
572 BnxeFmFini(pUM);
574 return B_FALSE;
577 if (BnxeProtoFcoeAfex(pUM))
579 /* No support for L2 on FCoE enabled AFEX function! */
580 BnxeLogInfo(pUM, "FCoE AFEX function, not registering with GLD.");
581 #if 0
583 * The following is wonky. Doing a CLONE_DEV makes it visible to
584 * various L2 networking commands even though the instance was
585 * not registered with GLDv3 via mac_register().
588 /* Create a style-2 DLPI device */
589 if (ddi_create_minor_node(pUM->pDev,
590 (char *)ddi_driver_name(pUM->pDev),
591 S_IFCHR,
593 DDI_PSEUDO, //DDI_NT_NET,
594 CLONE_DEV) != DDI_SUCCESS)
596 BnxeLogWarn(pUM, "Failed to create device minor node.");
597 BnxeKstatFini(pUM);
598 BnxeIntrFini(pUM);
599 BnxeBarMemDestroy(pUM);
600 BnxeWorkQueueWaitAndDestroy(pUM);
601 BnxeMutexDestroy(pUM);
602 BnxePciDestroy(pUM);
603 BnxeFmFini(pUM);
605 return B_FALSE;
608 /* Create a style-1 DLPI device */
609 if (ddi_create_minor_node(pUM->pDev,
610 pUM->devName,
611 S_IFCHR,
612 pUM->instance,
613 DDI_PSEUDO, //DDI_NT_NET,
614 0) != DDI_SUCCESS)
616 BnxeLogWarn(pUM, "Failed to create device instance minor node.");
617 ddi_remove_minor_node(pUM->pDev, (char *)ddi_driver_name(pUM->pDev));
618 BnxeKstatFini(pUM);
619 BnxeIntrFini(pUM);
620 BnxeBarMemDestroy(pUM);
621 BnxeWorkQueueWaitAndDestroy(pUM);
622 BnxeMutexDestroy(pUM);
623 BnxePciDestroy(pUM);
624 BnxeFmFini(pUM);
626 return B_FALSE;
628 #endif
630 else
632 /* register with the GLDv3 MAC layer */
633 if (!BnxeGldInit(pUM))
635 BnxeKstatFini(pUM);
636 BnxeIntrFini(pUM);
637 BnxeBarMemDestroy(pUM);
638 BnxeWorkQueueWaitAndDestroy(pUM);
639 BnxeMutexDestroy(pUM);
640 BnxePciDestroy(pUM);
641 BnxeFmFini(pUM);
643 return B_FALSE;
647 snprintf(pUM->version,
648 sizeof(pUM->version),
649 "%d.%d.%d",
650 MAJVERSION,
651 MINVERSION,
652 REVVERSION);
654 snprintf(pUM->versionLM,
655 sizeof(pUM->versionLM),
656 "%d.%d.%d",
657 LM_DRIVER_MAJOR_VER,
658 LM_DRIVER_MINOR_VER,
659 LM_DRIVER_FIX_NUM);
661 snprintf(pUM->versionFW,
662 sizeof(pUM->versionFW),
663 "%d.%d.%d.%d",
664 BCM_5710_FW_MAJOR_VERSION,
665 BCM_5710_FW_MINOR_VERSION,
666 BCM_5710_FW_REVISION_VERSION,
667 BCM_5710_FW_ENGINEERING_VERSION);
669 snprintf(pUM->versionBC,
670 sizeof(pUM->versionBC),
671 "%d.%d.%d",
672 ((pUM->lm_dev.hw_info.bc_rev >> 24) & 0xff),
673 ((pUM->lm_dev.hw_info.bc_rev >> 16) & 0xff),
674 ((pUM->lm_dev.hw_info.bc_rev >> 8) & 0xff));
676 snprintf(pUM->chipName,
677 sizeof(pUM->chipName),
678 "%s",
679 BnxeChipName(pUM));
681 snprintf(pUM->chipID,
682 sizeof(pUM->chipID),
683 "0x%x",
684 pUM->lm_dev.hw_info.chip_id);
686 *pUM->bus_dev_func = 0;
687 rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, pUM->pDev,
688 0, "reg", &props, &numProps);
689 if ((rc == DDI_PROP_SUCCESS) && (numProps > 0))
691 snprintf(pUM->bus_dev_func,
692 sizeof(pUM->bus_dev_func),
693 "%04x:%02x:%02x",
694 PCI_REG_BUS_G(props[0]),
695 PCI_REG_DEV_G(props[0]),
696 PCI_REG_FUNC_G(props[0]));
697 ddi_prop_free(props);
700 vendor_id = 0;
701 rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, pUM->pDev,
702 0, "vendor-id", &props, &numProps);
703 if ((rc == DDI_PROP_SUCCESS) && (numProps > 0))
705 vendor_id = props[0];
706 ddi_prop_free(props);
709 device_id = 0;
710 rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, pUM->pDev,
711 0, "device-id", &props, &numProps);
712 if ((rc == DDI_PROP_SUCCESS) && (numProps > 0))
714 device_id = props[0];
715 ddi_prop_free(props);
718 snprintf(pUM->vendor_device,
719 sizeof(pUM->vendor_device),
720 "%04x:%04x",
721 vendor_id,
722 device_id);
724 snprintf(pUM->intrAlloc,
725 sizeof(pUM->intrAlloc),
726 "%d %s",
727 (pUM->intrType == DDI_INTR_TYPE_FIXED) ? 1 : (pUM->defIntr.intrCount +
728 pUM->fcoeIntr.intrCount +
729 pUM->rssIntr.intrCount),
730 (pUM->intrType == DDI_INTR_TYPE_MSIX) ? "MSIX" :
731 (pUM->intrType == DDI_INTR_TYPE_MSI) ? "MSI" :
732 "Fixed");
734 BnxeLogInfo(pUM,
735 "(0x%p) %s %s - v%s - FW v%s - BC v%s - %s (%s)",
736 pUM,
737 pUM->chipName,
738 pUM->chipID,
739 pUM->version,
740 pUM->versionFW,
741 pUM->versionBC,
742 IS_MULTI_VNIC(&pUM->lm_dev) ? "MF" : "SF",
743 pUM->intrAlloc);
745 return B_TRUE;
749 static boolean_t BnxeDetachDevice(um_device_t * pUM)
751 int rc;
753 rc = BnxeFcoeFini(pUM);
755 if ((rc != 0) && (rc != ENOTSUP) && (rc != ENODEV))
757 return B_FALSE;
760 if (BnxeProtoFcoeAfex(pUM))
762 /* No support for L2 on FCoE enabled AFEX function! */
764 #if 0
765 ddi_remove_minor_node(pUM->pDev, pUM->devName);
766 ddi_remove_minor_node(pUM->pDev, (char *)ddi_driver_name(pUM->pDev));
767 #endif
769 else
771 if (!BnxeGldFini(pUM))
773 return B_FALSE;
777 BnxeKstatFini(pUM);
778 BnxeIntrFini(pUM);
779 BnxeBarMemDestroy(pUM);
780 BnxeWorkQueueWaitAndDestroy(pUM);
781 BnxeMutexDestroy(pUM);
782 BnxePciDestroy(pUM);
783 BnxeFmFini(pUM);
785 return B_TRUE;
789 static int BnxeAttach(dev_info_t * pDev, ddi_attach_cmd_t cmd)
791 um_device_t * pUM;
793 switch (cmd)
795 case DDI_ATTACH:
797 if ((pUM = kmem_zalloc(sizeof(um_device_t), KM_SLEEP)) == NULL)
799 BnxeLogWarn(NULL, "failed to allocate device structure");
800 return DDI_FAILURE;
803 ddi_set_driver_private(pDev, pUM);
805 /* set magic number for identification */
806 pUM->magic = BNXE_MAGIC;
808 /* default for debug logging is dump everything */
809 pUM->devParams.debug_level = (CP_ALL | LV_MASK);
811 /* save dev_info_t in the driver structure */
812 pUM->pDev = pDev;
814 d_list_clear(&pUM->memBlockList);
815 d_list_clear(&pUM->memDmaList);
816 d_list_clear(&pUM->memRegionList);
817 #ifdef BNXE_DEBUG_DMA_LIST
818 d_list_clear(&pUM->memDmaListSaved);
819 #endif
821 /* obtain a human-readable device name log messages with */
822 pUM->instance = ddi_get_instance(pDev);
823 snprintf(pUM->devName, sizeof(pUM->devName),
824 "bnxe%d", pUM->instance);
826 if (!BnxeAttachDevice(pUM))
828 kmem_free(pUM, sizeof(um_device_t));
829 return DDI_FAILURE;
832 if (BNXE_FCOE(pUM) && pUM->devParams.fcoeEnable)
834 BnxeFcoeStartStop(pUM);
837 return DDI_SUCCESS;
839 case DDI_RESUME:
840 #if !(defined(__S11) || defined(__S12))
841 case DDI_PM_RESUME:
842 #endif
844 pUM = (um_device_t *)ddi_get_driver_private(pDev);
846 /* sanity check */
847 if (pUM == NULL || pUM->pDev != pDev)
849 BnxeLogWarn(NULL, "%s: dev_info_t match failed", __func__);
850 return DDI_FAILURE;
853 if (BnxeHwResume(pUM) != 0)
855 BnxeLogWarn(pUM, "Fail to resume this device!");
856 return DDI_FAILURE;
859 return DDI_SUCCESS;
861 default:
863 return DDI_FAILURE;
868 static int BnxeDetach(dev_info_t * pDev, ddi_detach_cmd_t cmd)
870 um_device_t * pUM;
872 switch (cmd)
874 case DDI_DETACH:
876 pUM = (um_device_t *)ddi_get_driver_private(pDev);
878 /* sanity check */
879 if (pUM == NULL || pUM->pDev != pDev)
881 BnxeLogWarn(NULL, "%s: dev_info_t match failed", __func__);
882 return DDI_FAILURE;
885 if (pUM->intrEnabled != B_FALSE)
887 BnxeLogWarn(pUM, "Detaching a device that is currently running!");
888 return DDI_FAILURE;
891 if (!BnxeDetachDevice(pUM))
893 BnxeLogWarn(pUM, "Can't detach it now, please try again later!");
894 return DDI_FAILURE;
897 kmem_free(pUM, sizeof(um_device_t));
899 return DDI_SUCCESS;
901 case DDI_SUSPEND:
902 #if !(defined(__S11) || defined(__S12))
903 case DDI_PM_SUSPEND:
904 #endif
906 pUM = (um_device_t *)ddi_get_driver_private(pDev);
908 /* sanity check */
909 if (pUM == NULL || pUM->pDev != pDev)
911 BnxeLogWarn(NULL, "%s: dev_info_t match failed", __func__);
912 return DDI_FAILURE;
915 if (BnxeHwSuspend(pUM) != 0)
917 BnxeLogWarn(pUM, "Fail to suspend this device!");
918 return DDI_FAILURE;
921 return DDI_SUCCESS;
923 default:
925 return DDI_FAILURE;
930 #if (DEVO_REV > 3)
932 static int BnxeQuiesce(dev_info_t * pDev)
934 um_device_t * pUM;
936 pUM = (um_device_t *)ddi_get_driver_private(pDev);
938 /* sanity check */
939 if (pUM == NULL || pUM->pDev != pDev)
941 BnxeLogWarn(NULL, "%s: dev_info_t match failed", __func__);
942 return DDI_FAILURE;
945 if (!pUM->plumbed)
947 return DDI_SUCCESS;
950 if (BnxeHwQuiesce(pUM) != 0)
952 BnxeLogWarn(pUM, "Failed to quiesce the device!");
953 return DDI_FAILURE;
956 return DDI_SUCCESS;
959 #endif
962 void BnxeFcoeInitChild(dev_info_t * pDev,
963 dev_info_t * cDip)
965 um_device_t *pUM = (um_device_t *) ddi_get_driver_private(pDev);
967 if ((pUM == NULL) || (pUM->pDev != pDev))
969 BnxeLogWarn(NULL, "%s: dev_info_t match failed ", __func__);
970 return;
973 ddi_set_name_addr(cDip, ddi_get_name_addr(pUM->pDev));
977 void BnxeFcoeUninitChild(dev_info_t * pDev,
978 dev_info_t * cDip)
980 ddi_set_name_addr(cDip, NULL);
984 static int BnxeBusCtl(dev_info_t * pDev,
985 dev_info_t * pRDev,
986 ddi_ctl_enum_t op,
987 void * pArg,
988 void * pResult)
990 um_device_t * pUM = (um_device_t *)ddi_get_driver_private(pDev);
992 /* sanity check */
993 if (pUM == NULL || pUM->pDev != pDev)
995 BnxeLogWarn(NULL, "%s: dev_info_t match failed", __func__);
996 return DDI_FAILURE;
999 BnxeLogDbg(pUM, "BnxeBusCtl (%d)", op);
1001 switch (op)
1003 case DDI_CTLOPS_REPORTDEV:
1004 case DDI_CTLOPS_IOMIN:
1005 break;
1006 case DDI_CTLOPS_INITCHILD:
1007 BnxeFcoeInitChild(pDev, (dev_info_t *) pArg);
1008 break;
1009 case DDI_CTLOPS_UNINITCHILD:
1010 BnxeFcoeUninitChild(pDev, (dev_info_t *) pArg);
1011 break;
1013 default:
1015 return (ddi_ctlops(pDev, pRDev, op, pArg, pResult));
1018 return DDI_SUCCESS;
1022 static int BnxeCbIoctl(dev_t dev,
1023 int cmd,
1024 intptr_t arg,
1025 int mode,
1026 cred_t * credp,
1027 int * rvalp)
1029 BnxeBinding * pBinding = (BnxeBinding *)arg;
1030 um_device_t * pUM;
1032 (void)dev;
1033 (void)mode;
1034 (void)credp;
1035 (void)rvalp;
1037 if ((pBinding == NULL) ||
1038 (pBinding->pCliDev == NULL) ||
1039 (pBinding->pPrvDev == NULL))
1041 BnxeLogWarn(NULL, "Invalid binding arg to ioctl %d", cmd);
1042 return DDI_FAILURE;
1045 pUM = (um_device_t *)ddi_get_driver_private(pBinding->pPrvDev);
1047 /* sanity checks */
1049 if (pBinding->version != BNXE_BINDING_VERSION)
1051 BnxeLogWarn(NULL, "%s: Invalid binding version (0x%08x)",
1052 __func__, pBinding->version);
1053 return DDI_FAILURE;
1056 if ((pUM == NULL) ||
1057 (pUM->fcoe.pDev != pBinding->pCliDev) ||
1058 (pUM->pDev != pBinding->pPrvDev))
1060 BnxeLogWarn(NULL, "%s: dev_info_t match failed", __func__);
1061 return DDI_FAILURE;
1064 switch (cmd)
1066 case BNXE_BIND_FCOE:
1068 /* copy the binding struct and fill in the provider callback */
1070 BnxeLogInfo(pUM, "FCoE BIND start");
1072 if (!CLIENT_DEVI(pUM, LM_CLI_IDX_FCOE))
1074 BnxeLogWarn(pUM, "FCoE BIND when DEVI is offline!");
1075 return DDI_FAILURE;
1078 if (CLIENT_BOUND(pUM, LM_CLI_IDX_FCOE))
1080 BnxeLogWarn(pUM, "FCoE BIND when alread bound!");
1081 return DDI_FAILURE;
1084 pUM->fcoe.bind = *pBinding;
1086 pUM->fcoe.bind.prvCtl = pBinding->prvCtl = BnxeFcoePrvCtl;
1087 pUM->fcoe.bind.prvTx = pBinding->prvTx = BnxeFcoePrvTx;
1088 pUM->fcoe.bind.prvPoll = pBinding->prvPoll = BnxeFcoePrvPoll;
1089 pUM->fcoe.bind.prvSendWqes = pBinding->prvSendWqes = BnxeFcoePrvSendWqes;
1090 pUM->fcoe.bind.prvMapMailboxq = pBinding->prvMapMailboxq = BnxeFcoePrvMapMailboxq;
1091 pUM->fcoe.bind.prvUnmapMailboxq = pBinding->prvUnmapMailboxq = BnxeFcoePrvUnmapMailboxq;
1093 pUM->devParams.numRxDesc[LM_CLI_IDX_FCOE] = pBinding->numRxDescs;
1094 pUM->devParams.numTxDesc[LM_CLI_IDX_FCOE] = pBinding->numTxDescs;
1096 pUM->lm_dev.params.l2_rx_desc_cnt[LM_CLI_IDX_FCOE] = pBinding->numRxDescs;
1097 BnxeInitBdCnts(pUM, LM_CLI_IDX_FCOE);
1099 if (BnxeHwStartFCOE(pUM))
1101 return DDI_FAILURE;
1104 CLIENT_BIND_SET(pUM, LM_CLI_IDX_FCOE);
1105 lm_mcp_indicate_client_bind(&pUM->lm_dev, LM_CLI_IDX_FCOE);
1107 BnxeLogInfo(pUM, "FCoE BIND done");
1108 return DDI_SUCCESS;
1110 case BNXE_UNBIND_FCOE:
1112 /* clear the binding struct and stats */
1114 BnxeLogInfo(pUM, "FCoE UNBIND start");
1116 if (CLIENT_DEVI(pUM, LM_CLI_IDX_FCOE))
1118 BnxeLogWarn(pUM, "FCoE UNBIND when DEVI is online!");
1119 return DDI_FAILURE;
1122 if (!CLIENT_BOUND(pUM, LM_CLI_IDX_FCOE))
1124 BnxeLogWarn(pUM, "FCoE UNBIND when not bound!");
1125 return DDI_FAILURE;
1128 /* We must not detach until all packets held by fcoe are retrieved. */
1129 if (!BnxeWaitForPacketsFromClient(pUM, LM_CLI_IDX_FCOE))
1131 return DDI_FAILURE;
1134 lm_mcp_indicate_client_unbind(&pUM->lm_dev, LM_CLI_IDX_FCOE);
1135 CLIENT_BIND_RESET(pUM, LM_CLI_IDX_FCOE);
1137 BnxeHwStopFCOE(pUM);
1139 memset(&pUM->fcoe.bind, 0, sizeof(pUM->fcoe.bind));
1140 memset(&pUM->fcoe.stats, 0, sizeof(pUM->fcoe.stats));
1142 pBinding->prvCtl = NULL;
1143 pBinding->prvTx = NULL;
1144 pBinding->prvPoll = NULL;
1145 pBinding->prvSendWqes = NULL;
1146 pBinding->prvMapMailboxq = NULL;
1147 pBinding->prvUnmapMailboxq = NULL;
1149 pUM->fcoe.pDev = NULL; /* sketchy? */
1151 BnxeLogInfo(pUM, "FCoE UNBIND done");
1152 return DDI_SUCCESS;
1154 default:
1156 BnxeLogWarn(pUM, "Unknown ioctl %d", cmd);
1157 return DDI_FAILURE;
1161 #ifndef ILLUMOS
1162 static struct bus_ops bnxe_bus_ops =
1164 BUSO_REV,
1165 nullbusmap, /* bus_map */
1166 NULL, /* bus_get_intrspec */
1167 NULL, /* bus_add_intrspec */
1168 NULL, /* bus_remove_intrspec */
1169 i_ddi_map_fault, /* bus_map_fault */
1170 ddi_dma_map, /* bus_dma_map */
1171 ddi_dma_allochdl, /* bus_dma_allochdl */
1172 ddi_dma_freehdl, /* bus_dma_freehdl */
1173 ddi_dma_bindhdl, /* bus_dma_bindhdl */
1174 ddi_dma_unbindhdl, /* bus_unbindhdl */
1175 ddi_dma_flush, /* bus_dma_flush */
1176 ddi_dma_win, /* bus_dma_win */
1177 ddi_dma_mctl, /* bus_dma_ctl */
1178 BnxeBusCtl, /* bus_ctl */
1179 ddi_bus_prop_op, /* bus_prop_op */
1180 NULL, /* bus_get_eventcookie */
1181 NULL, /* bus_add_eventcall */
1182 NULL, /* bus_remove_event */
1183 NULL, /* bus_post_event */
1184 NULL, /* bus_intr_ctl */
1185 NULL, /* bus_config */
1186 NULL, /* bus_unconfig */
1187 NULL, /* bus_fm_init */
1188 NULL, /* bus_fm_fini */
1189 NULL, /* bus_fm_access_enter */
1190 NULL, /* bus_fm_access_exit */
1191 NULL, /* bus_power */
1192 NULL
1194 #endif /* ILLUMOS */
1197 static struct cb_ops bnxe_cb_ops =
1199 nulldev, /* cb_open */
1200 nulldev, /* cb_close */
1201 nodev, /* cb_strategy */
1202 nodev, /* cb_print */
1203 nodev, /* cb_dump */
1204 nodev, /* cb_read */
1205 nodev, /* cb_write */
1206 BnxeCbIoctl, /* cb_ioctl */
1207 nodev, /* cb_devmap */
1208 nodev, /* cb_mmap */
1209 nodev, /* cb_segmap */
1210 nochpoll, /* cb_chpoll */
1211 ddi_prop_op, /* cb_prop_op */
1212 NULL, /* cb_stream */
1213 (int)(D_MP | D_64BIT), /* cb_flag */
1214 CB_REV, /* cb_rev */
1215 nodev, /* cb_aread */
1216 nodev, /* cb_awrite */
1220 #if (DEVO_REV > 3)
1222 static struct dev_ops bnxe_dev_ops =
1224 DEVO_REV, /* devo_rev */
1225 0, /* devo_refcnt */
1226 NULL, /* devo_getinfo */
1227 nulldev, /* devo_identify */
1228 nulldev, /* devo_probe */
1229 BnxeAttach, /* devo_attach */
1230 BnxeDetach, /* devo_detach */
1231 nodev, /* devo_reset */
1232 &bnxe_cb_ops, /* devo_cb_ops */
1233 #ifndef ILLUMOS
1234 &bnxe_bus_ops, /* devo_bus_ops */
1235 #else
1236 NULL, /* devo_bus_ops */
1237 #endif
1238 NULL, /* devo_power */
1239 BnxeQuiesce /* devo_quiesce */
1242 #else
1244 static struct dev_ops bnxe_dev_ops =
1246 DEVO_REV, /* devo_rev */
1247 0, /* devo_refcnt */
1248 NULL, /* devo_getinfo */
1249 nulldev, /* devo_identify */
1250 nulldev, /* devo_probe */
1251 BnxeAttach, /* devo_attach */
1252 BnxeDetach, /* devo_detach */
1253 nodev, /* devo_reset */
1254 &bnxe_cb_ops, /* devo_cb_ops */
1255 &bnxe_bus_ops, /* devo_bus_ops */
1256 NULL /* devo_power */
1259 #endif
1262 static struct modldrv bnxe_modldrv =
1264 &mod_driverops, /* drv_modops (must be mod_driverops for drivers) */
1265 BNXE_PRODUCT_INFO, /* drv_linkinfo (string displayed by modinfo) */
1266 &bnxe_dev_ops /* drv_dev_ops */
1270 static struct modlinkage bnxe_modlinkage =
1272 MODREV_1, /* ml_rev */
1274 &bnxe_modldrv, /* ml_linkage */
1275 NULL /* NULL termination */
1280 int _init(void)
1282 int rc;
1284 mac_init_ops(&bnxe_dev_ops, "bnxe");
1286 /* Install module information with O/S */
1287 if ((rc = mod_install(&bnxe_modlinkage)) != DDI_SUCCESS)
1289 BnxeLogWarn(NULL, "mod_install returned 0x%x", rc);
1290 mac_fini_ops(&bnxe_dev_ops);
1291 return rc;
1294 mutex_init(&bnxeLoaderMutex, NULL, MUTEX_DRIVER, NULL);
1295 bnxeNumPlumbed = 0;
1297 BnxeLogInfo(NULL, "%s", BNXE_PRODUCT_BANNER);
1299 return rc;
1303 int _fini(void)
1305 int rc;
1307 if ((rc = mod_remove(&bnxe_modlinkage)) == DDI_SUCCESS)
1309 mac_fini_ops(&bnxe_dev_ops);
1310 mutex_destroy(&bnxeLoaderMutex);
1312 if (bnxeNumPlumbed > 0)
1315 * This shouldn't be possible since modunload must only call _fini
1316 * when no instances are currently plumbed.
1318 BnxeLogWarn(NULL, "%d instances have not been unplumbed", bnxeNumPlumbed);
1322 return rc;
1326 int _info(struct modinfo * pModinfo)
1328 return mod_info(&bnxe_modlinkage, pModinfo);