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]
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.
42 #define XSTRINGIFY(x) #x
43 #define STRINGIFY(x) XSTRINGIFY(x)
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
;
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
)
107 uint32_t port_feature_config_sf
;
109 if (IS_MULTI_VNIC(&pUM
->lm_dev
))
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
)
122 if (pUM
->lm_dev
.params
.mf_proto_support_flags
&
123 LM_PROTO_SUPPORT_FCOE
)
130 /* mcp is not present so allow enumeration */
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
:
149 case PORT_FEAT_CFG_STORAGE_PERSONALITY_FCOE
:
150 case PORT_FEAT_CFG_STORAGE_PERSONALITY_BOTH
:
151 case PORT_FEAT_CFG_STORAGE_PERSONALITY_DEFAULT
:
158 if (pUM
->lm_dev
.params
.max_func_fcoe_cons
== 0)
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");
188 static void BnxePciDestroy(um_device_t
* pUM
)
192 pci_config_teardown(&pUM
->pPciCfg
);
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
,
213 static void BnxeMutexInit(um_device_t
* pUM
)
215 lm_device_t
* pLM
= &pUM
->lm_dev
;
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
;
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
);
336 int BnxeCheckAccHandle(ddi_acc_handle_t handle
)
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
)
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
;
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
,
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
)
465 /* fm-capable in bnxe.conf can be used to set fmCapabilities. */
466 pUM
->fmCapabilities
= ddi_prop_get_int(DDI_DEV_T_ANY
,
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. */
478 if (!BnxePciInit(pUM
))
487 if (!BnxeWorkQueueInit(pUM
))
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
);
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
);
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
);
527 BnxeLogWarn(pUM
, "Failed to get device information");
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
);
538 /* check if FCoE is enabled on this function */
541 ((CHIP_IS_E2(&pUM
->lm_dev
) || CHIP_IS_E3(&pUM
->lm_dev
)) &&
542 BnxeProtoSupport(pUM
, LM_PROTO_SUPPORT_FCOE
)) ? B_TRUE
:
545 pUM
->do_fcoe
= B_FALSE
;
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
);
565 if (!BnxeKstatInit(pUM
))
568 BnxeBarMemDestroy(pUM
);
569 BnxeWorkQueueWaitAndDestroy(pUM
);
570 BnxeMutexDestroy(pUM
);
577 if (BnxeProtoFcoeAfex(pUM
))
579 /* No support for L2 on FCoE enabled AFEX function! */
580 BnxeLogInfo(pUM
, "FCoE AFEX function, not registering with GLD.");
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
),
593 DDI_PSEUDO
, //DDI_NT_NET,
594 CLONE_DEV
) != DDI_SUCCESS
)
596 BnxeLogWarn(pUM
, "Failed to create device minor node.");
599 BnxeBarMemDestroy(pUM
);
600 BnxeWorkQueueWaitAndDestroy(pUM
);
601 BnxeMutexDestroy(pUM
);
608 /* Create a style-1 DLPI device */
609 if (ddi_create_minor_node(pUM
->pDev
,
613 DDI_PSEUDO
, //DDI_NT_NET,
616 BnxeLogWarn(pUM
, "Failed to create device instance minor node.");
617 ddi_remove_minor_node(pUM
->pDev
, (char *)ddi_driver_name(pUM
->pDev
));
620 BnxeBarMemDestroy(pUM
);
621 BnxeWorkQueueWaitAndDestroy(pUM
);
622 BnxeMutexDestroy(pUM
);
632 /* register with the GLDv3 MAC layer */
633 if (!BnxeGldInit(pUM
))
637 BnxeBarMemDestroy(pUM
);
638 BnxeWorkQueueWaitAndDestroy(pUM
);
639 BnxeMutexDestroy(pUM
);
647 snprintf(pUM
->version
,
648 sizeof(pUM
->version
),
654 snprintf(pUM
->versionLM
,
655 sizeof(pUM
->versionLM
),
661 snprintf(pUM
->versionFW
,
662 sizeof(pUM
->versionFW
),
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
),
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
),
681 snprintf(pUM
->chipID
,
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
),
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
);
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
);
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
),
724 snprintf(pUM
->intrAlloc
,
725 sizeof(pUM
->intrAlloc
),
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" :
735 "(0x%p) %s %s - v%s - FW v%s - BC v%s - %s (%s)",
742 IS_MULTI_VNIC(&pUM
->lm_dev
) ? "MF" : "SF",
749 static boolean_t
BnxeDetachDevice(um_device_t
* pUM
)
753 rc
= BnxeFcoeFini(pUM
);
755 if ((rc
!= 0) && (rc
!= ENOTSUP
) && (rc
!= ENODEV
))
760 if (BnxeProtoFcoeAfex(pUM
))
762 /* No support for L2 on FCoE enabled AFEX function! */
765 ddi_remove_minor_node(pUM
->pDev
, pUM
->devName
);
766 ddi_remove_minor_node(pUM
->pDev
, (char *)ddi_driver_name(pUM
->pDev
));
771 if (!BnxeGldFini(pUM
))
779 BnxeBarMemDestroy(pUM
);
780 BnxeWorkQueueWaitAndDestroy(pUM
);
781 BnxeMutexDestroy(pUM
);
789 static int BnxeAttach(dev_info_t
* pDev
, ddi_attach_cmd_t cmd
)
797 if ((pUM
= kmem_zalloc(sizeof(um_device_t
), KM_SLEEP
)) == NULL
)
799 BnxeLogWarn(NULL
, "failed to allocate device structure");
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 */
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
);
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
));
832 if (BNXE_FCOE(pUM
) && pUM
->devParams
.fcoeEnable
)
834 BnxeFcoeStartStop(pUM
);
840 #if !(defined(__S11) || defined(__S12))
844 pUM
= (um_device_t
*)ddi_get_driver_private(pDev
);
847 if (pUM
== NULL
|| pUM
->pDev
!= pDev
)
849 BnxeLogWarn(NULL
, "%s: dev_info_t match failed", __func__
);
853 if (BnxeHwResume(pUM
) != 0)
855 BnxeLogWarn(pUM
, "Fail to resume this device!");
868 static int BnxeDetach(dev_info_t
* pDev
, ddi_detach_cmd_t cmd
)
876 pUM
= (um_device_t
*)ddi_get_driver_private(pDev
);
879 if (pUM
== NULL
|| pUM
->pDev
!= pDev
)
881 BnxeLogWarn(NULL
, "%s: dev_info_t match failed", __func__
);
885 if (pUM
->intrEnabled
!= B_FALSE
)
887 BnxeLogWarn(pUM
, "Detaching a device that is currently running!");
891 if (!BnxeDetachDevice(pUM
))
893 BnxeLogWarn(pUM
, "Can't detach it now, please try again later!");
897 kmem_free(pUM
, sizeof(um_device_t
));
902 #if !(defined(__S11) || defined(__S12))
906 pUM
= (um_device_t
*)ddi_get_driver_private(pDev
);
909 if (pUM
== NULL
|| pUM
->pDev
!= pDev
)
911 BnxeLogWarn(NULL
, "%s: dev_info_t match failed", __func__
);
915 if (BnxeHwSuspend(pUM
) != 0)
917 BnxeLogWarn(pUM
, "Fail to suspend this device!");
932 static int BnxeQuiesce(dev_info_t
* pDev
)
936 pUM
= (um_device_t
*)ddi_get_driver_private(pDev
);
939 if (pUM
== NULL
|| pUM
->pDev
!= pDev
)
941 BnxeLogWarn(NULL
, "%s: dev_info_t match failed", __func__
);
950 if (BnxeHwQuiesce(pUM
) != 0)
952 BnxeLogWarn(pUM
, "Failed to quiesce the device!");
962 void BnxeFcoeInitChild(dev_info_t
* pDev
,
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__
);
973 ddi_set_name_addr(cDip
, ddi_get_name_addr(pUM
->pDev
));
977 void BnxeFcoeUninitChild(dev_info_t
* pDev
,
980 ddi_set_name_addr(cDip
, NULL
);
984 static int BnxeBusCtl(dev_info_t
* pDev
,
990 um_device_t
* pUM
= (um_device_t
*)ddi_get_driver_private(pDev
);
993 if (pUM
== NULL
|| pUM
->pDev
!= pDev
)
995 BnxeLogWarn(NULL
, "%s: dev_info_t match failed", __func__
);
999 BnxeLogDbg(pUM
, "BnxeBusCtl (%d)", op
);
1003 case DDI_CTLOPS_REPORTDEV
:
1004 case DDI_CTLOPS_IOMIN
:
1006 case DDI_CTLOPS_INITCHILD
:
1007 BnxeFcoeInitChild(pDev
, (dev_info_t
*) pArg
);
1009 case DDI_CTLOPS_UNINITCHILD
:
1010 BnxeFcoeUninitChild(pDev
, (dev_info_t
*) pArg
);
1015 return (ddi_ctlops(pDev
, pRDev
, op
, pArg
, pResult
));
1022 static int BnxeCbIoctl(dev_t dev
,
1029 BnxeBinding
* pBinding
= (BnxeBinding
*)arg
;
1037 if ((pBinding
== NULL
) ||
1038 (pBinding
->pCliDev
== NULL
) ||
1039 (pBinding
->pPrvDev
== NULL
))
1041 BnxeLogWarn(NULL
, "Invalid binding arg to ioctl %d", cmd
);
1045 pUM
= (um_device_t
*)ddi_get_driver_private(pBinding
->pPrvDev
);
1049 if (pBinding
->version
!= BNXE_BINDING_VERSION
)
1051 BnxeLogWarn(NULL
, "%s: Invalid binding version (0x%08x)",
1052 __func__
, pBinding
->version
);
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__
);
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!");
1078 if (CLIENT_BOUND(pUM
, LM_CLI_IDX_FCOE
))
1080 BnxeLogWarn(pUM
, "FCoE BIND when alread bound!");
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
))
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");
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!");
1122 if (!CLIENT_BOUND(pUM
, LM_CLI_IDX_FCOE
))
1124 BnxeLogWarn(pUM
, "FCoE UNBIND when not bound!");
1128 /* We must not detach until all packets held by fcoe are retrieved. */
1129 if (!BnxeWaitForPacketsFromClient(pUM
, LM_CLI_IDX_FCOE
))
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");
1156 BnxeLogWarn(pUM
, "Unknown ioctl %d", cmd
);
1162 static struct bus_ops bnxe_bus_ops
=
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 */
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 */
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 */
1234 &bnxe_bus_ops
, /* devo_bus_ops */
1236 NULL
, /* devo_bus_ops */
1238 NULL
, /* devo_power */
1239 BnxeQuiesce
/* devo_quiesce */
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 */
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 */
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
);
1294 mutex_init(&bnxeLoaderMutex
, NULL
, MUTEX_DRIVER
, NULL
);
1297 BnxeLogInfo(NULL
, "%s", BNXE_PRODUCT_BANNER
);
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
);
1326 int _info(struct modinfo
* pModinfo
)
1328 return mod_info(&bnxe_modlinkage
, pModinfo
);