xref: /titanic_51/usr/src/uts/common/io/bnxe/bnxe_intr.c (revision d14abf155341d55053c76eeec58b787a456b753b)
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