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