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