xref: /illumos-gate/usr/src/uts/common/io/hxge/hxge_main.c (revision 5422785d352a2bb398daceab3d1898a8aa64d006)
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 2010 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  * Copyright 2012 Milan Jurik. All rights reserved.
25  */
26 
27 /*
28  * SunOs MT STREAMS Hydra 10Gb Ethernet Device Driver.
29  */
30 #include <hxge_impl.h>
31 #include <hxge_pfc.h>
32 
33 /*
34  * PSARC/2007/453 MSI-X interrupt limit override
35  * (This PSARC case is limited to MSI-X vectors
36  *  and SPARC platforms only).
37  */
38 uint32_t hxge_msi_enable = 2;
39 
40 /*
41  * Globals: tunable parameters (/etc/system or adb)
42  *
43  */
44 uint32_t hxge_rbr_size = HXGE_RBR_RBB_DEFAULT;
45 uint32_t hxge_rbr_spare_size = 0;
46 uint32_t hxge_rcr_size = HXGE_RCR_DEFAULT;
47 uint32_t hxge_tx_ring_size = HXGE_TX_RING_DEFAULT;
48 uint32_t hxge_bcopy_thresh = TX_BCOPY_MAX;
49 uint32_t hxge_dvma_thresh = TX_FASTDVMA_MIN;
50 uint32_t hxge_dma_stream_thresh = TX_STREAM_MIN;
51 uint32_t hxge_jumbo_frame_size = MAX_FRAME_SIZE;
52 
53 static hxge_os_mutex_t hxgedebuglock;
54 static int hxge_debug_init = 0;
55 
56 /*
57  * Debugging flags:
58  *		hxge_no_tx_lb : transmit load balancing
59  *		hxge_tx_lb_policy: 0 - TCP/UDP port (default)
60  *				   1 - From the Stack
61  *				   2 - Destination IP Address
62  */
63 uint32_t hxge_no_tx_lb = 0;
64 uint32_t hxge_tx_lb_policy = HXGE_TX_LB_TCPUDP;
65 
66 /*
67  * Tunables to manage the receive buffer blocks.
68  *
69  * hxge_rx_threshold_hi: copy all buffers.
70  * hxge_rx_bcopy_size_type: receive buffer block size type.
71  * hxge_rx_threshold_lo: copy only up to tunable block size type.
72  */
73 #if defined(__sparc)
74 hxge_rxbuf_threshold_t hxge_rx_threshold_hi = HXGE_RX_COPY_6;
75 hxge_rxbuf_threshold_t hxge_rx_threshold_lo = HXGE_RX_COPY_4;
76 #else
77 hxge_rxbuf_threshold_t hxge_rx_threshold_hi = HXGE_RX_COPY_NONE;
78 hxge_rxbuf_threshold_t hxge_rx_threshold_lo = HXGE_RX_COPY_NONE;
79 #endif
80 hxge_rxbuf_type_t hxge_rx_buf_size_type = RCR_PKTBUFSZ_0;
81 
82 rtrace_t hpi_rtracebuf;
83 
84 /*
85  * Function Prototypes
86  */
87 static int hxge_attach(dev_info_t *, ddi_attach_cmd_t);
88 static int hxge_detach(dev_info_t *, ddi_detach_cmd_t);
89 static void hxge_unattach(p_hxge_t);
90 
91 static hxge_status_t hxge_setup_system_dma_pages(p_hxge_t);
92 
93 static hxge_status_t hxge_setup_mutexes(p_hxge_t);
94 static void hxge_destroy_mutexes(p_hxge_t);
95 
96 static hxge_status_t hxge_map_regs(p_hxge_t hxgep);
97 static void hxge_unmap_regs(p_hxge_t hxgep);
98 
99 static hxge_status_t hxge_add_intrs(p_hxge_t hxgep);
100 static void hxge_remove_intrs(p_hxge_t hxgep);
101 static hxge_status_t hxge_add_intrs_adv(p_hxge_t hxgep);
102 static hxge_status_t hxge_add_intrs_adv_type(p_hxge_t, uint32_t);
103 static hxge_status_t hxge_add_intrs_adv_type_fix(p_hxge_t, uint32_t);
104 static void hxge_intrs_enable(p_hxge_t hxgep);
105 static void hxge_intrs_disable(p_hxge_t hxgep);
106 static void hxge_suspend(p_hxge_t);
107 static hxge_status_t hxge_resume(p_hxge_t);
108 static hxge_status_t hxge_setup_dev(p_hxge_t);
109 static void hxge_destroy_dev(p_hxge_t);
110 static hxge_status_t hxge_alloc_mem_pool(p_hxge_t);
111 static void hxge_free_mem_pool(p_hxge_t);
112 static hxge_status_t hxge_alloc_rx_mem_pool(p_hxge_t);
113 static void hxge_free_rx_mem_pool(p_hxge_t);
114 static hxge_status_t hxge_alloc_tx_mem_pool(p_hxge_t);
115 static void hxge_free_tx_mem_pool(p_hxge_t);
116 static hxge_status_t hxge_dma_mem_alloc(p_hxge_t, dma_method_t,
117     struct ddi_dma_attr *, size_t, ddi_device_acc_attr_t *, uint_t,
118     p_hxge_dma_common_t);
119 static void hxge_dma_mem_free(p_hxge_dma_common_t);
120 static hxge_status_t hxge_alloc_rx_buf_dma(p_hxge_t, uint16_t,
121     p_hxge_dma_common_t *, size_t, size_t, uint32_t *);
122 static void hxge_free_rx_buf_dma(p_hxge_t, p_hxge_dma_common_t, uint32_t);
123 static hxge_status_t hxge_alloc_rx_cntl_dma(p_hxge_t, uint16_t,
124     p_hxge_dma_common_t *, struct ddi_dma_attr *, size_t);
125 static void hxge_free_rx_cntl_dma(p_hxge_t, p_hxge_dma_common_t);
126 static hxge_status_t hxge_alloc_tx_buf_dma(p_hxge_t, uint16_t,
127     p_hxge_dma_common_t *, size_t, size_t, uint32_t *);
128 static void hxge_free_tx_buf_dma(p_hxge_t, p_hxge_dma_common_t, uint32_t);
129 static hxge_status_t hxge_alloc_tx_cntl_dma(p_hxge_t, uint16_t,
130     p_hxge_dma_common_t *, size_t);
131 static void hxge_free_tx_cntl_dma(p_hxge_t, p_hxge_dma_common_t);
132 static int hxge_init_common_dev(p_hxge_t);
133 static void hxge_uninit_common_dev(p_hxge_t);
134 
135 /*
136  * The next declarations are for the GLDv3 interface.
137  */
138 static int hxge_m_start(void *);
139 static void hxge_m_stop(void *);
140 static int hxge_m_multicst(void *, boolean_t, const uint8_t *);
141 static int hxge_m_promisc(void *, boolean_t);
142 static void hxge_m_ioctl(void *, queue_t *, mblk_t *);
143 static hxge_status_t hxge_mac_register(p_hxge_t hxgep);
144 
145 static boolean_t hxge_m_getcapab(void *, mac_capab_t, void *);
146 static boolean_t hxge_param_locked(mac_prop_id_t pr_num);
147 static int hxge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
148     uint_t pr_valsize, const void *pr_val);
149 static int hxge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
150     uint_t pr_valsize, void *pr_val);
151 static void hxge_m_propinfo(void *barg, const char *pr_name,
152     mac_prop_id_t pr_num, mac_prop_info_handle_t mph);
153 static int hxge_set_priv_prop(p_hxge_t hxgep, const char *pr_name,
154     uint_t pr_valsize, const void *pr_val);
155 static int hxge_get_priv_prop(p_hxge_t hxgep, const char *pr_name,
156     uint_t pr_valsize, void *pr_val);
157 static void hxge_link_poll(void *arg);
158 static void hxge_link_update(p_hxge_t hxge, link_state_t state);
159 static void hxge_msix_init(p_hxge_t hxgep);
160 
161 char *hxge_priv_props[] = {
162 	"_rxdma_intr_time",
163 	"_rxdma_intr_pkts",
164 	"_class_opt_ipv4_tcp",
165 	"_class_opt_ipv4_udp",
166 	"_class_opt_ipv4_ah",
167 	"_class_opt_ipv4_sctp",
168 	"_class_opt_ipv6_tcp",
169 	"_class_opt_ipv6_udp",
170 	"_class_opt_ipv6_ah",
171 	"_class_opt_ipv6_sctp",
172 	NULL
173 };
174 
175 #define	HXGE_MAX_PRIV_PROPS	\
176 	(sizeof (hxge_priv_props)/sizeof (mac_priv_prop_t))
177 
178 #define	HXGE_MAGIC	0x4E584745UL
179 #define	MAX_DUMP_SZ 256
180 
181 #define	HXGE_M_CALLBACK_FLAGS	\
182 	(MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP | MC_PROPINFO)
183 
184 extern hxge_status_t hxge_pfc_set_default_mac_addr(p_hxge_t hxgep);
185 
186 static mac_callbacks_t hxge_m_callbacks = {
187 	HXGE_M_CALLBACK_FLAGS,
188 	hxge_m_stat,
189 	hxge_m_start,
190 	hxge_m_stop,
191 	hxge_m_promisc,
192 	hxge_m_multicst,
193 	NULL,
194 	NULL,
195 	NULL,
196 	hxge_m_ioctl,
197 	hxge_m_getcapab,
198 	NULL,
199 	NULL,
200 	hxge_m_setprop,
201 	hxge_m_getprop,
202 	hxge_m_propinfo
203 };
204 
205 /* PSARC/2007/453 MSI-X interrupt limit override. */
206 #define	HXGE_MSIX_REQUEST_10G	8
207 static int hxge_create_msi_property(p_hxge_t);
208 
209 /* Enable debug messages as necessary. */
210 uint64_t hxge_debug_level = 0;
211 
212 /*
213  * This list contains the instance structures for the Hydra
214  * devices present in the system. The lock exists to guarantee
215  * mutually exclusive access to the list.
216  */
217 void *hxge_list = NULL;
218 void *hxge_hw_list = NULL;
219 hxge_os_mutex_t hxge_common_lock;
220 
221 extern uint64_t hpi_debug_level;
222 
223 extern hxge_status_t hxge_ldgv_init(p_hxge_t, int *, int *);
224 extern hxge_status_t hxge_ldgv_uninit(p_hxge_t);
225 extern hxge_status_t hxge_intr_ldgv_init(p_hxge_t);
226 extern void hxge_fm_init(p_hxge_t hxgep, ddi_device_acc_attr_t *reg_attr,
227     ddi_device_acc_attr_t *desc_attr, ddi_dma_attr_t *dma_attr);
228 extern void hxge_fm_fini(p_hxge_t hxgep);
229 
230 /*
231  * Count used to maintain the number of buffers being used
232  * by Hydra instances and loaned up to the upper layers.
233  */
234 uint32_t hxge_mblks_pending = 0;
235 
236 /*
237  * Device register access attributes for PIO.
238  */
239 static ddi_device_acc_attr_t hxge_dev_reg_acc_attr = {
240 	DDI_DEVICE_ATTR_V0,
241 	DDI_STRUCTURE_LE_ACC,
242 	DDI_STRICTORDER_ACC,
243 };
244 
245 /*
246  * Device descriptor access attributes for DMA.
247  */
248 static ddi_device_acc_attr_t hxge_dev_desc_dma_acc_attr = {
249 	DDI_DEVICE_ATTR_V0,
250 	DDI_STRUCTURE_LE_ACC,
251 	DDI_STRICTORDER_ACC
252 };
253 
254 /*
255  * Device buffer access attributes for DMA.
256  */
257 static ddi_device_acc_attr_t hxge_dev_buf_dma_acc_attr = {
258 	DDI_DEVICE_ATTR_V0,
259 	DDI_STRUCTURE_BE_ACC,
260 	DDI_STRICTORDER_ACC
261 };
262 
263 ddi_dma_attr_t hxge_rx_rcr_desc_dma_attr = {
264 	DMA_ATTR_V0,		/* version number. */
265 	0,			/* low address */
266 	0xffffffffffffffff,	/* high address */
267 	0xffffffffffffffff,	/* address counter max */
268 	0x80000,		/* alignment */
269 	0xfc00fc,		/* dlim_burstsizes */
270 	0x1,			/* minimum transfer size */
271 	0xffffffffffffffff,	/* maximum transfer size */
272 	0xffffffffffffffff,	/* maximum segment size */
273 	1,			/* scatter/gather list length */
274 	(unsigned int)1,	/* granularity */
275 	0			/* attribute flags */
276 };
277 
278 ddi_dma_attr_t hxge_tx_desc_dma_attr = {
279 	DMA_ATTR_V0,		/* version number. */
280 	0,			/* low address */
281 	0xffffffffffffffff,	/* high address */
282 	0xffffffffffffffff,	/* address counter max */
283 	0x100000,		/* alignment */
284 	0xfc00fc,		/* dlim_burstsizes */
285 	0x1,			/* minimum transfer size */
286 	0xffffffffffffffff,	/* maximum transfer size */
287 	0xffffffffffffffff,	/* maximum segment size */
288 	1,			/* scatter/gather list length */
289 	(unsigned int)1,	/* granularity */
290 	0			/* attribute flags */
291 };
292 
293 ddi_dma_attr_t hxge_rx_rbr_desc_dma_attr = {
294 	DMA_ATTR_V0,		/* version number. */
295 	0,			/* low address */
296 	0xffffffffffffffff,	/* high address */
297 	0xffffffffffffffff,	/* address counter max */
298 	0x40000,		/* alignment */
299 	0xfc00fc,		/* dlim_burstsizes */
300 	0x1,			/* minimum transfer size */
301 	0xffffffffffffffff,	/* maximum transfer size */
302 	0xffffffffffffffff,	/* maximum segment size */
303 	1,			/* scatter/gather list length */
304 	(unsigned int)1,	/* granularity */
305 	0			/* attribute flags */
306 };
307 
308 ddi_dma_attr_t hxge_rx_mbox_dma_attr = {
309 	DMA_ATTR_V0,		/* version number. */
310 	0,			/* low address */
311 	0xffffffffffffffff,	/* high address */
312 	0xffffffffffffffff,	/* address counter max */
313 #if defined(_BIG_ENDIAN)
314 	0x2000,			/* alignment */
315 #else
316 	0x1000,			/* alignment */
317 #endif
318 	0xfc00fc,		/* dlim_burstsizes */
319 	0x1,			/* minimum transfer size */
320 	0xffffffffffffffff,	/* maximum transfer size */
321 	0xffffffffffffffff,	/* maximum segment size */
322 	5,			/* scatter/gather list length */
323 	(unsigned int)1,	/* granularity */
324 	0			/* attribute flags */
325 };
326 
327 ddi_dma_attr_t hxge_tx_dma_attr = {
328 	DMA_ATTR_V0,		/* version number. */
329 	0,			/* low address */
330 	0xffffffffffffffff,	/* high address */
331 	0xffffffffffffffff,	/* address counter max */
332 #if defined(_BIG_ENDIAN)
333 	0x2000,			/* alignment */
334 #else
335 	0x1000,			/* alignment */
336 #endif
337 	0xfc00fc,		/* dlim_burstsizes */
338 	0x1,			/* minimum transfer size */
339 	0xffffffffffffffff,	/* maximum transfer size */
340 	0xffffffffffffffff,	/* maximum segment size */
341 	5,			/* scatter/gather list length */
342 	(unsigned int)1,	/* granularity */
343 	0			/* attribute flags */
344 };
345 
346 ddi_dma_attr_t hxge_rx_dma_attr = {
347 	DMA_ATTR_V0,		/* version number. */
348 	0,			/* low address */
349 	0xffffffffffffffff,	/* high address */
350 	0xffffffffffffffff,	/* address counter max */
351 	0x10000,		/* alignment */
352 	0xfc00fc,		/* dlim_burstsizes */
353 	0x1,			/* minimum transfer size */
354 	0xffffffffffffffff,	/* maximum transfer size */
355 	0xffffffffffffffff,	/* maximum segment size */
356 	1,			/* scatter/gather list length */
357 	(unsigned int)1,	/* granularity */
358 	DDI_DMA_RELAXED_ORDERING /* attribute flags */
359 };
360 
361 ddi_dma_lim_t hxge_dma_limits = {
362 	(uint_t)0,		/* dlim_addr_lo */
363 	(uint_t)0xffffffff,	/* dlim_addr_hi */
364 	(uint_t)0xffffffff,	/* dlim_cntr_max */
365 	(uint_t)0xfc00fc,	/* dlim_burstsizes for 32 and 64 bit xfers */
366 	0x1,			/* dlim_minxfer */
367 	1024			/* dlim_speed */
368 };
369 
370 dma_method_t hxge_force_dma = DVMA;
371 
372 /*
373  * dma chunk sizes.
374  *
375  * Try to allocate the largest possible size
376  * so that fewer number of dma chunks would be managed
377  */
378 size_t alloc_sizes[] = {
379     0x1000, 0x2000, 0x4000, 0x8000,
380     0x10000, 0x20000, 0x40000, 0x80000,
381     0x100000, 0x200000, 0x400000, 0x800000, 0x1000000
382 };
383 
384 /*
385  * Translate "dev_t" to a pointer to the associated "dev_info_t".
386  */
387 static int
388 hxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
389 {
390 	p_hxge_t	hxgep = NULL;
391 	int		instance;
392 	int		status = DDI_SUCCESS;
393 	int		i;
394 
395 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_attach"));
396 
397 	/*
398 	 * Get the device instance since we'll need to setup or retrieve a soft
399 	 * state for this instance.
400 	 */
401 	instance = ddi_get_instance(dip);
402 
403 	switch (cmd) {
404 	case DDI_ATTACH:
405 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_ATTACH"));
406 		break;
407 
408 	case DDI_RESUME:
409 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_RESUME"));
410 		hxgep = (p_hxge_t)ddi_get_soft_state(hxge_list, instance);
411 		if (hxgep == NULL) {
412 			status = DDI_FAILURE;
413 			break;
414 		}
415 		if (hxgep->dip != dip) {
416 			status = DDI_FAILURE;
417 			break;
418 		}
419 		if (hxgep->suspended == DDI_PM_SUSPEND) {
420 			status = ddi_dev_is_needed(hxgep->dip, 0, 1);
421 		} else {
422 			(void) hxge_resume(hxgep);
423 		}
424 		goto hxge_attach_exit;
425 
426 	case DDI_PM_RESUME:
427 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_PM_RESUME"));
428 		hxgep = (p_hxge_t)ddi_get_soft_state(hxge_list, instance);
429 		if (hxgep == NULL) {
430 			status = DDI_FAILURE;
431 			break;
432 		}
433 		if (hxgep->dip != dip) {
434 			status = DDI_FAILURE;
435 			break;
436 		}
437 		(void) hxge_resume(hxgep);
438 		goto hxge_attach_exit;
439 
440 	default:
441 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing unknown"));
442 		status = DDI_FAILURE;
443 		goto hxge_attach_exit;
444 	}
445 
446 	if (ddi_soft_state_zalloc(hxge_list, instance) == DDI_FAILURE) {
447 		status = DDI_FAILURE;
448 		HXGE_ERROR_MSG((hxgep, DDI_CTL,
449 		    "ddi_soft_state_zalloc failed"));
450 		goto hxge_attach_exit;
451 	}
452 
453 	hxgep = ddi_get_soft_state(hxge_list, instance);
454 	if (hxgep == NULL) {
455 		status = HXGE_ERROR;
456 		HXGE_ERROR_MSG((hxgep, DDI_CTL,
457 		    "ddi_get_soft_state failed"));
458 		goto hxge_attach_fail2;
459 	}
460 
461 	hxgep->drv_state = 0;
462 	hxgep->dip = dip;
463 	hxgep->instance = instance;
464 	hxgep->p_dip = ddi_get_parent(dip);
465 	hxgep->hxge_debug_level = hxge_debug_level;
466 	hpi_debug_level = hxge_debug_level;
467 
468 	/*
469 	 * Initialize MMAC struture.
470 	 */
471 	(void) hxge_pfc_num_macs_get(hxgep, &hxgep->mmac.total);
472 	hxgep->mmac.available = hxgep->mmac.total;
473 	for (i = 0; i < hxgep->mmac.total; i++) {
474 		hxgep->mmac.addrs[i].set = B_FALSE;
475 		hxgep->mmac.addrs[i].primary = B_FALSE;
476 	}
477 
478 	hxge_fm_init(hxgep, &hxge_dev_reg_acc_attr, &hxge_dev_desc_dma_acc_attr,
479 	    &hxge_rx_dma_attr);
480 
481 	status = hxge_map_regs(hxgep);
482 	if (status != HXGE_OK) {
483 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "hxge_map_regs failed"));
484 		goto hxge_attach_fail3;
485 	}
486 
487 	status = hxge_init_common_dev(hxgep);
488 	if (status != HXGE_OK) {
489 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
490 		    "hxge_init_common_dev failed"));
491 		goto hxge_attach_fail4;
492 	}
493 
494 	/*
495 	 * Setup the Ndd parameters for this instance.
496 	 */
497 	hxge_init_param(hxgep);
498 
499 	/*
500 	 * Setup Register Tracing Buffer.
501 	 */
502 	hpi_rtrace_buf_init((rtrace_t *)&hpi_rtracebuf);
503 
504 	/* init stats ptr */
505 	hxge_init_statsp(hxgep);
506 
507 	status = hxge_setup_mutexes(hxgep);
508 	if (status != HXGE_OK) {
509 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "set mutex failed"));
510 		goto hxge_attach_fail;
511 	}
512 
513 	/* Scrub the MSI-X memory */
514 	hxge_msix_init(hxgep);
515 
516 	status = hxge_get_config_properties(hxgep);
517 	if (status != HXGE_OK) {
518 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "get_hw create failed"));
519 		goto hxge_attach_fail;
520 	}
521 
522 	/*
523 	 * Setup the Kstats for the driver.
524 	 */
525 	hxge_setup_kstats(hxgep);
526 	hxge_setup_param(hxgep);
527 
528 	status = hxge_setup_system_dma_pages(hxgep);
529 	if (status != HXGE_OK) {
530 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "set dma page failed"));
531 		goto hxge_attach_fail;
532 	}
533 
534 	hxge_hw_id_init(hxgep);
535 	hxge_hw_init_niu_common(hxgep);
536 
537 	status = hxge_setup_dev(hxgep);
538 	if (status != DDI_SUCCESS) {
539 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "set dev failed"));
540 		goto hxge_attach_fail;
541 	}
542 
543 	status = hxge_add_intrs(hxgep);
544 	if (status != DDI_SUCCESS) {
545 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "add_intr failed"));
546 		goto hxge_attach_fail;
547 	}
548 
549 	/*
550 	 * Enable interrupts.
551 	 */
552 	hxge_intrs_enable(hxgep);
553 
554 	if ((status = hxge_mac_register(hxgep)) != HXGE_OK) {
555 		HXGE_DEBUG_MSG((hxgep, DDI_CTL,
556 		    "unable to register to mac layer (%d)", status));
557 		goto hxge_attach_fail;
558 	}
559 	mac_link_update(hxgep->mach, LINK_STATE_UNKNOWN);
560 
561 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "registered to mac (instance %d)",
562 	    instance));
563 
564 	goto hxge_attach_exit;
565 
566 hxge_attach_fail:
567 	hxge_unattach(hxgep);
568 	goto hxge_attach_fail1;
569 
570 hxge_attach_fail5:
571 	/*
572 	 * Tear down the ndd parameters setup.
573 	 */
574 	hxge_destroy_param(hxgep);
575 
576 	/*
577 	 * Tear down the kstat setup.
578 	 */
579 	hxge_destroy_kstats(hxgep);
580 
581 hxge_attach_fail4:
582 	if (hxgep->hxge_hw_p) {
583 		hxge_uninit_common_dev(hxgep);
584 		hxgep->hxge_hw_p = NULL;
585 	}
586 hxge_attach_fail3:
587 	/*
588 	 * Unmap the register setup.
589 	 */
590 	hxge_unmap_regs(hxgep);
591 
592 	hxge_fm_fini(hxgep);
593 
594 hxge_attach_fail2:
595 	ddi_soft_state_free(hxge_list, hxgep->instance);
596 
597 hxge_attach_fail1:
598 	if (status != HXGE_OK)
599 		status = (HXGE_ERROR | HXGE_DDI_FAILED);
600 	hxgep = NULL;
601 
602 hxge_attach_exit:
603 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_attach status = 0x%08x",
604 	    status));
605 
606 	return (status);
607 }
608 
609 static int
610 hxge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
611 {
612 	int		status = DDI_SUCCESS;
613 	int		instance;
614 	p_hxge_t	hxgep = NULL;
615 
616 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_detach"));
617 	instance = ddi_get_instance(dip);
618 	hxgep = ddi_get_soft_state(hxge_list, instance);
619 	if (hxgep == NULL) {
620 		status = DDI_FAILURE;
621 		goto hxge_detach_exit;
622 	}
623 
624 	switch (cmd) {
625 	case DDI_DETACH:
626 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_DETACH"));
627 		break;
628 
629 	case DDI_PM_SUSPEND:
630 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_PM_SUSPEND"));
631 		hxgep->suspended = DDI_PM_SUSPEND;
632 		hxge_suspend(hxgep);
633 		break;
634 
635 	case DDI_SUSPEND:
636 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_SUSPEND"));
637 		if (hxgep->suspended != DDI_PM_SUSPEND) {
638 			hxgep->suspended = DDI_SUSPEND;
639 			hxge_suspend(hxgep);
640 		}
641 		break;
642 
643 	default:
644 		status = DDI_FAILURE;
645 		break;
646 	}
647 
648 	if (cmd != DDI_DETACH)
649 		goto hxge_detach_exit;
650 
651 	/*
652 	 * Stop the xcvr polling.
653 	 */
654 	hxgep->suspended = cmd;
655 
656 	if (hxgep->mach && (status = mac_unregister(hxgep->mach)) != 0) {
657 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
658 		    "<== hxge_detach status = 0x%08X", status));
659 		return (DDI_FAILURE);
660 	}
661 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
662 	    "<== hxge_detach (mac_unregister) status = 0x%08X", status));
663 
664 	hxge_unattach(hxgep);
665 	hxgep = NULL;
666 
667 hxge_detach_exit:
668 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_detach status = 0x%08X",
669 	    status));
670 
671 	return (status);
672 }
673 
674 static void
675 hxge_unattach(p_hxge_t hxgep)
676 {
677 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_unattach"));
678 
679 	if (hxgep == NULL || hxgep->dev_regs == NULL) {
680 		return;
681 	}
682 
683 	if (hxgep->hxge_hw_p) {
684 		hxge_uninit_common_dev(hxgep);
685 		hxgep->hxge_hw_p = NULL;
686 	}
687 
688 	if (hxgep->hxge_timerid) {
689 		hxge_stop_timer(hxgep, hxgep->hxge_timerid);
690 		hxgep->hxge_timerid = 0;
691 	}
692 
693 	/* Stop interrupts. */
694 	hxge_intrs_disable(hxgep);
695 
696 	/* Stop any further interrupts. */
697 	hxge_remove_intrs(hxgep);
698 
699 	/* Stop the device and free resources. */
700 	hxge_destroy_dev(hxgep);
701 
702 	/* Tear down the ndd parameters setup. */
703 	hxge_destroy_param(hxgep);
704 
705 	/* Tear down the kstat setup. */
706 	hxge_destroy_kstats(hxgep);
707 
708 	/*
709 	 * Remove the list of ndd parameters which were setup during attach.
710 	 */
711 	if (hxgep->dip) {
712 		HXGE_DEBUG_MSG((hxgep, OBP_CTL,
713 		    " hxge_unattach: remove all properties"));
714 		(void) ddi_prop_remove_all(hxgep->dip);
715 	}
716 
717 	/*
718 	 * Reset RDC, TDC, PFC, and VMAC blocks from PEU to clear any
719 	 * previous state before unmapping the registers.
720 	 */
721 	HXGE_REG_WR32(hxgep->hpi_handle, BLOCK_RESET, 0x0000001E);
722 	HXGE_DELAY(1000);
723 
724 	/*
725 	 * Unmap the register setup.
726 	 */
727 	hxge_unmap_regs(hxgep);
728 
729 	hxge_fm_fini(hxgep);
730 
731 	/* Destroy all mutexes.  */
732 	hxge_destroy_mutexes(hxgep);
733 
734 	/*
735 	 * Free the soft state data structures allocated with this instance.
736 	 */
737 	ddi_soft_state_free(hxge_list, hxgep->instance);
738 
739 	HXGE_DEBUG_MSG((NULL, DDI_CTL, "<== hxge_unattach"));
740 }
741 
742 static hxge_status_t
743 hxge_map_regs(p_hxge_t hxgep)
744 {
745 	int		ddi_status = DDI_SUCCESS;
746 	p_dev_regs_t	dev_regs;
747 
748 #ifdef	HXGE_DEBUG
749 	char		*sysname;
750 #endif
751 
752 	off_t		regsize;
753 	hxge_status_t	status = HXGE_OK;
754 	int		nregs;
755 
756 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_map_regs"));
757 
758 	if (ddi_dev_nregs(hxgep->dip, &nregs) != DDI_SUCCESS)
759 		return (HXGE_ERROR);
760 
761 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "hxge_map_regs: nregs: %d", nregs));
762 
763 	hxgep->dev_regs = NULL;
764 	dev_regs = KMEM_ZALLOC(sizeof (dev_regs_t), KM_SLEEP);
765 	dev_regs->hxge_regh = NULL;
766 	dev_regs->hxge_pciregh = NULL;
767 	dev_regs->hxge_msix_regh = NULL;
768 
769 	(void) ddi_dev_regsize(hxgep->dip, 0, &regsize);
770 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
771 	    "hxge_map_regs: pci config size 0x%x", regsize));
772 
773 	ddi_status = ddi_regs_map_setup(hxgep->dip, 0,
774 	    (caddr_t *)&(dev_regs->hxge_pciregp), 0, 0,
775 	    &hxge_dev_reg_acc_attr, &dev_regs->hxge_pciregh);
776 	if (ddi_status != DDI_SUCCESS) {
777 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
778 		    "ddi_map_regs, hxge bus config regs failed"));
779 		goto hxge_map_regs_fail0;
780 	}
781 
782 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
783 	    "hxge_map_reg: PCI config addr 0x%0llx handle 0x%0llx",
784 	    dev_regs->hxge_pciregp,
785 	    dev_regs->hxge_pciregh));
786 
787 	(void) ddi_dev_regsize(hxgep->dip, 1, &regsize);
788 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
789 	    "hxge_map_regs: pio size 0x%x", regsize));
790 
791 	/* set up the device mapped register */
792 	ddi_status = ddi_regs_map_setup(hxgep->dip, 1,
793 	    (caddr_t *)&(dev_regs->hxge_regp), 0, 0,
794 	    &hxge_dev_reg_acc_attr, &dev_regs->hxge_regh);
795 
796 	if (ddi_status != DDI_SUCCESS) {
797 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
798 		    "ddi_map_regs for Hydra global reg failed"));
799 		goto hxge_map_regs_fail1;
800 	}
801 
802 	/* set up the msi/msi-x mapped register */
803 	(void) ddi_dev_regsize(hxgep->dip, 2, &regsize);
804 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
805 	    "hxge_map_regs: msix size 0x%x", regsize));
806 
807 	ddi_status = ddi_regs_map_setup(hxgep->dip, 2,
808 	    (caddr_t *)&(dev_regs->hxge_msix_regp), 0, 0,
809 	    &hxge_dev_reg_acc_attr, &dev_regs->hxge_msix_regh);
810 
811 	if (ddi_status != DDI_SUCCESS) {
812 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
813 		    "ddi_map_regs for msi reg failed"));
814 		goto hxge_map_regs_fail2;
815 	}
816 
817 	hxgep->dev_regs = dev_regs;
818 
819 	HPI_PCI_ACC_HANDLE_SET(hxgep, dev_regs->hxge_pciregh);
820 	HPI_PCI_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_pciregp);
821 	HPI_MSI_ACC_HANDLE_SET(hxgep, dev_regs->hxge_msix_regh);
822 	HPI_MSI_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_msix_regp);
823 
824 	HPI_ACC_HANDLE_SET(hxgep, dev_regs->hxge_regh);
825 	HPI_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_regp);
826 
827 	HPI_REG_ACC_HANDLE_SET(hxgep, dev_regs->hxge_regh);
828 	HPI_REG_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_regp);
829 
830 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "hxge_map_reg: hardware addr 0x%0llx "
831 	    " handle 0x%0llx", dev_regs->hxge_regp, dev_regs->hxge_regh));
832 
833 	goto hxge_map_regs_exit;
834 
835 hxge_map_regs_fail3:
836 	if (dev_regs->hxge_msix_regh) {
837 		ddi_regs_map_free(&dev_regs->hxge_msix_regh);
838 	}
839 
840 hxge_map_regs_fail2:
841 	if (dev_regs->hxge_regh) {
842 		ddi_regs_map_free(&dev_regs->hxge_regh);
843 	}
844 
845 hxge_map_regs_fail1:
846 	if (dev_regs->hxge_pciregh) {
847 		ddi_regs_map_free(&dev_regs->hxge_pciregh);
848 	}
849 
850 hxge_map_regs_fail0:
851 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "Freeing register set memory"));
852 	kmem_free(dev_regs, sizeof (dev_regs_t));
853 
854 hxge_map_regs_exit:
855 	if (ddi_status != DDI_SUCCESS)
856 		status |= (HXGE_ERROR | HXGE_DDI_FAILED);
857 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_map_regs"));
858 	return (status);
859 }
860 
861 static void
862 hxge_unmap_regs(p_hxge_t hxgep)
863 {
864 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_unmap_regs"));
865 	if (hxgep->dev_regs) {
866 		if (hxgep->dev_regs->hxge_pciregh) {
867 			HXGE_DEBUG_MSG((hxgep, DDI_CTL,
868 			    "==> hxge_unmap_regs: bus"));
869 			ddi_regs_map_free(&hxgep->dev_regs->hxge_pciregh);
870 			hxgep->dev_regs->hxge_pciregh = NULL;
871 		}
872 
873 		if (hxgep->dev_regs->hxge_regh) {
874 			HXGE_DEBUG_MSG((hxgep, DDI_CTL,
875 			    "==> hxge_unmap_regs: device registers"));
876 			ddi_regs_map_free(&hxgep->dev_regs->hxge_regh);
877 			hxgep->dev_regs->hxge_regh = NULL;
878 		}
879 
880 		if (hxgep->dev_regs->hxge_msix_regh) {
881 			HXGE_DEBUG_MSG((hxgep, DDI_CTL,
882 			    "==> hxge_unmap_regs: device interrupts"));
883 			ddi_regs_map_free(&hxgep->dev_regs->hxge_msix_regh);
884 			hxgep->dev_regs->hxge_msix_regh = NULL;
885 		}
886 		kmem_free(hxgep->dev_regs, sizeof (dev_regs_t));
887 		hxgep->dev_regs = NULL;
888 	}
889 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_unmap_regs"));
890 }
891 
892 static hxge_status_t
893 hxge_setup_mutexes(p_hxge_t hxgep)
894 {
895 	int		ddi_status = DDI_SUCCESS;
896 	hxge_status_t	status = HXGE_OK;
897 
898 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_setup_mutexes"));
899 
900 	/*
901 	 * Get the interrupt cookie so the mutexes can be Initialised.
902 	 */
903 	ddi_status = ddi_get_iblock_cookie(hxgep->dip, 0,
904 	    &hxgep->interrupt_cookie);
905 
906 	if (ddi_status != DDI_SUCCESS) {
907 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
908 		    "<== hxge_setup_mutexes: failed 0x%x", ddi_status));
909 		goto hxge_setup_mutexes_exit;
910 	}
911 
912 	/*
913 	 * Initialize mutex's for this device.
914 	 */
915 	MUTEX_INIT(hxgep->genlock, NULL,
916 	    MUTEX_DRIVER, (void *) hxgep->interrupt_cookie);
917 	MUTEX_INIT(&hxgep->vmac_lock, NULL,
918 	    MUTEX_DRIVER, (void *) hxgep->interrupt_cookie);
919 	MUTEX_INIT(&hxgep->ouraddr_lock, NULL,
920 	    MUTEX_DRIVER, (void *) hxgep->interrupt_cookie);
921 	RW_INIT(&hxgep->filter_lock, NULL,
922 	    RW_DRIVER, (void *) hxgep->interrupt_cookie);
923 	MUTEX_INIT(&hxgep->pio_lock, NULL,
924 	    MUTEX_DRIVER, (void *) hxgep->interrupt_cookie);
925 	MUTEX_INIT(&hxgep->timeout.lock, NULL,
926 	    MUTEX_DRIVER, (void *) hxgep->interrupt_cookie);
927 
928 hxge_setup_mutexes_exit:
929 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
930 	    "<== hxge_setup_mutexes status = %x", status));
931 
932 	if (ddi_status != DDI_SUCCESS)
933 		status |= (HXGE_ERROR | HXGE_DDI_FAILED);
934 
935 	return (status);
936 }
937 
938 static void
939 hxge_destroy_mutexes(p_hxge_t hxgep)
940 {
941 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_destroy_mutexes"));
942 	RW_DESTROY(&hxgep->filter_lock);
943 	MUTEX_DESTROY(&hxgep->vmac_lock);
944 	MUTEX_DESTROY(&hxgep->ouraddr_lock);
945 	MUTEX_DESTROY(hxgep->genlock);
946 	MUTEX_DESTROY(&hxgep->pio_lock);
947 	MUTEX_DESTROY(&hxgep->timeout.lock);
948 
949 	if (hxge_debug_init == 1) {
950 		MUTEX_DESTROY(&hxgedebuglock);
951 		hxge_debug_init = 0;
952 	}
953 
954 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_destroy_mutexes"));
955 }
956 
957 hxge_status_t
958 hxge_init(p_hxge_t hxgep)
959 {
960 	hxge_status_t status = HXGE_OK;
961 
962 	HXGE_DEBUG_MSG((hxgep, STR_CTL, "==> hxge_init"));
963 
964 	if (hxgep->drv_state & STATE_HW_INITIALIZED) {
965 		return (status);
966 	}
967 
968 	/*
969 	 * Allocate system memory for the receive/transmit buffer blocks and
970 	 * receive/transmit descriptor rings.
971 	 */
972 	status = hxge_alloc_mem_pool(hxgep);
973 	if (status != HXGE_OK) {
974 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "alloc mem failed\n"));
975 		goto hxge_init_fail1;
976 	}
977 
978 	/*
979 	 * Initialize and enable TXDMA channels.
980 	 */
981 	status = hxge_init_txdma_channels(hxgep);
982 	if (status != HXGE_OK) {
983 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init txdma failed\n"));
984 		goto hxge_init_fail3;
985 	}
986 
987 	/*
988 	 * Initialize and enable RXDMA channels.
989 	 */
990 	status = hxge_init_rxdma_channels(hxgep);
991 	if (status != HXGE_OK) {
992 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init rxdma failed\n"));
993 		goto hxge_init_fail4;
994 	}
995 
996 	/*
997 	 * Initialize TCAM
998 	 */
999 	status = hxge_classify_init(hxgep);
1000 	if (status != HXGE_OK) {
1001 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init classify failed\n"));
1002 		goto hxge_init_fail5;
1003 	}
1004 
1005 	/*
1006 	 * Initialize the VMAC block.
1007 	 */
1008 	status = hxge_vmac_init(hxgep);
1009 	if (status != HXGE_OK) {
1010 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init MAC failed\n"));
1011 		goto hxge_init_fail5;
1012 	}
1013 
1014 	/* Bringup - this may be unnecessary when PXE and FCODE available */
1015 	status = hxge_pfc_set_default_mac_addr(hxgep);
1016 	if (status != HXGE_OK) {
1017 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
1018 		    "Default Address Failure\n"));
1019 		goto hxge_init_fail5;
1020 	}
1021 
1022 	/*
1023 	 * Enable hardware interrupts.
1024 	 */
1025 	hxge_intr_hw_enable(hxgep);
1026 	hxgep->drv_state |= STATE_HW_INITIALIZED;
1027 
1028 	goto hxge_init_exit;
1029 
1030 hxge_init_fail5:
1031 	hxge_uninit_rxdma_channels(hxgep);
1032 hxge_init_fail4:
1033 	hxge_uninit_txdma_channels(hxgep);
1034 hxge_init_fail3:
1035 	hxge_free_mem_pool(hxgep);
1036 hxge_init_fail1:
1037 	HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
1038 	    "<== hxge_init status (failed) = 0x%08x", status));
1039 	return (status);
1040 
1041 hxge_init_exit:
1042 
1043 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_init status = 0x%08x",
1044 	    status));
1045 
1046 	return (status);
1047 }
1048 
1049 timeout_id_t
1050 hxge_start_timer(p_hxge_t hxgep, fptrv_t func, int msec)
1051 {
1052 	if ((hxgep->suspended == 0) || (hxgep->suspended == DDI_RESUME)) {
1053 		return (timeout(func, (caddr_t)hxgep,
1054 		    drv_usectohz(1000 * msec)));
1055 	}
1056 	return (NULL);
1057 }
1058 
1059 /*ARGSUSED*/
1060 void
1061 hxge_stop_timer(p_hxge_t hxgep, timeout_id_t timerid)
1062 {
1063 	if (timerid) {
1064 		(void) untimeout(timerid);
1065 	}
1066 }
1067 
1068 void
1069 hxge_uninit(p_hxge_t hxgep)
1070 {
1071 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_uninit"));
1072 
1073 	if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) {
1074 		HXGE_DEBUG_MSG((hxgep, DDI_CTL,
1075 		    "==> hxge_uninit: not initialized"));
1076 		HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_uninit"));
1077 		return;
1078 	}
1079 
1080 	/* Stop timer */
1081 	if (hxgep->hxge_timerid) {
1082 		hxge_stop_timer(hxgep, hxgep->hxge_timerid);
1083 		hxgep->hxge_timerid = 0;
1084 	}
1085 
1086 	(void) hxge_intr_hw_disable(hxgep);
1087 
1088 	/* Reset the receive VMAC side.  */
1089 	(void) hxge_rx_vmac_disable(hxgep);
1090 
1091 	/* Free classification resources */
1092 	(void) hxge_classify_uninit(hxgep);
1093 
1094 	/* Reset the transmit/receive DMA side.  */
1095 	(void) hxge_txdma_hw_mode(hxgep, HXGE_DMA_STOP);
1096 	(void) hxge_rxdma_hw_mode(hxgep, HXGE_DMA_STOP);
1097 
1098 	hxge_uninit_txdma_channels(hxgep);
1099 	hxge_uninit_rxdma_channels(hxgep);
1100 
1101 	/* Reset the transmit VMAC side.  */
1102 	(void) hxge_tx_vmac_disable(hxgep);
1103 
1104 	hxge_free_mem_pool(hxgep);
1105 
1106 	hxgep->drv_state &= ~STATE_HW_INITIALIZED;
1107 
1108 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_uninit"));
1109 }
1110 
1111 /*ARGSUSED*/
1112 /*VARARGS*/
1113 void
1114 hxge_debug_msg(p_hxge_t hxgep, uint64_t level, char *fmt, ...)
1115 {
1116 	char		msg_buffer[1048];
1117 	char		prefix_buffer[32];
1118 	int		instance;
1119 	uint64_t	debug_level;
1120 	int		cmn_level = CE_CONT;
1121 	va_list		ap;
1122 
1123 	debug_level = (hxgep == NULL) ? hxge_debug_level :
1124 	    hxgep->hxge_debug_level;
1125 
1126 	if ((level & debug_level) || (level == HXGE_NOTE) ||
1127 	    (level == HXGE_ERR_CTL)) {
1128 		/* do the msg processing */
1129 		if (hxge_debug_init == 0) {
1130 			MUTEX_INIT(&hxgedebuglock, NULL, MUTEX_DRIVER, NULL);
1131 			hxge_debug_init = 1;
1132 		}
1133 
1134 		MUTEX_ENTER(&hxgedebuglock);
1135 
1136 		if ((level & HXGE_NOTE)) {
1137 			cmn_level = CE_NOTE;
1138 		}
1139 
1140 		if (level & HXGE_ERR_CTL) {
1141 			cmn_level = CE_WARN;
1142 		}
1143 
1144 		va_start(ap, fmt);
1145 		(void) vsprintf(msg_buffer, fmt, ap);
1146 		va_end(ap);
1147 
1148 		if (hxgep == NULL) {
1149 			instance = -1;
1150 			(void) sprintf(prefix_buffer, "%s :", "hxge");
1151 		} else {
1152 			instance = hxgep->instance;
1153 			(void) sprintf(prefix_buffer,
1154 			    "%s%d :", "hxge", instance);
1155 		}
1156 
1157 		MUTEX_EXIT(&hxgedebuglock);
1158 		cmn_err(cmn_level, "%s %s\n", prefix_buffer, msg_buffer);
1159 	}
1160 }
1161 
1162 char *
1163 hxge_dump_packet(char *addr, int size)
1164 {
1165 	uchar_t		*ap = (uchar_t *)addr;
1166 	int		i;
1167 	static char	etherbuf[1024];
1168 	char		*cp = etherbuf;
1169 	char		digits[] = "0123456789abcdef";
1170 
1171 	if (!size)
1172 		size = 60;
1173 
1174 	if (size > MAX_DUMP_SZ) {
1175 		/* Dump the leading bytes */
1176 		for (i = 0; i < MAX_DUMP_SZ / 2; i++) {
1177 			if (*ap > 0x0f)
1178 				*cp++ = digits[*ap >> 4];
1179 			*cp++ = digits[*ap++ & 0xf];
1180 			*cp++ = ':';
1181 		}
1182 		for (i = 0; i < 20; i++)
1183 			*cp++ = '.';
1184 		/* Dump the last MAX_DUMP_SZ/2 bytes */
1185 		ap = (uchar_t *)(addr + (size - MAX_DUMP_SZ / 2));
1186 		for (i = 0; i < MAX_DUMP_SZ / 2; i++) {
1187 			if (*ap > 0x0f)
1188 				*cp++ = digits[*ap >> 4];
1189 			*cp++ = digits[*ap++ & 0xf];
1190 			*cp++ = ':';
1191 		}
1192 	} else {
1193 		for (i = 0; i < size; i++) {
1194 			if (*ap > 0x0f)
1195 				*cp++ = digits[*ap >> 4];
1196 			*cp++ = digits[*ap++ & 0xf];
1197 			*cp++ = ':';
1198 		}
1199 	}
1200 	*--cp = 0;
1201 	return (etherbuf);
1202 }
1203 
1204 static void
1205 hxge_suspend(p_hxge_t hxgep)
1206 {
1207 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_suspend"));
1208 
1209 	/*
1210 	 * Stop the link status timer before hxge_intrs_disable() to avoid
1211 	 * accessing the the MSIX table simultaneously. Note that the timer
1212 	 * routine polls for MSIX parity errors.
1213 	 */
1214 	MUTEX_ENTER(&hxgep->timeout.lock);
1215 	if (hxgep->timeout.id)
1216 		(void) untimeout(hxgep->timeout.id);
1217 	MUTEX_EXIT(&hxgep->timeout.lock);
1218 
1219 	hxge_intrs_disable(hxgep);
1220 	hxge_destroy_dev(hxgep);
1221 
1222 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_suspend"));
1223 }
1224 
1225 static hxge_status_t
1226 hxge_resume(p_hxge_t hxgep)
1227 {
1228 	hxge_status_t status = HXGE_OK;
1229 
1230 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_resume"));
1231 	hxgep->suspended = DDI_RESUME;
1232 
1233 	(void) hxge_rxdma_hw_mode(hxgep, HXGE_DMA_START);
1234 	(void) hxge_txdma_hw_mode(hxgep, HXGE_DMA_START);
1235 
1236 	(void) hxge_rx_vmac_enable(hxgep);
1237 	(void) hxge_tx_vmac_enable(hxgep);
1238 
1239 	hxge_intrs_enable(hxgep);
1240 
1241 	hxgep->suspended = 0;
1242 
1243 	/*
1244 	 * Resume the link status timer after hxge_intrs_enable to avoid
1245 	 * accessing MSIX table simultaneously.
1246 	 */
1247 	MUTEX_ENTER(&hxgep->timeout.lock);
1248 	hxgep->timeout.id = timeout(hxge_link_poll, (void *)hxgep,
1249 	    hxgep->timeout.ticks);
1250 	MUTEX_EXIT(&hxgep->timeout.lock);
1251 
1252 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
1253 	    "<== hxge_resume status = 0x%x", status));
1254 
1255 	return (status);
1256 }
1257 
1258 static hxge_status_t
1259 hxge_setup_dev(p_hxge_t hxgep)
1260 {
1261 	hxge_status_t status = HXGE_OK;
1262 
1263 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_setup_dev"));
1264 
1265 	status = hxge_link_init(hxgep);
1266 	if (fm_check_acc_handle(hxgep->dev_regs->hxge_regh) != DDI_FM_OK) {
1267 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
1268 		    "Bad register acc handle"));
1269 		status = HXGE_ERROR;
1270 	}
1271 
1272 	if (status != HXGE_OK) {
1273 		HXGE_DEBUG_MSG((hxgep, MAC_CTL,
1274 		    " hxge_setup_dev status (link init 0x%08x)", status));
1275 		goto hxge_setup_dev_exit;
1276 	}
1277 
1278 hxge_setup_dev_exit:
1279 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
1280 	    "<== hxge_setup_dev status = 0x%08x", status));
1281 
1282 	return (status);
1283 }
1284 
1285 static void
1286 hxge_destroy_dev(p_hxge_t hxgep)
1287 {
1288 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_destroy_dev"));
1289 
1290 	(void) hxge_hw_stop(hxgep);
1291 
1292 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_destroy_dev"));
1293 }
1294 
1295 static hxge_status_t
1296 hxge_setup_system_dma_pages(p_hxge_t hxgep)
1297 {
1298 	int			ddi_status = DDI_SUCCESS;
1299 	uint_t			count;
1300 	ddi_dma_cookie_t	cookie;
1301 	uint_t			iommu_pagesize;
1302 	hxge_status_t		status = HXGE_OK;
1303 
1304 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_setup_system_dma_pages"));
1305 
1306 	hxgep->sys_page_sz = ddi_ptob(hxgep->dip, (ulong_t)1);
1307 	iommu_pagesize = dvma_pagesize(hxgep->dip);
1308 
1309 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
1310 	    " hxge_setup_system_dma_pages: page %d (ddi_ptob %d) "
1311 	    " default_block_size %d iommu_pagesize %d",
1312 	    hxgep->sys_page_sz, ddi_ptob(hxgep->dip, (ulong_t)1),
1313 	    hxgep->rx_default_block_size, iommu_pagesize));
1314 
1315 	if (iommu_pagesize != 0) {
1316 		if (hxgep->sys_page_sz == iommu_pagesize) {
1317 			/* Hydra support up to 8K pages */
1318 			if (iommu_pagesize > 0x2000)
1319 				hxgep->sys_page_sz = 0x2000;
1320 		} else {
1321 			if (hxgep->sys_page_sz > iommu_pagesize)
1322 				hxgep->sys_page_sz = iommu_pagesize;
1323 		}
1324 	}
1325 
1326 	hxgep->sys_page_mask = ~(hxgep->sys_page_sz - 1);
1327 
1328 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
1329 	    "==> hxge_setup_system_dma_pages: page %d (ddi_ptob %d) "
1330 	    "default_block_size %d page mask %d",
1331 	    hxgep->sys_page_sz, ddi_ptob(hxgep->dip, (ulong_t)1),
1332 	    hxgep->rx_default_block_size, hxgep->sys_page_mask));
1333 
1334 	switch (hxgep->sys_page_sz) {
1335 	default:
1336 		hxgep->sys_page_sz = 0x1000;
1337 		hxgep->sys_page_mask = ~(hxgep->sys_page_sz - 1);
1338 		hxgep->rx_default_block_size = 0x1000;
1339 		hxgep->rx_bksize_code = RBR_BKSIZE_4K;
1340 		break;
1341 	case 0x1000:
1342 		hxgep->rx_default_block_size = 0x1000;
1343 		hxgep->rx_bksize_code = RBR_BKSIZE_4K;
1344 		break;
1345 	case 0x2000:
1346 		hxgep->rx_default_block_size = 0x2000;
1347 		hxgep->rx_bksize_code = RBR_BKSIZE_8K;
1348 		break;
1349 	}
1350 
1351 	hxge_rx_dma_attr.dma_attr_align = hxgep->sys_page_sz;
1352 	hxge_tx_dma_attr.dma_attr_align = hxgep->sys_page_sz;
1353 
1354 	/*
1355 	 * Get the system DMA burst size.
1356 	 */
1357 	ddi_status = ddi_dma_alloc_handle(hxgep->dip, &hxge_tx_dma_attr,
1358 	    DDI_DMA_DONTWAIT, 0, &hxgep->dmasparehandle);
1359 	if (ddi_status != DDI_SUCCESS) {
1360 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
1361 		    "ddi_dma_alloc_handle: failed status 0x%x", ddi_status));
1362 		goto hxge_get_soft_properties_exit;
1363 	}
1364 
1365 	ddi_status = ddi_dma_addr_bind_handle(hxgep->dmasparehandle, NULL,
1366 	    (caddr_t)hxgep->dmasparehandle, sizeof (hxgep->dmasparehandle),
1367 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, 0,
1368 	    &cookie, &count);
1369 	if (ddi_status != DDI_DMA_MAPPED) {
1370 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
1371 		    "Binding spare handle to find system burstsize failed."));
1372 		ddi_status = DDI_FAILURE;
1373 		goto hxge_get_soft_properties_fail1;
1374 	}
1375 
1376 	hxgep->sys_burst_sz = ddi_dma_burstsizes(hxgep->dmasparehandle);
1377 	(void) ddi_dma_unbind_handle(hxgep->dmasparehandle);
1378 
1379 hxge_get_soft_properties_fail1:
1380 	ddi_dma_free_handle(&hxgep->dmasparehandle);
1381 
1382 hxge_get_soft_properties_exit:
1383 
1384 	if (ddi_status != DDI_SUCCESS)
1385 		status |= (HXGE_ERROR | HXGE_DDI_FAILED);
1386 
1387 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
1388 	    "<== hxge_setup_system_dma_pages status = 0x%08x", status));
1389 
1390 	return (status);
1391 }
1392 
1393 static hxge_status_t
1394 hxge_alloc_mem_pool(p_hxge_t hxgep)
1395 {
1396 	hxge_status_t status = HXGE_OK;
1397 
1398 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_alloc_mem_pool"));
1399 
1400 	status = hxge_alloc_rx_mem_pool(hxgep);
1401 	if (status != HXGE_OK) {
1402 		return (HXGE_ERROR);
1403 	}
1404 
1405 	status = hxge_alloc_tx_mem_pool(hxgep);
1406 	if (status != HXGE_OK) {
1407 		hxge_free_rx_mem_pool(hxgep);
1408 		return (HXGE_ERROR);
1409 	}
1410 
1411 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_alloc_mem_pool"));
1412 	return (HXGE_OK);
1413 }
1414 
1415 static void
1416 hxge_free_mem_pool(p_hxge_t hxgep)
1417 {
1418 	HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_free_mem_pool"));
1419 
1420 	hxge_free_rx_mem_pool(hxgep);
1421 	hxge_free_tx_mem_pool(hxgep);
1422 
1423 	HXGE_DEBUG_MSG((hxgep, MEM_CTL, "<== hxge_free_mem_pool"));
1424 }
1425 
1426 static hxge_status_t
1427 hxge_alloc_rx_mem_pool(p_hxge_t hxgep)
1428 {
1429 	int			i, j;
1430 	uint32_t		ndmas, st_rdc;
1431 	p_hxge_dma_pt_cfg_t	p_all_cfgp;
1432 	p_hxge_hw_pt_cfg_t	p_cfgp;
1433 	p_hxge_dma_pool_t	dma_poolp;
1434 	p_hxge_dma_common_t	*dma_buf_p;
1435 	p_hxge_dma_pool_t	dma_rbr_cntl_poolp;
1436 	p_hxge_dma_common_t	*dma_rbr_cntl_p;
1437 	p_hxge_dma_pool_t	dma_rcr_cntl_poolp;
1438 	p_hxge_dma_common_t	*dma_rcr_cntl_p;
1439 	p_hxge_dma_pool_t	dma_mbox_cntl_poolp;
1440 	p_hxge_dma_common_t	*dma_mbox_cntl_p;
1441 	size_t			rx_buf_alloc_size;
1442 	size_t			rx_rbr_cntl_alloc_size;
1443 	size_t			rx_rcr_cntl_alloc_size;
1444 	size_t			rx_mbox_cntl_alloc_size;
1445 	uint32_t		*num_chunks;	/* per dma */
1446 	hxge_status_t		status = HXGE_OK;
1447 
1448 	uint32_t		hxge_port_rbr_size;
1449 	uint32_t		hxge_port_rbr_spare_size;
1450 	uint32_t		hxge_port_rcr_size;
1451 
1452 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_rx_mem_pool"));
1453 
1454 	p_all_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config;
1455 	p_cfgp = (p_hxge_hw_pt_cfg_t)&p_all_cfgp->hw_config;
1456 	st_rdc = p_cfgp->start_rdc;
1457 	ndmas = p_cfgp->max_rdcs;
1458 
1459 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1460 	    " hxge_alloc_rx_mem_pool st_rdc %d ndmas %d", st_rdc, ndmas));
1461 
1462 	/*
1463 	 * Allocate memory for each receive DMA channel.
1464 	 */
1465 	dma_poolp = (p_hxge_dma_pool_t)KMEM_ZALLOC(sizeof (hxge_dma_pool_t),
1466 	    KM_SLEEP);
1467 	dma_buf_p = (p_hxge_dma_common_t *)KMEM_ZALLOC(
1468 	    sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP);
1469 
1470 	dma_rbr_cntl_poolp = (p_hxge_dma_pool_t)
1471 	    KMEM_ZALLOC(sizeof (hxge_dma_pool_t), KM_SLEEP);
1472 	dma_rbr_cntl_p = (p_hxge_dma_common_t *)KMEM_ZALLOC(
1473 	    sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP);
1474 	dma_rcr_cntl_poolp = (p_hxge_dma_pool_t)
1475 	    KMEM_ZALLOC(sizeof (hxge_dma_pool_t), KM_SLEEP);
1476 	dma_rcr_cntl_p = (p_hxge_dma_common_t *)KMEM_ZALLOC(
1477 	    sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP);
1478 	dma_mbox_cntl_poolp = (p_hxge_dma_pool_t)
1479 	    KMEM_ZALLOC(sizeof (hxge_dma_pool_t), KM_SLEEP);
1480 	dma_mbox_cntl_p = (p_hxge_dma_common_t *)KMEM_ZALLOC(
1481 	    sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP);
1482 
1483 	num_chunks = (uint32_t *)KMEM_ZALLOC(sizeof (uint32_t) * ndmas,
1484 	    KM_SLEEP);
1485 
1486 	/*
1487 	 * Assume that each DMA channel will be configured with default block
1488 	 * size. rbr block counts are mod of batch count (16).
1489 	 */
1490 	hxge_port_rbr_size = p_all_cfgp->rbr_size;
1491 	hxge_port_rcr_size = p_all_cfgp->rcr_size;
1492 
1493 	if (!hxge_port_rbr_size) {
1494 		hxge_port_rbr_size = HXGE_RBR_RBB_DEFAULT;
1495 	}
1496 
1497 	if (hxge_port_rbr_size % HXGE_RXDMA_POST_BATCH) {
1498 		hxge_port_rbr_size = (HXGE_RXDMA_POST_BATCH *
1499 		    (hxge_port_rbr_size / HXGE_RXDMA_POST_BATCH + 1));
1500 	}
1501 
1502 	p_all_cfgp->rbr_size = hxge_port_rbr_size;
1503 	hxge_port_rbr_spare_size = hxge_rbr_spare_size;
1504 
1505 	if (hxge_port_rbr_spare_size % HXGE_RXDMA_POST_BATCH) {
1506 		hxge_port_rbr_spare_size = (HXGE_RXDMA_POST_BATCH *
1507 		    (hxge_port_rbr_spare_size / HXGE_RXDMA_POST_BATCH + 1));
1508 	}
1509 
1510 	rx_buf_alloc_size = (hxgep->rx_default_block_size *
1511 	    (hxge_port_rbr_size + hxge_port_rbr_spare_size));
1512 
1513 	/*
1514 	 * Addresses of receive block ring, receive completion ring and the
1515 	 * mailbox must be all cache-aligned (64 bytes).
1516 	 */
1517 	rx_rbr_cntl_alloc_size = hxge_port_rbr_size + hxge_port_rbr_spare_size;
1518 	rx_rbr_cntl_alloc_size *= sizeof (rx_desc_t);
1519 	rx_rcr_cntl_alloc_size = sizeof (rcr_entry_t) * hxge_port_rcr_size;
1520 	rx_mbox_cntl_alloc_size = sizeof (rxdma_mailbox_t);
1521 
1522 	HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_alloc_rx_mem_pool: "
1523 	    "hxge_port_rbr_size = %d hxge_port_rbr_spare_size = %d "
1524 	    "hxge_port_rcr_size = %d rx_cntl_alloc_size = %d",
1525 	    hxge_port_rbr_size, hxge_port_rbr_spare_size,
1526 	    hxge_port_rcr_size, rx_cntl_alloc_size));
1527 
1528 	hxgep->hxge_port_rbr_size = hxge_port_rbr_size;
1529 	hxgep->hxge_port_rcr_size = hxge_port_rcr_size;
1530 
1531 	/*
1532 	 * Allocate memory for receive buffers and descriptor rings. Replace
1533 	 * allocation functions with interface functions provided by the
1534 	 * partition manager when it is available.
1535 	 */
1536 	/*
1537 	 * Allocate memory for the receive buffer blocks.
1538 	 */
1539 	for (i = 0; i < ndmas; i++) {
1540 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
1541 		    " hxge_alloc_rx_mem_pool to alloc mem: "
1542 		    " dma %d dma_buf_p %llx &dma_buf_p %llx",
1543 		    i, dma_buf_p[i], &dma_buf_p[i]));
1544 
1545 		num_chunks[i] = 0;
1546 
1547 		status = hxge_alloc_rx_buf_dma(hxgep, st_rdc, &dma_buf_p[i],
1548 		    rx_buf_alloc_size, hxgep->rx_default_block_size,
1549 		    &num_chunks[i]);
1550 		if (status != HXGE_OK) {
1551 			break;
1552 		}
1553 
1554 		st_rdc++;
1555 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
1556 		    " hxge_alloc_rx_mem_pool DONE  alloc mem: "
1557 		    "dma %d dma_buf_p %llx &dma_buf_p %llx", i,
1558 		    dma_buf_p[i], &dma_buf_p[i]));
1559 	}
1560 
1561 	if (i < ndmas) {
1562 		goto hxge_alloc_rx_mem_fail1;
1563 	}
1564 
1565 	/*
1566 	 * Allocate memory for descriptor rings and mailbox.
1567 	 */
1568 	st_rdc = p_cfgp->start_rdc;
1569 	for (j = 0; j < ndmas; j++) {
1570 		if ((status = hxge_alloc_rx_cntl_dma(hxgep, st_rdc,
1571 		    &dma_rbr_cntl_p[j], &hxge_rx_rbr_desc_dma_attr,
1572 		    rx_rbr_cntl_alloc_size)) != HXGE_OK) {
1573 			break;
1574 		}
1575 
1576 		if ((status = hxge_alloc_rx_cntl_dma(hxgep, st_rdc,
1577 		    &dma_rcr_cntl_p[j], &hxge_rx_rcr_desc_dma_attr,
1578 		    rx_rcr_cntl_alloc_size)) != HXGE_OK) {
1579 			break;
1580 		}
1581 
1582 		if ((status = hxge_alloc_rx_cntl_dma(hxgep, st_rdc,
1583 		    &dma_mbox_cntl_p[j], &hxge_rx_mbox_dma_attr,
1584 		    rx_mbox_cntl_alloc_size)) != HXGE_OK) {
1585 			break;
1586 		}
1587 		st_rdc++;
1588 	}
1589 
1590 	if (j < ndmas) {
1591 		goto hxge_alloc_rx_mem_fail2;
1592 	}
1593 
1594 	dma_poolp->ndmas = ndmas;
1595 	dma_poolp->num_chunks = num_chunks;
1596 	dma_poolp->buf_allocated = B_TRUE;
1597 	hxgep->rx_buf_pool_p = dma_poolp;
1598 	dma_poolp->dma_buf_pool_p = dma_buf_p;
1599 
1600 	dma_rbr_cntl_poolp->ndmas = ndmas;
1601 	dma_rbr_cntl_poolp->buf_allocated = B_TRUE;
1602 	hxgep->rx_rbr_cntl_pool_p = dma_rbr_cntl_poolp;
1603 	dma_rbr_cntl_poolp->dma_buf_pool_p = dma_rbr_cntl_p;
1604 
1605 	dma_rcr_cntl_poolp->ndmas = ndmas;
1606 	dma_rcr_cntl_poolp->buf_allocated = B_TRUE;
1607 	hxgep->rx_rcr_cntl_pool_p = dma_rcr_cntl_poolp;
1608 	dma_rcr_cntl_poolp->dma_buf_pool_p = dma_rcr_cntl_p;
1609 
1610 	dma_mbox_cntl_poolp->ndmas = ndmas;
1611 	dma_mbox_cntl_poolp->buf_allocated = B_TRUE;
1612 	hxgep->rx_mbox_cntl_pool_p = dma_mbox_cntl_poolp;
1613 	dma_mbox_cntl_poolp->dma_buf_pool_p = dma_mbox_cntl_p;
1614 
1615 	goto hxge_alloc_rx_mem_pool_exit;
1616 
1617 hxge_alloc_rx_mem_fail2:
1618 	/* Free control buffers */
1619 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1620 	    "==> hxge_alloc_rx_mem_pool: freeing control bufs (%d)", j));
1621 	for (; j >= 0; j--) {
1622 		hxge_free_rx_cntl_dma(hxgep,
1623 		    (p_hxge_dma_common_t)dma_rbr_cntl_p[j]);
1624 		hxge_free_rx_cntl_dma(hxgep,
1625 		    (p_hxge_dma_common_t)dma_rcr_cntl_p[j]);
1626 		hxge_free_rx_cntl_dma(hxgep,
1627 		    (p_hxge_dma_common_t)dma_mbox_cntl_p[j]);
1628 		HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1629 		    "==> hxge_alloc_rx_mem_pool: control bufs freed (%d)", j));
1630 	}
1631 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1632 	    "==> hxge_alloc_rx_mem_pool: control bufs freed (%d)", j));
1633 
1634 hxge_alloc_rx_mem_fail1:
1635 	/* Free data buffers */
1636 	i--;
1637 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1638 	    "==> hxge_alloc_rx_mem_pool: freeing data bufs (%d)", i));
1639 	for (; i >= 0; i--) {
1640 		hxge_free_rx_buf_dma(hxgep, (p_hxge_dma_common_t)dma_buf_p[i],
1641 		    num_chunks[i]);
1642 	}
1643 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1644 	    "==> hxge_alloc_rx_mem_pool: data bufs freed (%d)", i));
1645 
1646 	KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
1647 	KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t));
1648 	KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t));
1649 	KMEM_FREE(dma_rbr_cntl_poolp, sizeof (hxge_dma_pool_t));
1650 	KMEM_FREE(dma_rbr_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
1651 	KMEM_FREE(dma_rcr_cntl_poolp, sizeof (hxge_dma_pool_t));
1652 	KMEM_FREE(dma_rcr_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
1653 	KMEM_FREE(dma_mbox_cntl_poolp, sizeof (hxge_dma_pool_t));
1654 	KMEM_FREE(dma_mbox_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
1655 
1656 hxge_alloc_rx_mem_pool_exit:
1657 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1658 	    "<== hxge_alloc_rx_mem_pool:status 0x%08x", status));
1659 
1660 	return (status);
1661 }
1662 
1663 static void
1664 hxge_free_rx_mem_pool(p_hxge_t hxgep)
1665 {
1666 	uint32_t		i, ndmas;
1667 	p_hxge_dma_pool_t	dma_poolp;
1668 	p_hxge_dma_common_t	*dma_buf_p;
1669 	p_hxge_dma_pool_t	dma_rbr_cntl_poolp;
1670 	p_hxge_dma_common_t	*dma_rbr_cntl_p;
1671 	p_hxge_dma_pool_t	dma_rcr_cntl_poolp;
1672 	p_hxge_dma_common_t	*dma_rcr_cntl_p;
1673 	p_hxge_dma_pool_t	dma_mbox_cntl_poolp;
1674 	p_hxge_dma_common_t	*dma_mbox_cntl_p;
1675 	uint32_t		*num_chunks;
1676 
1677 	HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_free_rx_mem_pool"));
1678 
1679 	dma_poolp = hxgep->rx_buf_pool_p;
1680 	if (dma_poolp == NULL || (!dma_poolp->buf_allocated)) {
1681 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_free_rx_mem_pool "
1682 		    "(null rx buf pool or buf not allocated"));
1683 		return;
1684 	}
1685 
1686 	dma_rbr_cntl_poolp = hxgep->rx_rbr_cntl_pool_p;
1687 	if (dma_rbr_cntl_poolp == NULL ||
1688 	    (!dma_rbr_cntl_poolp->buf_allocated)) {
1689 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
1690 		    "<== hxge_free_rx_mem_pool "
1691 		    "(null rbr cntl buf pool or rbr cntl buf not allocated"));
1692 		return;
1693 	}
1694 
1695 	dma_rcr_cntl_poolp = hxgep->rx_rcr_cntl_pool_p;
1696 	if (dma_rcr_cntl_poolp == NULL ||
1697 	    (!dma_rcr_cntl_poolp->buf_allocated)) {
1698 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
1699 		    "<== hxge_free_rx_mem_pool "
1700 		    "(null rcr cntl buf pool or rcr cntl buf not allocated"));
1701 		return;
1702 	}
1703 
1704 	dma_mbox_cntl_poolp = hxgep->rx_mbox_cntl_pool_p;
1705 	if (dma_mbox_cntl_poolp == NULL ||
1706 	    (!dma_mbox_cntl_poolp->buf_allocated)) {
1707 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
1708 		    "<== hxge_free_rx_mem_pool "
1709 		    "(null mbox cntl buf pool or mbox cntl buf not allocated"));
1710 		return;
1711 	}
1712 
1713 	dma_buf_p = dma_poolp->dma_buf_pool_p;
1714 	num_chunks = dma_poolp->num_chunks;
1715 
1716 	dma_rbr_cntl_p = dma_rbr_cntl_poolp->dma_buf_pool_p;
1717 	dma_rcr_cntl_p = dma_rcr_cntl_poolp->dma_buf_pool_p;
1718 	dma_mbox_cntl_p = dma_mbox_cntl_poolp->dma_buf_pool_p;
1719 	ndmas = dma_rbr_cntl_poolp->ndmas;
1720 
1721 	for (i = 0; i < ndmas; i++) {
1722 		hxge_free_rx_buf_dma(hxgep, dma_buf_p[i], num_chunks[i]);
1723 	}
1724 
1725 	for (i = 0; i < ndmas; i++) {
1726 		hxge_free_rx_cntl_dma(hxgep, dma_rbr_cntl_p[i]);
1727 		hxge_free_rx_cntl_dma(hxgep, dma_rcr_cntl_p[i]);
1728 		hxge_free_rx_cntl_dma(hxgep, dma_mbox_cntl_p[i]);
1729 	}
1730 
1731 	for (i = 0; i < ndmas; i++) {
1732 		KMEM_FREE(dma_buf_p[i],
1733 		    sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK);
1734 		KMEM_FREE(dma_rbr_cntl_p[i], sizeof (hxge_dma_common_t));
1735 		KMEM_FREE(dma_rcr_cntl_p[i], sizeof (hxge_dma_common_t));
1736 		KMEM_FREE(dma_mbox_cntl_p[i], sizeof (hxge_dma_common_t));
1737 	}
1738 
1739 	KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
1740 	KMEM_FREE(dma_rbr_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
1741 	KMEM_FREE(dma_rbr_cntl_poolp, sizeof (hxge_dma_pool_t));
1742 	KMEM_FREE(dma_rcr_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
1743 	KMEM_FREE(dma_rcr_cntl_poolp, sizeof (hxge_dma_pool_t));
1744 	KMEM_FREE(dma_mbox_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
1745 	KMEM_FREE(dma_mbox_cntl_poolp, sizeof (hxge_dma_pool_t));
1746 	KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t));
1747 	KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t));
1748 
1749 	hxgep->rx_buf_pool_p = NULL;
1750 	hxgep->rx_rbr_cntl_pool_p = NULL;
1751 	hxgep->rx_rcr_cntl_pool_p = NULL;
1752 	hxgep->rx_mbox_cntl_pool_p = NULL;
1753 
1754 	HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_free_rx_mem_pool"));
1755 }
1756 
1757 static hxge_status_t
1758 hxge_alloc_rx_buf_dma(p_hxge_t hxgep, uint16_t dma_channel,
1759     p_hxge_dma_common_t *dmap,
1760     size_t alloc_size, size_t block_size, uint32_t *num_chunks)
1761 {
1762 	p_hxge_dma_common_t	rx_dmap;
1763 	hxge_status_t		status = HXGE_OK;
1764 	size_t			total_alloc_size;
1765 	size_t			allocated = 0;
1766 	int			i, size_index, array_size;
1767 
1768 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_rx_buf_dma"));
1769 
1770 	rx_dmap = (p_hxge_dma_common_t)
1771 	    KMEM_ZALLOC(sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK, KM_SLEEP);
1772 
1773 	HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
1774 	    " alloc_rx_buf_dma rdc %d asize %x bsize %x bbuf %llx ",
1775 	    dma_channel, alloc_size, block_size, dmap));
1776 
1777 	total_alloc_size = alloc_size;
1778 
1779 	i = 0;
1780 	size_index = 0;
1781 	array_size = sizeof (alloc_sizes) / sizeof (size_t);
1782 	while ((size_index < array_size) &&
1783 	    (alloc_sizes[size_index] < alloc_size))
1784 		size_index++;
1785 	if (size_index >= array_size) {
1786 		size_index = array_size - 1;
1787 	}
1788 
1789 	while ((allocated < total_alloc_size) &&
1790 	    (size_index >= 0) && (i < HXGE_DMA_BLOCK)) {
1791 		rx_dmap[i].dma_chunk_index = i;
1792 		rx_dmap[i].block_size = block_size;
1793 		rx_dmap[i].alength = alloc_sizes[size_index];
1794 		rx_dmap[i].orig_alength = rx_dmap[i].alength;
1795 		rx_dmap[i].nblocks = alloc_sizes[size_index] / block_size;
1796 		rx_dmap[i].dma_channel = dma_channel;
1797 		rx_dmap[i].contig_alloc_type = B_FALSE;
1798 
1799 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
1800 		    "alloc_rx_buf_dma rdc %d chunk %d bufp %llx size %x "
1801 		    "i %d nblocks %d alength %d",
1802 		    dma_channel, i, &rx_dmap[i], block_size,
1803 		    i, rx_dmap[i].nblocks, rx_dmap[i].alength));
1804 		status = hxge_dma_mem_alloc(hxgep, hxge_force_dma,
1805 		    &hxge_rx_dma_attr, rx_dmap[i].alength,
1806 		    &hxge_dev_buf_dma_acc_attr,
1807 		    DDI_DMA_READ | DDI_DMA_STREAMING,
1808 		    (p_hxge_dma_common_t)(&rx_dmap[i]));
1809 		if (status != HXGE_OK) {
1810 			HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1811 			    " hxge_alloc_rx_buf_dma: Alloc Failed: "
1812 			    " for size: %d", alloc_sizes[size_index]));
1813 			size_index--;
1814 		} else {
1815 			HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1816 			    " alloc_rx_buf_dma allocated rdc %d "
1817 			    "chunk %d size %x dvma %x bufp %llx ",
1818 			    dma_channel, i, rx_dmap[i].alength,
1819 			    rx_dmap[i].ioaddr_pp, &rx_dmap[i]));
1820 			i++;
1821 			allocated += alloc_sizes[size_index];
1822 		}
1823 	}
1824 
1825 	if (allocated < total_alloc_size) {
1826 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
1827 		    " hxge_alloc_rx_buf_dma failed due to"
1828 		    " allocated(%d) < required(%d)",
1829 		    allocated, total_alloc_size));
1830 		goto hxge_alloc_rx_mem_fail1;
1831 	}
1832 
1833 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1834 	    " alloc_rx_buf_dma rdc %d allocated %d chunks", dma_channel, i));
1835 
1836 	*num_chunks = i;
1837 	*dmap = rx_dmap;
1838 
1839 	goto hxge_alloc_rx_mem_exit;
1840 
1841 hxge_alloc_rx_mem_fail1:
1842 	KMEM_FREE(rx_dmap, sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK);
1843 
1844 hxge_alloc_rx_mem_exit:
1845 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1846 	    "<== hxge_alloc_rx_buf_dma status 0x%08x", status));
1847 
1848 	return (status);
1849 }
1850 
1851 /*ARGSUSED*/
1852 static void
1853 hxge_free_rx_buf_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap,
1854     uint32_t num_chunks)
1855 {
1856 	int i;
1857 
1858 	HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
1859 	    "==> hxge_free_rx_buf_dma: # of chunks %d", num_chunks));
1860 
1861 	for (i = 0; i < num_chunks; i++) {
1862 		HXGE_DEBUG_MSG((hxgep, MEM2_CTL,
1863 		    "==> hxge_free_rx_buf_dma: chunk %d dmap 0x%llx", i, dmap));
1864 		hxge_dma_mem_free(dmap++);
1865 	}
1866 
1867 	HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_free_rx_buf_dma"));
1868 }
1869 
1870 /*ARGSUSED*/
1871 static hxge_status_t
1872 hxge_alloc_rx_cntl_dma(p_hxge_t hxgep, uint16_t dma_channel,
1873     p_hxge_dma_common_t *dmap, struct ddi_dma_attr *attr, size_t size)
1874 {
1875 	p_hxge_dma_common_t	rx_dmap;
1876 	hxge_status_t		status = HXGE_OK;
1877 
1878 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_rx_cntl_dma"));
1879 
1880 	rx_dmap = (p_hxge_dma_common_t)
1881 	    KMEM_ZALLOC(sizeof (hxge_dma_common_t), KM_SLEEP);
1882 
1883 	rx_dmap->contig_alloc_type = B_FALSE;
1884 
1885 	status = hxge_dma_mem_alloc(hxgep, hxge_force_dma,
1886 	    attr, size, &hxge_dev_desc_dma_acc_attr,
1887 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT, rx_dmap);
1888 	if (status != HXGE_OK) {
1889 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
1890 		    " hxge_alloc_rx_cntl_dma: Alloc Failed: "
1891 		    " for size: %d", size));
1892 		goto hxge_alloc_rx_cntl_dma_fail1;
1893 	}
1894 
1895 	*dmap = rx_dmap;
1896 
1897 	goto hxge_alloc_rx_cntl_dma_exit;
1898 
1899 hxge_alloc_rx_cntl_dma_fail1:
1900 	KMEM_FREE(rx_dmap, sizeof (hxge_dma_common_t));
1901 
1902 hxge_alloc_rx_cntl_dma_exit:
1903 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
1904 	    "<== hxge_alloc_rx_cntl_dma status 0x%08x", status));
1905 
1906 	return (status);
1907 }
1908 
1909 /*ARGSUSED*/
1910 static void
1911 hxge_free_rx_cntl_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap)
1912 {
1913 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_free_rx_cntl_dma"));
1914 
1915 	hxge_dma_mem_free(dmap);
1916 
1917 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_free_rx_cntl_dma"));
1918 }
1919 
1920 static hxge_status_t
1921 hxge_alloc_tx_mem_pool(p_hxge_t hxgep)
1922 {
1923 	hxge_status_t		status = HXGE_OK;
1924 	int			i, j;
1925 	uint32_t		ndmas, st_tdc;
1926 	p_hxge_dma_pt_cfg_t	p_all_cfgp;
1927 	p_hxge_hw_pt_cfg_t	p_cfgp;
1928 	p_hxge_dma_pool_t	dma_poolp;
1929 	p_hxge_dma_common_t	*dma_buf_p;
1930 	p_hxge_dma_pool_t	dma_cntl_poolp;
1931 	p_hxge_dma_common_t	*dma_cntl_p;
1932 	size_t			tx_buf_alloc_size;
1933 	size_t			tx_cntl_alloc_size;
1934 	uint32_t		*num_chunks;	/* per dma */
1935 
1936 	HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_alloc_tx_mem_pool"));
1937 
1938 	p_all_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config;
1939 	p_cfgp = (p_hxge_hw_pt_cfg_t)&p_all_cfgp->hw_config;
1940 	st_tdc = p_cfgp->start_tdc;
1941 	ndmas = p_cfgp->max_tdcs;
1942 
1943 	HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_alloc_tx_mem_pool: "
1944 	    "p_cfgp 0x%016llx start_tdc %d ndmas %d hxgep->max_tdcs %d",
1945 	    p_cfgp, p_cfgp->start_tdc, p_cfgp->max_tdcs, hxgep->max_tdcs));
1946 	/*
1947 	 * Allocate memory for each transmit DMA channel.
1948 	 */
1949 	dma_poolp = (p_hxge_dma_pool_t)KMEM_ZALLOC(sizeof (hxge_dma_pool_t),
1950 	    KM_SLEEP);
1951 	dma_buf_p = (p_hxge_dma_common_t *)KMEM_ZALLOC(
1952 	    sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP);
1953 
1954 	dma_cntl_poolp = (p_hxge_dma_pool_t)
1955 	    KMEM_ZALLOC(sizeof (hxge_dma_pool_t), KM_SLEEP);
1956 	dma_cntl_p = (p_hxge_dma_common_t *)KMEM_ZALLOC(
1957 	    sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP);
1958 
1959 	hxgep->hxge_port_tx_ring_size = hxge_tx_ring_size;
1960 
1961 	/*
1962 	 * Assume that each DMA channel will be configured with default
1963 	 * transmit bufer size for copying transmit data. (For packet payload
1964 	 * over this limit, packets will not be copied.)
1965 	 */
1966 	tx_buf_alloc_size = (hxge_bcopy_thresh * hxge_tx_ring_size);
1967 
1968 	/*
1969 	 * Addresses of transmit descriptor ring and the mailbox must be all
1970 	 * cache-aligned (64 bytes).
1971 	 */
1972 	tx_cntl_alloc_size = hxge_tx_ring_size;
1973 	tx_cntl_alloc_size *= (sizeof (tx_desc_t));
1974 	tx_cntl_alloc_size += sizeof (txdma_mailbox_t);
1975 
1976 	num_chunks = (uint32_t *)KMEM_ZALLOC(sizeof (uint32_t) * ndmas,
1977 	    KM_SLEEP);
1978 
1979 	/*
1980 	 * Allocate memory for transmit buffers and descriptor rings. Replace
1981 	 * allocation functions with interface functions provided by the
1982 	 * partition manager when it is available.
1983 	 *
1984 	 * Allocate memory for the transmit buffer pool.
1985 	 */
1986 	for (i = 0; i < ndmas; i++) {
1987 		num_chunks[i] = 0;
1988 		status = hxge_alloc_tx_buf_dma(hxgep, st_tdc, &dma_buf_p[i],
1989 		    tx_buf_alloc_size, hxge_bcopy_thresh, &num_chunks[i]);
1990 		if (status != HXGE_OK) {
1991 			break;
1992 		}
1993 		st_tdc++;
1994 	}
1995 
1996 	if (i < ndmas) {
1997 		goto hxge_alloc_tx_mem_pool_fail1;
1998 	}
1999 
2000 	st_tdc = p_cfgp->start_tdc;
2001 
2002 	/*
2003 	 * Allocate memory for descriptor rings and mailbox.
2004 	 */
2005 	for (j = 0; j < ndmas; j++) {
2006 		status = hxge_alloc_tx_cntl_dma(hxgep, st_tdc, &dma_cntl_p[j],
2007 		    tx_cntl_alloc_size);
2008 		if (status != HXGE_OK) {
2009 			break;
2010 		}
2011 		st_tdc++;
2012 	}
2013 
2014 	if (j < ndmas) {
2015 		goto hxge_alloc_tx_mem_pool_fail2;
2016 	}
2017 
2018 	dma_poolp->ndmas = ndmas;
2019 	dma_poolp->num_chunks = num_chunks;
2020 	dma_poolp->buf_allocated = B_TRUE;
2021 	dma_poolp->dma_buf_pool_p = dma_buf_p;
2022 	hxgep->tx_buf_pool_p = dma_poolp;
2023 
2024 	dma_cntl_poolp->ndmas = ndmas;
2025 	dma_cntl_poolp->buf_allocated = B_TRUE;
2026 	dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p;
2027 	hxgep->tx_cntl_pool_p = dma_cntl_poolp;
2028 
2029 	HXGE_DEBUG_MSG((hxgep, MEM_CTL,
2030 	    "==> hxge_alloc_tx_mem_pool: start_tdc %d "
2031 	    "ndmas %d poolp->ndmas %d", st_tdc, ndmas, dma_poolp->ndmas));
2032 
2033 	goto hxge_alloc_tx_mem_pool_exit;
2034 
2035 hxge_alloc_tx_mem_pool_fail2:
2036 	/* Free control buffers */
2037 	j--;
2038 	for (; j >= 0; j--) {
2039 		hxge_free_tx_cntl_dma(hxgep,
2040 		    (p_hxge_dma_common_t)dma_cntl_p[j]);
2041 	}
2042 
2043 hxge_alloc_tx_mem_pool_fail1:
2044 	/* Free data buffers */
2045 	i--;
2046 	for (; i >= 0; i--) {
2047 		hxge_free_tx_buf_dma(hxgep, (p_hxge_dma_common_t)dma_buf_p[i],
2048 		    num_chunks[i]);
2049 	}
2050 
2051 	KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t));
2052 	KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t));
2053 	KMEM_FREE(dma_cntl_poolp, sizeof (hxge_dma_pool_t));
2054 	KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
2055 	KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
2056 
2057 hxge_alloc_tx_mem_pool_exit:
2058 	HXGE_DEBUG_MSG((hxgep, MEM_CTL,
2059 	    "<== hxge_alloc_tx_mem_pool:status 0x%08x", status));
2060 
2061 	return (status);
2062 }
2063 
2064 static hxge_status_t
2065 hxge_alloc_tx_buf_dma(p_hxge_t hxgep, uint16_t dma_channel,
2066     p_hxge_dma_common_t *dmap, size_t alloc_size,
2067     size_t block_size, uint32_t *num_chunks)
2068 {
2069 	p_hxge_dma_common_t	tx_dmap;
2070 	hxge_status_t		status = HXGE_OK;
2071 	size_t			total_alloc_size;
2072 	size_t			allocated = 0;
2073 	int			i, size_index, array_size;
2074 
2075 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_tx_buf_dma"));
2076 
2077 	tx_dmap = (p_hxge_dma_common_t)
2078 	    KMEM_ZALLOC(sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK, KM_SLEEP);
2079 
2080 	total_alloc_size = alloc_size;
2081 	i = 0;
2082 	size_index = 0;
2083 	array_size = sizeof (alloc_sizes) / sizeof (size_t);
2084 	while ((size_index < array_size) &&
2085 	    (alloc_sizes[size_index] < alloc_size))
2086 		size_index++;
2087 	if (size_index >= array_size) {
2088 		size_index = array_size - 1;
2089 	}
2090 
2091 	while ((allocated < total_alloc_size) &&
2092 	    (size_index >= 0) && (i < HXGE_DMA_BLOCK)) {
2093 		tx_dmap[i].dma_chunk_index = i;
2094 		tx_dmap[i].block_size = block_size;
2095 		tx_dmap[i].alength = alloc_sizes[size_index];
2096 		tx_dmap[i].orig_alength = tx_dmap[i].alength;
2097 		tx_dmap[i].nblocks = alloc_sizes[size_index] / block_size;
2098 		tx_dmap[i].dma_channel = dma_channel;
2099 		tx_dmap[i].contig_alloc_type = B_FALSE;
2100 
2101 		status = hxge_dma_mem_alloc(hxgep, hxge_force_dma,
2102 		    &hxge_tx_dma_attr, tx_dmap[i].alength,
2103 		    &hxge_dev_buf_dma_acc_attr,
2104 		    DDI_DMA_WRITE | DDI_DMA_STREAMING,
2105 		    (p_hxge_dma_common_t)(&tx_dmap[i]));
2106 		if (status != HXGE_OK) {
2107 			HXGE_DEBUG_MSG((hxgep, DMA_CTL,
2108 			    " hxge_alloc_tx_buf_dma: Alloc Failed: "
2109 			    " for size: %d", alloc_sizes[size_index]));
2110 			size_index--;
2111 		} else {
2112 			i++;
2113 			allocated += alloc_sizes[size_index];
2114 		}
2115 	}
2116 
2117 	if (allocated < total_alloc_size) {
2118 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
2119 		    " hxge_alloc_tx_buf_dma: failed due to"
2120 		    " allocated(%d) < required(%d)",
2121 		    allocated, total_alloc_size));
2122 		goto hxge_alloc_tx_mem_fail1;
2123 	}
2124 
2125 	*num_chunks = i;
2126 	*dmap = tx_dmap;
2127 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
2128 	    "==> hxge_alloc_tx_buf_dma dmap 0x%016llx num chunks %d",
2129 	    *dmap, i));
2130 	goto hxge_alloc_tx_mem_exit;
2131 
2132 hxge_alloc_tx_mem_fail1:
2133 	KMEM_FREE(tx_dmap, sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK);
2134 
2135 hxge_alloc_tx_mem_exit:
2136 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
2137 	    "<== hxge_alloc_tx_buf_dma status 0x%08x", status));
2138 
2139 	return (status);
2140 }
2141 
2142 /*ARGSUSED*/
2143 static void
2144 hxge_free_tx_buf_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap,
2145     uint32_t num_chunks)
2146 {
2147 	int i;
2148 
2149 	HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_free_tx_buf_dma"));
2150 
2151 	for (i = 0; i < num_chunks; i++) {
2152 		hxge_dma_mem_free(dmap++);
2153 	}
2154 
2155 	HXGE_DEBUG_MSG((hxgep, MEM_CTL, "<== hxge_free_tx_buf_dma"));
2156 }
2157 
2158 /*ARGSUSED*/
2159 static hxge_status_t
2160 hxge_alloc_tx_cntl_dma(p_hxge_t hxgep, uint16_t dma_channel,
2161     p_hxge_dma_common_t *dmap, size_t size)
2162 {
2163 	p_hxge_dma_common_t	tx_dmap;
2164 	hxge_status_t		status = HXGE_OK;
2165 
2166 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_tx_cntl_dma"));
2167 
2168 	tx_dmap = (p_hxge_dma_common_t)KMEM_ZALLOC(sizeof (hxge_dma_common_t),
2169 	    KM_SLEEP);
2170 
2171 	tx_dmap->contig_alloc_type = B_FALSE;
2172 
2173 	status = hxge_dma_mem_alloc(hxgep, hxge_force_dma,
2174 	    &hxge_tx_desc_dma_attr, size, &hxge_dev_desc_dma_acc_attr,
2175 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT, tx_dmap);
2176 	if (status != HXGE_OK) {
2177 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
2178 		    " hxge_alloc_tx_cntl_dma: Alloc Failed: "
2179 		    " for size: %d", size));
2180 		goto hxge_alloc_tx_cntl_dma_fail1;
2181 	}
2182 
2183 	*dmap = tx_dmap;
2184 
2185 	goto hxge_alloc_tx_cntl_dma_exit;
2186 
2187 hxge_alloc_tx_cntl_dma_fail1:
2188 	KMEM_FREE(tx_dmap, sizeof (hxge_dma_common_t));
2189 
2190 hxge_alloc_tx_cntl_dma_exit:
2191 	HXGE_DEBUG_MSG((hxgep, DMA_CTL,
2192 	    "<== hxge_alloc_tx_cntl_dma status 0x%08x", status));
2193 
2194 	return (status);
2195 }
2196 
2197 /*ARGSUSED*/
2198 static void
2199 hxge_free_tx_cntl_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap)
2200 {
2201 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_free_tx_cntl_dma"));
2202 
2203 	hxge_dma_mem_free(dmap);
2204 
2205 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_free_tx_cntl_dma"));
2206 }
2207 
2208 static void
2209 hxge_free_tx_mem_pool(p_hxge_t hxgep)
2210 {
2211 	uint32_t		i, ndmas;
2212 	p_hxge_dma_pool_t	dma_poolp;
2213 	p_hxge_dma_common_t	*dma_buf_p;
2214 	p_hxge_dma_pool_t	dma_cntl_poolp;
2215 	p_hxge_dma_common_t	*dma_cntl_p;
2216 	uint32_t		*num_chunks;
2217 
2218 	HXGE_DEBUG_MSG((hxgep, MEM3_CTL, "==> hxge_free_tx_mem_pool"));
2219 
2220 	dma_poolp = hxgep->tx_buf_pool_p;
2221 	if (dma_poolp == NULL || (!dma_poolp->buf_allocated)) {
2222 		HXGE_DEBUG_MSG((hxgep, MEM3_CTL,
2223 		    "<== hxge_free_tx_mem_pool "
2224 		    "(null rx buf pool or buf not allocated"));
2225 		return;
2226 	}
2227 
2228 	dma_cntl_poolp = hxgep->tx_cntl_pool_p;
2229 	if (dma_cntl_poolp == NULL || (!dma_cntl_poolp->buf_allocated)) {
2230 		HXGE_DEBUG_MSG((hxgep, MEM3_CTL,
2231 		    "<== hxge_free_tx_mem_pool "
2232 		    "(null tx cntl buf pool or cntl buf not allocated"));
2233 		return;
2234 	}
2235 
2236 	dma_buf_p = dma_poolp->dma_buf_pool_p;
2237 	num_chunks = dma_poolp->num_chunks;
2238 
2239 	dma_cntl_p = dma_cntl_poolp->dma_buf_pool_p;
2240 	ndmas = dma_cntl_poolp->ndmas;
2241 
2242 	for (i = 0; i < ndmas; i++) {
2243 		hxge_free_tx_buf_dma(hxgep, dma_buf_p[i], num_chunks[i]);
2244 	}
2245 
2246 	for (i = 0; i < ndmas; i++) {
2247 		hxge_free_tx_cntl_dma(hxgep, dma_cntl_p[i]);
2248 	}
2249 
2250 	for (i = 0; i < ndmas; i++) {
2251 		KMEM_FREE(dma_buf_p[i],
2252 		    sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK);
2253 		KMEM_FREE(dma_cntl_p[i], sizeof (hxge_dma_common_t));
2254 	}
2255 
2256 	KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
2257 	KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_hxge_dma_common_t));
2258 	KMEM_FREE(dma_cntl_poolp, sizeof (hxge_dma_pool_t));
2259 	KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t));
2260 	KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t));
2261 
2262 	hxgep->tx_buf_pool_p = NULL;
2263 	hxgep->tx_cntl_pool_p = NULL;
2264 
2265 	HXGE_DEBUG_MSG((hxgep, MEM3_CTL, "<== hxge_free_tx_mem_pool"));
2266 }
2267 
2268 /*ARGSUSED*/
2269 static hxge_status_t
2270 hxge_dma_mem_alloc(p_hxge_t hxgep, dma_method_t method,
2271     struct ddi_dma_attr *dma_attrp,
2272     size_t length, ddi_device_acc_attr_t *acc_attr_p, uint_t xfer_flags,
2273     p_hxge_dma_common_t dma_p)
2274 {
2275 	caddr_t		kaddrp;
2276 	int		ddi_status = DDI_SUCCESS;
2277 
2278 	dma_p->dma_handle = NULL;
2279 	dma_p->acc_handle = NULL;
2280 	dma_p->kaddrp = NULL;
2281 
2282 	ddi_status = ddi_dma_alloc_handle(hxgep->dip, dma_attrp,
2283 	    DDI_DMA_DONTWAIT, NULL, &dma_p->dma_handle);
2284 	if (ddi_status != DDI_SUCCESS) {
2285 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
2286 		    "hxge_dma_mem_alloc:ddi_dma_alloc_handle failed."));
2287 		return (HXGE_ERROR | HXGE_DDI_FAILED);
2288 	}
2289 
2290 	ddi_status = ddi_dma_mem_alloc(dma_p->dma_handle, length, acc_attr_p,
2291 	    xfer_flags, DDI_DMA_DONTWAIT, 0, &kaddrp, &dma_p->alength,
2292 	    &dma_p->acc_handle);
2293 	if (ddi_status != DDI_SUCCESS) {
2294 		/* The caller will decide whether it is fatal */
2295 		HXGE_DEBUG_MSG((hxgep, DMA_CTL,
2296 		    "hxge_dma_mem_alloc:ddi_dma_mem_alloc failed"));
2297 		ddi_dma_free_handle(&dma_p->dma_handle);
2298 		dma_p->dma_handle = NULL;
2299 		return (HXGE_ERROR | HXGE_DDI_FAILED);
2300 	}
2301 
2302 	if (dma_p->alength < length) {
2303 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
2304 		    "hxge_dma_mem_alloc:ddi_dma_mem_alloc < length."));
2305 		ddi_dma_mem_free(&dma_p->acc_handle);
2306 		ddi_dma_free_handle(&dma_p->dma_handle);
2307 		dma_p->acc_handle = NULL;
2308 		dma_p->dma_handle = NULL;
2309 		return (HXGE_ERROR);
2310 	}
2311 
2312 	ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL,
2313 	    kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0,
2314 	    &dma_p->dma_cookie, &dma_p->ncookies);
2315 	if (ddi_status != DDI_DMA_MAPPED) {
2316 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
2317 		    "hxge_dma_mem_alloc:di_dma_addr_bind failed "
2318 		    "(staus 0x%x ncookies %d.)", ddi_status, dma_p->ncookies));
2319 		if (dma_p->acc_handle) {
2320 			ddi_dma_mem_free(&dma_p->acc_handle);
2321 			dma_p->acc_handle = NULL;
2322 		}
2323 		ddi_dma_free_handle(&dma_p->dma_handle);
2324 		dma_p->dma_handle = NULL;
2325 		return (HXGE_ERROR | HXGE_DDI_FAILED);
2326 	}
2327 
2328 	if (dma_p->ncookies != 1) {
2329 		HXGE_DEBUG_MSG((hxgep, DMA_CTL,
2330 		    "hxge_dma_mem_alloc:ddi_dma_addr_bind > 1 cookie"
2331 		    "(staus 0x%x ncookies %d.)", ddi_status, dma_p->ncookies));
2332 		if (dma_p->acc_handle) {
2333 			ddi_dma_mem_free(&dma_p->acc_handle);
2334 			dma_p->acc_handle = NULL;
2335 		}
2336 		(void) ddi_dma_unbind_handle(dma_p->dma_handle);
2337 		ddi_dma_free_handle(&dma_p->dma_handle);
2338 		dma_p->dma_handle = NULL;
2339 		return (HXGE_ERROR);
2340 	}
2341 
2342 	dma_p->kaddrp = kaddrp;
2343 #if defined(__i386)
2344 	dma_p->ioaddr_pp =
2345 	    (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress;
2346 #else
2347 	dma_p->ioaddr_pp = (unsigned char *) dma_p->dma_cookie.dmac_laddress;
2348 #endif
2349 
2350 	HPI_DMA_ACC_HANDLE_SET(dma_p, dma_p->acc_handle);
2351 
2352 	HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_dma_mem_alloc: "
2353 	    "dma buffer allocated: dma_p $%p "
2354 	    "return dmac_ladress from cookie $%p dmac_size %d "
2355 	    "dma_p->ioaddr_p $%p "
2356 	    "dma_p->orig_ioaddr_p $%p "
2357 	    "orig_vatopa $%p "
2358 	    "alength %d (0x%x) "
2359 	    "kaddrp $%p "
2360 	    "length %d (0x%x)",
2361 	    dma_p,
2362 	    dma_p->dma_cookie.dmac_laddress,
2363 	    dma_p->dma_cookie.dmac_size,
2364 	    dma_p->ioaddr_pp,
2365 	    dma_p->orig_ioaddr_pp,
2366 	    dma_p->orig_vatopa,
2367 	    dma_p->alength, dma_p->alength,
2368 	    kaddrp,
2369 	    length, length));
2370 
2371 	return (HXGE_OK);
2372 }
2373 
2374 static void
2375 hxge_dma_mem_free(p_hxge_dma_common_t dma_p)
2376 {
2377 	if (dma_p == NULL)
2378 		return;
2379 
2380 	if (dma_p->dma_handle != NULL) {
2381 		if (dma_p->ncookies) {
2382 			(void) ddi_dma_unbind_handle(dma_p->dma_handle);
2383 			dma_p->ncookies = 0;
2384 		}
2385 		ddi_dma_free_handle(&dma_p->dma_handle);
2386 		dma_p->dma_handle = NULL;
2387 	}
2388 
2389 	if (dma_p->acc_handle != NULL) {
2390 		ddi_dma_mem_free(&dma_p->acc_handle);
2391 		dma_p->acc_handle = NULL;
2392 		HPI_DMA_ACC_HANDLE_SET(dma_p, NULL);
2393 	}
2394 
2395 	dma_p->kaddrp = NULL;
2396 	dma_p->alength = NULL;
2397 }
2398 
2399 /*
2400  *	hxge_m_start() -- start transmitting and receiving.
2401  *
2402  *	This function is called by the MAC layer when the first
2403  *	stream is open to prepare the hardware ready for sending
2404  *	and transmitting packets.
2405  */
2406 static int
2407 hxge_m_start(void *arg)
2408 {
2409 	p_hxge_t hxgep = (p_hxge_t)arg;
2410 
2411 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_start"));
2412 
2413 	MUTEX_ENTER(hxgep->genlock);
2414 
2415 	if (hxge_init(hxgep) != DDI_SUCCESS) {
2416 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
2417 		    "<== hxge_m_start: initialization failed"));
2418 		MUTEX_EXIT(hxgep->genlock);
2419 		return (EIO);
2420 	}
2421 
2422 	if (hxgep->hxge_mac_state != HXGE_MAC_STARTED) {
2423 		/*
2424 		 * Start timer to check the system error and tx hangs
2425 		 */
2426 		hxgep->hxge_timerid = hxge_start_timer(hxgep,
2427 		    hxge_check_hw_state, HXGE_CHECK_TIMER);
2428 
2429 		hxgep->hxge_mac_state = HXGE_MAC_STARTED;
2430 
2431 		hxgep->timeout.link_status = 0;
2432 		hxgep->timeout.report_link_status = B_TRUE;
2433 		hxgep->timeout.ticks = drv_usectohz(2 * 1000000);
2434 
2435 		/* Start the link status timer to check the link status */
2436 		MUTEX_ENTER(&hxgep->timeout.lock);
2437 		hxgep->timeout.id = timeout(hxge_link_poll, (void *)hxgep,
2438 		    hxgep->timeout.ticks);
2439 		MUTEX_EXIT(&hxgep->timeout.lock);
2440 	}
2441 
2442 	MUTEX_EXIT(hxgep->genlock);
2443 
2444 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_start"));
2445 
2446 	return (0);
2447 }
2448 
2449 /*
2450  * hxge_m_stop(): stop transmitting and receiving.
2451  */
2452 static void
2453 hxge_m_stop(void *arg)
2454 {
2455 	p_hxge_t hxgep = (p_hxge_t)arg;
2456 
2457 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_stop"));
2458 
2459 	if (hxgep->hxge_timerid) {
2460 		hxge_stop_timer(hxgep, hxgep->hxge_timerid);
2461 		hxgep->hxge_timerid = 0;
2462 	}
2463 
2464 	/* Stop the link status timer before unregistering */
2465 	MUTEX_ENTER(&hxgep->timeout.lock);
2466 	if (hxgep->timeout.id) {
2467 		(void) untimeout(hxgep->timeout.id);
2468 		hxgep->timeout.id = 0;
2469 	}
2470 	hxge_link_update(hxgep, LINK_STATE_DOWN);
2471 	MUTEX_EXIT(&hxgep->timeout.lock);
2472 
2473 	MUTEX_ENTER(hxgep->genlock);
2474 
2475 	hxge_uninit(hxgep);
2476 
2477 	hxgep->hxge_mac_state = HXGE_MAC_STOPPED;
2478 
2479 	MUTEX_EXIT(hxgep->genlock);
2480 
2481 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_stop"));
2482 }
2483 
2484 static int
2485 hxge_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
2486 {
2487 	p_hxge_t		hxgep = (p_hxge_t)arg;
2488 	struct ether_addr	addrp;
2489 
2490 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_m_multicst: add %d", add));
2491 
2492 	bcopy(mca, (uint8_t *)&addrp, ETHERADDRL);
2493 
2494 	if (add) {
2495 		if (hxge_add_mcast_addr(hxgep, &addrp)) {
2496 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
2497 			    "<== hxge_m_multicst: add multicast failed"));
2498 			return (EINVAL);
2499 		}
2500 	} else {
2501 		if (hxge_del_mcast_addr(hxgep, &addrp)) {
2502 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
2503 			    "<== hxge_m_multicst: del multicast failed"));
2504 			return (EINVAL);
2505 		}
2506 	}
2507 
2508 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_m_multicst"));
2509 
2510 	return (0);
2511 }
2512 
2513 static int
2514 hxge_m_promisc(void *arg, boolean_t on)
2515 {
2516 	p_hxge_t hxgep = (p_hxge_t)arg;
2517 
2518 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_m_promisc: on %d", on));
2519 
2520 	if (hxge_set_promisc(hxgep, on)) {
2521 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
2522 		    "<== hxge_m_promisc: set promisc failed"));
2523 		return (EINVAL);
2524 	}
2525 
2526 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_m_promisc: on %d", on));
2527 
2528 	return (0);
2529 }
2530 
2531 static void
2532 hxge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
2533 {
2534 	p_hxge_t	hxgep = (p_hxge_t)arg;
2535 	struct iocblk	*iocp = (struct iocblk *)mp->b_rptr;
2536 	boolean_t	need_privilege;
2537 	int		err;
2538 	int		cmd;
2539 
2540 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_ioctl"));
2541 
2542 	iocp = (struct iocblk *)mp->b_rptr;
2543 	iocp->ioc_error = 0;
2544 	need_privilege = B_TRUE;
2545 	cmd = iocp->ioc_cmd;
2546 
2547 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_ioctl: cmd 0x%08x", cmd));
2548 	switch (cmd) {
2549 	default:
2550 		miocnak(wq, mp, 0, EINVAL);
2551 		HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_ioctl: invalid"));
2552 		return;
2553 
2554 	case LB_GET_INFO_SIZE:
2555 	case LB_GET_INFO:
2556 	case LB_GET_MODE:
2557 		need_privilege = B_FALSE;
2558 		break;
2559 
2560 	case LB_SET_MODE:
2561 		break;
2562 
2563 	case ND_GET:
2564 		need_privilege = B_FALSE;
2565 		break;
2566 	case ND_SET:
2567 		break;
2568 
2569 	case HXGE_GET_TX_RING_SZ:
2570 	case HXGE_GET_TX_DESC:
2571 	case HXGE_TX_SIDE_RESET:
2572 	case HXGE_RX_SIDE_RESET:
2573 	case HXGE_GLOBAL_RESET:
2574 	case HXGE_RESET_MAC:
2575 	case HXGE_PUT_TCAM:
2576 	case HXGE_GET_TCAM:
2577 	case HXGE_RTRACE:
2578 
2579 		need_privilege = B_FALSE;
2580 		break;
2581 	}
2582 
2583 	if (need_privilege) {
2584 		err = secpolicy_net_config(iocp->ioc_cr, B_FALSE);
2585 		if (err != 0) {
2586 			miocnak(wq, mp, 0, err);
2587 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
2588 			    "<== hxge_m_ioctl: no priv"));
2589 			return;
2590 		}
2591 	}
2592 
2593 	switch (cmd) {
2594 	case ND_GET:
2595 		HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "ND_GET command"));
2596 	case ND_SET:
2597 		HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "ND_SET command"));
2598 		hxge_param_ioctl(hxgep, wq, mp, iocp);
2599 		break;
2600 
2601 	case LB_GET_MODE:
2602 	case LB_SET_MODE:
2603 	case LB_GET_INFO_SIZE:
2604 	case LB_GET_INFO:
2605 		hxge_loopback_ioctl(hxgep, wq, mp, iocp);
2606 		break;
2607 
2608 	case HXGE_PUT_TCAM:
2609 	case HXGE_GET_TCAM:
2610 	case HXGE_GET_TX_RING_SZ:
2611 	case HXGE_GET_TX_DESC:
2612 	case HXGE_TX_SIDE_RESET:
2613 	case HXGE_RX_SIDE_RESET:
2614 	case HXGE_GLOBAL_RESET:
2615 	case HXGE_RESET_MAC:
2616 		HXGE_DEBUG_MSG((hxgep, NEMO_CTL,
2617 		    "==> hxge_m_ioctl: cmd 0x%x", cmd));
2618 		hxge_hw_ioctl(hxgep, wq, mp, iocp);
2619 		break;
2620 	}
2621 
2622 	HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_ioctl"));
2623 }
2624 
2625 /*ARGSUSED*/
2626 static int
2627 hxge_tx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num)
2628 {
2629 	p_hxge_ring_handle_t	rhp = (p_hxge_ring_handle_t)rdriver;
2630 	p_hxge_t		hxgep;
2631 	p_tx_ring_t		ring;
2632 
2633 	ASSERT(rhp != NULL);
2634 	ASSERT((rhp->index >= 0) && (rhp->index < HXGE_MAX_TDCS));
2635 
2636 	hxgep = rhp->hxgep;
2637 
2638 	/*
2639 	 * Get the ring pointer.
2640 	 */
2641 	ring = hxgep->tx_rings->rings[rhp->index];
2642 
2643 	/*
2644 	 * Fill in the handle for the transmit.
2645 	 */
2646 	MUTEX_ENTER(&ring->lock);
2647 	rhp->started = B_TRUE;
2648 	ring->ring_handle = rhp->ring_handle;
2649 	MUTEX_EXIT(&ring->lock);
2650 
2651 	return (0);
2652 }
2653 
2654 static void
2655 hxge_tx_ring_stop(mac_ring_driver_t rdriver)
2656 {
2657 	p_hxge_ring_handle_t    rhp = (p_hxge_ring_handle_t)rdriver;
2658 	p_hxge_t		hxgep;
2659 	p_tx_ring_t		ring;
2660 
2661 	ASSERT(rhp != NULL);
2662 	ASSERT((rhp->index >= 0) && (rhp->index < HXGE_MAX_TDCS));
2663 
2664 	hxgep = rhp->hxgep;
2665 	ring = hxgep->tx_rings->rings[rhp->index];
2666 
2667 	MUTEX_ENTER(&ring->lock);
2668 	ring->ring_handle = (mac_ring_handle_t)NULL;
2669 	rhp->started = B_FALSE;
2670 	MUTEX_EXIT(&ring->lock);
2671 }
2672 
2673 static int
2674 hxge_rx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num)
2675 {
2676 	p_hxge_ring_handle_t	rhp = (p_hxge_ring_handle_t)rdriver;
2677 	p_hxge_t		hxgep;
2678 	p_rx_rcr_ring_t		ring;
2679 	int			i;
2680 
2681 	ASSERT(rhp != NULL);
2682 	ASSERT((rhp->index >= 0) && (rhp->index < HXGE_MAX_TDCS));
2683 
2684 	hxgep = rhp->hxgep;
2685 
2686 	/*
2687 	 * Get pointer to ring.
2688 	 */
2689 	ring = hxgep->rx_rcr_rings->rcr_rings[rhp->index];
2690 
2691 	MUTEX_ENTER(&ring->lock);
2692 
2693 	if (rhp->started) {
2694 		MUTEX_EXIT(&ring->lock);
2695 		return (0);
2696 	}
2697 
2698 	/*
2699 	 * Set the ldvp and ldgp pointers to enable/disable
2700 	 * polling.
2701 	 */
2702 	for (i = 0; i < hxgep->ldgvp->maxldvs; i++) {
2703 		if ((hxgep->ldgvp->ldvp[i].is_rxdma == 1) &&
2704 		    (hxgep->ldgvp->ldvp[i].channel == rhp->index)) {
2705 			ring->ldvp = &hxgep->ldgvp->ldvp[i];
2706 			ring->ldgp = hxgep->ldgvp->ldvp[i].ldgp;
2707 			break;
2708 		}
2709 	}
2710 
2711 	rhp->started = B_TRUE;
2712 	ring->rcr_mac_handle = rhp->ring_handle;
2713 	ring->rcr_gen_num = mr_gen_num;
2714 	MUTEX_EXIT(&ring->lock);
2715 
2716 	return (0);
2717 }
2718 
2719 static void
2720 hxge_rx_ring_stop(mac_ring_driver_t rdriver)
2721 {
2722 	p_hxge_ring_handle_t	rhp = (p_hxge_ring_handle_t)rdriver;
2723 	p_hxge_t		hxgep;
2724 	p_rx_rcr_ring_t		ring;
2725 
2726 	ASSERT(rhp != NULL);
2727 	ASSERT((rhp->index >= 0) && (rhp->index < HXGE_MAX_TDCS));
2728 
2729 	hxgep = rhp->hxgep;
2730 	ring =  hxgep->rx_rcr_rings->rcr_rings[rhp->index];
2731 
2732 	MUTEX_ENTER(&ring->lock);
2733 	rhp->started = B_TRUE;
2734 	ring->rcr_mac_handle = NULL;
2735 	ring->ldvp = NULL;
2736 	ring->ldgp = NULL;
2737 	MUTEX_EXIT(&ring->lock);
2738 }
2739 
2740 static int
2741 hxge_rx_group_start(mac_group_driver_t gdriver)
2742 {
2743 	hxge_ring_group_t	*group = (hxge_ring_group_t *)gdriver;
2744 
2745 	ASSERT(group->hxgep != NULL);
2746 	ASSERT(group->hxgep->hxge_mac_state == HXGE_MAC_STARTED);
2747 
2748 	MUTEX_ENTER(group->hxgep->genlock);
2749 	group->started = B_TRUE;
2750 	MUTEX_EXIT(group->hxgep->genlock);
2751 
2752 	return (0);
2753 }
2754 
2755 static void
2756 hxge_rx_group_stop(mac_group_driver_t gdriver)
2757 {
2758 	hxge_ring_group_t	*group = (hxge_ring_group_t *)gdriver;
2759 
2760 	ASSERT(group->hxgep != NULL);
2761 	ASSERT(group->hxgep->hxge_mac_state == HXGE_MAC_STARTED);
2762 	ASSERT(group->started == B_TRUE);
2763 
2764 	MUTEX_ENTER(group->hxgep->genlock);
2765 	group->started = B_FALSE;
2766 	MUTEX_EXIT(group->hxgep->genlock);
2767 }
2768 
2769 static int
2770 hxge_mmac_get_slot(p_hxge_t hxgep, int *slot)
2771 {
2772 	int	i;
2773 
2774 	/*
2775 	 * Find an open slot.
2776 	 */
2777 	for (i = 0; i < hxgep->mmac.total; i++) {
2778 		if (!hxgep->mmac.addrs[i].set) {
2779 			*slot = i;
2780 			return (0);
2781 		}
2782 	}
2783 
2784 	return (ENXIO);
2785 }
2786 
2787 static int
2788 hxge_mmac_set_addr(p_hxge_t hxgep, int slot, const uint8_t *addr)
2789 {
2790 	struct ether_addr	eaddr;
2791 	hxge_status_t		status = HXGE_OK;
2792 
2793 	bcopy(addr, (uint8_t *)&eaddr, ETHERADDRL);
2794 
2795 	/*
2796 	 * Set new interface local address and re-init device.
2797 	 * This is destructive to any other streams attached
2798 	 * to this device.
2799 	 */
2800 	RW_ENTER_WRITER(&hxgep->filter_lock);
2801 	status = hxge_pfc_set_mac_address(hxgep, slot, &eaddr);
2802 	RW_EXIT(&hxgep->filter_lock);
2803 	if (status != HXGE_OK)
2804 		return (status);
2805 
2806 	hxgep->mmac.addrs[slot].set = B_TRUE;
2807 	bcopy(addr, hxgep->mmac.addrs[slot].addr, ETHERADDRL);
2808 	hxgep->mmac.available--;
2809 	if (slot == HXGE_MAC_DEFAULT_ADDR_SLOT)
2810 		hxgep->mmac.addrs[slot].primary = B_TRUE;
2811 
2812 	return (0);
2813 }
2814 
2815 static int
2816 hxge_mmac_find_addr(p_hxge_t hxgep, const uint8_t *addr, int *slot)
2817 {
2818 	int	i, result;
2819 
2820 	for (i = 0; i < hxgep->mmac.total; i++) {
2821 		if (hxgep->mmac.addrs[i].set) {
2822 			result = memcmp(hxgep->mmac.addrs[i].addr,
2823 			    addr, ETHERADDRL);
2824 			if (result == 0) {
2825 				*slot = i;
2826 				return (0);
2827 			}
2828 		}
2829 	}
2830 
2831 	return (EINVAL);
2832 }
2833 
2834 static int
2835 hxge_mmac_unset_addr(p_hxge_t hxgep, int slot)
2836 {
2837 	hxge_status_t	status;
2838 	int		i;
2839 
2840 	status = hxge_pfc_clear_mac_address(hxgep, slot);
2841 	if (status != HXGE_OK)
2842 		return (status);
2843 
2844 	for (i = 0; i < ETHERADDRL; i++)
2845 		hxgep->mmac.addrs[slot].addr[i] = 0;
2846 
2847 	hxgep->mmac.addrs[slot].set = B_FALSE;
2848 	if (slot == HXGE_MAC_DEFAULT_ADDR_SLOT)
2849 		hxgep->mmac.addrs[slot].primary = B_FALSE;
2850 	hxgep->mmac.available++;
2851 
2852 	return (0);
2853 }
2854 
2855 static int
2856 hxge_rx_group_add_mac(void *arg, const uint8_t *mac_addr)
2857 {
2858 	hxge_ring_group_t	*group = arg;
2859 	p_hxge_t		hxgep = group->hxgep;
2860 	int			slot = 0;
2861 
2862 	ASSERT(group->type == MAC_RING_TYPE_RX);
2863 
2864 	MUTEX_ENTER(hxgep->genlock);
2865 
2866 	/*
2867 	 * Find a slot for the address.
2868 	 */
2869 	if (hxge_mmac_get_slot(hxgep, &slot) != 0) {
2870 		MUTEX_EXIT(hxgep->genlock);
2871 		return (ENOSPC);
2872 	}
2873 
2874 	/*
2875 	 * Program the MAC address.
2876 	 */
2877 	if (hxge_mmac_set_addr(hxgep, slot, mac_addr) != 0) {
2878 		MUTEX_EXIT(hxgep->genlock);
2879 		return (ENOSPC);
2880 	}
2881 
2882 	MUTEX_EXIT(hxgep->genlock);
2883 	return (0);
2884 }
2885 
2886 static int
2887 hxge_rx_group_rem_mac(void *arg, const uint8_t *mac_addr)
2888 {
2889 	hxge_ring_group_t	*group = arg;
2890 	p_hxge_t		hxgep = group->hxgep;
2891 	int			rv, slot;
2892 
2893 	ASSERT(group->type == MAC_RING_TYPE_RX);
2894 
2895 	MUTEX_ENTER(hxgep->genlock);
2896 
2897 	if ((rv = hxge_mmac_find_addr(hxgep, mac_addr, &slot)) != 0) {
2898 		MUTEX_EXIT(hxgep->genlock);
2899 		return (rv);
2900 	}
2901 
2902 	if ((rv = hxge_mmac_unset_addr(hxgep, slot)) != 0) {
2903 		MUTEX_EXIT(hxgep->genlock);
2904 		return (rv);
2905 	}
2906 
2907 	MUTEX_EXIT(hxgep->genlock);
2908 	return (0);
2909 }
2910 
2911 static void
2912 hxge_group_get(void *arg, mac_ring_type_t type, int groupid,
2913     mac_group_info_t *infop, mac_group_handle_t gh)
2914 {
2915 	p_hxge_t		hxgep = arg;
2916 	hxge_ring_group_t	*group;
2917 
2918 	ASSERT(type == MAC_RING_TYPE_RX);
2919 
2920 	switch (type) {
2921 	case MAC_RING_TYPE_RX:
2922 		group = &hxgep->rx_groups[groupid];
2923 		group->hxgep = hxgep;
2924 		group->ghandle = gh;
2925 		group->index = groupid;
2926 		group->type = type;
2927 
2928 		infop->mgi_driver = (mac_group_driver_t)group;
2929 		infop->mgi_start = hxge_rx_group_start;
2930 		infop->mgi_stop = hxge_rx_group_stop;
2931 		infop->mgi_addmac = hxge_rx_group_add_mac;
2932 		infop->mgi_remmac = hxge_rx_group_rem_mac;
2933 		infop->mgi_count = HXGE_MAX_RDCS;
2934 		break;
2935 
2936 	case MAC_RING_TYPE_TX:
2937 	default:
2938 		break;
2939 	}
2940 }
2941 
2942 static int
2943 hxge_ring_get_htable_idx(p_hxge_t hxgep, mac_ring_type_t type, uint32_t channel)
2944 {
2945 	int i;
2946 
2947 	ASSERT(hxgep->ldgvp != NULL);
2948 
2949 	switch (type) {
2950 	case MAC_RING_TYPE_RX:
2951 		for (i = 0; i < hxgep->ldgvp->maxldvs; i++) {
2952 			if ((hxgep->ldgvp->ldvp[i].is_rxdma) &&
2953 			    (hxgep->ldgvp->ldvp[i].channel == channel)) {
2954 				return ((int)
2955 				    hxgep->ldgvp->ldvp[i].ldgp->htable_idx);
2956 			}
2957 		}
2958 		break;
2959 
2960 	case MAC_RING_TYPE_TX:
2961 		for (i = 0; i < hxgep->ldgvp->maxldvs; i++) {
2962 			if ((hxgep->ldgvp->ldvp[i].is_txdma) &&
2963 			    (hxgep->ldgvp->ldvp[i].channel == channel)) {
2964 				return ((int)
2965 				    hxgep->ldgvp->ldvp[i].ldgp->htable_idx);
2966 			}
2967 		}
2968 		break;
2969 
2970 	default:
2971 		break;
2972 	}
2973 
2974 	return (-1);
2975 }
2976 
2977 /*
2978  * Callback function for the GLDv3 layer to register all rings.
2979  */
2980 /*ARGSUSED*/
2981 static void
2982 hxge_fill_ring(void *arg, mac_ring_type_t type, const int rg_index,
2983     const int index, mac_ring_info_t *infop, mac_ring_handle_t rh)
2984 {
2985 	p_hxge_t	hxgep = arg;
2986 
2987 	ASSERT(hxgep != NULL);
2988 	ASSERT(infop != NULL);
2989 
2990 	switch (type) {
2991 	case MAC_RING_TYPE_TX: {
2992 		p_hxge_ring_handle_t	rhp;
2993 		mac_intr_t		*mintr = &infop->mri_intr;
2994 		p_hxge_intr_t		intrp;
2995 		int			htable_idx;
2996 
2997 		ASSERT((index >= 0) && (index < HXGE_MAX_TDCS));
2998 		rhp = &hxgep->tx_ring_handles[index];
2999 		rhp->hxgep = hxgep;
3000 		rhp->index = index;
3001 		rhp->ring_handle = rh;
3002 		infop->mri_driver = (mac_ring_driver_t)rhp;
3003 		infop->mri_start = hxge_tx_ring_start;
3004 		infop->mri_stop = hxge_tx_ring_stop;
3005 		infop->mri_tx = hxge_tx_ring_send;
3006 		infop->mri_stat = hxge_tx_ring_stat;
3007 
3008 		intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
3009 		htable_idx = hxge_ring_get_htable_idx(hxgep, type, index);
3010 		if (htable_idx >= 0)
3011 			mintr->mi_ddi_handle = intrp->htable[htable_idx];
3012 		else
3013 			mintr->mi_ddi_handle = NULL;
3014 		break;
3015 	}
3016 
3017 	case MAC_RING_TYPE_RX: {
3018 		p_hxge_ring_handle_t    rhp;
3019 		mac_intr_t		hxge_mac_intr;
3020 		p_hxge_intr_t		intrp;
3021 		int			htable_idx;
3022 
3023 		ASSERT((index >= 0) && (index < HXGE_MAX_RDCS));
3024 		rhp = &hxgep->rx_ring_handles[index];
3025 		rhp->hxgep = hxgep;
3026 		rhp->index = index;
3027 		rhp->ring_handle = rh;
3028 
3029 		/*
3030 		 * Entrypoint to enable interrupt (disable poll) and
3031 		 * disable interrupt (enable poll).
3032 		 */
3033 		hxge_mac_intr.mi_handle = (mac_intr_handle_t)rhp;
3034 		hxge_mac_intr.mi_enable = (mac_intr_enable_t)hxge_disable_poll;
3035 		hxge_mac_intr.mi_disable = (mac_intr_disable_t)hxge_enable_poll;
3036 
3037 		intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
3038 		htable_idx = hxge_ring_get_htable_idx(hxgep, type, index);
3039 		if (htable_idx >= 0)
3040 			hxge_mac_intr.mi_ddi_handle = intrp->htable[htable_idx];
3041 		else
3042 			hxge_mac_intr.mi_ddi_handle = NULL;
3043 
3044 		infop->mri_driver = (mac_ring_driver_t)rhp;
3045 		infop->mri_start = hxge_rx_ring_start;
3046 		infop->mri_stop = hxge_rx_ring_stop;
3047 		infop->mri_intr = hxge_mac_intr;
3048 		infop->mri_poll = hxge_rx_poll;
3049 		infop->mri_stat = hxge_rx_ring_stat;
3050 		break;
3051 	}
3052 
3053 	default:
3054 		break;
3055 	}
3056 }
3057 
3058 /*ARGSUSED*/
3059 boolean_t
3060 hxge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
3061 {
3062 	p_hxge_t	hxgep = arg;
3063 
3064 	switch (cap) {
3065 	case MAC_CAPAB_HCKSUM: {
3066 		uint32_t	*txflags = cap_data;
3067 
3068 		*txflags = HCKSUM_INET_PARTIAL;
3069 		break;
3070 	}
3071 
3072 	case MAC_CAPAB_RINGS: {
3073 		mac_capab_rings_t	*cap_rings = cap_data;
3074 
3075 		MUTEX_ENTER(hxgep->genlock);
3076 		if (cap_rings->mr_type == MAC_RING_TYPE_RX) {
3077 			cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
3078 			cap_rings->mr_rnum = HXGE_MAX_RDCS;
3079 			cap_rings->mr_rget = hxge_fill_ring;
3080 			cap_rings->mr_gnum = HXGE_MAX_RX_GROUPS;
3081 			cap_rings->mr_gget = hxge_group_get;
3082 			cap_rings->mr_gaddring = NULL;
3083 			cap_rings->mr_gremring = NULL;
3084 		} else {
3085 			cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
3086 			cap_rings->mr_rnum = HXGE_MAX_TDCS;
3087 			cap_rings->mr_rget = hxge_fill_ring;
3088 			cap_rings->mr_gnum = 0;
3089 			cap_rings->mr_gget = NULL;
3090 			cap_rings->mr_gaddring = NULL;
3091 			cap_rings->mr_gremring = NULL;
3092 		}
3093 		MUTEX_EXIT(hxgep->genlock);
3094 		break;
3095 	}
3096 
3097 	default:
3098 		return (B_FALSE);
3099 	}
3100 	return (B_TRUE);
3101 }
3102 
3103 static boolean_t
3104 hxge_param_locked(mac_prop_id_t pr_num)
3105 {
3106 	/*
3107 	 * All adv_* parameters are locked (read-only) while
3108 	 * the device is in any sort of loopback mode ...
3109 	 */
3110 	switch (pr_num) {
3111 		case MAC_PROP_ADV_1000FDX_CAP:
3112 		case MAC_PROP_EN_1000FDX_CAP:
3113 		case MAC_PROP_ADV_1000HDX_CAP:
3114 		case MAC_PROP_EN_1000HDX_CAP:
3115 		case MAC_PROP_ADV_100FDX_CAP:
3116 		case MAC_PROP_EN_100FDX_CAP:
3117 		case MAC_PROP_ADV_100HDX_CAP:
3118 		case MAC_PROP_EN_100HDX_CAP:
3119 		case MAC_PROP_ADV_10FDX_CAP:
3120 		case MAC_PROP_EN_10FDX_CAP:
3121 		case MAC_PROP_ADV_10HDX_CAP:
3122 		case MAC_PROP_EN_10HDX_CAP:
3123 		case MAC_PROP_AUTONEG:
3124 		case MAC_PROP_FLOWCTRL:
3125 			return (B_TRUE);
3126 	}
3127 	return (B_FALSE);
3128 }
3129 
3130 /*
3131  * callback functions for set/get of properties
3132  */
3133 static int
3134 hxge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
3135     uint_t pr_valsize, const void *pr_val)
3136 {
3137 	hxge_t		*hxgep = barg;
3138 	p_hxge_stats_t	statsp;
3139 	int		err = 0;
3140 	uint32_t	new_mtu, old_framesize, new_framesize;
3141 
3142 	HXGE_DEBUG_MSG((hxgep, DLADM_CTL, "==> hxge_m_setprop"));
3143 
3144 	statsp = hxgep->statsp;
3145 	MUTEX_ENTER(hxgep->genlock);
3146 	if (statsp->port_stats.lb_mode != hxge_lb_normal &&
3147 	    hxge_param_locked(pr_num)) {
3148 		/*
3149 		 * All adv_* parameters are locked (read-only)
3150 		 * while the device is in any sort of loopback mode.
3151 		 */
3152 		HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
3153 		    "==> hxge_m_setprop: loopback mode: read only"));
3154 		MUTEX_EXIT(hxgep->genlock);
3155 		return (EBUSY);
3156 	}
3157 
3158 	switch (pr_num) {
3159 		/*
3160 		 * These properties are either not exist or read only
3161 		 */
3162 		case MAC_PROP_EN_1000FDX_CAP:
3163 		case MAC_PROP_EN_100FDX_CAP:
3164 		case MAC_PROP_EN_10FDX_CAP:
3165 		case MAC_PROP_EN_1000HDX_CAP:
3166 		case MAC_PROP_EN_100HDX_CAP:
3167 		case MAC_PROP_EN_10HDX_CAP:
3168 		case MAC_PROP_ADV_1000FDX_CAP:
3169 		case MAC_PROP_ADV_1000HDX_CAP:
3170 		case MAC_PROP_ADV_100FDX_CAP:
3171 		case MAC_PROP_ADV_100HDX_CAP:
3172 		case MAC_PROP_ADV_10FDX_CAP:
3173 		case MAC_PROP_ADV_10HDX_CAP:
3174 		case MAC_PROP_STATUS:
3175 		case MAC_PROP_SPEED:
3176 		case MAC_PROP_DUPLEX:
3177 		case MAC_PROP_AUTONEG:
3178 		/*
3179 		 * Flow control is handled in the shared domain and
3180 		 * it is readonly here.
3181 		 */
3182 		case MAC_PROP_FLOWCTRL:
3183 			err = EINVAL;
3184 			HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
3185 			    "==> hxge_m_setprop:  read only property %d",
3186 			    pr_num));
3187 			break;
3188 
3189 		case MAC_PROP_MTU:
3190 			bcopy(pr_val, &new_mtu, sizeof (new_mtu));
3191 			HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
3192 			    "==> hxge_m_setprop: set MTU: %d", new_mtu));
3193 
3194 			new_framesize = new_mtu + MTU_TO_FRAME_SIZE;
3195 			if (new_framesize == hxgep->vmac.maxframesize) {
3196 				err = 0;
3197 				break;
3198 			}
3199 
3200 			if (hxgep->hxge_mac_state == HXGE_MAC_STARTED) {
3201 				err = EBUSY;
3202 				break;
3203 			}
3204 
3205 			if (new_framesize < MIN_FRAME_SIZE ||
3206 			    new_framesize > MAX_FRAME_SIZE) {
3207 				err = EINVAL;
3208 				break;
3209 			}
3210 
3211 			old_framesize = hxgep->vmac.maxframesize;
3212 			hxgep->vmac.maxframesize = (uint16_t)new_framesize;
3213 
3214 			if (hxge_vmac_set_framesize(hxgep)) {
3215 				hxgep->vmac.maxframesize =
3216 				    (uint16_t)old_framesize;
3217 				err = EINVAL;
3218 				break;
3219 			}
3220 
3221 			err = mac_maxsdu_update(hxgep->mach, new_mtu);
3222 			if (err) {
3223 				hxgep->vmac.maxframesize =
3224 				    (uint16_t)old_framesize;
3225 				(void) hxge_vmac_set_framesize(hxgep);
3226 			}
3227 
3228 			HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
3229 			    "==> hxge_m_setprop: set MTU: %d maxframe %d",
3230 			    new_mtu, hxgep->vmac.maxframesize));
3231 			break;
3232 
3233 		case MAC_PROP_PRIVATE:
3234 			HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
3235 			    "==> hxge_m_setprop: private property"));
3236 			err = hxge_set_priv_prop(hxgep, pr_name, pr_valsize,
3237 			    pr_val);
3238 			break;
3239 
3240 		default:
3241 			err = ENOTSUP;
3242 			break;
3243 	}
3244 
3245 	MUTEX_EXIT(hxgep->genlock);
3246 
3247 	HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
3248 	    "<== hxge_m_setprop (return %d)", err));
3249 
3250 	return (err);
3251 }
3252 
3253 static int
3254 hxge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
3255     uint_t pr_valsize, void *pr_val)
3256 {
3257 	hxge_t 		*hxgep = barg;
3258 	p_hxge_stats_t	statsp = hxgep->statsp;
3259 	int		err = 0;
3260 	link_flowctrl_t fl;
3261 	uint64_t	tmp = 0;
3262 	link_state_t	ls;
3263 
3264 	HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
3265 	    "==> hxge_m_getprop: pr_num %d", pr_num));
3266 
3267 	switch (pr_num) {
3268 		case MAC_PROP_DUPLEX:
3269 			*(uint8_t *)pr_val = statsp->mac_stats.link_duplex;
3270 			HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
3271 			    "==> hxge_m_getprop: duplex mode %d",
3272 			    *(uint8_t *)pr_val));
3273 			break;
3274 
3275 		case MAC_PROP_SPEED:
3276 			ASSERT(pr_valsize >= sizeof (uint64_t));
3277 			tmp = statsp->mac_stats.link_speed * 1000000ull;
3278 			bcopy(&tmp, pr_val, sizeof (tmp));
3279 			break;
3280 
3281 		case MAC_PROP_STATUS:
3282 			ASSERT(pr_valsize >= sizeof (link_state_t));
3283 			if (!statsp->mac_stats.link_up)
3284 				ls = LINK_STATE_DOWN;
3285 			else
3286 				ls = LINK_STATE_UP;
3287 			bcopy(&ls, pr_val, sizeof (ls));
3288 			break;
3289 
3290 		case MAC_PROP_FLOWCTRL:
3291 			/*
3292 			 * Flow control is supported by the shared domain and
3293 			 * it is currently transmit only
3294 			 */
3295 			ASSERT(pr_valsize < sizeof (link_flowctrl_t));
3296 			fl = LINK_FLOWCTRL_TX;
3297 			bcopy(&fl, pr_val, sizeof (fl));
3298 			break;
3299 		case MAC_PROP_AUTONEG:
3300 			/* 10G link only and it is not negotiable */
3301 			*(uint8_t *)pr_val = 0;
3302 			break;
3303 		case MAC_PROP_ADV_1000FDX_CAP:
3304 		case MAC_PROP_ADV_100FDX_CAP:
3305 		case MAC_PROP_ADV_10FDX_CAP:
3306 		case MAC_PROP_ADV_1000HDX_CAP:
3307 		case MAC_PROP_ADV_100HDX_CAP:
3308 		case MAC_PROP_ADV_10HDX_CAP:
3309 		case MAC_PROP_EN_1000FDX_CAP:
3310 		case MAC_PROP_EN_100FDX_CAP:
3311 		case MAC_PROP_EN_10FDX_CAP:
3312 		case MAC_PROP_EN_1000HDX_CAP:
3313 		case MAC_PROP_EN_100HDX_CAP:
3314 		case MAC_PROP_EN_10HDX_CAP:
3315 			err = ENOTSUP;
3316 			break;
3317 
3318 		case MAC_PROP_PRIVATE:
3319 			err = hxge_get_priv_prop(hxgep, pr_name, pr_valsize,
3320 			    pr_val);
3321 			break;
3322 
3323 		default:
3324 			err = EINVAL;
3325 			break;
3326 	}
3327 
3328 	HXGE_DEBUG_MSG((hxgep, DLADM_CTL, "<== hxge_m_getprop"));
3329 
3330 	return (err);
3331 }
3332 
3333 static void
3334 hxge_m_propinfo(void *arg, const char *pr_name,
3335     mac_prop_id_t pr_num, mac_prop_info_handle_t prh)
3336 {
3337 	_NOTE(ARGUNUSED(arg));
3338 	switch (pr_num) {
3339 	case MAC_PROP_DUPLEX:
3340 	case MAC_PROP_SPEED:
3341 	case MAC_PROP_STATUS:
3342 	case MAC_PROP_AUTONEG:
3343 	case MAC_PROP_FLOWCTRL:
3344 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
3345 		break;
3346 
3347 	case MAC_PROP_MTU:
3348 		mac_prop_info_set_range_uint32(prh,
3349 		    MIN_FRAME_SIZE - MTU_TO_FRAME_SIZE,
3350 		    MAX_FRAME_SIZE - MTU_TO_FRAME_SIZE);
3351 		break;
3352 
3353 	case MAC_PROP_PRIVATE: {
3354 		char valstr[MAXNAMELEN];
3355 
3356 		bzero(valstr, sizeof (valstr));
3357 
3358 		/* Receive Interrupt Blanking Parameters */
3359 		if (strcmp(pr_name, "_rxdma_intr_time") == 0) {
3360 			(void) snprintf(valstr, sizeof (valstr), "%d",
3361 			    RXDMA_RCR_TO_DEFAULT);
3362 		} else if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) {
3363 			(void) snprintf(valstr, sizeof (valstr), "%d",
3364 			    RXDMA_RCR_PTHRES_DEFAULT);
3365 
3366 		/* Classification and Load Distribution Configuration */
3367 		} else if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0 ||
3368 		    strcmp(pr_name, "_class_opt_ipv4_udp") == 0 ||
3369 		    strcmp(pr_name, "_class_opt_ipv4_ah") == 0 ||
3370 		    strcmp(pr_name, "_class_opt_ipv4_sctp") == 0 ||
3371 		    strcmp(pr_name, "_class_opt_ipv6_tcp") == 0 ||
3372 		    strcmp(pr_name, "_class_opt_ipv6_udp") == 0 ||
3373 		    strcmp(pr_name, "_class_opt_ipv6_ah") == 0 ||
3374 		    strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) {
3375 			(void) snprintf(valstr, sizeof (valstr), "%d",
3376 			    HXGE_CLASS_TCAM_LOOKUP);
3377 		}
3378 
3379 		if (strlen(valstr) > 0)
3380 			mac_prop_info_set_default_str(prh, valstr);
3381 		break;
3382 	}
3383 	}
3384 }
3385 
3386 
3387 /* ARGSUSED */
3388 static int
3389 hxge_set_priv_prop(p_hxge_t hxgep, const char *pr_name, uint_t pr_valsize,
3390     const void *pr_val)
3391 {
3392 	p_hxge_param_t	param_arr = hxgep->param_arr;
3393 	int		err = 0;
3394 
3395 	HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
3396 	    "==> hxge_set_priv_prop: name %s (value %s)", pr_name, pr_val));
3397 
3398 	if (pr_val == NULL) {
3399 		return (EINVAL);
3400 	}
3401 
3402 	/* Blanking */
3403 	if (strcmp(pr_name, "_rxdma_intr_time") == 0) {
3404 		err = hxge_param_rx_intr_time(hxgep, NULL, NULL,
3405 		    (char *)pr_val, (caddr_t)&param_arr[param_rxdma_intr_time]);
3406 	} else if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) {
3407 		err = hxge_param_rx_intr_pkts(hxgep, NULL, NULL,
3408 		    (char *)pr_val, (caddr_t)&param_arr[param_rxdma_intr_pkts]);
3409 
3410 	/* Classification */
3411 	} else if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) {
3412 		err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
3413 		    (caddr_t)&param_arr[param_class_opt_ipv4_tcp]);
3414 	} else if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) {
3415 		err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
3416 		    (caddr_t)&param_arr[param_class_opt_ipv4_udp]);
3417 	} else if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) {
3418 		err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
3419 		    (caddr_t)&param_arr[param_class_opt_ipv4_ah]);
3420 	} else if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) {
3421 		err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
3422 		    (caddr_t)&param_arr[param_class_opt_ipv4_sctp]);
3423 	} else if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) {
3424 		err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
3425 		    (caddr_t)&param_arr[param_class_opt_ipv6_tcp]);
3426 	} else if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) {
3427 		err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
3428 		    (caddr_t)&param_arr[param_class_opt_ipv6_udp]);
3429 	} else if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) {
3430 		err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
3431 		    (caddr_t)&param_arr[param_class_opt_ipv6_ah]);
3432 	} else if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) {
3433 		err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val,
3434 		    (caddr_t)&param_arr[param_class_opt_ipv6_sctp]);
3435 	} else {
3436 		err = EINVAL;
3437 	}
3438 
3439 	HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
3440 	    "<== hxge_set_priv_prop: err %d", err));
3441 
3442 	return (err);
3443 }
3444 
3445 static int
3446 hxge_get_priv_prop(p_hxge_t hxgep, const char *pr_name, uint_t pr_valsize,
3447     void *pr_val)
3448 {
3449 	p_hxge_param_t	param_arr = hxgep->param_arr;
3450 	char		valstr[MAXNAMELEN];
3451 	int		err = 0;
3452 	uint_t		strsize;
3453 	int		value = 0;
3454 
3455 	HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
3456 	    "==> hxge_get_priv_prop: property %s", pr_name));
3457 
3458 	/* Receive Interrupt Blanking Parameters */
3459 	if (strcmp(pr_name, "_rxdma_intr_time") == 0) {
3460 		value = hxgep->intr_timeout;
3461 	} else if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) {
3462 		value = hxgep->intr_threshold;
3463 
3464 	/* Classification and Load Distribution Configuration */
3465 	} else if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) {
3466 		err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3467 		    (caddr_t)&param_arr[param_class_opt_ipv4_tcp]);
3468 
3469 		value = (int)param_arr[param_class_opt_ipv4_tcp].value;
3470 	} else if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) {
3471 		err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3472 		    (caddr_t)&param_arr[param_class_opt_ipv4_udp]);
3473 
3474 		value = (int)param_arr[param_class_opt_ipv4_udp].value;
3475 	} else if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) {
3476 		err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3477 		    (caddr_t)&param_arr[param_class_opt_ipv4_ah]);
3478 
3479 		value = (int)param_arr[param_class_opt_ipv4_ah].value;
3480 	} else if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) {
3481 		err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3482 		    (caddr_t)&param_arr[param_class_opt_ipv4_sctp]);
3483 
3484 		value = (int)param_arr[param_class_opt_ipv4_sctp].value;
3485 	} else if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) {
3486 		err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3487 		    (caddr_t)&param_arr[param_class_opt_ipv6_tcp]);
3488 
3489 		value = (int)param_arr[param_class_opt_ipv6_tcp].value;
3490 	} else if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) {
3491 		err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3492 		    (caddr_t)&param_arr[param_class_opt_ipv6_udp]);
3493 
3494 		value = (int)param_arr[param_class_opt_ipv6_udp].value;
3495 	} else if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) {
3496 		err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3497 		    (caddr_t)&param_arr[param_class_opt_ipv6_ah]);
3498 
3499 		value = (int)param_arr[param_class_opt_ipv6_ah].value;
3500 	} else if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) {
3501 		err = hxge_param_get_ip_opt(hxgep, NULL, NULL,
3502 		    (caddr_t)&param_arr[param_class_opt_ipv6_sctp]);
3503 
3504 		value = (int)param_arr[param_class_opt_ipv6_sctp].value;
3505 	} else {
3506 		err = EINVAL;
3507 	}
3508 
3509 	if (err == 0) {
3510 		(void) snprintf(valstr, sizeof (valstr), "0x%x", value);
3511 
3512 		strsize = (uint_t)strlen(valstr);
3513 		if (pr_valsize < strsize) {
3514 			err = ENOBUFS;
3515 		} else {
3516 			(void) strlcpy(pr_val, valstr, pr_valsize);
3517 		}
3518 	}
3519 
3520 	HXGE_DEBUG_MSG((hxgep, DLADM_CTL,
3521 	    "<== hxge_get_priv_prop: return %d", err));
3522 
3523 	return (err);
3524 }
3525 /*
3526  * Module loading and removing entry points.
3527  */
3528 DDI_DEFINE_STREAM_OPS(hxge_dev_ops, nulldev, nulldev, hxge_attach, hxge_detach,
3529     nodev, NULL, D_MP, NULL, NULL);
3530 
3531 extern struct mod_ops mod_driverops;
3532 
3533 #define	HXGE_DESC_VER	"HXGE 10Gb Ethernet Driver"
3534 
3535 /*
3536  * Module linkage information for the kernel.
3537  */
3538 static struct modldrv hxge_modldrv = {
3539 	&mod_driverops,
3540 	HXGE_DESC_VER,
3541 	&hxge_dev_ops
3542 };
3543 
3544 static struct modlinkage modlinkage = {
3545 	MODREV_1, (void *) &hxge_modldrv, NULL
3546 };
3547 
3548 int
3549 _init(void)
3550 {
3551 	int status;
3552 
3553 	HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _init"));
3554 	mac_init_ops(&hxge_dev_ops, "hxge");
3555 	status = ddi_soft_state_init(&hxge_list, sizeof (hxge_t), 0);
3556 	if (status != 0) {
3557 		HXGE_ERROR_MSG((NULL, HXGE_ERR_CTL,
3558 		    "failed to init device soft state"));
3559 		mac_fini_ops(&hxge_dev_ops);
3560 		goto _init_exit;
3561 	}
3562 
3563 	status = mod_install(&modlinkage);
3564 	if (status != 0) {
3565 		ddi_soft_state_fini(&hxge_list);
3566 		HXGE_ERROR_MSG((NULL, HXGE_ERR_CTL, "Mod install failed"));
3567 		goto _init_exit;
3568 	}
3569 
3570 	MUTEX_INIT(&hxge_common_lock, NULL, MUTEX_DRIVER, NULL);
3571 
3572 _init_exit:
3573 	HXGE_DEBUG_MSG((NULL, MOD_CTL, "_init status = 0x%X", status));
3574 
3575 	return (status);
3576 }
3577 
3578 int
3579 _fini(void)
3580 {
3581 	int status;
3582 
3583 	HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini"));
3584 
3585 	HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini: mod_remove"));
3586 
3587 	if (hxge_mblks_pending)
3588 		return (EBUSY);
3589 
3590 	status = mod_remove(&modlinkage);
3591 	if (status != DDI_SUCCESS) {
3592 		HXGE_DEBUG_MSG((NULL, MOD_CTL,
3593 		    "Module removal failed 0x%08x", status));
3594 		goto _fini_exit;
3595 	}
3596 
3597 	mac_fini_ops(&hxge_dev_ops);
3598 
3599 	ddi_soft_state_fini(&hxge_list);
3600 
3601 	MUTEX_DESTROY(&hxge_common_lock);
3602 
3603 _fini_exit:
3604 	HXGE_DEBUG_MSG((NULL, MOD_CTL, "_fini status = 0x%08x", status));
3605 
3606 	return (status);
3607 }
3608 
3609 int
3610 _info(struct modinfo *modinfop)
3611 {
3612 	int status;
3613 
3614 	HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _info"));
3615 	status = mod_info(&modlinkage, modinfop);
3616 	HXGE_DEBUG_MSG((NULL, MOD_CTL, " _info status = 0x%X", status));
3617 
3618 	return (status);
3619 }
3620 
3621 /*ARGSUSED*/
3622 static hxge_status_t
3623 hxge_add_intrs(p_hxge_t hxgep)
3624 {
3625 	int		intr_types;
3626 	int		type = 0;
3627 	int		ddi_status = DDI_SUCCESS;
3628 	hxge_status_t	status = HXGE_OK;
3629 
3630 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs"));
3631 
3632 	hxgep->hxge_intr_type.intr_registered = B_FALSE;
3633 	hxgep->hxge_intr_type.intr_enabled = B_FALSE;
3634 	hxgep->hxge_intr_type.msi_intx_cnt = 0;
3635 	hxgep->hxge_intr_type.intr_added = 0;
3636 	hxgep->hxge_intr_type.niu_msi_enable = B_FALSE;
3637 	hxgep->hxge_intr_type.intr_type = 0;
3638 
3639 	if (hxge_msi_enable) {
3640 		hxgep->hxge_intr_type.niu_msi_enable = B_TRUE;
3641 	}
3642 
3643 	/* Get the supported interrupt types */
3644 	if ((ddi_status = ddi_intr_get_supported_types(hxgep->dip, &intr_types))
3645 	    != DDI_SUCCESS) {
3646 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "<== hxge_add_intrs: "
3647 		    "ddi_intr_get_supported_types failed: status 0x%08x",
3648 		    ddi_status));
3649 		return (HXGE_ERROR | HXGE_DDI_FAILED);
3650 	}
3651 
3652 	hxgep->hxge_intr_type.intr_types = intr_types;
3653 
3654 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: "
3655 	    "ddi_intr_get_supported_types: 0x%08x", intr_types));
3656 
3657 	/*
3658 	 * Pick the interrupt type to use MSIX, MSI, INTX hxge_msi_enable:
3659 	 *	(1): 1 - MSI
3660 	 *	(2): 2 - MSI-X
3661 	 *	others - FIXED
3662 	 */
3663 	switch (hxge_msi_enable) {
3664 	default:
3665 		type = DDI_INTR_TYPE_FIXED;
3666 		HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: "
3667 		    "use fixed (intx emulation) type %08x", type));
3668 		break;
3669 
3670 	case 2:
3671 		HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: "
3672 		    "ddi_intr_get_supported_types: 0x%08x", intr_types));
3673 		if (intr_types & DDI_INTR_TYPE_MSIX) {
3674 			type = DDI_INTR_TYPE_MSIX;
3675 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
3676 			    "==> hxge_add_intrs: "
3677 			    "ddi_intr_get_supported_types: MSIX 0x%08x", type));
3678 		} else if (intr_types & DDI_INTR_TYPE_MSI) {
3679 			type = DDI_INTR_TYPE_MSI;
3680 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
3681 			    "==> hxge_add_intrs: "
3682 			    "ddi_intr_get_supported_types: MSI 0x%08x", type));
3683 		} else if (intr_types & DDI_INTR_TYPE_FIXED) {
3684 			type = DDI_INTR_TYPE_FIXED;
3685 			HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: "
3686 			    "ddi_intr_get_supported_types: MSXED0x%08x", type));
3687 		}
3688 		break;
3689 
3690 	case 1:
3691 		if (intr_types & DDI_INTR_TYPE_MSI) {
3692 			type = DDI_INTR_TYPE_MSI;
3693 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
3694 			    "==> hxge_add_intrs: "
3695 			    "ddi_intr_get_supported_types: MSI 0x%08x", type));
3696 		} else if (intr_types & DDI_INTR_TYPE_MSIX) {
3697 			type = DDI_INTR_TYPE_MSIX;
3698 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
3699 			    "==> hxge_add_intrs: "
3700 			    "ddi_intr_get_supported_types: MSIX 0x%08x", type));
3701 		} else if (intr_types & DDI_INTR_TYPE_FIXED) {
3702 			type = DDI_INTR_TYPE_FIXED;
3703 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
3704 			    "==> hxge_add_intrs: "
3705 			    "ddi_intr_get_supported_types: MSXED0x%08x", type));
3706 		}
3707 	}
3708 
3709 	hxgep->hxge_intr_type.intr_type = type;
3710 	if ((type == DDI_INTR_TYPE_MSIX || type == DDI_INTR_TYPE_MSI ||
3711 	    type == DDI_INTR_TYPE_FIXED) &&
3712 	    hxgep->hxge_intr_type.niu_msi_enable) {
3713 		if ((status = hxge_add_intrs_adv(hxgep)) != DDI_SUCCESS) {
3714 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
3715 			    " hxge_add_intrs: "
3716 			    " hxge_add_intrs_adv failed: status 0x%08x",
3717 			    status));
3718 			return (status);
3719 		} else {
3720 			HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_add_intrs: "
3721 			    "interrupts registered : type %d", type));
3722 			hxgep->hxge_intr_type.intr_registered = B_TRUE;
3723 
3724 			HXGE_DEBUG_MSG((hxgep, DDI_CTL,
3725 			    "\nAdded advanced hxge add_intr_adv "
3726 			    "intr type 0x%x\n", type));
3727 
3728 			return (status);
3729 		}
3730 	}
3731 
3732 	if (!hxgep->hxge_intr_type.intr_registered) {
3733 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
3734 		    "==> hxge_add_intrs: failed to register interrupts"));
3735 		return (HXGE_ERROR | HXGE_DDI_FAILED);
3736 	}
3737 
3738 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs"));
3739 
3740 	return (status);
3741 }
3742 
3743 /*ARGSUSED*/
3744 static hxge_status_t
3745 hxge_add_intrs_adv(p_hxge_t hxgep)
3746 {
3747 	int		intr_type;
3748 	p_hxge_intr_t	intrp;
3749 	hxge_status_t	status;
3750 
3751 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv"));
3752 
3753 	intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
3754 	intr_type = intrp->intr_type;
3755 
3756 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv: type 0x%x",
3757 	    intr_type));
3758 
3759 	switch (intr_type) {
3760 	case DDI_INTR_TYPE_MSI:		/* 0x2 */
3761 	case DDI_INTR_TYPE_MSIX:	/* 0x4 */
3762 		status = hxge_add_intrs_adv_type(hxgep, intr_type);
3763 		break;
3764 
3765 	case DDI_INTR_TYPE_FIXED:	/* 0x1 */
3766 		status = hxge_add_intrs_adv_type_fix(hxgep, intr_type);
3767 		break;
3768 
3769 	default:
3770 		status = HXGE_ERROR;
3771 		break;
3772 	}
3773 
3774 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs_adv"));
3775 
3776 	return (status);
3777 }
3778 
3779 /*ARGSUSED*/
3780 static hxge_status_t
3781 hxge_add_intrs_adv_type(p_hxge_t hxgep, uint32_t int_type)
3782 {
3783 	dev_info_t	*dip = hxgep->dip;
3784 	p_hxge_ldg_t	ldgp;
3785 	p_hxge_intr_t	intrp;
3786 	uint_t		*inthandler;
3787 	void		*arg1, *arg2;
3788 	int		behavior;
3789 	int		nintrs, navail;
3790 	int		nactual, nrequired, nrequest;
3791 	int		inum = 0;
3792 	int		loop = 0;
3793 	int		x, y;
3794 	int		ddi_status = DDI_SUCCESS;
3795 	hxge_status_t	status = HXGE_OK;
3796 
3797 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv_type"));
3798 
3799 	intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
3800 
3801 	ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs);
3802 	if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) {
3803 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
3804 		    "ddi_intr_get_nintrs() failed, status: 0x%x%, "
3805 		    "nintrs: %d", ddi_status, nintrs));
3806 		return (HXGE_ERROR | HXGE_DDI_FAILED);
3807 	}
3808 
3809 	ddi_status = ddi_intr_get_navail(dip, int_type, &navail);
3810 	if ((ddi_status != DDI_SUCCESS) || (navail == 0)) {
3811 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
3812 		    "ddi_intr_get_navail() failed, status: 0x%x%, "
3813 		    "nintrs: %d", ddi_status, navail));
3814 		return (HXGE_ERROR | HXGE_DDI_FAILED);
3815 	}
3816 
3817 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
3818 	    "ddi_intr_get_navail() returned: intr type %d nintrs %d, navail %d",
3819 	    int_type, nintrs, navail));
3820 
3821 	/* PSARC/2007/453 MSI-X interrupt limit override */
3822 	if (int_type == DDI_INTR_TYPE_MSIX) {
3823 		nrequest = hxge_create_msi_property(hxgep);
3824 		if (nrequest < navail) {
3825 			navail = nrequest;
3826 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
3827 			    "hxge_add_intrs_adv_type: nintrs %d "
3828 			    "navail %d (nrequest %d)",
3829 			    nintrs, navail, nrequest));
3830 		}
3831 	}
3832 
3833 	if (int_type == DDI_INTR_TYPE_MSI && !ISP2(navail)) {
3834 		/* MSI must be power of 2 */
3835 		if ((navail & 16) == 16) {
3836 			navail = 16;
3837 		} else if ((navail & 8) == 8) {
3838 			navail = 8;
3839 		} else if ((navail & 4) == 4) {
3840 			navail = 4;
3841 		} else if ((navail & 2) == 2) {
3842 			navail = 2;
3843 		} else {
3844 			navail = 1;
3845 		}
3846 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
3847 		    "ddi_intr_get_navail(): (msi power of 2) nintrs %d, "
3848 		    "navail %d", nintrs, navail));
3849 	}
3850 
3851 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
3852 	    "requesting: intr type %d nintrs %d, navail %d",
3853 	    int_type, nintrs, navail));
3854 
3855 	behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT :
3856 	    DDI_INTR_ALLOC_NORMAL);
3857 	intrp->intr_size = navail * sizeof (ddi_intr_handle_t);
3858 	intrp->htable = kmem_zalloc(intrp->intr_size, KM_SLEEP);
3859 
3860 	ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum,
3861 	    navail, &nactual, behavior);
3862 	if (ddi_status != DDI_SUCCESS || nactual == 0) {
3863 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
3864 		    " ddi_intr_alloc() failed: %d", ddi_status));
3865 		kmem_free(intrp->htable, intrp->intr_size);
3866 		return (HXGE_ERROR | HXGE_DDI_FAILED);
3867 	}
3868 
3869 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
3870 	    "ddi_intr_alloc() returned: navail %d nactual %d",
3871 	    navail, nactual));
3872 
3873 	if ((ddi_status = ddi_intr_get_pri(intrp->htable[0],
3874 	    (uint_t *)&intrp->pri)) != DDI_SUCCESS) {
3875 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
3876 		    " ddi_intr_get_pri() failed: %d", ddi_status));
3877 		/* Free already allocated interrupts */
3878 		for (y = 0; y < nactual; y++) {
3879 			(void) ddi_intr_free(intrp->htable[y]);
3880 		}
3881 
3882 		kmem_free(intrp->htable, intrp->intr_size);
3883 		return (HXGE_ERROR | HXGE_DDI_FAILED);
3884 	}
3885 
3886 	nrequired = 0;
3887 	status = hxge_ldgv_init(hxgep, &nactual, &nrequired);
3888 	if (status != HXGE_OK) {
3889 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
3890 		    "hxge_add_intrs_adv_typ:hxge_ldgv_init "
3891 		    "failed: 0x%x", status));
3892 		/* Free already allocated interrupts */
3893 		for (y = 0; y < nactual; y++) {
3894 			(void) ddi_intr_free(intrp->htable[y]);
3895 		}
3896 
3897 		kmem_free(intrp->htable, intrp->intr_size);
3898 		return (status);
3899 	}
3900 
3901 	ldgp = hxgep->ldgvp->ldgp;
3902 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
3903 	    "After hxge_ldgv_init(): nreq %d nactual %d", nrequired, nactual));
3904 
3905 	if (nactual < nrequired)
3906 		loop = nactual;
3907 	else
3908 		loop = nrequired;
3909 
3910 	for (x = 0; x < loop; x++, ldgp++) {
3911 		ldgp->vector = (uint8_t)x;
3912 		arg1 = ldgp->ldvp;
3913 		arg2 = hxgep;
3914 		if (ldgp->nldvs == 1) {
3915 			inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler;
3916 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
3917 			    "hxge_add_intrs_adv_type: arg1 0x%x arg2 0x%x: "
3918 			    "1-1 int handler (entry %d)\n",
3919 			    arg1, arg2, x));
3920 		} else if (ldgp->nldvs > 1) {
3921 			inthandler = (uint_t *)ldgp->sys_intr_handler;
3922 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
3923 			    "hxge_add_intrs_adv_type: arg1 0x%x arg2 0x%x: "
3924 			    "nldevs %d int handler (entry %d)\n",
3925 			    arg1, arg2, ldgp->nldvs, x));
3926 		}
3927 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
3928 		    "==> hxge_add_intrs_adv_type: ddi_add_intr(inum) #%d "
3929 		    "htable 0x%llx", x, intrp->htable[x]));
3930 
3931 		if ((ddi_status = ddi_intr_add_handler(intrp->htable[x],
3932 		    (ddi_intr_handler_t *)inthandler, arg1, arg2)) !=
3933 		    DDI_SUCCESS) {
3934 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
3935 			    "==> hxge_add_intrs_adv_type: failed #%d "
3936 			    "status 0x%x", x, ddi_status));
3937 			for (y = 0; y < intrp->intr_added; y++) {
3938 				(void) ddi_intr_remove_handler(
3939 				    intrp->htable[y]);
3940 			}
3941 
3942 			/* Free already allocated intr */
3943 			for (y = 0; y < nactual; y++) {
3944 				(void) ddi_intr_free(intrp->htable[y]);
3945 			}
3946 			kmem_free(intrp->htable, intrp->intr_size);
3947 
3948 			(void) hxge_ldgv_uninit(hxgep);
3949 
3950 			return (HXGE_ERROR | HXGE_DDI_FAILED);
3951 		}
3952 
3953 		ldgp->htable_idx = x;
3954 		intrp->intr_added++;
3955 	}
3956 	intrp->msi_intx_cnt = nactual;
3957 
3958 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
3959 	    "Requested: %d, Allowed: %d msi_intx_cnt %d intr_added %d",
3960 	    navail, nactual, intrp->msi_intx_cnt, intrp->intr_added));
3961 
3962 	(void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap);
3963 	(void) hxge_intr_ldgv_init(hxgep);
3964 
3965 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs_adv_type"));
3966 
3967 	return (status);
3968 }
3969 
3970 /*ARGSUSED*/
3971 static hxge_status_t
3972 hxge_add_intrs_adv_type_fix(p_hxge_t hxgep, uint32_t int_type)
3973 {
3974 	dev_info_t	*dip = hxgep->dip;
3975 	p_hxge_ldg_t	ldgp;
3976 	p_hxge_intr_t	intrp;
3977 	uint_t		*inthandler;
3978 	void		*arg1, *arg2;
3979 	int		behavior;
3980 	int		nintrs, navail;
3981 	int		nactual, nrequired;
3982 	int		inum = 0;
3983 	int		x, y;
3984 	int		ddi_status = DDI_SUCCESS;
3985 	hxge_status_t	status = HXGE_OK;
3986 
3987 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv_type_fix"));
3988 	intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
3989 
3990 	ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs);
3991 	if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) {
3992 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
3993 		    "ddi_intr_get_nintrs() failed, status: 0x%x%, "
3994 		    "nintrs: %d", status, nintrs));
3995 		return (HXGE_ERROR | HXGE_DDI_FAILED);
3996 	}
3997 
3998 	ddi_status = ddi_intr_get_navail(dip, int_type, &navail);
3999 	if ((ddi_status != DDI_SUCCESS) || (navail == 0)) {
4000 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
4001 		    "ddi_intr_get_navail() failed, status: 0x%x%, "
4002 		    "nintrs: %d", ddi_status, navail));
4003 		return (HXGE_ERROR | HXGE_DDI_FAILED);
4004 	}
4005 
4006 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
4007 	    "ddi_intr_get_navail() returned: nintrs %d, naavail %d",
4008 	    nintrs, navail));
4009 
4010 	behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT :
4011 	    DDI_INTR_ALLOC_NORMAL);
4012 	intrp->intr_size = navail * sizeof (ddi_intr_handle_t);
4013 	intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP);
4014 	ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum,
4015 	    navail, &nactual, behavior);
4016 	if (ddi_status != DDI_SUCCESS || nactual == 0) {
4017 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
4018 		    " ddi_intr_alloc() failed: %d", ddi_status));
4019 		kmem_free(intrp->htable, intrp->intr_size);
4020 		return (HXGE_ERROR | HXGE_DDI_FAILED);
4021 	}
4022 
4023 	if ((ddi_status = ddi_intr_get_pri(intrp->htable[0],
4024 	    (uint_t *)&intrp->pri)) != DDI_SUCCESS) {
4025 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
4026 		    " ddi_intr_get_pri() failed: %d", ddi_status));
4027 		/* Free already allocated interrupts */
4028 		for (y = 0; y < nactual; y++) {
4029 			(void) ddi_intr_free(intrp->htable[y]);
4030 		}
4031 
4032 		kmem_free(intrp->htable, intrp->intr_size);
4033 		return (HXGE_ERROR | HXGE_DDI_FAILED);
4034 	}
4035 
4036 	nrequired = 0;
4037 	status = hxge_ldgv_init(hxgep, &nactual, &nrequired);
4038 	if (status != HXGE_OK) {
4039 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
4040 		    "hxge_add_intrs_adv_type_fix:hxge_ldgv_init "
4041 		    "failed: 0x%x", status));
4042 		/* Free already allocated interrupts */
4043 		for (y = 0; y < nactual; y++) {
4044 			(void) ddi_intr_free(intrp->htable[y]);
4045 		}
4046 
4047 		kmem_free(intrp->htable, intrp->intr_size);
4048 		return (status);
4049 	}
4050 
4051 	ldgp = hxgep->ldgvp->ldgp;
4052 	for (x = 0; x < nrequired; x++, ldgp++) {
4053 		ldgp->vector = (uint8_t)x;
4054 		arg1 = ldgp->ldvp;
4055 		arg2 = hxgep;
4056 		if (ldgp->nldvs == 1) {
4057 			inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler;
4058 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
4059 			    "hxge_add_intrs_adv_type_fix: "
4060 			    "1-1 int handler(%d) ldg %d ldv %d "
4061 			    "arg1 $%p arg2 $%p\n",
4062 			    x, ldgp->ldg, ldgp->ldvp->ldv, arg1, arg2));
4063 		} else if (ldgp->nldvs > 1) {
4064 			inthandler = (uint_t *)ldgp->sys_intr_handler;
4065 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
4066 			    "hxge_add_intrs_adv_type_fix: "
4067 			    "shared ldv %d int handler(%d) ldv %d ldg %d"
4068 			    "arg1 0x%016llx arg2 0x%016llx\n",
4069 			    x, ldgp->nldvs, ldgp->ldg, ldgp->ldvp->ldv,
4070 			    arg1, arg2));
4071 		}
4072 
4073 		if ((ddi_status = ddi_intr_add_handler(intrp->htable[x],
4074 		    (ddi_intr_handler_t *)inthandler, arg1, arg2)) !=
4075 		    DDI_SUCCESS) {
4076 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
4077 			    "==> hxge_add_intrs_adv_type_fix: failed #%d "
4078 			    "status 0x%x", x, ddi_status));
4079 			for (y = 0; y < intrp->intr_added; y++) {
4080 				(void) ddi_intr_remove_handler(
4081 				    intrp->htable[y]);
4082 			}
4083 			for (y = 0; y < nactual; y++) {
4084 				(void) ddi_intr_free(intrp->htable[y]);
4085 			}
4086 			/* Free already allocated intr */
4087 			kmem_free(intrp->htable, intrp->intr_size);
4088 
4089 			(void) hxge_ldgv_uninit(hxgep);
4090 
4091 			return (HXGE_ERROR | HXGE_DDI_FAILED);
4092 		}
4093 		intrp->intr_added++;
4094 	}
4095 
4096 	intrp->msi_intx_cnt = nactual;
4097 
4098 	(void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap);
4099 
4100 	status = hxge_intr_ldgv_init(hxgep);
4101 
4102 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs_adv_type_fix"));
4103 
4104 	return (status);
4105 }
4106 
4107 /*ARGSUSED*/
4108 static void
4109 hxge_remove_intrs(p_hxge_t hxgep)
4110 {
4111 	int		i, inum;
4112 	p_hxge_intr_t	intrp;
4113 
4114 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_remove_intrs"));
4115 	intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
4116 	if (!intrp->intr_registered) {
4117 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
4118 		    "<== hxge_remove_intrs: interrupts not registered"));
4119 		return;
4120 	}
4121 
4122 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_remove_intrs:advanced"));
4123 
4124 	if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
4125 		(void) ddi_intr_block_disable(intrp->htable,
4126 		    intrp->intr_added);
4127 	} else {
4128 		for (i = 0; i < intrp->intr_added; i++) {
4129 			(void) ddi_intr_disable(intrp->htable[i]);
4130 		}
4131 	}
4132 
4133 	for (inum = 0; inum < intrp->intr_added; inum++) {
4134 		if (intrp->htable[inum]) {
4135 			(void) ddi_intr_remove_handler(intrp->htable[inum]);
4136 		}
4137 	}
4138 
4139 	for (inum = 0; inum < intrp->msi_intx_cnt; inum++) {
4140 		if (intrp->htable[inum]) {
4141 			HXGE_DEBUG_MSG((hxgep, DDI_CTL,
4142 			    "hxge_remove_intrs: ddi_intr_free inum %d "
4143 			    "msi_intx_cnt %d intr_added %d",
4144 			    inum, intrp->msi_intx_cnt, intrp->intr_added));
4145 
4146 			(void) ddi_intr_free(intrp->htable[inum]);
4147 		}
4148 	}
4149 
4150 	kmem_free(intrp->htable, intrp->intr_size);
4151 	intrp->intr_registered = B_FALSE;
4152 	intrp->intr_enabled = B_FALSE;
4153 	intrp->msi_intx_cnt = 0;
4154 	intrp->intr_added = 0;
4155 
4156 	(void) hxge_ldgv_uninit(hxgep);
4157 
4158 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_remove_intrs"));
4159 }
4160 
4161 /*ARGSUSED*/
4162 static void
4163 hxge_intrs_enable(p_hxge_t hxgep)
4164 {
4165 	p_hxge_intr_t	intrp;
4166 	int		i;
4167 	int		status;
4168 
4169 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_enable"));
4170 
4171 	intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
4172 
4173 	if (!intrp->intr_registered) {
4174 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "<== hxge_intrs_enable: "
4175 		    "interrupts are not registered"));
4176 		return;
4177 	}
4178 
4179 	if (intrp->intr_enabled) {
4180 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
4181 		    "<== hxge_intrs_enable: already enabled"));
4182 		return;
4183 	}
4184 
4185 	if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
4186 		status = ddi_intr_block_enable(intrp->htable,
4187 		    intrp->intr_added);
4188 		HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_enable "
4189 		    "block enable - status 0x%x total inums #%d\n",
4190 		    status, intrp->intr_added));
4191 	} else {
4192 		for (i = 0; i < intrp->intr_added; i++) {
4193 			status = ddi_intr_enable(intrp->htable[i]);
4194 			HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_enable "
4195 			    "ddi_intr_enable:enable - status 0x%x "
4196 			    "total inums %d enable inum #%d\n",
4197 			    status, intrp->intr_added, i));
4198 			if (status == DDI_SUCCESS) {
4199 				intrp->intr_enabled = B_TRUE;
4200 			}
4201 		}
4202 	}
4203 
4204 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intrs_enable"));
4205 }
4206 
4207 /*ARGSUSED*/
4208 static void
4209 hxge_intrs_disable(p_hxge_t hxgep)
4210 {
4211 	p_hxge_intr_t	intrp;
4212 	int		i;
4213 
4214 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_disable"));
4215 
4216 	intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type;
4217 
4218 	if (!intrp->intr_registered) {
4219 		HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intrs_disable: "
4220 		    "interrupts are not registered"));
4221 		return;
4222 	}
4223 
4224 	if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
4225 		(void) ddi_intr_block_disable(intrp->htable,
4226 		    intrp->intr_added);
4227 	} else {
4228 		for (i = 0; i < intrp->intr_added; i++) {
4229 			(void) ddi_intr_disable(intrp->htable[i]);
4230 		}
4231 	}
4232 
4233 	intrp->intr_enabled = B_FALSE;
4234 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intrs_disable"));
4235 }
4236 
4237 static hxge_status_t
4238 hxge_mac_register(p_hxge_t hxgep)
4239 {
4240 	mac_register_t	*macp;
4241 	int		status;
4242 
4243 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_mac_register"));
4244 
4245 	if ((macp = mac_alloc(MAC_VERSION)) == NULL)
4246 		return (HXGE_ERROR);
4247 
4248 	macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
4249 	macp->m_driver = hxgep;
4250 	macp->m_dip = hxgep->dip;
4251 	macp->m_src_addr = hxgep->ouraddr.ether_addr_octet;
4252 	macp->m_callbacks = &hxge_m_callbacks;
4253 	macp->m_min_sdu = 0;
4254 	macp->m_max_sdu = hxgep->vmac.maxframesize - MTU_TO_FRAME_SIZE;
4255 	macp->m_margin = VLAN_TAGSZ;
4256 	macp->m_priv_props = hxge_priv_props;
4257 	macp->m_v12n = MAC_VIRT_LEVEL1;
4258 
4259 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
4260 	    "hxge_mac_register: ether addr is %x:%x:%x:%x:%x:%x",
4261 	    macp->m_src_addr[0],
4262 	    macp->m_src_addr[1],
4263 	    macp->m_src_addr[2],
4264 	    macp->m_src_addr[3],
4265 	    macp->m_src_addr[4],
4266 	    macp->m_src_addr[5]));
4267 
4268 	status = mac_register(macp, &hxgep->mach);
4269 	mac_free(macp);
4270 
4271 	if (status != 0) {
4272 		cmn_err(CE_WARN,
4273 		    "hxge_mac_register failed (status %d instance %d)",
4274 		    status, hxgep->instance);
4275 		return (HXGE_ERROR);
4276 	}
4277 
4278 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_mac_register success "
4279 	    "(instance %d)", hxgep->instance));
4280 
4281 	return (HXGE_OK);
4282 }
4283 
4284 static int
4285 hxge_init_common_dev(p_hxge_t hxgep)
4286 {
4287 	p_hxge_hw_list_t	hw_p;
4288 	dev_info_t		*p_dip;
4289 
4290 	HXGE_DEBUG_MSG((hxgep, MOD_CTL, "==> hxge_init_common_dev"));
4291 
4292 	p_dip = hxgep->p_dip;
4293 	MUTEX_ENTER(&hxge_common_lock);
4294 
4295 	/*
4296 	 * Loop through existing per Hydra hardware list.
4297 	 */
4298 	for (hw_p = hxge_hw_list; hw_p; hw_p = hw_p->next) {
4299 		HXGE_DEBUG_MSG((hxgep, MOD_CTL,
4300 		    "==> hxge_init_common_dev: hw_p $%p parent dip $%p",
4301 		    hw_p, p_dip));
4302 		if (hw_p->parent_devp == p_dip) {
4303 			hxgep->hxge_hw_p = hw_p;
4304 			hw_p->ndevs++;
4305 			hw_p->hxge_p = hxgep;
4306 			HXGE_DEBUG_MSG((hxgep, MOD_CTL,
4307 			    "==> hxge_init_common_device: "
4308 			    "hw_p $%p parent dip $%p ndevs %d (found)",
4309 			    hw_p, p_dip, hw_p->ndevs));
4310 			break;
4311 		}
4312 	}
4313 
4314 	if (hw_p == NULL) {
4315 		HXGE_DEBUG_MSG((hxgep, MOD_CTL,
4316 		    "==> hxge_init_common_dev: parent dip $%p (new)", p_dip));
4317 		hw_p = kmem_zalloc(sizeof (hxge_hw_list_t), KM_SLEEP);
4318 		hw_p->parent_devp = p_dip;
4319 		hw_p->magic = HXGE_MAGIC;
4320 		hxgep->hxge_hw_p = hw_p;
4321 		hw_p->ndevs++;
4322 		hw_p->hxge_p = hxgep;
4323 		hw_p->next = hxge_hw_list;
4324 
4325 		MUTEX_INIT(&hw_p->hxge_cfg_lock, NULL, MUTEX_DRIVER, NULL);
4326 		MUTEX_INIT(&hw_p->hxge_tcam_lock, NULL, MUTEX_DRIVER, NULL);
4327 		MUTEX_INIT(&hw_p->hxge_vlan_lock, NULL, MUTEX_DRIVER, NULL);
4328 
4329 		hxge_hw_list = hw_p;
4330 	}
4331 	MUTEX_EXIT(&hxge_common_lock);
4332 	HXGE_DEBUG_MSG((hxgep, MOD_CTL,
4333 	    "==> hxge_init_common_dev (hxge_hw_list) $%p", hxge_hw_list));
4334 	HXGE_DEBUG_MSG((hxgep, MOD_CTL, "<== hxge_init_common_dev"));
4335 
4336 	return (HXGE_OK);
4337 }
4338 
4339 static void
4340 hxge_uninit_common_dev(p_hxge_t hxgep)
4341 {
4342 	p_hxge_hw_list_t	hw_p, h_hw_p;
4343 	dev_info_t		*p_dip;
4344 
4345 	HXGE_DEBUG_MSG((hxgep, MOD_CTL, "==> hxge_uninit_common_dev"));
4346 	if (hxgep->hxge_hw_p == NULL) {
4347 		HXGE_DEBUG_MSG((hxgep, MOD_CTL,
4348 		    "<== hxge_uninit_common_dev (no common)"));
4349 		return;
4350 	}
4351 
4352 	MUTEX_ENTER(&hxge_common_lock);
4353 	h_hw_p = hxge_hw_list;
4354 	for (hw_p = hxge_hw_list; hw_p; hw_p = hw_p->next) {
4355 		p_dip = hw_p->parent_devp;
4356 		if (hxgep->hxge_hw_p == hw_p && p_dip == hxgep->p_dip &&
4357 		    hxgep->hxge_hw_p->magic == HXGE_MAGIC &&
4358 		    hw_p->magic == HXGE_MAGIC) {
4359 			HXGE_DEBUG_MSG((hxgep, MOD_CTL,
4360 			    "==> hxge_uninit_common_dev: "
4361 			    "hw_p $%p parent dip $%p ndevs %d (found)",
4362 			    hw_p, p_dip, hw_p->ndevs));
4363 
4364 			hxgep->hxge_hw_p = NULL;
4365 			if (hw_p->ndevs) {
4366 				hw_p->ndevs--;
4367 			}
4368 			hw_p->hxge_p = NULL;
4369 			if (!hw_p->ndevs) {
4370 				MUTEX_DESTROY(&hw_p->hxge_vlan_lock);
4371 				MUTEX_DESTROY(&hw_p->hxge_tcam_lock);
4372 				MUTEX_DESTROY(&hw_p->hxge_cfg_lock);
4373 				HXGE_DEBUG_MSG((hxgep, MOD_CTL,
4374 				    "==> hxge_uninit_common_dev: "
4375 				    "hw_p $%p parent dip $%p ndevs %d (last)",
4376 				    hw_p, p_dip, hw_p->ndevs));
4377 
4378 				if (hw_p == hxge_hw_list) {
4379 					HXGE_DEBUG_MSG((hxgep, MOD_CTL,
4380 					    "==> hxge_uninit_common_dev:"
4381 					    "remove head "
4382 					    "hw_p $%p parent dip $%p "
4383 					    "ndevs %d (head)",
4384 					    hw_p, p_dip, hw_p->ndevs));
4385 					hxge_hw_list = hw_p->next;
4386 				} else {
4387 					HXGE_DEBUG_MSG((hxgep, MOD_CTL,
4388 					    "==> hxge_uninit_common_dev:"
4389 					    "remove middle "
4390 					    "hw_p $%p parent dip $%p "
4391 					    "ndevs %d (middle)",
4392 					    hw_p, p_dip, hw_p->ndevs));
4393 					h_hw_p->next = hw_p->next;
4394 				}
4395 
4396 				KMEM_FREE(hw_p, sizeof (hxge_hw_list_t));
4397 			}
4398 			break;
4399 		} else {
4400 			h_hw_p = hw_p;
4401 		}
4402 	}
4403 
4404 	MUTEX_EXIT(&hxge_common_lock);
4405 	HXGE_DEBUG_MSG((hxgep, MOD_CTL,
4406 	    "==> hxge_uninit_common_dev (hxge_hw_list) $%p", hxge_hw_list));
4407 
4408 	HXGE_DEBUG_MSG((hxgep, MOD_CTL, "<= hxge_uninit_common_dev"));
4409 }
4410 
4411 #define	HXGE_MSIX_ENTRIES		32
4412 #define	HXGE_MSIX_WAIT_COUNT		10
4413 #define	HXGE_MSIX_PARITY_CHECK_COUNT	30
4414 
4415 static void
4416 hxge_link_poll(void *arg)
4417 {
4418 	p_hxge_t		hxgep = (p_hxge_t)arg;
4419 	hpi_handle_t		handle;
4420 	cip_link_stat_t		link_stat;
4421 	hxge_timeout		*to = &hxgep->timeout;
4422 
4423 	handle = HXGE_DEV_HPI_HANDLE(hxgep);
4424 	HXGE_REG_RD32(handle, CIP_LINK_STAT, &link_stat.value);
4425 
4426 	if (to->report_link_status ||
4427 	    (to->link_status != link_stat.bits.xpcs0_link_up)) {
4428 		to->link_status = link_stat.bits.xpcs0_link_up;
4429 		to->report_link_status = B_FALSE;
4430 
4431 		if (link_stat.bits.xpcs0_link_up) {
4432 			hxge_link_update(hxgep, LINK_STATE_UP);
4433 		} else {
4434 			hxge_link_update(hxgep, LINK_STATE_DOWN);
4435 		}
4436 	}
4437 
4438 	/* Restart the link status timer to check the link status */
4439 	MUTEX_ENTER(&to->lock);
4440 	to->id = timeout(hxge_link_poll, arg, to->ticks);
4441 	MUTEX_EXIT(&to->lock);
4442 }
4443 
4444 static void
4445 hxge_link_update(p_hxge_t hxgep, link_state_t state)
4446 {
4447 	p_hxge_stats_t		statsp = (p_hxge_stats_t)hxgep->statsp;
4448 
4449 	mac_link_update(hxgep->mach, state);
4450 	if (state == LINK_STATE_UP) {
4451 		statsp->mac_stats.link_speed = 10000;
4452 		statsp->mac_stats.link_duplex = 2;
4453 		statsp->mac_stats.link_up = 1;
4454 	} else {
4455 		statsp->mac_stats.link_speed = 0;
4456 		statsp->mac_stats.link_duplex = 0;
4457 		statsp->mac_stats.link_up = 0;
4458 	}
4459 }
4460 
4461 static void
4462 hxge_msix_init(p_hxge_t hxgep)
4463 {
4464 	uint32_t 		data0;
4465 	uint32_t 		data1;
4466 	uint32_t 		data2;
4467 	int			i;
4468 	uint32_t		msix_entry0;
4469 	uint32_t		msix_entry1;
4470 	uint32_t		msix_entry2;
4471 	uint32_t		msix_entry3;
4472 
4473 	/* Change to use MSIx bar instead of indirect access */
4474 	for (i = 0; i < HXGE_MSIX_ENTRIES; i++) {
4475 		data0 = 0xffffffff - i;
4476 		data1 = 0xffffffff - i - 1;
4477 		data2 = 0xffffffff - i - 2;
4478 
4479 		HXGE_REG_WR32(hxgep->hpi_msi_handle, i * 16, data0);
4480 		HXGE_REG_WR32(hxgep->hpi_msi_handle, i * 16 + 4, data1);
4481 		HXGE_REG_WR32(hxgep->hpi_msi_handle, i * 16 + 8, data2);
4482 		HXGE_REG_WR32(hxgep->hpi_msi_handle, i * 16 + 12, 0);
4483 	}
4484 
4485 	/* Initialize ram data out buffer. */
4486 	for (i = 0; i < HXGE_MSIX_ENTRIES; i++) {
4487 		HXGE_REG_RD32(hxgep->hpi_msi_handle, i * 16, &msix_entry0);
4488 		HXGE_REG_RD32(hxgep->hpi_msi_handle, i * 16 + 4, &msix_entry1);
4489 		HXGE_REG_RD32(hxgep->hpi_msi_handle, i * 16 + 8, &msix_entry2);
4490 		HXGE_REG_RD32(hxgep->hpi_msi_handle, i * 16 + 12, &msix_entry3);
4491 	}
4492 }
4493 
4494 /*
4495  * The following function is to support
4496  * PSARC/2007/453 MSI-X interrupt limit override.
4497  */
4498 static int
4499 hxge_create_msi_property(p_hxge_t hxgep)
4500 {
4501 	int	nmsi;
4502 	extern	int ncpus;
4503 
4504 	HXGE_DEBUG_MSG((hxgep, MOD_CTL, "==>hxge_create_msi_property"));
4505 
4506 	(void) ddi_prop_create(DDI_DEV_T_NONE, hxgep->dip,
4507 	    DDI_PROP_CANSLEEP, "#msix-request", NULL, 0);
4508 	/*
4509 	 * The maximum MSI-X requested will be 8.
4510 	 * If the # of CPUs is less than 8, we will reqeust
4511 	 * # MSI-X based on the # of CPUs.
4512 	 */
4513 	if (ncpus >= HXGE_MSIX_REQUEST_10G) {
4514 		nmsi = HXGE_MSIX_REQUEST_10G;
4515 	} else {
4516 		nmsi = ncpus;
4517 	}
4518 
4519 	HXGE_DEBUG_MSG((hxgep, MOD_CTL,
4520 	    "==>hxge_create_msi_property(10G): exists 0x%x (nmsi %d)",
4521 	    ddi_prop_exists(DDI_DEV_T_NONE, hxgep->dip,
4522 	    DDI_PROP_CANSLEEP, "#msix-request"), nmsi));
4523 
4524 	HXGE_DEBUG_MSG((hxgep, MOD_CTL, "<==hxge_create_msi_property"));
4525 	return (nmsi);
4526 }
4527