Print this page
NEX-1890 update oce from source provided by Emulex
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/io/fibre-channel/fca/oce/oce_intr.c
+++ new/usr/src/uts/common/io/fibre-channel/fca/oce/oce_intr.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
|
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 -/* Copyright © 2003-2011 Emulex. All rights reserved. */
22 +/*
23 + * Copyright (c) 2009-2012 Emulex. All rights reserved.
24 + * Use is subject to license terms.
25 + */
23 26
27 +
28 +
24 29 /*
25 30 * Source file interrupt registration
26 31 * and related helper functions
27 32 */
28 33
29 34 #include <oce_impl.h>
30 35
31 -
32 36 static uint_t oce_isr(caddr_t arg1, caddr_t arg2);
37 +static int
38 +oce_adjust_intrs(struct oce_dev *dev, ddi_cb_action_t action, int count);
33 39
34 40 /*
35 41 * top level function to setup interrupts
36 42 *
37 43 * dev - software handle to the device
38 44 *
39 45 * return DDI_SUCCESS => success, failure otherwise
40 46 */
41 47 int
42 48 oce_setup_intr(struct oce_dev *dev)
43 49 {
44 - int ret;
50 + int ret, i;
45 51 int intr_types = 0;
46 52 int navail = 0;
47 53 int nsupported = 0;
48 54 int min = 0;
49 55 int nreqd = 0;
50 56 int nallocd = 0;
57 + extern int oce_irm_enable;
51 58
52 59 /* get supported intr types */
53 60 ret = ddi_intr_get_supported_types(dev->dip, &intr_types);
54 61 if (ret != DDI_SUCCESS) {
55 - oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
56 - "Failed to retrieve intr types ");
62 + oce_log(dev, CE_WARN, MOD_CONFIG,
63 + "Failed to retrieve intr types 0x%x", ret);
57 64 return (DDI_FAILURE);
58 65 }
59 66
67 + dev->rx_rings = min(dev->rx_rings, ncpus + dev->rss_cnt);
68 + dev->tx_rings = min(dev->tx_rings, ncpus);
69 +#ifdef __sparc
70 + nreqd = min(dev->tx_rings + dev->rx_rings - dev->rss_cnt, ncpus);
71 + dev->rx_group[0].eq_idx = dev->tx_rings;
72 +#else
73 + nreqd = max(dev->tx_rings, dev->rx_rings - dev->rss_cnt);
74 +#endif
75 + min = OCE_MIN_VECTORS;
76 +
60 77 retry_intr:
78 +
61 79 if (intr_types & DDI_INTR_TYPE_MSIX) {
62 80 dev->intr_type = DDI_INTR_TYPE_MSIX;
63 - /* one vector is shared by MCC and Tx */
64 - nreqd = dev->rx_rings + 1;
65 - min = OCE_MIN_VECTORS;
66 - } else if (intr_types & DDI_INTR_TYPE_FIXED) {
67 - dev->intr_type = DDI_INTR_TYPE_FIXED;
81 + } else {
82 + oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
83 + "MSIX not available");
84 +
85 + if (intr_types & DDI_INTR_TYPE_FIXED) {
86 + dev->intr_type = DDI_INTR_TYPE_FIXED;
87 + dev->rx_rings = dev->tx_rings = min;
88 + } else {
89 + return (DDI_FAILURE);
90 + }
68 91 nreqd = OCE_MIN_VECTORS;
69 - min = OCE_MIN_VECTORS;
70 92 }
71 93
72 94 ret = ddi_intr_get_nintrs(dev->dip, dev->intr_type, &nsupported);
73 95 if (ret != DDI_SUCCESS) {
74 96 oce_log(dev, CE_WARN, MOD_CONFIG,
75 - "Could not get nintrs:0x%d", ret);
97 + "Could not get supported intrs:0x%x", ret);
76 98 return (DDI_FAILURE);
77 99 }
78 100
79 101 /* get the number of vectors available */
80 102 ret = ddi_intr_get_navail(dev->dip, dev->intr_type, &navail);
81 103 if (ret != DDI_SUCCESS || navail < min) {
82 - oce_log(dev, CE_WARN, MOD_CONFIG,
83 - "Could not get msix vectors:0x%x",
84 - navail);
85 - return (DDI_FAILURE);
104 + oce_log(dev, CE_NOTE, MOD_CONFIG,
105 + "Vectors: supported:0x%x, available:0x%x, ret:0x%x",
106 + nsupported, navail, ret);
107 + intr_types &= ~dev->intr_type;
108 + goto retry_intr;
86 109 }
87 110
88 - if (navail < min) {
89 - return (DDI_FAILURE);
90 - }
91 -
92 - /* if the requested number is more than available reset reqd */
93 111 if (navail < nreqd) {
94 112 nreqd = navail;
95 113 }
96 114
97 115 /* allocate htable */
98 116 dev->hsize = nreqd * sizeof (ddi_intr_handle_t);
99 117 dev->htable = kmem_zalloc(dev->hsize, KM_NOSLEEP);
100 118
101 119 if (dev->htable == NULL)
102 120 return (DDI_FAILURE);
103 121
104 - nallocd = 0;
105 - /* allocate interrupt handlers */
122 + /* allocate interrupt */
106 123 ret = ddi_intr_alloc(dev->dip, dev->htable, dev->intr_type,
107 124 0, nreqd, &nallocd, DDI_INTR_ALLOC_NORMAL);
108 125
109 - if (ret != DDI_SUCCESS) {
110 - goto fail_intr;
126 + if (ret != DDI_SUCCESS || nallocd < min) {
127 + oce_log(dev, CE_WARN, MOD_CONFIG,
128 + "Alloc intr failed: %d %d",
129 + navail, ret);
130 + kmem_free(dev->htable, nreqd * sizeof (ddi_intr_handle_t));
131 + intr_types &= ~dev->intr_type;
132 + goto retry_intr;
111 133 }
112 134
113 - dev->num_vectors = nallocd;
114 - if (nallocd < min) {
115 - goto fail_intr;
116 - }
117 -
118 135 /*
119 136 * get the interrupt priority. Assumption is that all handlers have
120 137 * equal priority
121 138 */
122 139
123 140 ret = ddi_intr_get_pri(dev->htable[0], &dev->intr_pri);
124 141
125 142 if (ret != DDI_SUCCESS) {
126 - goto fail_intr;
143 + oce_log(dev, CE_WARN, MOD_CONFIG,
144 + "Unable to get intr priority: 0x%x", ret);
145 +
146 + for (i = 0; i < dev->num_vectors; i++) {
147 + (void) ddi_intr_free(dev->htable[i]);
148 + }
149 + kmem_free(dev->htable, nreqd * sizeof (ddi_intr_handle_t));
150 + return (DDI_FAILURE);
127 151 }
128 152
129 153 (void) ddi_intr_get_cap(dev->htable[0], &dev->intr_cap);
130 154
131 - if ((intr_types & DDI_INTR_TYPE_MSIX) && (nallocd > 1)) {
132 - dev->rx_rings = nallocd - 1;
155 + /* update the actual number of interrupts allocated */
156 + dev->num_vectors = nallocd;
157 + if (oce_irm_enable && dev->intr_type == DDI_INTR_TYPE_MSIX) {
158 + dev->max_vectors = nreqd;
133 159 } else {
134 - dev->rx_rings = 1;
160 + dev->max_vectors = nallocd;
161 + dev->tx_rings = min(dev->tx_rings, nallocd);
162 + dev->rx_rings = min(dev->rx_rings, nallocd + dev->rss_cnt);
135 163 }
136 164
165 + oce_group_rings(dev);
137 166 return (DDI_SUCCESS);
138 -
139 -fail_intr:
140 - (void) oce_teardown_intr(dev);
141 - if ((dev->intr_type == DDI_INTR_TYPE_MSIX) &&
142 - (intr_types & DDI_INTR_TYPE_FIXED)) {
143 - intr_types &= ~DDI_INTR_TYPE_MSIX;
144 - oce_log(dev, CE_NOTE, MOD_CONFIG, "%s",
145 - "Could not get MSIX vectors, trying for FIXED vectors");
146 - goto retry_intr;
147 - }
148 - return (DDI_FAILURE);
149 167 }
150 168
169 +
151 170 /*
152 171 * top level function to undo initialization in oce_setup_intr
153 172 *
154 173 * dev - software handle to the device
155 174 *
156 175 * return DDI_SUCCESS => success, failure otherwise
157 176 */
158 177 int
159 178 oce_teardown_intr(struct oce_dev *dev)
160 179 {
161 180 int i;
162 181
163 182 /* release handlers */
164 183 for (i = 0; i < dev->num_vectors; i++) {
165 184 (void) ddi_intr_free(dev->htable[i]);
166 185 }
167 186
168 187 /* release htable */
169 188 kmem_free(dev->htable, dev->hsize);
170 189 dev->htable = NULL;
171 -
190 + if (dev->attach_state & ATTACH_CB_REG) {
191 + (void) ddi_cb_unregister(dev->cb_handle);
192 + }
172 193 return (DDI_SUCCESS);
173 194 }
174 195
175 196 /*
176 197 * helper function to add ISR based on interrupt type
177 198 *
178 199 * dev - software handle to the device
179 200 *
180 201 * return DDI_SUCCESS => success, failure otherwise
181 202 */
182 203 int
183 204 oce_setup_handlers(struct oce_dev *dev)
184 205 {
185 206 int i = 0;
186 207 int ret;
187 208 for (i = 0; i < dev->num_vectors; i++) {
188 209 ret = ddi_intr_add_handler(dev->htable[i], oce_isr,
189 - (caddr_t)dev->eq[i], NULL);
210 + (caddr_t)&dev->eq[i], NULL);
190 211 if (ret != DDI_SUCCESS) {
191 - oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
192 - "Failed to add interrupt handlers");
212 + oce_log(dev, CE_WARN, MOD_CONFIG,
213 + "Failed to add interrupt handler %d, ret = 0x%x",
214 + i, ret);
193 215 for (i--; i >= 0; i--) {
194 216 (void) ddi_intr_remove_handler(dev->htable[i]);
195 217 }
196 218 return (DDI_FAILURE);
197 219 }
198 220 }
199 221 return (DDI_SUCCESS);
200 222 }
201 223
202 224 /*
203 225 * helper function to remove ISRs added in oce_setup_handlers
204 226 *
205 227 * dev - software handle to the device
206 228 *
207 229 * return DDI_SUCCESS => success, failure otherwise
208 230 */
209 231 void
210 232 oce_remove_handler(struct oce_dev *dev)
211 233 {
212 234 int nvec;
213 235 for (nvec = 0; nvec < dev->num_vectors; nvec++) {
214 236 (void) ddi_intr_remove_handler(dev->htable[nvec]);
215 237 }
216 238 }
217 239
218 240 void
219 241 oce_chip_ei(struct oce_dev *dev)
220 242 {
221 243 uint32_t reg;
222 244
223 245 reg = OCE_CFG_READ32(dev, PCICFG_INTR_CTRL);
224 246 reg |= HOSTINTR_MASK;
|
↓ open down ↓ |
22 lines elided |
↑ open up ↑ |
225 247 OCE_CFG_WRITE32(dev, PCICFG_INTR_CTRL, reg);
226 248 }
227 249
228 250 /*
229 251 * function to enable interrupts
230 252 *
231 253 * dev - software handle to the device
232 254 *
233 255 * return DDI_SUCCESS => success, failure otherwise
234 256 */
235 -void
257 +int
236 258 oce_ei(struct oce_dev *dev)
237 259 {
238 260 int i;
239 261 int ret;
240 262
241 263 if (dev->intr_cap & DDI_INTR_FLAG_BLOCK) {
242 - (void) ddi_intr_block_enable(dev->htable, dev->num_vectors);
264 + ret = ddi_intr_block_enable(dev->htable, dev->num_vectors);
265 + if (ret != DDI_SUCCESS) {
266 + oce_log(dev, CE_WARN, MOD_CONFIG,
267 + "Interrupts block enable failed :%d\n", ret);
268 + return (DDI_FAILURE);
269 + }
243 270 } else {
244 -
245 271 for (i = 0; i < dev->num_vectors; i++) {
246 272 ret = ddi_intr_enable(dev->htable[i]);
247 273 if (ret != DDI_SUCCESS) {
274 + oce_log(dev, CE_WARN, MOD_CONFIG,
275 + "Failed to enable, ret %d, interrupt %d,"
276 + " type %d, cnt %d ",
277 + ret, i, dev->intr_type, dev->num_vectors);
248 278 for (i--; i >= 0; i--) {
249 279 (void) ddi_intr_disable(dev->htable[i]);
250 280 }
281 + return (DDI_FAILURE);
251 282 }
252 283 }
253 284 }
254 - oce_chip_ei(dev);
285 +
286 + return (DDI_SUCCESS);
255 287 } /* oce_ei */
256 288
257 289 void
258 290 oce_chip_di(struct oce_dev *dev)
259 291 {
260 292 uint32_t reg;
261 293
262 294 reg = OCE_CFG_READ32(dev, PCICFG_INTR_CTRL);
263 295 reg &= ~HOSTINTR_MASK;
264 296 OCE_CFG_WRITE32(dev, PCICFG_INTR_CTRL, reg);
265 297 }
266 298
267 299 /*
268 300 * function to disable interrupts
269 301 *
270 302 * dev - software handle to the device
271 303 *
272 304 * return DDI_SUCCESS => success, failure otherwise
273 305 */
274 -void
306 +int
275 307 oce_di(struct oce_dev *dev)
276 308 {
277 309 int i;
278 310 int ret;
279 311
280 - oce_chip_di(dev);
312 + dev->state &= ~STATE_INTR_ENABLED;
313 + if (!LANCER_CHIP(dev))
314 + oce_chip_di(dev);
315 +
281 316 if (dev->intr_cap & DDI_INTR_FLAG_BLOCK) {
282 - (void) ddi_intr_block_disable(dev->htable, dev->num_vectors);
317 + ret = ddi_intr_block_disable(dev->htable, dev->num_vectors);
318 + if (ret != DDI_SUCCESS) {
319 + oce_log(dev, CE_WARN, MOD_CONFIG,
320 + "Interrupt block disable failed :%d\n", ret);
321 + return (DDI_FAILURE);
322 + }
283 323 } else {
284 324 for (i = 0; i < dev->num_vectors; i++) {
285 325 ret = ddi_intr_disable(dev->htable[i]);
286 326 if (ret != DDI_SUCCESS) {
287 327 oce_log(dev, CE_WARN, MOD_CONFIG,
288 - "Failed to disable interrupts 0x%x", ret);
328 + "Failed to disable the interrupts 0x%x",
329 + ret);
330 + return (DDI_FAILURE);
289 331 }
290 332 }
291 333 }
292 -
334 + return (DDI_SUCCESS);
293 335 } /* oce_di */
294 336
295 -/*
296 - * command interrupt handler routine added to all vectors
297 - *
298 - * arg1 = callback data
299 - * arg2 - callback data
300 - *
301 - * return DDI_INTR_CLAIMED => interrupt was claimed by the ISR
302 - */
303 -static uint_t
304 -oce_isr(caddr_t arg1, caddr_t arg2)
337 +
338 +int
339 +oce_ring_intr_enable(mac_intr_handle_t ring_handle)
305 340 {
306 - struct oce_eq *eq;
341 + struct oce_rq *rx_ring = (struct oce_rq *)ring_handle;
342 + struct oce_dev *dev;
343 + dev = rx_ring->parent;
344 + oce_group_t *grp = rx_ring->grp;
345 + mutex_enter(&grp->grp_lock);
346 + if (grp->state & GROUP_SUSPEND) {
347 + mutex_exit(&grp->grp_lock);
348 + return (DDI_SUCCESS);
349 + }
350 + mutex_enter(&rx_ring->rx_lock);
351 + oce_arm_cq(dev, rx_ring->cq->cq_id, 0, B_TRUE);
352 + rx_ring->qmode = OCE_MODE_INTR;
353 + mutex_exit(&rx_ring->rx_lock);
354 + mutex_exit(&grp->grp_lock);
355 + return (DDI_SUCCESS);
356 +}
357 +
358 +
359 +int
360 +oce_ring_intr_disable(mac_intr_handle_t ring_handle)
361 +{
362 + struct oce_rq *rx_ring = (struct oce_rq *)ring_handle;
363 + struct oce_dev *dev;
364 +
365 + dev = rx_ring->parent;
366 + mutex_enter(&rx_ring->rx_lock);
367 + oce_arm_cq(dev, rx_ring->cq->cq_id, 0, B_FALSE);
368 + rx_ring->qmode = OCE_MODE_POLL;
369 + mutex_exit(&rx_ring->rx_lock);
370 + return (DDI_SUCCESS);
371 +}
372 +
373 +uint_t
374 +oce_ring_common_drain(struct oce_eq *eq)
375 +{
307 376 struct oce_eqe *eqe;
308 377 uint16_t num_eqe = 0;
309 378 uint16_t cq_id;
310 379 struct oce_cq *cq;
311 380 struct oce_dev *dev;
312 381
313 - _NOTE(ARGUNUSED(arg2));
314 -
315 - eq = (struct oce_eq *)(void *)(arg1);
316 -
317 382 dev = eq->parent;
318 383
319 384 eqe = RING_GET_CONSUMER_ITEM_VA(eq->ring, struct oce_eqe);
320 385
321 - while (eqe->u0.dw0) {
322 -
386 + if (eqe->u0.dw0) {
323 387 eqe->u0.dw0 = LE_32(eqe->u0.dw0);
324 388
325 - /* if not CQ then continue else flag an error */
326 - if (EQ_MAJOR_CODE_COMPLETION != eqe->u0.s.major_code) {
327 - oce_log(dev, CE_WARN, MOD_ISR,
328 - "NOT a CQ event. 0x%x",
329 - eqe->u0.s.major_code);
330 - }
331 -
332 389 /* get the cq from the eqe */
333 390 cq_id = eqe->u0.s.resource_id % OCE_MAX_CQ;
334 391 cq = dev->cq[cq_id];
335 392
336 - /* Call the completion handler */
337 - (void) cq->cq_handler(cq->cb_arg);
338 -
339 393 /* clear valid bit and progress eqe */
340 394 eqe->u0.dw0 = 0;
341 395 RING_GET(eq->ring, 1);
342 - eqe = RING_GET_CONSUMER_ITEM_VA(eq->ring, struct oce_eqe);
343 396 num_eqe++;
344 - } /* for all EQEs */
345 397
398 + if (cq) {
399 + /* Call the completion handler */
400 + (void) cq->cq_handler(cq->cb_arg, 0, 0);
401 + }
402 + }
403 +
346 404 /* ring the eq doorbell, signify that it's done processing */
347 405 oce_arm_eq(dev, eq->eq_id, num_eqe, B_TRUE, B_TRUE);
348 - if (num_eqe > 0) {
406 +
407 + return (num_eqe);
408 +
409 +} /* oce_ring_common_drain */
410 +
411 +
412 +/* MSI/INTX handler: common vector for TX/RX/MQ */
413 +uint_t
414 +oce_isr(caddr_t arg1, caddr_t arg2)
415 +{
416 + struct oce_eq *eq;
417 + struct oce_dev *dev;
418 + uint16_t num_eqe = 0;
419 +
420 + _NOTE(ARGUNUSED(arg2));
421 +
422 + eq = (struct oce_eq *)(void *)(arg1);
423 + dev = eq->parent;
424 +
425 + if ((dev == NULL) ||
426 + !(dev->state & STATE_INTR_ENABLED)) {
427 + oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
428 + "Dummy interrupt received");
349 429 return (DDI_INTR_CLAIMED);
430 + }
431 +
432 + mutex_enter(&eq->lock);
433 + if (eq->qstate != QSTARTED) {
434 + mutex_exit(&eq->lock);
435 + oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
436 + "oce_isr EQ Not started");
437 + return (DDI_INTR_CLAIMED);
438 + }
439 + num_eqe = oce_ring_common_drain(eq);
440 + mutex_exit(&eq->lock);
441 + if (num_eqe) {
442 + return (DDI_INTR_CLAIMED);
350 443 } else {
351 444 return (DDI_INTR_UNCLAIMED);
352 445 }
353 -} /* oce_msix_handler */
446 +}
447 +
448 +/*
449 + * IRM callback routine
450 + */
451 +int
452 +oce_cbfunc(dev_info_t *dip, ddi_cb_action_t cbaction, void *cbarg,
453 + void *arg1, void *arg2)
454 +{
455 + struct oce_dev *dev = (struct oce_dev *)arg1;
456 + int count = (int)(uintptr_t)cbarg, ret = DDI_ENOTSUP;
457 +
458 + _NOTE(ARGUNUSED(dip));
459 + _NOTE(ARGUNUSED(arg2));
460 +
461 + switch (cbaction) {
462 + case DDI_CB_INTR_ADD:
463 + case DDI_CB_INTR_REMOVE:
464 +
465 + oce_log(dev, CE_NOTE, MOD_CONFIG,
466 + "IRM cbaction %d count %d vectors %d max_vectors %d",
467 + cbaction, count, dev->num_vectors, dev->max_vectors);
468 + ret = oce_adjust_intrs(dev, cbaction, count);
469 + if (ret != DDI_SUCCESS) {
470 + oce_log(dev, CE_NOTE, MOD_CONFIG, "%s",
471 + "IRM: Failed to adjust interrupts");
472 + return (ret);
473 + }
474 + break;
475 +
476 + default:
477 + return (ret);
478 + }
479 + return (ret);
480 +}
481 +
482 +
483 +static int
484 +oce_adjust_intrs(struct oce_dev *dev, ddi_cb_action_t action, int count)
485 +{
486 + int i, nallocd, ret;
487 +
488 + if (count == 0)
489 + return (DDI_SUCCESS);
490 +
491 + if ((action == DDI_CB_INTR_ADD &&
492 + dev->num_vectors + count > dev->max_vectors) ||
493 + (action == DDI_CB_INTR_REMOVE &&
494 + dev->num_vectors - count < OCE_MIN_VECTORS)) {
495 + return (DDI_FAILURE);
496 + }
497 +
498 + if (!(dev->state & STATE_MAC_STARTED)) {
499 + return (DDI_FAILURE);
500 + }
501 +
502 + mutex_enter(&dev->dev_lock);
503 + dev->state |= STATE_INTR_ADJUST;
504 + dev->suspended = B_TRUE;
505 +
506 + /* stop the groups */
507 + for (i = 0; i < dev->num_rx_groups; i++) {
508 + mutex_enter(&dev->rx_group[i].grp_lock);
509 + oce_suspend_group_rings(&dev->rx_group[i]);
510 + oce_stop_group(&dev->rx_group[i], B_FALSE);
511 + mutex_exit(&dev->rx_group[i].grp_lock);
512 + }
513 +
514 + oce_stop(dev);
515 + oce_remove_handler(dev);
516 + if (action == DDI_CB_INTR_ADD) {
517 + /* allocate additional vectors */
518 + ret = ddi_intr_alloc(dev->dip, dev->htable, DDI_INTR_TYPE_MSIX,
519 + dev->num_vectors, count, &nallocd, DDI_INTR_ALLOC_NORMAL);
520 +
521 + if (ret != DDI_SUCCESS) {
522 + goto irm_fail;
523 + }
524 +
525 + /* update actual count of available interrupts */
526 + dev->num_vectors += nallocd;
527 + oce_log(dev, CE_NOTE, MOD_CONFIG,
528 + "IRM: INTR_ADD - count=0x%x allocated=0x%x vectors=0x%x",
529 + count, nallocd, dev->num_vectors);
530 + } else {
531 + /* free interrupt vectors */
532 + for (i = dev->num_vectors - count;
533 + i < dev->num_vectors; i++) {
534 + ret = ddi_intr_free(dev->htable[i]);
535 + if (ret != DDI_SUCCESS) {
536 + oce_log(dev, CE_WARN, MOD_CONFIG,
537 + "IRM: can't free vectors ret 0x%x", ret);
538 + goto irm_fail;
539 + }
540 + dev->htable[i] = NULL;
541 + }
542 +
543 + /* update actual count of available interrupts */
544 + dev->num_vectors -= count;
545 + oce_log(dev, CE_NOTE, MOD_CONFIG,
546 + "IRM: INTR_REMOVE - count = 0x%x vectors = 0x%x",
547 + count, dev->num_vectors);
548 + }
549 +
550 + if (oce_setup_handlers(dev) != DDI_SUCCESS) {
551 + oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
552 + "Failed to Setup handlers during IRM");
553 + goto irm_fail;
554 + }
555 +
556 + /* re-start the device instance */
557 + if (oce_start(dev) != DDI_SUCCESS) {
558 + goto irm_fail;
559 + }
560 +
561 + ret = ddi_intr_get_pri(dev->htable[0], &dev->intr_pri);
562 +
563 + if (ret != DDI_SUCCESS) {
564 + goto irm_fail;
565 + }
566 +
567 + (void) ddi_intr_get_cap(dev->htable[0], &dev->intr_cap);
568 +
569 + /* re-start the groups */
570 + for (i = 0; i < dev->num_rx_groups; i++) {
571 + mutex_enter(&dev->rx_group[i].grp_lock);
572 + ret = oce_start_group(&dev->rx_group[i], B_FALSE);
573 + if (ret == DDI_SUCCESS) {
574 + ret = oce_resume_group_rings(&dev->rx_group[i]);
575 + }
576 + mutex_exit(&dev->rx_group[i].grp_lock);
577 + if (ret != DDI_SUCCESS) {
578 + goto irm_fail;
579 + }
580 + }
581 + dev->state &= ~STATE_INTR_ADJUST;
582 + dev->suspended = B_FALSE;
583 + mutex_exit(&dev->dev_lock);
584 +
585 + /* Wakeup all Tx rings */
586 + for (i = 0; i < dev->tx_rings; i++) {
587 + mac_tx_ring_update(dev->mac_handle,
588 + dev->default_tx_rings[i].tx->handle);
589 + }
590 +
591 + return (DDI_SUCCESS);
592 +
593 +irm_fail:
594 + ddi_fm_service_impact(dev->dip, DDI_SERVICE_LOST);
595 + mutex_exit(&dev->dev_lock);
596 + return (DDI_FAILURE);
597 +}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX