xref: /titanic_51/usr/src/uts/common/io/xge/drv/xgell.c (revision 00687e57f8c568d4f8fb446b6530a2942842292f)
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 /*
23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  *  Copyright (c) 2002-2005 Neterion, Inc.
31  *  All right Reserved.
32  *
33  *  FileName :    xgell.c
34  *
35  *  Description:  Xge Link Layer data path implementation
36  *
37  */
38 
39 #include "xgell.h"
40 
41 #include <netinet/ip.h>
42 #include <netinet/tcp.h>
43 #include <netinet/udp.h>
44 
45 #define	XGELL_MAX_FRAME_SIZE(hldev)	((hldev)->config.mtu +	\
46     sizeof (struct ether_vlan_header))
47 
48 #define	HEADROOM		2	/* for DIX-only packets */
49 
50 #ifdef XGELL_L3_ALIGNED
51 void header_free_func(void *arg) { }
52 frtn_t header_frtn = {header_free_func, NULL};
53 #endif
54 
55 /* DMA attributes used for Tx side */
56 static struct ddi_dma_attr tx_dma_attr = {
57 	DMA_ATTR_V0,			/* dma_attr_version */
58 	0x0ULL,				/* dma_attr_addr_lo */
59 	0xFFFFFFFFFFFFFFFFULL,		/* dma_attr_addr_hi */
60 	0xFFFFFFFFULL,			/* dma_attr_count_max */
61 	0x1ULL,				/* dma_attr_align */
62 	0xFFF,				/* dma_attr_burstsizes */
63 	1,				/* dma_attr_minxfer */
64 	0xFFFFFFFFULL,			/* dma_attr_maxxfer */
65 	0xFFFFFFFFFFFFFFFFULL,		/* dma_attr_seg */
66 	18,				/* dma_attr_sgllen */
67 	1,				/* dma_attr_granular */
68 	0				/* dma_attr_flags */
69 };
70 
71 /* Aligned DMA attributes used for Tx side */
72 struct ddi_dma_attr tx_dma_attr_align = {
73 	DMA_ATTR_V0,			/* dma_attr_version */
74 	0x0ULL,				/* dma_attr_addr_lo */
75 	0xFFFFFFFFFFFFFFFFULL,		/* dma_attr_addr_hi */
76 	0xFFFFFFFFULL,			/* dma_attr_count_max */
77 	4096,				/* dma_attr_align */
78 	0xFFF,				/* dma_attr_burstsizes */
79 	1,				/* dma_attr_minxfer */
80 	0xFFFFFFFFULL,			/* dma_attr_maxxfer */
81 	0xFFFFFFFFFFFFFFFFULL,		/* dma_attr_seg */
82 	4,				/* dma_attr_sgllen */
83 	1,				/* dma_attr_granular */
84 	0				/* dma_attr_flags */
85 };
86 
87 /*
88  * DMA attributes used when using ddi_dma_mem_alloc to
89  * allocat HAL descriptors and Rx buffers during replenish
90  */
91 static struct ddi_dma_attr hal_dma_attr = {
92 	DMA_ATTR_V0,			/* dma_attr_version */
93 	0x0ULL,				/* dma_attr_addr_lo */
94 	0xFFFFFFFFFFFFFFFFULL,		/* dma_attr_addr_hi */
95 	0xFFFFFFFFULL,			/* dma_attr_count_max */
96 	0x1ULL,				/* dma_attr_align */
97 	0xFFF,				/* dma_attr_burstsizes */
98 	1,				/* dma_attr_minxfer */
99 	0xFFFFFFFFULL,			/* dma_attr_maxxfer */
100 	0xFFFFFFFFFFFFFFFFULL,		/* dma_attr_seg */
101 	1,				/* dma_attr_sgllen */
102 	1,				/* dma_attr_granular */
103 	0				/* dma_attr_flags */
104 };
105 
106 /*
107  * Aligned DMA attributes used when using ddi_dma_mem_alloc to
108  * allocat HAL descriptors and Rx buffers during replenish
109  */
110 struct ddi_dma_attr hal_dma_attr_aligned = {
111 	DMA_ATTR_V0,			/* dma_attr_version */
112 	0x0ULL,				/* dma_attr_addr_lo */
113 	0xFFFFFFFFFFFFFFFFULL,		/* dma_attr_addr_hi */
114 	0xFFFFFFFFULL,			/* dma_attr_count_max */
115 	4096,				/* dma_attr_align */
116 	0xFFF,				/* dma_attr_burstsizes */
117 	1,				/* dma_attr_minxfer */
118 	0xFFFFFFFFULL,			/* dma_attr_maxxfer */
119 	0xFFFFFFFFFFFFFFFFULL,		/* dma_attr_seg */
120 	1,				/* dma_attr_sgllen */
121 	1,				/* dma_attr_granular */
122 	0				/* dma_attr_flags */
123 };
124 
125 struct ddi_dma_attr *p_hal_dma_attr = &hal_dma_attr;
126 struct ddi_dma_attr *p_hal_dma_attr_aligned = &hal_dma_attr_aligned;
127 
128 static int		xgell_m_stat(void *, uint_t, uint64_t *);
129 static int		xgell_m_start(void *);
130 static void		xgell_m_stop(void *);
131 static int		xgell_m_promisc(void *, boolean_t);
132 static int		xgell_m_multicst(void *, boolean_t, const uint8_t *);
133 static int		xgell_m_unicst(void *, const uint8_t *);
134 static void		xgell_m_ioctl(void *, queue_t *, mblk_t *);
135 static mblk_t 		*xgell_m_tx(void *, mblk_t *);
136 static boolean_t	xgell_m_getcapab(void *, mac_capab_t, void *);
137 
138 #define	XGELL_M_CALLBACK_FLAGS	(MC_IOCTL | MC_GETCAPAB)
139 
140 static mac_callbacks_t xgell_m_callbacks = {
141 	XGELL_M_CALLBACK_FLAGS,
142 	xgell_m_stat,
143 	xgell_m_start,
144 	xgell_m_stop,
145 	xgell_m_promisc,
146 	xgell_m_multicst,
147 	xgell_m_unicst,
148 	xgell_m_tx,
149 	NULL,
150 	xgell_m_ioctl,
151 	xgell_m_getcapab
152 };
153 
154 /*
155  * xge_device_poll
156  *
157  * Cyclic should call me every 1s. xge_callback_event_queued should call me
158  * when HAL hope event was rescheduled.
159  */
160 /*ARGSUSED*/
161 void
162 xge_device_poll(void *data)
163 {
164 	xgelldev_t *lldev = xge_hal_device_private(data);
165 
166 	mutex_enter(&lldev->genlock);
167 	if (lldev->is_initialized) {
168 		xge_hal_device_poll(data);
169 		lldev->timeout_id = timeout(xge_device_poll, data,
170 		    XGE_DEV_POLL_TICKS);
171 	} else if (lldev->in_reset == 1) {
172 		lldev->timeout_id = timeout(xge_device_poll, data,
173 		    XGE_DEV_POLL_TICKS);
174 	} else {
175 		lldev->timeout_id = 0;
176 	}
177 	mutex_exit(&lldev->genlock);
178 }
179 
180 /*
181  * xge_device_poll_now
182  *
183  * Will call xge_device_poll() immediately
184  */
185 void
186 xge_device_poll_now(void *data)
187 {
188 	xgelldev_t *lldev = xge_hal_device_private(data);
189 
190 	mutex_enter(&lldev->genlock);
191 	if (lldev->is_initialized) {
192 		xge_hal_device_poll(data);
193 	}
194 	mutex_exit(&lldev->genlock);
195 }
196 
197 /*
198  * xgell_callback_link_up
199  *
200  * This function called by HAL to notify HW link up state change.
201  */
202 void
203 xgell_callback_link_up(void *userdata)
204 {
205 	xgelldev_t *lldev = (xgelldev_t *)userdata;
206 
207 	mac_link_update(lldev->mh, LINK_STATE_UP);
208 	/* Link states should be reported to user whenever it changes */
209 	cmn_err(CE_NOTE, "!%s%d: Link is up [10 Gbps Full Duplex]",
210 	    XGELL_IFNAME, lldev->instance);
211 }
212 
213 /*
214  * xgell_callback_link_down
215  *
216  * This function called by HAL to notify HW link down state change.
217  */
218 void
219 xgell_callback_link_down(void *userdata)
220 {
221 	xgelldev_t *lldev = (xgelldev_t *)userdata;
222 
223 	mac_link_update(lldev->mh, LINK_STATE_DOWN);
224 	/* Link states should be reported to user whenever it changes */
225 	cmn_err(CE_NOTE, "!%s%d: Link is down", XGELL_IFNAME,
226 	    lldev->instance);
227 }
228 
229 /*
230  * xgell_rx_buffer_replenish_all
231  *
232  * To replenish all freed dtr(s) with buffers in free pool. It's called by
233  * xgell_rx_buffer_recycle() or xgell_rx_1b_compl().
234  * Must be called with pool_lock held.
235  */
236 static void
237 xgell_rx_buffer_replenish_all(xgelldev_t *lldev)
238 {
239 	xge_hal_dtr_h dtr;
240 	xgell_rx_buffer_t *rx_buffer;
241 	xgell_rxd_priv_t *rxd_priv;
242 
243 	xge_assert(mutex_owned(&lldev->bf_pool.pool_lock));
244 
245 	while ((lldev->bf_pool.free > 0) &&
246 	    (xge_hal_ring_dtr_reserve(lldev->ring_main.channelh, &dtr) ==
247 	    XGE_HAL_OK)) {
248 		rx_buffer = lldev->bf_pool.head;
249 		lldev->bf_pool.head = rx_buffer->next;
250 		lldev->bf_pool.free--;
251 
252 		xge_assert(rx_buffer);
253 		xge_assert(rx_buffer->dma_addr);
254 
255 		rxd_priv = (xgell_rxd_priv_t *)
256 		    xge_hal_ring_dtr_private(lldev->ring_main.channelh, dtr);
257 		xge_hal_ring_dtr_1b_set(dtr, rx_buffer->dma_addr,
258 		    lldev->bf_pool.size);
259 
260 		rxd_priv->rx_buffer = rx_buffer;
261 		xge_hal_ring_dtr_post(lldev->ring_main.channelh, dtr);
262 	}
263 }
264 
265 /*
266  * xgell_rx_buffer_release
267  *
268  * The only thing done here is to put the buffer back to the pool.
269  * Calling this function need be protected by mutex, bf_pool.pool_lock.
270  */
271 static void
272 xgell_rx_buffer_release(xgell_rx_buffer_t *rx_buffer)
273 {
274 	xgelldev_t *lldev = rx_buffer->lldev;
275 
276 	xge_assert(mutex_owned(&lldev->bf_pool.pool_lock));
277 
278 	/* Put the buffer back to pool */
279 	rx_buffer->next = lldev->bf_pool.head;
280 	lldev->bf_pool.head = rx_buffer;
281 
282 	lldev->bf_pool.free++;
283 }
284 
285 /*
286  * xgell_rx_buffer_recycle
287  *
288  * Called by desballoc() to "free" the resource.
289  * We will try to replenish all descripters.
290  */
291 static void
292 xgell_rx_buffer_recycle(char *arg)
293 {
294 	xgell_rx_buffer_t *rx_buffer = (xgell_rx_buffer_t *)arg;
295 	xgelldev_t *lldev = rx_buffer->lldev;
296 
297 	mutex_enter(&lldev->bf_pool.pool_lock);
298 
299 	xgell_rx_buffer_release(rx_buffer);
300 	lldev->bf_pool.post--;
301 
302 	/*
303 	 * Before finding a good way to set this hiwat, just always call to
304 	 * replenish_all. *TODO*
305 	 */
306 	if (lldev->is_initialized != 0) {
307 		xgell_rx_buffer_replenish_all(lldev);
308 	}
309 
310 	mutex_exit(&lldev->bf_pool.pool_lock);
311 }
312 
313 /*
314  * xgell_rx_buffer_alloc
315  *
316  * Allocate one rx buffer and return with the pointer to the buffer.
317  * Return NULL if failed.
318  */
319 static xgell_rx_buffer_t *
320 xgell_rx_buffer_alloc(xgelldev_t *lldev)
321 {
322 	xge_hal_device_t *hldev;
323 	void *vaddr;
324 	ddi_dma_handle_t dma_handle;
325 	ddi_acc_handle_t dma_acch;
326 	dma_addr_t dma_addr;
327 	uint_t ncookies;
328 	ddi_dma_cookie_t dma_cookie;
329 	size_t real_size;
330 	extern ddi_device_acc_attr_t *p_xge_dev_attr;
331 	xgell_rx_buffer_t *rx_buffer;
332 
333 	hldev = (xge_hal_device_t *)lldev->devh;
334 
335 	if (ddi_dma_alloc_handle(hldev->pdev, p_hal_dma_attr, DDI_DMA_SLEEP,
336 	    0, &dma_handle) != DDI_SUCCESS) {
337 		xge_debug_ll(XGE_ERR, "%s%d: can not allocate DMA handle",
338 		    XGELL_IFNAME, lldev->instance);
339 		goto handle_failed;
340 	}
341 
342 	/* reserve some space at the end of the buffer for recycling */
343 	if (ddi_dma_mem_alloc(dma_handle, HEADROOM + lldev->bf_pool.size +
344 	    sizeof (xgell_rx_buffer_t), p_xge_dev_attr, DDI_DMA_STREAMING,
345 	    DDI_DMA_SLEEP, 0, (caddr_t *)&vaddr, &real_size, &dma_acch) !=
346 	    DDI_SUCCESS) {
347 		xge_debug_ll(XGE_ERR, "%s%d: can not allocate DMA-able memory",
348 		    XGELL_IFNAME, lldev->instance);
349 		goto mem_failed;
350 	}
351 
352 	if (HEADROOM + lldev->bf_pool.size + sizeof (xgell_rx_buffer_t) >
353 	    real_size) {
354 		xge_debug_ll(XGE_ERR, "%s%d: can not allocate DMA-able memory",
355 		    XGELL_IFNAME, lldev->instance);
356 		goto bind_failed;
357 	}
358 
359 	if (ddi_dma_addr_bind_handle(dma_handle, NULL, (char *)vaddr + HEADROOM,
360 	    lldev->bf_pool.size, DDI_DMA_READ | DDI_DMA_STREAMING,
361 	    DDI_DMA_SLEEP, 0, &dma_cookie, &ncookies) != DDI_SUCCESS) {
362 		xge_debug_ll(XGE_ERR, "%s%d: out of mapping for mblk",
363 		    XGELL_IFNAME, lldev->instance);
364 		goto bind_failed;
365 	}
366 
367 	if (ncookies != 1 || dma_cookie.dmac_size < lldev->bf_pool.size) {
368 		xge_debug_ll(XGE_ERR, "%s%d: can not handle partial DMA",
369 		    XGELL_IFNAME, lldev->instance);
370 		goto check_failed;
371 	}
372 
373 	dma_addr = dma_cookie.dmac_laddress;
374 
375 	rx_buffer = (xgell_rx_buffer_t *)((char *)vaddr + real_size -
376 	    sizeof (xgell_rx_buffer_t));
377 	rx_buffer->next = NULL;
378 	rx_buffer->vaddr = vaddr;
379 	rx_buffer->dma_addr = dma_addr;
380 	rx_buffer->dma_handle = dma_handle;
381 	rx_buffer->dma_acch = dma_acch;
382 	rx_buffer->lldev = lldev;
383 	rx_buffer->frtn.free_func = xgell_rx_buffer_recycle;
384 	rx_buffer->frtn.free_arg = (void *)rx_buffer;
385 
386 	return (rx_buffer);
387 
388 check_failed:
389 	(void) ddi_dma_unbind_handle(dma_handle);
390 bind_failed:
391 	XGE_OS_MEMORY_CHECK_FREE(vaddr, 0);
392 	ddi_dma_mem_free(&dma_acch);
393 mem_failed:
394 	ddi_dma_free_handle(&dma_handle);
395 handle_failed:
396 
397 	return (NULL);
398 }
399 
400 /*
401  * xgell_rx_destroy_buffer_pool
402  *
403  * Destroy buffer pool. If there is still any buffer hold by upper layer,
404  * recorded by bf_pool.post, return DDI_FAILURE to reject to be unloaded.
405  */
406 static int
407 xgell_rx_destroy_buffer_pool(xgelldev_t *lldev)
408 {
409 	xgell_rx_buffer_t *rx_buffer;
410 	ddi_dma_handle_t  dma_handle;
411 	ddi_acc_handle_t  dma_acch;
412 	int i;
413 
414 	/*
415 	 * If there is any posted buffer, the driver should reject to be
416 	 * detached. Need notice upper layer to release them.
417 	 */
418 	if (lldev->bf_pool.post != 0) {
419 		xge_debug_ll(XGE_ERR,
420 		    "%s%d has some buffers not be recycled, try later!",
421 		    XGELL_IFNAME, lldev->instance);
422 		return (DDI_FAILURE);
423 	}
424 
425 	/*
426 	 * Relase buffers one by one.
427 	 */
428 	for (i = lldev->bf_pool.total; i > 0; i--) {
429 		rx_buffer = lldev->bf_pool.head;
430 		xge_assert(rx_buffer != NULL);
431 
432 		lldev->bf_pool.head = rx_buffer->next;
433 
434 		dma_handle = rx_buffer->dma_handle;
435 		dma_acch = rx_buffer->dma_acch;
436 
437 		if (ddi_dma_unbind_handle(dma_handle) != DDI_SUCCESS) {
438 			xge_debug_ll(XGE_ERR, "failed to unbind DMA handle!");
439 			lldev->bf_pool.head = rx_buffer;
440 			return (DDI_FAILURE);
441 		}
442 		ddi_dma_mem_free(&dma_acch);
443 		ddi_dma_free_handle(&dma_handle);
444 
445 		lldev->bf_pool.total--;
446 		lldev->bf_pool.free--;
447 	}
448 
449 	mutex_destroy(&lldev->bf_pool.pool_lock);
450 	return (DDI_SUCCESS);
451 }
452 
453 /*
454  * xgell_rx_create_buffer_pool
455  *
456  * Initialize RX buffer pool for all RX rings. Refer to rx_buffer_pool_t.
457  */
458 static int
459 xgell_rx_create_buffer_pool(xgelldev_t *lldev)
460 {
461 	xge_hal_device_t *hldev;
462 	xgell_rx_buffer_t *rx_buffer;
463 	int i;
464 
465 	hldev = (xge_hal_device_t *)lldev->devh;
466 
467 	lldev->bf_pool.total = 0;
468 	lldev->bf_pool.size = XGELL_MAX_FRAME_SIZE(hldev);
469 	lldev->bf_pool.head = NULL;
470 	lldev->bf_pool.free = 0;
471 	lldev->bf_pool.post = 0;
472 	lldev->bf_pool.post_hiwat = lldev->config.rx_buffer_post_hiwat;
473 
474 	mutex_init(&lldev->bf_pool.pool_lock, NULL, MUTEX_DRIVER,
475 	    hldev->irqh);
476 
477 	/*
478 	 * Allocate buffers one by one. If failed, destroy whole pool by
479 	 * call to xgell_rx_destroy_buffer_pool().
480 	 */
481 	for (i = 0; i < lldev->config.rx_buffer_total; i++) {
482 		if ((rx_buffer = xgell_rx_buffer_alloc(lldev)) == NULL) {
483 			(void) xgell_rx_destroy_buffer_pool(lldev);
484 			return (DDI_FAILURE);
485 		}
486 
487 		rx_buffer->next = lldev->bf_pool.head;
488 		lldev->bf_pool.head = rx_buffer;
489 
490 		lldev->bf_pool.total++;
491 		lldev->bf_pool.free++;
492 	}
493 
494 	return (DDI_SUCCESS);
495 }
496 
497 /*
498  * xgell_rx_dtr_replenish
499  *
500  * Replenish descriptor with rx_buffer in RX buffer pool.
501  * The dtr should be post right away.
502  */
503 xge_hal_status_e
504 xgell_rx_dtr_replenish(xge_hal_channel_h channelh, xge_hal_dtr_h dtr, int index,
505     void *userdata, xge_hal_channel_reopen_e reopen)
506 {
507 	xgell_ring_t *ring = userdata;
508 	xgelldev_t *lldev = ring->lldev;
509 	xgell_rx_buffer_t *rx_buffer;
510 	xgell_rxd_priv_t *rxd_priv;
511 
512 	if (lldev->bf_pool.head == NULL) {
513 		xge_debug_ll(XGE_ERR, "no more available rx DMA buffer!");
514 		return (XGE_HAL_FAIL);
515 	}
516 	rx_buffer = lldev->bf_pool.head;
517 	lldev->bf_pool.head = rx_buffer->next;
518 	lldev->bf_pool.free--;
519 
520 	xge_assert(rx_buffer);
521 	xge_assert(rx_buffer->dma_addr);
522 
523 	rxd_priv = (xgell_rxd_priv_t *)
524 	    xge_hal_ring_dtr_private(lldev->ring_main.channelh, dtr);
525 	xge_hal_ring_dtr_1b_set(dtr, rx_buffer->dma_addr, lldev->bf_pool.size);
526 
527 	rxd_priv->rx_buffer = rx_buffer;
528 
529 	return (XGE_HAL_OK);
530 }
531 
532 /*
533  * xgell_get_ip_offset
534  *
535  * Calculate the offset to IP header.
536  */
537 static inline int
538 xgell_get_ip_offset(xge_hal_dtr_info_t *ext_info)
539 {
540 	int ip_off;
541 
542 	/* get IP-header offset */
543 	switch (ext_info->frame) {
544 	case XGE_HAL_FRAME_TYPE_DIX:
545 		ip_off = XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE;
546 		break;
547 	case XGE_HAL_FRAME_TYPE_IPX:
548 		ip_off = (XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE +
549 		    XGE_HAL_HEADER_802_2_SIZE +
550 		    XGE_HAL_HEADER_SNAP_SIZE);
551 		break;
552 	case XGE_HAL_FRAME_TYPE_LLC:
553 		ip_off = (XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE +
554 		    XGE_HAL_HEADER_802_2_SIZE);
555 		break;
556 	case XGE_HAL_FRAME_TYPE_SNAP:
557 		ip_off = (XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE +
558 		    XGE_HAL_HEADER_SNAP_SIZE);
559 		break;
560 	default:
561 		ip_off = 0;
562 		break;
563 	}
564 
565 	if ((ext_info->proto & XGE_HAL_FRAME_PROTO_IPV4 ||
566 	    ext_info->proto & XGE_HAL_FRAME_PROTO_IPV6) &&
567 	    (ext_info->proto & XGE_HAL_FRAME_PROTO_VLAN_TAGGED)) {
568 		ip_off += XGE_HAL_HEADER_VLAN_SIZE;
569 	}
570 
571 	return (ip_off);
572 }
573 
574 /*
575  * xgell_rx_hcksum_assoc
576  *
577  * Judge the packet type and then call to hcksum_assoc() to associate
578  * h/w checksum information.
579  */
580 static inline void
581 xgell_rx_hcksum_assoc(mblk_t *mp, char *vaddr, int pkt_length,
582     xge_hal_dtr_info_t *ext_info)
583 {
584 	int cksum_flags = 0;
585 
586 	if (!(ext_info->proto & XGE_HAL_FRAME_PROTO_IP_FRAGMENTED)) {
587 		if (ext_info->proto & XGE_HAL_FRAME_PROTO_TCP_OR_UDP) {
588 			if (ext_info->l3_cksum == XGE_HAL_L3_CKSUM_OK) {
589 				cksum_flags |= HCK_IPV4_HDRCKSUM;
590 			}
591 			if (ext_info->l4_cksum == XGE_HAL_L4_CKSUM_OK) {
592 				cksum_flags |= HCK_FULLCKSUM_OK;
593 			}
594 			if (cksum_flags) {
595 				cksum_flags |= HCK_FULLCKSUM;
596 				(void) hcksum_assoc(mp, NULL, NULL, 0,
597 				    0, 0, 0, cksum_flags, 0);
598 			}
599 		}
600 	} else if (ext_info->proto &
601 	    (XGE_HAL_FRAME_PROTO_IPV4 | XGE_HAL_FRAME_PROTO_IPV6)) {
602 		/*
603 		 * Just pass the partial cksum up to IP.
604 		 */
605 		int ip_off = xgell_get_ip_offset(ext_info);
606 		int start, end = pkt_length - ip_off;
607 
608 		if (ext_info->proto & XGE_HAL_FRAME_PROTO_IPV4) {
609 			struct ip *ip =
610 			    (struct ip *)(vaddr + ip_off);
611 			start = ip->ip_hl * 4 + ip_off;
612 		} else {
613 			start = ip_off + 40;
614 		}
615 		cksum_flags |= HCK_PARTIALCKSUM;
616 		(void) hcksum_assoc(mp, NULL, NULL, start, 0,
617 		    end, ntohs(ext_info->l4_cksum), cksum_flags,
618 		    0);
619 	}
620 }
621 
622 /*
623  * xgell_rx_1b_msg_alloc
624  *
625  * Allocate message header for data buffer, and decide if copy the packet to
626  * new data buffer to release big rx_buffer to save memory.
627  *
628  * If the pkt_length <= XGELL_RX_DMA_LOWAT, call allocb() to allocate
629  * new message and copy the payload in.
630  */
631 static mblk_t *
632 xgell_rx_1b_msg_alloc(xgelldev_t *lldev, xgell_rx_buffer_t *rx_buffer,
633     int pkt_length, xge_hal_dtr_info_t *ext_info, boolean_t *copyit)
634 {
635 	mblk_t *mp;
636 	mblk_t *nmp = NULL;
637 	char *vaddr;
638 	int hdr_length = 0;
639 
640 #ifdef XGELL_L3_ALIGNED
641 	boolean_t doalign = B_TRUE;
642 	struct ip *ip;
643 	struct tcphdr *tcp;
644 	int tcp_off;
645 	int mp_align_len;
646 	int ip_off;
647 #endif
648 
649 	vaddr = (char *)rx_buffer->vaddr + HEADROOM;
650 #ifdef XGELL_L3_ALIGNED
651 	ip_off = xgell_get_ip_offset(ext_info);
652 
653 	/* Check ip_off with HEADROOM */
654 	if ((ip_off & 3) == HEADROOM) {
655 		doalign = B_FALSE;
656 	}
657 
658 	/*
659 	 * Doalign? Check for types of packets.
660 	 */
661 	/* Is IPv4 or IPv6? */
662 	if (doalign && !(ext_info->proto & XGE_HAL_FRAME_PROTO_IPV4 ||
663 	    ext_info->proto & XGE_HAL_FRAME_PROTO_IPV6)) {
664 		doalign = B_FALSE;
665 	}
666 
667 	/* Is TCP? */
668 	if (doalign &&
669 	    ((ip = (struct ip *)(vaddr + ip_off))->ip_p == IPPROTO_TCP)) {
670 		tcp_off = ip->ip_hl * 4 + ip_off;
671 		tcp = (struct tcphdr *)(vaddr + tcp_off);
672 		hdr_length = tcp_off + tcp->th_off * 4;
673 		if (pkt_length < (XGE_HAL_TCPIP_HEADER_MAX_SIZE +
674 		    XGE_HAL_MAC_HEADER_MAX_SIZE)) {
675 			hdr_length = pkt_length;
676 		}
677 	} else {
678 		doalign = B_FALSE;
679 	}
680 #endif
681 
682 	/*
683 	 * Copy packet into new allocated message buffer, if pkt_length
684 	 * is less than XGELL_RX_DMA_LOWAT
685 	 */
686 	if (*copyit || pkt_length <= lldev->config.rx_dma_lowat) {
687 		/* Keep room for alignment */
688 		if ((mp = allocb(pkt_length + HEADROOM + 4, 0)) == NULL) {
689 			return (NULL);
690 		}
691 #ifdef XGELL_L3_ALIGNED
692 		if (doalign) {
693 			mp_align_len =
694 			    (4 - ((uint64_t)(mp->b_rptr + ip_off) & 3));
695 			mp->b_rptr += mp_align_len;
696 		}
697 #endif
698 		bcopy(vaddr, mp->b_rptr, pkt_length);
699 		mp->b_wptr = mp->b_rptr + pkt_length;
700 		*copyit = B_TRUE;
701 		return (mp);
702 	}
703 
704 	/*
705 	 * Just allocate mblk for current data buffer
706 	 */
707 	if ((nmp = (mblk_t *)desballoc((unsigned char *)vaddr, pkt_length, 0,
708 	    &rx_buffer->frtn)) == NULL) {
709 		/* Drop it */
710 		return (NULL);
711 	}
712 
713 	/*
714 	 * Adjust the b_rptr/b_wptr in the mblk_t structure to point to
715 	 * payload.
716 	 */
717 	nmp->b_rptr += hdr_length;
718 	nmp->b_wptr += pkt_length;
719 
720 #ifdef XGELL_L3_ALIGNED
721 	if (doalign) {
722 		if ((mp = esballoc(rx_buffer->header, hdr_length + 4, 0,
723 		    &header_frtn)) == NULL) {
724 			/* can not align! */
725 			mp = nmp;
726 			mp->b_rptr = (u8 *)vaddr;
727 			mp->b_wptr = mp->b_rptr + pkt_length;
728 			mp->b_next = NULL;
729 			mp->b_cont = NULL;
730 		} else {
731 			/* align packet's ip-header offset */
732 			mp_align_len =
733 			    (4 - ((uint64_t)(mp->b_rptr + ip_off) & 3));
734 			mp->b_rptr += mp_align_len;
735 			mp->b_wptr += mp_align_len + hdr_length;
736 			mp->b_cont = nmp;
737 			mp->b_next = NULL;
738 			nmp->b_cont = NULL;
739 			nmp->b_next = NULL;
740 
741 			bcopy(vaddr, mp->b_rptr, hdr_length);
742 		}
743 	} else {
744 		/* no need to align */
745 		mp = nmp;
746 		mp->b_next = NULL;
747 		mp->b_cont = NULL;
748 	}
749 #else
750 	mp = nmp;
751 	mp->b_next = NULL;
752 	mp->b_cont = NULL;
753 #endif
754 
755 	return (mp);
756 }
757 
758 /*
759  * xgell_rx_1b_compl
760  *
761  * If the interrupt is because of a received frame or if the receive ring
762  * contains fresh as yet un-processed frames, this function is called.
763  */
764 static xge_hal_status_e
765 xgell_rx_1b_compl(xge_hal_channel_h channelh, xge_hal_dtr_h dtr, u8 t_code,
766     void *userdata)
767 {
768 	xgelldev_t *lldev = ((xgell_ring_t *)userdata)->lldev;
769 	xgell_rx_buffer_t *rx_buffer;
770 	mblk_t *mp_head = NULL;
771 	mblk_t *mp_end  = NULL;
772 	int pkt_burst = 0;
773 
774 	mutex_enter(&lldev->bf_pool.pool_lock);
775 
776 	do {
777 		int pkt_length;
778 		dma_addr_t dma_data;
779 		mblk_t *mp;
780 		boolean_t copyit = B_FALSE;
781 
782 		xgell_rxd_priv_t *rxd_priv = ((xgell_rxd_priv_t *)
783 		    xge_hal_ring_dtr_private(channelh, dtr));
784 		xge_hal_dtr_info_t ext_info;
785 
786 		rx_buffer = rxd_priv->rx_buffer;
787 
788 		xge_hal_ring_dtr_1b_get(channelh, dtr, &dma_data, &pkt_length);
789 		xge_hal_ring_dtr_info_get(channelh, dtr, &ext_info);
790 
791 		xge_assert(dma_data == rx_buffer->dma_addr);
792 
793 		if (t_code != 0) {
794 			xge_debug_ll(XGE_ERR, "%s%d: rx: dtr 0x%"PRIx64
795 			    " completed due to error t_code %01x", XGELL_IFNAME,
796 			    lldev->instance, (uint64_t)(uintptr_t)dtr, t_code);
797 
798 			(void) xge_hal_device_handle_tcode(channelh, dtr,
799 			    t_code);
800 			xge_hal_ring_dtr_free(channelh, dtr); /* drop it */
801 			xgell_rx_buffer_release(rx_buffer);
802 			continue;
803 		}
804 
805 		/*
806 		 * Sync the DMA memory
807 		 */
808 		if (ddi_dma_sync(rx_buffer->dma_handle, 0, pkt_length,
809 		    DDI_DMA_SYNC_FORKERNEL) != DDI_SUCCESS) {
810 			xge_debug_ll(XGE_ERR, "%s%d: rx: can not do DMA sync",
811 			    XGELL_IFNAME, lldev->instance);
812 			xge_hal_ring_dtr_free(channelh, dtr); /* drop it */
813 			xgell_rx_buffer_release(rx_buffer);
814 			continue;
815 		}
816 
817 		/*
818 		 * Allocate message for the packet.
819 		 */
820 		if (lldev->bf_pool.post > lldev->bf_pool.post_hiwat) {
821 			copyit = B_TRUE;
822 		} else {
823 			copyit = B_FALSE;
824 		}
825 
826 		mp = xgell_rx_1b_msg_alloc(lldev, rx_buffer, pkt_length,
827 		    &ext_info, &copyit);
828 
829 		xge_hal_ring_dtr_free(channelh, dtr);
830 
831 		/*
832 		 * Release the buffer and recycle it later
833 		 */
834 		if ((mp == NULL) || copyit) {
835 			xgell_rx_buffer_release(rx_buffer);
836 		} else {
837 			/*
838 			 * Count it since the buffer should be loaned up.
839 			 */
840 			lldev->bf_pool.post++;
841 		}
842 		if (mp == NULL) {
843 			xge_debug_ll(XGE_ERR,
844 			    "%s%d: rx: can not allocate mp mblk",
845 			    XGELL_IFNAME, lldev->instance);
846 			continue;
847 		}
848 
849 		/*
850 		 * Associate cksum_flags per packet type and h/w
851 		 * cksum flags.
852 		 */
853 		xgell_rx_hcksum_assoc(mp, (char *)rx_buffer->vaddr +
854 		    HEADROOM, pkt_length, &ext_info);
855 
856 		if (mp_head == NULL) {
857 			mp_head = mp;
858 			mp_end = mp;
859 		} else {
860 			mp_end->b_next = mp;
861 			mp_end = mp;
862 		}
863 
864 		if (++pkt_burst < lldev->config.rx_pkt_burst)
865 			continue;
866 
867 		if (lldev->bf_pool.post > lldev->bf_pool.post_hiwat) {
868 			/* Replenish rx buffers */
869 			xgell_rx_buffer_replenish_all(lldev);
870 		}
871 		mutex_exit(&lldev->bf_pool.pool_lock);
872 		if (mp_head != NULL) {
873 			mac_rx(lldev->mh, ((xgell_ring_t *)userdata)->handle,
874 			    mp_head);
875 		}
876 		mp_head = mp_end  = NULL;
877 		pkt_burst = 0;
878 		mutex_enter(&lldev->bf_pool.pool_lock);
879 
880 	} while (xge_hal_ring_dtr_next_completed(channelh, &dtr, &t_code) ==
881 	    XGE_HAL_OK);
882 
883 	/*
884 	 * Always call replenish_all to recycle rx_buffers.
885 	 */
886 	xgell_rx_buffer_replenish_all(lldev);
887 	mutex_exit(&lldev->bf_pool.pool_lock);
888 
889 	if (mp_head != NULL) {
890 		mac_rx(lldev->mh, ((xgell_ring_t *)userdata)->handle, mp_head);
891 	}
892 
893 	return (XGE_HAL_OK);
894 }
895 
896 /*
897  * xgell_xmit_compl
898  *
899  * If an interrupt was raised to indicate DMA complete of the Tx packet,
900  * this function is called. It identifies the last TxD whose buffer was
901  * freed and frees all skbs whose data have already DMA'ed into the NICs
902  * internal memory.
903  */
904 static xge_hal_status_e
905 xgell_xmit_compl(xge_hal_channel_h channelh, xge_hal_dtr_h dtr, u8 t_code,
906     void *userdata)
907 {
908 	xgelldev_t *lldev = userdata;
909 
910 	do {
911 		xgell_txd_priv_t *txd_priv = ((xgell_txd_priv_t *)
912 		    xge_hal_fifo_dtr_private(dtr));
913 		mblk_t *mp = txd_priv->mblk;
914 		int i;
915 
916 		if (t_code) {
917 			xge_debug_ll(XGE_TRACE, "%s%d: tx: dtr 0x%"PRIx64
918 			    " completed due to error t_code %01x", XGELL_IFNAME,
919 			    lldev->instance, (uint64_t)(uintptr_t)dtr, t_code);
920 
921 			(void) xge_hal_device_handle_tcode(channelh, dtr,
922 			    t_code);
923 		}
924 
925 		for (i = 0; i < txd_priv->handle_cnt; i++) {
926 			xge_assert(txd_priv->dma_handles[i]);
927 			(void) ddi_dma_unbind_handle(txd_priv->dma_handles[i]);
928 			ddi_dma_free_handle(&txd_priv->dma_handles[i]);
929 			txd_priv->dma_handles[i] = 0;
930 		}
931 
932 		xge_hal_fifo_dtr_free(channelh, dtr);
933 
934 		freemsg(mp);
935 		lldev->resched_avail++;
936 
937 	} while (xge_hal_fifo_dtr_next_completed(channelh, &dtr, &t_code) ==
938 	    XGE_HAL_OK);
939 
940 	if (lldev->resched_retry &&
941 	    xge_queue_produce_context(xge_hal_device_queue(lldev->devh),
942 	    XGELL_EVENT_RESCHED_NEEDED, lldev) == XGE_QUEUE_OK) {
943 	    xge_debug_ll(XGE_TRACE, "%s%d: IRQ produced event for queue %d",
944 		XGELL_IFNAME, lldev->instance,
945 		((xge_hal_channel_t *)lldev->fifo_channel)->post_qid);
946 		lldev->resched_send = lldev->resched_avail;
947 		lldev->resched_retry = 0;
948 	}
949 
950 	return (XGE_HAL_OK);
951 }
952 
953 /*
954  * xgell_send
955  * @hldev: pointer to xge_hal_device_t strucutre
956  * @mblk: pointer to network buffer, i.e. mblk_t structure
957  *
958  * Called by the xgell_m_tx to transmit the packet to the XFRAME firmware.
959  * A pointer to an M_DATA message that contains the packet is passed to
960  * this routine.
961  */
962 static boolean_t
963 xgell_send(xgelldev_t *lldev, mblk_t *mp)
964 {
965 	mblk_t *bp;
966 	boolean_t retry;
967 	xge_hal_device_t *hldev = lldev->devh;
968 	xge_hal_status_e status;
969 	xge_hal_dtr_h dtr;
970 	xgell_txd_priv_t *txd_priv;
971 	uint32_t hckflags;
972 	uint32_t mss;
973 	int handle_cnt, frag_cnt, ret, i, copied;
974 	boolean_t used_copy;
975 
976 _begin:
977 	retry = B_FALSE;
978 	handle_cnt = frag_cnt = 0;
979 
980 	if (!lldev->is_initialized || lldev->in_reset)
981 		return (B_FALSE);
982 
983 	/*
984 	 * If the free Tx dtrs count reaches the lower threshold,
985 	 * inform the gld to stop sending more packets till the free
986 	 * dtrs count exceeds higher threshold. Driver informs the
987 	 * gld through gld_sched call, when the free dtrs count exceeds
988 	 * the higher threshold.
989 	 */
990 	if (xge_hal_channel_dtr_count(lldev->fifo_channel)
991 	    <= XGELL_TX_LEVEL_LOW) {
992 		xge_debug_ll(XGE_TRACE, "%s%d: queue %d: err on xmit,"
993 		    "free descriptors count at low threshold %d",
994 		    XGELL_IFNAME, lldev->instance,
995 		    ((xge_hal_channel_t *)lldev->fifo_channel)->post_qid,
996 		    XGELL_TX_LEVEL_LOW);
997 		retry = B_TRUE;
998 		goto _exit;
999 	}
1000 
1001 	status = xge_hal_fifo_dtr_reserve(lldev->fifo_channel, &dtr);
1002 	if (status != XGE_HAL_OK) {
1003 		switch (status) {
1004 		case XGE_HAL_INF_CHANNEL_IS_NOT_READY:
1005 			xge_debug_ll(XGE_ERR,
1006 			    "%s%d: channel %d is not ready.", XGELL_IFNAME,
1007 			    lldev->instance,
1008 			    ((xge_hal_channel_t *)
1009 			    lldev->fifo_channel)->post_qid);
1010 			retry = B_TRUE;
1011 			goto _exit;
1012 		case XGE_HAL_INF_OUT_OF_DESCRIPTORS:
1013 			xge_debug_ll(XGE_TRACE, "%s%d: queue %d: error in xmit,"
1014 			    " out of descriptors.", XGELL_IFNAME,
1015 			    lldev->instance,
1016 			    ((xge_hal_channel_t *)
1017 			    lldev->fifo_channel)->post_qid);
1018 			retry = B_TRUE;
1019 			goto _exit;
1020 		default:
1021 			return (B_FALSE);
1022 		}
1023 	}
1024 
1025 	txd_priv = xge_hal_fifo_dtr_private(dtr);
1026 	txd_priv->mblk = mp;
1027 
1028 	/*
1029 	 * VLAN tag should be passed down along with MAC header, so h/w needn't
1030 	 * do insertion.
1031 	 *
1032 	 * For NIC driver that has to strip and re-insert VLAN tag, the example
1033 	 * is the other implementation for xge. The driver can simple bcopy()
1034 	 * ether_vlan_header to overwrite VLAN tag and let h/w insert the tag
1035 	 * automatically, since it's impossible that GLD sends down mp(s) with
1036 	 * splited ether_vlan_header.
1037 	 *
1038 	 * struct ether_vlan_header *evhp;
1039 	 * uint16_t tci;
1040 	 *
1041 	 * evhp = (struct ether_vlan_header *)mp->b_rptr;
1042 	 * if (evhp->ether_tpid == htons(VLAN_TPID)) {
1043 	 *	tci = ntohs(evhp->ether_tci);
1044 	 *	(void) bcopy(mp->b_rptr, mp->b_rptr + VLAN_TAGSZ,
1045 	 *	    2 * ETHERADDRL);
1046 	 *	mp->b_rptr += VLAN_TAGSZ;
1047 	 *
1048 	 *	xge_hal_fifo_dtr_vlan_set(dtr, tci);
1049 	 * }
1050 	 */
1051 
1052 	copied = 0;
1053 	used_copy = B_FALSE;
1054 	for (bp = mp; bp != NULL; bp = bp->b_cont) {
1055 		int mblen;
1056 		uint_t ncookies;
1057 		ddi_dma_cookie_t dma_cookie;
1058 		ddi_dma_handle_t dma_handle;
1059 
1060 		/* skip zero-length message blocks */
1061 		mblen = MBLKL(bp);
1062 		if (mblen == 0) {
1063 			continue;
1064 		}
1065 
1066 		/*
1067 		 * Check the message length to decide to DMA or bcopy() data
1068 		 * to tx descriptor(s).
1069 		 */
1070 		if (mblen < lldev->config.tx_dma_lowat &&
1071 		    (copied + mblen) < lldev->tx_copied_max) {
1072 			xge_hal_status_e rc;
1073 			rc = xge_hal_fifo_dtr_buffer_append(lldev->fifo_channel,
1074 			    dtr, bp->b_rptr, mblen);
1075 			if (rc == XGE_HAL_OK) {
1076 				used_copy = B_TRUE;
1077 				copied += mblen;
1078 				continue;
1079 			} else if (used_copy) {
1080 				xge_hal_fifo_dtr_buffer_finalize(
1081 					lldev->fifo_channel, dtr, frag_cnt++);
1082 				used_copy = B_FALSE;
1083 			}
1084 		} else if (used_copy) {
1085 			xge_hal_fifo_dtr_buffer_finalize(lldev->fifo_channel,
1086 			    dtr, frag_cnt++);
1087 			used_copy = B_FALSE;
1088 		}
1089 
1090 		ret = ddi_dma_alloc_handle(lldev->dev_info, &tx_dma_attr,
1091 		    DDI_DMA_DONTWAIT, 0, &dma_handle);
1092 		if (ret != DDI_SUCCESS) {
1093 			xge_debug_ll(XGE_ERR,
1094 			    "%s%d: can not allocate dma handle", XGELL_IFNAME,
1095 			    lldev->instance);
1096 			goto _exit_cleanup;
1097 		}
1098 
1099 		ret = ddi_dma_addr_bind_handle(dma_handle, NULL,
1100 		    (caddr_t)bp->b_rptr, mblen,
1101 		    DDI_DMA_WRITE | DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, 0,
1102 		    &dma_cookie, &ncookies);
1103 
1104 		switch (ret) {
1105 		case DDI_DMA_MAPPED:
1106 			/* everything's fine */
1107 			break;
1108 
1109 		case DDI_DMA_NORESOURCES:
1110 			xge_debug_ll(XGE_ERR,
1111 			    "%s%d: can not bind dma address",
1112 			    XGELL_IFNAME, lldev->instance);
1113 			ddi_dma_free_handle(&dma_handle);
1114 			goto _exit_cleanup;
1115 
1116 		case DDI_DMA_NOMAPPING:
1117 		case DDI_DMA_INUSE:
1118 		case DDI_DMA_TOOBIG:
1119 		default:
1120 			/* drop packet, don't retry */
1121 			xge_debug_ll(XGE_ERR,
1122 			    "%s%d: can not map message buffer",
1123 			    XGELL_IFNAME, lldev->instance);
1124 			ddi_dma_free_handle(&dma_handle);
1125 			goto _exit_cleanup;
1126 		}
1127 
1128 		if (ncookies + frag_cnt > hldev->config.fifo.max_frags) {
1129 			xge_debug_ll(XGE_ERR, "%s%d: too many fragments, "
1130 			    "requested c:%d+f:%d", XGELL_IFNAME,
1131 			    lldev->instance, ncookies, frag_cnt);
1132 			(void) ddi_dma_unbind_handle(dma_handle);
1133 			ddi_dma_free_handle(&dma_handle);
1134 			goto _exit_cleanup;
1135 		}
1136 
1137 		/* setup the descriptors for this data buffer */
1138 		while (ncookies) {
1139 			xge_hal_fifo_dtr_buffer_set(lldev->fifo_channel, dtr,
1140 			    frag_cnt++, dma_cookie.dmac_laddress,
1141 			    dma_cookie.dmac_size);
1142 			if (--ncookies) {
1143 				ddi_dma_nextcookie(dma_handle, &dma_cookie);
1144 			}
1145 
1146 		}
1147 
1148 		txd_priv->dma_handles[handle_cnt++] = dma_handle;
1149 
1150 		if (bp->b_cont &&
1151 		    (frag_cnt + XGE_HAL_DEFAULT_FIFO_FRAGS_THRESHOLD >=
1152 			hldev->config.fifo.max_frags)) {
1153 			mblk_t *nmp;
1154 
1155 			xge_debug_ll(XGE_TRACE,
1156 			    "too many FRAGs [%d], pull up them", frag_cnt);
1157 
1158 			if ((nmp = msgpullup(bp->b_cont, -1)) == NULL) {
1159 				/* Drop packet, don't retry */
1160 				xge_debug_ll(XGE_ERR,
1161 				    "%s%d: can not pullup message buffer",
1162 				    XGELL_IFNAME, lldev->instance);
1163 				goto _exit_cleanup;
1164 			}
1165 			freemsg(bp->b_cont);
1166 			bp->b_cont = nmp;
1167 		}
1168 	}
1169 
1170 	/* finalize unfinished copies */
1171 	if (used_copy) {
1172 		xge_hal_fifo_dtr_buffer_finalize(lldev->fifo_channel, dtr,
1173 		    frag_cnt++);
1174 	}
1175 
1176 	txd_priv->handle_cnt = handle_cnt;
1177 
1178 	/*
1179 	 * If LSO is required, just call xge_hal_fifo_dtr_mss_set(dtr, mss) to
1180 	 * do all necessary work.
1181 	 */
1182 	hcksum_retrieve(mp, NULL, NULL, NULL, NULL, NULL, &mss, &hckflags);
1183 	if ((hckflags & HW_LSO) && (mss != 0)) {
1184 		xge_hal_fifo_dtr_mss_set(dtr, mss);
1185 	}
1186 
1187 	if (hckflags & HCK_IPV4_HDRCKSUM) {
1188 		xge_hal_fifo_dtr_cksum_set_bits(dtr,
1189 		    XGE_HAL_TXD_TX_CKO_IPV4_EN);
1190 	}
1191 	if (hckflags & HCK_FULLCKSUM) {
1192 		xge_hal_fifo_dtr_cksum_set_bits(dtr, XGE_HAL_TXD_TX_CKO_TCP_EN |
1193 		    XGE_HAL_TXD_TX_CKO_UDP_EN);
1194 	}
1195 
1196 	xge_hal_fifo_dtr_post(lldev->fifo_channel, dtr);
1197 
1198 	return (B_TRUE);
1199 
1200 _exit_cleanup:
1201 
1202 	for (i = 0; i < handle_cnt; i++) {
1203 		(void) ddi_dma_unbind_handle(txd_priv->dma_handles[i]);
1204 		ddi_dma_free_handle(&txd_priv->dma_handles[i]);
1205 		txd_priv->dma_handles[i] = 0;
1206 	}
1207 
1208 	xge_hal_fifo_dtr_free(lldev->fifo_channel, dtr);
1209 
1210 _exit:
1211 	if (retry) {
1212 		if (lldev->resched_avail != lldev->resched_send &&
1213 		    xge_queue_produce_context(xge_hal_device_queue(lldev->devh),
1214 		    XGELL_EVENT_RESCHED_NEEDED, lldev) == XGE_QUEUE_OK) {
1215 			lldev->resched_send = lldev->resched_avail;
1216 			return (B_FALSE);
1217 		} else {
1218 			lldev->resched_retry = 1;
1219 		}
1220 	}
1221 
1222 	freemsg(mp);
1223 	return (B_TRUE);
1224 }
1225 
1226 /*
1227  * xge_m_tx
1228  * @arg: pointer to the xgelldev_t structure
1229  * @resid: resource id
1230  * @mp: pointer to the message buffer
1231  *
1232  * Called by MAC Layer to send a chain of packets
1233  */
1234 static mblk_t *
1235 xgell_m_tx(void *arg, mblk_t *mp)
1236 {
1237 	xgelldev_t *lldev = arg;
1238 	mblk_t *next;
1239 
1240 	while (mp != NULL) {
1241 		next = mp->b_next;
1242 		mp->b_next = NULL;
1243 
1244 		if (!xgell_send(lldev, mp)) {
1245 			mp->b_next = next;
1246 			break;
1247 		}
1248 		mp = next;
1249 	}
1250 
1251 	return (mp);
1252 }
1253 
1254 /*
1255  * xgell_rx_dtr_term
1256  *
1257  * Function will be called by HAL to terminate all DTRs for
1258  * Ring(s) type of channels.
1259  */
1260 static void
1261 xgell_rx_dtr_term(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh,
1262     xge_hal_dtr_state_e state, void *userdata, xge_hal_channel_reopen_e reopen)
1263 {
1264 	xgell_rxd_priv_t *rxd_priv =
1265 	    ((xgell_rxd_priv_t *)xge_hal_ring_dtr_private(channelh, dtrh));
1266 	xgell_rx_buffer_t *rx_buffer = rxd_priv->rx_buffer;
1267 
1268 	if (state == XGE_HAL_DTR_STATE_POSTED) {
1269 		xgelldev_t *lldev = rx_buffer->lldev;
1270 
1271 		mutex_enter(&lldev->bf_pool.pool_lock);
1272 		xge_hal_ring_dtr_free(channelh, dtrh);
1273 		xgell_rx_buffer_release(rx_buffer);
1274 		mutex_exit(&lldev->bf_pool.pool_lock);
1275 	}
1276 }
1277 
1278 /*
1279  * xgell_tx_term
1280  *
1281  * Function will be called by HAL to terminate all DTRs for
1282  * Fifo(s) type of channels.
1283  */
1284 static void
1285 xgell_tx_term(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh,
1286     xge_hal_dtr_state_e state, void *userdata, xge_hal_channel_reopen_e reopen)
1287 {
1288 	xgell_txd_priv_t *txd_priv =
1289 	    ((xgell_txd_priv_t *)xge_hal_fifo_dtr_private(dtrh));
1290 	mblk_t *mp = txd_priv->mblk;
1291 	int i;
1292 
1293 	/*
1294 	 * for Tx we must clean up the DTR *only* if it has been
1295 	 * posted!
1296 	 */
1297 	if (state != XGE_HAL_DTR_STATE_POSTED) {
1298 		return;
1299 	}
1300 
1301 	for (i = 0; i < txd_priv->handle_cnt; i++) {
1302 		xge_assert(txd_priv->dma_handles[i]);
1303 		(void) ddi_dma_unbind_handle(txd_priv->dma_handles[i]);
1304 		ddi_dma_free_handle(&txd_priv->dma_handles[i]);
1305 		txd_priv->dma_handles[i] = 0;
1306 	}
1307 
1308 	xge_hal_fifo_dtr_free(channelh, dtrh);
1309 
1310 	freemsg(mp);
1311 }
1312 
1313 /*
1314  * xgell_tx_open
1315  * @lldev: the link layer object
1316  *
1317  * Initialize and open all Tx channels;
1318  */
1319 static boolean_t
1320 xgell_tx_open(xgelldev_t *lldev)
1321 {
1322 	xge_hal_status_e status;
1323 	u64 adapter_status;
1324 	xge_hal_channel_attr_t attr;
1325 
1326 	attr.post_qid		= 0;
1327 	attr.compl_qid		= 0;
1328 	attr.callback		= xgell_xmit_compl;
1329 	attr.per_dtr_space	= sizeof (xgell_txd_priv_t);
1330 	attr.flags		= 0;
1331 	attr.type		= XGE_HAL_CHANNEL_TYPE_FIFO;
1332 	attr.userdata		= lldev;
1333 	attr.dtr_init		= NULL;
1334 	attr.dtr_term		= xgell_tx_term;
1335 
1336 	if (xge_hal_device_status(lldev->devh, &adapter_status)) {
1337 		xge_debug_ll(XGE_ERR, "%s%d: device is not ready "
1338 		    "adaper status reads 0x%"PRIx64, XGELL_IFNAME,
1339 		    lldev->instance, (uint64_t)adapter_status);
1340 		return (B_FALSE);
1341 	}
1342 
1343 	status = xge_hal_channel_open(lldev->devh, &attr,
1344 	    &lldev->fifo_channel, XGE_HAL_CHANNEL_OC_NORMAL);
1345 	if (status != XGE_HAL_OK) {
1346 		xge_debug_ll(XGE_ERR, "%s%d: cannot open Tx channel "
1347 		    "got status code %d", XGELL_IFNAME,
1348 		    lldev->instance, status);
1349 		return (B_FALSE);
1350 	}
1351 
1352 	return (B_TRUE);
1353 }
1354 
1355 /*
1356  * xgell_rx_open
1357  * @lldev: the link layer object
1358  *
1359  * Initialize and open all Rx channels;
1360  */
1361 static boolean_t
1362 xgell_rx_open(xgelldev_t *lldev)
1363 {
1364 	xge_hal_status_e status;
1365 	u64 adapter_status;
1366 	xge_hal_channel_attr_t attr;
1367 
1368 	attr.post_qid		= XGELL_RING_MAIN_QID;
1369 	attr.compl_qid		= 0;
1370 	attr.callback		= xgell_rx_1b_compl;
1371 	attr.per_dtr_space	= sizeof (xgell_rxd_priv_t);
1372 	attr.flags		= 0;
1373 	attr.type		= XGE_HAL_CHANNEL_TYPE_RING;
1374 	attr.dtr_init		= xgell_rx_dtr_replenish;
1375 	attr.dtr_term		= xgell_rx_dtr_term;
1376 
1377 	if (xge_hal_device_status(lldev->devh, &adapter_status)) {
1378 		xge_debug_ll(XGE_ERR,
1379 		    "%s%d: device is not ready adaper status reads 0x%"PRIx64,
1380 		    XGELL_IFNAME, lldev->instance,
1381 		    (uint64_t)adapter_status);
1382 		return (B_FALSE);
1383 	}
1384 
1385 	lldev->ring_main.lldev = lldev;
1386 	attr.userdata = &lldev->ring_main;
1387 
1388 	status = xge_hal_channel_open(lldev->devh, &attr,
1389 	    &lldev->ring_main.channelh, XGE_HAL_CHANNEL_OC_NORMAL);
1390 	if (status != XGE_HAL_OK) {
1391 		xge_debug_ll(XGE_ERR, "%s%d: cannot open Rx channel got status "
1392 		    " code %d", XGELL_IFNAME, lldev->instance, status);
1393 		return (B_FALSE);
1394 	}
1395 
1396 	return (B_TRUE);
1397 }
1398 
1399 static int
1400 xgell_initiate_start(xgelldev_t *lldev)
1401 {
1402 	xge_hal_status_e status;
1403 	xge_hal_device_t *hldev = lldev->devh;
1404 	int maxpkt = hldev->config.mtu;
1405 
1406 	/* check initial mtu before enabling the device */
1407 	status = xge_hal_device_mtu_check(lldev->devh, maxpkt);
1408 	if (status != XGE_HAL_OK) {
1409 		xge_debug_ll(XGE_ERR, "%s%d: MTU size %d is invalid",
1410 		    XGELL_IFNAME, lldev->instance, maxpkt);
1411 		return (EINVAL);
1412 	}
1413 
1414 	/* set initial mtu before enabling the device */
1415 	status = xge_hal_device_mtu_set(lldev->devh, maxpkt);
1416 	if (status != XGE_HAL_OK) {
1417 		xge_debug_ll(XGE_ERR, "%s%d: can not set new MTU %d",
1418 		    XGELL_IFNAME, lldev->instance, maxpkt);
1419 		return (EIO);
1420 	}
1421 
1422 	/* tune jumbo/normal frame UFC counters */
1423 	hldev->config.ring.queue[XGELL_RING_MAIN_QID].rti.ufc_b = \
1424 		maxpkt > XGE_HAL_DEFAULT_MTU ?
1425 			XGE_HAL_DEFAULT_RX_UFC_B_J :
1426 			XGE_HAL_DEFAULT_RX_UFC_B_N;
1427 
1428 	hldev->config.ring.queue[XGELL_RING_MAIN_QID].rti.ufc_c = \
1429 		maxpkt > XGE_HAL_DEFAULT_MTU ?
1430 			XGE_HAL_DEFAULT_RX_UFC_C_J :
1431 			XGE_HAL_DEFAULT_RX_UFC_C_N;
1432 
1433 	/* now, enable the device */
1434 	status = xge_hal_device_enable(lldev->devh);
1435 	if (status != XGE_HAL_OK) {
1436 		xge_debug_ll(XGE_ERR, "%s%d: can not enable the device",
1437 		    XGELL_IFNAME, lldev->instance);
1438 		return (EIO);
1439 	}
1440 
1441 	if (!xgell_rx_open(lldev)) {
1442 		status = xge_hal_device_disable(lldev->devh);
1443 		if (status != XGE_HAL_OK) {
1444 			u64 adapter_status;
1445 			(void) xge_hal_device_status(lldev->devh,
1446 			    &adapter_status);
1447 			xge_debug_ll(XGE_ERR, "%s%d: can not safely disable "
1448 			    "the device. adaper status 0x%"PRIx64
1449 			    " returned status %d",
1450 			    XGELL_IFNAME, lldev->instance,
1451 			    (uint64_t)adapter_status, status);
1452 		}
1453 		xge_os_mdelay(1500);
1454 		return (ENOMEM);
1455 	}
1456 
1457 	if (!xgell_tx_open(lldev)) {
1458 		status = xge_hal_device_disable(lldev->devh);
1459 		if (status != XGE_HAL_OK) {
1460 			u64 adapter_status;
1461 			(void) xge_hal_device_status(lldev->devh,
1462 			    &adapter_status);
1463 			xge_debug_ll(XGE_ERR, "%s%d: can not safely disable "
1464 			    "the device. adaper status 0x%"PRIx64
1465 			    " returned status %d",
1466 			    XGELL_IFNAME, lldev->instance,
1467 			    (uint64_t)adapter_status, status);
1468 		}
1469 		xge_os_mdelay(1500);
1470 		xge_hal_channel_close(lldev->ring_main.channelh,
1471 		    XGE_HAL_CHANNEL_OC_NORMAL);
1472 		return (ENOMEM);
1473 	}
1474 
1475 	/* time to enable interrupts */
1476 	xge_hal_device_intr_enable(lldev->devh);
1477 
1478 	lldev->is_initialized = 1;
1479 
1480 	return (0);
1481 }
1482 
1483 static void
1484 xgell_initiate_stop(xgelldev_t *lldev)
1485 {
1486 	xge_hal_status_e status;
1487 
1488 	lldev->is_initialized = 0;
1489 
1490 	status = xge_hal_device_disable(lldev->devh);
1491 	if (status != XGE_HAL_OK) {
1492 		u64 adapter_status;
1493 		(void) xge_hal_device_status(lldev->devh, &adapter_status);
1494 		xge_debug_ll(XGE_ERR, "%s%d: can not safely disable "
1495 		    "the device. adaper status 0x%"PRIx64" returned status %d",
1496 		    XGELL_IFNAME, lldev->instance,
1497 		    (uint64_t)adapter_status, status);
1498 	}
1499 	xge_hal_device_intr_disable(lldev->devh);
1500 
1501 	xge_debug_ll(XGE_TRACE, "%s",
1502 	    "waiting for device irq to become quiescent...");
1503 	xge_os_mdelay(1500);
1504 
1505 	xge_queue_flush(xge_hal_device_queue(lldev->devh));
1506 
1507 	xge_hal_channel_close(lldev->ring_main.channelh,
1508 	    XGE_HAL_CHANNEL_OC_NORMAL);
1509 
1510 	xge_hal_channel_close(lldev->fifo_channel,
1511 	    XGE_HAL_CHANNEL_OC_NORMAL);
1512 }
1513 
1514 /*
1515  * xgell_m_start
1516  * @arg: pointer to device private strucutre(hldev)
1517  *
1518  * This function is called by MAC Layer to enable the XFRAME
1519  * firmware to generate interrupts and also prepare the
1520  * driver to call mac_rx for delivering receive packets
1521  * to MAC Layer.
1522  */
1523 static int
1524 xgell_m_start(void *arg)
1525 {
1526 	xgelldev_t *lldev = arg;
1527 	xge_hal_device_t *hldev = lldev->devh;
1528 	int ret;
1529 
1530 	xge_debug_ll(XGE_TRACE, "%s%d: M_START", XGELL_IFNAME,
1531 	    lldev->instance);
1532 
1533 	mutex_enter(&lldev->genlock);
1534 
1535 	if (lldev->is_initialized) {
1536 		xge_debug_ll(XGE_ERR, "%s%d: device is already initialized",
1537 		    XGELL_IFNAME, lldev->instance);
1538 		mutex_exit(&lldev->genlock);
1539 		return (EINVAL);
1540 	}
1541 
1542 	hldev->terminating = 0;
1543 	if (ret = xgell_initiate_start(lldev)) {
1544 		mutex_exit(&lldev->genlock);
1545 		return (ret);
1546 	}
1547 
1548 	lldev->timeout_id = timeout(xge_device_poll, hldev, XGE_DEV_POLL_TICKS);
1549 
1550 	mutex_exit(&lldev->genlock);
1551 
1552 	return (0);
1553 }
1554 
1555 /*
1556  * xgell_m_stop
1557  * @arg: pointer to device private data (hldev)
1558  *
1559  * This function is called by the MAC Layer to disable
1560  * the XFRAME firmware for generating any interrupts and
1561  * also stop the driver from calling mac_rx() for
1562  * delivering data packets to the MAC Layer.
1563  */
1564 static void
1565 xgell_m_stop(void *arg)
1566 {
1567 	xgelldev_t *lldev = arg;
1568 	xge_hal_device_t *hldev = lldev->devh;
1569 
1570 	xge_debug_ll(XGE_TRACE, "%s", "MAC_STOP");
1571 
1572 	mutex_enter(&lldev->genlock);
1573 	if (!lldev->is_initialized) {
1574 		xge_debug_ll(XGE_ERR, "%s", "device is not initialized...");
1575 		mutex_exit(&lldev->genlock);
1576 		return;
1577 	}
1578 
1579 	xge_hal_device_terminating(hldev);
1580 	xgell_initiate_stop(lldev);
1581 
1582 	/* reset device */
1583 	(void) xge_hal_device_reset(lldev->devh);
1584 
1585 	mutex_exit(&lldev->genlock);
1586 
1587 	if (lldev->timeout_id != 0) {
1588 		(void) untimeout(lldev->timeout_id);
1589 	}
1590 
1591 	xge_debug_ll(XGE_TRACE, "%s", "returning back to MAC Layer...");
1592 }
1593 
1594 /*
1595  * xgell_onerr_reset
1596  * @lldev: pointer to xgelldev_t structure
1597  *
1598  * This function is called by HAL Event framework to reset the HW
1599  * This function is must be called with genlock taken.
1600  */
1601 int
1602 xgell_onerr_reset(xgelldev_t *lldev)
1603 {
1604 	int rc = 0;
1605 
1606 	if (!lldev->is_initialized) {
1607 		xge_debug_ll(XGE_ERR, "%s%d: can not reset",
1608 		    XGELL_IFNAME, lldev->instance);
1609 		return (rc);
1610 	}
1611 
1612 	lldev->in_reset = 1;
1613 	xgell_initiate_stop(lldev);
1614 
1615 	/* reset device */
1616 	(void) xge_hal_device_reset(lldev->devh);
1617 
1618 	rc = xgell_initiate_start(lldev);
1619 	lldev->in_reset = 0;
1620 
1621 	return (rc);
1622 }
1623 
1624 
1625 /*
1626  * xgell_m_unicst
1627  * @arg: pointer to device private strucutre(hldev)
1628  * @mac_addr:
1629  *
1630  * This function is called by MAC Layer to set the physical address
1631  * of the XFRAME firmware.
1632  */
1633 static int
1634 xgell_m_unicst(void *arg, const uint8_t *macaddr)
1635 {
1636 	xge_hal_status_e status;
1637 	xgelldev_t *lldev = (xgelldev_t *)arg;
1638 	xge_hal_device_t *hldev = lldev->devh;
1639 	xge_debug_ll(XGE_TRACE, "%s", "MAC_UNICST");
1640 
1641 	xge_debug_ll(XGE_TRACE, "%s", "M_UNICAST");
1642 
1643 	mutex_enter(&lldev->genlock);
1644 
1645 	xge_debug_ll(XGE_TRACE,
1646 	    "setting macaddr: 0x%02x-%02x-%02x-%02x-%02x-%02x",
1647 	    macaddr[0], macaddr[1], macaddr[2],
1648 	    macaddr[3], macaddr[4], macaddr[5]);
1649 
1650 	status = xge_hal_device_macaddr_set(hldev, 0, (uchar_t *)macaddr);
1651 	if (status != XGE_HAL_OK) {
1652 		xge_debug_ll(XGE_ERR, "%s%d: can not set mac address",
1653 		    XGELL_IFNAME, lldev->instance);
1654 		mutex_exit(&lldev->genlock);
1655 		return (EIO);
1656 	}
1657 
1658 	mutex_exit(&lldev->genlock);
1659 
1660 	return (0);
1661 }
1662 
1663 
1664 /*
1665  * xgell_m_multicst
1666  * @arg: pointer to device private strucutre(hldev)
1667  * @add:
1668  * @mc_addr:
1669  *
1670  * This function is called by MAC Layer to enable or
1671  * disable device-level reception of specific multicast addresses.
1672  */
1673 static int
1674 xgell_m_multicst(void *arg, boolean_t add, const uint8_t *mc_addr)
1675 {
1676 	xge_hal_status_e status;
1677 	xgelldev_t *lldev = (xgelldev_t *)arg;
1678 	xge_hal_device_t *hldev = lldev->devh;
1679 
1680 	xge_debug_ll(XGE_TRACE, "M_MULTICAST add %d", add);
1681 
1682 	mutex_enter(&lldev->genlock);
1683 
1684 	if (!lldev->is_initialized) {
1685 		xge_debug_ll(XGE_ERR, "%s%d: can not set multicast",
1686 		    XGELL_IFNAME, lldev->instance);
1687 		mutex_exit(&lldev->genlock);
1688 		return (EIO);
1689 	}
1690 
1691 	/* FIXME: missing HAL functionality: enable_one() */
1692 
1693 	status = (add) ?
1694 	    xge_hal_device_mcast_enable(hldev) :
1695 	    xge_hal_device_mcast_disable(hldev);
1696 
1697 	if (status != XGE_HAL_OK) {
1698 		xge_debug_ll(XGE_ERR, "failed to %s multicast, status %d",
1699 		    add ? "enable" : "disable", status);
1700 		mutex_exit(&lldev->genlock);
1701 		return (EIO);
1702 	}
1703 
1704 	mutex_exit(&lldev->genlock);
1705 
1706 	return (0);
1707 }
1708 
1709 
1710 /*
1711  * xgell_m_promisc
1712  * @arg: pointer to device private strucutre(hldev)
1713  * @on:
1714  *
1715  * This function is called by MAC Layer to enable or
1716  * disable the reception of all the packets on the medium
1717  */
1718 static int
1719 xgell_m_promisc(void *arg, boolean_t on)
1720 {
1721 	xgelldev_t *lldev = (xgelldev_t *)arg;
1722 	xge_hal_device_t *hldev = lldev->devh;
1723 
1724 	mutex_enter(&lldev->genlock);
1725 
1726 	xge_debug_ll(XGE_TRACE, "%s", "MAC_PROMISC_SET");
1727 
1728 	if (!lldev->is_initialized) {
1729 		xge_debug_ll(XGE_ERR, "%s%d: can not set promiscuous",
1730 		    XGELL_IFNAME, lldev->instance);
1731 		mutex_exit(&lldev->genlock);
1732 		return (EIO);
1733 	}
1734 
1735 	if (on) {
1736 		xge_hal_device_promisc_enable(hldev);
1737 	} else {
1738 		xge_hal_device_promisc_disable(hldev);
1739 	}
1740 
1741 	mutex_exit(&lldev->genlock);
1742 
1743 	return (0);
1744 }
1745 
1746 /*
1747  * xgell_m_stat
1748  * @arg: pointer to device private strucutre(hldev)
1749  *
1750  * This function is called by MAC Layer to get network statistics
1751  * from the driver.
1752  */
1753 static int
1754 xgell_m_stat(void *arg, uint_t stat, uint64_t *val)
1755 {
1756 	xge_hal_stats_hw_info_t *hw_info;
1757 	xgelldev_t *lldev = (xgelldev_t *)arg;
1758 	xge_hal_device_t *hldev = lldev->devh;
1759 
1760 	xge_debug_ll(XGE_TRACE, "%s", "MAC_STATS_GET");
1761 
1762 	if (!mutex_tryenter(&lldev->genlock))
1763 		return (EAGAIN);
1764 
1765 	if (!lldev->is_initialized) {
1766 		mutex_exit(&lldev->genlock);
1767 		return (EAGAIN);
1768 	}
1769 
1770 	if (xge_hal_stats_hw(hldev, &hw_info) != XGE_HAL_OK) {
1771 		mutex_exit(&lldev->genlock);
1772 		return (EAGAIN);
1773 	}
1774 
1775 	switch (stat) {
1776 	case MAC_STAT_IFSPEED:
1777 		*val = 10000000000ull; /* 10G */
1778 		break;
1779 
1780 	case MAC_STAT_MULTIRCV:
1781 		*val = ((u64) hw_info->rmac_vld_mcst_frms_oflow << 32) |
1782 		    hw_info->rmac_vld_mcst_frms;
1783 		break;
1784 
1785 	case MAC_STAT_BRDCSTRCV:
1786 		*val = ((u64) hw_info->rmac_vld_bcst_frms_oflow << 32) |
1787 		    hw_info->rmac_vld_bcst_frms;
1788 		break;
1789 
1790 	case MAC_STAT_MULTIXMT:
1791 		*val = ((u64) hw_info->tmac_mcst_frms_oflow << 32) |
1792 		    hw_info->tmac_mcst_frms;
1793 		break;
1794 
1795 	case MAC_STAT_BRDCSTXMT:
1796 		*val = ((u64) hw_info->tmac_bcst_frms_oflow << 32) |
1797 		    hw_info->tmac_bcst_frms;
1798 		break;
1799 
1800 	case MAC_STAT_RBYTES:
1801 		*val = ((u64) hw_info->rmac_ttl_octets_oflow << 32) |
1802 		    hw_info->rmac_ttl_octets;
1803 		break;
1804 
1805 	case MAC_STAT_NORCVBUF:
1806 		*val = hw_info->rmac_drop_frms;
1807 		break;
1808 
1809 	case MAC_STAT_IERRORS:
1810 		*val = ((u64) hw_info->rmac_discarded_frms_oflow << 32) |
1811 		    hw_info->rmac_discarded_frms;
1812 		break;
1813 
1814 	case MAC_STAT_OBYTES:
1815 		*val = ((u64) hw_info->tmac_ttl_octets_oflow << 32) |
1816 		    hw_info->tmac_ttl_octets;
1817 		break;
1818 
1819 	case MAC_STAT_NOXMTBUF:
1820 		*val = hw_info->tmac_drop_frms;
1821 		break;
1822 
1823 	case MAC_STAT_OERRORS:
1824 		*val = ((u64) hw_info->tmac_any_err_frms_oflow << 32) |
1825 		    hw_info->tmac_any_err_frms;
1826 		break;
1827 
1828 	case MAC_STAT_IPACKETS:
1829 		*val = ((u64) hw_info->rmac_vld_frms_oflow << 32) |
1830 		    hw_info->rmac_vld_frms;
1831 		break;
1832 
1833 	case MAC_STAT_OPACKETS:
1834 		*val = ((u64) hw_info->tmac_frms_oflow << 32) |
1835 		    hw_info->tmac_frms;
1836 		break;
1837 
1838 	case ETHER_STAT_FCS_ERRORS:
1839 		*val = hw_info->rmac_fcs_err_frms;
1840 		break;
1841 
1842 	case ETHER_STAT_TOOLONG_ERRORS:
1843 		*val = hw_info->rmac_long_frms;
1844 		break;
1845 
1846 	case ETHER_STAT_LINK_DUPLEX:
1847 		*val = LINK_DUPLEX_FULL;
1848 		break;
1849 
1850 	default:
1851 		mutex_exit(&lldev->genlock);
1852 		return (ENOTSUP);
1853 	}
1854 
1855 	mutex_exit(&lldev->genlock);
1856 
1857 	return (0);
1858 }
1859 
1860 /*
1861  * xgell_device_alloc - Allocate new LL device
1862  */
1863 int
1864 xgell_device_alloc(xge_hal_device_h devh,
1865     dev_info_t *dev_info, xgelldev_t **lldev_out)
1866 {
1867 	xgelldev_t *lldev;
1868 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
1869 	int instance = ddi_get_instance(dev_info);
1870 
1871 	*lldev_out = NULL;
1872 
1873 	xge_debug_ll(XGE_TRACE, "trying to register etherenet device %s%d...",
1874 	    XGELL_IFNAME, instance);
1875 
1876 	lldev = kmem_zalloc(sizeof (xgelldev_t), KM_SLEEP);
1877 
1878 	lldev->devh = hldev;
1879 	lldev->instance = instance;
1880 	lldev->dev_info = dev_info;
1881 
1882 	*lldev_out = lldev;
1883 
1884 	ddi_set_driver_private(dev_info, (caddr_t)hldev);
1885 
1886 	return (DDI_SUCCESS);
1887 }
1888 
1889 /*
1890  * xgell_device_free
1891  */
1892 void
1893 xgell_device_free(xgelldev_t *lldev)
1894 {
1895 	xge_debug_ll(XGE_TRACE, "freeing device %s%d",
1896 	    XGELL_IFNAME, lldev->instance);
1897 
1898 	kmem_free(lldev, sizeof (xgelldev_t));
1899 }
1900 
1901 /*
1902  * xgell_ioctl
1903  */
1904 static void
1905 xgell_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
1906 {
1907 	xgelldev_t *lldev = arg;
1908 	struct iocblk *iocp;
1909 	int err = 0;
1910 	int cmd;
1911 	int need_privilege = 1;
1912 	int ret = 0;
1913 
1914 
1915 	iocp = (struct iocblk *)mp->b_rptr;
1916 	iocp->ioc_error = 0;
1917 	cmd = iocp->ioc_cmd;
1918 	xge_debug_ll(XGE_TRACE, "MAC_IOCTL cmd 0x%x", cmd);
1919 	switch (cmd) {
1920 	case ND_GET:
1921 		need_privilege = 0;
1922 		/* FALLTHRU */
1923 	case ND_SET:
1924 		break;
1925 	default:
1926 		xge_debug_ll(XGE_TRACE, "unknown cmd 0x%x", cmd);
1927 		miocnak(wq, mp, 0, EINVAL);
1928 		return;
1929 	}
1930 
1931 	if (need_privilege) {
1932 		err = secpolicy_net_config(iocp->ioc_cr, B_FALSE);
1933 		if (err != 0) {
1934 			xge_debug_ll(XGE_ERR,
1935 			    "drv_priv(): rejected cmd 0x%x, err %d",
1936 			    cmd, err);
1937 			miocnak(wq, mp, 0, err);
1938 			return;
1939 		}
1940 	}
1941 
1942 	switch (cmd) {
1943 	case ND_GET:
1944 		/*
1945 		 * If nd_getset() returns B_FALSE, the command was
1946 		 * not valid (e.g. unknown name), so we just tell the
1947 		 * top-level ioctl code to send a NAK (with code EINVAL).
1948 		 *
1949 		 * Otherwise, nd_getset() will have built the reply to
1950 		 * be sent (but not actually sent it), so we tell the
1951 		 * caller to send the prepared reply.
1952 		 */
1953 		ret = nd_getset(wq, lldev->ndp, mp);
1954 		xge_debug_ll(XGE_TRACE, "got ndd get ioctl");
1955 		break;
1956 
1957 	case ND_SET:
1958 		ret = nd_getset(wq, lldev->ndp, mp);
1959 		xge_debug_ll(XGE_TRACE, "got ndd set ioctl");
1960 		break;
1961 
1962 	default:
1963 		break;
1964 	}
1965 
1966 	if (ret == B_FALSE) {
1967 		xge_debug_ll(XGE_ERR,
1968 		    "nd_getset(): rejected cmd 0x%x, err %d",
1969 		    cmd, err);
1970 		miocnak(wq, mp, 0, EINVAL);
1971 	} else {
1972 		mp->b_datap->db_type = iocp->ioc_error == 0 ?
1973 		    M_IOCACK : M_IOCNAK;
1974 		qreply(wq, mp);
1975 	}
1976 }
1977 
1978 /* ARGSUSED */
1979 static boolean_t
1980 xgell_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
1981 {
1982 	xgelldev_t *lldev = arg;
1983 
1984 	switch (cap) {
1985 	case MAC_CAPAB_HCKSUM: {
1986 		uint32_t *hcksum_txflags = cap_data;
1987 		*hcksum_txflags = HCKSUM_INET_FULL_V4 | HCKSUM_INET_FULL_V6 |
1988 		    HCKSUM_IPHDRCKSUM;
1989 		break;
1990 	}
1991 	case MAC_CAPAB_LSO: {
1992 		mac_capab_lso_t *cap_lso = cap_data;
1993 
1994 		if (lldev->config.lso_enable) {
1995 			cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
1996 			cap_lso->lso_basic_tcp_ipv4.lso_max = XGELL_LSO_MAXLEN;
1997 			break;
1998 		} else {
1999 			return (B_FALSE);
2000 		}
2001 	}
2002 	default:
2003 		return (B_FALSE);
2004 	}
2005 	return (B_TRUE);
2006 }
2007 
2008 static int
2009 xgell_stats_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
2010 {
2011 	xgelldev_t *lldev = (xgelldev_t *)cp;
2012 	xge_hal_status_e status;
2013 	int count = 0, retsize;
2014 	char *buf;
2015 
2016 	buf = kmem_alloc(XGELL_STATS_BUFSIZE, KM_SLEEP);
2017 	if (buf == NULL) {
2018 		return (ENOSPC);
2019 	}
2020 
2021 	status = xge_hal_aux_stats_tmac_read(lldev->devh, XGELL_STATS_BUFSIZE,
2022 	    buf, &retsize);
2023 	if (status != XGE_HAL_OK) {
2024 		kmem_free(buf, XGELL_STATS_BUFSIZE);
2025 		xge_debug_ll(XGE_ERR, "tmac_read(): status %d", status);
2026 		return (EINVAL);
2027 	}
2028 	count += retsize;
2029 
2030 	status = xge_hal_aux_stats_rmac_read(lldev->devh,
2031 	    XGELL_STATS_BUFSIZE - count,
2032 	    buf+count, &retsize);
2033 	if (status != XGE_HAL_OK) {
2034 		kmem_free(buf, XGELL_STATS_BUFSIZE);
2035 		xge_debug_ll(XGE_ERR, "rmac_read(): status %d", status);
2036 		return (EINVAL);
2037 	}
2038 	count += retsize;
2039 
2040 	status = xge_hal_aux_stats_pci_read(lldev->devh,
2041 	    XGELL_STATS_BUFSIZE - count, buf + count, &retsize);
2042 	if (status != XGE_HAL_OK) {
2043 		kmem_free(buf, XGELL_STATS_BUFSIZE);
2044 		xge_debug_ll(XGE_ERR, "pci_read(): status %d", status);
2045 		return (EINVAL);
2046 	}
2047 	count += retsize;
2048 
2049 	status = xge_hal_aux_stats_sw_dev_read(lldev->devh,
2050 	    XGELL_STATS_BUFSIZE - count, buf + count, &retsize);
2051 	if (status != XGE_HAL_OK) {
2052 		kmem_free(buf, XGELL_STATS_BUFSIZE);
2053 		xge_debug_ll(XGE_ERR, "sw_dev_read(): status %d", status);
2054 		return (EINVAL);
2055 	}
2056 	count += retsize;
2057 
2058 	status = xge_hal_aux_stats_hal_read(lldev->devh,
2059 	    XGELL_STATS_BUFSIZE - count, buf + count, &retsize);
2060 	if (status != XGE_HAL_OK) {
2061 		kmem_free(buf, XGELL_STATS_BUFSIZE);
2062 		xge_debug_ll(XGE_ERR, "pci_read(): status %d", status);
2063 		return (EINVAL);
2064 	}
2065 	count += retsize;
2066 
2067 	*(buf + count - 1) = '\0'; /* remove last '\n' */
2068 	(void) mi_mpprintf(mp, "%s", buf);
2069 	kmem_free(buf, XGELL_STATS_BUFSIZE);
2070 
2071 	return (0);
2072 }
2073 
2074 static int
2075 xgell_pciconf_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
2076 {
2077 	xgelldev_t *lldev = (xgelldev_t *)cp;
2078 	xge_hal_status_e status;
2079 	int retsize;
2080 	char *buf;
2081 
2082 	buf = kmem_alloc(XGELL_PCICONF_BUFSIZE, KM_SLEEP);
2083 	if (buf == NULL) {
2084 		return (ENOSPC);
2085 	}
2086 	status = xge_hal_aux_pci_config_read(lldev->devh, XGELL_PCICONF_BUFSIZE,
2087 	    buf, &retsize);
2088 	if (status != XGE_HAL_OK) {
2089 		kmem_free(buf, XGELL_PCICONF_BUFSIZE);
2090 		xge_debug_ll(XGE_ERR, "pci_config_read(): status %d", status);
2091 		return (EINVAL);
2092 	}
2093 	*(buf + retsize - 1) = '\0'; /* remove last '\n' */
2094 	(void) mi_mpprintf(mp, "%s", buf);
2095 	kmem_free(buf, XGELL_PCICONF_BUFSIZE);
2096 
2097 	return (0);
2098 }
2099 
2100 static int
2101 xgell_about_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
2102 {
2103 	xgelldev_t *lldev = (xgelldev_t *)cp;
2104 	xge_hal_status_e status;
2105 	int retsize;
2106 	char *buf;
2107 
2108 	buf = kmem_alloc(XGELL_ABOUT_BUFSIZE, KM_SLEEP);
2109 	if (buf == NULL) {
2110 		return (ENOSPC);
2111 	}
2112 	status = xge_hal_aux_about_read(lldev->devh, XGELL_ABOUT_BUFSIZE,
2113 	    buf, &retsize);
2114 	if (status != XGE_HAL_OK) {
2115 		kmem_free(buf, XGELL_ABOUT_BUFSIZE);
2116 		xge_debug_ll(XGE_ERR, "about_read(): status %d", status);
2117 		return (EINVAL);
2118 	}
2119 	*(buf + retsize - 1) = '\0'; /* remove last '\n' */
2120 	(void) mi_mpprintf(mp, "%s", buf);
2121 	kmem_free(buf, XGELL_ABOUT_BUFSIZE);
2122 
2123 	return (0);
2124 }
2125 
2126 static unsigned long bar0_offset = 0x110; /* adapter_control */
2127 
2128 static int
2129 xgell_bar0_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
2130 {
2131 	xgelldev_t *lldev = (xgelldev_t *)cp;
2132 	xge_hal_status_e status;
2133 	int retsize;
2134 	char *buf;
2135 
2136 	buf = kmem_alloc(XGELL_IOCTL_BUFSIZE, KM_SLEEP);
2137 	if (buf == NULL) {
2138 		return (ENOSPC);
2139 	}
2140 	status = xge_hal_aux_bar0_read(lldev->devh, bar0_offset,
2141 	    XGELL_IOCTL_BUFSIZE, buf, &retsize);
2142 	if (status != XGE_HAL_OK) {
2143 		kmem_free(buf, XGELL_IOCTL_BUFSIZE);
2144 		xge_debug_ll(XGE_ERR, "bar0_read(): status %d", status);
2145 		return (EINVAL);
2146 	}
2147 	*(buf + retsize - 1) = '\0'; /* remove last '\n' */
2148 	(void) mi_mpprintf(mp, "%s", buf);
2149 	kmem_free(buf, XGELL_IOCTL_BUFSIZE);
2150 
2151 	return (0);
2152 }
2153 
2154 static int
2155 xgell_bar0_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, cred_t *credp)
2156 {
2157 	unsigned long old_offset = bar0_offset;
2158 	char *end;
2159 
2160 	if (value && *value == '0' &&
2161 	    (*(value + 1) == 'x' || *(value + 1) == 'X')) {
2162 		value += 2;
2163 	}
2164 
2165 	bar0_offset = mi_strtol(value, &end, 16);
2166 	if (end == value) {
2167 		bar0_offset = old_offset;
2168 		return (EINVAL);
2169 	}
2170 
2171 	xge_debug_ll(XGE_TRACE, "bar0: new value %s:%lX", value, bar0_offset);
2172 
2173 	return (0);
2174 }
2175 
2176 static int
2177 xgell_debug_level_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
2178 {
2179 	char *buf;
2180 
2181 	buf = kmem_alloc(XGELL_IOCTL_BUFSIZE, KM_SLEEP);
2182 	if (buf == NULL) {
2183 		return (ENOSPC);
2184 	}
2185 	(void) mi_mpprintf(mp, "debug_level %d", xge_hal_driver_debug_level());
2186 	kmem_free(buf, XGELL_IOCTL_BUFSIZE);
2187 
2188 	return (0);
2189 }
2190 
2191 static int
2192 xgell_debug_level_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp,
2193     cred_t *credp)
2194 {
2195 	int level;
2196 	char *end;
2197 
2198 	level = mi_strtol(value, &end, 10);
2199 	if (level < XGE_NONE || level > XGE_ERR || end == value) {
2200 		return (EINVAL);
2201 	}
2202 
2203 	xge_hal_driver_debug_level_set(level);
2204 
2205 	return (0);
2206 }
2207 
2208 static int
2209 xgell_debug_module_mask_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
2210 {
2211 	char *buf;
2212 
2213 	buf = kmem_alloc(XGELL_IOCTL_BUFSIZE, KM_SLEEP);
2214 	if (buf == NULL) {
2215 		return (ENOSPC);
2216 	}
2217 	(void) mi_mpprintf(mp, "debug_module_mask 0x%08x",
2218 	    xge_hal_driver_debug_module_mask());
2219 	kmem_free(buf, XGELL_IOCTL_BUFSIZE);
2220 
2221 	return (0);
2222 }
2223 
2224 static int
2225 xgell_debug_module_mask_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp,
2226 			    cred_t *credp)
2227 {
2228 	u32 mask;
2229 	char *end;
2230 
2231 	if (value && *value == '0' &&
2232 	    (*(value + 1) == 'x' || *(value + 1) == 'X')) {
2233 		value += 2;
2234 	}
2235 
2236 	mask = mi_strtol(value, &end, 16);
2237 	if (end == value) {
2238 		return (EINVAL);
2239 	}
2240 
2241 	xge_hal_driver_debug_module_mask_set(mask);
2242 
2243 	return (0);
2244 }
2245 
2246 static int
2247 xgell_devconfig_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
2248 {
2249 	xgelldev_t *lldev = (xgelldev_t *)(void *)cp;
2250 	xge_hal_status_e status;
2251 	int retsize;
2252 	char *buf;
2253 
2254 	buf = kmem_alloc(XGELL_DEVCONF_BUFSIZE, KM_SLEEP);
2255 	if (buf == NULL) {
2256 		return (ENOSPC);
2257 	}
2258 	status = xge_hal_aux_device_config_read(lldev->devh,
2259 						XGELL_DEVCONF_BUFSIZE,
2260 						buf, &retsize);
2261 	if (status != XGE_HAL_OK) {
2262 		kmem_free(buf, XGELL_DEVCONF_BUFSIZE);
2263 		xge_debug_ll(XGE_ERR, "device_config_read(): status %d",
2264 		    status);
2265 		return (EINVAL);
2266 	}
2267 	*(buf + retsize - 1) = '\0'; /* remove last '\n' */
2268 	(void) mi_mpprintf(mp, "%s", buf);
2269 	kmem_free(buf, XGELL_DEVCONF_BUFSIZE);
2270 
2271 	return (0);
2272 }
2273 
2274 /*
2275  * xgell_device_register
2276  * @devh: pointer on HAL device
2277  * @config: pointer on this network device configuration
2278  * @ll_out: output pointer. Will be assigned to valid LL device.
2279  *
2280  * This function will allocate and register network device
2281  */
2282 int
2283 xgell_device_register(xgelldev_t *lldev, xgell_config_t *config)
2284 {
2285 	mac_register_t *macp = NULL;
2286 	xge_hal_device_t *hldev = (xge_hal_device_t *)lldev->devh;
2287 
2288 	if (nd_load(&lldev->ndp, "pciconf", xgell_pciconf_get, NULL,
2289 	    (caddr_t)lldev) == B_FALSE)
2290 		goto xgell_ndd_fail;
2291 
2292 	if (nd_load(&lldev->ndp, "about", xgell_about_get, NULL,
2293 	    (caddr_t)lldev) == B_FALSE)
2294 		goto xgell_ndd_fail;
2295 
2296 	if (nd_load(&lldev->ndp, "stats", xgell_stats_get, NULL,
2297 	    (caddr_t)lldev) == B_FALSE)
2298 		goto xgell_ndd_fail;
2299 
2300 	if (nd_load(&lldev->ndp, "bar0", xgell_bar0_get, xgell_bar0_set,
2301 	    (caddr_t)lldev) == B_FALSE)
2302 		goto xgell_ndd_fail;
2303 
2304 	if (nd_load(&lldev->ndp, "debug_level", xgell_debug_level_get,
2305 	    xgell_debug_level_set, (caddr_t)lldev) == B_FALSE)
2306 		goto xgell_ndd_fail;
2307 
2308 	if (nd_load(&lldev->ndp, "debug_module_mask",
2309 	    xgell_debug_module_mask_get, xgell_debug_module_mask_set,
2310 	    (caddr_t)lldev) == B_FALSE)
2311 		goto xgell_ndd_fail;
2312 
2313 	if (nd_load(&lldev->ndp, "devconfig", xgell_devconfig_get, NULL,
2314 	    (caddr_t)lldev) == B_FALSE)
2315 		goto xgell_ndd_fail;
2316 
2317 	bcopy(config, &lldev->config, sizeof (xgell_config_t));
2318 
2319 	if (xgell_rx_create_buffer_pool(lldev) != DDI_SUCCESS) {
2320 		nd_free(&lldev->ndp);
2321 		xge_debug_ll(XGE_ERR, "unable to create RX buffer pool");
2322 		return (DDI_FAILURE);
2323 	}
2324 
2325 	mutex_init(&lldev->genlock, NULL, MUTEX_DRIVER, hldev->irqh);
2326 
2327 	if ((macp = mac_alloc(MAC_VERSION)) == NULL)
2328 		goto xgell_register_fail;
2329 	macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
2330 	macp->m_driver = lldev;
2331 	macp->m_dip = lldev->dev_info;
2332 	macp->m_src_addr = hldev->macaddr[0];
2333 	macp->m_callbacks = &xgell_m_callbacks;
2334 	macp->m_min_sdu = 0;
2335 	macp->m_max_sdu = hldev->config.mtu;
2336 	/*
2337 	 * Finally, we're ready to register ourselves with the Nemo
2338 	 * interface; if this succeeds, we're all ready to start()
2339 	 */
2340 
2341 	if (mac_register(macp, &lldev->mh) != 0)
2342 		goto xgell_register_fail;
2343 
2344 	/* Calculate tx_copied_max here ??? */
2345 	lldev->tx_copied_max = hldev->config.fifo.max_frags *
2346 		hldev->config.fifo.alignment_size *
2347 		hldev->config.fifo.max_aligned_frags;
2348 
2349 	xge_debug_ll(XGE_TRACE, "etherenet device %s%d registered",
2350 	    XGELL_IFNAME, lldev->instance);
2351 
2352 	return (DDI_SUCCESS);
2353 
2354 xgell_ndd_fail:
2355 	nd_free(&lldev->ndp);
2356 	xge_debug_ll(XGE_ERR, "%s", "unable to load ndd parameter");
2357 	return (DDI_FAILURE);
2358 
2359 xgell_register_fail:
2360 	if (macp != NULL)
2361 		mac_free(macp);
2362 	nd_free(&lldev->ndp);
2363 	mutex_destroy(&lldev->genlock);
2364 	/* Ignore return value, since RX not start */
2365 	(void) xgell_rx_destroy_buffer_pool(lldev);
2366 	xge_debug_ll(XGE_ERR, "%s", "unable to register networking device");
2367 	return (DDI_FAILURE);
2368 }
2369 
2370 /*
2371  * xgell_device_unregister
2372  * @devh: pointer on HAL device
2373  * @lldev: pointer to valid LL device.
2374  *
2375  * This function will unregister and free network device
2376  */
2377 int
2378 xgell_device_unregister(xgelldev_t *lldev)
2379 {
2380 	/*
2381 	 * Destroy RX buffer pool.
2382 	 */
2383 	if (xgell_rx_destroy_buffer_pool(lldev) != DDI_SUCCESS) {
2384 		return (DDI_FAILURE);
2385 	}
2386 
2387 	if (mac_unregister(lldev->mh) != 0) {
2388 		xge_debug_ll(XGE_ERR, "unable to unregister device %s%d",
2389 		    XGELL_IFNAME, lldev->instance);
2390 		return (DDI_FAILURE);
2391 	}
2392 
2393 	mutex_destroy(&lldev->genlock);
2394 
2395 	nd_free(&lldev->ndp);
2396 
2397 	xge_debug_ll(XGE_TRACE, "etherenet device %s%d unregistered",
2398 	    XGELL_IFNAME, lldev->instance);
2399 
2400 	return (DDI_SUCCESS);
2401 }
2402