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 /* 42*d14abf15SRobert Mustacchi * The interrupt status bit vector is as follows: 43*d14abf15SRobert Mustacchi * 44*d14abf15SRobert Mustacchi * bit 0: default interrupt 45*d14abf15SRobert Mustacchi * 46*d14abf15SRobert Mustacchi * Single Mode: 47*d14abf15SRobert Mustacchi * 48*d14abf15SRobert Mustacchi * bits 1-16: Function 1 (RSS 0-15) 49*d14abf15SRobert Mustacchi * 50*d14abf15SRobert Mustacchi * Multi-Function Mode: 51*d14abf15SRobert Mustacchi * 52*d14abf15SRobert Mustacchi * bits 1-4: Virtual Function 1 (RSS 0-3) 53*d14abf15SRobert Mustacchi * bits 5-8: Virtual Function 2 (RSS 4-7) 54*d14abf15SRobert Mustacchi * bits 9-12: Virtual Function 3 (RSS 8-11) 55*d14abf15SRobert Mustacchi * bits 13-16: Virtual Function 4 (RSS 12-15) 56*d14abf15SRobert Mustacchi * 57*d14abf15SRobert Mustacchi * While processing interrupts the programmatic index used for the default 58*d14abf15SRobert Mustacchi * status block is 16 and the RSS status blocks are shifted down one (i.e. 59*d14abf15SRobert Mustacchi * 0-15). 60*d14abf15SRobert Mustacchi * 61*d14abf15SRobert Mustacchi * Solaris defaults to 2 MSIX interrupts per function so only the default 62*d14abf15SRobert Mustacchi * interrupt plus one RSS interrupt is used. This default behavior can be 63*d14abf15SRobert Mustacchi * modified via the /etc/system configuration file. 64*d14abf15SRobert Mustacchi */ 65*d14abf15SRobert Mustacchi 66*d14abf15SRobert Mustacchi 67*d14abf15SRobert Mustacchi static inline char * BnxeIntrTypeName(int intrType) 68*d14abf15SRobert Mustacchi { 69*d14abf15SRobert Mustacchi return (intrType == DDI_INTR_TYPE_MSIX) ? "MSIX" : 70*d14abf15SRobert Mustacchi (intrType == DDI_INTR_TYPE_MSI) ? "MSI" : 71*d14abf15SRobert Mustacchi (intrType == DDI_INTR_TYPE_FIXED) ? "FIXED" : 72*d14abf15SRobert Mustacchi "UNKNOWN"; 73*d14abf15SRobert Mustacchi } 74*d14abf15SRobert Mustacchi 75*d14abf15SRobert Mustacchi 76*d14abf15SRobert Mustacchi static void BnxeFindDmaHandles(um_device_t * pUM) 77*d14abf15SRobert Mustacchi { 78*d14abf15SRobert Mustacchi lm_address_t physAddr; 79*d14abf15SRobert Mustacchi BnxeMemDma * pTmp; 80*d14abf15SRobert Mustacchi u32_t idx; 81*d14abf15SRobert Mustacchi 82*d14abf15SRobert Mustacchi BNXE_LOCK_ENTER_MEM(pUM); 83*d14abf15SRobert Mustacchi 84*d14abf15SRobert Mustacchi /* find the RSS status blocks */ 85*d14abf15SRobert Mustacchi 86*d14abf15SRobert Mustacchi LM_FOREACH_SB_ID(&pUM->lm_dev, idx) 87*d14abf15SRobert Mustacchi { 88*d14abf15SRobert Mustacchi if (CHIP_IS_E1x(&pUM->lm_dev)) 89*d14abf15SRobert Mustacchi { 90*d14abf15SRobert Mustacchi physAddr.as_u32.low = 91*d14abf15SRobert Mustacchi pUM->lm_dev.vars.status_blocks_arr[idx].hc_status_block_data.e1x_sb_data.common.host_sb_addr.lo; 92*d14abf15SRobert Mustacchi physAddr.as_u32.high = 93*d14abf15SRobert Mustacchi pUM->lm_dev.vars.status_blocks_arr[idx].hc_status_block_data.e1x_sb_data.common.host_sb_addr.hi; 94*d14abf15SRobert Mustacchi } 95*d14abf15SRobert Mustacchi else 96*d14abf15SRobert Mustacchi { 97*d14abf15SRobert Mustacchi physAddr.as_u32.low = 98*d14abf15SRobert Mustacchi pUM->lm_dev.vars.status_blocks_arr[idx].hc_status_block_data.e2_sb_data.common.host_sb_addr.lo; 99*d14abf15SRobert Mustacchi physAddr.as_u32.high = 100*d14abf15SRobert Mustacchi pUM->lm_dev.vars.status_blocks_arr[idx].hc_status_block_data.e2_sb_data.common.host_sb_addr.hi; 101*d14abf15SRobert Mustacchi } 102*d14abf15SRobert Mustacchi 103*d14abf15SRobert Mustacchi pTmp = (BnxeMemDma *)d_list_peek_head(&pUM->memDmaList); 104*d14abf15SRobert Mustacchi while (pTmp) 105*d14abf15SRobert Mustacchi { 106*d14abf15SRobert Mustacchi if (pTmp->physAddr.as_ptr == physAddr.as_ptr) 107*d14abf15SRobert Mustacchi { 108*d14abf15SRobert Mustacchi break; 109*d14abf15SRobert Mustacchi } 110*d14abf15SRobert Mustacchi 111*d14abf15SRobert Mustacchi pTmp = (BnxeMemDma *)d_list_next_entry(&pTmp->link); 112*d14abf15SRobert Mustacchi } 113*d14abf15SRobert Mustacchi 114*d14abf15SRobert Mustacchi if (pTmp == NULL) 115*d14abf15SRobert Mustacchi { 116*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to find DMA handle for RSS status block %d", idx); 117*d14abf15SRobert Mustacchi } 118*d14abf15SRobert Mustacchi 119*d14abf15SRobert Mustacchi pUM->statusBlocks[idx] = pTmp; 120*d14abf15SRobert Mustacchi } 121*d14abf15SRobert Mustacchi 122*d14abf15SRobert Mustacchi /* find the default status block */ 123*d14abf15SRobert Mustacchi 124*d14abf15SRobert Mustacchi pTmp = (BnxeMemDma *)d_list_peek_head(&pUM->memDmaList); 125*d14abf15SRobert Mustacchi while (pTmp) 126*d14abf15SRobert Mustacchi { 127*d14abf15SRobert Mustacchi if (pTmp->physAddr.as_ptr == 128*d14abf15SRobert Mustacchi pUM->lm_dev.vars.gen_sp_status_block.blk_phy_address.as_ptr) 129*d14abf15SRobert Mustacchi { 130*d14abf15SRobert Mustacchi break; 131*d14abf15SRobert Mustacchi } 132*d14abf15SRobert Mustacchi 133*d14abf15SRobert Mustacchi pTmp = (BnxeMemDma *)d_list_next_entry(&pTmp->link); 134*d14abf15SRobert Mustacchi } 135*d14abf15SRobert Mustacchi 136*d14abf15SRobert Mustacchi if (pTmp == NULL) 137*d14abf15SRobert Mustacchi { 138*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to find DMA handle for default status block"); 139*d14abf15SRobert Mustacchi } 140*d14abf15SRobert Mustacchi 141*d14abf15SRobert Mustacchi pUM->statusBlocks[DEF_STATUS_BLOCK_IGU_INDEX] = pTmp; 142*d14abf15SRobert Mustacchi 143*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_MEM(pUM); 144*d14abf15SRobert Mustacchi } 145*d14abf15SRobert Mustacchi 146*d14abf15SRobert Mustacchi 147*d14abf15SRobert Mustacchi void BnxeIntrIguSbEnable(um_device_t * pUM, 148*d14abf15SRobert Mustacchi u32_t idx, 149*d14abf15SRobert Mustacchi boolean_t fromISR) 150*d14abf15SRobert Mustacchi { 151*d14abf15SRobert Mustacchi RxQueue * pRxQ = &pUM->rxq[idx]; 152*d14abf15SRobert Mustacchi u32_t igu_id = (FCOE_CID(&pUM->lm_dev) == idx) ? 153*d14abf15SRobert Mustacchi LM_NON_RSS_SB(&pUM->lm_dev) : idx; 154*d14abf15SRobert Mustacchi 155*d14abf15SRobert Mustacchi BNXE_LOCK_ENTER_INTR_FLIP(pUM, igu_id); 156*d14abf15SRobert Mustacchi 157*d14abf15SRobert Mustacchi if (fromISR) 158*d14abf15SRobert Mustacchi { 159*d14abf15SRobert Mustacchi /* 160*d14abf15SRobert Mustacchi * If in an ISR and poll mode is ON then poll mode was flipped in the 161*d14abf15SRobert Mustacchi * ISR which can occur during Rx processing. If this is the case then 162*d14abf15SRobert Mustacchi * don't do anything. Only re-enable the IGU when poll mode is OFF. 163*d14abf15SRobert Mustacchi */ 164*d14abf15SRobert Mustacchi if (!pRxQ->inPollMode) 165*d14abf15SRobert Mustacchi { 166*d14abf15SRobert Mustacchi lm_int_ack_sb_enable(&pUM->lm_dev, igu_id); 167*d14abf15SRobert Mustacchi } 168*d14abf15SRobert Mustacchi } 169*d14abf15SRobert Mustacchi else 170*d14abf15SRobert Mustacchi { 171*d14abf15SRobert Mustacchi if (!pRxQ->inPollMode) 172*d14abf15SRobert Mustacchi { 173*d14abf15SRobert Mustacchi /* Why are intrs getting enabled on the ring twice...? */ 174*d14abf15SRobert Mustacchi cmn_err(CE_PANIC, 175*d14abf15SRobert Mustacchi "%s: Ring %d, enable intrs and NOT in poll mode!", 176*d14abf15SRobert Mustacchi BnxeDevName(pUM), igu_id); 177*d14abf15SRobert Mustacchi } 178*d14abf15SRobert Mustacchi 179*d14abf15SRobert Mustacchi atomic_swap_32(&pRxQ->inPollMode, B_FALSE); 180*d14abf15SRobert Mustacchi pRxQ->intrEnableCnt++; 181*d14abf15SRobert Mustacchi 182*d14abf15SRobert Mustacchi lm_int_ack_sb_enable(&pUM->lm_dev, igu_id); 183*d14abf15SRobert Mustacchi } 184*d14abf15SRobert Mustacchi 185*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_INTR_FLIP(pUM, igu_id); 186*d14abf15SRobert Mustacchi } 187*d14abf15SRobert Mustacchi 188*d14abf15SRobert Mustacchi 189*d14abf15SRobert Mustacchi void BnxeIntrIguSbDisable(um_device_t * pUM, 190*d14abf15SRobert Mustacchi u32_t idx, 191*d14abf15SRobert Mustacchi boolean_t fromISR) 192*d14abf15SRobert Mustacchi { 193*d14abf15SRobert Mustacchi RxQueue * pRxQ = &pUM->rxq[idx]; 194*d14abf15SRobert Mustacchi u32_t igu_id = (FCOE_CID(&pUM->lm_dev) == idx) ? 195*d14abf15SRobert Mustacchi LM_NON_RSS_SB(&pUM->lm_dev) : idx; 196*d14abf15SRobert Mustacchi 197*d14abf15SRobert Mustacchi BNXE_LOCK_ENTER_INTR_FLIP(pUM, igu_id); 198*d14abf15SRobert Mustacchi 199*d14abf15SRobert Mustacchi if (fromISR) 200*d14abf15SRobert Mustacchi { 201*d14abf15SRobert Mustacchi /* we should never get here when in poll mode... */ 202*d14abf15SRobert Mustacchi ASSERT(pRxQ->inPollMode == B_FALSE); 203*d14abf15SRobert Mustacchi lm_int_ack_sb_disable(&pUM->lm_dev, igu_id); 204*d14abf15SRobert Mustacchi } 205*d14abf15SRobert Mustacchi else 206*d14abf15SRobert Mustacchi { 207*d14abf15SRobert Mustacchi if (pRxQ->inPollMode) 208*d14abf15SRobert Mustacchi { 209*d14abf15SRobert Mustacchi /* Why are intrs getting disabled on the ring twice...? */ 210*d14abf15SRobert Mustacchi cmn_err(CE_PANIC, 211*d14abf15SRobert Mustacchi "%s: Ring %d, disable intrs and ALREADY in poll mode!", 212*d14abf15SRobert Mustacchi BnxeDevName(pUM), igu_id); 213*d14abf15SRobert Mustacchi } 214*d14abf15SRobert Mustacchi 215*d14abf15SRobert Mustacchi /* 216*d14abf15SRobert Mustacchi * Note here that the interrupt can already be disabled if GLDv3 217*d14abf15SRobert Mustacchi * is disabling the interrupt under the context of an ISR. This is 218*d14abf15SRobert Mustacchi * OK as the inPollMode flag will tell the ISR not to re-enable the 219*d14abf15SRobert Mustacchi * interrupt upon return. 220*d14abf15SRobert Mustacchi */ 221*d14abf15SRobert Mustacchi 222*d14abf15SRobert Mustacchi lm_int_ack_sb_disable(&pUM->lm_dev, igu_id); 223*d14abf15SRobert Mustacchi 224*d14abf15SRobert Mustacchi atomic_swap_32(&pRxQ->inPollMode, B_TRUE); 225*d14abf15SRobert Mustacchi pRxQ->intrDisableCnt++; 226*d14abf15SRobert Mustacchi } 227*d14abf15SRobert Mustacchi 228*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_INTR_FLIP(pUM, igu_id); 229*d14abf15SRobert Mustacchi } 230*d14abf15SRobert Mustacchi 231*d14abf15SRobert Mustacchi 232*d14abf15SRobert Mustacchi static void BnxeServiceDefSbIntr(um_device_t * pUM, 233*d14abf15SRobert Mustacchi boolean_t * pPktsRxed, 234*d14abf15SRobert Mustacchi boolean_t * pPktsTxed) 235*d14abf15SRobert Mustacchi { 236*d14abf15SRobert Mustacchi lm_device_t * pLM = (lm_device_t *)pUM; 237*d14abf15SRobert Mustacchi u32_t activity_flg = 0; 238*d14abf15SRobert Mustacchi u16_t lcl_attn_bits = 0; 239*d14abf15SRobert Mustacchi u16_t lcl_attn_ack = 0; 240*d14abf15SRobert Mustacchi u16_t asserted_proc_grps = 0; 241*d14abf15SRobert Mustacchi u16_t deasserted_proc_grps = 0; 242*d14abf15SRobert Mustacchi 243*d14abf15SRobert Mustacchi *pPktsRxed = B_FALSE; 244*d14abf15SRobert Mustacchi *pPktsTxed = B_FALSE; 245*d14abf15SRobert Mustacchi 246*d14abf15SRobert Mustacchi BnxeLogDbg(pUM, "Default INTR: Handling default status block %d", DEF_STATUS_BLOCK_INDEX); 247*d14abf15SRobert Mustacchi 248*d14abf15SRobert Mustacchi ddi_dma_sync(pUM->statusBlocks[DEF_STATUS_BLOCK_IGU_INDEX]->dmaHandle, 249*d14abf15SRobert Mustacchi 0, 0, DDI_DMA_SYNC_FORKERNEL); 250*d14abf15SRobert Mustacchi 251*d14abf15SRobert Mustacchi if (pUM->fmCapabilities && 252*d14abf15SRobert Mustacchi BnxeCheckDmaHandle(pUM->statusBlocks[DEF_STATUS_BLOCK_IGU_INDEX]->dmaHandle) != DDI_FM_OK) 253*d14abf15SRobert Mustacchi { 254*d14abf15SRobert Mustacchi ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); 255*d14abf15SRobert Mustacchi } 256*d14abf15SRobert Mustacchi 257*d14abf15SRobert Mustacchi pUM->intrSbCnt[DEF_STATUS_BLOCK_IGU_INDEX]++; 258*d14abf15SRobert Mustacchi 259*d14abf15SRobert Mustacchi if (lm_is_def_sb_updated(pLM) == 0) 260*d14abf15SRobert Mustacchi { 261*d14abf15SRobert Mustacchi BnxeLogDbg(pUM, "Default INTR: No change in default status index so bail!"); 262*d14abf15SRobert Mustacchi pUM->intrSbNoChangeCnt[DEF_STATUS_BLOCK_IGU_INDEX]++; 263*d14abf15SRobert Mustacchi 264*d14abf15SRobert Mustacchi if (pUM->fmCapabilities && 265*d14abf15SRobert Mustacchi BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK) 266*d14abf15SRobert Mustacchi { 267*d14abf15SRobert Mustacchi ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); 268*d14abf15SRobert Mustacchi } 269*d14abf15SRobert Mustacchi 270*d14abf15SRobert Mustacchi return; 271*d14abf15SRobert Mustacchi } 272*d14abf15SRobert Mustacchi 273*d14abf15SRobert Mustacchi /* get a local copy of the indices from the status block */ 274*d14abf15SRobert Mustacchi lm_update_def_hc_indices(pLM, DEF_STATUS_BLOCK_INDEX, &activity_flg); 275*d14abf15SRobert Mustacchi 276*d14abf15SRobert Mustacchi BnxeDbgBreakIfFastPath(pUM, !(activity_flg & LM_DEF_EVENT_MASK)); 277*d14abf15SRobert Mustacchi 278*d14abf15SRobert Mustacchi BnxeLogDbg(pUM, "Default INTR: processing events on sb: %x, events: 0x%x", 279*d14abf15SRobert Mustacchi DEF_STATUS_BLOCK_INDEX, activity_flg); 280*d14abf15SRobert Mustacchi 281*d14abf15SRobert Mustacchi if (activity_flg & LM_DEF_ATTN_ACTIVE) 282*d14abf15SRobert Mustacchi { 283*d14abf15SRobert Mustacchi /* Attentions! Usually these are bad things we don't want to see */ 284*d14abf15SRobert Mustacchi 285*d14abf15SRobert Mustacchi lm_get_attn_info(pLM, &lcl_attn_bits, &lcl_attn_ack); 286*d14abf15SRobert Mustacchi 287*d14abf15SRobert Mustacchi // NOTE: in case the status index of the attention has changed 288*d14abf15SRobert Mustacchi // already (while processing), we could override with it our local 289*d14abf15SRobert Mustacchi // copy. However, this is not a must, since it will be caught at the 290*d14abf15SRobert Mustacchi // end of the loop with the call to lm_is_sb_updated(). In case the 291*d14abf15SRobert Mustacchi // dpc_loop_cnt has exhausted, no worry, since will get an interrupt 292*d14abf15SRobert Mustacchi // for that at a later time. 293*d14abf15SRobert Mustacchi 294*d14abf15SRobert Mustacchi // find out which lines are asserted/deasserted with account to 295*d14abf15SRobert Mustacchi // their states, ASSERT if necessary. 296*d14abf15SRobert Mustacchi GET_ATTN_CHNG_GROUPS(pLM, lcl_attn_bits, lcl_attn_ack, 297*d14abf15SRobert Mustacchi &asserted_proc_grps, &deasserted_proc_grps); 298*d14abf15SRobert Mustacchi 299*d14abf15SRobert Mustacchi BnxeLogDbg(pUM, "Default INTR: asserted_proc_grps: 0x%x, deasserted_proc_grps:0x%x", 300*d14abf15SRobert Mustacchi asserted_proc_grps, deasserted_proc_grps); 301*d14abf15SRobert Mustacchi 302*d14abf15SRobert Mustacchi if (asserted_proc_grps) 303*d14abf15SRobert Mustacchi { 304*d14abf15SRobert Mustacchi lm_handle_assertion_processing(pLM, asserted_proc_grps); 305*d14abf15SRobert Mustacchi 306*d14abf15SRobert Mustacchi if (pUM->fmCapabilities && 307*d14abf15SRobert Mustacchi BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK) 308*d14abf15SRobert Mustacchi { 309*d14abf15SRobert Mustacchi ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); 310*d14abf15SRobert Mustacchi } 311*d14abf15SRobert Mustacchi } 312*d14abf15SRobert Mustacchi 313*d14abf15SRobert Mustacchi // keep in mind that in the same round, it is possible that this 314*d14abf15SRobert Mustacchi // func will have processing to do regarding deassertion on bits 315*d14abf15SRobert Mustacchi // that are different than the ones processed earlier for assertion 316*d14abf15SRobert Mustacchi // processing. 317*d14abf15SRobert Mustacchi 318*d14abf15SRobert Mustacchi if (deasserted_proc_grps) 319*d14abf15SRobert Mustacchi { 320*d14abf15SRobert Mustacchi lm_handle_deassertion_processing(pLM, deasserted_proc_grps); 321*d14abf15SRobert Mustacchi 322*d14abf15SRobert Mustacchi if (pUM->fmCapabilities && 323*d14abf15SRobert Mustacchi BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK) 324*d14abf15SRobert Mustacchi { 325*d14abf15SRobert Mustacchi ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); 326*d14abf15SRobert Mustacchi } 327*d14abf15SRobert Mustacchi } 328*d14abf15SRobert Mustacchi } 329*d14abf15SRobert Mustacchi 330*d14abf15SRobert Mustacchi if (activity_flg & LM_DEF_USTORM_ACTIVE) 331*d14abf15SRobert Mustacchi { 332*d14abf15SRobert Mustacchi /* Check for L4 TOE/iSCSI/FCoE Rx completions. */ 333*d14abf15SRobert Mustacchi 334*d14abf15SRobert Mustacchi if (lm_is_rx_completion(pLM, ISCSI_CID(pLM))) 335*d14abf15SRobert Mustacchi { 336*d14abf15SRobert Mustacchi BnxeDbgBreakMsg(pUM, "Unknown iSCSI Rx completion!"); 337*d14abf15SRobert Mustacchi } 338*d14abf15SRobert Mustacchi 339*d14abf15SRobert Mustacchi if (lm_is_rx_completion(pLM, FCOE_CID(pLM))) 340*d14abf15SRobert Mustacchi { 341*d14abf15SRobert Mustacchi *pPktsRxed = B_TRUE; 342*d14abf15SRobert Mustacchi } 343*d14abf15SRobert Mustacchi } 344*d14abf15SRobert Mustacchi 345*d14abf15SRobert Mustacchi if (activity_flg & LM_DEF_CSTORM_ACTIVE) 346*d14abf15SRobert Mustacchi { 347*d14abf15SRobert Mustacchi if (lm_is_eq_completion(pLM)) 348*d14abf15SRobert Mustacchi { 349*d14abf15SRobert Mustacchi lm_service_eq_intr(pLM); 350*d14abf15SRobert Mustacchi } 351*d14abf15SRobert Mustacchi 352*d14abf15SRobert Mustacchi if (lm_is_tx_completion(pLM, FWD_CID(pLM))) 353*d14abf15SRobert Mustacchi { 354*d14abf15SRobert Mustacchi /* XXX Possible? */ 355*d14abf15SRobert Mustacchi *pPktsTxed = B_TRUE; 356*d14abf15SRobert Mustacchi } 357*d14abf15SRobert Mustacchi 358*d14abf15SRobert Mustacchi if (lm_is_tx_completion(pLM, ISCSI_CID(pLM))) 359*d14abf15SRobert Mustacchi { 360*d14abf15SRobert Mustacchi /* XXX iSCSI Tx. NO! */ 361*d14abf15SRobert Mustacchi BnxeDbgBreakMsg(pUM, "Unknown iSCSI Tx completion!"); 362*d14abf15SRobert Mustacchi } 363*d14abf15SRobert Mustacchi 364*d14abf15SRobert Mustacchi if (lm_is_tx_completion(pLM, FCOE_CID(pLM))) 365*d14abf15SRobert Mustacchi { 366*d14abf15SRobert Mustacchi *pPktsTxed = B_TRUE; 367*d14abf15SRobert Mustacchi } 368*d14abf15SRobert Mustacchi } 369*d14abf15SRobert Mustacchi } 370*d14abf15SRobert Mustacchi 371*d14abf15SRobert Mustacchi 372*d14abf15SRobert Mustacchi /* 373*d14abf15SRobert Mustacchi * This is the polling path for an individual Rx Ring. Here we simply pull 374*d14abf15SRobert Mustacchi * any pending packets out of the hardware and put them into the wait queue. 375*d14abf15SRobert Mustacchi * Note that there might already be packets in the wait queue which is OK as 376*d14abf15SRobert Mustacchi * the caller will call BnxeRxRingProcess() next to process the queue. 377*d14abf15SRobert Mustacchi */ 378*d14abf15SRobert Mustacchi void BnxePollRxRing(um_device_t * pUM, 379*d14abf15SRobert Mustacchi u32_t idx, 380*d14abf15SRobert Mustacchi boolean_t * pPktsRxed, 381*d14abf15SRobert Mustacchi boolean_t * pPktsTxed) 382*d14abf15SRobert Mustacchi { 383*d14abf15SRobert Mustacchi lm_device_t * pLM = (lm_device_t *)pUM; 384*d14abf15SRobert Mustacchi u32_t activity_flg = 0; 385*d14abf15SRobert Mustacchi u8_t drv_rss_id = (u8_t)idx; 386*d14abf15SRobert Mustacchi 387*d14abf15SRobert Mustacchi *pPktsRxed = B_FALSE; 388*d14abf15SRobert Mustacchi *pPktsTxed = B_FALSE; 389*d14abf15SRobert Mustacchi 390*d14abf15SRobert Mustacchi BnxeLogDbg(pUM, "Ring Poll: Handling status block sb_id:%d drv_rss_id:%d", 391*d14abf15SRobert Mustacchi idx, drv_rss_id); 392*d14abf15SRobert Mustacchi 393*d14abf15SRobert Mustacchi /* use drv_rss_id for mapping into status block array (from LM) */ 394*d14abf15SRobert Mustacchi ddi_dma_sync(pUM->statusBlocks[drv_rss_id]->dmaHandle, 395*d14abf15SRobert Mustacchi 0, 0, DDI_DMA_SYNC_FORKERNEL); 396*d14abf15SRobert Mustacchi 397*d14abf15SRobert Mustacchi if (pUM->fmCapabilities && 398*d14abf15SRobert Mustacchi BnxeCheckDmaHandle(pUM->statusBlocks[drv_rss_id]->dmaHandle) != DDI_FM_OK) 399*d14abf15SRobert Mustacchi { 400*d14abf15SRobert Mustacchi ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); 401*d14abf15SRobert Mustacchi } 402*d14abf15SRobert Mustacchi 403*d14abf15SRobert Mustacchi pUM->intrSbPollCnt[drv_rss_id]++; 404*d14abf15SRobert Mustacchi 405*d14abf15SRobert Mustacchi if (lm_is_sb_updated(pLM, drv_rss_id) == 0) 406*d14abf15SRobert Mustacchi { 407*d14abf15SRobert Mustacchi BnxeLogDbg(pUM, "Ring Poll: No change in status index so bail!"); 408*d14abf15SRobert Mustacchi pUM->intrSbPollNoChangeCnt[drv_rss_id]++; 409*d14abf15SRobert Mustacchi return; 410*d14abf15SRobert Mustacchi } 411*d14abf15SRobert Mustacchi 412*d14abf15SRobert Mustacchi /* get a local copy of the indices from the status block */ 413*d14abf15SRobert Mustacchi lm_update_fp_hc_indices(pLM, drv_rss_id, &activity_flg, &drv_rss_id); 414*d14abf15SRobert Mustacchi 415*d14abf15SRobert Mustacchi BnxeDbgBreakIf(pUM, !(activity_flg & LM_NON_DEF_EVENT_MASK)); 416*d14abf15SRobert Mustacchi 417*d14abf15SRobert Mustacchi BnxeLogDbg(pUM, "Ring Poll: processing events on sb: %x, events: 0x%x", 418*d14abf15SRobert Mustacchi drv_rss_id, activity_flg); 419*d14abf15SRobert Mustacchi 420*d14abf15SRobert Mustacchi if (activity_flg & LM_NON_DEF_USTORM_ACTIVE) 421*d14abf15SRobert Mustacchi { 422*d14abf15SRobert Mustacchi /* Rx Completions */ 423*d14abf15SRobert Mustacchi if (lm_is_rx_completion(pLM, drv_rss_id)) 424*d14abf15SRobert Mustacchi { 425*d14abf15SRobert Mustacchi *pPktsRxed = B_TRUE; 426*d14abf15SRobert Mustacchi } 427*d14abf15SRobert Mustacchi 428*d14abf15SRobert Mustacchi /* XXX Check for L4 TOE/FCoE Rx completions. NO! */ 429*d14abf15SRobert Mustacchi } 430*d14abf15SRobert Mustacchi 431*d14abf15SRobert Mustacchi if (activity_flg & LM_NON_DEF_CSTORM_ACTIVE) 432*d14abf15SRobert Mustacchi { 433*d14abf15SRobert Mustacchi /* Tx completions */ 434*d14abf15SRobert Mustacchi if (lm_is_tx_completion(pLM, drv_rss_id)) 435*d14abf15SRobert Mustacchi { 436*d14abf15SRobert Mustacchi *pPktsTxed = B_TRUE; 437*d14abf15SRobert Mustacchi } 438*d14abf15SRobert Mustacchi 439*d14abf15SRobert Mustacchi /* XXX Check for L4 Tx and L5 EQ completions. NO! */ 440*d14abf15SRobert Mustacchi } 441*d14abf15SRobert Mustacchi } 442*d14abf15SRobert Mustacchi 443*d14abf15SRobert Mustacchi 444*d14abf15SRobert Mustacchi /* 445*d14abf15SRobert Mustacchi * This is the polling path for the FCoE Ring. Here we don't pull any 446*d14abf15SRobert Mustacchi * pending packets out of the hardware. We only care about FCoE Fast Path 447*d14abf15SRobert Mustacchi * completions. FCoE slow path L2 packets are processed via the default 448*d14abf15SRobert Mustacchi * status block not the LM_NON_RSS_SB. In this path we're assuming that 449*d14abf15SRobert Mustacchi * the FCoE driver is performing a crashdump. 450*d14abf15SRobert Mustacchi */ 451*d14abf15SRobert Mustacchi void BnxePollRxRingFCOE(um_device_t * pUM) 452*d14abf15SRobert Mustacchi { 453*d14abf15SRobert Mustacchi lm_device_t * pLM = (lm_device_t *)pUM; 454*d14abf15SRobert Mustacchi u32_t activity_flg = 0; 455*d14abf15SRobert Mustacchi 456*d14abf15SRobert Mustacchi u8_t sb_id = LM_NON_RSS_SB(pLM); 457*d14abf15SRobert Mustacchi u8_t drv_rss_id = FCOE_CID(pLM); 458*d14abf15SRobert Mustacchi 459*d14abf15SRobert Mustacchi BnxeLogDbg(pUM, "Ring Poll FCoE: Handling status block sb_id:%d drv_rss_id:%d", 460*d14abf15SRobert Mustacchi sb_id, drv_rss_id); 461*d14abf15SRobert Mustacchi 462*d14abf15SRobert Mustacchi /* use sb_id for mapping into status block array (from LM) */ 463*d14abf15SRobert Mustacchi ddi_dma_sync(pUM->statusBlocks[sb_id]->dmaHandle, 464*d14abf15SRobert Mustacchi 0, 0, DDI_DMA_SYNC_FORKERNEL); 465*d14abf15SRobert Mustacchi 466*d14abf15SRobert Mustacchi if (pUM->fmCapabilities && 467*d14abf15SRobert Mustacchi BnxeCheckDmaHandle(pUM->statusBlocks[sb_id]->dmaHandle) != DDI_FM_OK) 468*d14abf15SRobert Mustacchi { 469*d14abf15SRobert Mustacchi ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); 470*d14abf15SRobert Mustacchi } 471*d14abf15SRobert Mustacchi 472*d14abf15SRobert Mustacchi pUM->intrSbPollCnt[sb_id]++; 473*d14abf15SRobert Mustacchi 474*d14abf15SRobert Mustacchi if (lm_is_sb_updated(pLM, sb_id) == 0) 475*d14abf15SRobert Mustacchi { 476*d14abf15SRobert Mustacchi BnxeLogDbg(pUM, "Ring Poll FCoE: No change in status index so bail!"); 477*d14abf15SRobert Mustacchi pUM->intrSbPollNoChangeCnt[sb_id]++; 478*d14abf15SRobert Mustacchi return; 479*d14abf15SRobert Mustacchi } 480*d14abf15SRobert Mustacchi 481*d14abf15SRobert Mustacchi /* get a local copy of the indices from the status block */ 482*d14abf15SRobert Mustacchi lm_update_fp_hc_indices(pLM, sb_id, &activity_flg, &drv_rss_id); 483*d14abf15SRobert Mustacchi 484*d14abf15SRobert Mustacchi BnxeDbgBreakIf(pUM, !(activity_flg & LM_NON_DEF_EVENT_MASK)); 485*d14abf15SRobert Mustacchi 486*d14abf15SRobert Mustacchi BnxeLogDbg(pUM, "Ring Poll FCoE: processing events on sb: %x, events: 0x%x", 487*d14abf15SRobert Mustacchi sb_id, activity_flg); 488*d14abf15SRobert Mustacchi 489*d14abf15SRobert Mustacchi if (activity_flg & LM_NON_DEF_USTORM_ACTIVE) 490*d14abf15SRobert Mustacchi { 491*d14abf15SRobert Mustacchi if (lm_fc_is_eq_completion(pLM, drv_rss_id)) 492*d14abf15SRobert Mustacchi { 493*d14abf15SRobert Mustacchi lm_fc_service_eq_intr(pLM, drv_rss_id); 494*d14abf15SRobert Mustacchi } 495*d14abf15SRobert Mustacchi } 496*d14abf15SRobert Mustacchi } 497*d14abf15SRobert Mustacchi 498*d14abf15SRobert Mustacchi 499*d14abf15SRobert Mustacchi static void BnxeServiceSbIntr(um_device_t * pUM, 500*d14abf15SRobert Mustacchi u8_t sb_id, 501*d14abf15SRobert Mustacchi boolean_t * pPktsRxed, 502*d14abf15SRobert Mustacchi boolean_t * pPktsTxed) 503*d14abf15SRobert Mustacchi { 504*d14abf15SRobert Mustacchi lm_device_t * pLM = (lm_device_t *)pUM; 505*d14abf15SRobert Mustacchi u32_t activity_flg = 0; 506*d14abf15SRobert Mustacchi u8_t drv_rss_id; 507*d14abf15SRobert Mustacchi 508*d14abf15SRobert Mustacchi *pPktsRxed = B_FALSE; 509*d14abf15SRobert Mustacchi *pPktsTxed = B_FALSE; 510*d14abf15SRobert Mustacchi 511*d14abf15SRobert Mustacchi drv_rss_id = lm_map_igu_sb_id_to_drv_rss(pLM, sb_id); 512*d14abf15SRobert Mustacchi 513*d14abf15SRobert Mustacchi BnxeLogDbg(pUM, "Ring INTR: Handling status block sb_id:%d drv_rss_id:%d", 514*d14abf15SRobert Mustacchi sb_id, drv_rss_id); 515*d14abf15SRobert Mustacchi 516*d14abf15SRobert Mustacchi /* use sb_id for mapping into status block array (from LM) */ 517*d14abf15SRobert Mustacchi ddi_dma_sync(pUM->statusBlocks[sb_id]->dmaHandle, 518*d14abf15SRobert Mustacchi 0, 0, DDI_DMA_SYNC_FORKERNEL); 519*d14abf15SRobert Mustacchi 520*d14abf15SRobert Mustacchi if (pUM->fmCapabilities && 521*d14abf15SRobert Mustacchi BnxeCheckDmaHandle(pUM->statusBlocks[sb_id]->dmaHandle) != DDI_FM_OK) 522*d14abf15SRobert Mustacchi { 523*d14abf15SRobert Mustacchi ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); 524*d14abf15SRobert Mustacchi } 525*d14abf15SRobert Mustacchi 526*d14abf15SRobert Mustacchi pUM->intrSbCnt[sb_id]++; 527*d14abf15SRobert Mustacchi 528*d14abf15SRobert Mustacchi if (lm_is_sb_updated(pLM, sb_id) == 0) 529*d14abf15SRobert Mustacchi { 530*d14abf15SRobert Mustacchi BnxeLogDbg(pUM, "Ring INTR: No change in status index so bail!"); 531*d14abf15SRobert Mustacchi pUM->intrSbNoChangeCnt[sb_id]++; 532*d14abf15SRobert Mustacchi return; 533*d14abf15SRobert Mustacchi } 534*d14abf15SRobert Mustacchi 535*d14abf15SRobert Mustacchi /* 536*d14abf15SRobert Mustacchi * get a local copy of the indices from the status block 537*d14abf15SRobert Mustacchi * XXX note that here drv_rss_id is assigned to the sb_id 538*d14abf15SRobert Mustacchi */ 539*d14abf15SRobert Mustacchi lm_update_fp_hc_indices(pLM, sb_id, &activity_flg, &drv_rss_id); 540*d14abf15SRobert Mustacchi 541*d14abf15SRobert Mustacchi BnxeDbgBreakIf(pUM, !(activity_flg & LM_NON_DEF_EVENT_MASK)); 542*d14abf15SRobert Mustacchi 543*d14abf15SRobert Mustacchi BnxeLogDbg(pUM, "Ring INTR: processing events on sb: %x, events: 0x%x", 544*d14abf15SRobert Mustacchi drv_rss_id, activity_flg); 545*d14abf15SRobert Mustacchi 546*d14abf15SRobert Mustacchi if (activity_flg & LM_NON_DEF_USTORM_ACTIVE) 547*d14abf15SRobert Mustacchi { 548*d14abf15SRobert Mustacchi /* Rx Completions */ 549*d14abf15SRobert Mustacchi if (lm_is_rx_completion(pLM, drv_rss_id)) 550*d14abf15SRobert Mustacchi { 551*d14abf15SRobert Mustacchi *pPktsRxed = B_TRUE; 552*d14abf15SRobert Mustacchi } 553*d14abf15SRobert Mustacchi 554*d14abf15SRobert Mustacchi if (lm_fc_is_eq_completion(pLM, drv_rss_id)) 555*d14abf15SRobert Mustacchi { 556*d14abf15SRobert Mustacchi lm_fc_service_eq_intr(pLM, drv_rss_id); 557*d14abf15SRobert Mustacchi } 558*d14abf15SRobert Mustacchi 559*d14abf15SRobert Mustacchi /* XXX Check for ISCSI-OOO and L4 TOE Rx completions. NO! */ 560*d14abf15SRobert Mustacchi } 561*d14abf15SRobert Mustacchi 562*d14abf15SRobert Mustacchi if (activity_flg & LM_NON_DEF_CSTORM_ACTIVE) 563*d14abf15SRobert Mustacchi { 564*d14abf15SRobert Mustacchi /* Tx completions */ 565*d14abf15SRobert Mustacchi if (lm_is_tx_completion(pLM, drv_rss_id)) 566*d14abf15SRobert Mustacchi { 567*d14abf15SRobert Mustacchi *pPktsTxed = B_TRUE; 568*d14abf15SRobert Mustacchi } 569*d14abf15SRobert Mustacchi 570*d14abf15SRobert Mustacchi /* XXX Check for L4 Tx and L5 EQ completions. NO! */ 571*d14abf15SRobert Mustacchi 572*d14abf15SRobert Mustacchi /* L4 Tx completions */ 573*d14abf15SRobert Mustacchi if (lm_toe_is_tx_completion(pLM, drv_rss_id)) 574*d14abf15SRobert Mustacchi { 575*d14abf15SRobert Mustacchi BnxeDbgBreakMsg(pUM, "Unknown TOE Tx completion!"); 576*d14abf15SRobert Mustacchi } 577*d14abf15SRobert Mustacchi 578*d14abf15SRobert Mustacchi /* L5 EQ completions */ 579*d14abf15SRobert Mustacchi if (lm_sc_is_eq_completion(pLM, drv_rss_id)) 580*d14abf15SRobert Mustacchi { 581*d14abf15SRobert Mustacchi BnxeDbgBreakMsg(pUM, "Unknown iSCSI EQ completion!"); 582*d14abf15SRobert Mustacchi //lm_sc_service_eq_intr(pLM, drv_rss_id); 583*d14abf15SRobert Mustacchi } 584*d14abf15SRobert Mustacchi } 585*d14abf15SRobert Mustacchi } 586*d14abf15SRobert Mustacchi 587*d14abf15SRobert Mustacchi 588*d14abf15SRobert Mustacchi uint_t BnxeIntrISR(caddr_t arg1, caddr_t arg2) 589*d14abf15SRobert Mustacchi { 590*d14abf15SRobert Mustacchi um_device_t * pUM = (um_device_t *)arg1; 591*d14abf15SRobert Mustacchi lm_device_t * pLM = &pUM->lm_dev; 592*d14abf15SRobert Mustacchi lm_interrupt_status_t intrStatus = 0; 593*d14abf15SRobert Mustacchi boolean_t pktsRxed = 0; 594*d14abf15SRobert Mustacchi boolean_t pktsTxed = 0; 595*d14abf15SRobert Mustacchi u32_t rss_id = 0; 596*d14abf15SRobert Mustacchi int idx = (int)(uintptr_t)arg2; 597*d14abf15SRobert Mustacchi 598*d14abf15SRobert Mustacchi BNXE_LOCK_ENTER_INTR(pUM, idx); 599*d14abf15SRobert Mustacchi 600*d14abf15SRobert Mustacchi if (!pUM->intrEnabled) 601*d14abf15SRobert Mustacchi { 602*d14abf15SRobert Mustacchi pLM->vars.dbg_intr_in_wrong_state++; 603*d14abf15SRobert Mustacchi 604*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_INTR(pUM, idx); 605*d14abf15SRobert Mustacchi return DDI_INTR_UNCLAIMED; 606*d14abf15SRobert Mustacchi } 607*d14abf15SRobert Mustacchi 608*d14abf15SRobert Mustacchi BnxeLogDbg(pUM, "-> BNXE INTA Interrupt <-"); 609*d14abf15SRobert Mustacchi 610*d14abf15SRobert Mustacchi if (pLM->vars.enable_intr) 611*d14abf15SRobert Mustacchi { 612*d14abf15SRobert Mustacchi intrStatus = lm_get_interrupt_status(pLM); 613*d14abf15SRobert Mustacchi 614*d14abf15SRobert Mustacchi if (pUM->fmCapabilities && 615*d14abf15SRobert Mustacchi BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK) 616*d14abf15SRobert Mustacchi { 617*d14abf15SRobert Mustacchi ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); 618*d14abf15SRobert Mustacchi } 619*d14abf15SRobert Mustacchi 620*d14abf15SRobert Mustacchi if (intrStatus == 0) 621*d14abf15SRobert Mustacchi { 622*d14abf15SRobert Mustacchi pLM->vars.dbg_intr_zero_status++; 623*d14abf15SRobert Mustacchi 624*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_INTR(pUM, idx); 625*d14abf15SRobert Mustacchi return DDI_INTR_UNCLAIMED; 626*d14abf15SRobert Mustacchi } 627*d14abf15SRobert Mustacchi } 628*d14abf15SRobert Mustacchi else 629*d14abf15SRobert Mustacchi { 630*d14abf15SRobert Mustacchi pLM->vars.dbg_intr_in_disabled++; 631*d14abf15SRobert Mustacchi BnxeLogDbg(pUM, "INTA INTR: we got an interrupt when disabled"); 632*d14abf15SRobert Mustacchi 633*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_INTR(pUM, idx); 634*d14abf15SRobert Mustacchi return DDI_INTR_CLAIMED; 635*d14abf15SRobert Mustacchi } 636*d14abf15SRobert Mustacchi 637*d14abf15SRobert Mustacchi atomic_add_64((volatile uint64_t *)&pUM->intrFired, 1); 638*d14abf15SRobert Mustacchi 639*d14abf15SRobert Mustacchi while (intrStatus) 640*d14abf15SRobert Mustacchi { 641*d14abf15SRobert Mustacchi if (intrStatus & 0x1) 642*d14abf15SRobert Mustacchi { 643*d14abf15SRobert Mustacchi if (rss_id == 0) 644*d14abf15SRobert Mustacchi { 645*d14abf15SRobert Mustacchi lm_int_ack_def_sb_disable(pLM); 646*d14abf15SRobert Mustacchi 647*d14abf15SRobert Mustacchi BnxeServiceDefSbIntr(pUM, &pktsRxed, &pktsTxed); 648*d14abf15SRobert Mustacchi 649*d14abf15SRobert Mustacchi /* 650*d14abf15SRobert Mustacchi * Default sb only handles FCoE only right now. If this changes 651*d14abf15SRobert Mustacchi * BnxeServiceDefSbIntr will have to change to return which CIDs 652*d14abf15SRobert Mustacchi * have packets pending. 653*d14abf15SRobert Mustacchi */ 654*d14abf15SRobert Mustacchi 655*d14abf15SRobert Mustacchi if (pktsTxed) BnxeTxRingProcess(pUM, FCOE_CID(pLM)); 656*d14abf15SRobert Mustacchi if (pktsRxed) BnxeRxRingProcess(pUM, FCOE_CID(pLM), B_FALSE, 0); 657*d14abf15SRobert Mustacchi 658*d14abf15SRobert Mustacchi lm_sq_post_pending(pLM); 659*d14abf15SRobert Mustacchi 660*d14abf15SRobert Mustacchi lm_int_ack_def_sb_enable(pLM); 661*d14abf15SRobert Mustacchi } 662*d14abf15SRobert Mustacchi else 663*d14abf15SRobert Mustacchi { 664*d14abf15SRobert Mustacchi /* 665*d14abf15SRobert Mustacchi * (rss_id - 1) is used because the non-default sbs are located 666*d14abf15SRobert Mustacchi * in lm_device at indices 0-15. 667*d14abf15SRobert Mustacchi */ 668*d14abf15SRobert Mustacchi 669*d14abf15SRobert Mustacchi lm_int_ack_sb_disable(pLM, (rss_id - 1)); 670*d14abf15SRobert Mustacchi 671*d14abf15SRobert Mustacchi BnxeServiceSbIntr(pUM, (rss_id - 1), &pktsRxed, &pktsTxed); 672*d14abf15SRobert Mustacchi 673*d14abf15SRobert Mustacchi if (pktsTxed) BnxeTxRingProcess(pUM, (rss_id - 1)); 674*d14abf15SRobert Mustacchi if (pktsRxed) BnxeRxRingProcess(pUM, (rss_id - 1), B_FALSE, 0); 675*d14abf15SRobert Mustacchi 676*d14abf15SRobert Mustacchi lm_sq_post_pending(pLM); 677*d14abf15SRobert Mustacchi 678*d14abf15SRobert Mustacchi lm_int_ack_sb_enable(pLM, (rss_id - 1)); 679*d14abf15SRobert Mustacchi } 680*d14abf15SRobert Mustacchi } 681*d14abf15SRobert Mustacchi 682*d14abf15SRobert Mustacchi intrStatus >>= 1; 683*d14abf15SRobert Mustacchi rss_id++; 684*d14abf15SRobert Mustacchi } 685*d14abf15SRobert Mustacchi 686*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_INTR(pUM, idx); 687*d14abf15SRobert Mustacchi 688*d14abf15SRobert Mustacchi return DDI_INTR_CLAIMED; 689*d14abf15SRobert Mustacchi } 690*d14abf15SRobert Mustacchi 691*d14abf15SRobert Mustacchi 692*d14abf15SRobert Mustacchi uint_t BnxeIntrMISR(caddr_t arg1, caddr_t arg2) 693*d14abf15SRobert Mustacchi { 694*d14abf15SRobert Mustacchi um_device_t * pUM = (um_device_t *)arg1; 695*d14abf15SRobert Mustacchi lm_device_t * pLM = &pUM->lm_dev; 696*d14abf15SRobert Mustacchi boolean_t pktsRxed = 0; 697*d14abf15SRobert Mustacchi boolean_t pktsTxed = 0; 698*d14abf15SRobert Mustacchi int sb_id = (int)(uintptr_t)arg2; 699*d14abf15SRobert Mustacchi u32_t idx; 700*d14abf15SRobert Mustacchi 701*d14abf15SRobert Mustacchi BNXE_LOCK_ENTER_INTR(pUM, sb_id); 702*d14abf15SRobert Mustacchi 703*d14abf15SRobert Mustacchi if (!pUM->intrEnabled) 704*d14abf15SRobert Mustacchi { 705*d14abf15SRobert Mustacchi pLM->vars.dbg_intr_in_wrong_state++; 706*d14abf15SRobert Mustacchi 707*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_INTR(pUM, sb_id); 708*d14abf15SRobert Mustacchi return DDI_INTR_UNCLAIMED; 709*d14abf15SRobert Mustacchi } 710*d14abf15SRobert Mustacchi 711*d14abf15SRobert Mustacchi BnxeLogDbg(pUM, "-> BNXE MSIX Interrupt SB %d <-", sb_id); 712*d14abf15SRobert Mustacchi 713*d14abf15SRobert Mustacchi if (!pLM->vars.enable_intr) 714*d14abf15SRobert Mustacchi { 715*d14abf15SRobert Mustacchi pLM->vars.dbg_intr_in_disabled++; 716*d14abf15SRobert Mustacchi BnxeLogDbg(pUM, "MISR INTR: we got an interrupt when disabled"); 717*d14abf15SRobert Mustacchi 718*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_INTR(pUM, sb_id); 719*d14abf15SRobert Mustacchi return DDI_INTR_CLAIMED; 720*d14abf15SRobert Mustacchi } 721*d14abf15SRobert Mustacchi 722*d14abf15SRobert Mustacchi atomic_add_64((volatile uint64_t *)&pUM->intrFired, 1); 723*d14abf15SRobert Mustacchi 724*d14abf15SRobert Mustacchi if (sb_id == DEF_STATUS_BLOCK_IGU_INDEX) 725*d14abf15SRobert Mustacchi { 726*d14abf15SRobert Mustacchi lm_int_ack_def_sb_disable(pLM); 727*d14abf15SRobert Mustacchi 728*d14abf15SRobert Mustacchi BnxeServiceDefSbIntr(pUM, &pktsRxed, &pktsTxed); 729*d14abf15SRobert Mustacchi 730*d14abf15SRobert Mustacchi /* 731*d14abf15SRobert Mustacchi * Default sb only handles FCoE only right now. If this changes 732*d14abf15SRobert Mustacchi * BnxeServiceDefSbIntr will have to change to return which CIDs 733*d14abf15SRobert Mustacchi * have packets pending. 734*d14abf15SRobert Mustacchi */ 735*d14abf15SRobert Mustacchi 736*d14abf15SRobert Mustacchi if (pktsTxed) BnxeTxRingProcess(pUM, FCOE_CID(pLM)); 737*d14abf15SRobert Mustacchi if (pktsRxed) BnxeRxRingProcess(pUM, FCOE_CID(pLM), FALSE, 0); 738*d14abf15SRobert Mustacchi 739*d14abf15SRobert Mustacchi lm_sq_post_pending(pLM); 740*d14abf15SRobert Mustacchi 741*d14abf15SRobert Mustacchi lm_int_ack_def_sb_enable(pLM); 742*d14abf15SRobert Mustacchi } 743*d14abf15SRobert Mustacchi else 744*d14abf15SRobert Mustacchi { 745*d14abf15SRobert Mustacchi /* 746*d14abf15SRobert Mustacchi * Note that polling is not allowed by GLDv3 on the LM_NON_RSS_SB when 747*d14abf15SRobert Mustacchi * overlapped with FCoE. This is enforced by the BnxeRxRingIntrEnable 748*d14abf15SRobert Mustacchi * and BnxeRxRingIntrDisable routines. The FCoE driver IS ALLOWED to 749*d14abf15SRobert Mustacchi * put the SB into poll mode. FCoE trumps GLDv3/L2 and it's assumed 750*d14abf15SRobert Mustacchi * the FCoE driver is performing a crashdump in this case. 751*d14abf15SRobert Mustacchi */ 752*d14abf15SRobert Mustacchi 753*d14abf15SRobert Mustacchi idx = ((sb_id == LM_NON_RSS_SB(pLM)) && 754*d14abf15SRobert Mustacchi CLIENT_BOUND(pUM, LM_CLI_IDX_FCOE) && 755*d14abf15SRobert Mustacchi (pUM->rssIntr.intrCount == LM_MAX_RSS_CHAINS(&pUM->lm_dev))) ? 756*d14abf15SRobert Mustacchi FCOE_CID(pLM) : sb_id; 757*d14abf15SRobert Mustacchi 758*d14abf15SRobert Mustacchi if (pUM->rxq[idx].inPollMode) 759*d14abf15SRobert Mustacchi { 760*d14abf15SRobert Mustacchi /* Shouldn't be here! */ 761*d14abf15SRobert Mustacchi cmn_err(CE_PANIC, 762*d14abf15SRobert Mustacchi "%s: Interupt on RSS/MSIX ring %d when in poll mode!", 763*d14abf15SRobert Mustacchi BnxeDevName(pUM), idx); 764*d14abf15SRobert Mustacchi } 765*d14abf15SRobert Mustacchi 766*d14abf15SRobert Mustacchi /* accounts for poll mode */ 767*d14abf15SRobert Mustacchi BnxeIntrIguSbDisable(pUM, idx, B_TRUE); 768*d14abf15SRobert Mustacchi 769*d14abf15SRobert Mustacchi BnxeServiceSbIntr(pUM, sb_id, &pktsRxed, &pktsTxed); 770*d14abf15SRobert Mustacchi 771*d14abf15SRobert Mustacchi if (pktsTxed) BnxeTxRingProcess(pUM, sb_id); 772*d14abf15SRobert Mustacchi if (pktsRxed) BnxeRxRingProcess(pUM, sb_id, B_FALSE, 0); 773*d14abf15SRobert Mustacchi 774*d14abf15SRobert Mustacchi lm_sq_post_pending(pLM); 775*d14abf15SRobert Mustacchi 776*d14abf15SRobert Mustacchi /* accounts for poll mode */ 777*d14abf15SRobert Mustacchi BnxeIntrIguSbEnable(pUM, idx, B_TRUE); 778*d14abf15SRobert Mustacchi } 779*d14abf15SRobert Mustacchi 780*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_INTR(pUM, sb_id); 781*d14abf15SRobert Mustacchi 782*d14abf15SRobert Mustacchi return DDI_INTR_CLAIMED; 783*d14abf15SRobert Mustacchi } 784*d14abf15SRobert Mustacchi 785*d14abf15SRobert Mustacchi 786*d14abf15SRobert Mustacchi static int BnxeGetInterruptCount(dev_info_t * pDev, int type, int intrTypes) 787*d14abf15SRobert Mustacchi { 788*d14abf15SRobert Mustacchi int nintrs = 0; 789*d14abf15SRobert Mustacchi 790*d14abf15SRobert Mustacchi if (intrTypes & type) 791*d14abf15SRobert Mustacchi { 792*d14abf15SRobert Mustacchi return (ddi_intr_get_nintrs(pDev, type, &nintrs) != DDI_SUCCESS) ? 793*d14abf15SRobert Mustacchi -1 : nintrs; 794*d14abf15SRobert Mustacchi } 795*d14abf15SRobert Mustacchi 796*d14abf15SRobert Mustacchi return -1; 797*d14abf15SRobert Mustacchi } 798*d14abf15SRobert Mustacchi 799*d14abf15SRobert Mustacchi 800*d14abf15SRobert Mustacchi static boolean_t BnxeIntrBlockAlloc(um_device_t * pUM, 801*d14abf15SRobert Mustacchi int intrInum, 802*d14abf15SRobert Mustacchi int intrCnt, 803*d14abf15SRobert Mustacchi BnxeIntrBlock * pBlock) 804*d14abf15SRobert Mustacchi 805*d14abf15SRobert Mustacchi { 806*d14abf15SRobert Mustacchi dev_info_t * pDev = pUM->pDev; 807*d14abf15SRobert Mustacchi int intrRequest; 808*d14abf15SRobert Mustacchi int intrActual; 809*d14abf15SRobert Mustacchi int rc, i; 810*d14abf15SRobert Mustacchi 811*d14abf15SRobert Mustacchi if ((pUM->intrType == DDI_INTR_TYPE_FIXED) && (intrCnt != 1)) 812*d14abf15SRobert Mustacchi { 813*d14abf15SRobert Mustacchi return B_FALSE; 814*d14abf15SRobert Mustacchi } 815*d14abf15SRobert Mustacchi 816*d14abf15SRobert Mustacchi intrRequest = intrCnt; 817*d14abf15SRobert Mustacchi intrActual = 0; 818*d14abf15SRobert Mustacchi 819*d14abf15SRobert Mustacchi /* 820*d14abf15SRobert Mustacchi * We need to allocate an interrupt block array of maximum size which is 821*d14abf15SRobert Mustacchi * MAX_RSS_CHAINS plus one for the default interrupt. Even though we 822*d14abf15SRobert Mustacchi * won't allocate all of those handlers the "inum" value passed to 823*d14abf15SRobert Mustacchi * ddi_intr_alloc() determines the starting index where the handlers 824*d14abf15SRobert Mustacchi * will be allocated. See the multi-function block offset documentation 825*d14abf15SRobert Mustacchi * at the top of this file. 826*d14abf15SRobert Mustacchi */ 827*d14abf15SRobert Mustacchi pBlock->intrHandleBlockSize = 828*d14abf15SRobert Mustacchi ((MAX_RSS_CHAINS + 1) * sizeof(ddi_intr_handle_t)); 829*d14abf15SRobert Mustacchi 830*d14abf15SRobert Mustacchi if ((pBlock->pIntrHandleBlockAlloc = 831*d14abf15SRobert Mustacchi (ddi_intr_handle_t *)kmem_zalloc(pBlock->intrHandleBlockSize, 832*d14abf15SRobert Mustacchi KM_SLEEP)) == NULL) 833*d14abf15SRobert Mustacchi { 834*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Memory alloc failed for isr handle block (inum=%d)!", 835*d14abf15SRobert Mustacchi intrInum); 836*d14abf15SRobert Mustacchi return B_FALSE; 837*d14abf15SRobert Mustacchi } 838*d14abf15SRobert Mustacchi 839*d14abf15SRobert Mustacchi if ((rc = ddi_intr_alloc(pDev, 840*d14abf15SRobert Mustacchi pBlock->pIntrHandleBlockAlloc, 841*d14abf15SRobert Mustacchi pUM->intrType, 842*d14abf15SRobert Mustacchi intrInum, 843*d14abf15SRobert Mustacchi intrRequest, 844*d14abf15SRobert Mustacchi &intrActual, 845*d14abf15SRobert Mustacchi DDI_INTR_ALLOC_NORMAL)) != DDI_SUCCESS) 846*d14abf15SRobert Mustacchi { 847*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to allocate isr handle block (%d) (inum=%d cnt=%d)!", 848*d14abf15SRobert Mustacchi rc, intrInum, intrRequest); 849*d14abf15SRobert Mustacchi kmem_free(pBlock->pIntrHandleBlockAlloc, pBlock->intrHandleBlockSize); 850*d14abf15SRobert Mustacchi return B_FALSE; 851*d14abf15SRobert Mustacchi } 852*d14abf15SRobert Mustacchi 853*d14abf15SRobert Mustacchi /* 854*d14abf15SRobert Mustacchi * Point 'pIntrHandleBlock' to the starting interrupt index in the 855*d14abf15SRobert Mustacchi * allocated interrupt block array. This is done so we can easily enable, 856*d14abf15SRobert Mustacchi * disable, free, etc the interrupts. For 10u8 and beyond the inum value 857*d14abf15SRobert Mustacchi * is also used as an index into the interrupt block so we point 858*d14abf15SRobert Mustacchi * pIntrHandleBlock to the inum'th index. For 10u7 and below all 859*d14abf15SRobert Mustacchi * interrupt allocations start at index 0 per block. 860*d14abf15SRobert Mustacchi */ 861*d14abf15SRobert Mustacchi #if 0 862*d14abf15SRobert Mustacchi 863*d14abf15SRobert Mustacchi #ifdef DDI_INTR_IRM 864*d14abf15SRobert Mustacchi pBlock->pIntrHandleBlock = 865*d14abf15SRobert Mustacchi &pBlock->pIntrHandleBlockAlloc[intrInum]; 866*d14abf15SRobert Mustacchi #else 867*d14abf15SRobert Mustacchi pBlock->pIntrHandleBlock = 868*d14abf15SRobert Mustacchi &pBlock->pIntrHandleBlockAlloc[0]; 869*d14abf15SRobert Mustacchi #endif 870*d14abf15SRobert Mustacchi 871*d14abf15SRobert Mustacchi #else 872*d14abf15SRobert Mustacchi 873*d14abf15SRobert Mustacchi if (pBlock->pIntrHandleBlockAlloc[0]) 874*d14abf15SRobert Mustacchi { 875*d14abf15SRobert Mustacchi pBlock->pIntrHandleBlock = 876*d14abf15SRobert Mustacchi &pBlock->pIntrHandleBlockAlloc[0]; 877*d14abf15SRobert Mustacchi } 878*d14abf15SRobert Mustacchi else 879*d14abf15SRobert Mustacchi { 880*d14abf15SRobert Mustacchi pBlock->pIntrHandleBlock = 881*d14abf15SRobert Mustacchi &pBlock->pIntrHandleBlockAlloc[intrInum]; 882*d14abf15SRobert Mustacchi } 883*d14abf15SRobert Mustacchi 884*d14abf15SRobert Mustacchi #endif 885*d14abf15SRobert Mustacchi 886*d14abf15SRobert Mustacchi if (intrRequest != intrActual) 887*d14abf15SRobert Mustacchi { 888*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to allocate desired isr count (%d/%d)!", 889*d14abf15SRobert Mustacchi intrActual, intrRequest); 890*d14abf15SRobert Mustacchi 891*d14abf15SRobert Mustacchi #if 0 892*d14abf15SRobert Mustacchi for (i = 0; i < intrActual; i++) 893*d14abf15SRobert Mustacchi { 894*d14abf15SRobert Mustacchi ddi_intr_free(pBlock->pIntrHandleBlock[i]); 895*d14abf15SRobert Mustacchi } 896*d14abf15SRobert Mustacchi 897*d14abf15SRobert Mustacchi kmem_free(pBlock->pIntrHandleBlockAlloc, pBlock->intrHandleBlockSize); 898*d14abf15SRobert Mustacchi return B_FALSE; 899*d14abf15SRobert Mustacchi #else 900*d14abf15SRobert Mustacchi if (intrActual == 0) 901*d14abf15SRobert Mustacchi { 902*d14abf15SRobert Mustacchi kmem_free(pBlock->pIntrHandleBlockAlloc, pBlock->intrHandleBlockSize); 903*d14abf15SRobert Mustacchi return B_FALSE; 904*d14abf15SRobert Mustacchi } 905*d14abf15SRobert Mustacchi #endif 906*d14abf15SRobert Mustacchi } 907*d14abf15SRobert Mustacchi 908*d14abf15SRobert Mustacchi pBlock->intrCount = intrActual; 909*d14abf15SRobert Mustacchi 910*d14abf15SRobert Mustacchi if ((rc = ddi_intr_get_cap(pBlock->pIntrHandleBlock[0], 911*d14abf15SRobert Mustacchi &pBlock->intrCapability)) != DDI_SUCCESS) 912*d14abf15SRobert Mustacchi { 913*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to get isr capability (%d)!", rc); 914*d14abf15SRobert Mustacchi goto BnxeIntrBlockAlloc_fail; 915*d14abf15SRobert Mustacchi } 916*d14abf15SRobert Mustacchi 917*d14abf15SRobert Mustacchi if ((rc = ddi_intr_get_pri(pBlock->pIntrHandleBlock[0], 918*d14abf15SRobert Mustacchi &pBlock->intrPriority)) != DDI_SUCCESS) 919*d14abf15SRobert Mustacchi { 920*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to get isr priority (%d)!", rc); 921*d14abf15SRobert Mustacchi goto BnxeIntrBlockAlloc_fail; 922*d14abf15SRobert Mustacchi } 923*d14abf15SRobert Mustacchi 924*d14abf15SRobert Mustacchi if (pBlock->intrPriority >= ddi_intr_get_hilevel_pri()) 925*d14abf15SRobert Mustacchi { 926*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Interrupt priority is too high!"); 927*d14abf15SRobert Mustacchi goto BnxeIntrBlockAlloc_fail; 928*d14abf15SRobert Mustacchi } 929*d14abf15SRobert Mustacchi 930*d14abf15SRobert Mustacchi return B_TRUE; 931*d14abf15SRobert Mustacchi 932*d14abf15SRobert Mustacchi BnxeIntrBlockAlloc_fail: 933*d14abf15SRobert Mustacchi 934*d14abf15SRobert Mustacchi for (i = 0; i < intrActual; i++) 935*d14abf15SRobert Mustacchi { 936*d14abf15SRobert Mustacchi ddi_intr_free(pBlock->pIntrHandleBlock[i]); 937*d14abf15SRobert Mustacchi } 938*d14abf15SRobert Mustacchi 939*d14abf15SRobert Mustacchi kmem_free(pBlock->pIntrHandleBlockAlloc, pBlock->intrHandleBlockSize); 940*d14abf15SRobert Mustacchi 941*d14abf15SRobert Mustacchi memset(pBlock, 0, sizeof(BnxeIntrBlock)); 942*d14abf15SRobert Mustacchi 943*d14abf15SRobert Mustacchi return B_FALSE; 944*d14abf15SRobert Mustacchi } 945*d14abf15SRobert Mustacchi 946*d14abf15SRobert Mustacchi 947*d14abf15SRobert Mustacchi static void BnxeIntrBlockFree(um_device_t * pUM, 948*d14abf15SRobert Mustacchi BnxeIntrBlock * pBlock) 949*d14abf15SRobert Mustacchi 950*d14abf15SRobert Mustacchi { 951*d14abf15SRobert Mustacchi int i; 952*d14abf15SRobert Mustacchi 953*d14abf15SRobert Mustacchi if (pBlock->intrCount == 0) 954*d14abf15SRobert Mustacchi { 955*d14abf15SRobert Mustacchi memset(pBlock, 0, sizeof(BnxeIntrBlock)); 956*d14abf15SRobert Mustacchi return; 957*d14abf15SRobert Mustacchi } 958*d14abf15SRobert Mustacchi 959*d14abf15SRobert Mustacchi for (i = 0; i < pBlock->intrCount; i++) 960*d14abf15SRobert Mustacchi { 961*d14abf15SRobert Mustacchi ddi_intr_free(pBlock->pIntrHandleBlock[i]); 962*d14abf15SRobert Mustacchi } 963*d14abf15SRobert Mustacchi 964*d14abf15SRobert Mustacchi kmem_free(pBlock->pIntrHandleBlockAlloc, pBlock->intrHandleBlockSize); 965*d14abf15SRobert Mustacchi 966*d14abf15SRobert Mustacchi memset(pBlock, 0, sizeof(BnxeIntrBlock)); 967*d14abf15SRobert Mustacchi } 968*d14abf15SRobert Mustacchi 969*d14abf15SRobert Mustacchi 970*d14abf15SRobert Mustacchi static boolean_t BnxeIntrAddHandlers(um_device_t * pUM) 971*d14abf15SRobert Mustacchi { 972*d14abf15SRobert Mustacchi int rc, i, j; 973*d14abf15SRobert Mustacchi 974*d14abf15SRobert Mustacchi switch (pUM->intrType) 975*d14abf15SRobert Mustacchi { 976*d14abf15SRobert Mustacchi case DDI_INTR_TYPE_MSIX: 977*d14abf15SRobert Mustacchi 978*d14abf15SRobert Mustacchi if ((rc = ddi_intr_add_handler( 979*d14abf15SRobert Mustacchi pUM->defIntr.pIntrHandleBlock[0], 980*d14abf15SRobert Mustacchi BnxeIntrMISR, 981*d14abf15SRobert Mustacchi (caddr_t)pUM, 982*d14abf15SRobert Mustacchi (caddr_t)(uintptr_t)DEF_STATUS_BLOCK_IGU_INDEX)) != 983*d14abf15SRobert Mustacchi DDI_SUCCESS) 984*d14abf15SRobert Mustacchi { 985*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to add the MSIX default isr handler (%d)", rc); 986*d14abf15SRobert Mustacchi return B_FALSE; 987*d14abf15SRobert Mustacchi } 988*d14abf15SRobert Mustacchi 989*d14abf15SRobert Mustacchi for (i = 0; i < pUM->rssIntr.intrCount; i++) 990*d14abf15SRobert Mustacchi { 991*d14abf15SRobert Mustacchi if ((rc = ddi_intr_add_handler( 992*d14abf15SRobert Mustacchi pUM->rssIntr.pIntrHandleBlock[i], 993*d14abf15SRobert Mustacchi BnxeIntrMISR, 994*d14abf15SRobert Mustacchi (caddr_t)pUM, 995*d14abf15SRobert Mustacchi (caddr_t)(uintptr_t)i)) != 996*d14abf15SRobert Mustacchi DDI_SUCCESS) 997*d14abf15SRobert Mustacchi { 998*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to add the MSIX RSS isr handler %d (%d)", 999*d14abf15SRobert Mustacchi (i + NDIS_CID(&pUM->lm_dev)), rc); 1000*d14abf15SRobert Mustacchi 1001*d14abf15SRobert Mustacchi ddi_intr_remove_handler(pUM->defIntr.pIntrHandleBlock[0]); 1002*d14abf15SRobert Mustacchi 1003*d14abf15SRobert Mustacchi for (j = 0; j < i; j++) /* unwind */ 1004*d14abf15SRobert Mustacchi { 1005*d14abf15SRobert Mustacchi ddi_intr_remove_handler(pUM->rssIntr.pIntrHandleBlock[j]); 1006*d14abf15SRobert Mustacchi } 1007*d14abf15SRobert Mustacchi 1008*d14abf15SRobert Mustacchi return B_FALSE; 1009*d14abf15SRobert Mustacchi } 1010*d14abf15SRobert Mustacchi } 1011*d14abf15SRobert Mustacchi 1012*d14abf15SRobert Mustacchi /* 1013*d14abf15SRobert Mustacchi * fcoeIntr.intrCount == 1 implies LM_NON_RSS_SB (last) status block 1014*d14abf15SRobert Mustacchi * was allocated for FCoE and there was no overlap with the RSS 1015*d14abf15SRobert Mustacchi * allocation. 1016*d14abf15SRobert Mustacchi */ 1017*d14abf15SRobert Mustacchi if (pUM->fcoeIntr.intrCount == 1) 1018*d14abf15SRobert Mustacchi { 1019*d14abf15SRobert Mustacchi if ((rc = ddi_intr_add_handler( 1020*d14abf15SRobert Mustacchi pUM->fcoeIntr.pIntrHandleBlock[0], 1021*d14abf15SRobert Mustacchi BnxeIntrMISR, 1022*d14abf15SRobert Mustacchi (caddr_t)pUM, 1023*d14abf15SRobert Mustacchi (caddr_t)(uintptr_t)LM_NON_RSS_SB(&pUM->lm_dev))) != 1024*d14abf15SRobert Mustacchi DDI_SUCCESS) 1025*d14abf15SRobert Mustacchi { 1026*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to add the MSIX FCoE isr handler (%d)", rc); 1027*d14abf15SRobert Mustacchi 1028*d14abf15SRobert Mustacchi ddi_intr_remove_handler(pUM->defIntr.pIntrHandleBlock[0]); 1029*d14abf15SRobert Mustacchi 1030*d14abf15SRobert Mustacchi for (i = 0; i < pUM->rssIntr.intrCount; i++) 1031*d14abf15SRobert Mustacchi { 1032*d14abf15SRobert Mustacchi ddi_intr_remove_handler(pUM->rssIntr.pIntrHandleBlock[i]); 1033*d14abf15SRobert Mustacchi } 1034*d14abf15SRobert Mustacchi 1035*d14abf15SRobert Mustacchi return B_FALSE; 1036*d14abf15SRobert Mustacchi } 1037*d14abf15SRobert Mustacchi } 1038*d14abf15SRobert Mustacchi 1039*d14abf15SRobert Mustacchi break; 1040*d14abf15SRobert Mustacchi 1041*d14abf15SRobert Mustacchi case DDI_INTR_TYPE_FIXED: 1042*d14abf15SRobert Mustacchi 1043*d14abf15SRobert Mustacchi if ((rc = ddi_intr_add_handler( 1044*d14abf15SRobert Mustacchi pUM->defIntr.pIntrHandleBlock[0], 1045*d14abf15SRobert Mustacchi BnxeIntrISR, 1046*d14abf15SRobert Mustacchi (caddr_t)pUM, 1047*d14abf15SRobert Mustacchi (caddr_t)(uintptr_t)DEF_STATUS_BLOCK_IGU_INDEX)) != 1048*d14abf15SRobert Mustacchi DDI_SUCCESS) 1049*d14abf15SRobert Mustacchi { 1050*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to add the fixed default isr handler (%d)", rc); 1051*d14abf15SRobert Mustacchi return B_FALSE; 1052*d14abf15SRobert Mustacchi } 1053*d14abf15SRobert Mustacchi 1054*d14abf15SRobert Mustacchi break; 1055*d14abf15SRobert Mustacchi 1056*d14abf15SRobert Mustacchi default: 1057*d14abf15SRobert Mustacchi 1058*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to add isr handler (unsupported type %d)!", 1059*d14abf15SRobert Mustacchi pUM->intrType); 1060*d14abf15SRobert Mustacchi return B_FALSE; 1061*d14abf15SRobert Mustacchi } 1062*d14abf15SRobert Mustacchi 1063*d14abf15SRobert Mustacchi return B_TRUE; 1064*d14abf15SRobert Mustacchi } 1065*d14abf15SRobert Mustacchi 1066*d14abf15SRobert Mustacchi 1067*d14abf15SRobert Mustacchi static void BnxeIntrBlockRemoveHandler(um_device_t * pUM, 1068*d14abf15SRobert Mustacchi BnxeIntrBlock * pBlock) 1069*d14abf15SRobert Mustacchi { 1070*d14abf15SRobert Mustacchi int i; 1071*d14abf15SRobert Mustacchi 1072*d14abf15SRobert Mustacchi (void)pUM; 1073*d14abf15SRobert Mustacchi 1074*d14abf15SRobert Mustacchi if (pBlock->intrCount == 0) 1075*d14abf15SRobert Mustacchi { 1076*d14abf15SRobert Mustacchi return; 1077*d14abf15SRobert Mustacchi } 1078*d14abf15SRobert Mustacchi 1079*d14abf15SRobert Mustacchi for (i = 0; i < pBlock->intrCount; i++) 1080*d14abf15SRobert Mustacchi { 1081*d14abf15SRobert Mustacchi ddi_intr_remove_handler(pBlock->pIntrHandleBlock[i]); 1082*d14abf15SRobert Mustacchi } 1083*d14abf15SRobert Mustacchi } 1084*d14abf15SRobert Mustacchi 1085*d14abf15SRobert Mustacchi 1086*d14abf15SRobert Mustacchi static boolean_t BnxeIntrBlockEnable(um_device_t * pUM, 1087*d14abf15SRobert Mustacchi BnxeIntrBlock * pBlock) 1088*d14abf15SRobert Mustacchi { 1089*d14abf15SRobert Mustacchi int rc, i, j; 1090*d14abf15SRobert Mustacchi 1091*d14abf15SRobert Mustacchi if (pBlock->intrCount == 0) 1092*d14abf15SRobert Mustacchi { 1093*d14abf15SRobert Mustacchi return B_TRUE; 1094*d14abf15SRobert Mustacchi } 1095*d14abf15SRobert Mustacchi 1096*d14abf15SRobert Mustacchi if (pBlock->intrCapability & DDI_INTR_FLAG_BLOCK) 1097*d14abf15SRobert Mustacchi { 1098*d14abf15SRobert Mustacchi if ((rc = ddi_intr_block_enable(pBlock->pIntrHandleBlock, 1099*d14abf15SRobert Mustacchi pBlock->intrCount)) != DDI_SUCCESS) 1100*d14abf15SRobert Mustacchi { 1101*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to enable isr block (%d)", rc); 1102*d14abf15SRobert Mustacchi return B_FALSE; 1103*d14abf15SRobert Mustacchi } 1104*d14abf15SRobert Mustacchi } 1105*d14abf15SRobert Mustacchi else 1106*d14abf15SRobert Mustacchi { 1107*d14abf15SRobert Mustacchi for (i = 0; i < pBlock->intrCount; i++) 1108*d14abf15SRobert Mustacchi { 1109*d14abf15SRobert Mustacchi if ((rc = ddi_intr_enable(pBlock->pIntrHandleBlock[i])) != 1110*d14abf15SRobert Mustacchi DDI_SUCCESS) 1111*d14abf15SRobert Mustacchi { 1112*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to enable isr %d (%d)", i, rc); 1113*d14abf15SRobert Mustacchi 1114*d14abf15SRobert Mustacchi for (j = 0; j < i; j++) /* unwind */ 1115*d14abf15SRobert Mustacchi { 1116*d14abf15SRobert Mustacchi ddi_intr_disable(pBlock->pIntrHandleBlock[j]); 1117*d14abf15SRobert Mustacchi } 1118*d14abf15SRobert Mustacchi 1119*d14abf15SRobert Mustacchi return B_FALSE; 1120*d14abf15SRobert Mustacchi } 1121*d14abf15SRobert Mustacchi } 1122*d14abf15SRobert Mustacchi } 1123*d14abf15SRobert Mustacchi 1124*d14abf15SRobert Mustacchi return B_TRUE; 1125*d14abf15SRobert Mustacchi } 1126*d14abf15SRobert Mustacchi 1127*d14abf15SRobert Mustacchi 1128*d14abf15SRobert Mustacchi static void BnxeIntrBlockDisable(um_device_t * pUM, 1129*d14abf15SRobert Mustacchi BnxeIntrBlock * pBlock) 1130*d14abf15SRobert Mustacchi { 1131*d14abf15SRobert Mustacchi int i; 1132*d14abf15SRobert Mustacchi 1133*d14abf15SRobert Mustacchi if (pBlock->intrCount == 0) 1134*d14abf15SRobert Mustacchi { 1135*d14abf15SRobert Mustacchi return; 1136*d14abf15SRobert Mustacchi } 1137*d14abf15SRobert Mustacchi 1138*d14abf15SRobert Mustacchi if (pBlock->intrCapability & DDI_INTR_FLAG_BLOCK) 1139*d14abf15SRobert Mustacchi { 1140*d14abf15SRobert Mustacchi ddi_intr_block_disable(pBlock->pIntrHandleBlock, pBlock->intrCount); 1141*d14abf15SRobert Mustacchi } 1142*d14abf15SRobert Mustacchi else 1143*d14abf15SRobert Mustacchi { 1144*d14abf15SRobert Mustacchi for (i = 0; i < pBlock->intrCount; i++) 1145*d14abf15SRobert Mustacchi { 1146*d14abf15SRobert Mustacchi ddi_intr_disable(pBlock->pIntrHandleBlock[i]); 1147*d14abf15SRobert Mustacchi } 1148*d14abf15SRobert Mustacchi } 1149*d14abf15SRobert Mustacchi } 1150*d14abf15SRobert Mustacchi 1151*d14abf15SRobert Mustacchi 1152*d14abf15SRobert Mustacchi int BnxeIntrEnable(um_device_t * pUM) 1153*d14abf15SRobert Mustacchi { 1154*d14abf15SRobert Mustacchi BnxeMemDma * pDma; 1155*d14abf15SRobert Mustacchi int rc, i, j; 1156*d14abf15SRobert Mustacchi 1157*d14abf15SRobert Mustacchi atomic_swap_64((volatile uint64_t *)&pUM->intrFired, 0); 1158*d14abf15SRobert Mustacchi 1159*d14abf15SRobert Mustacchi for (i = 0; i < (MAX_RSS_CHAINS + 1); i++) 1160*d14abf15SRobert Mustacchi { 1161*d14abf15SRobert Mustacchi pUM->intrSbCnt[i] = 0; 1162*d14abf15SRobert Mustacchi pUM->intrSbNoChangeCnt[i] = 0; 1163*d14abf15SRobert Mustacchi } 1164*d14abf15SRobert Mustacchi 1165*d14abf15SRobert Mustacchi /* get the DMA handles for quick access to the status blocks for sync */ 1166*d14abf15SRobert Mustacchi BnxeFindDmaHandles(pUM); 1167*d14abf15SRobert Mustacchi 1168*d14abf15SRobert Mustacchi /* Enable the default interrupt... */ 1169*d14abf15SRobert Mustacchi 1170*d14abf15SRobert Mustacchi if (!BnxeIntrBlockEnable(pUM, &pUM->defIntr)) 1171*d14abf15SRobert Mustacchi { 1172*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to enable the default interrupt"); 1173*d14abf15SRobert Mustacchi return -1; 1174*d14abf15SRobert Mustacchi } 1175*d14abf15SRobert Mustacchi 1176*d14abf15SRobert Mustacchi /* Enable the FCoE interrupt... */ 1177*d14abf15SRobert Mustacchi 1178*d14abf15SRobert Mustacchi if (!BnxeIntrBlockEnable(pUM, &pUM->fcoeIntr)) 1179*d14abf15SRobert Mustacchi { 1180*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to enable the FCoE interrupt"); 1181*d14abf15SRobert Mustacchi BnxeIntrBlockDisable(pUM, &pUM->defIntr); 1182*d14abf15SRobert Mustacchi return -1; 1183*d14abf15SRobert Mustacchi } 1184*d14abf15SRobert Mustacchi 1185*d14abf15SRobert Mustacchi /* Enable the RSS interrupts... */ 1186*d14abf15SRobert Mustacchi 1187*d14abf15SRobert Mustacchi if (!BnxeIntrBlockEnable(pUM, &pUM->rssIntr)) 1188*d14abf15SRobert Mustacchi { 1189*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to enable the RSS interrupt"); 1190*d14abf15SRobert Mustacchi BnxeIntrBlockDisable(pUM, &pUM->defIntr); 1191*d14abf15SRobert Mustacchi BnxeIntrBlockDisable(pUM, &pUM->fcoeIntr); 1192*d14abf15SRobert Mustacchi return -1; 1193*d14abf15SRobert Mustacchi } 1194*d14abf15SRobert Mustacchi 1195*d14abf15SRobert Mustacchi /* allow the hardware to generate interrupts */ 1196*d14abf15SRobert Mustacchi atomic_swap_32(&pUM->intrEnabled, B_TRUE); 1197*d14abf15SRobert Mustacchi lm_enable_int(&pUM->lm_dev); 1198*d14abf15SRobert Mustacchi 1199*d14abf15SRobert Mustacchi if (pUM->fmCapabilities && 1200*d14abf15SRobert Mustacchi BnxeCheckAccHandle(pUM->lm_dev.vars.reg_handle[BAR_0]) != DDI_FM_OK) 1201*d14abf15SRobert Mustacchi { 1202*d14abf15SRobert Mustacchi ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); 1203*d14abf15SRobert Mustacchi } 1204*d14abf15SRobert Mustacchi 1205*d14abf15SRobert Mustacchi /* XXX do not remove this... edavis */ 1206*d14abf15SRobert Mustacchi drv_usecwait(1000000); /* :-( */ 1207*d14abf15SRobert Mustacchi 1208*d14abf15SRobert Mustacchi return 0; 1209*d14abf15SRobert Mustacchi } 1210*d14abf15SRobert Mustacchi 1211*d14abf15SRobert Mustacchi 1212*d14abf15SRobert Mustacchi void BnxeIntrDisable(um_device_t * pUM) 1213*d14abf15SRobert Mustacchi { 1214*d14abf15SRobert Mustacchi int rc, i; 1215*d14abf15SRobert Mustacchi 1216*d14abf15SRobert Mustacchi /* stop the device from generating any interrupts */ 1217*d14abf15SRobert Mustacchi lm_disable_int(&pUM->lm_dev); 1218*d14abf15SRobert Mustacchi 1219*d14abf15SRobert Mustacchi if (pUM->fmCapabilities && 1220*d14abf15SRobert Mustacchi BnxeCheckAccHandle(pUM->lm_dev.vars.reg_handle[BAR_0]) != DDI_FM_OK) 1221*d14abf15SRobert Mustacchi { 1222*d14abf15SRobert Mustacchi ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); 1223*d14abf15SRobert Mustacchi } 1224*d14abf15SRobert Mustacchi 1225*d14abf15SRobert Mustacchi atomic_swap_32(&pUM->intrEnabled, B_FALSE); 1226*d14abf15SRobert Mustacchi 1227*d14abf15SRobert Mustacchi /* 1228*d14abf15SRobert Mustacchi * Ensure the ISR no longer touches the hardware by making sure the ISR 1229*d14abf15SRobert Mustacchi * is not running or the current run completes. Since interrupts were 1230*d14abf15SRobert Mustacchi * disabled before here and intrEnabled is FALSE, we can be sure 1231*d14abf15SRobert Mustacchi * interrupts will no longer be processed. 1232*d14abf15SRobert Mustacchi */ 1233*d14abf15SRobert Mustacchi for (i = 0; i < (MAX_RSS_CHAINS + 1); i++) 1234*d14abf15SRobert Mustacchi { 1235*d14abf15SRobert Mustacchi BNXE_LOCK_ENTER_INTR(pUM, i); 1236*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_INTR(pUM, i); 1237*d14abf15SRobert Mustacchi } 1238*d14abf15SRobert Mustacchi 1239*d14abf15SRobert Mustacchi /* Disable the default interrupt... */ 1240*d14abf15SRobert Mustacchi 1241*d14abf15SRobert Mustacchi BnxeIntrBlockDisable(pUM, &pUM->defIntr); 1242*d14abf15SRobert Mustacchi 1243*d14abf15SRobert Mustacchi /* Disable the FCoE interrupt... */ 1244*d14abf15SRobert Mustacchi 1245*d14abf15SRobert Mustacchi BnxeIntrBlockDisable(pUM, &pUM->fcoeIntr); 1246*d14abf15SRobert Mustacchi 1247*d14abf15SRobert Mustacchi /* Disable the RSS interrupts... */ 1248*d14abf15SRobert Mustacchi 1249*d14abf15SRobert Mustacchi BnxeIntrBlockDisable(pUM, &pUM->rssIntr); 1250*d14abf15SRobert Mustacchi } 1251*d14abf15SRobert Mustacchi 1252*d14abf15SRobert Mustacchi 1253*d14abf15SRobert Mustacchi boolean_t BnxeIntrInit(um_device_t * pUM) 1254*d14abf15SRobert Mustacchi { 1255*d14abf15SRobert Mustacchi dev_info_t * pDev; 1256*d14abf15SRobert Mustacchi int intrTypes = 0; 1257*d14abf15SRobert Mustacchi int intrTotalAlloc = 0; 1258*d14abf15SRobert Mustacchi int numMSIX, numMSI, numFIX; 1259*d14abf15SRobert Mustacchi int rc, i; 1260*d14abf15SRobert Mustacchi 1261*d14abf15SRobert Mustacchi pDev = pUM->pDev; 1262*d14abf15SRobert Mustacchi 1263*d14abf15SRobert Mustacchi atomic_swap_32(&pUM->intrEnabled, B_FALSE); 1264*d14abf15SRobert Mustacchi 1265*d14abf15SRobert Mustacchi if ((rc = ddi_intr_get_supported_types(pDev, &intrTypes)) != DDI_SUCCESS) 1266*d14abf15SRobert Mustacchi { 1267*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to get supported interrupt types (%d)", rc); 1268*d14abf15SRobert Mustacchi return B_FALSE; 1269*d14abf15SRobert Mustacchi } 1270*d14abf15SRobert Mustacchi 1271*d14abf15SRobert Mustacchi numMSIX = BnxeGetInterruptCount(pDev, DDI_INTR_TYPE_MSIX, intrTypes); 1272*d14abf15SRobert Mustacchi numMSI = BnxeGetInterruptCount(pDev, DDI_INTR_TYPE_MSI, intrTypes); 1273*d14abf15SRobert Mustacchi numFIX = BnxeGetInterruptCount(pDev, DDI_INTR_TYPE_FIXED, intrTypes); 1274*d14abf15SRobert Mustacchi 1275*d14abf15SRobert Mustacchi if (numFIX <= 0) 1276*d14abf15SRobert Mustacchi { 1277*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Fixed interrupt not supported!"); 1278*d14abf15SRobert Mustacchi return B_FALSE; 1279*d14abf15SRobert Mustacchi } 1280*d14abf15SRobert Mustacchi 1281*d14abf15SRobert Mustacchi memset(&pUM->defIntr, 0, sizeof(BnxeIntrBlock)); 1282*d14abf15SRobert Mustacchi memset(&pUM->rssIntr, 0, sizeof(BnxeIntrBlock)); 1283*d14abf15SRobert Mustacchi memset(&pUM->fcoeIntr, 0, sizeof(BnxeIntrBlock)); 1284*d14abf15SRobert Mustacchi 1285*d14abf15SRobert Mustacchi if (pUM->devParams.disableMsix) 1286*d14abf15SRobert Mustacchi { 1287*d14abf15SRobert Mustacchi BnxeLogInfo(pUM, "Forcing fixed level interrupts."); 1288*d14abf15SRobert Mustacchi pUM->lm_dev.params.interrupt_mode = LM_INT_MODE_INTA; 1289*d14abf15SRobert Mustacchi pUM->intrType = DDI_INTR_TYPE_FIXED; 1290*d14abf15SRobert Mustacchi } 1291*d14abf15SRobert Mustacchi else if (numMSIX > 0) 1292*d14abf15SRobert Mustacchi { 1293*d14abf15SRobert Mustacchi pUM->lm_dev.params.interrupt_mode = LM_INT_MODE_MIMD; 1294*d14abf15SRobert Mustacchi pUM->intrType = DDI_INTR_TYPE_MSIX; 1295*d14abf15SRobert Mustacchi } 1296*d14abf15SRobert Mustacchi else /* numFIX */ 1297*d14abf15SRobert Mustacchi { 1298*d14abf15SRobert Mustacchi pUM->lm_dev.params.interrupt_mode = LM_INT_MODE_INTA; 1299*d14abf15SRobert Mustacchi pUM->intrType = DDI_INTR_TYPE_FIXED; 1300*d14abf15SRobert Mustacchi } 1301*d14abf15SRobert Mustacchi 1302*d14abf15SRobert Mustacchi while (1) 1303*d14abf15SRobert Mustacchi { 1304*d14abf15SRobert Mustacchi /* allocate the default interrupt */ 1305*d14abf15SRobert Mustacchi 1306*d14abf15SRobert Mustacchi if (!BnxeIntrBlockAlloc(pUM, 1307*d14abf15SRobert Mustacchi 0, 1308*d14abf15SRobert Mustacchi 1, 1309*d14abf15SRobert Mustacchi &pUM->defIntr)) 1310*d14abf15SRobert Mustacchi { 1311*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to allocate default %s interrupt!", 1312*d14abf15SRobert Mustacchi BnxeIntrTypeName(pUM->intrType)); 1313*d14abf15SRobert Mustacchi goto BnxeIntrInit_alloc_fail; 1314*d14abf15SRobert Mustacchi } 1315*d14abf15SRobert Mustacchi 1316*d14abf15SRobert Mustacchi intrTotalAlloc++; 1317*d14abf15SRobert Mustacchi 1318*d14abf15SRobert Mustacchi if (pUM->intrType == DDI_INTR_TYPE_FIXED) 1319*d14abf15SRobert Mustacchi { 1320*d14abf15SRobert Mustacchi /* only one interrupt allocated for fixed (default) */ 1321*d14abf15SRobert Mustacchi break; 1322*d14abf15SRobert Mustacchi } 1323*d14abf15SRobert Mustacchi 1324*d14abf15SRobert Mustacchi if (BnxeProtoFcoeAfex(pUM)) 1325*d14abf15SRobert Mustacchi { 1326*d14abf15SRobert Mustacchi pUM->devParams.numRings = 0; 1327*d14abf15SRobert Mustacchi } 1328*d14abf15SRobert Mustacchi else 1329*d14abf15SRobert Mustacchi { 1330*d14abf15SRobert Mustacchi /* allocate the RSS interrupts */ 1331*d14abf15SRobert Mustacchi 1332*d14abf15SRobert Mustacchi while (pUM->devParams.numRings > 0) 1333*d14abf15SRobert Mustacchi { 1334*d14abf15SRobert Mustacchi if (!BnxeIntrBlockAlloc(pUM, 1335*d14abf15SRobert Mustacchi (NDIS_CID(&pUM->lm_dev) + 1), 1336*d14abf15SRobert Mustacchi pUM->devParams.numRings, 1337*d14abf15SRobert Mustacchi &pUM->rssIntr)) 1338*d14abf15SRobert Mustacchi { 1339*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to allocate %d RSS %s interrupts!", 1340*d14abf15SRobert Mustacchi pUM->devParams.numRings, 1341*d14abf15SRobert Mustacchi BnxeIntrTypeName(pUM->intrType)); 1342*d14abf15SRobert Mustacchi pUM->devParams.numRings >>= 1; 1343*d14abf15SRobert Mustacchi continue; 1344*d14abf15SRobert Mustacchi } 1345*d14abf15SRobert Mustacchi 1346*d14abf15SRobert Mustacchi break; 1347*d14abf15SRobert Mustacchi } 1348*d14abf15SRobert Mustacchi 1349*d14abf15SRobert Mustacchi if (pUM->devParams.numRings == 0) 1350*d14abf15SRobert Mustacchi { 1351*d14abf15SRobert Mustacchi BnxeIntrBlockFree(pUM, &pUM->defIntr); 1352*d14abf15SRobert Mustacchi goto BnxeIntrInit_alloc_fail; 1353*d14abf15SRobert Mustacchi } 1354*d14abf15SRobert Mustacchi 1355*d14abf15SRobert Mustacchi BnxeLogInfo(pUM, "Allocated %d RSS %s interrupts.", 1356*d14abf15SRobert Mustacchi pUM->rssIntr.intrCount, 1357*d14abf15SRobert Mustacchi BnxeIntrTypeName(pUM->intrType)); 1358*d14abf15SRobert Mustacchi 1359*d14abf15SRobert Mustacchi intrTotalAlloc += pUM->rssIntr.intrCount; /* intrCount <= numRings */ 1360*d14abf15SRobert Mustacchi } 1361*d14abf15SRobert Mustacchi 1362*d14abf15SRobert Mustacchi /* 1363*d14abf15SRobert Mustacchi * Allocate the FCoE interrupt only if all available status blocks 1364*d14abf15SRobert Mustacchi * were not taken up by the RSS chains. If they were then the last 1365*d14abf15SRobert Mustacchi * status block (LM_NON_RSS_SB) is overloaded for both RSS and FCoE. 1366*d14abf15SRobert Mustacchi */ 1367*d14abf15SRobert Mustacchi 1368*d14abf15SRobert Mustacchi if (BNXE_FCOE(pUM)) 1369*d14abf15SRobert Mustacchi { 1370*d14abf15SRobert Mustacchi if (pUM->rssIntr.intrCount < LM_MAX_RSS_CHAINS(&pUM->lm_dev)) 1371*d14abf15SRobert Mustacchi { 1372*d14abf15SRobert Mustacchi if (!BnxeIntrBlockAlloc(pUM, 1373*d14abf15SRobert Mustacchi (LM_NON_RSS_SB(&pUM->lm_dev) + 1), 1374*d14abf15SRobert Mustacchi 1, 1375*d14abf15SRobert Mustacchi &pUM->fcoeIntr)) 1376*d14abf15SRobert Mustacchi { 1377*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to allocate FCoE %s interrupt!", 1378*d14abf15SRobert Mustacchi BnxeIntrTypeName(pUM->intrType)); 1379*d14abf15SRobert Mustacchi BnxeIntrBlockFree(pUM, &pUM->defIntr); 1380*d14abf15SRobert Mustacchi BnxeIntrBlockFree(pUM, &pUM->rssIntr); 1381*d14abf15SRobert Mustacchi goto BnxeIntrInit_alloc_fail; 1382*d14abf15SRobert Mustacchi } 1383*d14abf15SRobert Mustacchi 1384*d14abf15SRobert Mustacchi intrTotalAlloc++; 1385*d14abf15SRobert Mustacchi } 1386*d14abf15SRobert Mustacchi else 1387*d14abf15SRobert Mustacchi { 1388*d14abf15SRobert Mustacchi /* to be safe, sets fcoeIntr.intrCount to 0 */ 1389*d14abf15SRobert Mustacchi memset(&pUM->fcoeIntr, 0, sizeof(BnxeIntrBlock)); 1390*d14abf15SRobert Mustacchi } 1391*d14abf15SRobert Mustacchi } 1392*d14abf15SRobert Mustacchi 1393*d14abf15SRobert Mustacchi break; 1394*d14abf15SRobert Mustacchi 1395*d14abf15SRobert Mustacchi BnxeIntrInit_alloc_fail: 1396*d14abf15SRobert Mustacchi 1397*d14abf15SRobert Mustacchi if (pUM->intrType == DDI_INTR_TYPE_FIXED) 1398*d14abf15SRobert Mustacchi { 1399*d14abf15SRobert Mustacchi return B_FALSE; 1400*d14abf15SRobert Mustacchi } 1401*d14abf15SRobert Mustacchi 1402*d14abf15SRobert Mustacchi /* fall back to fixed a retry allocation */ 1403*d14abf15SRobert Mustacchi intrTotalAlloc = 0; 1404*d14abf15SRobert Mustacchi pUM->lm_dev.params.interrupt_mode = LM_INT_MODE_INTA; 1405*d14abf15SRobert Mustacchi pUM->intrType = DDI_INTR_TYPE_FIXED; 1406*d14abf15SRobert Mustacchi } 1407*d14abf15SRobert Mustacchi 1408*d14abf15SRobert Mustacchi if (pUM->intrType == DDI_INTR_TYPE_MSIX) 1409*d14abf15SRobert Mustacchi { 1410*d14abf15SRobert Mustacchi pUM->devParams.numRings = pUM->rssIntr.intrCount; 1411*d14abf15SRobert Mustacchi pUM->lm_dev.params.rss_chain_cnt = pUM->rssIntr.intrCount; 1412*d14abf15SRobert Mustacchi pUM->lm_dev.params.tss_chain_cnt = pUM->rssIntr.intrCount; 1413*d14abf15SRobert Mustacchi } 1414*d14abf15SRobert Mustacchi else 1415*d14abf15SRobert Mustacchi { 1416*d14abf15SRobert Mustacchi /* fixed level (no rings)... */ 1417*d14abf15SRobert Mustacchi pUM->devParams.numRings = 0; 1418*d14abf15SRobert Mustacchi pUM->lm_dev.params.rss_chain_cnt = 1; 1419*d14abf15SRobert Mustacchi pUM->lm_dev.params.tss_chain_cnt = 1; 1420*d14abf15SRobert Mustacchi 1421*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Using Fixed Level Interrupts! (set ddi_msix_alloc_limit in /etc/system)"); 1422*d14abf15SRobert Mustacchi } 1423*d14abf15SRobert Mustacchi 1424*d14abf15SRobert Mustacchi BnxeLogInfo(pUM, "Interrupts (Supported - %d Fixed / %d MSI / %d MSIX) (Allocated - %d %s)", 1425*d14abf15SRobert Mustacchi numFIX, numMSI, numMSIX, intrTotalAlloc, BnxeIntrTypeName(pUM->intrType)); 1426*d14abf15SRobert Mustacchi 1427*d14abf15SRobert Mustacchi if (!BnxeIntrAddHandlers(pUM)) 1428*d14abf15SRobert Mustacchi { 1429*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to add interrupts!"); 1430*d14abf15SRobert Mustacchi BnxeIntrBlockFree(pUM, &pUM->defIntr); 1431*d14abf15SRobert Mustacchi BnxeIntrBlockFree(pUM, &pUM->fcoeIntr); 1432*d14abf15SRobert Mustacchi BnxeIntrBlockFree(pUM, &pUM->rssIntr); 1433*d14abf15SRobert Mustacchi return B_FALSE; 1434*d14abf15SRobert Mustacchi } 1435*d14abf15SRobert Mustacchi 1436*d14abf15SRobert Mustacchi /* copy default priority and assume rest are the same (for mutex) */ 1437*d14abf15SRobert Mustacchi pUM->intrPriority = pUM->defIntr.intrPriority; 1438*d14abf15SRobert Mustacchi 1439*d14abf15SRobert Mustacchi return B_TRUE; 1440*d14abf15SRobert Mustacchi } 1441*d14abf15SRobert Mustacchi 1442*d14abf15SRobert Mustacchi 1443*d14abf15SRobert Mustacchi void BnxeIntrFini(um_device_t * pUM) 1444*d14abf15SRobert Mustacchi { 1445*d14abf15SRobert Mustacchi int i; 1446*d14abf15SRobert Mustacchi 1447*d14abf15SRobert Mustacchi BnxeIntrBlockDisable(pUM, &pUM->defIntr); 1448*d14abf15SRobert Mustacchi BnxeIntrBlockRemoveHandler(pUM, &pUM->defIntr); 1449*d14abf15SRobert Mustacchi BnxeIntrBlockFree(pUM, &pUM->defIntr); 1450*d14abf15SRobert Mustacchi 1451*d14abf15SRobert Mustacchi BnxeIntrBlockDisable(pUM, &pUM->fcoeIntr); 1452*d14abf15SRobert Mustacchi BnxeIntrBlockRemoveHandler(pUM, &pUM->fcoeIntr); 1453*d14abf15SRobert Mustacchi BnxeIntrBlockFree(pUM, &pUM->fcoeIntr); 1454*d14abf15SRobert Mustacchi 1455*d14abf15SRobert Mustacchi BnxeIntrBlockDisable(pUM, &pUM->rssIntr); 1456*d14abf15SRobert Mustacchi BnxeIntrBlockRemoveHandler(pUM, &pUM->rssIntr); 1457*d14abf15SRobert Mustacchi BnxeIntrBlockFree(pUM, &pUM->rssIntr); 1458*d14abf15SRobert Mustacchi } 1459*d14abf15SRobert Mustacchi 1460