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