xref: /illumos-gate/usr/src/uts/common/io/bnxe/bnxe_main.c (revision 55fea89d)
1d14abf15SRobert Mustacchi /*
2d14abf15SRobert Mustacchi  * CDDL HEADER START
3d14abf15SRobert Mustacchi  *
4d14abf15SRobert Mustacchi  * The contents of this file are subject to the terms of the
5d14abf15SRobert Mustacchi  * Common Development and Distribution License (the "License").
6d14abf15SRobert Mustacchi  * You may not use this file except in compliance with the License.
7d14abf15SRobert Mustacchi  *
8d14abf15SRobert Mustacchi  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9d14abf15SRobert Mustacchi  * or http://www.opensolaris.org/os/licensing.
10d14abf15SRobert Mustacchi  * See the License for the specific language governing permissions
11d14abf15SRobert Mustacchi  * and limitations under the License.
12d14abf15SRobert Mustacchi  *
13d14abf15SRobert Mustacchi  * When distributing Covered Code, include this CDDL HEADER in each
14d14abf15SRobert Mustacchi  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15d14abf15SRobert Mustacchi  * If applicable, add the following below this CDDL HEADER, with the
16d14abf15SRobert Mustacchi  * fields enclosed by brackets "[]" replaced with your own identifying
17d14abf15SRobert Mustacchi  * information: Portions Copyright [yyyy] [name of copyright owner]
18d14abf15SRobert Mustacchi  *
19d14abf15SRobert Mustacchi  * CDDL HEADER END
20d14abf15SRobert Mustacchi  */
21d14abf15SRobert Mustacchi 
22d14abf15SRobert Mustacchi /*
23d14abf15SRobert Mustacchi  * Copyright 2014 QLogic Corporation
24d14abf15SRobert Mustacchi  * The contents of this file are subject to the terms of the
25d14abf15SRobert Mustacchi  * QLogic End User License (the "License").
26d14abf15SRobert Mustacchi  * You may not use this file except in compliance with the License.
27d14abf15SRobert Mustacchi  *
28d14abf15SRobert Mustacchi  * You can obtain a copy of the License at
29d14abf15SRobert Mustacchi  * http://www.qlogic.com/Resources/Documents/DriverDownloadHelp/
30d14abf15SRobert Mustacchi  * QLogic_End_User_Software_License.txt
31d14abf15SRobert Mustacchi  * See the License for the specific language governing permissions
32d14abf15SRobert Mustacchi  * and limitations under the License.
33d14abf15SRobert Mustacchi  */
34d14abf15SRobert Mustacchi 
35d14abf15SRobert Mustacchi /*
36d14abf15SRobert Mustacchi  * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
37d14abf15SRobert Mustacchi  */
38d14abf15SRobert Mustacchi 
39d14abf15SRobert Mustacchi #include "bnxe.h"
40d14abf15SRobert Mustacchi 
41d14abf15SRobert Mustacchi #ifndef STRINGIFY
42d14abf15SRobert Mustacchi #define XSTRINGIFY(x) #x
43d14abf15SRobert Mustacchi #define STRINGIFY(x) XSTRINGIFY(x)
44d14abf15SRobert Mustacchi #endif
45d14abf15SRobert Mustacchi 
46d14abf15SRobert Mustacchi #define BNXE_PRODUCT_BANNER "QLogic NetXtreme II 10 Gigabit Ethernet Driver v" STRINGIFY(MAJVERSION) "." STRINGIFY(MINVERSION) "." STRINGIFY(REVVERSION)
47d14abf15SRobert Mustacchi #define BNXE_PRODUCT_INFO   "QLogic NXII 10 GbE v" STRINGIFY(MAJVERSION) "." STRINGIFY(MINVERSION) "." STRINGIFY(REVVERSION)
48d14abf15SRobert Mustacchi 
49d14abf15SRobert Mustacchi #define BNXE_REGISTER_BAR_NUM      1
50d14abf15SRobert Mustacchi #define BNXE_REGS_MAP_OFFSET       0
51d14abf15SRobert Mustacchi #define BNXE_L2_MEMORY_WINDOW_SIZE 0x40000 /* 256K for PCI Config Registers */
52d14abf15SRobert Mustacchi 
53d14abf15SRobert Mustacchi u32_t    dbg_code_path   = CP_ALL;
54d14abf15SRobert Mustacchi u8_t     dbg_trace_level = LV_VERBOSE;
55d14abf15SRobert Mustacchi u32_t    g_dbg_flags     = 0;
56d14abf15SRobert Mustacchi 
57d14abf15SRobert Mustacchi kmutex_t bnxeLoaderMutex;
58d14abf15SRobert Mustacchi u32_t    bnxeNumPlumbed;
59d14abf15SRobert Mustacchi 
60d14abf15SRobert Mustacchi extern ddi_dma_attr_t bnxeDmaPageAttrib;
61d14abf15SRobert Mustacchi extern ddi_dma_attr_t bnxeRxDmaAttrib;
62d14abf15SRobert Mustacchi extern ddi_dma_attr_t bnxeTxDmaAttrib;
63d14abf15SRobert Mustacchi extern ddi_dma_attr_t bnxeTxCbDmaAttrib;
64d14abf15SRobert Mustacchi 
65d14abf15SRobert Mustacchi 
BnxeInstance(void * pDev)66d14abf15SRobert Mustacchi u8_t BnxeInstance(void * pDev)
67d14abf15SRobert Mustacchi {
68d14abf15SRobert Mustacchi     um_device_t * pUM = (um_device_t *)pDev;
69d14abf15SRobert Mustacchi     return (pUM == NULL) ? 0xf : pUM->instance;
70d14abf15SRobert Mustacchi }
71d14abf15SRobert Mustacchi 
72d14abf15SRobert Mustacchi 
73d14abf15SRobert Mustacchi /* pass in pointer to either lm_device_t or um_device_t */
BnxeDevName(void * pDev)74d14abf15SRobert Mustacchi char * BnxeDevName(void * pDev)
75d14abf15SRobert Mustacchi {
76d14abf15SRobert Mustacchi     um_device_t * pUM = (um_device_t *)pDev;
77d14abf15SRobert Mustacchi     return ((pUM == NULL) || (*pUM->devName == 0)) ? "(bnxe)" : pUM->devName;
78d14abf15SRobert Mustacchi }
79d14abf15SRobert Mustacchi 
80d14abf15SRobert Mustacchi 
BnxeChipName(um_device_t * pUM)81d14abf15SRobert Mustacchi char * BnxeChipName(um_device_t * pUM)
82d14abf15SRobert Mustacchi {
83d14abf15SRobert Mustacchi     switch (CHIP_NUM(&pUM->lm_dev) >> 16)
84d14abf15SRobert Mustacchi     {
85d14abf15SRobert Mustacchi     case 0x164e: return "BCM57710";
86d14abf15SRobert Mustacchi     case 0x164f: return "BCM57711";
87d14abf15SRobert Mustacchi     case 0x1650: return "BCM57711E";
88d14abf15SRobert Mustacchi     case 0x1662: return "BCM57712";
89d14abf15SRobert Mustacchi     case 0x1663: return "BCM57712NP";
90d14abf15SRobert Mustacchi     case 0x16a1: return "BCM57840";
91d14abf15SRobert Mustacchi     case 0x168d: return "BCM57840";
92d14abf15SRobert Mustacchi     case 0x16a4: return "BCM57840NP";
93d14abf15SRobert Mustacchi     case 0x16ab: return "BCM57840NP";
94d14abf15SRobert Mustacchi     case 0x168e: return "BCM57810";
95d14abf15SRobert Mustacchi     case 0x16ae: return "BCM57810NP";
96d14abf15SRobert Mustacchi     case 0x168a: return "BCM57800";
97d14abf15SRobert Mustacchi     case 0x16a5: return "BCM57800NP";
98d14abf15SRobert Mustacchi     default:     return "UNKNOWN";
99d14abf15SRobert Mustacchi     }
100d14abf15SRobert Mustacchi }
101d14abf15SRobert Mustacchi 
102d14abf15SRobert Mustacchi 
BnxeProtoSupport(um_device_t * pUM,int proto)103d14abf15SRobert Mustacchi boolean_t BnxeProtoSupport(um_device_t * pUM, int proto)
104d14abf15SRobert Mustacchi {
105d14abf15SRobert Mustacchi     boolean_t do_eth;
106d14abf15SRobert Mustacchi     boolean_t do_fcoe;
107d14abf15SRobert Mustacchi     uint32_t port_feature_config_sf;
108d14abf15SRobert Mustacchi 
109d14abf15SRobert Mustacchi     if (IS_MULTI_VNIC(&pUM->lm_dev))
110d14abf15SRobert Mustacchi     {
111d14abf15SRobert Mustacchi         do_eth  = B_FALSE;
112d14abf15SRobert Mustacchi         do_fcoe = B_FALSE;
113d14abf15SRobert Mustacchi 
114d14abf15SRobert Mustacchi         if (pUM->lm_dev.hw_info.mcp_detected == 1)
115d14abf15SRobert Mustacchi         {
116d14abf15SRobert Mustacchi             if (pUM->lm_dev.params.mf_proto_support_flags &
117d14abf15SRobert Mustacchi                 LM_PROTO_SUPPORT_ETHERNET)
118d14abf15SRobert Mustacchi             {
119d14abf15SRobert Mustacchi                 do_eth = B_TRUE;
120d14abf15SRobert Mustacchi             }
121d14abf15SRobert Mustacchi 
122d14abf15SRobert Mustacchi             if (pUM->lm_dev.params.mf_proto_support_flags &
123d14abf15SRobert Mustacchi                 LM_PROTO_SUPPORT_FCOE)
124d14abf15SRobert Mustacchi             {
125d14abf15SRobert Mustacchi                 do_fcoe = B_TRUE;
126d14abf15SRobert Mustacchi             }
127d14abf15SRobert Mustacchi         }
128d14abf15SRobert Mustacchi         else
129d14abf15SRobert Mustacchi         {
130d14abf15SRobert Mustacchi             /* mcp is not present so allow enumeration */
131d14abf15SRobert Mustacchi             do_eth  = B_TRUE;
132d14abf15SRobert Mustacchi             do_fcoe = B_TRUE;
133d14abf15SRobert Mustacchi         }
134d14abf15SRobert Mustacchi     }
135d14abf15SRobert Mustacchi     else /* SF */
136d14abf15SRobert Mustacchi     {
137d14abf15SRobert Mustacchi         do_eth  = B_TRUE;
138d14abf15SRobert Mustacchi         do_fcoe = B_FALSE;
139d14abf15SRobert Mustacchi 
140d14abf15SRobert Mustacchi         /* check per port storage personality config from NVRAM */
141d14abf15SRobert Mustacchi         port_feature_config_sf = (pUM->lm_dev.hw_info.port_feature_config &
142d14abf15SRobert Mustacchi                                   PORT_FEAT_CFG_STORAGE_PERSONALITY_MASK);
143d14abf15SRobert Mustacchi 
144d14abf15SRobert Mustacchi         switch (port_feature_config_sf)
145d14abf15SRobert Mustacchi         {
146d14abf15SRobert Mustacchi         case PORT_FEAT_CFG_STORAGE_PERSONALITY_ISCSI:
147d14abf15SRobert Mustacchi             break;
148d14abf15SRobert Mustacchi 
149d14abf15SRobert Mustacchi         case PORT_FEAT_CFG_STORAGE_PERSONALITY_FCOE:
150d14abf15SRobert Mustacchi         case PORT_FEAT_CFG_STORAGE_PERSONALITY_BOTH:
151d14abf15SRobert Mustacchi         case PORT_FEAT_CFG_STORAGE_PERSONALITY_DEFAULT:
152d14abf15SRobert Mustacchi         default:
153d14abf15SRobert Mustacchi             do_fcoe = B_TRUE;
154d14abf15SRobert Mustacchi             break;
155d14abf15SRobert Mustacchi         }
156d14abf15SRobert Mustacchi     }
157d14abf15SRobert Mustacchi 
158d14abf15SRobert Mustacchi     if (pUM->lm_dev.params.max_func_fcoe_cons == 0)
159d14abf15SRobert Mustacchi     {
160d14abf15SRobert Mustacchi         do_fcoe = B_FALSE;
161d14abf15SRobert Mustacchi     }
162d14abf15SRobert Mustacchi 
163d14abf15SRobert Mustacchi     return (((proto == LM_PROTO_SUPPORT_ETHERNET) && do_eth) ||
164d14abf15SRobert Mustacchi             ((proto == LM_PROTO_SUPPORT_FCOE) && do_fcoe));
165d14abf15SRobert Mustacchi }
166d14abf15SRobert Mustacchi 
167d14abf15SRobert Mustacchi 
BnxeProtoFcoeAfex(um_device_t * pUM)168d14abf15SRobert Mustacchi boolean_t BnxeProtoFcoeAfex(um_device_t * pUM)
169d14abf15SRobert Mustacchi {
170d14abf15SRobert Mustacchi     return ((pUM->lm_dev.params.mf_mode == MULTI_FUNCTION_AFEX) &&
171d14abf15SRobert Mustacchi             BnxeProtoSupport(pUM, LM_PROTO_SUPPORT_FCOE)) ? B_TRUE : B_FALSE;
172d14abf15SRobert Mustacchi }
173d14abf15SRobert Mustacchi 
174d14abf15SRobert Mustacchi 
BnxePciInit(um_device_t * pUM)175d14abf15SRobert Mustacchi static boolean_t BnxePciInit(um_device_t * pUM)
176d14abf15SRobert Mustacchi {
177d14abf15SRobert Mustacchi     /* setup resources needed for accessing the PCI configuration space */
178d14abf15SRobert Mustacchi     if (pci_config_setup(pUM->pDev, &pUM->pPciCfg) != DDI_SUCCESS)
179d14abf15SRobert Mustacchi     {
180d14abf15SRobert Mustacchi         BnxeLogWarn(pUM, "Failed to setup PCI config");
181d14abf15SRobert Mustacchi         return B_FALSE;
182d14abf15SRobert Mustacchi     }
183d14abf15SRobert Mustacchi 
184d14abf15SRobert Mustacchi     return B_TRUE;
185d14abf15SRobert Mustacchi }
186d14abf15SRobert Mustacchi 
187d14abf15SRobert Mustacchi 
BnxePciDestroy(um_device_t * pUM)188d14abf15SRobert Mustacchi static void BnxePciDestroy(um_device_t * pUM)
189d14abf15SRobert Mustacchi {
190d14abf15SRobert Mustacchi     if (pUM->pPciCfg)
191d14abf15SRobert Mustacchi     {
192d14abf15SRobert Mustacchi         pci_config_teardown(&pUM->pPciCfg);
193d14abf15SRobert Mustacchi         pUM->pPciCfg = NULL;
194d14abf15SRobert Mustacchi     }
195d14abf15SRobert Mustacchi }
196d14abf15SRobert Mustacchi 
197d14abf15SRobert Mustacchi 
BnxeBarMemDestroy(um_device_t * pUM)198d14abf15SRobert Mustacchi static void BnxeBarMemDestroy(um_device_t * pUM)
199d14abf15SRobert Mustacchi {
200d14abf15SRobert Mustacchi     BnxeMemRegion * pMemRegion;
201d14abf15SRobert Mustacchi 
202d14abf15SRobert Mustacchi     /* free the BAR mappings */
203d14abf15SRobert Mustacchi     while (!d_list_is_empty(&pUM->memRegionList))
204d14abf15SRobert Mustacchi     {
205d14abf15SRobert Mustacchi         pMemRegion = (BnxeMemRegion *)d_list_peek_head(&pUM->memRegionList);
206d14abf15SRobert Mustacchi         mm_unmap_io_space(&pUM->lm_dev,
207d14abf15SRobert Mustacchi                           pMemRegion->pRegAddr,
208d14abf15SRobert Mustacchi                           pMemRegion->size);
209d14abf15SRobert Mustacchi     }
210d14abf15SRobert Mustacchi }
211d14abf15SRobert Mustacchi 
212d14abf15SRobert Mustacchi 
BnxeMutexInit(um_device_t * pUM)213d14abf15SRobert Mustacchi static void BnxeMutexInit(um_device_t * pUM)
214d14abf15SRobert Mustacchi {
215d14abf15SRobert Mustacchi     lm_device_t * pLM = &pUM->lm_dev;
216d14abf15SRobert Mustacchi     int idx;
217d14abf15SRobert Mustacchi 
218d14abf15SRobert Mustacchi     for (idx = 0; idx < (MAX_RSS_CHAINS + 1); idx++)
219d14abf15SRobert Mustacchi     {
220d14abf15SRobert Mustacchi         mutex_init(&pUM->intrMutex[idx], NULL,
221d14abf15SRobert Mustacchi                    MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
222d14abf15SRobert Mustacchi         mutex_init(&pUM->intrFlipMutex[idx], NULL,
223d14abf15SRobert Mustacchi                    MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
224d14abf15SRobert Mustacchi         mutex_init(&pUM->sbMutex[idx], NULL,
225d14abf15SRobert Mustacchi                    MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
226d14abf15SRobert Mustacchi     }
227d14abf15SRobert Mustacchi 
228d14abf15SRobert Mustacchi     for (idx = 0; idx < MAX_ETH_CONS; idx++)
229d14abf15SRobert Mustacchi     {
230d14abf15SRobert Mustacchi         mutex_init(&pUM->txq[idx].txMutex, NULL,
231d14abf15SRobert Mustacchi                    MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
232d14abf15SRobert Mustacchi         mutex_init(&pUM->txq[idx].freeTxDescMutex, NULL,
233d14abf15SRobert Mustacchi                    MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
234d14abf15SRobert Mustacchi         pUM->txq[idx].pUM = pUM;
235d14abf15SRobert Mustacchi         pUM->txq[idx].idx = idx;
236d14abf15SRobert Mustacchi     }
237d14abf15SRobert Mustacchi 
238d14abf15SRobert Mustacchi     for (idx = 0; idx < MAX_ETH_CONS; idx++)
239d14abf15SRobert Mustacchi     {
240d14abf15SRobert Mustacchi         mutex_init(&pUM->rxq[idx].rxMutex, NULL,
241d14abf15SRobert Mustacchi                    MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
242d14abf15SRobert Mustacchi         mutex_init(&pUM->rxq[idx].doneRxMutex, NULL,
243d14abf15SRobert Mustacchi                    MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
244d14abf15SRobert Mustacchi         pUM->rxq[idx].pUM = pUM;
245d14abf15SRobert Mustacchi         pUM->rxq[idx].idx = idx;
246d14abf15SRobert Mustacchi     }
247d14abf15SRobert Mustacchi 
248d14abf15SRobert Mustacchi     for (idx = 0; idx < USER_OPTION_RX_RING_GROUPS_MAX; idx++)
249d14abf15SRobert Mustacchi     {
250d14abf15SRobert Mustacchi         pUM->rxqGroup[idx].pUM = pUM;
251d14abf15SRobert Mustacchi         pUM->rxqGroup[idx].idx = idx;
252d14abf15SRobert Mustacchi     }
253d14abf15SRobert Mustacchi 
254d14abf15SRobert Mustacchi     mutex_init(&pUM->ethConMutex, NULL,
255d14abf15SRobert Mustacchi                MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
256d14abf15SRobert Mustacchi     mutex_init(&pUM->mcpMutex, NULL,
257d14abf15SRobert Mustacchi                MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
258d14abf15SRobert Mustacchi     mutex_init(&pUM->phyMutex, NULL,
259d14abf15SRobert Mustacchi                MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
260d14abf15SRobert Mustacchi     mutex_init(&pUM->indMutex, NULL,
261d14abf15SRobert Mustacchi                MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
262d14abf15SRobert Mustacchi     mutex_init(&pUM->cidMutex, NULL,
263d14abf15SRobert Mustacchi                MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
264d14abf15SRobert Mustacchi     mutex_init(&pUM->spqMutex, NULL,
265d14abf15SRobert Mustacchi                MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
266d14abf15SRobert Mustacchi     mutex_init(&pUM->spReqMutex, NULL,
267d14abf15SRobert Mustacchi                MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
268d14abf15SRobert Mustacchi     mutex_init(&pUM->rrReqMutex, NULL,
269d14abf15SRobert Mustacchi                MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
270d14abf15SRobert Mustacchi     mutex_init(&pUM->islesCtrlMutex, NULL,
271d14abf15SRobert Mustacchi                MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
272d14abf15SRobert Mustacchi     mutex_init(&pUM->toeMutex, NULL,
273d14abf15SRobert Mustacchi                MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
274d14abf15SRobert Mustacchi     mutex_init(&pUM->memMutex, NULL,
275d14abf15SRobert Mustacchi                MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
276d14abf15SRobert Mustacchi     mutex_init(&pUM->offloadMutex, NULL,
277d14abf15SRobert Mustacchi                MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
278d14abf15SRobert Mustacchi     mutex_init(&pUM->hwInitMutex, NULL,
279d14abf15SRobert Mustacchi                MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
280d14abf15SRobert Mustacchi     mutex_init(&pUM->gldMutex, NULL,
281d14abf15SRobert Mustacchi                MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
282d14abf15SRobert Mustacchi     rw_init(&pUM->gldTxMutex, NULL, RW_DRIVER, NULL);
283d14abf15SRobert Mustacchi     mutex_init(&pUM->timerMutex, NULL,
284d14abf15SRobert Mustacchi                MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
285d14abf15SRobert Mustacchi     mutex_init(&pUM->kstatMutex, NULL,
286d14abf15SRobert Mustacchi                MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
287d14abf15SRobert Mustacchi }
288d14abf15SRobert Mustacchi 
289d14abf15SRobert Mustacchi 
BnxeMutexDestroy(um_device_t * pUM)290d14abf15SRobert Mustacchi static void BnxeMutexDestroy(um_device_t * pUM)
291d14abf15SRobert Mustacchi {
292d14abf15SRobert Mustacchi     lm_device_t * pLM = &pUM->lm_dev;
293d14abf15SRobert Mustacchi     int idx;
294d14abf15SRobert Mustacchi 
295d14abf15SRobert Mustacchi     for (idx = 0; idx < (MAX_RSS_CHAINS + 1); idx++)
296d14abf15SRobert Mustacchi     {
297d14abf15SRobert Mustacchi         mutex_destroy(&pUM->intrMutex[idx]);
298d14abf15SRobert Mustacchi         mutex_destroy(&pUM->intrFlipMutex[idx]);
299d14abf15SRobert Mustacchi         mutex_destroy(&pUM->sbMutex[idx]);
300d14abf15SRobert Mustacchi     }
301d14abf15SRobert Mustacchi 
302d14abf15SRobert Mustacchi     for (idx = 0; idx < MAX_ETH_CONS; idx++)
303d14abf15SRobert Mustacchi     {
304d14abf15SRobert Mustacchi         mutex_destroy(&pUM->txq[idx].txMutex);
305d14abf15SRobert Mustacchi         mutex_destroy(&pUM->txq[idx].freeTxDescMutex);
306d14abf15SRobert Mustacchi     }
307d14abf15SRobert Mustacchi 
308d14abf15SRobert Mustacchi     for (idx = 0; idx < MAX_ETH_CONS; idx++)
309d14abf15SRobert Mustacchi     {
310d14abf15SRobert Mustacchi         mutex_destroy(&pUM->rxq[idx].rxMutex);
311d14abf15SRobert Mustacchi         mutex_destroy(&pUM->rxq[idx].doneRxMutex);
312d14abf15SRobert Mustacchi     }
313d14abf15SRobert Mustacchi 
314d14abf15SRobert Mustacchi     mutex_destroy(&pUM->ethConMutex);
315d14abf15SRobert Mustacchi     mutex_destroy(&pUM->mcpMutex);
316d14abf15SRobert Mustacchi     mutex_destroy(&pUM->phyMutex);
317d14abf15SRobert Mustacchi     mutex_destroy(&pUM->indMutex);
318d14abf15SRobert Mustacchi     mutex_destroy(&pUM->cidMutex);
319d14abf15SRobert Mustacchi     mutex_destroy(&pUM->spqMutex);
320d14abf15SRobert Mustacchi     mutex_destroy(&pUM->spReqMutex);
321d14abf15SRobert Mustacchi     mutex_destroy(&pUM->rrReqMutex);
322d14abf15SRobert Mustacchi     mutex_destroy(&pUM->islesCtrlMutex);
323d14abf15SRobert Mustacchi     mutex_destroy(&pUM->toeMutex);
324d14abf15SRobert Mustacchi     mutex_destroy(&pUM->memMutex);   /* not until all mem deleted */
325d14abf15SRobert Mustacchi     mutex_destroy(&pUM->offloadMutex);
326d14abf15SRobert Mustacchi     mutex_destroy(&pUM->hwInitMutex);
327d14abf15SRobert Mustacchi     mutex_destroy(&pUM->gldMutex);
328d14abf15SRobert Mustacchi     rw_destroy(&pUM->gldTxMutex);
329d14abf15SRobert Mustacchi     mutex_destroy(&pUM->timerMutex);
330d14abf15SRobert Mustacchi     mutex_destroy(&pUM->kstatMutex);
331d14abf15SRobert Mustacchi }
332d14abf15SRobert Mustacchi 
333d14abf15SRobert Mustacchi 
334d14abf15SRobert Mustacchi /* FMA support */
335d14abf15SRobert Mustacchi 
BnxeCheckAccHandle(ddi_acc_handle_t handle)336d14abf15SRobert Mustacchi int BnxeCheckAccHandle(ddi_acc_handle_t handle)
337d14abf15SRobert Mustacchi {
338d14abf15SRobert Mustacchi     ddi_fm_error_t de;
339d14abf15SRobert Mustacchi 
340d14abf15SRobert Mustacchi     ddi_fm_acc_err_get(handle, &de, DDI_FME_VERSION);
341d14abf15SRobert Mustacchi     ddi_fm_acc_err_clear(handle, DDI_FME_VERSION);
342d14abf15SRobert Mustacchi 
343d14abf15SRobert Mustacchi     return (de.fme_status);
344d14abf15SRobert Mustacchi }
345d14abf15SRobert Mustacchi 
346d14abf15SRobert Mustacchi 
BnxeCheckDmaHandle(ddi_dma_handle_t handle)347d14abf15SRobert Mustacchi int BnxeCheckDmaHandle(ddi_dma_handle_t handle)
348d14abf15SRobert Mustacchi {
349d14abf15SRobert Mustacchi     ddi_fm_error_t de;
350d14abf15SRobert Mustacchi 
351d14abf15SRobert Mustacchi     ddi_fm_dma_err_get(handle, &de, DDI_FME_VERSION);
352d14abf15SRobert Mustacchi 
353d14abf15SRobert Mustacchi     return (de.fme_status);
354d14abf15SRobert Mustacchi }
355d14abf15SRobert Mustacchi 
356d14abf15SRobert Mustacchi 
357d14abf15SRobert Mustacchi /* The IO fault service error handling callback function */
BnxeFmErrorCb(dev_info_t * pDev,ddi_fm_error_t * err,const void * impl_data)358d14abf15SRobert Mustacchi static int BnxeFmErrorCb(dev_info_t *     pDev,
359d14abf15SRobert Mustacchi                          ddi_fm_error_t * err,
360d14abf15SRobert Mustacchi                          const void *     impl_data)
361d14abf15SRobert Mustacchi {
362d14abf15SRobert Mustacchi     /*
363d14abf15SRobert Mustacchi      * As the driver can always deal with an error in any dma or
364d14abf15SRobert Mustacchi      * access handle, we can just return the fme_status value.
365d14abf15SRobert Mustacchi      */
366d14abf15SRobert Mustacchi     pci_ereport_post(pDev, err, NULL);
367d14abf15SRobert Mustacchi 
368d14abf15SRobert Mustacchi     return (err->fme_status);
369d14abf15SRobert Mustacchi }
370d14abf15SRobert Mustacchi 
371d14abf15SRobert Mustacchi 
BnxeFmInit(um_device_t * pUM)372d14abf15SRobert Mustacchi static void BnxeFmInit(um_device_t * pUM)
373d14abf15SRobert Mustacchi {
374d14abf15SRobert Mustacchi     ddi_iblock_cookie_t iblk;
375d14abf15SRobert Mustacchi     int fma_acc_flag;
376d14abf15SRobert Mustacchi     int fma_dma_flag;
377d14abf15SRobert Mustacchi 
378d14abf15SRobert Mustacchi     /* Only register with IO Fault Services if we have some capability */
379d14abf15SRobert Mustacchi     if (pUM->fmCapabilities & DDI_FM_ACCCHK_CAPABLE)
380d14abf15SRobert Mustacchi     {
381d14abf15SRobert Mustacchi         bnxeAccessAttribBAR.devacc_attr_version = DDI_DEVICE_ATTR_V1;
382d14abf15SRobert Mustacchi         bnxeAccessAttribBAR.devacc_attr_access = DDI_FLAGERR_ACC;
383d14abf15SRobert Mustacchi     }
384d14abf15SRobert Mustacchi 
385d14abf15SRobert Mustacchi     if (pUM->fmCapabilities & DDI_FM_DMACHK_CAPABLE)
386d14abf15SRobert Mustacchi     {
387d14abf15SRobert Mustacchi         bnxeDmaPageAttrib.dma_attr_flags = DDI_DMA_FLAGERR;
388d14abf15SRobert Mustacchi         bnxeRxDmaAttrib.dma_attr_flags   = DDI_DMA_FLAGERR;
389d14abf15SRobert Mustacchi         bnxeTxDmaAttrib.dma_attr_flags   = DDI_DMA_FLAGERR;
390d14abf15SRobert Mustacchi         bnxeTxCbDmaAttrib.dma_attr_flags = DDI_DMA_FLAGERR;
391d14abf15SRobert Mustacchi     }
392d14abf15SRobert Mustacchi 
393*55fea89dSDan Cross     if (pUM->fmCapabilities)
394d14abf15SRobert Mustacchi     {
395d14abf15SRobert Mustacchi         /* Register capabilities with IO Fault Services */
396d14abf15SRobert Mustacchi         ddi_fm_init(pUM->pDev, &pUM->fmCapabilities, &iblk);
397d14abf15SRobert Mustacchi 
398d14abf15SRobert Mustacchi         /* Initialize pci ereport capabilities if ereport capable */
399d14abf15SRobert Mustacchi         if (DDI_FM_EREPORT_CAP(pUM->fmCapabilities) ||
400d14abf15SRobert Mustacchi             DDI_FM_ERRCB_CAP(pUM->fmCapabilities))
401d14abf15SRobert Mustacchi         {
402d14abf15SRobert Mustacchi             pci_ereport_setup(pUM->pDev);
403d14abf15SRobert Mustacchi         }
404d14abf15SRobert Mustacchi 
405d14abf15SRobert Mustacchi         /* Register error callback if error callback capable */
406d14abf15SRobert Mustacchi         if (DDI_FM_ERRCB_CAP(pUM->fmCapabilities))
407d14abf15SRobert Mustacchi         {
408d14abf15SRobert Mustacchi             ddi_fm_handler_register(pUM->pDev, BnxeFmErrorCb, (void *)pUM);
409d14abf15SRobert Mustacchi         }
410d14abf15SRobert Mustacchi     }
411d14abf15SRobert Mustacchi }
412d14abf15SRobert Mustacchi 
413d14abf15SRobert Mustacchi 
BnxeFmFini(um_device_t * pUM)414d14abf15SRobert Mustacchi static void BnxeFmFini(um_device_t * pUM)
415d14abf15SRobert Mustacchi {
416d14abf15SRobert Mustacchi     /* Only unregister FMA capabilities if we registered some */
417*55fea89dSDan Cross     if (pUM->fmCapabilities)
418d14abf15SRobert Mustacchi     {
419d14abf15SRobert Mustacchi         /* Release any resources allocated by pci_ereport_setup() */
420d14abf15SRobert Mustacchi         if (DDI_FM_EREPORT_CAP(pUM->fmCapabilities) ||
421d14abf15SRobert Mustacchi             DDI_FM_ERRCB_CAP(pUM->fmCapabilities))
422d14abf15SRobert Mustacchi         {
423d14abf15SRobert Mustacchi             pci_ereport_teardown(pUM->pDev);
424d14abf15SRobert Mustacchi         }
425d14abf15SRobert Mustacchi 
426d14abf15SRobert Mustacchi         /* Un-register error callback if error callback capable */
427d14abf15SRobert Mustacchi         if (DDI_FM_ERRCB_CAP(pUM->fmCapabilities))
428d14abf15SRobert Mustacchi         {
429d14abf15SRobert Mustacchi             ddi_fm_handler_unregister(pUM->pDev);
430d14abf15SRobert Mustacchi         }
431d14abf15SRobert Mustacchi 
432d14abf15SRobert Mustacchi         /* Unregister from IO Fault Services */
433d14abf15SRobert Mustacchi         ddi_fm_fini(pUM->pDev);
434d14abf15SRobert Mustacchi     }
435d14abf15SRobert Mustacchi }
436d14abf15SRobert Mustacchi 
437d14abf15SRobert Mustacchi 
BnxeFmErrorReport(um_device_t * pUM,char * detail)438d14abf15SRobert Mustacchi void BnxeFmErrorReport(um_device_t * pUM,
439d14abf15SRobert Mustacchi                        char *        detail)
440d14abf15SRobert Mustacchi {
441d14abf15SRobert Mustacchi     uint64_t ena;
442d14abf15SRobert Mustacchi     char buf[FM_MAX_CLASS];
443d14abf15SRobert Mustacchi 
444d14abf15SRobert Mustacchi     (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail);
445d14abf15SRobert Mustacchi 
446d14abf15SRobert Mustacchi     ena = fm_ena_generate(0, FM_ENA_FMT1);
447d14abf15SRobert Mustacchi 
448d14abf15SRobert Mustacchi     if (DDI_FM_EREPORT_CAP(pUM->fmCapabilities))
449d14abf15SRobert Mustacchi     {
450d14abf15SRobert Mustacchi         ddi_fm_ereport_post(pUM->pDev, buf, ena, DDI_NOSLEEP,
451d14abf15SRobert Mustacchi                             FM_VERSION, DATA_TYPE_UINT8,
452d14abf15SRobert Mustacchi                             FM_EREPORT_VERS0, NULL);
453d14abf15SRobert Mustacchi     }
454d14abf15SRobert Mustacchi }
455d14abf15SRobert Mustacchi 
456d14abf15SRobert Mustacchi 
BnxeAttachDevice(um_device_t * pUM)457d14abf15SRobert Mustacchi static boolean_t BnxeAttachDevice(um_device_t * pUM)
458d14abf15SRobert Mustacchi {
459d14abf15SRobert Mustacchi     int rc;
460d14abf15SRobert Mustacchi     int * props = NULL;
461d14abf15SRobert Mustacchi     uint_t numProps;
462d14abf15SRobert Mustacchi     u32_t vendor_id;
463d14abf15SRobert Mustacchi     u32_t device_id;
464d14abf15SRobert Mustacchi 
465d14abf15SRobert Mustacchi     /* fm-capable in bnxe.conf can be used to set fmCapabilities. */
466d14abf15SRobert Mustacchi     pUM->fmCapabilities = ddi_prop_get_int(DDI_DEV_T_ANY,
467d14abf15SRobert Mustacchi                                            pUM->pDev,
468d14abf15SRobert Mustacchi                                            DDI_PROP_DONTPASS,
469d14abf15SRobert Mustacchi                                            "fm-capable",
470d14abf15SRobert Mustacchi                                            (DDI_FM_EREPORT_CAPABLE |
471d14abf15SRobert Mustacchi                                             DDI_FM_ACCCHK_CAPABLE  |
472d14abf15SRobert Mustacchi                                             DDI_FM_DMACHK_CAPABLE  |
473d14abf15SRobert Mustacchi                                             DDI_FM_ERRCB_CAPABLE));
474d14abf15SRobert Mustacchi 
475d14abf15SRobert Mustacchi     /* Register capabilities with IO Fault Services. */
476d14abf15SRobert Mustacchi     BnxeFmInit(pUM);
477d14abf15SRobert Mustacchi 
478d14abf15SRobert Mustacchi     if (!BnxePciInit(pUM))
479d14abf15SRobert Mustacchi     {
480d14abf15SRobert Mustacchi         BnxeFmFini(pUM);
481d14abf15SRobert Mustacchi 
482d14abf15SRobert Mustacchi         return B_FALSE;
483d14abf15SRobert Mustacchi     }
484d14abf15SRobert Mustacchi 
485d14abf15SRobert Mustacchi     BnxeMutexInit(pUM);
486d14abf15SRobert Mustacchi 
487d14abf15SRobert Mustacchi     if (!BnxeWorkQueueInit(pUM))
488d14abf15SRobert Mustacchi     {
489d14abf15SRobert Mustacchi         return B_FALSE;
490d14abf15SRobert Mustacchi     }
491d14abf15SRobert Mustacchi 
492d14abf15SRobert Mustacchi     rc = lm_get_dev_info(&pUM->lm_dev);
493d14abf15SRobert Mustacchi 
494d14abf15SRobert Mustacchi     if (pUM->fmCapabilities &&
495d14abf15SRobert Mustacchi         BnxeCheckAccHandle(pUM->pPciCfg) != DDI_FM_OK)
496d14abf15SRobert Mustacchi     {
497d14abf15SRobert Mustacchi         ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_LOST);
498d14abf15SRobert Mustacchi         BnxeWorkQueueWaitAndDestroy(pUM);
499d14abf15SRobert Mustacchi         BnxeMutexDestroy(pUM);
500d14abf15SRobert Mustacchi         BnxePciDestroy(pUM);
501d14abf15SRobert Mustacchi         BnxeFmFini(pUM);
502d14abf15SRobert Mustacchi 
503d14abf15SRobert Mustacchi         return B_FALSE;
504d14abf15SRobert Mustacchi     }
505d14abf15SRobert Mustacchi 
506d14abf15SRobert Mustacchi     if (pUM->fmCapabilities &&
507d14abf15SRobert Mustacchi         BnxeCheckAccHandle(pUM->lm_dev.vars.reg_handle[BAR_0]) != DDI_FM_OK)
508d14abf15SRobert Mustacchi     {
509d14abf15SRobert Mustacchi         ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_LOST);
510d14abf15SRobert Mustacchi         BnxeWorkQueueWaitAndDestroy(pUM);
511d14abf15SRobert Mustacchi         BnxeMutexDestroy(pUM);
512d14abf15SRobert Mustacchi         BnxePciDestroy(pUM);
513d14abf15SRobert Mustacchi         BnxeFmFini(pUM);
514d14abf15SRobert Mustacchi 
515d14abf15SRobert Mustacchi         return B_FALSE;
516d14abf15SRobert Mustacchi     }
517d14abf15SRobert Mustacchi 
518d14abf15SRobert Mustacchi     if (rc != LM_STATUS_SUCCESS)
519d14abf15SRobert Mustacchi     {
520d14abf15SRobert Mustacchi         BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE);
521d14abf15SRobert Mustacchi         ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_LOST);
522d14abf15SRobert Mustacchi         BnxeWorkQueueWaitAndDestroy(pUM);
523d14abf15SRobert Mustacchi         BnxeMutexDestroy(pUM);
524d14abf15SRobert Mustacchi         BnxePciDestroy(pUM);
525d14abf15SRobert Mustacchi         BnxeFmFini(pUM);
526d14abf15SRobert Mustacchi 
527d14abf15SRobert Mustacchi         BnxeLogWarn(pUM, "Failed to get device information");
528d14abf15SRobert Mustacchi         return B_FALSE;
529d14abf15SRobert Mustacchi     }
530d14abf15SRobert Mustacchi 
531d14abf15SRobert Mustacchi #if 0
532d14abf15SRobert Mustacchi     if (IS_PFDEV(&pUM->lm_dev) && lm_check_if_pf_assigned_to_vm(&pUM->lm_dev))
533d14abf15SRobert Mustacchi     {
534d14abf15SRobert Mustacchi         lm_set_virt_mode(&pUM->lm_dev, DEVICE_TYPE_PF, VT_ASSIGNED_TO_VM_PF);
535d14abf15SRobert Mustacchi     }
536d14abf15SRobert Mustacchi #endif
537*55fea89dSDan Cross 
538d14abf15SRobert Mustacchi     /* check if FCoE is enabled on this function */
539d14abf15SRobert Mustacchi #if 0
540d14abf15SRobert Mustacchi     pUM->do_fcoe =
541d14abf15SRobert Mustacchi         ((CHIP_IS_E2(&pUM->lm_dev) || CHIP_IS_E3(&pUM->lm_dev)) &&
542d14abf15SRobert Mustacchi          BnxeProtoSupport(pUM, LM_PROTO_SUPPORT_FCOE)) ? B_TRUE :
543d14abf15SRobert Mustacchi                                                          B_FALSE;
544d14abf15SRobert Mustacchi #else
545d14abf15SRobert Mustacchi     pUM->do_fcoe = B_FALSE;
546d14abf15SRobert Mustacchi #endif
547d14abf15SRobert Mustacchi 
548d14abf15SRobert Mustacchi     lm_get_iscsi_boot_info_block(&pUM->lm_dev, &pUM->iscsiInfo);
549d14abf15SRobert Mustacchi     if (pUM->iscsiInfo.signature != 0)
550d14abf15SRobert Mustacchi     {
551d14abf15SRobert Mustacchi         BnxeLogInfo(pUM, "MBA FCoE boot occurred on this interface.");
552d14abf15SRobert Mustacchi     }
553d14abf15SRobert Mustacchi 
554d14abf15SRobert Mustacchi     if (!BnxeIntrInit(pUM))
555d14abf15SRobert Mustacchi     {
556d14abf15SRobert Mustacchi         BnxeBarMemDestroy(pUM);
557d14abf15SRobert Mustacchi         BnxeWorkQueueWaitAndDestroy(pUM);
558d14abf15SRobert Mustacchi         BnxeMutexDestroy(pUM);
559d14abf15SRobert Mustacchi         BnxePciDestroy(pUM);
560d14abf15SRobert Mustacchi         BnxeFmFini(pUM);
561d14abf15SRobert Mustacchi 
562d14abf15SRobert Mustacchi         return B_FALSE;
563d14abf15SRobert Mustacchi     }
564d14abf15SRobert Mustacchi 
565d14abf15SRobert Mustacchi     if (!BnxeKstatInit(pUM))
566d14abf15SRobert Mustacchi     {
567d14abf15SRobert Mustacchi         BnxeIntrFini(pUM);
568d14abf15SRobert Mustacchi         BnxeBarMemDestroy(pUM);
569d14abf15SRobert Mustacchi         BnxeWorkQueueWaitAndDestroy(pUM);
570d14abf15SRobert Mustacchi         BnxeMutexDestroy(pUM);
571d14abf15SRobert Mustacchi         BnxePciDestroy(pUM);
572d14abf15SRobert Mustacchi         BnxeFmFini(pUM);
573d14abf15SRobert Mustacchi 
574d14abf15SRobert Mustacchi         return B_FALSE;
575d14abf15SRobert Mustacchi     }
576d14abf15SRobert Mustacchi 
577d14abf15SRobert Mustacchi     if (BnxeProtoFcoeAfex(pUM))
578d14abf15SRobert Mustacchi     {
579d14abf15SRobert Mustacchi         /* No support for L2 on FCoE enabled AFEX function! */
580d14abf15SRobert Mustacchi         BnxeLogInfo(pUM, "FCoE AFEX function, not registering with GLD.");
581d14abf15SRobert Mustacchi #if 0
582d14abf15SRobert Mustacchi         /*
583d14abf15SRobert Mustacchi          * The following is wonky. Doing a CLONE_DEV makes it visible to
584d14abf15SRobert Mustacchi          * various L2 networking commands even though the instance was
585d14abf15SRobert Mustacchi          * not registered with GLDv3 via mac_register().
586d14abf15SRobert Mustacchi          */
587d14abf15SRobert Mustacchi 
588d14abf15SRobert Mustacchi         /* Create a style-2 DLPI device */
589d14abf15SRobert Mustacchi         if (ddi_create_minor_node(pUM->pDev,
590d14abf15SRobert Mustacchi                                   (char *)ddi_driver_name(pUM->pDev),
591d14abf15SRobert Mustacchi                                   S_IFCHR,
592d14abf15SRobert Mustacchi                                   0,
593d14abf15SRobert Mustacchi                                   DDI_PSEUDO, //DDI_NT_NET,
594d14abf15SRobert Mustacchi                                   CLONE_DEV) != DDI_SUCCESS)
595d14abf15SRobert Mustacchi         {
596d14abf15SRobert Mustacchi             BnxeLogWarn(pUM, "Failed to create device minor node.");
597d14abf15SRobert Mustacchi             BnxeKstatFini(pUM);
598d14abf15SRobert Mustacchi             BnxeIntrFini(pUM);
599d14abf15SRobert Mustacchi             BnxeBarMemDestroy(pUM);
600d14abf15SRobert Mustacchi             BnxeWorkQueueWaitAndDestroy(pUM);
601d14abf15SRobert Mustacchi             BnxeMutexDestroy(pUM);
602d14abf15SRobert Mustacchi             BnxePciDestroy(pUM);
603d14abf15SRobert Mustacchi             BnxeFmFini(pUM);
604d14abf15SRobert Mustacchi 
605d14abf15SRobert Mustacchi             return B_FALSE;
606d14abf15SRobert Mustacchi         }
607d14abf15SRobert Mustacchi 
608d14abf15SRobert Mustacchi         /* Create a style-1 DLPI device */
609d14abf15SRobert Mustacchi         if (ddi_create_minor_node(pUM->pDev,
610d14abf15SRobert Mustacchi                                   pUM->devName,
611d14abf15SRobert Mustacchi                                   S_IFCHR,
612d14abf15SRobert Mustacchi                                   pUM->instance,
613d14abf15SRobert Mustacchi                                   DDI_PSEUDO, //DDI_NT_NET,
614d14abf15SRobert Mustacchi                                   0) != DDI_SUCCESS)
615d14abf15SRobert Mustacchi         {
616d14abf15SRobert Mustacchi             BnxeLogWarn(pUM, "Failed to create device instance minor node.");
617d14abf15SRobert Mustacchi             ddi_remove_minor_node(pUM->pDev, (char *)ddi_driver_name(pUM->pDev));
618d14abf15SRobert Mustacchi             BnxeKstatFini(pUM);
619d14abf15SRobert Mustacchi             BnxeIntrFini(pUM);
620d14abf15SRobert Mustacchi             BnxeBarMemDestroy(pUM);
621d14abf15SRobert Mustacchi             BnxeWorkQueueWaitAndDestroy(pUM);
622d14abf15SRobert Mustacchi             BnxeMutexDestroy(pUM);
623d14abf15SRobert Mustacchi             BnxePciDestroy(pUM);
624d14abf15SRobert Mustacchi             BnxeFmFini(pUM);
625d14abf15SRobert Mustacchi 
626d14abf15SRobert Mustacchi             return B_FALSE;
627d14abf15SRobert Mustacchi         }
628d14abf15SRobert Mustacchi #endif
629d14abf15SRobert Mustacchi     }
630d14abf15SRobert Mustacchi     else
631d14abf15SRobert Mustacchi     {
632d14abf15SRobert Mustacchi         /* register with the GLDv3 MAC layer */
633d14abf15SRobert Mustacchi         if (!BnxeGldInit(pUM))
634d14abf15SRobert Mustacchi         {
635d14abf15SRobert Mustacchi             BnxeKstatFini(pUM);
636d14abf15SRobert Mustacchi             BnxeIntrFini(pUM);
637d14abf15SRobert Mustacchi             BnxeBarMemDestroy(pUM);
638d14abf15SRobert Mustacchi             BnxeWorkQueueWaitAndDestroy(pUM);
639d14abf15SRobert Mustacchi             BnxeMutexDestroy(pUM);
640d14abf15SRobert Mustacchi             BnxePciDestroy(pUM);
641d14abf15SRobert Mustacchi             BnxeFmFini(pUM);
642d14abf15SRobert Mustacchi 
643d14abf15SRobert Mustacchi             return B_FALSE;
644d14abf15SRobert Mustacchi         }
645d14abf15SRobert Mustacchi     }
646d14abf15SRobert Mustacchi 
647d14abf15SRobert Mustacchi     snprintf(pUM->version,
648d14abf15SRobert Mustacchi              sizeof(pUM->version),
649d14abf15SRobert Mustacchi              "%d.%d.%d",
650d14abf15SRobert Mustacchi              MAJVERSION,
651d14abf15SRobert Mustacchi              MINVERSION,
652d14abf15SRobert Mustacchi              REVVERSION);
653d14abf15SRobert Mustacchi 
654d14abf15SRobert Mustacchi     snprintf(pUM->versionLM,
655d14abf15SRobert Mustacchi              sizeof(pUM->versionLM),
656d14abf15SRobert Mustacchi              "%d.%d.%d",
657d14abf15SRobert Mustacchi              LM_DRIVER_MAJOR_VER,
658d14abf15SRobert Mustacchi              LM_DRIVER_MINOR_VER,
659d14abf15SRobert Mustacchi              LM_DRIVER_FIX_NUM);
660d14abf15SRobert Mustacchi 
661d14abf15SRobert Mustacchi     snprintf(pUM->versionFW,
662d14abf15SRobert Mustacchi              sizeof(pUM->versionFW),
663d14abf15SRobert Mustacchi              "%d.%d.%d.%d",
664d14abf15SRobert Mustacchi              BCM_5710_FW_MAJOR_VERSION,
665d14abf15SRobert Mustacchi              BCM_5710_FW_MINOR_VERSION,
666d14abf15SRobert Mustacchi              BCM_5710_FW_REVISION_VERSION,
667d14abf15SRobert Mustacchi              BCM_5710_FW_ENGINEERING_VERSION);
668d14abf15SRobert Mustacchi 
669d14abf15SRobert Mustacchi     snprintf(pUM->versionBC,
670d14abf15SRobert Mustacchi              sizeof(pUM->versionBC),
671d14abf15SRobert Mustacchi              "%d.%d.%d",
672d14abf15SRobert Mustacchi              ((pUM->lm_dev.hw_info.bc_rev >> 24) & 0xff),
673d14abf15SRobert Mustacchi              ((pUM->lm_dev.hw_info.bc_rev >> 16) & 0xff),
674d14abf15SRobert Mustacchi              ((pUM->lm_dev.hw_info.bc_rev >>  8) & 0xff));
675d14abf15SRobert Mustacchi 
676d14abf15SRobert Mustacchi     snprintf(pUM->chipName,
677d14abf15SRobert Mustacchi              sizeof(pUM->chipName),
678d14abf15SRobert Mustacchi              "%s",
679d14abf15SRobert Mustacchi              BnxeChipName(pUM));
680d14abf15SRobert Mustacchi 
681d14abf15SRobert Mustacchi     snprintf(pUM->chipID,
682d14abf15SRobert Mustacchi              sizeof(pUM->chipID),
683d14abf15SRobert Mustacchi              "0x%x",
684d14abf15SRobert Mustacchi              pUM->lm_dev.hw_info.chip_id);
685d14abf15SRobert Mustacchi 
686d14abf15SRobert Mustacchi     *pUM->bus_dev_func = 0;
687d14abf15SRobert Mustacchi 	rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, pUM->pDev,
688d14abf15SRobert Mustacchi                                    0, "reg", &props, &numProps);
689d14abf15SRobert Mustacchi 	if ((rc == DDI_PROP_SUCCESS) && (numProps > 0))
690d14abf15SRobert Mustacchi     {
691d14abf15SRobert Mustacchi         snprintf(pUM->bus_dev_func,
692d14abf15SRobert Mustacchi                  sizeof(pUM->bus_dev_func),
693d14abf15SRobert Mustacchi                  "%04x:%02x:%02x",
694d14abf15SRobert Mustacchi                  PCI_REG_BUS_G(props[0]),
695d14abf15SRobert Mustacchi                  PCI_REG_DEV_G(props[0]),
696d14abf15SRobert Mustacchi                  PCI_REG_FUNC_G(props[0]));
697d14abf15SRobert Mustacchi 		ddi_prop_free(props);
698d14abf15SRobert Mustacchi 	}
699d14abf15SRobert Mustacchi 
700d14abf15SRobert Mustacchi     vendor_id = 0;
701d14abf15SRobert Mustacchi 	rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, pUM->pDev,
702d14abf15SRobert Mustacchi                                    0, "vendor-id", &props, &numProps);
703d14abf15SRobert Mustacchi 	if ((rc == DDI_PROP_SUCCESS) && (numProps > 0))
704d14abf15SRobert Mustacchi     {
705d14abf15SRobert Mustacchi         vendor_id = props[0];
706d14abf15SRobert Mustacchi 		ddi_prop_free(props);
707d14abf15SRobert Mustacchi 	}
708d14abf15SRobert Mustacchi 
709d14abf15SRobert Mustacchi     device_id = 0;
710d14abf15SRobert Mustacchi 	rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, pUM->pDev,
711d14abf15SRobert Mustacchi                                    0, "device-id", &props, &numProps);
712d14abf15SRobert Mustacchi 	if ((rc == DDI_PROP_SUCCESS) && (numProps > 0))
713d14abf15SRobert Mustacchi     {
714d14abf15SRobert Mustacchi         device_id = props[0];
715d14abf15SRobert Mustacchi 		ddi_prop_free(props);
716d14abf15SRobert Mustacchi 	}
717d14abf15SRobert Mustacchi 
718d14abf15SRobert Mustacchi     snprintf(pUM->vendor_device,
719d14abf15SRobert Mustacchi              sizeof(pUM->vendor_device),
720d14abf15SRobert Mustacchi              "%04x:%04x",
721d14abf15SRobert Mustacchi              vendor_id,
722d14abf15SRobert Mustacchi              device_id);
723d14abf15SRobert Mustacchi 
724d14abf15SRobert Mustacchi     snprintf(pUM->intrAlloc,
725d14abf15SRobert Mustacchi              sizeof(pUM->intrAlloc),
726d14abf15SRobert Mustacchi              "%d %s",
727d14abf15SRobert Mustacchi              (pUM->intrType == DDI_INTR_TYPE_FIXED) ? 1 : (pUM->defIntr.intrCount +
728d14abf15SRobert Mustacchi                                                            pUM->fcoeIntr.intrCount +
729d14abf15SRobert Mustacchi                                                            pUM->rssIntr.intrCount),
730d14abf15SRobert Mustacchi              (pUM->intrType == DDI_INTR_TYPE_MSIX) ? "MSIX" :
731d14abf15SRobert Mustacchi              (pUM->intrType == DDI_INTR_TYPE_MSI)  ? "MSI"  :
732d14abf15SRobert Mustacchi                                                      "Fixed");
733d14abf15SRobert Mustacchi 
734d14abf15SRobert Mustacchi     BnxeLogInfo(pUM,
735d14abf15SRobert Mustacchi                 "(0x%p) %s %s - v%s - FW v%s - BC v%s - %s (%s)",
736d14abf15SRobert Mustacchi                 pUM,
737d14abf15SRobert Mustacchi                 pUM->chipName,
738d14abf15SRobert Mustacchi                 pUM->chipID,
739d14abf15SRobert Mustacchi                 pUM->version,
740d14abf15SRobert Mustacchi                 pUM->versionFW,
741d14abf15SRobert Mustacchi                 pUM->versionBC,
742d14abf15SRobert Mustacchi                 IS_MULTI_VNIC(&pUM->lm_dev) ? "MF" : "SF",
743d14abf15SRobert Mustacchi                 pUM->intrAlloc);
744d14abf15SRobert Mustacchi 
745d14abf15SRobert Mustacchi     return B_TRUE;
746d14abf15SRobert Mustacchi }
747d14abf15SRobert Mustacchi 
748d14abf15SRobert Mustacchi 
BnxeDetachDevice(um_device_t * pUM)749d14abf15SRobert Mustacchi static boolean_t BnxeDetachDevice(um_device_t * pUM)
750d14abf15SRobert Mustacchi {
751d14abf15SRobert Mustacchi     int rc;
752d14abf15SRobert Mustacchi 
753d14abf15SRobert Mustacchi     rc = BnxeFcoeFini(pUM);
754d14abf15SRobert Mustacchi 
755d14abf15SRobert Mustacchi     if ((rc != 0) && (rc != ENOTSUP) && (rc != ENODEV))
756d14abf15SRobert Mustacchi     {
757d14abf15SRobert Mustacchi         return B_FALSE;
758d14abf15SRobert Mustacchi     }
759d14abf15SRobert Mustacchi 
760d14abf15SRobert Mustacchi     if (BnxeProtoFcoeAfex(pUM))
761d14abf15SRobert Mustacchi     {
762d14abf15SRobert Mustacchi         /* No support for L2 on FCoE enabled AFEX function! */
763d14abf15SRobert Mustacchi         ;
764d14abf15SRobert Mustacchi #if 0
765d14abf15SRobert Mustacchi         ddi_remove_minor_node(pUM->pDev, pUM->devName);
766d14abf15SRobert Mustacchi         ddi_remove_minor_node(pUM->pDev, (char *)ddi_driver_name(pUM->pDev));
767d14abf15SRobert Mustacchi #endif
768d14abf15SRobert Mustacchi     }
769d14abf15SRobert Mustacchi     else
770d14abf15SRobert Mustacchi     {
771d14abf15SRobert Mustacchi         if (!BnxeGldFini(pUM))
772d14abf15SRobert Mustacchi         {
773d14abf15SRobert Mustacchi             return B_FALSE;
774d14abf15SRobert Mustacchi         }
775d14abf15SRobert Mustacchi     }
776d14abf15SRobert Mustacchi 
777d14abf15SRobert Mustacchi     BnxeKstatFini(pUM);
778d14abf15SRobert Mustacchi     BnxeIntrFini(pUM);
779d14abf15SRobert Mustacchi     BnxeBarMemDestroy(pUM);
780d14abf15SRobert Mustacchi     BnxeWorkQueueWaitAndDestroy(pUM);
781d14abf15SRobert Mustacchi     BnxeMutexDestroy(pUM);
782d14abf15SRobert Mustacchi     BnxePciDestroy(pUM);
783d14abf15SRobert Mustacchi     BnxeFmFini(pUM);
784d14abf15SRobert Mustacchi 
785d14abf15SRobert Mustacchi     return B_TRUE;
786d14abf15SRobert Mustacchi }
787d14abf15SRobert Mustacchi 
788d14abf15SRobert Mustacchi 
BnxeAttach(dev_info_t * pDev,ddi_attach_cmd_t cmd)789d14abf15SRobert Mustacchi static int BnxeAttach(dev_info_t * pDev, ddi_attach_cmd_t cmd)
790d14abf15SRobert Mustacchi {
791d14abf15SRobert Mustacchi     um_device_t * pUM;
792d14abf15SRobert Mustacchi 
793d14abf15SRobert Mustacchi     switch (cmd)
794d14abf15SRobert Mustacchi     {
795d14abf15SRobert Mustacchi     case DDI_ATTACH:
796d14abf15SRobert Mustacchi 
797d14abf15SRobert Mustacchi         if ((pUM = kmem_zalloc(sizeof(um_device_t), KM_SLEEP)) == NULL)
798d14abf15SRobert Mustacchi         {
799d14abf15SRobert Mustacchi             BnxeLogWarn(NULL, "failed to allocate device structure");
800d14abf15SRobert Mustacchi             return DDI_FAILURE;
801d14abf15SRobert Mustacchi         }
802d14abf15SRobert Mustacchi 
803d14abf15SRobert Mustacchi         ddi_set_driver_private(pDev, pUM);
804d14abf15SRobert Mustacchi 
805d14abf15SRobert Mustacchi         /* set magic number for identification */
806d14abf15SRobert Mustacchi         pUM->magic = BNXE_MAGIC;
807d14abf15SRobert Mustacchi 
808d14abf15SRobert Mustacchi         /* default for debug logging is dump everything */
809d14abf15SRobert Mustacchi         pUM->devParams.debug_level = (CP_ALL | LV_MASK);
810d14abf15SRobert Mustacchi 
811d14abf15SRobert Mustacchi         /* save dev_info_t in the driver structure */
812d14abf15SRobert Mustacchi         pUM->pDev = pDev;
813d14abf15SRobert Mustacchi 
814d14abf15SRobert Mustacchi         d_list_clear(&pUM->memBlockList);
815d14abf15SRobert Mustacchi         d_list_clear(&pUM->memDmaList);
816d14abf15SRobert Mustacchi         d_list_clear(&pUM->memRegionList);
817d14abf15SRobert Mustacchi #ifdef BNXE_DEBUG_DMA_LIST
818d14abf15SRobert Mustacchi         d_list_clear(&pUM->memDmaListSaved);
819d14abf15SRobert Mustacchi #endif
820d14abf15SRobert Mustacchi 
821d14abf15SRobert Mustacchi         /* obtain a human-readable device name log messages with */
822d14abf15SRobert Mustacchi         pUM->instance = ddi_get_instance(pDev);
823d14abf15SRobert Mustacchi         snprintf(pUM->devName, sizeof(pUM->devName),
824d14abf15SRobert Mustacchi                  "bnxe%d", pUM->instance);
825d14abf15SRobert Mustacchi 
826d14abf15SRobert Mustacchi         if (!BnxeAttachDevice(pUM))
827d14abf15SRobert Mustacchi         {
828d14abf15SRobert Mustacchi             kmem_free(pUM, sizeof(um_device_t));
829d14abf15SRobert Mustacchi             return DDI_FAILURE;
830d14abf15SRobert Mustacchi         }
831d14abf15SRobert Mustacchi 
832d14abf15SRobert Mustacchi         if (BNXE_FCOE(pUM) && pUM->devParams.fcoeEnable)
833d14abf15SRobert Mustacchi         {
834d14abf15SRobert Mustacchi             BnxeFcoeStartStop(pUM);
835d14abf15SRobert Mustacchi         }
836d14abf15SRobert Mustacchi 
837d14abf15SRobert Mustacchi         return DDI_SUCCESS;
838d14abf15SRobert Mustacchi 
839d14abf15SRobert Mustacchi     case DDI_RESUME:
840d14abf15SRobert Mustacchi #if !(defined(__S11) || defined(__S12))
841d14abf15SRobert Mustacchi     case DDI_PM_RESUME:
842d14abf15SRobert Mustacchi #endif
843d14abf15SRobert Mustacchi 
844d14abf15SRobert Mustacchi         pUM = (um_device_t *)ddi_get_driver_private(pDev);
845d14abf15SRobert Mustacchi 
846d14abf15SRobert Mustacchi         /* sanity check */
847d14abf15SRobert Mustacchi         if (pUM == NULL || pUM->pDev != pDev)
848d14abf15SRobert Mustacchi         {
849d14abf15SRobert Mustacchi             BnxeLogWarn(NULL, "%s: dev_info_t match failed", __func__);
850d14abf15SRobert Mustacchi             return DDI_FAILURE;
851d14abf15SRobert Mustacchi         }
852d14abf15SRobert Mustacchi 
853d14abf15SRobert Mustacchi         if (BnxeHwResume(pUM) != 0)
854d14abf15SRobert Mustacchi         {
855d14abf15SRobert Mustacchi             BnxeLogWarn(pUM, "Fail to resume this device!");
856d14abf15SRobert Mustacchi             return DDI_FAILURE;
857d14abf15SRobert Mustacchi         }
858d14abf15SRobert Mustacchi 
859d14abf15SRobert Mustacchi         return DDI_SUCCESS;
860d14abf15SRobert Mustacchi 
861d14abf15SRobert Mustacchi     default:
862d14abf15SRobert Mustacchi 
863d14abf15SRobert Mustacchi         return DDI_FAILURE;
864d14abf15SRobert Mustacchi     }
865d14abf15SRobert Mustacchi }
866d14abf15SRobert Mustacchi 
867d14abf15SRobert Mustacchi 
BnxeDetach(dev_info_t * pDev,ddi_detach_cmd_t cmd)868d14abf15SRobert Mustacchi static int BnxeDetach(dev_info_t * pDev, ddi_detach_cmd_t cmd)
869d14abf15SRobert Mustacchi {
870d14abf15SRobert Mustacchi     um_device_t * pUM;
871d14abf15SRobert Mustacchi 
872d14abf15SRobert Mustacchi     switch (cmd)
873d14abf15SRobert Mustacchi     {
874d14abf15SRobert Mustacchi     case DDI_DETACH:
875d14abf15SRobert Mustacchi 
876d14abf15SRobert Mustacchi         pUM = (um_device_t *)ddi_get_driver_private(pDev);
877d14abf15SRobert Mustacchi 
878d14abf15SRobert Mustacchi         /* sanity check */
879d14abf15SRobert Mustacchi         if (pUM == NULL || pUM->pDev != pDev)
880d14abf15SRobert Mustacchi         {
881d14abf15SRobert Mustacchi             BnxeLogWarn(NULL, "%s: dev_info_t match failed", __func__);
882d14abf15SRobert Mustacchi             return DDI_FAILURE;
883d14abf15SRobert Mustacchi         }
884d14abf15SRobert Mustacchi 
885d14abf15SRobert Mustacchi         if (pUM->intrEnabled != B_FALSE)
886d14abf15SRobert Mustacchi         {
887d14abf15SRobert Mustacchi             BnxeLogWarn(pUM, "Detaching a device that is currently running!");
888d14abf15SRobert Mustacchi             return DDI_FAILURE;
889d14abf15SRobert Mustacchi         }
890d14abf15SRobert Mustacchi 
891d14abf15SRobert Mustacchi         if (!BnxeDetachDevice(pUM))
892d14abf15SRobert Mustacchi         {
893d14abf15SRobert Mustacchi             BnxeLogWarn(pUM, "Can't detach it now, please try again later!");
894d14abf15SRobert Mustacchi             return DDI_FAILURE;
895d14abf15SRobert Mustacchi         }
896d14abf15SRobert Mustacchi 
897d14abf15SRobert Mustacchi         kmem_free(pUM, sizeof(um_device_t));
898d14abf15SRobert Mustacchi 
899d14abf15SRobert Mustacchi         return DDI_SUCCESS;
900d14abf15SRobert Mustacchi 
901d14abf15SRobert Mustacchi     case DDI_SUSPEND:
902d14abf15SRobert Mustacchi #if !(defined(__S11) || defined(__S12))
903d14abf15SRobert Mustacchi     case DDI_PM_SUSPEND:
904d14abf15SRobert Mustacchi #endif
905d14abf15SRobert Mustacchi 
906d14abf15SRobert Mustacchi         pUM = (um_device_t *)ddi_get_driver_private(pDev);
907d14abf15SRobert Mustacchi 
908d14abf15SRobert Mustacchi         /* sanity check */
909d14abf15SRobert Mustacchi         if (pUM == NULL || pUM->pDev != pDev)
910d14abf15SRobert Mustacchi         {
911d14abf15SRobert Mustacchi             BnxeLogWarn(NULL, "%s: dev_info_t match failed", __func__);
912d14abf15SRobert Mustacchi             return DDI_FAILURE;
913d14abf15SRobert Mustacchi         }
914d14abf15SRobert Mustacchi 
915d14abf15SRobert Mustacchi         if (BnxeHwSuspend(pUM) != 0)
916d14abf15SRobert Mustacchi         {
917d14abf15SRobert Mustacchi             BnxeLogWarn(pUM, "Fail to suspend this device!");
918d14abf15SRobert Mustacchi             return DDI_FAILURE;
919d14abf15SRobert Mustacchi         }
920d14abf15SRobert Mustacchi 
921d14abf15SRobert Mustacchi         return DDI_SUCCESS;
922d14abf15SRobert Mustacchi 
923d14abf15SRobert Mustacchi     default:
924d14abf15SRobert Mustacchi 
925d14abf15SRobert Mustacchi         return DDI_FAILURE;
926d14abf15SRobert Mustacchi     }
927d14abf15SRobert Mustacchi }
928d14abf15SRobert Mustacchi 
929d14abf15SRobert Mustacchi 
930d14abf15SRobert Mustacchi #if (DEVO_REV > 3)
931d14abf15SRobert Mustacchi 
BnxeQuiesce(dev_info_t * pDev)932d14abf15SRobert Mustacchi static int BnxeQuiesce(dev_info_t * pDev)
933d14abf15SRobert Mustacchi {
934d14abf15SRobert Mustacchi     um_device_t * pUM;
935d14abf15SRobert Mustacchi 
936d14abf15SRobert Mustacchi     pUM = (um_device_t *)ddi_get_driver_private(pDev);
937d14abf15SRobert Mustacchi 
938d14abf15SRobert Mustacchi     /* sanity check */
939d14abf15SRobert Mustacchi     if (pUM == NULL || pUM->pDev != pDev)
940d14abf15SRobert Mustacchi     {
941d14abf15SRobert Mustacchi         BnxeLogWarn(NULL, "%s: dev_info_t match failed", __func__);
942d14abf15SRobert Mustacchi         return DDI_FAILURE;
943d14abf15SRobert Mustacchi     }
944d14abf15SRobert Mustacchi 
945d14abf15SRobert Mustacchi     if (!pUM->plumbed)
946d14abf15SRobert Mustacchi     {
947d14abf15SRobert Mustacchi         return DDI_SUCCESS;
948d14abf15SRobert Mustacchi     }
949d14abf15SRobert Mustacchi 
950d14abf15SRobert Mustacchi     if (BnxeHwQuiesce(pUM) != 0)
951d14abf15SRobert Mustacchi     {
952d14abf15SRobert Mustacchi         BnxeLogWarn(pUM, "Failed to quiesce the device!");
953d14abf15SRobert Mustacchi         return DDI_FAILURE;
954d14abf15SRobert Mustacchi     }
955d14abf15SRobert Mustacchi 
956d14abf15SRobert Mustacchi     return DDI_SUCCESS;
957d14abf15SRobert Mustacchi }
958d14abf15SRobert Mustacchi 
959d14abf15SRobert Mustacchi #endif
960d14abf15SRobert Mustacchi 
961d14abf15SRobert Mustacchi 
BnxeFcoeInitChild(dev_info_t * pDev,dev_info_t * cDip)962d14abf15SRobert Mustacchi void BnxeFcoeInitChild(dev_info_t * pDev,
963d14abf15SRobert Mustacchi                        dev_info_t * cDip)
964d14abf15SRobert Mustacchi {
965d14abf15SRobert Mustacchi     um_device_t *pUM = (um_device_t *) ddi_get_driver_private(pDev);
966d14abf15SRobert Mustacchi 
967d14abf15SRobert Mustacchi     if ((pUM == NULL) || (pUM->pDev != pDev))
968d14abf15SRobert Mustacchi     {
969d14abf15SRobert Mustacchi         BnxeLogWarn(NULL, "%s: dev_info_t match failed ", __func__);
970d14abf15SRobert Mustacchi         return;
971d14abf15SRobert Mustacchi     }
972d14abf15SRobert Mustacchi 
973d14abf15SRobert Mustacchi     ddi_set_name_addr(cDip, ddi_get_name_addr(pUM->pDev));
974d14abf15SRobert Mustacchi }
975d14abf15SRobert Mustacchi 
976d14abf15SRobert Mustacchi 
BnxeFcoeUninitChild(dev_info_t * pDev,dev_info_t * cDip)977d14abf15SRobert Mustacchi void BnxeFcoeUninitChild(dev_info_t * pDev,
978d14abf15SRobert Mustacchi                          dev_info_t * cDip)
979d14abf15SRobert Mustacchi {
980d14abf15SRobert Mustacchi 	ddi_set_name_addr(cDip, NULL);
981d14abf15SRobert Mustacchi }
982d14abf15SRobert Mustacchi 
983d14abf15SRobert Mustacchi 
BnxeBusCtl(dev_info_t * pDev,dev_info_t * pRDev,ddi_ctl_enum_t op,void * pArg,void * pResult)984d14abf15SRobert Mustacchi static int BnxeBusCtl(dev_info_t *   pDev,
985d14abf15SRobert Mustacchi                       dev_info_t *   pRDev,
986d14abf15SRobert Mustacchi                       ddi_ctl_enum_t op,
987d14abf15SRobert Mustacchi                       void *         pArg,
988d14abf15SRobert Mustacchi                       void *         pResult)
989d14abf15SRobert Mustacchi {
990d14abf15SRobert Mustacchi     um_device_t * pUM = (um_device_t *)ddi_get_driver_private(pDev);
991d14abf15SRobert Mustacchi 
992d14abf15SRobert Mustacchi     /* sanity check */
993d14abf15SRobert Mustacchi     if (pUM == NULL || pUM->pDev != pDev)
994d14abf15SRobert Mustacchi     {
995d14abf15SRobert Mustacchi         BnxeLogWarn(NULL, "%s: dev_info_t match failed", __func__);
996d14abf15SRobert Mustacchi         return DDI_FAILURE;
997d14abf15SRobert Mustacchi     }
998d14abf15SRobert Mustacchi 
999d14abf15SRobert Mustacchi     BnxeLogDbg(pUM, "BnxeBusCtl (%d)", op);
1000d14abf15SRobert Mustacchi 
1001d14abf15SRobert Mustacchi     switch (op)
1002d14abf15SRobert Mustacchi     {
1003d14abf15SRobert Mustacchi     case DDI_CTLOPS_REPORTDEV:
1004d14abf15SRobert Mustacchi     case DDI_CTLOPS_IOMIN:
1005d14abf15SRobert Mustacchi         break;
1006d14abf15SRobert Mustacchi     case DDI_CTLOPS_INITCHILD:
1007d14abf15SRobert Mustacchi         BnxeFcoeInitChild(pDev, (dev_info_t *) pArg);
1008d14abf15SRobert Mustacchi         break;
1009d14abf15SRobert Mustacchi     case DDI_CTLOPS_UNINITCHILD:
1010d14abf15SRobert Mustacchi         BnxeFcoeUninitChild(pDev, (dev_info_t *) pArg);
1011d14abf15SRobert Mustacchi         break;
1012d14abf15SRobert Mustacchi 
1013d14abf15SRobert Mustacchi     default:
1014d14abf15SRobert Mustacchi 
1015d14abf15SRobert Mustacchi         return (ddi_ctlops(pDev, pRDev, op, pArg, pResult));
1016d14abf15SRobert Mustacchi     }
1017d14abf15SRobert Mustacchi 
1018d14abf15SRobert Mustacchi     return DDI_SUCCESS;
1019d14abf15SRobert Mustacchi }
1020d14abf15SRobert Mustacchi 
1021d14abf15SRobert Mustacchi 
BnxeCbIoctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)1022d14abf15SRobert Mustacchi static int BnxeCbIoctl(dev_t    dev,
1023d14abf15SRobert Mustacchi                        int      cmd,
1024d14abf15SRobert Mustacchi                        intptr_t arg,
1025d14abf15SRobert Mustacchi                        int      mode,
1026d14abf15SRobert Mustacchi                        cred_t * credp,
1027d14abf15SRobert Mustacchi                        int *    rvalp)
1028d14abf15SRobert Mustacchi {
1029d14abf15SRobert Mustacchi     BnxeBinding * pBinding = (BnxeBinding *)arg;
1030d14abf15SRobert Mustacchi     um_device_t * pUM;
1031d14abf15SRobert Mustacchi 
1032d14abf15SRobert Mustacchi     (void)dev;
1033d14abf15SRobert Mustacchi     (void)mode;
1034d14abf15SRobert Mustacchi     (void)credp;
1035d14abf15SRobert Mustacchi     (void)rvalp;
1036d14abf15SRobert Mustacchi 
1037d14abf15SRobert Mustacchi     if ((pBinding == NULL) ||
1038d14abf15SRobert Mustacchi         (pBinding->pCliDev == NULL) ||
1039d14abf15SRobert Mustacchi         (pBinding->pPrvDev == NULL))
1040d14abf15SRobert Mustacchi     {
1041d14abf15SRobert Mustacchi         BnxeLogWarn(NULL, "Invalid binding arg to ioctl %d", cmd);
1042d14abf15SRobert Mustacchi         return DDI_FAILURE;
1043d14abf15SRobert Mustacchi     }
1044d14abf15SRobert Mustacchi 
1045d14abf15SRobert Mustacchi     pUM = (um_device_t *)ddi_get_driver_private(pBinding->pPrvDev);
1046d14abf15SRobert Mustacchi 
1047d14abf15SRobert Mustacchi     /* sanity checks */
1048d14abf15SRobert Mustacchi 
1049d14abf15SRobert Mustacchi     if (pBinding->version != BNXE_BINDING_VERSION)
1050d14abf15SRobert Mustacchi     {
1051d14abf15SRobert Mustacchi         BnxeLogWarn(NULL, "%s: Invalid binding version (0x%08x)",
1052d14abf15SRobert Mustacchi                     __func__, pBinding->version);
1053d14abf15SRobert Mustacchi         return DDI_FAILURE;
1054d14abf15SRobert Mustacchi     }
1055d14abf15SRobert Mustacchi 
1056d14abf15SRobert Mustacchi     if ((pUM == NULL) ||
1057d14abf15SRobert Mustacchi         (pUM->fcoe.pDev != pBinding->pCliDev) ||
1058d14abf15SRobert Mustacchi         (pUM->pDev != pBinding->pPrvDev))
1059d14abf15SRobert Mustacchi     {
1060d14abf15SRobert Mustacchi         BnxeLogWarn(NULL, "%s: dev_info_t match failed", __func__);
1061d14abf15SRobert Mustacchi         return DDI_FAILURE;
1062d14abf15SRobert Mustacchi     }
1063d14abf15SRobert Mustacchi 
1064d14abf15SRobert Mustacchi     switch (cmd)
1065d14abf15SRobert Mustacchi     {
1066d14abf15SRobert Mustacchi     case BNXE_BIND_FCOE:
1067d14abf15SRobert Mustacchi 
1068d14abf15SRobert Mustacchi         /* copy the binding struct and fill in the provider callback */
1069d14abf15SRobert Mustacchi 
1070d14abf15SRobert Mustacchi         BnxeLogInfo(pUM, "FCoE BIND start");
1071d14abf15SRobert Mustacchi 
1072d14abf15SRobert Mustacchi         if (!CLIENT_DEVI(pUM, LM_CLI_IDX_FCOE))
1073d14abf15SRobert Mustacchi         {
1074d14abf15SRobert Mustacchi             BnxeLogWarn(pUM, "FCoE BIND when DEVI is offline!");
1075d14abf15SRobert Mustacchi             return DDI_FAILURE;
1076d14abf15SRobert Mustacchi         }
1077d14abf15SRobert Mustacchi 
1078d14abf15SRobert Mustacchi         if (CLIENT_BOUND(pUM, LM_CLI_IDX_FCOE))
1079d14abf15SRobert Mustacchi         {
1080d14abf15SRobert Mustacchi             BnxeLogWarn(pUM, "FCoE BIND when alread bound!");
1081d14abf15SRobert Mustacchi             return DDI_FAILURE;
1082d14abf15SRobert Mustacchi         }
1083d14abf15SRobert Mustacchi 
1084d14abf15SRobert Mustacchi         pUM->fcoe.bind = *pBinding;
1085d14abf15SRobert Mustacchi 
1086d14abf15SRobert Mustacchi         pUM->fcoe.bind.prvCtl           = pBinding->prvCtl           = BnxeFcoePrvCtl;
1087d14abf15SRobert Mustacchi         pUM->fcoe.bind.prvTx            = pBinding->prvTx            = BnxeFcoePrvTx;
1088d14abf15SRobert Mustacchi         pUM->fcoe.bind.prvPoll          = pBinding->prvPoll          = BnxeFcoePrvPoll;
1089d14abf15SRobert Mustacchi         pUM->fcoe.bind.prvSendWqes      = pBinding->prvSendWqes      = BnxeFcoePrvSendWqes;
1090d14abf15SRobert Mustacchi         pUM->fcoe.bind.prvMapMailboxq   = pBinding->prvMapMailboxq   = BnxeFcoePrvMapMailboxq;
1091d14abf15SRobert Mustacchi         pUM->fcoe.bind.prvUnmapMailboxq = pBinding->prvUnmapMailboxq = BnxeFcoePrvUnmapMailboxq;
1092d14abf15SRobert Mustacchi 
1093d14abf15SRobert Mustacchi         pUM->devParams.numRxDesc[LM_CLI_IDX_FCOE] = pBinding->numRxDescs;
1094d14abf15SRobert Mustacchi         pUM->devParams.numTxDesc[LM_CLI_IDX_FCOE] = pBinding->numTxDescs;
1095d14abf15SRobert Mustacchi 
1096d14abf15SRobert Mustacchi         pUM->lm_dev.params.l2_rx_desc_cnt[LM_CLI_IDX_FCOE] = pBinding->numRxDescs;
1097d14abf15SRobert Mustacchi         BnxeInitBdCnts(pUM, LM_CLI_IDX_FCOE);
1098d14abf15SRobert Mustacchi 
1099d14abf15SRobert Mustacchi         if (BnxeHwStartFCOE(pUM))
1100d14abf15SRobert Mustacchi         {
1101d14abf15SRobert Mustacchi             return DDI_FAILURE;
1102d14abf15SRobert Mustacchi         }
1103d14abf15SRobert Mustacchi 
1104d14abf15SRobert Mustacchi         CLIENT_BIND_SET(pUM, LM_CLI_IDX_FCOE);
1105d14abf15SRobert Mustacchi         lm_mcp_indicate_client_bind(&pUM->lm_dev, LM_CLI_IDX_FCOE);
1106d14abf15SRobert Mustacchi 
1107d14abf15SRobert Mustacchi         BnxeLogInfo(pUM, "FCoE BIND done");
1108d14abf15SRobert Mustacchi         return DDI_SUCCESS;
1109d14abf15SRobert Mustacchi 
1110d14abf15SRobert Mustacchi     case BNXE_UNBIND_FCOE:
1111d14abf15SRobert Mustacchi 
1112d14abf15SRobert Mustacchi         /* clear the binding struct and stats */
1113d14abf15SRobert Mustacchi 
1114d14abf15SRobert Mustacchi         BnxeLogInfo(pUM, "FCoE UNBIND start");
1115d14abf15SRobert Mustacchi 
1116d14abf15SRobert Mustacchi         if (CLIENT_DEVI(pUM, LM_CLI_IDX_FCOE))
1117d14abf15SRobert Mustacchi         {
1118d14abf15SRobert Mustacchi             BnxeLogWarn(pUM, "FCoE UNBIND when DEVI is online!");
1119d14abf15SRobert Mustacchi             return DDI_FAILURE;
1120d14abf15SRobert Mustacchi         }
1121d14abf15SRobert Mustacchi 
1122d14abf15SRobert Mustacchi         if (!CLIENT_BOUND(pUM, LM_CLI_IDX_FCOE))
1123d14abf15SRobert Mustacchi         {
1124d14abf15SRobert Mustacchi             BnxeLogWarn(pUM, "FCoE UNBIND when not bound!");
1125d14abf15SRobert Mustacchi             return DDI_FAILURE;
1126d14abf15SRobert Mustacchi         }
1127d14abf15SRobert Mustacchi 
1128d14abf15SRobert Mustacchi         /* We must not detach until all packets held by fcoe are retrieved. */
1129d14abf15SRobert Mustacchi         if (!BnxeWaitForPacketsFromClient(pUM, LM_CLI_IDX_FCOE))
1130d14abf15SRobert Mustacchi         {
1131d14abf15SRobert Mustacchi             return DDI_FAILURE;
1132d14abf15SRobert Mustacchi         }
1133d14abf15SRobert Mustacchi 
1134d14abf15SRobert Mustacchi         lm_mcp_indicate_client_unbind(&pUM->lm_dev, LM_CLI_IDX_FCOE);
1135d14abf15SRobert Mustacchi         CLIENT_BIND_RESET(pUM, LM_CLI_IDX_FCOE);
1136d14abf15SRobert Mustacchi 
1137d14abf15SRobert Mustacchi         BnxeHwStopFCOE(pUM);
1138d14abf15SRobert Mustacchi 
1139d14abf15SRobert Mustacchi         memset(&pUM->fcoe.bind, 0, sizeof(pUM->fcoe.bind));
1140d14abf15SRobert Mustacchi         memset(&pUM->fcoe.stats, 0, sizeof(pUM->fcoe.stats));
1141d14abf15SRobert Mustacchi 
1142d14abf15SRobert Mustacchi         pBinding->prvCtl           = NULL;
1143d14abf15SRobert Mustacchi         pBinding->prvTx            = NULL;
1144d14abf15SRobert Mustacchi         pBinding->prvPoll          = NULL;
1145d14abf15SRobert Mustacchi         pBinding->prvSendWqes      = NULL;
1146d14abf15SRobert Mustacchi         pBinding->prvMapMailboxq   = NULL;
1147d14abf15SRobert Mustacchi         pBinding->prvUnmapMailboxq = NULL;
1148d14abf15SRobert Mustacchi 
1149d14abf15SRobert Mustacchi         pUM->fcoe.pDev = NULL; /* sketchy? */
1150d14abf15SRobert Mustacchi 
1151d14abf15SRobert Mustacchi         BnxeLogInfo(pUM, "FCoE UNBIND done");
1152d14abf15SRobert Mustacchi         return DDI_SUCCESS;
1153d14abf15SRobert Mustacchi 
1154d14abf15SRobert Mustacchi     default:
1155d14abf15SRobert Mustacchi 
1156d14abf15SRobert Mustacchi         BnxeLogWarn(pUM, "Unknown ioctl %d", cmd);
1157d14abf15SRobert Mustacchi         return DDI_FAILURE;
1158d14abf15SRobert Mustacchi     }
1159d14abf15SRobert Mustacchi }
1160d14abf15SRobert Mustacchi 
1161d14abf15SRobert Mustacchi #ifndef ILLUMOS
1162d14abf15SRobert Mustacchi static struct bus_ops bnxe_bus_ops =
1163d14abf15SRobert Mustacchi {
1164d14abf15SRobert Mustacchi     BUSO_REV,
1165d14abf15SRobert Mustacchi     nullbusmap,        /* bus_map */
1166d14abf15SRobert Mustacchi     NULL,              /* bus_get_intrspec */
1167d14abf15SRobert Mustacchi     NULL,              /* bus_add_intrspec */
1168d14abf15SRobert Mustacchi     NULL,              /* bus_remove_intrspec */
1169d14abf15SRobert Mustacchi     i_ddi_map_fault,   /* bus_map_fault */
1170d14abf15SRobert Mustacchi     ddi_dma_map,       /* bus_dma_map */
1171d14abf15SRobert Mustacchi     ddi_dma_allochdl,  /* bus_dma_allochdl */
1172d14abf15SRobert Mustacchi     ddi_dma_freehdl,   /* bus_dma_freehdl */
1173d14abf15SRobert Mustacchi     ddi_dma_bindhdl,   /* bus_dma_bindhdl */
1174d14abf15SRobert Mustacchi     ddi_dma_unbindhdl, /* bus_unbindhdl */
1175d14abf15SRobert Mustacchi     ddi_dma_flush,     /* bus_dma_flush */
1176d14abf15SRobert Mustacchi     ddi_dma_win,       /* bus_dma_win */
1177d14abf15SRobert Mustacchi     ddi_dma_mctl,      /* bus_dma_ctl */
1178d14abf15SRobert Mustacchi     BnxeBusCtl,        /* bus_ctl */
1179d14abf15SRobert Mustacchi     ddi_bus_prop_op,   /* bus_prop_op */
1180d14abf15SRobert Mustacchi     NULL,              /* bus_get_eventcookie */
1181d14abf15SRobert Mustacchi     NULL,              /* bus_add_eventcall */
1182d14abf15SRobert Mustacchi     NULL,              /* bus_remove_event */
1183d14abf15SRobert Mustacchi     NULL,              /* bus_post_event */
1184d14abf15SRobert Mustacchi     NULL,              /* bus_intr_ctl */
1185d14abf15SRobert Mustacchi     NULL,              /* bus_config */
1186d14abf15SRobert Mustacchi     NULL,              /* bus_unconfig */
1187d14abf15SRobert Mustacchi     NULL,              /* bus_fm_init */
1188d14abf15SRobert Mustacchi     NULL,              /* bus_fm_fini */
1189d14abf15SRobert Mustacchi     NULL,              /* bus_fm_access_enter */
1190d14abf15SRobert Mustacchi     NULL,              /* bus_fm_access_exit */
1191d14abf15SRobert Mustacchi     NULL,              /* bus_power */
1192d14abf15SRobert Mustacchi     NULL
1193d14abf15SRobert Mustacchi };
1194d14abf15SRobert Mustacchi #endif	/* ILLUMOS */
1195d14abf15SRobert Mustacchi 
1196d14abf15SRobert Mustacchi 
1197d14abf15SRobert Mustacchi static struct cb_ops bnxe_cb_ops =
1198d14abf15SRobert Mustacchi {
1199d14abf15SRobert Mustacchi     nulldev,               /* cb_open */
1200d14abf15SRobert Mustacchi     nulldev,               /* cb_close */
1201d14abf15SRobert Mustacchi     nodev,                 /* cb_strategy */
1202d14abf15SRobert Mustacchi     nodev,                 /* cb_print */
1203d14abf15SRobert Mustacchi     nodev,                 /* cb_dump */
1204d14abf15SRobert Mustacchi     nodev,                 /* cb_read */
1205d14abf15SRobert Mustacchi     nodev,                 /* cb_write */
1206d14abf15SRobert Mustacchi     BnxeCbIoctl,           /* cb_ioctl */
1207d14abf15SRobert Mustacchi     nodev,                 /* cb_devmap */
1208d14abf15SRobert Mustacchi     nodev,                 /* cb_mmap */
1209d14abf15SRobert Mustacchi     nodev,                 /* cb_segmap */
1210d14abf15SRobert Mustacchi     nochpoll,              /* cb_chpoll */
1211d14abf15SRobert Mustacchi     ddi_prop_op,           /* cb_prop_op */
1212d14abf15SRobert Mustacchi     NULL,                  /* cb_stream */
1213d14abf15SRobert Mustacchi     (int)(D_MP | D_64BIT), /* cb_flag */
1214d14abf15SRobert Mustacchi     CB_REV,                /* cb_rev */
1215d14abf15SRobert Mustacchi     nodev,                 /* cb_aread */
1216d14abf15SRobert Mustacchi     nodev,                 /* cb_awrite */
1217d14abf15SRobert Mustacchi };
1218d14abf15SRobert Mustacchi 
1219d14abf15SRobert Mustacchi 
1220d14abf15SRobert Mustacchi #if (DEVO_REV > 3)
1221d14abf15SRobert Mustacchi 
1222d14abf15SRobert Mustacchi static struct dev_ops bnxe_dev_ops =
1223d14abf15SRobert Mustacchi {
1224d14abf15SRobert Mustacchi     DEVO_REV,      /* devo_rev */
1225d14abf15SRobert Mustacchi     0,             /* devo_refcnt */
1226d14abf15SRobert Mustacchi     NULL,          /* devo_getinfo */
1227d14abf15SRobert Mustacchi     nulldev,       /* devo_identify */
1228d14abf15SRobert Mustacchi     nulldev,       /* devo_probe */
1229d14abf15SRobert Mustacchi     BnxeAttach,    /* devo_attach */
1230d14abf15SRobert Mustacchi     BnxeDetach,    /* devo_detach */
1231d14abf15SRobert Mustacchi     nodev,         /* devo_reset */
1232d14abf15SRobert Mustacchi     &bnxe_cb_ops,  /* devo_cb_ops */
1233d14abf15SRobert Mustacchi #ifndef	ILLUMOS
1234d14abf15SRobert Mustacchi     &bnxe_bus_ops, /* devo_bus_ops */
1235d14abf15SRobert Mustacchi #else
1236d14abf15SRobert Mustacchi     NULL,          /* devo_bus_ops */
1237d14abf15SRobert Mustacchi #endif
1238d14abf15SRobert Mustacchi     NULL,          /* devo_power */
1239d14abf15SRobert Mustacchi     BnxeQuiesce    /* devo_quiesce */
1240d14abf15SRobert Mustacchi };
1241d14abf15SRobert Mustacchi 
1242d14abf15SRobert Mustacchi #else
1243d14abf15SRobert Mustacchi 
1244d14abf15SRobert Mustacchi static struct dev_ops bnxe_dev_ops =
1245d14abf15SRobert Mustacchi {
1246d14abf15SRobert Mustacchi     DEVO_REV,      /* devo_rev */
1247d14abf15SRobert Mustacchi     0,             /* devo_refcnt */
1248d14abf15SRobert Mustacchi     NULL,          /* devo_getinfo */
1249d14abf15SRobert Mustacchi     nulldev,       /* devo_identify */
1250d14abf15SRobert Mustacchi     nulldev,       /* devo_probe */
1251d14abf15SRobert Mustacchi     BnxeAttach,    /* devo_attach */
1252d14abf15SRobert Mustacchi     BnxeDetach,    /* devo_detach */
1253d14abf15SRobert Mustacchi     nodev,         /* devo_reset */
1254d14abf15SRobert Mustacchi     &bnxe_cb_ops,  /* devo_cb_ops */
1255d14abf15SRobert Mustacchi     &bnxe_bus_ops, /* devo_bus_ops */
1256d14abf15SRobert Mustacchi     NULL           /* devo_power */
1257d14abf15SRobert Mustacchi };
1258d14abf15SRobert Mustacchi 
1259d14abf15SRobert Mustacchi #endif
1260d14abf15SRobert Mustacchi 
1261d14abf15SRobert Mustacchi 
1262d14abf15SRobert Mustacchi static struct modldrv bnxe_modldrv =
1263d14abf15SRobert Mustacchi {
1264d14abf15SRobert Mustacchi     &mod_driverops,    /* drv_modops (must be mod_driverops for drivers) */
1265d14abf15SRobert Mustacchi     BNXE_PRODUCT_INFO, /* drv_linkinfo (string displayed by modinfo) */
1266d14abf15SRobert Mustacchi     &bnxe_dev_ops      /* drv_dev_ops */
1267d14abf15SRobert Mustacchi };
1268d14abf15SRobert Mustacchi 
1269d14abf15SRobert Mustacchi 
1270d14abf15SRobert Mustacchi static struct modlinkage bnxe_modlinkage =
1271d14abf15SRobert Mustacchi {
1272d14abf15SRobert Mustacchi     MODREV_1,        /* ml_rev */
1273d14abf15SRobert Mustacchi     {
1274d14abf15SRobert Mustacchi       &bnxe_modldrv, /* ml_linkage */
1275d14abf15SRobert Mustacchi       NULL           /* NULL termination */
1276d14abf15SRobert Mustacchi     }
1277d14abf15SRobert Mustacchi };
1278d14abf15SRobert Mustacchi 
1279d14abf15SRobert Mustacchi 
_init(void)1280d14abf15SRobert Mustacchi int _init(void)
1281d14abf15SRobert Mustacchi {
1282d14abf15SRobert Mustacchi     int rc;
1283d14abf15SRobert Mustacchi 
1284d14abf15SRobert Mustacchi     mac_init_ops(&bnxe_dev_ops, "bnxe");
1285d14abf15SRobert Mustacchi 
1286d14abf15SRobert Mustacchi     /* Install module information with O/S */
1287d14abf15SRobert Mustacchi     if ((rc = mod_install(&bnxe_modlinkage)) != DDI_SUCCESS)
1288d14abf15SRobert Mustacchi     {
1289d14abf15SRobert Mustacchi         BnxeLogWarn(NULL, "mod_install returned 0x%x", rc);
1290d14abf15SRobert Mustacchi         mac_fini_ops(&bnxe_dev_ops);
1291d14abf15SRobert Mustacchi         return rc;
1292d14abf15SRobert Mustacchi     }
1293d14abf15SRobert Mustacchi 
1294d14abf15SRobert Mustacchi     mutex_init(&bnxeLoaderMutex, NULL, MUTEX_DRIVER, NULL);
1295d14abf15SRobert Mustacchi     bnxeNumPlumbed = 0;
1296d14abf15SRobert Mustacchi 
1297d14abf15SRobert Mustacchi     BnxeLogInfo(NULL, "%s", BNXE_PRODUCT_BANNER);
1298d14abf15SRobert Mustacchi 
1299d14abf15SRobert Mustacchi     return rc;
1300d14abf15SRobert Mustacchi }
1301d14abf15SRobert Mustacchi 
1302d14abf15SRobert Mustacchi 
_fini(void)1303d14abf15SRobert Mustacchi int _fini(void)
1304d14abf15SRobert Mustacchi {
1305d14abf15SRobert Mustacchi     int rc;
1306d14abf15SRobert Mustacchi 
1307d14abf15SRobert Mustacchi     if ((rc = mod_remove(&bnxe_modlinkage)) == DDI_SUCCESS)
1308d14abf15SRobert Mustacchi     {
1309d14abf15SRobert Mustacchi         mac_fini_ops(&bnxe_dev_ops);
1310d14abf15SRobert Mustacchi         mutex_destroy(&bnxeLoaderMutex);
1311d14abf15SRobert Mustacchi 
1312d14abf15SRobert Mustacchi         if (bnxeNumPlumbed > 0)
1313d14abf15SRobert Mustacchi         {
1314d14abf15SRobert Mustacchi             /*
1315d14abf15SRobert Mustacchi              * This shouldn't be possible since modunload must only call _fini
1316d14abf15SRobert Mustacchi              * when no instances are currently plumbed.
1317d14abf15SRobert Mustacchi              */
1318d14abf15SRobert Mustacchi             BnxeLogWarn(NULL, "%d instances have not been unplumbed", bnxeNumPlumbed);
1319d14abf15SRobert Mustacchi         }
1320d14abf15SRobert Mustacchi     }
1321d14abf15SRobert Mustacchi 
1322d14abf15SRobert Mustacchi     return rc;
1323d14abf15SRobert Mustacchi }
1324d14abf15SRobert Mustacchi 
1325d14abf15SRobert Mustacchi 
_info(struct modinfo * pModinfo)1326d14abf15SRobert Mustacchi int _info(struct modinfo * pModinfo)
1327d14abf15SRobert Mustacchi {
1328d14abf15SRobert Mustacchi     return mod_info(&bnxe_modlinkage, pModinfo);
1329d14abf15SRobert Mustacchi }
1330d14abf15SRobert Mustacchi 
1331