xref: /titanic_50/usr/src/uts/common/io/hxge/hxge_main.c (revision 7257d1b4d25bfac0c802847390e98a464fd787ac)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * SunOs MT STREAMS Hydra 10Gb Ethernet Device Driver.
30  */
31 #include <hxge_impl.h>
32 #include <hxge_pfc.h>
33 
34 /*
35  * PSARC/2007/453 MSI-X interrupt limit override
36  * (This PSARC case is limited to MSI-X vectors
37  *  and SPARC platforms only).
38  */
39 #if defined(_BIG_ENDIAN)
40 uint32_t hxge_msi_enable = 2;
41 #else
42 uint32_t hxge_msi_enable = 1;
43 #endif
44 
45 /*
46  * Globals: tunable parameters (/etc/system or adb)
47  *
48  */
49 uint32_t hxge_rbr_size = HXGE_RBR_RBB_DEFAULT;
50 uint32_t hxge_rbr_spare_size = 0;
51 uint32_t hxge_rcr_size = HXGE_RCR_DEFAULT;
52 uint32_t hxge_tx_ring_size = HXGE_TX_RING_DEFAULT;
53 uint32_t hxge_bcopy_thresh = TX_BCOPY_MAX;
54 uint32_t hxge_dvma_thresh = TX_FASTDVMA_MIN;
55 uint32_t hxge_dma_stream_thresh = TX_STREAM_MIN;
56 uint32_t hxge_jumbo_mtu = TX_JUMBO_MTU;
57 boolean_t hxge_jumbo_enable = B_FALSE;
58 
59 static hxge_os_mutex_t hxgedebuglock;
60 static int hxge_debug_init = 0;
61 
62 /*
63  * Debugging flags:
64  *		hxge_no_tx_lb : transmit load balancing
65  *		hxge_tx_lb_policy: 0 - TCP/UDP port (default)
66  *				   1 - From the Stack
67  *				   2 - Destination IP Address
68  */
69 uint32_t hxge_no_tx_lb = 0;
70 uint32_t hxge_tx_lb_policy = HXGE_TX_LB_TCPUDP;
71 
72 /*
73  * Add tunable to reduce the amount of time spent in the
74  * ISR doing Rx Processing.
75  */
76 uint32_t hxge_max_rx_pkts = 1024;
77 
78 /*
79  * Tunables to manage the receive buffer blocks.
80  *
81  * hxge_rx_threshold_hi: copy all buffers.
82  * hxge_rx_bcopy_size_type: receive buffer block size type.
83  * hxge_rx_threshold_lo: copy only up to tunable block size type.
84  */
85 hxge_rxbuf_threshold_t hxge_rx_threshold_hi = HXGE_RX_COPY_6;
86 hxge_rxbuf_type_t hxge_rx_buf_size_type = RCR_PKTBUFSZ_0;
87 hxge_rxbuf_threshold_t hxge_rx_threshold_lo = HXGE_RX_COPY_3;
88 
89 rtrace_t hpi_rtracebuf;
90 
91 /*
92  * Function Prototypes
93  */
94 static int hxge_attach(dev_info_t *, ddi_attach_cmd_t);
95 static int hxge_detach(dev_info_t *, ddi_detach_cmd_t);
96 static void hxge_unattach(p_hxge_t);
97 
98 static hxge_status_t hxge_setup_system_dma_pages(p_hxge_t);
99 
100 static hxge_status_t hxge_setup_mutexes(p_hxge_t);
101 static void hxge_destroy_mutexes(p_hxge_t);
102 
103 static hxge_status_t hxge_map_regs(p_hxge_t hxgep);
104 static void hxge_unmap_regs(p_hxge_t hxgep);
105 
106 hxge_status_t hxge_add_intrs(p_hxge_t hxgep);
107 static hxge_status_t hxge_add_soft_intrs(p_hxge_t hxgep);
108 static void hxge_remove_intrs(p_hxge_t hxgep);
109 static void hxge_remove_soft_intrs(p_hxge_t hxgep);
110 static hxge_status_t hxge_add_intrs_adv(p_hxge_t hxgep);
111 static hxge_status_t hxge_add_intrs_adv_type(p_hxge_t, uint32_t);
112 static hxge_status_t hxge_add_intrs_adv_type_fix(p_hxge_t, uint32_t);
113 void hxge_intrs_enable(p_hxge_t hxgep);
114 static void hxge_intrs_disable(p_hxge_t hxgep);
115 static void hxge_suspend(p_hxge_t);
116 static hxge_status_t hxge_resume(p_hxge_t);
117 hxge_status_t hxge_setup_dev(p_hxge_t);
118 static void hxge_destroy_dev(p_hxge_t);
119 hxge_status_t hxge_alloc_mem_pool(p_hxge_t);
120 static void hxge_free_mem_pool(p_hxge_t);
121 static hxge_status_t hxge_alloc_rx_mem_pool(p_hxge_t);
122 static void hxge_free_rx_mem_pool(p_hxge_t);
123 static hxge_status_t hxge_alloc_tx_mem_pool(p_hxge_t);
124 static void hxge_free_tx_mem_pool(p_hxge_t);
125 static hxge_status_t hxge_dma_mem_alloc(p_hxge_t, dma_method_t,
126     struct ddi_dma_attr *, size_t, ddi_device_acc_attr_t *, uint_t,
127     p_hxge_dma_common_t);
128 static void hxge_dma_mem_free(p_hxge_dma_common_t);
129 static hxge_status_t hxge_alloc_rx_buf_dma(p_hxge_t, uint16_t,
130     p_hxge_dma_common_t *, size_t, size_t, uint32_t *);
131 static void hxge_free_rx_buf_dma(p_hxge_t, p_hxge_dma_common_t, uint32_t);
132 static hxge_status_t hxge_alloc_rx_cntl_dma(p_hxge_t, uint16_t,
133     p_hxge_dma_common_t *, size_t);
134 static void hxge_free_rx_cntl_dma(p_hxge_t, p_hxge_dma_common_t);
135 static hxge_status_t hxge_alloc_tx_buf_dma(p_hxge_t, uint16_t,
136     p_hxge_dma_common_t *, size_t, size_t, uint32_t *);
137 static void hxge_free_tx_buf_dma(p_hxge_t, p_hxge_dma_common_t, uint32_t);
138 static hxge_status_t hxge_alloc_tx_cntl_dma(p_hxge_t, uint16_t,
139     p_hxge_dma_common_t *, size_t);
140 static void hxge_free_tx_cntl_dma(p_hxge_t, p_hxge_dma_common_t);
141 static int hxge_init_common_dev(p_hxge_t);
142 static void hxge_uninit_common_dev(p_hxge_t);
143 
144 /*
145  * The next declarations are for the GLDv3 interface.
146  */
147 static int hxge_m_start(void *);
148 static void hxge_m_stop(void *);
149 static int hxge_m_unicst(void *, const uint8_t *);
150 static int hxge_m_multicst(void *, boolean_t, const uint8_t *);
151 static int hxge_m_promisc(void *, boolean_t);
152 static void hxge_m_ioctl(void *, queue_t *, mblk_t *);
153 static void hxge_m_resources(void *);
154 static hxge_status_t hxge_mac_register(p_hxge_t hxgep);
155 
156 static int hxge_m_mmac_add(void *arg, mac_multi_addr_t *maddr);
157 static int hxge_m_mmac_remove(void *arg, mac_addr_slot_t slot);
158 static int hxge_m_mmac_modify(void *arg, mac_multi_addr_t *maddr);
159 static int hxge_m_mmac_get(void *arg, mac_multi_addr_t *maddr);
160 static boolean_t hxge_m_getcapab(void *, mac_capab_t, void *);
161 
162 #define	HXGE_MAGIC	0x4E584745UL
163 #define	MAX_DUMP_SZ 256
164 
165 #define	HXGE_M_CALLBACK_FLAGS	(MC_RESOURCES | MC_IOCTL | MC_GETCAPAB)
166 
167 extern mblk_t *hxge_m_tx(void *arg, mblk_t *mp);
168 extern hxge_status_t hxge_pfc_set_default_mac_addr(p_hxge_t hxgep);
169 
170 static mac_callbacks_t hxge_m_callbacks = {
171 	HXGE_M_CALLBACK_FLAGS,
172 	hxge_m_stat,
173 	hxge_m_start,
174 	hxge_m_stop,
175 	hxge_m_promisc,
176 	hxge_m_multicst,
177 	hxge_m_unicst,
178 	hxge_m_tx,
179 	hxge_m_resources,
180 	hxge_m_ioctl,
181 	hxge_m_getcapab
182 };
183 
184 /* Enable debug messages as necessary. */
185 uint64_t hxge_debug_level = 0x0;
186 
187 /*
188  * This list contains the instance structures for the Hydra
189  * devices present in the system. The lock exists to guarantee
190  * mutually exclusive access to the list.
191  */
192 void *hxge_list = NULL;
193 void *hxge_hw_list = NULL;
194 hxge_os_mutex_t hxge_common_lock;
195 
196 extern uint64_t hpi_debug_level;
197 
198 extern hxge_status_t hxge_ldgv_init();
199 extern hxge_status_t hxge_ldgv_uninit();
200 extern hxge_status_t hxge_intr_ldgv_init();
201 extern void hxge_fm_init(p_hxge_t hxgep, ddi_device_acc_attr_t *reg_attr,
202     ddi_device_acc_attr_t *desc_attr, ddi_dma_attr_t *dma_attr);
203 extern void hxge_fm_fini(p_hxge_t hxgep);
204 
205 /*
206  * Count used to maintain the number of buffers being used
207  * by Hydra instances and loaned up to the upper layers.
208  */
209 uint32_t hxge_mblks_pending = 0;
210 
211 /*
212  * Device register access attributes for PIO.
213  */
214 static ddi_device_acc_attr_t hxge_dev_reg_acc_attr = {
215 	DDI_DEVICE_ATTR_V0,
216 	DDI_STRUCTURE_LE_ACC,
217 	DDI_STRICTORDER_ACC,
218 };
219 
220 /*
221  * Device descriptor access attributes for DMA.
222  */
223 static ddi_device_acc_attr_t hxge_dev_desc_dma_acc_attr = {
224 	DDI_DEVICE_ATTR_V0,
225 	DDI_STRUCTURE_LE_ACC,
226 	DDI_STRICTORDER_ACC
227 };
228 
229 /*
230  * Device buffer access attributes for DMA.
231  */
232 static ddi_device_acc_attr_t hxge_dev_buf_dma_acc_attr = {
233 	DDI_DEVICE_ATTR_V0,
234 	DDI_STRUCTURE_BE_ACC,
235 	DDI_STRICTORDER_ACC
236 };
237 
238 ddi_dma_attr_t hxge_desc_dma_attr = {
239 	DMA_ATTR_V0,		/* version number. */
240 	0,			/* low address */
241 	0xffffffffffffffff,	/* high address */
242 	0xffffffffffffffff,	/* address counter max */
243 	0x100000,		/* alignment */
244 	0xfc00fc,		/* dlim_burstsizes */
245 	0x1,			/* minimum transfer size */
246 	0xffffffffffffffff,	/* maximum transfer size */
247 	0xffffffffffffffff,	/* maximum segment size */
248 	1,			/* scatter/gather list length */
249 	(unsigned int)1,	/* granularity */
250 	0			/* attribute flags */
251 };
252 
253 ddi_dma_attr_t hxge_tx_dma_attr = {
254 	DMA_ATTR_V0,		/* version number. */
255 	0,			/* low address */
256 	0xffffffffffffffff,	/* high address */
257 	0xffffffffffffffff,	/* address counter max */
258 #if defined(_BIG_ENDIAN)
259 	0x2000,			/* alignment */
260 #else
261 	0x1000,			/* alignment */
262 #endif
263 	0xfc00fc,		/* dlim_burstsizes */
264 	0x1,			/* minimum transfer size */
265 	0xffffffffffffffff,	/* maximum transfer size */
266 	0xffffffffffffffff,	/* maximum segment size */
267 	5,			/* scatter/gather list length */
268 	(unsigned int)1,	/* granularity */
269 	0			/* attribute flags */
270 };
271 
272 ddi_dma_attr_t hxge_rx_dma_attr = {
273 	DMA_ATTR_V0,		/* version number. */
274 	0,			/* low address */
275 	0xffffffffffffffff,	/* high address */
276 	0xffffffffffffffff,	/* address counter max */
277 	0x10000,		/* alignment */
278 	0xfc00fc,		/* dlim_burstsizes */
279 	0x1,			/* minimum transfer size */
280 	0xffffffffffffffff,	/* maximum transfer size */
281 	0xffffffffffffffff,	/* maximum segment size */
282 	1,			/* scatter/gather list length */
283 	(unsigned int)1,	/* granularity */
284 	DDI_DMA_RELAXED_ORDERING /* attribute flags */
285 };
286 
287 ddi_dma_lim_t hxge_dma_limits = {
288 	(uint_t)0,		/* dlim_addr_lo */
289 	(uint_t)0xffffffff,	/* dlim_addr_hi */
290 	(uint_t)0xffffffff,	/* dlim_cntr_max */
291 	(uint_t)0xfc00fc,	/* dlim_burstsizes for 32 and 64 bit xfers */
292 	0x1,			/* dlim_minxfer */
293 	1024			/* dlim_speed */
294 };
295 
296 dma_method_t hxge_force_dma = DVMA;
297 
298 /*
299  * dma chunk sizes.
300  *
301  * Try to allocate the largest possible size
302  * so that fewer number of dma chunks would be managed
303  */
304 size_t alloc_sizes[] = {
305     0x1000, 0x2000, 0x4000, 0x8000,
306     0x10000, 0x20000, 0x40000, 0x80000,
307     0x100000, 0x200000, 0x400000, 0x800000, 0x1000000
308 };
309 
310 /*
311  * Translate "dev_t" to a pointer to the associated "dev_info_t".
312  */
313 static int
314 hxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
315 {
316 	p_hxge_t	hxgep = NULL;
317 	int		instance;
318 	int		status = DDI_SUCCESS;
319 
320 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_attach"));
321 
322 	/*
323 	 * Get the device instance since we'll need to setup or retrieve a soft
324 	 * state for this instance.
325 	 */
326 	instance = ddi_get_instance(dip);
327 
328 	switch (cmd) {
329 	case DDI_ATTACH:
330 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_ATTACH"));
331 		break;
332 
333 	case DDI_RESUME:
334 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_RESUME"));
335 		hxgep = (p_hxge_t)ddi_get_soft_state(hxge_list, instance);
336 		if (hxgep == NULL) {
337 			status = DDI_FAILURE;
338 			break;
339 		}
340 		if (hxgep->dip != dip) {
341 			status = DDI_FAILURE;
342 			break;
343 		}
344 		if (hxgep->suspended == DDI_PM_SUSPEND) {
345 			status = ddi_dev_is_needed(hxgep->dip, 0, 1);
346 		} else {
347 			(void) hxge_resume(hxgep);
348 		}
349 		goto hxge_attach_exit;
350 
351 	case DDI_PM_RESUME:
352 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_PM_RESUME"));
353 		hxgep = (p_hxge_t)ddi_get_soft_state(hxge_list, instance);
354 		if (hxgep == NULL) {
355 			status = DDI_FAILURE;
356 			break;
357 		}
358 		if (hxgep->dip != dip) {
359 			status = DDI_FAILURE;
360 			break;
361 		}
362 		(void) hxge_resume(hxgep);
363 		goto hxge_attach_exit;
364 
365 	default:
366 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing unknown"));
367 		status = DDI_FAILURE;
368 		goto hxge_attach_exit;
369 	}
370 
371 	if (ddi_soft_state_zalloc(hxge_list, instance) == DDI_FAILURE) {
372 		status = DDI_FAILURE;
373 		HXGE_ERROR_MSG((hxgep, DDI_CTL,
374 		    "ddi_soft_state_zalloc failed"));
375 		goto hxge_attach_exit;
376 	}
377 
378 	hxgep = ddi_get_soft_state(hxge_list, instance);
379 	if (hxgep == NULL) {
380 		status = HXGE_ERROR;
381 		HXGE_ERROR_MSG((hxgep, DDI_CTL,
382 		    "ddi_get_soft_state failed"));
383 		goto hxge_attach_fail2;
384 	}
385 
386 	hxgep->drv_state = 0;
387 	hxgep->dip = dip;
388 	hxgep->instance = instance;
389 	hxgep->p_dip = ddi_get_parent(dip);
390 	hxgep->hxge_debug_level = hxge_debug_level;
391 	hpi_debug_level = hxge_debug_level;
392 
393 	hxge_fm_init(hxgep, &hxge_dev_reg_acc_attr, &hxge_dev_desc_dma_acc_attr,
394 	    &hxge_rx_dma_attr);
395 
396 	status = hxge_map_regs(hxgep);
397 	if (status != HXGE_OK) {
398 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "hxge_map_regs failed"));
399 		goto hxge_attach_fail3;
400 	}
401 
402 	status = hxge_init_common_dev(hxgep);
403 	if (status != HXGE_OK) {
404 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
405 		    "hxge_init_common_dev failed"));
406 		goto hxge_attach_fail4;
407 	}
408 
409 	/*
410 	 * Setup the Ndd parameters for this instance.
411 	 */
412 	hxge_init_param(hxgep);
413 
414 	/*
415 	 * Setup Register Tracing Buffer.
416 	 */
417 	hpi_rtrace_buf_init((rtrace_t *)&hpi_rtracebuf);
418 
419 	/* init stats ptr */
420 	hxge_init_statsp(hxgep);
421 
422 	status = hxge_get_config_properties(hxgep);
423 	if (status != HXGE_OK) {
424 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "get_hw create failed"));
425 		goto hxge_attach_fail;
426 	}
427 
428 	/*
429 	 * Setup the Kstats for the driver.
430 	 */
431 	hxge_setup_kstats(hxgep);
432 	hxge_setup_param(hxgep);
433 
434 	status = hxge_setup_system_dma_pages(hxgep);
435 	if (status != HXGE_OK) {
436 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "set dma page failed"));
437 		goto hxge_attach_fail;
438 	}
439 
440 	hxge_hw_id_init(hxgep);
441 	hxge_hw_init_niu_common(hxgep);
442 
443 	status = hxge_setup_mutexes(hxgep);
444 	if (status != HXGE_OK) {
445 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "set mutex failed"));
446 		goto hxge_attach_fail;
447 	}
448 
449 	status = hxge_setup_dev(hxgep);
450 	if (status != DDI_SUCCESS) {
451 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "set dev failed"));
452 		goto hxge_attach_fail;
453 	}
454 
455 	status = hxge_add_intrs(hxgep);
456 	if (status != DDI_SUCCESS) {
457 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "add_intr failed"));
458 		goto hxge_attach_fail;
459 	}
460 
461 	status = hxge_add_soft_intrs(hxgep);
462 	if (status != DDI_SUCCESS) {
463 		HXGE_DEBUG_MSG((hxgep, HXGE_ERR_CTL, "add_soft_intr failed"));
464 		goto hxge_attach_fail;
465 	}
466 
467 	/*
468 	 * Enable interrupts.
469 	 */
470 	hxge_intrs_enable(hxgep);
471 
472 	if ((status = hxge_mac_register(hxgep)) != HXGE_OK) {
473 		HXGE_DEBUG_MSG((hxgep, DDI_CTL,
474 		    "unable to register to mac layer (%d)", status));
475 		goto hxge_attach_fail;
476 	}
477 	mac_link_update(hxgep->mach, LINK_STATE_UP);
478 
479 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "registered to mac (instance %d)",
480 	    instance));
481 
482 	goto hxge_attach_exit;
483 
484 hxge_attach_fail:
485 	hxge_unattach(hxgep);
486 	goto hxge_attach_fail1;
487 
488 hxge_attach_fail5:
489 	/*
490 	 * Tear down the ndd parameters setup.
491 	 */
492 	hxge_destroy_param(hxgep);
493 
494 	/*
495 	 * Tear down the kstat setup.
496 	 */
497 	hxge_destroy_kstats(hxgep);
498 
499 hxge_attach_fail4:
500 	if (hxgep->hxge_hw_p) {
501 		hxge_uninit_common_dev(hxgep);
502 		hxgep->hxge_hw_p = NULL;
503 	}
504 hxge_attach_fail3:
505 	/*
506 	 * Unmap the register setup.
507 	 */
508 	hxge_unmap_regs(hxgep);
509 
510 	hxge_fm_fini(hxgep);
511 
512 hxge_attach_fail2:
513 	ddi_soft_state_free(hxge_list, hxgep->instance);
514 
515 hxge_attach_fail1:
516 	if (status != HXGE_OK)
517 		status = (HXGE_ERROR | HXGE_DDI_FAILED);
518 	hxgep = NULL;
519 
520 hxge_attach_exit:
521 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_attach status = 0x%08x",
522 	    status));
523 
524 	return (status);
525 }
526 
527 static int
528 hxge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
529 {
530 	int		status = DDI_SUCCESS;
531 	int		instance;
532 	p_hxge_t	hxgep = NULL;
533 
534 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_detach"));
535 	instance = ddi_get_instance(dip);
536 	hxgep = ddi_get_soft_state(hxge_list, instance);
537 	if (hxgep == NULL) {
538 		status = DDI_FAILURE;
539 		goto hxge_detach_exit;
540 	}
541 
542 	switch (cmd) {
543 	case DDI_DETACH:
544 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_DETACH"));
545 		break;
546 
547 	case DDI_PM_SUSPEND:
548 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_PM_SUSPEND"));
549 		hxgep->suspended = DDI_PM_SUSPEND;
550 		hxge_suspend(hxgep);
551 		break;
552 
553 	case DDI_SUSPEND:
554 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_SUSPEND"));
555 		if (hxgep->suspended != DDI_PM_SUSPEND) {
556 			hxgep->suspended = DDI_SUSPEND;
557 			hxge_suspend(hxgep);
558 		}
559 		break;
560 
561 	default:
562 		status = DDI_FAILURE;
563 		break;
564 	}
565 
566 	if (cmd != DDI_DETACH)
567 		goto hxge_detach_exit;
568 
569 	/*
570 	 * Stop the xcvr polling.
571 	 */
572 	hxgep->suspended = cmd;
573 
574 	if (hxgep->mach && (status = mac_unregister(hxgep->mach)) != 0) {
575 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
576 		    "<== hxge_detach status = 0x%08X", status));
577 		return (DDI_FAILURE);
578 	}
579 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
580 	    "<== hxge_detach (mac_unregister) status = 0x%08X", status));
581 
582 	hxge_unattach(hxgep);
583 	hxgep = NULL;
584 
585 hxge_detach_exit:
586 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_detach status = 0x%08X",
587 	    status));
588 
589 	return (status);
590 }
591 
592 static void
593 hxge_unattach(p_hxge_t hxgep)
594 {
595 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_unattach"));
596 
597 	if (hxgep == NULL || hxgep->dev_regs == NULL) {
598 		return;
599 	}
600 
601 	if (hxgep->hxge_hw_p) {
602 		hxge_uninit_common_dev(hxgep);
603 		hxgep->hxge_hw_p = NULL;
604 	}
605 
606 	if (hxgep->hxge_timerid) {
607 		hxge_stop_timer(hxgep, hxgep->hxge_timerid);
608 		hxgep->hxge_timerid = 0;
609 	}
610 
611 	/* Stop any further interrupts. */
612 	hxge_remove_intrs(hxgep);
613 
614 	/* Remove soft interrups */
615 	hxge_remove_soft_intrs(hxgep);
616 
617 	/* Stop the device and free resources. */
618 	hxge_destroy_dev(hxgep);
619 
620 	/* Tear down the ndd parameters setup. */
621 	hxge_destroy_param(hxgep);
622 
623 	/* Tear down the kstat setup. */
624 	hxge_destroy_kstats(hxgep);
625 
626 	/* Destroy all mutexes.  */
627 	hxge_destroy_mutexes(hxgep);
628 
629 	/*
630 	 * Remove the list of ndd parameters which were setup during attach.
631 	 */
632 	if (hxgep->dip) {
633 		HXGE_DEBUG_MSG((hxgep, OBP_CTL,
634 		    " hxge_unattach: remove all properties"));
635 		(void) ddi_prop_remove_all(hxgep->dip);
636 	}
637 
638 	/*
639 	 * Unmap the register setup.
640 	 */
641 	hxge_unmap_regs(hxgep);
642 
643 	hxge_fm_fini(hxgep);
644 
645 	/*
646 	 * Free the soft state data structures allocated with this instance.
647 	 */
648 	ddi_soft_state_free(hxge_list, hxgep->instance);
649 
650 	HXGE_DEBUG_MSG((NULL, DDI_CTL, "<== hxge_unattach"));
651 }
652 
653 static hxge_status_t
654 hxge_map_regs(p_hxge_t hxgep)
655 {
656 	int		ddi_status = DDI_SUCCESS;
657 	p_dev_regs_t	dev_regs;
658 
659 #ifdef	HXGE_DEBUG
660 	char		*sysname;
661 #endif
662 
663 	off_t		regsize;
664 	hxge_status_t	status = HXGE_OK;
665 	int		nregs;
666 
667 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_map_regs"));
668 
669 	if (ddi_dev_nregs(hxgep->dip, &nregs) != DDI_SUCCESS)
670 		return (HXGE_ERROR);
671 
672 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "hxge_map_regs: nregs: %d", nregs));
673 
674 	hxgep->dev_regs = NULL;
675 	dev_regs = KMEM_ZALLOC(sizeof (dev_regs_t), KM_SLEEP);
676 	dev_regs->hxge_regh = NULL;
677 	dev_regs->hxge_pciregh = NULL;
678 	dev_regs->hxge_msix_regh = NULL;
679 
680 	(void) ddi_dev_regsize(hxgep->dip, 0, &regsize);
681 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
682 	    "hxge_map_regs: pci config size 0x%x", regsize));
683 
684 	ddi_status = ddi_regs_map_setup(hxgep->dip, 0,
685 	    (caddr_t *)&(dev_regs->hxge_pciregp), 0, 0,
686 	    &hxge_dev_reg_acc_attr, &dev_regs->hxge_pciregh);
687 	if (ddi_status != DDI_SUCCESS) {
688 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
689 		    "ddi_map_regs, hxge bus config regs failed"));
690 		goto hxge_map_regs_fail0;
691 	}
692 
693 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
694 	    "hxge_map_reg: PCI config addr 0x%0llx handle 0x%0llx",
695 	    dev_regs->hxge_pciregp,
696 	    dev_regs->hxge_pciregh));
697 
698 	(void) ddi_dev_regsize(hxgep->dip, 1, &regsize);
699 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
700 	    "hxge_map_regs: pio size 0x%x", regsize));
701 
702 	/* set up the device mapped register */
703 	ddi_status = ddi_regs_map_setup(hxgep->dip, 1,
704 	    (caddr_t *)&(dev_regs->hxge_regp), 0, 0,
705 	    &hxge_dev_reg_acc_attr, &dev_regs->hxge_regh);
706 
707 	if (ddi_status != DDI_SUCCESS) {
708 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
709 		    "ddi_map_regs for Hydra global reg failed"));
710 		goto hxge_map_regs_fail1;
711 	}
712 
713 	/* set up the msi/msi-x mapped register */
714 	(void) ddi_dev_regsize(hxgep->dip, 2, &regsize);
715 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
716 	    "hxge_map_regs: msix size 0x%x", regsize));
717 
718 	ddi_status = ddi_regs_map_setup(hxgep->dip, 2,
719 	    (caddr_t *)&(dev_regs->hxge_msix_regp), 0, 0,
720 	    &hxge_dev_reg_acc_attr, &dev_regs->hxge_msix_regh);
721 
722 	if (ddi_status != DDI_SUCCESS) {
723 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
724 		    "ddi_map_regs for msi reg failed"));
725 		goto hxge_map_regs_fail2;
726 	}
727 
728 	hxgep->dev_regs = dev_regs;
729 
730 	HPI_PCI_ACC_HANDLE_SET(hxgep, dev_regs->hxge_pciregh);
731 	HPI_PCI_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_pciregp);
732 	HPI_MSI_ACC_HANDLE_SET(hxgep, dev_regs->hxge_msix_regh);
733 	HPI_MSI_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_msix_regp);
734 
735 	HPI_ACC_HANDLE_SET(hxgep, dev_regs->hxge_regh);
736 	HPI_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_regp);
737 
738 	HPI_REG_ACC_HANDLE_SET(hxgep, dev_regs->hxge_regh);
739 	HPI_REG_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_regp);
740 
741 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "hxge_map_reg: hardware addr 0x%0llx "
742 	    " handle 0x%0llx", dev_regs->hxge_regp, dev_regs->hxge_regh));
743 
744 	goto hxge_map_regs_exit;
745 
746 hxge_map_regs_fail3:
747 	if (dev_regs->hxge_msix_regh) {
748 		ddi_regs_map_free(&dev_regs->hxge_msix_regh);
749 	}
750 
751 hxge_map_regs_fail2:
752 	if (dev_regs->hxge_regh) {
753 		ddi_regs_map_free(&dev_regs->hxge_regh);
754 	}
755 
756 hxge_map_regs_fail1:
757 	if (dev_regs->hxge_pciregh) {
758 		ddi_regs_map_free(&dev_regs->hxge_pciregh);
759 	}
760 
761 hxge_map_regs_fail0:
762 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "Freeing register set memory"));
763 	kmem_free(dev_regs, sizeof (dev_regs_t));
764 
765 hxge_map_regs_exit:
766 	if (ddi_status != DDI_SUCCESS)
767 		status |= (HXGE_ERROR | HXGE_DDI_FAILED);
768 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_map_regs"));
769 	return (status);
770 }
771 
772 static void
773 hxge_unmap_regs(p_hxge_t hxgep)
774 {
775 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_unmap_regs"));
776 	if (hxgep->dev_regs) {
777 		if (hxgep->dev_regs->hxge_pciregh) {
778 			HXGE_DEBUG_MSG((hxgep, DDI_CTL,
779 			    "==> hxge_unmap_regs: bus"));
780 			ddi_regs_map_free(&hxgep->dev_regs->hxge_pciregh);
781 			hxgep->dev_regs->hxge_pciregh = NULL;
782 		}
783 
784 		if (hxgep->dev_regs->hxge_regh) {
785 			HXGE_DEBUG_MSG((hxgep, DDI_CTL,
786 			    "==> hxge_unmap_regs: device registers"));
787 			ddi_regs_map_free(&hxgep->dev_regs->hxge_regh);
788 			hxgep->dev_regs->hxge_regh = NULL;
789 		}
790 
791 		if (hxgep->dev_regs->hxge_msix_regh) {
792 			HXGE_DEBUG_MSG((hxgep, DDI_CTL,
793 			    "==> hxge_unmap_regs: device interrupts"));
794 			ddi_regs_map_free(&hxgep->dev_regs->hxge_msix_regh);
795 			hxgep->dev_regs->hxge_msix_regh = NULL;
796 		}
797 		kmem_free(hxgep->dev_regs, sizeof (dev_regs_t));
798 		hxgep->dev_regs = NULL;
799 	}
800 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_unmap_regs"));
801 }
802 
803 static hxge_status_t
804 hxge_setup_mutexes(p_hxge_t hxgep)
805 {
806 	int		ddi_status = DDI_SUCCESS;
807 	hxge_status_t	status = HXGE_OK;
808 
809 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_setup_mutexes"));
810 
811 	/*
812 	 * Get the interrupt cookie so the mutexes can be Initialised.
813 	 */
814 	ddi_status = ddi_get_iblock_cookie(hxgep->dip, 0,
815 	    &hxgep->interrupt_cookie);
816 
817 	if (ddi_status != DDI_SUCCESS) {
818 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
819 		    "<== hxge_setup_mutexes: failed 0x%x", ddi_status));
820 		goto hxge_setup_mutexes_exit;
821 	}
822 
823 	/*
824 	 * Initialize mutex's for this device.
825 	 */
826 	MUTEX_INIT(hxgep->genlock, NULL,
827 	    MUTEX_DRIVER, (void *) hxgep->interrupt_cookie);
828 	MUTEX_INIT(&hxgep->ouraddr_lock, NULL,
829 	    MUTEX_DRIVER, (void *) hxgep->interrupt_cookie);
830 	RW_INIT(&hxgep->filter_lock, NULL,
831 	    RW_DRIVER, (void *) hxgep->interrupt_cookie);
832 
833 hxge_setup_mutexes_exit:
834 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
835 	    "<== hxge_setup_mutexes status = %x", status));
836 
837 	if (ddi_status != DDI_SUCCESS)
838 		status |= (HXGE_ERROR | HXGE_DDI_FAILED);
839 
840 	return (status);
841 }
842 
843 static void
844 hxge_destroy_mutexes(p_hxge_t hxgep)
845 {
846 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_destroy_mutexes"));
847 	RW_DESTROY(&hxgep->filter_lock);
848 	MUTEX_DESTROY(&hxgep->ouraddr_lock);
849 	MUTEX_DESTROY(hxgep->genlock);
850 
851 	if (hxge_debug_init == 1) {
852 		MUTEX_DESTROY(&hxgedebuglock);
853 		hxge_debug_init = 0;
854 	}
855 
856 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_destroy_mutexes"));
857 }
858 
859 hxge_status_t
860 hxge_init(p_hxge_t hxgep)
861 {
862 	hxge_status_t status = HXGE_OK;
863 
864 	HXGE_DEBUG_MSG((hxgep, STR_CTL, "==> hxge_init"));
865 
866 	if (hxgep->drv_state & STATE_HW_INITIALIZED) {
867 		return (status);
868 	}
869 
870 	/*
871 	 * Allocate system memory for the receive/transmit buffer blocks and
872 	 * receive/transmit descriptor rings.
873 	 */
874 	status = hxge_alloc_mem_pool(hxgep);
875 	if (status != HXGE_OK) {
876 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "alloc mem failed\n"));
877 		goto hxge_init_fail1;
878 	}
879 
880 	/*
881 	 * Initialize and enable TXDMA channels.
882 	 */
883 	status = hxge_init_txdma_channels(hxgep);
884 	if (status != HXGE_OK) {
885 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init txdma failed\n"));
886 		goto hxge_init_fail3;
887 	}
888 
889 	/*
890 	 * Initialize and enable RXDMA channels.
891 	 */
892 	status = hxge_init_rxdma_channels(hxgep);
893 	if (status != HXGE_OK) {
894 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init rxdma failed\n"));
895 		goto hxge_init_fail4;
896 	}
897 
898 	/*
899 	 * Initialize TCAM
900 	 */
901 	status = hxge_classify_init(hxgep);
902 	if (status != HXGE_OK) {
903 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init classify failed\n"));
904 		goto hxge_init_fail5;
905 	}
906 
907 	/*
908 	 * Initialize the VMAC block.
909 	 */
910 	status = hxge_vmac_init(hxgep);
911 	if (status != HXGE_OK) {
912 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init MAC failed\n"));
913 		goto hxge_init_fail5;
914 	}
915 
916 	/* Bringup - this may be unnecessary when PXE and FCODE available */
917 	status = hxge_pfc_set_default_mac_addr(hxgep);
918 	if (status != HXGE_OK) {
919 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
920 		    "Default Address Failure\n"));
921 		goto hxge_init_fail5;
922 	}
923 
924 	hxge_intrs_enable(hxgep);
925 
926 	/*
927 	 * Enable hardware interrupts.
928 	 */
929 	hxge_intr_hw_enable(hxgep);
930 	hxgep->drv_state |= STATE_HW_INITIALIZED;
931 
932 	goto hxge_init_exit;
933 
934 hxge_init_fail5:
935 	hxge_uninit_rxdma_channels(hxgep);
936 hxge_init_fail4:
937 	hxge_uninit_txdma_channels(hxgep);
938 hxge_init_fail3:
939 	hxge_free_mem_pool(hxgep);
940 hxge_init_fail1:
941 	HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
942 	    "<== hxge_init status (failed) = 0x%08x", status));
943 	return (status);
944 
945 hxge_init_exit:
946 
947 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_init status = 0x%08x",
948 	    status));
949 
950 	return (status);
951 }
952 
953 timeout_id_t
954 hxge_start_timer(p_hxge_t hxgep, fptrv_t func, int msec)
955 {
956 	if ((hxgep->suspended == 0) || (hxgep->suspended == DDI_RESUME)) {
957 		return (timeout(func, (caddr_t)hxgep,
958 		    drv_usectohz(1000 * msec)));
959 	}
960 	return (NULL);
961 }
962 
963 /*ARGSUSED*/
964 void
965 hxge_stop_timer(p_hxge_t hxgep, timeout_id_t timerid)
966 {
967 	if (timerid) {
968 		(void) untimeout(timerid);
969 	}
970 }
971 
972 void
973 hxge_uninit(p_hxge_t hxgep)
974 {
975 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_uninit"));
976 
977 	if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) {
978 		HXGE_DEBUG_MSG((hxgep, DDI_CTL,
979 		    "==> hxge_uninit: not initialized"));
980 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_uninit"));
981 		return;
982 	}
983 
984 	/* Stop timer */
985 	if (hxgep->hxge_timerid) {
986 		hxge_stop_timer(hxgep, hxgep->hxge_timerid);
987 		hxgep->hxge_timerid = 0;
988 	}
989 
990 	(void) hxge_intr_hw_disable(hxgep);
991 
992 	/* Reset the receive VMAC side.  */
993 	(void) hxge_rx_vmac_disable(hxgep);
994 
995 	/* Free classification resources */
996 	(void) hxge_classify_uninit(hxgep);
997 
998 	/* Reset the transmit/receive DMA side.  */
999 	(void) hxge_txdma_hw_mode(hxgep, HXGE_DMA_STOP);
1000 	(void) hxge_rxdma_hw_mode(hxgep, HXGE_DMA_STOP);
1001 
1002 	hxge_uninit_txdma_channels(hxgep);
1003 	hxge_uninit_rxdma_channels(hxgep);
1004 
1005 	/* Reset the transmit VMAC side.  */
1006 	(void) hxge_tx_vmac_disable(hxgep);
1007 
1008 	hxge_free_mem_pool(hxgep);
1009 
1010 	hxgep->drv_state &= ~STATE_HW_INITIALIZED;
1011 
1012 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_uninit"));
1013 }
1014 
1015 void
1016 hxge_get64(p_hxge_t hxgep, p_mblk_t mp)
1017 {
1018 #if defined(__i386)
1019 	size_t		reg;
1020 #else
1021 	uint64_t	reg;
1022 #endif
1023 	uint64_t	regdata;
1024 	int		i, retry;
1025 
1026 	bcopy((char *)mp->b_rptr, (char *)&reg, sizeof (uint64_t));
1027 	regdata = 0;
1028 	retry = 1;
1029 
1030 	for (i = 0; i < retry; i++) {
1031 		HXGE_REG_RD64(hxgep->hpi_handle, reg, &regdata);
1032 	}
1033 	bcopy((char *)&regdata, (char *)mp->b_rptr, sizeof (uint64_t));
1034 }
1035 
1036 void
1037 hxge_put64(p_hxge_t hxgep, p_mblk_t mp)
1038 {
1039 #if defined(__i386)
1040 	size_t		reg;
1041 #else
1042 	uint64_t	reg;
1043 #endif
1044 	uint64_t	buf[2];
1045 
1046 	bcopy((char *)mp->b_rptr, (char *)&buf[0], 2 * sizeof (uint64_t));
1047 #if defined(__i386)
1048 	reg = (size_t)buf[0];
1049 #else
1050 	reg = buf[0];
1051 #endif
1052 
1053 	HXGE_HPI_PIO_WRITE64(hxgep->hpi_handle, reg, buf[1]);
1054 }
1055 
1056 /*ARGSUSED*/
1057 /*VARARGS*/
1058 void
1059 hxge_debug_msg(p_hxge_t hxgep, uint64_t level, char *fmt, ...)
1060 {
1061 	char		msg_buffer[1048];
1062 	char		prefix_buffer[32];
1063 	int		instance;
1064 	uint64_t	debug_level;
1065 	int		cmn_level = CE_CONT;
1066 	va_list		ap;
1067 
1068 	debug_level = (hxgep == NULL) ? hxge_debug_level :
1069 	    hxgep->hxge_debug_level;
1070 
1071 	if ((level & debug_level) || (level == HXGE_NOTE) ||
1072 	    (level == HXGE_ERR_CTL)) {
1073 		/* do the msg processing */
1074 		if (hxge_debug_init == 0) {
1075 			MUTEX_INIT(&hxgedebuglock, NULL, MUTEX_DRIVER, NULL);
1076 			hxge_debug_init = 1;
1077 		}
1078 
1079 		MUTEX_ENTER(&hxgedebuglock);
1080 
1081 		if ((level & HXGE_NOTE)) {
1082 			cmn_level = CE_NOTE;
1083 		}
1084 
1085 		if (level & HXGE_ERR_CTL) {
1086 			cmn_level = CE_WARN;
1087 		}
1088 
1089 		va_start(ap, fmt);
1090 		(void) vsprintf(msg_buffer, fmt, ap);
1091 		va_end(ap);
1092 
1093 		if (hxgep == NULL) {
1094 			instance = -1;
1095 			(void) sprintf(prefix_buffer, "%s :", "hxge");
1096 		} else {
1097 			instance = hxgep->instance;
1098 			(void) sprintf(prefix_buffer,
1099 			    "%s%d :", "hxge", instance);
1100 		}
1101 
1102 		MUTEX_EXIT(&hxgedebuglock);
1103 		cmn_err(cmn_level, "%s %s\n", prefix_buffer, msg_buffer);
1104 	}
1105 }
1106 
1107 char *
1108 hxge_dump_packet(char *addr, int size)
1109 {
1110 	uchar_t		*ap = (uchar_t *)addr;
1111 	int		i;
1112 	static char	etherbuf[1024];
1113 	char		*cp = etherbuf;
1114 	char		digits[] = "0123456789abcdef";
1115 
1116 	if (!size)
1117 		size = 60;
1118 
1119 	if (size > MAX_DUMP_SZ) {
1120 		/* Dump the leading bytes */
1121 		for (i = 0; i < MAX_DUMP_SZ / 2; i++) {
1122 			if (*ap > 0x0f)
1123 				*cp++ = digits[*ap >> 4];
1124 			*cp++ = digits[*ap++ & 0xf];
1125 			*cp++ = ':';
1126 		}
1127 		for (i = 0; i < 20; i++)
1128 			*cp++ = '.';
1129 		/* Dump the last MAX_DUMP_SZ/2 bytes */
1130 		ap = (uchar_t *)(addr + (size - MAX_DUMP_SZ / 2));
1131 		for (i = 0; i < MAX_DUMP_SZ / 2; i++) {
1132 			if (*ap > 0x0f)
1133 				*cp++ = digits[*ap >> 4];
1134 			*cp++ = digits[*ap++ & 0xf];
1135 			*cp++ = ':';
1136 		}
1137 	} else {
1138 		for (i = 0; i < size; i++) {
1139 			if (*ap > 0x0f)
1140 				*cp++ = digits[*ap >> 4];
1141 			*cp++ = digits[*ap++ & 0xf];
1142 			*cp++ = ':';
1143 		}
1144 	}
1145 	*--cp = 0;
1146 	return (etherbuf);
1147 }
1148 
1149 static void
1150 hxge_suspend(p_hxge_t hxgep)
1151 {
1152 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_suspend"));
1153 
1154 	hxge_intrs_disable(hxgep);
1155 	hxge_destroy_dev(hxgep);
1156 
1157 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_suspend"));
1158 }
1159 
1160 static hxge_status_t
1161 hxge_resume(p_hxge_t hxgep)
1162 {
1163 	hxge_status_t status = HXGE_OK;
1164 
1165 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_resume"));
1166 	hxgep->suspended = DDI_RESUME;
1167 
1168 	(void) hxge_rxdma_hw_mode(hxgep, HXGE_DMA_START);
1169 	(void) hxge_txdma_hw_mode(hxgep, HXGE_DMA_START);
1170 
1171 	(void) hxge_rx_vmac_enable(hxgep);
1172 	(void) hxge_tx_vmac_enable(hxgep);
1173 
1174 	hxge_intrs_enable(hxgep);
1175 
1176 	hxgep->suspended = 0;
1177 
1178 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
1179 	    "<== hxge_resume status = 0x%x", status));
1180 
1181 	return (status);
1182 }
1183 
1184 hxge_status_t
1185 hxge_setup_dev(p_hxge_t hxgep)
1186 {
1187 	hxge_status_t status = HXGE_OK;
1188 
1189 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_setup_dev"));
1190 
1191 	status = hxge_link_init(hxgep);
1192 	if (fm_check_acc_handle(hxgep->dev_regs->hxge_regh) != DDI_FM_OK) {
1193 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
1194 		    "Bad register acc handle"));
1195 		status = HXGE_ERROR;
1196 	}
1197 
1198 	if (status != HXGE_OK) {
1199 		HXGE_DEBUG_MSG((hxgep, MAC_CTL,
1200 		    " hxge_setup_dev status (link init 0x%08x)", status));
1201 		goto hxge_setup_dev_exit;
1202 	}
1203 
1204 hxge_setup_dev_exit:
1205 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
1206 	    "<== hxge_setup_dev status = 0x%08x", status));
1207 
1208 	return (status);
1209 }
1210 
1211 static void
1212 hxge_destroy_dev(p_hxge_t hxgep)
1213 {
1214 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_destroy_dev"));
1215 
1216 	(void) hxge_hw_stop(hxgep);
1217 
1218 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_destroy_dev"));
1219 }
1220 
1221 static hxge_status_t
1222 hxge_setup_system_dma_pages(p_hxge_t hxgep)
1223 {
1224 	int			ddi_status = DDI_SUCCESS;
1225 	uint_t			count;
1226 	ddi_dma_cookie_t	cookie;
1227 	uint_t			iommu_pagesize;
1228 	hxge_status_t		status = HXGE_OK;
1229 
1230 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_setup_system_dma_pages"));
1231 
1232 	hxgep->sys_page_sz = ddi_ptob(hxgep->dip, (ulong_t)1);
1233 	iommu_pagesize = dvma_pagesize(hxgep->dip);
1234 
1235 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
1236 	    " hxge_setup_system_dma_pages: page %d (ddi_ptob %d) "
1237 	    " default_block_size %d iommu_pagesize %d",
1238 	    hxgep->sys_page_sz, ddi_ptob(hxgep->dip, (ulong_t)1),
1239 	    hxgep->rx_default_block_size, iommu_pagesize));
1240 
1241 	if (iommu_pagesize != 0) {
1242 		if (hxgep->sys_page_sz == iommu_pagesize) {
1243 			/* Hydra support up to 8K pages */
1244 			if (iommu_pagesize > 0x2000)
1245 				hxgep->sys_page_sz = 0x2000;
1246 		} else {
1247 			if (hxgep->sys_page_sz > iommu_pagesize)
1248 				hxgep->sys_page_sz = iommu_pagesize;
1249 		}
1250 	}
1251 
1252 	hxgep->sys_page_mask = ~(hxgep->sys_page_sz - 1);
1253 
1254 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
1255 	    "==> hxge_setup_system_dma_pages: page %d (ddi_ptob %d) "
1256 	    "default_block_size %d page mask %d",
1257 	    hxgep->sys_page_sz, ddi_ptob(hxgep->dip, (ulong_t)1),
1258 	    hxgep->rx_default_block_size, hxgep->sys_page_mask));
1259 
1260 	switch (hxgep->sys_page_sz) {
1261 	default:
1262 		hxgep->sys_page_sz = 0x1000;
1263 		hxgep->sys_page_mask = ~(hxgep->sys_page_sz - 1);
1264 		hxgep->rx_default_block_size = 0x1000;
1265 		hxgep->rx_bksize_code = RBR_BKSIZE_4K;
1266 		break;
1267 	case 0x1000:
1268 		hxgep->rx_default_block_size = 0x1000;
1269 		hxgep->rx_bksize_code = RBR_BKSIZE_4K;
1270 		break;
1271 	case 0x2000:
1272 		hxgep->rx_default_block_size = 0x2000;
1273 		hxgep->rx_bksize_code = RBR_BKSIZE_8K;
1274 		break;
1275 	}
1276 
1277 	hxge_rx_dma_attr.dma_attr_align = hxgep->sys_page_sz;
1278 	hxge_tx_dma_attr.dma_attr_align = hxgep->sys_page_sz;
1279 	hxge_desc_dma_attr.dma_attr_align = hxgep->sys_page_sz;
1280 
1281 	/*
1282 	 * Get the system DMA burst size.
1283 	 */
1284 	ddi_status = ddi_dma_alloc_handle(hxgep->dip, &hxge_tx_dma_attr,
1285 	    DDI_DMA_DONTWAIT, 0, &hxgep->dmasparehandle);
1286 	if (ddi_status != DDI_SUCCESS) {
1287 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
1288 		    "ddi_dma_alloc_handle: failed status 0x%x", ddi_status));
1289 		goto hxge_get_soft_properties_exit;
1290 	}
1291 
1292 	ddi_status = ddi_dma_addr_bind_handle(hxgep->dmasparehandle, NULL,
1293 	    (caddr_t)hxgep->dmasparehandle, sizeof (hxgep->dmasparehandle),
1294 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, 0,
1295 	    &cookie, &count);
1296 	if (ddi_status != DDI_DMA_MAPPED) {
1297 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
1298 		    "Binding spare handle to find system burstsize failed."));
1299 		ddi_status = DDI_FAILURE;
1300 		goto hxge_get_soft_properties_fail1;
1301 	}
1302 
1303 	hxgep->sys_burst_sz = ddi_dma_burstsizes(hxgep->dmasparehandle);
1304 	(void) ddi_dma_unbind_handle(hxgep->dmasparehandle);
1305 
1306 hxge_get_soft_properties_fail1:
1307 	ddi_dma_free_handle(&hxgep->dmasparehandle);
1308 
1309 hxge_get_soft_properties_exit:
1310 
1311 	if (ddi_status != DDI_SUCCESS)
1312 		status |= (HXGE_ERROR | HXGE_DDI_FAILED);
1313 
1314 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
1315 	    "<== hxge_setup_system_dma_pages status = 0x%08x", status));
1316 
1317 	return (status);
1318 }
1319 
1320 hxge_status_t
1321 hxge_alloc_mem_pool(p_hxge_t hxgep)
1322 {
1323 	hxge_status_t status = HXGE_OK;
1324 
1325 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_alloc_mem_pool"));
1326 
1327 	status = hxge_alloc_rx_mem_pool(hxgep);
1328 	if (status != HXGE_OK) {
1329 		return (HXGE_ERROR);
1330 	}
1331 
1332 	status = hxge_alloc_tx_mem_pool(hxgep);
1333 	if (status != HXGE_OK) {
1334 		hxge_free_rx_mem_pool(hxgep);
1335 		return (HXGE_ERROR);
1336 	}
1337 
1338 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_alloc_mem_pool"));
1339 	return (HXGE_OK);
1340 }
1341 
1342 static void
1343 hxge_free_mem_pool(p_hxge_t hxgep)
1344 {
1345 	HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_free_mem_pool"));
1346 
1347 	hxge_free_rx_mem_pool(hxgep);
1348 	hxge_free_tx_mem_pool(hxgep);
1349 
1350 	HXGE_DEBUG_MSG((hxgep, MEM_CTL, "<== hxge_free_mem_pool"));
1351 }
1352 
1353 static hxge_status_t
1354 hxge_alloc_rx_mem_pool(p_hxge_t hxgep)
1355 {
1356 	int			i, j;
1357 	uint32_t		ndmas, st_rdc;
1358 	p_hxge_dma_pt_cfg_t	p_all_cfgp;
1359 	p_hxge_hw_pt_cfg_t	p_cfgp;
1360 	p_hxge_dma_pool_t	dma_poolp;
1361 	p_hxge_dma_common_t	*dma_buf_p;
1362 	p_hxge_dma_pool_t	dma_cntl_poolp;
1363 	p_hxge_dma_common_t	*dma_cntl_p;
1364 	size_t			rx_buf_alloc_size;
1365 	size_t			rx_cntl_alloc_size;
1366 	uint32_t		*num_chunks;	/* per dma */
1367 	hxge_status_t		status = HXGE_OK;
1368 
1369 	uint32_t		hxge_port_rbr_size;
1370 	uint32_t		hxge_port_rbr_spare_size;
1371 	uint32_t		hxge_port_rcr_size;
1372 
1373 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_rx_mem_pool"));
1374 
1375 	p_all_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config;
1376 	p_cfgp = (p_hxge_hw_pt_cfg_t)&p_all_cfgp->hw_config;
1377 	st_rdc = p_cfgp->start_rdc;
1378 	ndmas = p_cfgp->max_rdcs;
1379 
1380 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1381 	    " hxge_alloc_rx_mem_pool st_rdc %d ndmas %d", st_rdc, ndmas));
1382 
1383 	/*
1384 	 * Allocate memory for each receive DMA channel.
1385 	 */
1386 	dma_poolp = (p_hxge_dma_pool_t)KMEM_ZALLOC(sizeof (hxge_dma_pool_t),
1387 	    KM_SLEEP);
1388 	dma_buf_p = (p_hxge_dma_common_t *)KMEM_ZALLOC(
1389 	    sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP);
1390 
1391 	dma_cntl_poolp = (p_hxge_dma_pool_t)
1392 	    KMEM_ZALLOC(sizeof (hxge_dma_pool_t), KM_SLEEP);
1393 	dma_cntl_p = (p_hxge_dma_common_t *)KMEM_ZALLOC(
1394 	    sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP);
1395 
1396 	num_chunks = (uint32_t *)KMEM_ZALLOC(sizeof (uint32_t) * ndmas,
1397 	    KM_SLEEP);
1398 
1399 	/*
1400 	 * Assume that each DMA channel will be configured with default block
1401 	 * size. rbr block counts are mod of batch count (16).
1402 	 */
1403 	hxge_port_rbr_size = p_all_cfgp->rbr_size;
1404 	hxge_port_rcr_size = p_all_cfgp->rcr_size;
1405 
1406 	if (!hxge_port_rbr_size) {
1407 		hxge_port_rbr_size = HXGE_RBR_RBB_DEFAULT;
1408 	}
1409 
1410 	if (hxge_port_rbr_size % HXGE_RXDMA_POST_BATCH) {
1411 		hxge_port_rbr_size = (HXGE_RXDMA_POST_BATCH *
1412 		    (hxge_port_rbr_size / HXGE_RXDMA_POST_BATCH + 1));
1413 	}
1414 
1415 	p_all_cfgp->rbr_size = hxge_port_rbr_size;
1416 	hxge_port_rbr_spare_size = hxge_rbr_spare_size;
1417 
1418 	if (hxge_port_rbr_spare_size % HXGE_RXDMA_POST_BATCH) {
1419 		hxge_port_rbr_spare_size = (HXGE_RXDMA_POST_BATCH *
1420 		    (hxge_port_rbr_spare_size / HXGE_RXDMA_POST_BATCH + 1));
1421 	}
1422 
1423 	rx_buf_alloc_size = (hxgep->rx_default_block_size *
1424 	    (hxge_port_rbr_size + hxge_port_rbr_spare_size));
1425 
1426 	/*
1427 	 * Addresses of receive block ring, receive completion ring and the
1428 	 * mailbox must be all cache-aligned (64 bytes).
1429 	 */
1430 	rx_cntl_alloc_size = hxge_port_rbr_size + hxge_port_rbr_spare_size;
1431 	rx_cntl_alloc_size *= (sizeof (rx_desc_t));
1432 	rx_cntl_alloc_size += (sizeof (rcr_entry_t) * hxge_port_rcr_size);
1433 	rx_cntl_alloc_size += sizeof (rxdma_mailbox_t);
1434 
1435 	HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_alloc_rx_mem_pool: "
1436 	    "hxge_port_rbr_size = %d hxge_port_rbr_spare_size = %d "
1437 	    "hxge_port_rcr_size = %d rx_cntl_alloc_size = %d",
1438 	    hxge_port_rbr_size, hxge_port_rbr_spare_size,
1439 	    hxge_port_rcr_size, rx_cntl_alloc_size));
1440 
1441 	hxgep->hxge_port_rbr_size = hxge_port_rbr_size;
1442 	hxgep->hxge_port_rcr_size = hxge_port_rcr_size;
1443 
1444 	/*
1445 	 * Allocate memory for receive buffers and descriptor rings. Replace
1446 	 * allocation functions with interface functions provided by the
1447 	 * partition manager when it is available.
1448 	 */
1449 	/*
1450 	 * Allocate memory for the receive buffer blocks.
1451 	 */
1452 	for (i = 0; i < ndmas; i++) {
1453 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
1454 		    " hxge_alloc_rx_mem_pool to alloc mem: "
1455 		    " dma %d dma_buf_p %llx &dma_buf_p %llx",
1456 		    i, dma_buf_p[i], &dma_buf_p[i]));
1457 
1458 		num_chunks[i] = 0;
1459 
1460 		status = hxge_alloc_rx_buf_dma(hxgep, st_rdc, &dma_buf_p[i],
1461 		    rx_buf_alloc_size, hxgep->rx_default_block_size,
1462 		    &num_chunks[i]);
1463 		if (status != HXGE_OK) {
1464 			break;
1465 		}
1466 
1467 		st_rdc++;
1468 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
1469 		    " hxge_alloc_rx_mem_pool DONE  alloc mem: "
1470 		    "dma %d dma_buf_p %llx &dma_buf_p %llx", i,
1471 		    dma_buf_p[i], &dma_buf_p[i]));
1472 	}
1473 
1474 	if (i < ndmas) {
1475 		goto hxge_alloc_rx_mem_fail1;
1476 	}
1477 
1478 	/*
1479 	 * Allocate memory for descriptor rings and mailbox.
1480 	 */
1481 	st_rdc = p_cfgp->start_rdc;
1482 	for (j = 0; j < ndmas; j++) {
1483 		status = hxge_alloc_rx_cntl_dma(hxgep, st_rdc, &dma_cntl_p[j],
1484 		    rx_cntl_alloc_size);
1485 		if (status != HXGE_OK) {
1486 			break;
1487 		}
1488 		st_rdc++;
1489 	}
1490 
1491 	if (j < ndmas) {
1492 		goto hxge_alloc_rx_mem_fail2;
1493 	}
1494 
1495 	dma_poolp->ndmas = ndmas;
1496 	dma_poolp->num_chunks = num_chunks;
1497 	dma_poolp->buf_allocated = B_TRUE;
1498 	hxgep->rx_buf_pool_p = dma_poolp;
1499 	dma_poolp->dma_buf_pool_p = dma_buf_p;
1500 
1501 	dma_cntl_poolp->ndmas = ndmas;
1502 	dma_cntl_poolp->buf_allocated = B_TRUE;
1503 	hxgep->rx_cntl_pool_p = dma_cntl_poolp;
1504 	dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p;
1505 
1506 	goto hxge_alloc_rx_mem_pool_exit;
1507 
1508 hxge_alloc_rx_mem_fail2:
1509 	/* Free control buffers */
1510 	j--;
1511 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1512 	    "==> hxge_alloc_rx_mem_pool: freeing control bufs (%d)", j));
1513 	for (; j >= 0; j--) {
1514 		hxge_free_rx_cntl_dma(hxgep,
1515 		    (p_hxge_dma_common_t)dma_cntl_p[j]);
1516 		HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1517 		    "==> hxge_alloc_rx_mem_pool: control bufs freed (%d)", j));
1518 	}
1519 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1520 	    "==> hxge_alloc_rx_mem_pool: control bufs freed (%d)", j));
1521 
1522 hxge_alloc_rx_mem_fail1:
1523 	/* Free data buffers */
1524 	i--;
1525 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1526 	    "==> hxge_alloc_rx_mem_pool: freeing data bufs (%d)", i));
1527 	for (; i >= 0; i--) {
1528 		hxge_free_rx_buf_dma(hxgep, (p_hxge_dma_common_t)dma_buf_p[i],
1529 		    num_chunks[i]);
1530 	}
1531 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1532 	    "==> hxge_alloc_rx_mem_pool: data bufs freed (%d)", i));
1533 
1534 	KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
1535 	KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t));
1536 	KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t));
1537 	KMEM_FREE(dma_cntl_poolp, sizeof (hxge_dma_pool_t));
1538 	KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
1539 
1540 hxge_alloc_rx_mem_pool_exit:
1541 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1542 	    "<== hxge_alloc_rx_mem_pool:status 0x%08x", status));
1543 
1544 	return (status);
1545 }
1546 
1547 static void
1548 hxge_free_rx_mem_pool(p_hxge_t hxgep)
1549 {
1550 	uint32_t		i, ndmas;
1551 	p_hxge_dma_pool_t	dma_poolp;
1552 	p_hxge_dma_common_t	*dma_buf_p;
1553 	p_hxge_dma_pool_t	dma_cntl_poolp;
1554 	p_hxge_dma_common_t	*dma_cntl_p;
1555 	uint32_t		*num_chunks;
1556 
1557 	HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_free_rx_mem_pool"));
1558 
1559 	dma_poolp = hxgep->rx_buf_pool_p;
1560 	if (dma_poolp == NULL || (!dma_poolp->buf_allocated)) {
1561 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_free_rx_mem_pool "
1562 		    "(null rx buf pool or buf not allocated"));
1563 		return;
1564 	}
1565 
1566 	dma_cntl_poolp = hxgep->rx_cntl_pool_p;
1567 	if (dma_cntl_poolp == NULL || (!dma_cntl_poolp->buf_allocated)) {
1568 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
1569 		    "<== hxge_free_rx_mem_pool "
1570 		    "(null rx cntl buf pool or cntl buf not allocated"));
1571 		return;
1572 	}
1573 
1574 	dma_buf_p = dma_poolp->dma_buf_pool_p;
1575 	num_chunks = dma_poolp->num_chunks;
1576 
1577 	dma_cntl_p = dma_cntl_poolp->dma_buf_pool_p;
1578 	ndmas = dma_cntl_poolp->ndmas;
1579 
1580 	for (i = 0; i < ndmas; i++) {
1581 		hxge_free_rx_buf_dma(hxgep, dma_buf_p[i], num_chunks[i]);
1582 	}
1583 
1584 	for (i = 0; i < ndmas; i++) {
1585 		hxge_free_rx_cntl_dma(hxgep, dma_cntl_p[i]);
1586 	}
1587 
1588 	for (i = 0; i < ndmas; i++) {
1589 		KMEM_FREE(dma_buf_p[i],
1590 		    sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK);
1591 		KMEM_FREE(dma_cntl_p[i], sizeof (hxge_dma_common_t));
1592 	}
1593 
1594 	KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
1595 	KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
1596 	KMEM_FREE(dma_cntl_poolp, sizeof (hxge_dma_pool_t));
1597 	KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t));
1598 	KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t));
1599 
1600 	hxgep->rx_buf_pool_p = NULL;
1601 	hxgep->rx_cntl_pool_p = NULL;
1602 
1603 	HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_free_rx_mem_pool"));
1604 }
1605 
1606 static hxge_status_t
1607 hxge_alloc_rx_buf_dma(p_hxge_t hxgep, uint16_t dma_channel,
1608     p_hxge_dma_common_t *dmap,
1609     size_t alloc_size, size_t block_size, uint32_t *num_chunks)
1610 {
1611 	p_hxge_dma_common_t	rx_dmap;
1612 	hxge_status_t		status = HXGE_OK;
1613 	size_t			total_alloc_size;
1614 	size_t			allocated = 0;
1615 	int			i, size_index, array_size;
1616 
1617 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_rx_buf_dma"));
1618 
1619 	rx_dmap = (p_hxge_dma_common_t)
1620 	    KMEM_ZALLOC(sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK, KM_SLEEP);
1621 
1622 	HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
1623 	    " alloc_rx_buf_dma rdc %d asize %x bsize %x bbuf %llx ",
1624 	    dma_channel, alloc_size, block_size, dmap));
1625 
1626 	total_alloc_size = alloc_size;
1627 
1628 	i = 0;
1629 	size_index = 0;
1630 	array_size = sizeof (alloc_sizes) / sizeof (size_t);
1631 	while ((alloc_sizes[size_index] < alloc_size) &&
1632 	    (size_index < array_size))
1633 		size_index++;
1634 	if (size_index >= array_size) {
1635 		size_index = array_size - 1;
1636 	}
1637 
1638 	while ((allocated < total_alloc_size) &&
1639 	    (size_index >= 0) && (i < HXGE_DMA_BLOCK)) {
1640 		rx_dmap[i].dma_chunk_index = i;
1641 		rx_dmap[i].block_size = block_size;
1642 		rx_dmap[i].alength = alloc_sizes[size_index];
1643 		rx_dmap[i].orig_alength = rx_dmap[i].alength;
1644 		rx_dmap[i].nblocks = alloc_sizes[size_index] / block_size;
1645 		rx_dmap[i].dma_channel = dma_channel;
1646 		rx_dmap[i].contig_alloc_type = B_FALSE;
1647 
1648 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
1649 		    "alloc_rx_buf_dma rdc %d chunk %d bufp %llx size %x "
1650 		    "i %d nblocks %d alength %d",
1651 		    dma_channel, i, &rx_dmap[i], block_size,
1652 		    i, rx_dmap[i].nblocks, rx_dmap[i].alength));
1653 		status = hxge_dma_mem_alloc(hxgep, hxge_force_dma,
1654 		    &hxge_rx_dma_attr, rx_dmap[i].alength,
1655 		    &hxge_dev_buf_dma_acc_attr,
1656 		    DDI_DMA_READ | DDI_DMA_STREAMING,
1657 		    (p_hxge_dma_common_t)(&rx_dmap[i]));
1658 		if (status != HXGE_OK) {
1659 			HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1660 			    " hxge_alloc_rx_buf_dma: Alloc Failed: "
1661 			    " for size: %d", alloc_sizes[size_index]));
1662 			size_index--;
1663 		} else {
1664 			HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1665 			    " alloc_rx_buf_dma allocated rdc %d "
1666 			    "chunk %d size %x dvma %x bufp %llx ",
1667 			    dma_channel, i, rx_dmap[i].alength,
1668 			    rx_dmap[i].ioaddr_pp, &rx_dmap[i]));
1669 			i++;
1670 			allocated += alloc_sizes[size_index];
1671 		}
1672 	}
1673 
1674 	if (allocated < total_alloc_size) {
1675 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
1676 		    " hxge_alloc_rx_buf_dma failed due to"
1677 		    " allocated(%d) < required(%d)",
1678 		    allocated, total_alloc_size));
1679 		goto hxge_alloc_rx_mem_fail1;
1680 	}
1681 
1682 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1683 	    " alloc_rx_buf_dma rdc %d allocated %d chunks", dma_channel, i));
1684 
1685 	*num_chunks = i;
1686 	*dmap = rx_dmap;
1687 
1688 	goto hxge_alloc_rx_mem_exit;
1689 
1690 hxge_alloc_rx_mem_fail1:
1691 	KMEM_FREE(rx_dmap, sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK);
1692 
1693 hxge_alloc_rx_mem_exit:
1694 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1695 	    "<== hxge_alloc_rx_buf_dma status 0x%08x", status));
1696 
1697 	return (status);
1698 }
1699 
1700 /*ARGSUSED*/
1701 static void
1702 hxge_free_rx_buf_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap,
1703     uint32_t num_chunks)
1704 {
1705 	int i;
1706 
1707 	HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
1708 	    "==> hxge_free_rx_buf_dma: # of chunks %d", num_chunks));
1709 
1710 	for (i = 0; i < num_chunks; i++) {
1711 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
1712 		    "==> hxge_free_rx_buf_dma: chunk %d dmap 0x%llx", i, dmap));
1713 		hxge_dma_mem_free(dmap++);
1714 	}
1715 
1716 	HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_free_rx_buf_dma"));
1717 }
1718 
1719 /*ARGSUSED*/
1720 static hxge_status_t
1721 hxge_alloc_rx_cntl_dma(p_hxge_t hxgep, uint16_t dma_channel,
1722     p_hxge_dma_common_t *dmap, size_t size)
1723 {
1724 	p_hxge_dma_common_t	rx_dmap;
1725 	hxge_status_t		status = HXGE_OK;
1726 
1727 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_rx_cntl_dma"));
1728 
1729 	rx_dmap = (p_hxge_dma_common_t)
1730 	    KMEM_ZALLOC(sizeof (hxge_dma_common_t), KM_SLEEP);
1731 
1732 	rx_dmap->contig_alloc_type = B_FALSE;
1733 
1734 	status = hxge_dma_mem_alloc(hxgep, hxge_force_dma,
1735 	    &hxge_desc_dma_attr, size, &hxge_dev_desc_dma_acc_attr,
1736 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT, rx_dmap);
1737 	if (status != HXGE_OK) {
1738 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
1739 		    " hxge_alloc_rx_cntl_dma: Alloc Failed: "
1740 		    " for size: %d", size));
1741 		goto hxge_alloc_rx_cntl_dma_fail1;
1742 	}
1743 
1744 	*dmap = rx_dmap;
1745 
1746 	goto hxge_alloc_rx_cntl_dma_exit;
1747 
1748 hxge_alloc_rx_cntl_dma_fail1:
1749 	KMEM_FREE(rx_dmap, sizeof (hxge_dma_common_t));
1750 
1751 hxge_alloc_rx_cntl_dma_exit:
1752 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1753 	    "<== hxge_alloc_rx_cntl_dma status 0x%08x", status));
1754 
1755 	return (status);
1756 }
1757 
1758 /*ARGSUSED*/
1759 static void
1760 hxge_free_rx_cntl_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap)
1761 {
1762 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_free_rx_cntl_dma"));
1763 
1764 	hxge_dma_mem_free(dmap);
1765 
1766 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_free_rx_cntl_dma"));
1767 }
1768 
1769 static hxge_status_t
1770 hxge_alloc_tx_mem_pool(p_hxge_t hxgep)
1771 {
1772 	hxge_status_t		status = HXGE_OK;
1773 	int			i, j;
1774 	uint32_t		ndmas, st_tdc;
1775 	p_hxge_dma_pt_cfg_t	p_all_cfgp;
1776 	p_hxge_hw_pt_cfg_t	p_cfgp;
1777 	p_hxge_dma_pool_t	dma_poolp;
1778 	p_hxge_dma_common_t	*dma_buf_p;
1779 	p_hxge_dma_pool_t	dma_cntl_poolp;
1780 	p_hxge_dma_common_t	*dma_cntl_p;
1781 	size_t			tx_buf_alloc_size;
1782 	size_t			tx_cntl_alloc_size;
1783 	uint32_t		*num_chunks;	/* per dma */
1784 
1785 	HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_alloc_tx_mem_pool"));
1786 
1787 	p_all_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config;
1788 	p_cfgp = (p_hxge_hw_pt_cfg_t)&p_all_cfgp->hw_config;
1789 	st_tdc = p_cfgp->start_tdc;
1790 	ndmas = p_cfgp->max_tdcs;
1791 
1792 	HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_alloc_tx_mem_pool: "
1793 	    "p_cfgp 0x%016llx start_tdc %d ndmas %d hxgep->max_tdcs %d",
1794 	    p_cfgp, p_cfgp->start_tdc, p_cfgp->max_tdcs, hxgep->max_tdcs));
1795 	/*
1796 	 * Allocate memory for each transmit DMA channel.
1797 	 */
1798 	dma_poolp = (p_hxge_dma_pool_t)KMEM_ZALLOC(sizeof (hxge_dma_pool_t),
1799 	    KM_SLEEP);
1800 	dma_buf_p = (p_hxge_dma_common_t *)KMEM_ZALLOC(
1801 	    sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP);
1802 
1803 	dma_cntl_poolp = (p_hxge_dma_pool_t)
1804 	    KMEM_ZALLOC(sizeof (hxge_dma_pool_t), KM_SLEEP);
1805 	dma_cntl_p = (p_hxge_dma_common_t *)KMEM_ZALLOC(
1806 	    sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP);
1807 
1808 	hxgep->hxge_port_tx_ring_size = hxge_tx_ring_size;
1809 
1810 	/*
1811 	 * Assume that each DMA channel will be configured with default
1812 	 * transmit bufer size for copying transmit data. (For packet payload
1813 	 * over this limit, packets will not be copied.)
1814 	 */
1815 	tx_buf_alloc_size = (hxge_bcopy_thresh * hxge_tx_ring_size);
1816 
1817 	/*
1818 	 * Addresses of transmit descriptor ring and the mailbox must be all
1819 	 * cache-aligned (64 bytes).
1820 	 */
1821 	tx_cntl_alloc_size = hxge_tx_ring_size;
1822 	tx_cntl_alloc_size *= (sizeof (tx_desc_t));
1823 	tx_cntl_alloc_size += sizeof (txdma_mailbox_t);
1824 
1825 	num_chunks = (uint32_t *)KMEM_ZALLOC(sizeof (uint32_t) * ndmas,
1826 	    KM_SLEEP);
1827 
1828 	/*
1829 	 * Allocate memory for transmit buffers and descriptor rings. Replace
1830 	 * allocation functions with interface functions provided by the
1831 	 * partition manager when it is available.
1832 	 *
1833 	 * Allocate memory for the transmit buffer pool.
1834 	 */
1835 	for (i = 0; i < ndmas; i++) {
1836 		num_chunks[i] = 0;
1837 		status = hxge_alloc_tx_buf_dma(hxgep, st_tdc, &dma_buf_p[i],
1838 		    tx_buf_alloc_size, hxge_bcopy_thresh, &num_chunks[i]);
1839 		if (status != HXGE_OK) {
1840 			break;
1841 		}
1842 		st_tdc++;
1843 	}
1844 
1845 	if (i < ndmas) {
1846 		goto hxge_alloc_tx_mem_pool_fail1;
1847 	}
1848 
1849 	st_tdc = p_cfgp->start_tdc;
1850 
1851 	/*
1852 	 * Allocate memory for descriptor rings and mailbox.
1853 	 */
1854 	for (j = 0; j < ndmas; j++) {
1855 		status = hxge_alloc_tx_cntl_dma(hxgep, st_tdc, &dma_cntl_p[j],
1856 		    tx_cntl_alloc_size);
1857 		if (status != HXGE_OK) {
1858 			break;
1859 		}
1860 		st_tdc++;
1861 	}
1862 
1863 	if (j < ndmas) {
1864 		goto hxge_alloc_tx_mem_pool_fail2;
1865 	}
1866 
1867 	dma_poolp->ndmas = ndmas;
1868 	dma_poolp->num_chunks = num_chunks;
1869 	dma_poolp->buf_allocated = B_TRUE;
1870 	dma_poolp->dma_buf_pool_p = dma_buf_p;
1871 	hxgep->tx_buf_pool_p = dma_poolp;
1872 
1873 	dma_cntl_poolp->ndmas = ndmas;
1874 	dma_cntl_poolp->buf_allocated = B_TRUE;
1875 	dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p;
1876 	hxgep->tx_cntl_pool_p = dma_cntl_poolp;
1877 
1878 	HXGE_DEBUG_MSG((hxgep, MEM_CTL,
1879 	    "==> hxge_alloc_tx_mem_pool: start_tdc %d "
1880 	    "ndmas %d poolp->ndmas %d", st_tdc, ndmas, dma_poolp->ndmas));
1881 
1882 	goto hxge_alloc_tx_mem_pool_exit;
1883 
1884 hxge_alloc_tx_mem_pool_fail2:
1885 	/* Free control buffers */
1886 	j--;
1887 	for (; j >= 0; j--) {
1888 		hxge_free_tx_cntl_dma(hxgep,
1889 		    (p_hxge_dma_common_t)dma_cntl_p[j]);
1890 	}
1891 
1892 hxge_alloc_tx_mem_pool_fail1:
1893 	/* Free data buffers */
1894 	i--;
1895 	for (; i >= 0; i--) {
1896 		hxge_free_tx_buf_dma(hxgep, (p_hxge_dma_common_t)dma_buf_p[i],
1897 		    num_chunks[i]);
1898 	}
1899 
1900 	KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t));
1901 	KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t));
1902 	KMEM_FREE(dma_cntl_poolp, sizeof (hxge_dma_pool_t));
1903 	KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
1904 	KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
1905 
1906 hxge_alloc_tx_mem_pool_exit:
1907 	HXGE_DEBUG_MSG((hxgep, MEM_CTL,
1908 	    "<== hxge_alloc_tx_mem_pool:status 0x%08x", status));
1909 
1910 	return (status);
1911 }
1912 
1913 static hxge_status_t
1914 hxge_alloc_tx_buf_dma(p_hxge_t hxgep, uint16_t dma_channel,
1915     p_hxge_dma_common_t *dmap, size_t alloc_size,
1916     size_t block_size, uint32_t *num_chunks)
1917 {
1918 	p_hxge_dma_common_t	tx_dmap;
1919 	hxge_status_t		status = HXGE_OK;
1920 	size_t			total_alloc_size;
1921 	size_t			allocated = 0;
1922 	int			i, size_index, array_size;
1923 
1924 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_tx_buf_dma"));
1925 
1926 	tx_dmap = (p_hxge_dma_common_t)
1927 	    KMEM_ZALLOC(sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK, KM_SLEEP);
1928 
1929 	total_alloc_size = alloc_size;
1930 	i = 0;
1931 	size_index = 0;
1932 	array_size = sizeof (alloc_sizes) / sizeof (size_t);
1933 	while ((alloc_sizes[size_index] < alloc_size) &&
1934 	    (size_index < array_size))
1935 		size_index++;
1936 	if (size_index >= array_size) {
1937 		size_index = array_size - 1;
1938 	}
1939 
1940 	while ((allocated < total_alloc_size) &&
1941 	    (size_index >= 0) && (i < HXGE_DMA_BLOCK)) {
1942 		tx_dmap[i].dma_chunk_index = i;
1943 		tx_dmap[i].block_size = block_size;
1944 		tx_dmap[i].alength = alloc_sizes[size_index];
1945 		tx_dmap[i].orig_alength = tx_dmap[i].alength;
1946 		tx_dmap[i].nblocks = alloc_sizes[size_index] / block_size;
1947 		tx_dmap[i].dma_channel = dma_channel;
1948 		tx_dmap[i].contig_alloc_type = B_FALSE;
1949 
1950 		status = hxge_dma_mem_alloc(hxgep, hxge_force_dma,
1951 		    &hxge_tx_dma_attr, tx_dmap[i].alength,
1952 		    &hxge_dev_buf_dma_acc_attr,
1953 		    DDI_DMA_WRITE | DDI_DMA_STREAMING,
1954 		    (p_hxge_dma_common_t)(&tx_dmap[i]));
1955 		if (status != HXGE_OK) {
1956 			HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1957 			    " hxge_alloc_tx_buf_dma: Alloc Failed: "
1958 			    " for size: %d", alloc_sizes[size_index]));
1959 			size_index--;
1960 		} else {
1961 			i++;
1962 			allocated += alloc_sizes[size_index];
1963 		}
1964 	}
1965 
1966 	if (allocated < total_alloc_size) {
1967 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
1968 		    " hxge_alloc_tx_buf_dma: failed due to"
1969 		    " allocated(%d) < required(%d)",
1970 		    allocated, total_alloc_size));
1971 		goto hxge_alloc_tx_mem_fail1;
1972 	}
1973 
1974 	*num_chunks = i;
1975 	*dmap = tx_dmap;
1976 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1977 	    "==> hxge_alloc_tx_buf_dma dmap 0x%016llx num chunks %d",
1978 	    *dmap, i));
1979 	goto hxge_alloc_tx_mem_exit;
1980 
1981 hxge_alloc_tx_mem_fail1:
1982 	KMEM_FREE(tx_dmap, sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK);
1983 
1984 hxge_alloc_tx_mem_exit:
1985 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1986 	    "<== hxge_alloc_tx_buf_dma status 0x%08x", status));
1987 
1988 	return (status);
1989 }
1990 
1991 /*ARGSUSED*/
1992 static void
1993 hxge_free_tx_buf_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap,
1994     uint32_t num_chunks)
1995 {
1996 	int i;
1997 
1998 	HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_free_tx_buf_dma"));
1999 
2000 	for (i = 0; i < num_chunks; i++) {
2001 		hxge_dma_mem_free(dmap++);
2002 	}
2003 
2004 	HXGE_DEBUG_MSG((hxgep, MEM_CTL, "<== hxge_free_tx_buf_dma"));
2005 }
2006 
2007 /*ARGSUSED*/
2008 static hxge_status_t
2009 hxge_alloc_tx_cntl_dma(p_hxge_t hxgep, uint16_t dma_channel,
2010     p_hxge_dma_common_t *dmap, size_t size)
2011 {
2012 	p_hxge_dma_common_t	tx_dmap;
2013 	hxge_status_t		status = HXGE_OK;
2014 
2015 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_tx_cntl_dma"));
2016 
2017 	tx_dmap = (p_hxge_dma_common_t)KMEM_ZALLOC(sizeof (hxge_dma_common_t),
2018 	    KM_SLEEP);
2019 
2020 	tx_dmap->contig_alloc_type = B_FALSE;
2021 
2022 	status = hxge_dma_mem_alloc(hxgep, hxge_force_dma,
2023 	    &hxge_desc_dma_attr, size, &hxge_dev_desc_dma_acc_attr,
2024 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT, tx_dmap);
2025 	if (status != HXGE_OK) {
2026 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
2027 		    " hxge_alloc_tx_cntl_dma: Alloc Failed: "
2028 		    " for size: %d", size));
2029 		goto hxge_alloc_tx_cntl_dma_fail1;
2030 	}
2031 
2032 	*dmap = tx_dmap;
2033 
2034 	goto hxge_alloc_tx_cntl_dma_exit;
2035 
2036 hxge_alloc_tx_cntl_dma_fail1:
2037 	KMEM_FREE(tx_dmap, sizeof (hxge_dma_common_t));
2038 
2039 hxge_alloc_tx_cntl_dma_exit:
2040 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
2041 	    "<== hxge_alloc_tx_cntl_dma status 0x%08x", status));
2042 
2043 	return (status);
2044 }
2045 
2046 /*ARGSUSED*/
2047 static void
2048 hxge_free_tx_cntl_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap)
2049 {
2050 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_free_tx_cntl_dma"));
2051 
2052 	hxge_dma_mem_free(dmap);
2053 
2054 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_free_tx_cntl_dma"));
2055 }
2056 
2057 static void
2058 hxge_free_tx_mem_pool(p_hxge_t hxgep)
2059 {
2060 	uint32_t		i, ndmas;
2061 	p_hxge_dma_pool_t	dma_poolp;
2062 	p_hxge_dma_common_t	*dma_buf_p;
2063 	p_hxge_dma_pool_t	dma_cntl_poolp;
2064 	p_hxge_dma_common_t	*dma_cntl_p;
2065 	uint32_t		*num_chunks;
2066 
2067 	HXGE_DEBUG_MSG((hxgep, MEM3_CTL, "==> hxge_free_tx_mem_pool"));
2068 
2069 	dma_poolp = hxgep->tx_buf_pool_p;
2070 	if (dma_poolp == NULL || (!dma_poolp->buf_allocated)) {
2071 		HXGE_DEBUG_MSG((hxgep, MEM3_CTL,
2072 		    "<== hxge_free_tx_mem_pool "
2073 		    "(null rx buf pool or buf not allocated"));
2074 		return;
2075 	}
2076 
2077 	dma_cntl_poolp = hxgep->tx_cntl_pool_p;
2078 	if (dma_cntl_poolp == NULL || (!dma_cntl_poolp->buf_allocated)) {
2079 		HXGE_DEBUG_MSG((hxgep, MEM3_CTL,
2080 		    "<== hxge_free_tx_mem_pool "
2081 		    "(null tx cntl buf pool or cntl buf not allocated"));
2082 		return;
2083 	}
2084 
2085 	dma_buf_p = dma_poolp->dma_buf_pool_p;
2086 	num_chunks = dma_poolp->num_chunks;
2087 
2088 	dma_cntl_p = dma_cntl_poolp->dma_buf_pool_p;
2089 	ndmas = dma_cntl_poolp->ndmas;
2090 
2091 	for (i = 0; i < ndmas; i++) {
2092 		hxge_free_tx_buf_dma(hxgep, dma_buf_p[i], num_chunks[i]);
2093 	}
2094 
2095 	for (i = 0; i < ndmas; i++) {
2096 		hxge_free_tx_cntl_dma(hxgep, dma_cntl_p[i]);
2097 	}
2098 
2099 	for (i = 0; i < ndmas; i++) {
2100 		KMEM_FREE(dma_buf_p[i],
2101 		    sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK);
2102 		KMEM_FREE(dma_cntl_p[i], sizeof (hxge_dma_common_t));
2103 	}
2104 
2105 	KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
2106 	KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
2107 	KMEM_FREE(dma_cntl_poolp, sizeof (hxge_dma_pool_t));
2108 	KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t));
2109 	KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t));
2110 
2111 	hxgep->tx_buf_pool_p = NULL;
2112 	hxgep->tx_cntl_pool_p = NULL;
2113 
2114 	HXGE_DEBUG_MSG((hxgep, MEM3_CTL, "<== hxge_free_tx_mem_pool"));
2115 }
2116 
2117 /*ARGSUSED*/
2118 static hxge_status_t
2119 hxge_dma_mem_alloc(p_hxge_t hxgep, dma_method_t method,
2120     struct ddi_dma_attr *dma_attrp,
2121     size_t length, ddi_device_acc_attr_t *acc_attr_p, uint_t xfer_flags,
2122     p_hxge_dma_common_t dma_p)
2123 {
2124 	caddr_t		kaddrp;
2125 	int		ddi_status = DDI_SUCCESS;
2126 
2127 	dma_p->dma_handle = NULL;
2128 	dma_p->acc_handle = NULL;
2129 	dma_p->kaddrp = NULL;
2130 
2131 	ddi_status = ddi_dma_alloc_handle(hxgep->dip, dma_attrp,
2132 	    DDI_DMA_DONTWAIT, NULL, &dma_p->dma_handle);
2133 	if (ddi_status != DDI_SUCCESS) {
2134 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
2135 		    "hxge_dma_mem_alloc:ddi_dma_alloc_handle failed."));
2136 		return (HXGE_ERROR | HXGE_DDI_FAILED);
2137 	}
2138 
2139 	ddi_status = ddi_dma_mem_alloc(dma_p->dma_handle, length, acc_attr_p,
2140 	    xfer_flags, DDI_DMA_DONTWAIT, 0, &kaddrp, &dma_p->alength,
2141 	    &dma_p->acc_handle);
2142 	if (ddi_status != DDI_SUCCESS) {
2143 		/* The caller will decide whether it is fatal */
2144 		HXGE_DEBUG_MSG((hxgep, DMA_CTL,
2145 		    "hxge_dma_mem_alloc:ddi_dma_mem_alloc failed"));
2146 		ddi_dma_free_handle(&dma_p->dma_handle);
2147 		dma_p->dma_handle = NULL;
2148 		return (HXGE_ERROR | HXGE_DDI_FAILED);
2149 	}
2150 
2151 	if (dma_p->alength < length) {
2152 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
2153 		    "hxge_dma_mem_alloc:ddi_dma_mem_alloc < length."));
2154 		ddi_dma_mem_free(&dma_p->acc_handle);
2155 		ddi_dma_free_handle(&dma_p->dma_handle);
2156 		dma_p->acc_handle = NULL;
2157 		dma_p->dma_handle = NULL;
2158 		return (HXGE_ERROR);
2159 	}
2160 
2161 	ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL,
2162 	    kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0,
2163 	    &dma_p->dma_cookie, &dma_p->ncookies);
2164 	if (ddi_status != DDI_DMA_MAPPED) {
2165 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
2166 		    "hxge_dma_mem_alloc:di_dma_addr_bind failed "
2167 		    "(staus 0x%x ncookies %d.)", ddi_status, dma_p->ncookies));
2168 		if (dma_p->acc_handle) {
2169 			ddi_dma_mem_free(&dma_p->acc_handle);
2170 			dma_p->acc_handle = NULL;
2171 		}
2172 		ddi_dma_free_handle(&dma_p->dma_handle);
2173 		dma_p->dma_handle = NULL;
2174 		return (HXGE_ERROR | HXGE_DDI_FAILED);
2175 	}
2176 
2177 	if (dma_p->ncookies != 1) {
2178 		HXGE_DEBUG_MSG((hxgep, DMA_CTL,
2179 		    "hxge_dma_mem_alloc:ddi_dma_addr_bind > 1 cookie"
2180 		    "(staus 0x%x ncookies %d.)", ddi_status, dma_p->ncookies));
2181 		if (dma_p->acc_handle) {
2182 			ddi_dma_mem_free(&dma_p->acc_handle);
2183 			dma_p->acc_handle = NULL;
2184 		}
2185 		(void) ddi_dma_unbind_handle(dma_p->dma_handle);
2186 		ddi_dma_free_handle(&dma_p->dma_handle);
2187 		dma_p->dma_handle = NULL;
2188 		return (HXGE_ERROR);
2189 	}
2190 
2191 	dma_p->kaddrp = kaddrp;
2192 #if defined(__i386)
2193 	dma_p->ioaddr_pp =
2194 	    (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress;
2195 #else
2196 	dma_p->ioaddr_pp = (unsigned char *) dma_p->dma_cookie.dmac_laddress;
2197 #endif
2198 
2199 	HPI_DMA_ACC_HANDLE_SET(dma_p, dma_p->acc_handle);
2200 
2201 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_dma_mem_alloc: "
2202 	    "dma buffer allocated: dma_p $%p "
2203 	    "return dmac_ladress from cookie $%p dmac_size %d "
2204 	    "dma_p->ioaddr_p $%p "
2205 	    "dma_p->orig_ioaddr_p $%p "
2206 	    "orig_vatopa $%p "
2207 	    "alength %d (0x%x) "
2208 	    "kaddrp $%p "
2209 	    "length %d (0x%x)",
2210 	    dma_p,
2211 	    dma_p->dma_cookie.dmac_laddress,
2212 	    dma_p->dma_cookie.dmac_size,
2213 	    dma_p->ioaddr_pp,
2214 	    dma_p->orig_ioaddr_pp,
2215 	    dma_p->orig_vatopa,
2216 	    dma_p->alength, dma_p->alength,
2217 	    kaddrp,
2218 	    length, length));
2219 
2220 	return (HXGE_OK);
2221 }
2222 
2223 static void
2224 hxge_dma_mem_free(p_hxge_dma_common_t dma_p)
2225 {
2226 	if (dma_p->dma_handle != NULL) {
2227 		if (dma_p->ncookies) {
2228 			(void) ddi_dma_unbind_handle(dma_p->dma_handle);
2229 			dma_p->ncookies = 0;
2230 		}
2231 		ddi_dma_free_handle(&dma_p->dma_handle);
2232 		dma_p->dma_handle = NULL;
2233 	}
2234 	if (dma_p->acc_handle != NULL) {
2235 		ddi_dma_mem_free(&dma_p->acc_handle);
2236 		dma_p->acc_handle = NULL;
2237 		HPI_DMA_ACC_HANDLE_SET(dma_p, NULL);
2238 	}
2239 	dma_p->kaddrp = NULL;
2240 	dma_p->alength = NULL;
2241 }
2242 
2243 /*
2244  *	hxge_m_start() -- start transmitting and receiving.
2245  *
2246  *	This function is called by the MAC layer when the first
2247  *	stream is open to prepare the hardware ready for sending
2248  *	and transmitting packets.
2249  */
2250 static int
2251 hxge_m_start(void *arg)
2252 {
2253 	p_hxge_t hxgep = (p_hxge_t)arg;
2254 
2255 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_start"));
2256 
2257 	MUTEX_ENTER(hxgep->genlock);
2258 
2259 	if (hxge_init(hxgep) != DDI_SUCCESS) {
2260 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
2261 		    "<== hxge_m_start: initialization failed"));
2262 		MUTEX_EXIT(hxgep->genlock);
2263 		return (EIO);
2264 	}
2265 
2266 	if (hxgep->hxge_mac_state != HXGE_MAC_STARTED) {
2267 		/*
2268 		 * Start timer to check the system error and tx hangs
2269 		 */
2270 		hxgep->hxge_timerid = hxge_start_timer(hxgep,
2271 		    hxge_check_hw_state, HXGE_CHECK_TIMER);
2272 
2273 		hxgep->hxge_mac_state = HXGE_MAC_STARTED;
2274 	}
2275 
2276 	MUTEX_EXIT(hxgep->genlock);
2277 
2278 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_start"));
2279 
2280 	return (0);
2281 }
2282 
2283 /*
2284  * hxge_m_stop(): stop transmitting and receiving.
2285  */
2286 static void
2287 hxge_m_stop(void *arg)
2288 {
2289 	p_hxge_t hxgep = (p_hxge_t)arg;
2290 
2291 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_stop"));
2292 
2293 	if (hxgep->hxge_timerid) {
2294 		hxge_stop_timer(hxgep, hxgep->hxge_timerid);
2295 		hxgep->hxge_timerid = 0;
2296 	}
2297 
2298 	MUTEX_ENTER(hxgep->genlock);
2299 
2300 	hxge_uninit(hxgep);
2301 
2302 	hxgep->hxge_mac_state = HXGE_MAC_STOPPED;
2303 
2304 	MUTEX_EXIT(hxgep->genlock);
2305 
2306 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_stop"));
2307 }
2308 
2309 static int
2310 hxge_m_unicst(void *arg, const uint8_t *macaddr)
2311 {
2312 	p_hxge_t		hxgep = (p_hxge_t)arg;
2313 	struct ether_addr	addrp;
2314 	hxge_status_t		status;
2315 
2316 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_m_unicst"));
2317 
2318 	bcopy(macaddr, (uint8_t *)&addrp, ETHERADDRL);
2319 
2320 	status = hxge_set_mac_addr(hxgep, &addrp);
2321 	if (status != HXGE_OK) {
2322 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
2323 		    "<== hxge_m_unicst: set unitcast failed"));
2324 		return (EINVAL);
2325 	}
2326 
2327 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_m_unicst"));
2328 
2329 	return (0);
2330 }
2331 
2332 static int
2333 hxge_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
2334 {
2335 	p_hxge_t		hxgep = (p_hxge_t)arg;
2336 	struct ether_addr	addrp;
2337 
2338 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_m_multicst: add %d", add));
2339 
2340 	bcopy(mca, (uint8_t *)&addrp, ETHERADDRL);
2341 
2342 	if (add) {
2343 		if (hxge_add_mcast_addr(hxgep, &addrp)) {
2344 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
2345 			    "<== hxge_m_multicst: add multicast failed"));
2346 			return (EINVAL);
2347 		}
2348 	} else {
2349 		if (hxge_del_mcast_addr(hxgep, &addrp)) {
2350 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
2351 			    "<== hxge_m_multicst: del multicast failed"));
2352 			return (EINVAL);
2353 		}
2354 	}
2355 
2356 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_m_multicst"));
2357 
2358 	return (0);
2359 }
2360 
2361 static int
2362 hxge_m_promisc(void *arg, boolean_t on)
2363 {
2364 	p_hxge_t hxgep = (p_hxge_t)arg;
2365 
2366 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_m_promisc: on %d", on));
2367 
2368 	if (hxge_set_promisc(hxgep, on)) {
2369 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
2370 		    "<== hxge_m_promisc: set promisc failed"));
2371 		return (EINVAL);
2372 	}
2373 
2374 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_m_promisc: on %d", on));
2375 
2376 	return (0);
2377 }
2378 
2379 static void
2380 hxge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
2381 {
2382 	p_hxge_t	hxgep = (p_hxge_t)arg;
2383 	struct iocblk	*iocp = (struct iocblk *)mp->b_rptr;
2384 	boolean_t	need_privilege;
2385 	int		err;
2386 	int		cmd;
2387 
2388 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_ioctl"));
2389 
2390 	iocp = (struct iocblk *)mp->b_rptr;
2391 	iocp->ioc_error = 0;
2392 	need_privilege = B_TRUE;
2393 	cmd = iocp->ioc_cmd;
2394 
2395 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_ioctl: cmd 0x%08x", cmd));
2396 	switch (cmd) {
2397 	default:
2398 		miocnak(wq, mp, 0, EINVAL);
2399 		HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_ioctl: invalid"));
2400 		return;
2401 
2402 	case LB_GET_INFO_SIZE:
2403 	case LB_GET_INFO:
2404 	case LB_GET_MODE:
2405 		need_privilege = B_FALSE;
2406 		break;
2407 
2408 	case LB_SET_MODE:
2409 		break;
2410 
2411 	case ND_GET:
2412 		need_privilege = B_FALSE;
2413 		break;
2414 	case ND_SET:
2415 		break;
2416 
2417 	case HXGE_GET64:
2418 	case HXGE_PUT64:
2419 	case HXGE_GET_TX_RING_SZ:
2420 	case HXGE_GET_TX_DESC:
2421 	case HXGE_TX_SIDE_RESET:
2422 	case HXGE_RX_SIDE_RESET:
2423 	case HXGE_GLOBAL_RESET:
2424 	case HXGE_RESET_MAC:
2425 	case HXGE_PUT_TCAM:
2426 	case HXGE_GET_TCAM:
2427 	case HXGE_RTRACE:
2428 
2429 		need_privilege = B_FALSE;
2430 		break;
2431 	}
2432 
2433 	if (need_privilege) {
2434 		err = secpolicy_net_config(iocp->ioc_cr, B_FALSE);
2435 		if (err != 0) {
2436 			miocnak(wq, mp, 0, err);
2437 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
2438 			    "<== hxge_m_ioctl: no priv"));
2439 			return;
2440 		}
2441 	}
2442 
2443 	switch (cmd) {
2444 	case ND_GET:
2445 		HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "ND_GET command"));
2446 	case ND_SET:
2447 		HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "ND_SET command"));
2448 		hxge_param_ioctl(hxgep, wq, mp, iocp);
2449 		break;
2450 
2451 	case LB_GET_MODE:
2452 	case LB_SET_MODE:
2453 	case LB_GET_INFO_SIZE:
2454 	case LB_GET_INFO:
2455 		hxge_loopback_ioctl(hxgep, wq, mp, iocp);
2456 		break;
2457 
2458 	case HXGE_PUT_TCAM:
2459 	case HXGE_GET_TCAM:
2460 	case HXGE_GET64:
2461 	case HXGE_PUT64:
2462 	case HXGE_GET_TX_RING_SZ:
2463 	case HXGE_GET_TX_DESC:
2464 	case HXGE_TX_SIDE_RESET:
2465 	case HXGE_RX_SIDE_RESET:
2466 	case HXGE_GLOBAL_RESET:
2467 	case HXGE_RESET_MAC:
2468 		HXGE_DEBUG_MSG((hxgep, NEMO_CTL,
2469 		    "==> hxge_m_ioctl: cmd 0x%x", cmd));
2470 		hxge_hw_ioctl(hxgep, wq, mp, iocp);
2471 		break;
2472 	}
2473 
2474 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_ioctl"));
2475 }
2476 
2477 extern void hxge_rx_hw_blank(void *arg, time_t ticks, uint_t count);
2478 
2479 static void
2480 hxge_m_resources(void *arg)
2481 {
2482 	p_hxge_t hxgep = arg;
2483 	mac_rx_fifo_t mrf;
2484 	p_rx_rcr_rings_t rcr_rings;
2485 	p_rx_rcr_ring_t *rcr_p;
2486 	p_rx_rcr_ring_t rcrp;
2487 	uint32_t i, ndmas;
2488 	int status;
2489 
2490 	HXGE_DEBUG_MSG((hxgep, RX_CTL, "==> hxge_m_resources"));
2491 
2492 	MUTEX_ENTER(hxgep->genlock);
2493 
2494 	if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) {
2495 		status = hxge_init(hxgep);
2496 		if (status != HXGE_OK) {
2497 			HXGE_DEBUG_MSG((hxgep, RX_CTL, "==> hxge_m_resources: "
2498 			    "hxge_init failed"));
2499 			MUTEX_EXIT(hxgep->genlock);
2500 			return;
2501 		}
2502 	}
2503 
2504 	mrf.mrf_type = MAC_RX_FIFO;
2505 	mrf.mrf_blank = hxge_rx_hw_blank;
2506 
2507 	mrf.mrf_normal_blank_time = RXDMA_RCR_PTHRES_DEFAULT;
2508 	mrf.mrf_normal_pkt_count = RXDMA_RCR_TO_DEFAULT;
2509 
2510 	rcr_rings = hxgep->rx_rcr_rings;
2511 	rcr_p = rcr_rings->rcr_rings;
2512 	ndmas = rcr_rings->ndmas;
2513 
2514 	/*
2515 	 * Export our receive resources to the MAC layer.
2516 	 */
2517 	for (i = 0; i < ndmas; i++) {
2518 		rcrp = (void *)(p_rx_rcr_ring_t)rcr_p[i];
2519 		mrf.mrf_arg = rcrp;
2520 		rcrp->rcr_mac_handle =
2521 		    mac_resource_add(hxgep->mach, (mac_resource_t *)&mrf);
2522 
2523 		HXGE_DEBUG_MSG((hxgep, RX_CTL,
2524 		    "==> hxge_m_resources: vdma %d dma %d "
2525 		    "rcrptr 0x%016llx mac_handle 0x%016llx",
2526 		    i, rcrp->rdc, rcr_p[i], rcrp->rcr_mac_handle));
2527 	}
2528 
2529 	MUTEX_EXIT(hxgep->genlock);
2530 
2531 	HXGE_DEBUG_MSG((hxgep, RX_CTL, "<== hxge_m_resources"));
2532 }
2533 
2534 /*
2535  * Set an alternate MAC address
2536  */
2537 static int
2538 hxge_altmac_set(p_hxge_t hxgep, uint8_t *maddr, mac_addr_slot_t slot)
2539 {
2540 	uint64_t	address;
2541 	uint64_t	tmp;
2542 	hpi_status_t	status;
2543 	uint8_t		addrn;
2544 	int		i;
2545 
2546 	/*
2547 	 * Convert a byte array to a 48 bit value.
2548 	 * Need to check endianess if in doubt
2549 	 */
2550 	address = 0;
2551 	for (i = 0; i < ETHERADDRL; i++) {
2552 		tmp = maddr[i];
2553 		address <<= 8;
2554 		address |= tmp;
2555 	}
2556 
2557 	addrn = (uint8_t)slot;
2558 	status = hpi_pfc_set_mac_address(hxgep->hpi_handle, addrn, address);
2559 	if (status != HPI_SUCCESS)
2560 		return (EIO);
2561 
2562 	return (0);
2563 }
2564 
2565 static void
2566 hxge_mmac_kstat_update(p_hxge_t hxgep, mac_addr_slot_t slot)
2567 {
2568 	p_hxge_mmac_stats_t	mmac_stats;
2569 	int			i;
2570 	hxge_mmac_t		*mmac_info;
2571 
2572 	mmac_info = &hxgep->hxge_mmac_info;
2573 	mmac_stats = &hxgep->statsp->mmac_stats;
2574 	mmac_stats->mmac_max_cnt = mmac_info->num_mmac;
2575 	mmac_stats->mmac_avail_cnt = mmac_info->naddrfree;
2576 
2577 	for (i = 0; i < ETHERADDRL; i++) {
2578 		mmac_stats->mmac_avail_pool[slot].ether_addr_octet[i] =
2579 		    mmac_info->mac_pool[slot].addr[(ETHERADDRL - 1) - i];
2580 	}
2581 }
2582 
2583 /*
2584  * Find an unused address slot, set the address value to the one specified,
2585  * enable the port to start filtering on the new MAC address.
2586  * Returns: 0 on success.
2587  */
2588 int
2589 hxge_m_mmac_add(void *arg, mac_multi_addr_t *maddr)
2590 {
2591 	p_hxge_t	hxgep = arg;
2592 	mac_addr_slot_t	slot;
2593 	hxge_mmac_t	*mmac_info;
2594 	int		err;
2595 	hxge_status_t	status;
2596 
2597 	mutex_enter(hxgep->genlock);
2598 
2599 	/*
2600 	 * Make sure that hxge is initialized, if _start() has
2601 	 * not been called.
2602 	 */
2603 	if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) {
2604 		status = hxge_init(hxgep);
2605 		if (status != HXGE_OK) {
2606 			mutex_exit(hxgep->genlock);
2607 			return (ENXIO);
2608 		}
2609 	}
2610 
2611 	mmac_info = &hxgep->hxge_mmac_info;
2612 	if (mmac_info->naddrfree == 0) {
2613 		mutex_exit(hxgep->genlock);
2614 		return (ENOSPC);
2615 	}
2616 
2617 	if (!mac_unicst_verify(hxgep->mach, maddr->mma_addr,
2618 	    maddr->mma_addrlen)) {
2619 		mutex_exit(hxgep->genlock);
2620 		return (EINVAL);
2621 	}
2622 
2623 	/*
2624 	 * Search for the first available slot. Because naddrfree
2625 	 * is not zero, we are guaranteed to find one.
2626 	 * Slot 0 is for unique (primary) MAC.  The first alternate
2627 	 * MAC slot is slot 1.
2628 	 */
2629 	for (slot = 1; slot < mmac_info->num_mmac; slot++) {
2630 		if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED))
2631 			break;
2632 	}
2633 
2634 	ASSERT(slot < mmac_info->num_mmac);
2635 	if ((err = hxge_altmac_set(hxgep, maddr->mma_addr, slot)) != 0) {
2636 		mutex_exit(hxgep->genlock);
2637 		return (err);
2638 	}
2639 	bcopy(maddr->mma_addr, mmac_info->mac_pool[slot].addr, ETHERADDRL);
2640 	mmac_info->mac_pool[slot].flags |= MMAC_SLOT_USED;
2641 	mmac_info->naddrfree--;
2642 	hxge_mmac_kstat_update(hxgep, slot);
2643 
2644 	maddr->mma_slot = slot;
2645 
2646 	mutex_exit(hxgep->genlock);
2647 	return (0);
2648 }
2649 
2650 /*
2651  * Remove the specified mac address and update
2652  * the h/w not to filter the mac address anymore.
2653  * Returns: 0, on success.
2654  */
2655 int
2656 hxge_m_mmac_remove(void *arg, mac_addr_slot_t slot)
2657 {
2658 	p_hxge_t	hxgep = arg;
2659 	hxge_mmac_t	*mmac_info;
2660 	int		err = 0;
2661 	hxge_status_t	status;
2662 
2663 	mutex_enter(hxgep->genlock);
2664 
2665 	/*
2666 	 * Make sure that hxge is initialized, if _start() has
2667 	 * not been called.
2668 	 */
2669 	if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) {
2670 		status = hxge_init(hxgep);
2671 		if (status != HXGE_OK) {
2672 			mutex_exit(hxgep->genlock);
2673 			return (ENXIO);
2674 		}
2675 	}
2676 
2677 	mmac_info = &hxgep->hxge_mmac_info;
2678 	if (slot <= 0 || slot >= mmac_info->num_mmac) {
2679 		mutex_exit(hxgep->genlock);
2680 		return (EINVAL);
2681 	}
2682 
2683 	if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) {
2684 		if (hpi_pfc_mac_addr_disable(hxgep->hpi_handle, slot) ==
2685 		    HPI_SUCCESS) {
2686 			mmac_info->mac_pool[slot].flags &= ~MMAC_SLOT_USED;
2687 			mmac_info->naddrfree++;
2688 			/*
2689 			 * Clear mac_pool[slot].addr so that kstat shows 0
2690 			 * alternate MAC address if the slot is not used.
2691 			 */
2692 			bzero(mmac_info->mac_pool[slot].addr, ETHERADDRL);
2693 			hxge_mmac_kstat_update(hxgep, slot);
2694 		} else {
2695 			err = EIO;
2696 		}
2697 	} else {
2698 		err = EINVAL;
2699 	}
2700 
2701 	mutex_exit(hxgep->genlock);
2702 	return (err);
2703 }
2704 
2705 /*
2706  * Modify a mac address added by hxge_mmac_add().
2707  * Returns: 0, on success.
2708  */
2709 int
2710 hxge_m_mmac_modify(void *arg, mac_multi_addr_t *maddr)
2711 {
2712 	p_hxge_t	hxgep = arg;
2713 	mac_addr_slot_t	slot;
2714 	hxge_mmac_t	*mmac_info;
2715 	int		err = 0;
2716 	hxge_status_t	status;
2717 
2718 	if (!mac_unicst_verify(hxgep->mach, maddr->mma_addr,
2719 	    maddr->mma_addrlen))
2720 		return (EINVAL);
2721 
2722 	slot = maddr->mma_slot;
2723 
2724 	mutex_enter(hxgep->genlock);
2725 
2726 	/*
2727 	 * Make sure that hxge is initialized, if _start() has
2728 	 * not been called.
2729 	 */
2730 	if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) {
2731 		status = hxge_init(hxgep);
2732 		if (status != HXGE_OK) {
2733 			mutex_exit(hxgep->genlock);
2734 			return (ENXIO);
2735 		}
2736 	}
2737 
2738 	mmac_info = &hxgep->hxge_mmac_info;
2739 	if (slot <= 0 || slot >= mmac_info->num_mmac) {
2740 		mutex_exit(hxgep->genlock);
2741 		return (EINVAL);
2742 	}
2743 
2744 	if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) {
2745 		if ((err = hxge_altmac_set(hxgep, maddr->mma_addr,
2746 		    slot)) == 0) {
2747 			bcopy(maddr->mma_addr, mmac_info->mac_pool[slot].addr,
2748 			    ETHERADDRL);
2749 			hxge_mmac_kstat_update(hxgep, slot);
2750 		}
2751 	} else {
2752 		err = EINVAL;
2753 	}
2754 
2755 	mutex_exit(hxgep->genlock);
2756 	return (err);
2757 }
2758 
2759 /*
2760  * static int
2761  * hxge_m_mmac_get() - Get the MAC address and other information
2762  *	related to the slot.  mma_flags should be set to 0 in the call.
2763  *	Note: although kstat shows MAC address as zero when a slot is
2764  *	not used, Crossbow expects hxge_m_mmac_get to copy factory MAC
2765  *	to the caller as long as the slot is not using a user MAC address.
2766  *	The following table shows the rules,
2767  *
2768  *     					USED    VENDOR    mma_addr
2769  *	------------------------------------------------------------
2770  *	(1) Slot uses a user MAC:	yes      no     user MAC
2771  *	(2) Slot uses a factory MAC:    yes      yes    factory MAC
2772  *	(3) Slot is not used but is
2773  *	     factory MAC capable:	no       yes    factory MAC
2774  *	(4) Slot is not used and is
2775  *	     not factory MAC capable:   no       no	0
2776  *	------------------------------------------------------------
2777  */
2778 int
2779 hxge_m_mmac_get(void *arg, mac_multi_addr_t *maddr)
2780 {
2781 	hxge_t		*hxgep = arg;
2782 	mac_addr_slot_t	slot;
2783 	hxge_mmac_t	*mmac_info;
2784 	hxge_status_t	status;
2785 
2786 	slot = maddr->mma_slot;
2787 
2788 	mutex_enter(hxgep->genlock);
2789 
2790 	/*
2791 	 * Make sure that hxge is initialized, if _start() has
2792 	 * not been called.
2793 	 */
2794 	if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) {
2795 		status = hxge_init(hxgep);
2796 		if (status != HXGE_OK) {
2797 			mutex_exit(hxgep->genlock);
2798 			return (ENXIO);
2799 		}
2800 	}
2801 
2802 	mmac_info = &hxgep->hxge_mmac_info;
2803 	if (slot <= 0 || slot >= mmac_info->num_mmac) {
2804 		mutex_exit(hxgep->genlock);
2805 		return (EINVAL);
2806 	}
2807 
2808 	maddr->mma_flags = 0;
2809 	if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) {
2810 		maddr->mma_flags |= MMAC_SLOT_USED;
2811 		bcopy(mmac_info->mac_pool[slot].addr,
2812 		    maddr->mma_addr, ETHERADDRL);
2813 		maddr->mma_addrlen = ETHERADDRL;
2814 	}
2815 
2816 	mutex_exit(hxgep->genlock);
2817 	return (0);
2818 }
2819 
2820 /*ARGSUSED*/
2821 boolean_t
2822 hxge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
2823 {
2824 	p_hxge_t		hxgep = (p_hxge_t)arg;
2825 	uint32_t		*txflags = cap_data;
2826 	multiaddress_capab_t	*mmacp = cap_data;
2827 
2828 	switch (cap) {
2829 	case MAC_CAPAB_HCKSUM:
2830 		*txflags = HCKSUM_INET_PARTIAL;
2831 		break;
2832 
2833 	case MAC_CAPAB_POLL:
2834 		/*
2835 		 * There's nothing for us to fill in, simply returning B_TRUE
2836 		 * stating that we support polling is sufficient.
2837 		 */
2838 		break;
2839 
2840 	case MAC_CAPAB_MULTIADDRESS:
2841 		/*
2842 		 * The number of MAC addresses made available by
2843 		 * this capability is one less than the total as
2844 		 * the primary address in slot 0 is counted in
2845 		 * the total.
2846 		 */
2847 		mmacp->maddr_naddr = PFC_N_MAC_ADDRESSES - 1;
2848 		mmacp->maddr_naddrfree = hxgep->hxge_mmac_info.naddrfree;
2849 		mmacp->maddr_flag = 0;	/* No multiple factory macs */
2850 		mmacp->maddr_handle = hxgep;
2851 		mmacp->maddr_add = hxge_m_mmac_add;
2852 		mmacp->maddr_remove = hxge_m_mmac_remove;
2853 		mmacp->maddr_modify = hxge_m_mmac_modify;
2854 		mmacp->maddr_get = hxge_m_mmac_get;
2855 		mmacp->maddr_reserve = NULL;	/* No multiple factory macs */
2856 		break;
2857 	default:
2858 		return (B_FALSE);
2859 	}
2860 	return (B_TRUE);
2861 }
2862 
2863 /*
2864  * Module loading and removing entry points.
2865  */
2866 DDI_DEFINE_STREAM_OPS(hxge_dev_ops, nulldev, nulldev, hxge_attach, hxge_detach,
2867     nodev, NULL, D_MP, NULL);
2868 
2869 extern struct mod_ops mod_driverops;
2870 
2871 #define	HXGE_DESC_VER	"HXGE 10Gb Ethernet Driver"
2872 
2873 /*
2874  * Module linkage information for the kernel.
2875  */
2876 static struct modldrv hxge_modldrv = {
2877 	&mod_driverops,
2878 	HXGE_DESC_VER,
2879 	&hxge_dev_ops
2880 };
2881 
2882 static struct modlinkage modlinkage = {
2883 	MODREV_1, (void *) &hxge_modldrv, NULL
2884 };
2885 
2886 int
2887 _init(void)
2888 {
2889 	int status;
2890 
2891 	HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _init"));
2892 	mac_init_ops(&hxge_dev_ops, "hxge");
2893 	status = ddi_soft_state_init(&hxge_list, sizeof (hxge_t), 0);
2894 	if (status != 0) {
2895 		HXGE_ERROR_MSG((NULL, HXGE_ERR_CTL,
2896 		    "failed to init device soft state"));
2897 		mac_fini_ops(&hxge_dev_ops);
2898 		goto _init_exit;
2899 	}
2900 
2901 	status = mod_install(&modlinkage);
2902 	if (status != 0) {
2903 		ddi_soft_state_fini(&hxge_list);
2904 		HXGE_ERROR_MSG((NULL, HXGE_ERR_CTL, "Mod install failed"));
2905 		goto _init_exit;
2906 	}
2907 
2908 	MUTEX_INIT(&hxge_common_lock, NULL, MUTEX_DRIVER, NULL);
2909 
2910 _init_exit:
2911 	HXGE_DEBUG_MSG((NULL, MOD_CTL, "_init status = 0x%X", status));
2912 
2913 	return (status);
2914 }
2915 
2916 int
2917 _fini(void)
2918 {
2919 	int status;
2920 
2921 	HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini"));
2922 
2923 	HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini: mod_remove"));
2924 
2925 	if (hxge_mblks_pending)
2926 		return (EBUSY);
2927 
2928 	status = mod_remove(&modlinkage);
2929 	if (status != DDI_SUCCESS) {
2930 		HXGE_DEBUG_MSG((NULL, MOD_CTL,
2931 		    "Module removal failed 0x%08x", status));
2932 		goto _fini_exit;
2933 	}
2934 
2935 	mac_fini_ops(&hxge_dev_ops);
2936 
2937 	ddi_soft_state_fini(&hxge_list);
2938 
2939 	MUTEX_DESTROY(&hxge_common_lock);
2940 
2941 _fini_exit:
2942 	HXGE_DEBUG_MSG((NULL, MOD_CTL, "_fini status = 0x%08x", status));
2943 
2944 	return (status);
2945 }
2946 
2947 int
2948 _info(struct modinfo *modinfop)
2949 {
2950 	int status;
2951 
2952 	HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _info"));
2953 	status = mod_info(&modlinkage, modinfop);
2954 	HXGE_DEBUG_MSG((NULL, MOD_CTL, " _info status = 0x%X", status));
2955 
2956 	return (status);
2957 }
2958 
2959 /*ARGSUSED*/
2960 hxge_status_t
2961 hxge_add_intrs(p_hxge_t hxgep)
2962 {
2963 	int		intr_types;
2964 	int		type = 0;
2965 	int		ddi_status = DDI_SUCCESS;
2966 	hxge_status_t	status = HXGE_OK;
2967 
2968 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs"));
2969 
2970 	hxgep->hxge_intr_type.intr_registered = B_FALSE;
2971 	hxgep->hxge_intr_type.intr_enabled = B_FALSE;
2972 	hxgep->hxge_intr_type.msi_intx_cnt = 0;
2973 	hxgep->hxge_intr_type.intr_added = 0;
2974 	hxgep->hxge_intr_type.niu_msi_enable = B_FALSE;
2975 	hxgep->hxge_intr_type.intr_type = 0;
2976 
2977 	if (hxge_msi_enable) {
2978 		hxgep->hxge_intr_type.niu_msi_enable = B_TRUE;
2979 	}
2980 
2981 	/* Get the supported interrupt types */
2982 	if ((ddi_status = ddi_intr_get_supported_types(hxgep->dip, &intr_types))
2983 	    != DDI_SUCCESS) {
2984 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "<== hxge_add_intrs: "
2985 		    "ddi_intr_get_supported_types failed: status 0x%08x",
2986 		    ddi_status));
2987 		return (HXGE_ERROR | HXGE_DDI_FAILED);
2988 	}
2989 
2990 	hxgep->hxge_intr_type.intr_types = intr_types;
2991 
2992 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: "
2993 	    "ddi_intr_get_supported_types: 0x%08x", intr_types));
2994 
2995 	/*
2996 	 * Pick the interrupt type to use MSIX, MSI, INTX hxge_msi_enable:
2997 	 *	(1): 1 - MSI
2998 	 *	(2): 2 - MSI-X
2999 	 *	others - FIXED
3000 	 */
3001 	switch (hxge_msi_enable) {
3002 	default:
3003 		type = DDI_INTR_TYPE_FIXED;
3004 		HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: "
3005 		    "use fixed (intx emulation) type %08x", type));
3006 		break;
3007 
3008 	case 2:
3009 		HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: "
3010 		    "ddi_intr_get_supported_types: 0x%08x", intr_types));
3011 		if (intr_types & DDI_INTR_TYPE_MSIX) {
3012 			type = DDI_INTR_TYPE_MSIX;
3013 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
3014 			    "==> hxge_add_intrs: "
3015 			    "ddi_intr_get_supported_types: MSIX 0x%08x", type));
3016 		} else if (intr_types & DDI_INTR_TYPE_MSI) {
3017 			type = DDI_INTR_TYPE_MSI;
3018 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
3019 			    "==> hxge_add_intrs: "
3020 			    "ddi_intr_get_supported_types: MSI 0x%08x", type));
3021 		} else if (intr_types & DDI_INTR_TYPE_FIXED) {
3022 			type = DDI_INTR_TYPE_FIXED;
3023 			HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: "
3024 			    "ddi_intr_get_supported_types: MSXED0x%08x", type));
3025 		}
3026 		break;
3027 
3028 	case 1:
3029 		if (intr_types & DDI_INTR_TYPE_MSI) {
3030 			type = DDI_INTR_TYPE_MSI;
3031 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
3032 			    "==> hxge_add_intrs: "
3033 			    "ddi_intr_get_supported_types: MSI 0x%08x", type));
3034 		} else if (intr_types & DDI_INTR_TYPE_MSIX) {
3035 			type = DDI_INTR_TYPE_MSIX;
3036 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
3037 			    "==> hxge_add_intrs: "
3038 			    "ddi_intr_get_supported_types: MSIX 0x%08x", type));
3039 		} else if (intr_types & DDI_INTR_TYPE_FIXED) {
3040 			type = DDI_INTR_TYPE_FIXED;
3041 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
3042 			    "==> hxge_add_intrs: "
3043 			    "ddi_intr_get_supported_types: MSXED0x%08x", type));
3044 		}
3045 	}
3046 
3047 	hxgep->hxge_intr_type.intr_type = type;
3048 	if ((type == DDI_INTR_TYPE_MSIX || type == DDI_INTR_TYPE_MSI ||
3049 	    type == DDI_INTR_TYPE_FIXED) &&
3050 	    hxgep->hxge_intr_type.niu_msi_enable) {
3051 		if ((status = hxge_add_intrs_adv(hxgep)) != DDI_SUCCESS) {
3052 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
3053 			    " hxge_add_intrs: "
3054 			    " hxge_add_intrs_adv failed: status 0x%08x",
3055 			    status));
3056 			return (status);
3057 		} else {
3058 			HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_add_intrs: "
3059 			    "interrupts registered : type %d", type));
3060 			hxgep->hxge_intr_type.intr_registered = B_TRUE;
3061 
3062 			HXGE_DEBUG_MSG((hxgep, DDI_CTL,
3063 			    "\nAdded advanced hxge add_intr_adv "
3064 			    "intr type 0x%x\n", type));
3065 
3066 			return (status);
3067 		}
3068 	}
3069 
3070 	if (!hxgep->hxge_intr_type.intr_registered) {
3071 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
3072 		    "==> hxge_add_intrs: failed to register interrupts"));
3073 		return (HXGE_ERROR | HXGE_DDI_FAILED);
3074 	}
3075 
3076 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs"));
3077 
3078 	return (status);
3079 }
3080 
3081 /*ARGSUSED*/
3082 static hxge_status_t
3083 hxge_add_soft_intrs(p_hxge_t hxgep)
3084 {
3085 	int		ddi_status = DDI_SUCCESS;
3086 	hxge_status_t	status = HXGE_OK;
3087 
3088 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_add_soft_intrs"));
3089 
3090 	hxgep->resched_id = NULL;
3091 	hxgep->resched_running = B_FALSE;
3092 	ddi_status = ddi_add_softintr(hxgep->dip, DDI_SOFTINT_LOW,
3093 	    &hxgep->resched_id, NULL, NULL, hxge_reschedule, (caddr_t)hxgep);
3094 	if (ddi_status != DDI_SUCCESS) {
3095 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "<== hxge_add_soft_intrs: "
3096 		    "ddi_add_softintrs failed: status 0x%08x", ddi_status));
3097 		return (HXGE_ERROR | HXGE_DDI_FAILED);
3098 	}
3099 
3100 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_ddi_add_soft_intrs"));
3101 
3102 	return (status);
3103 }
3104 
3105 /*ARGSUSED*/
3106 static hxge_status_t
3107 hxge_add_intrs_adv(p_hxge_t hxgep)
3108 {
3109 	int		intr_type;
3110 	p_hxge_intr_t	intrp;
3111 	hxge_status_t	status;
3112 
3113 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv"));
3114 
3115 	intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
3116 	intr_type = intrp->intr_type;
3117 
3118 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv: type 0x%x",
3119 	    intr_type));
3120 
3121 	switch (intr_type) {
3122 	case DDI_INTR_TYPE_MSI:		/* 0x2 */
3123 	case DDI_INTR_TYPE_MSIX:	/* 0x4 */
3124 		status = hxge_add_intrs_adv_type(hxgep, intr_type);
3125 		break;
3126 
3127 	case DDI_INTR_TYPE_FIXED:	/* 0x1 */
3128 		status = hxge_add_intrs_adv_type_fix(hxgep, intr_type);
3129 		break;
3130 
3131 	default:
3132 		status = HXGE_ERROR;
3133 		break;
3134 	}
3135 
3136 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs_adv"));
3137 
3138 	return (status);
3139 }
3140 
3141 /*ARGSUSED*/
3142 static hxge_status_t
3143 hxge_add_intrs_adv_type(p_hxge_t hxgep, uint32_t int_type)
3144 {
3145 	dev_info_t	*dip = hxgep->dip;
3146 	p_hxge_ldg_t	ldgp;
3147 	p_hxge_intr_t	intrp;
3148 	uint_t		*inthandler;
3149 	void		*arg1, *arg2;
3150 	int		behavior;
3151 	int		nintrs, navail;
3152 	int		nactual, nrequired;
3153 	int		inum = 0;
3154 	int		loop = 0;
3155 	int		x, y;
3156 	int		ddi_status = DDI_SUCCESS;
3157 	hxge_status_t	status = HXGE_OK;
3158 
3159 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv_type"));
3160 
3161 	intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
3162 
3163 	ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs);
3164 	if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) {
3165 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
3166 		    "ddi_intr_get_nintrs() failed, status: 0x%x%, "
3167 		    "nintrs: %d", ddi_status, nintrs));
3168 		return (HXGE_ERROR | HXGE_DDI_FAILED);
3169 	}
3170 
3171 	ddi_status = ddi_intr_get_navail(dip, int_type, &navail);
3172 	if ((ddi_status != DDI_SUCCESS) || (navail == 0)) {
3173 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
3174 		    "ddi_intr_get_navail() failed, status: 0x%x%, "
3175 		    "nintrs: %d", ddi_status, navail));
3176 		return (HXGE_ERROR | HXGE_DDI_FAILED);
3177 	}
3178 
3179 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
3180 	    "ddi_intr_get_navail() returned: intr type %d nintrs %d, navail %d",
3181 	    int_type, nintrs, navail));
3182 
3183 	if (int_type == DDI_INTR_TYPE_MSI && !ISP2(navail)) {
3184 		/* MSI must be power of 2 */
3185 		if ((navail & 16) == 16) {
3186 			navail = 16;
3187 		} else if ((navail & 8) == 8) {
3188 			navail = 8;
3189 		} else if ((navail & 4) == 4) {
3190 			navail = 4;
3191 		} else if ((navail & 2) == 2) {
3192 			navail = 2;
3193 		} else {
3194 			navail = 1;
3195 		}
3196 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
3197 		    "ddi_intr_get_navail(): (msi power of 2) nintrs %d, "
3198 		    "navail %d", nintrs, navail));
3199 	}
3200 
3201 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
3202 	    "requesting: intr type %d nintrs %d, navail %d",
3203 	    int_type, nintrs, navail));
3204 
3205 	behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT :
3206 	    DDI_INTR_ALLOC_NORMAL);
3207 	intrp->intr_size = navail * sizeof (ddi_intr_handle_t);
3208 	intrp->htable = kmem_zalloc(intrp->intr_size, KM_SLEEP);
3209 
3210 	ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum,
3211 	    navail, &nactual, behavior);
3212 	if (ddi_status != DDI_SUCCESS || nactual == 0) {
3213 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
3214 		    " ddi_intr_alloc() failed: %d", ddi_status));
3215 		kmem_free(intrp->htable, intrp->intr_size);
3216 		return (HXGE_ERROR | HXGE_DDI_FAILED);
3217 	}
3218 
3219 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
3220 	    "ddi_intr_alloc() returned: navail %d nactual %d",
3221 	    navail, nactual));
3222 
3223 	if ((ddi_status = ddi_intr_get_pri(intrp->htable[0],
3224 	    (uint_t *)&intrp->pri)) != DDI_SUCCESS) {
3225 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
3226 		    " ddi_intr_get_pri() failed: %d", ddi_status));
3227 		/* Free already allocated interrupts */
3228 		for (y = 0; y < nactual; y++) {
3229 			(void) ddi_intr_free(intrp->htable[y]);
3230 		}
3231 
3232 		kmem_free(intrp->htable, intrp->intr_size);
3233 		return (HXGE_ERROR | HXGE_DDI_FAILED);
3234 	}
3235 
3236 	nrequired = 0;
3237 	status = hxge_ldgv_init(hxgep, &nactual, &nrequired);
3238 	if (status != HXGE_OK) {
3239 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
3240 		    "hxge_add_intrs_adv_typ:hxge_ldgv_init "
3241 		    "failed: 0x%x", status));
3242 		/* Free already allocated interrupts */
3243 		for (y = 0; y < nactual; y++) {
3244 			(void) ddi_intr_free(intrp->htable[y]);
3245 		}
3246 
3247 		kmem_free(intrp->htable, intrp->intr_size);
3248 		return (status);
3249 	}
3250 
3251 	ldgp = hxgep->ldgvp->ldgp;
3252 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
3253 	    "After hxge_ldgv_init(): nreq %d nactual %d", nrequired, nactual));
3254 
3255 	if (nactual < nrequired)
3256 		loop = nactual;
3257 	else
3258 		loop = nrequired;
3259 
3260 	for (x = 0; x < loop; x++, ldgp++) {
3261 		ldgp->vector = (uint8_t)x;
3262 		arg1 = ldgp->ldvp;
3263 		arg2 = hxgep;
3264 		if (ldgp->nldvs == 1) {
3265 			inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler;
3266 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
3267 			    "hxge_add_intrs_adv_type: arg1 0x%x arg2 0x%x: "
3268 			    "1-1 int handler (entry %d)\n",
3269 			    arg1, arg2, x));
3270 		} else if (ldgp->nldvs > 1) {
3271 			inthandler = (uint_t *)ldgp->sys_intr_handler;
3272 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
3273 			    "hxge_add_intrs_adv_type: arg1 0x%x arg2 0x%x: "
3274 			    "nldevs %d int handler (entry %d)\n",
3275 			    arg1, arg2, ldgp->nldvs, x));
3276 		}
3277 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
3278 		    "==> hxge_add_intrs_adv_type: ddi_add_intr(inum) #%d "
3279 		    "htable 0x%llx", x, intrp->htable[x]));
3280 
3281 		if ((ddi_status = ddi_intr_add_handler(intrp->htable[x],
3282 		    (ddi_intr_handler_t *)inthandler, arg1, arg2)) !=
3283 		    DDI_SUCCESS) {
3284 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
3285 			    "==> hxge_add_intrs_adv_type: failed #%d "
3286 			    "status 0x%x", x, ddi_status));
3287 			for (y = 0; y < intrp->intr_added; y++) {
3288 				(void) ddi_intr_remove_handler(
3289 				    intrp->htable[y]);
3290 			}
3291 
3292 			/* Free already allocated intr */
3293 			for (y = 0; y < nactual; y++) {
3294 				(void) ddi_intr_free(intrp->htable[y]);
3295 			}
3296 			kmem_free(intrp->htable, intrp->intr_size);
3297 
3298 			(void) hxge_ldgv_uninit(hxgep);
3299 
3300 			return (HXGE_ERROR | HXGE_DDI_FAILED);
3301 		}
3302 
3303 		intrp->intr_added++;
3304 	}
3305 	intrp->msi_intx_cnt = nactual;
3306 
3307 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
3308 	    "Requested: %d, Allowed: %d msi_intx_cnt %d intr_added %d",
3309 	    navail, nactual, intrp->msi_intx_cnt, intrp->intr_added));
3310 
3311 	(void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap);
3312 	(void) hxge_intr_ldgv_init(hxgep);
3313 
3314 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs_adv_type"));
3315 
3316 	return (status);
3317 }
3318 
3319 /*ARGSUSED*/
3320 static hxge_status_t
3321 hxge_add_intrs_adv_type_fix(p_hxge_t hxgep, uint32_t int_type)
3322 {
3323 	dev_info_t	*dip = hxgep->dip;
3324 	p_hxge_ldg_t	ldgp;
3325 	p_hxge_intr_t	intrp;
3326 	uint_t		*inthandler;
3327 	void		*arg1, *arg2;
3328 	int		behavior;
3329 	int		nintrs, navail;
3330 	int		nactual, nrequired;
3331 	int		inum = 0;
3332 	int		x, y;
3333 	int		ddi_status = DDI_SUCCESS;
3334 	hxge_status_t	status = HXGE_OK;
3335 
3336 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv_type_fix"));
3337 	intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
3338 
3339 	ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs);
3340 	if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) {
3341 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
3342 		    "ddi_intr_get_nintrs() failed, status: 0x%x%, "
3343 		    "nintrs: %d", status, nintrs));
3344 		return (HXGE_ERROR | HXGE_DDI_FAILED);
3345 	}
3346 
3347 	ddi_status = ddi_intr_get_navail(dip, int_type, &navail);
3348 	if ((ddi_status != DDI_SUCCESS) || (navail == 0)) {
3349 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
3350 		    "ddi_intr_get_navail() failed, status: 0x%x%, "
3351 		    "nintrs: %d", ddi_status, navail));
3352 		return (HXGE_ERROR | HXGE_DDI_FAILED);
3353 	}
3354 
3355 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
3356 	    "ddi_intr_get_navail() returned: nintrs %d, naavail %d",
3357 	    nintrs, navail));
3358 
3359 	behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT :
3360 	    DDI_INTR_ALLOC_NORMAL);
3361 	intrp->intr_size = navail * sizeof (ddi_intr_handle_t);
3362 	intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP);
3363 	ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum,
3364 	    navail, &nactual, behavior);
3365 	if (ddi_status != DDI_SUCCESS || nactual == 0) {
3366 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
3367 		    " ddi_intr_alloc() failed: %d", ddi_status));
3368 		kmem_free(intrp->htable, intrp->intr_size);
3369 		return (HXGE_ERROR | HXGE_DDI_FAILED);
3370 	}
3371 
3372 	if ((ddi_status = ddi_intr_get_pri(intrp->htable[0],
3373 	    (uint_t *)&intrp->pri)) != DDI_SUCCESS) {
3374 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
3375 		    " ddi_intr_get_pri() failed: %d", ddi_status));
3376 		/* Free already allocated interrupts */
3377 		for (y = 0; y < nactual; y++) {
3378 			(void) ddi_intr_free(intrp->htable[y]);
3379 		}
3380 
3381 		kmem_free(intrp->htable, intrp->intr_size);
3382 		return (HXGE_ERROR | HXGE_DDI_FAILED);
3383 	}
3384 
3385 	nrequired = 0;
3386 	status = hxge_ldgv_init(hxgep, &nactual, &nrequired);
3387 	if (status != HXGE_OK) {
3388 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
3389 		    "hxge_add_intrs_adv_type_fix:hxge_ldgv_init "
3390 		    "failed: 0x%x", status));
3391 		/* Free already allocated interrupts */
3392 		for (y = 0; y < nactual; y++) {
3393 			(void) ddi_intr_free(intrp->htable[y]);
3394 		}
3395 
3396 		kmem_free(intrp->htable, intrp->intr_size);
3397 		return (status);
3398 	}
3399 
3400 	ldgp = hxgep->ldgvp->ldgp;
3401 	for (x = 0; x < nrequired; x++, ldgp++) {
3402 		ldgp->vector = (uint8_t)x;
3403 		arg1 = ldgp->ldvp;
3404 		arg2 = hxgep;
3405 		if (ldgp->nldvs == 1) {
3406 			inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler;
3407 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
3408 			    "hxge_add_intrs_adv_type_fix: "
3409 			    "1-1 int handler(%d) ldg %d ldv %d "
3410 			    "arg1 $%p arg2 $%p\n",
3411 			    x, ldgp->ldg, ldgp->ldvp->ldv, arg1, arg2));
3412 		} else if (ldgp->nldvs > 1) {
3413 			inthandler = (uint_t *)ldgp->sys_intr_handler;
3414 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
3415 			    "hxge_add_intrs_adv_type_fix: "
3416 			    "shared ldv %d int handler(%d) ldv %d ldg %d"
3417 			    "arg1 0x%016llx arg2 0x%016llx\n",
3418 			    x, ldgp->nldvs, ldgp->ldg, ldgp->ldvp->ldv,
3419 			    arg1, arg2));
3420 		}
3421 
3422 		if ((ddi_status = ddi_intr_add_handler(intrp->htable[x],
3423 		    (ddi_intr_handler_t *)inthandler, arg1, arg2)) !=
3424 		    DDI_SUCCESS) {
3425 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
3426 			    "==> hxge_add_intrs_adv_type_fix: failed #%d "
3427 			    "status 0x%x", x, ddi_status));
3428 			for (y = 0; y < intrp->intr_added; y++) {
3429 				(void) ddi_intr_remove_handler(
3430 				    intrp->htable[y]);
3431 			}
3432 			for (y = 0; y < nactual; y++) {
3433 				(void) ddi_intr_free(intrp->htable[y]);
3434 			}
3435 			/* Free already allocated intr */
3436 			kmem_free(intrp->htable, intrp->intr_size);
3437 
3438 			(void) hxge_ldgv_uninit(hxgep);
3439 
3440 			return (HXGE_ERROR | HXGE_DDI_FAILED);
3441 		}
3442 		intrp->intr_added++;
3443 	}
3444 
3445 	intrp->msi_intx_cnt = nactual;
3446 
3447 	(void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap);
3448 
3449 	status = hxge_intr_ldgv_init(hxgep);
3450 
3451 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs_adv_type_fix"));
3452 
3453 	return (status);
3454 }
3455 
3456 /*ARGSUSED*/
3457 static void
3458 hxge_remove_intrs(p_hxge_t hxgep)
3459 {
3460 	int		i, inum;
3461 	p_hxge_intr_t	intrp;
3462 
3463 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_remove_intrs"));
3464 	intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
3465 	if (!intrp->intr_registered) {
3466 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
3467 		    "<== hxge_remove_intrs: interrupts not registered"));
3468 		return;
3469 	}
3470 
3471 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_remove_intrs:advanced"));
3472 
3473 	if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
3474 		(void) ddi_intr_block_disable(intrp->htable,
3475 		    intrp->intr_added);
3476 	} else {
3477 		for (i = 0; i < intrp->intr_added; i++) {
3478 			(void) ddi_intr_disable(intrp->htable[i]);
3479 		}
3480 	}
3481 
3482 	for (inum = 0; inum < intrp->intr_added; inum++) {
3483 		if (intrp->htable[inum]) {
3484 			(void) ddi_intr_remove_handler(intrp->htable[inum]);
3485 		}
3486 	}
3487 
3488 	for (inum = 0; inum < intrp->msi_intx_cnt; inum++) {
3489 		if (intrp->htable[inum]) {
3490 			HXGE_DEBUG_MSG((hxgep, DDI_CTL,
3491 			    "hxge_remove_intrs: ddi_intr_free inum %d "
3492 			    "msi_intx_cnt %d intr_added %d",
3493 			    inum, intrp->msi_intx_cnt, intrp->intr_added));
3494 
3495 			(void) ddi_intr_free(intrp->htable[inum]);
3496 		}
3497 	}
3498 
3499 	kmem_free(intrp->htable, intrp->intr_size);
3500 	intrp->intr_registered = B_FALSE;
3501 	intrp->intr_enabled = B_FALSE;
3502 	intrp->msi_intx_cnt = 0;
3503 	intrp->intr_added = 0;
3504 
3505 	(void) hxge_ldgv_uninit(hxgep);
3506 
3507 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_remove_intrs"));
3508 }
3509 
3510 /*ARGSUSED*/
3511 static void
3512 hxge_remove_soft_intrs(p_hxge_t hxgep)
3513 {
3514 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_remove_soft_intrs"));
3515 
3516 	if (hxgep->resched_id) {
3517 		ddi_remove_softintr(hxgep->resched_id);
3518 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
3519 		    "==> hxge_remove_soft_intrs: removed"));
3520 		hxgep->resched_id = NULL;
3521 	}
3522 
3523 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_remove_soft_intrs"));
3524 }
3525 
3526 /*ARGSUSED*/
3527 void
3528 hxge_intrs_enable(p_hxge_t hxgep)
3529 {
3530 	p_hxge_intr_t	intrp;
3531 	int		i;
3532 	int		status;
3533 
3534 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_enable"));
3535 
3536 	intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
3537 
3538 	if (!intrp->intr_registered) {
3539 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "<== hxge_intrs_enable: "
3540 		    "interrupts are not registered"));
3541 		return;
3542 	}
3543 
3544 	if (intrp->intr_enabled) {
3545 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
3546 		    "<== hxge_intrs_enable: already enabled"));
3547 		return;
3548 	}
3549 
3550 	if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
3551 		status = ddi_intr_block_enable(intrp->htable,
3552 		    intrp->intr_added);
3553 		HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_enable "
3554 		    "block enable - status 0x%x total inums #%d\n",
3555 		    status, intrp->intr_added));
3556 	} else {
3557 		for (i = 0; i < intrp->intr_added; i++) {
3558 			status = ddi_intr_enable(intrp->htable[i]);
3559 			HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_enable "
3560 			    "ddi_intr_enable:enable - status 0x%x "
3561 			    "total inums %d enable inum #%d\n",
3562 			    status, intrp->intr_added, i));
3563 			if (status == DDI_SUCCESS) {
3564 				intrp->intr_enabled = B_TRUE;
3565 			}
3566 		}
3567 	}
3568 
3569 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intrs_enable"));
3570 }
3571 
3572 /*ARGSUSED*/
3573 static void
3574 hxge_intrs_disable(p_hxge_t hxgep)
3575 {
3576 	p_hxge_intr_t	intrp;
3577 	int		i;
3578 
3579 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_disable"));
3580 
3581 	intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
3582 
3583 	if (!intrp->intr_registered) {
3584 		HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intrs_disable: "
3585 		    "interrupts are not registered"));
3586 		return;
3587 	}
3588 
3589 	if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
3590 		(void) ddi_intr_block_disable(intrp->htable,
3591 		    intrp->intr_added);
3592 	} else {
3593 		for (i = 0; i < intrp->intr_added; i++) {
3594 			(void) ddi_intr_disable(intrp->htable[i]);
3595 		}
3596 	}
3597 
3598 	intrp->intr_enabled = B_FALSE;
3599 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intrs_disable"));
3600 }
3601 
3602 static hxge_status_t
3603 hxge_mac_register(p_hxge_t hxgep)
3604 {
3605 	mac_register_t	*macp;
3606 	int		status;
3607 
3608 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_mac_register"));
3609 
3610 	if ((macp = mac_alloc(MAC_VERSION)) == NULL)
3611 		return (HXGE_ERROR);
3612 
3613 	macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
3614 	macp->m_driver = hxgep;
3615 	macp->m_dip = hxgep->dip;
3616 	macp->m_src_addr = hxgep->ouraddr.ether_addr_octet;
3617 
3618 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
3619 	    "hxge_mac_register: ether addr is %x:%x:%x:%x:%x:%x",
3620 	    macp->m_src_addr[0],
3621 	    macp->m_src_addr[1],
3622 	    macp->m_src_addr[2],
3623 	    macp->m_src_addr[3],
3624 	    macp->m_src_addr[4],
3625 	    macp->m_src_addr[5]));
3626 
3627 	macp->m_callbacks = &hxge_m_callbacks;
3628 	macp->m_min_sdu = 0;
3629 	macp->m_max_sdu = hxgep->vmac.maxframesize -
3630 	    sizeof (struct ether_header) - ETHERFCSL - 4 - TX_PKT_HEADER_SIZE;
3631 
3632 	status = mac_register(macp, &hxgep->mach);
3633 	mac_free(macp);
3634 
3635 	if (status != 0) {
3636 		cmn_err(CE_WARN,
3637 		    "hxge_mac_register failed (status %d instance %d)",
3638 		    status, hxgep->instance);
3639 		return (HXGE_ERROR);
3640 	}
3641 
3642 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_mac_register success "
3643 	    "(instance %d)", hxgep->instance));
3644 
3645 	return (HXGE_OK);
3646 }
3647 
3648 static int
3649 hxge_init_common_dev(p_hxge_t hxgep)
3650 {
3651 	p_hxge_hw_list_t	hw_p;
3652 	dev_info_t		*p_dip;
3653 
3654 	HXGE_DEBUG_MSG((hxgep, MOD_CTL, "==> hxge_init_common_dev"));
3655 
3656 	p_dip = hxgep->p_dip;
3657 	MUTEX_ENTER(&hxge_common_lock);
3658 
3659 	/*
3660 	 * Loop through existing per Hydra hardware list.
3661 	 */
3662 	for (hw_p = hxge_hw_list; hw_p; hw_p = hw_p->next) {
3663 		HXGE_DEBUG_MSG((hxgep, MOD_CTL,
3664 		    "==> hxge_init_common_dev: hw_p $%p parent dip $%p",
3665 		    hw_p, p_dip));
3666 		if (hw_p->parent_devp == p_dip) {
3667 			hxgep->hxge_hw_p = hw_p;
3668 			hw_p->ndevs++;
3669 			hw_p->hxge_p = hxgep;
3670 			HXGE_DEBUG_MSG((hxgep, MOD_CTL,
3671 			    "==> hxge_init_common_device: "
3672 			    "hw_p $%p parent dip $%p ndevs %d (found)",
3673 			    hw_p, p_dip, hw_p->ndevs));
3674 			break;
3675 		}
3676 	}
3677 
3678 	if (hw_p == NULL) {
3679 		HXGE_DEBUG_MSG((hxgep, MOD_CTL,
3680 		    "==> hxge_init_common_dev: parent dip $%p (new)", p_dip));
3681 		hw_p = kmem_zalloc(sizeof (hxge_hw_list_t), KM_SLEEP);
3682 		hw_p->parent_devp = p_dip;
3683 		hw_p->magic = HXGE_MAGIC;
3684 		hxgep->hxge_hw_p = hw_p;
3685 		hw_p->ndevs++;
3686 		hw_p->hxge_p = hxgep;
3687 		hw_p->next = hxge_hw_list;
3688 
3689 		MUTEX_INIT(&hw_p->hxge_cfg_lock, NULL, MUTEX_DRIVER, NULL);
3690 		MUTEX_INIT(&hw_p->hxge_tcam_lock, NULL, MUTEX_DRIVER, NULL);
3691 		MUTEX_INIT(&hw_p->hxge_vlan_lock, NULL, MUTEX_DRIVER, NULL);
3692 
3693 		hxge_hw_list = hw_p;
3694 	}
3695 	MUTEX_EXIT(&hxge_common_lock);
3696 	HXGE_DEBUG_MSG((hxgep, MOD_CTL,
3697 	    "==> hxge_init_common_dev (hxge_hw_list) $%p", hxge_hw_list));
3698 	HXGE_DEBUG_MSG((hxgep, MOD_CTL, "<== hxge_init_common_dev"));
3699 
3700 	return (HXGE_OK);
3701 }
3702 
3703 static void
3704 hxge_uninit_common_dev(p_hxge_t hxgep)
3705 {
3706 	p_hxge_hw_list_t	hw_p, h_hw_p;
3707 	dev_info_t		*p_dip;
3708 
3709 	HXGE_DEBUG_MSG((hxgep, MOD_CTL, "==> hxge_uninit_common_dev"));
3710 	if (hxgep->hxge_hw_p == NULL) {
3711 		HXGE_DEBUG_MSG((hxgep, MOD_CTL,
3712 		    "<== hxge_uninit_common_dev (no common)"));
3713 		return;
3714 	}
3715 
3716 	MUTEX_ENTER(&hxge_common_lock);
3717 	h_hw_p = hxge_hw_list;
3718 	for (hw_p = hxge_hw_list; hw_p; hw_p = hw_p->next) {
3719 		p_dip = hw_p->parent_devp;
3720 		if (hxgep->hxge_hw_p == hw_p && p_dip == hxgep->p_dip &&
3721 		    hxgep->hxge_hw_p->magic == HXGE_MAGIC &&
3722 		    hw_p->magic == HXGE_MAGIC) {
3723 			HXGE_DEBUG_MSG((hxgep, MOD_CTL,
3724 			    "==> hxge_uninit_common_dev: "
3725 			    "hw_p $%p parent dip $%p ndevs %d (found)",
3726 			    hw_p, p_dip, hw_p->ndevs));
3727 
3728 			hxgep->hxge_hw_p = NULL;
3729 			if (hw_p->ndevs) {
3730 				hw_p->ndevs--;
3731 			}
3732 			hw_p->hxge_p = NULL;
3733 			if (!hw_p->ndevs) {
3734 				MUTEX_DESTROY(&hw_p->hxge_vlan_lock);
3735 				MUTEX_DESTROY(&hw_p->hxge_tcam_lock);
3736 				MUTEX_DESTROY(&hw_p->hxge_cfg_lock);
3737 				HXGE_DEBUG_MSG((hxgep, MOD_CTL,
3738 				    "==> hxge_uninit_common_dev: "
3739 				    "hw_p $%p parent dip $%p ndevs %d (last)",
3740 				    hw_p, p_dip, hw_p->ndevs));
3741 
3742 				if (hw_p == hxge_hw_list) {
3743 					HXGE_DEBUG_MSG((hxgep, MOD_CTL,
3744 					    "==> hxge_uninit_common_dev:"
3745 					    "remove head "
3746 					    "hw_p $%p parent dip $%p "
3747 					    "ndevs %d (head)",
3748 					    hw_p, p_dip, hw_p->ndevs));
3749 					hxge_hw_list = hw_p->next;
3750 				} else {
3751 					HXGE_DEBUG_MSG((hxgep, MOD_CTL,
3752 					    "==> hxge_uninit_common_dev:"
3753 					    "remove middle "
3754 					    "hw_p $%p parent dip $%p "
3755 					    "ndevs %d (middle)",
3756 					    hw_p, p_dip, hw_p->ndevs));
3757 					h_hw_p->next = hw_p->next;
3758 				}
3759 
3760 				KMEM_FREE(hw_p, sizeof (hxge_hw_list_t));
3761 			}
3762 			break;
3763 		} else {
3764 			h_hw_p = hw_p;
3765 		}
3766 	}
3767 
3768 	MUTEX_EXIT(&hxge_common_lock);
3769 	HXGE_DEBUG_MSG((hxgep, MOD_CTL,
3770 	    "==> hxge_uninit_common_dev (hxge_hw_list) $%p", hxge_hw_list));
3771 
3772 	HXGE_DEBUG_MSG((hxgep, MOD_CTL, "<= hxge_uninit_common_dev"));
3773 }
3774