xref: /onnv-gate/usr/src/uts/common/io/ixgbe/ixgbe_buf.c (revision 11486:6c9e5c271535)
16621Sbt150084 /*
26621Sbt150084  * CDDL HEADER START
36621Sbt150084  *
49353SSamuel.Tu@Sun.COM  * Copyright(c) 2007-2009 Intel Corporation. All rights reserved.
56621Sbt150084  * The contents of this file are subject to the terms of the
66621Sbt150084  * Common Development and Distribution License (the "License").
76621Sbt150084  * You may not use this file except in compliance with the License.
86621Sbt150084  *
96621Sbt150084  * You can obtain a copy of the license at:
106621Sbt150084  *      http://www.opensolaris.org/os/licensing.
116621Sbt150084  * See the License for the specific language governing permissions
126621Sbt150084  * and limitations under the License.
136621Sbt150084  *
146621Sbt150084  * When using or redistributing this file, you may do so under the
156621Sbt150084  * License only. No other modification of this header is permitted.
166621Sbt150084  *
176621Sbt150084  * If applicable, add the following below this CDDL HEADER, with the
186621Sbt150084  * fields enclosed by brackets "[]" replaced with your own identifying
196621Sbt150084  * information: Portions Copyright [yyyy] [name of copyright owner]
206621Sbt150084  *
216621Sbt150084  * CDDL HEADER END
226621Sbt150084  */
236621Sbt150084 
246621Sbt150084 /*
25*11486SZhen.W@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
269353SSamuel.Tu@Sun.COM  * Use is subject to license terms.
276621Sbt150084  */
286621Sbt150084 
296621Sbt150084 #include "ixgbe_sw.h"
306621Sbt150084 
316621Sbt150084 static int ixgbe_alloc_tbd_ring(ixgbe_tx_ring_t *);
326621Sbt150084 static void ixgbe_free_tbd_ring(ixgbe_tx_ring_t *);
3310376SChenlu.Chen@Sun.COM static int ixgbe_alloc_rbd_ring(ixgbe_rx_data_t *);
3410376SChenlu.Chen@Sun.COM static void ixgbe_free_rbd_ring(ixgbe_rx_data_t *);
356621Sbt150084 static int ixgbe_alloc_dma_buffer(ixgbe_t *, dma_buffer_t *, size_t);
366621Sbt150084 static int ixgbe_alloc_tcb_lists(ixgbe_tx_ring_t *);
376621Sbt150084 static void ixgbe_free_tcb_lists(ixgbe_tx_ring_t *);
3810376SChenlu.Chen@Sun.COM static int ixgbe_alloc_rcb_lists(ixgbe_rx_data_t *);
3910376SChenlu.Chen@Sun.COM static void ixgbe_free_rcb_lists(ixgbe_rx_data_t *);
406621Sbt150084 
416621Sbt150084 #ifdef __sparc
426621Sbt150084 #define	IXGBE_DMA_ALIGNMENT	0x0000000000002000ull
436621Sbt150084 #else
446621Sbt150084 #define	IXGBE_DMA_ALIGNMENT	0x0000000000001000ull
456621Sbt150084 #endif
466621Sbt150084 
476621Sbt150084 /*
486621Sbt150084  * DMA attributes for tx/rx descriptors.
496621Sbt150084  */
506621Sbt150084 static ddi_dma_attr_t ixgbe_desc_dma_attr = {
516621Sbt150084 	DMA_ATTR_V0,			/* version number */
526621Sbt150084 	0x0000000000000000ull,		/* low address */
536621Sbt150084 	0xFFFFFFFFFFFFFFFFull,		/* high address */
546621Sbt150084 	0x00000000FFFFFFFFull,		/* dma counter max */
556621Sbt150084 	IXGBE_DMA_ALIGNMENT,		/* alignment */
566621Sbt150084 	0x00000FFF,			/* burst sizes */
576621Sbt150084 	0x00000001,			/* minimum transfer size */
586621Sbt150084 	0x00000000FFFFFFFFull,		/* maximum transfer size */
596621Sbt150084 	0xFFFFFFFFFFFFFFFFull,		/* maximum segment size */
606621Sbt150084 	1,				/* scatter/gather list length */
616621Sbt150084 	0x00000001,			/* granularity */
626621Sbt150084 	DDI_DMA_FLAGERR			/* DMA flags */
636621Sbt150084 };
646621Sbt150084 
656621Sbt150084 /*
666621Sbt150084  * DMA attributes for tx/rx buffers.
676621Sbt150084  */
686621Sbt150084 static ddi_dma_attr_t ixgbe_buf_dma_attr = {
696621Sbt150084 	DMA_ATTR_V0,			/* version number */
706621Sbt150084 	0x0000000000000000ull,		/* low address */
716621Sbt150084 	0xFFFFFFFFFFFFFFFFull,		/* high address */
726621Sbt150084 	0x00000000FFFFFFFFull,		/* dma counter max */
736621Sbt150084 	IXGBE_DMA_ALIGNMENT,		/* alignment */
746621Sbt150084 	0x00000FFF,			/* burst sizes */
756621Sbt150084 	0x00000001,			/* minimum transfer size */
766621Sbt150084 	0x00000000FFFFFFFFull,		/* maximum transfer size */
776621Sbt150084 	0xFFFFFFFFFFFFFFFFull,		/* maximum segment size	 */
786621Sbt150084 	1,				/* scatter/gather list length */
796621Sbt150084 	0x00000001,			/* granularity */
806621Sbt150084 	DDI_DMA_FLAGERR			/* DMA flags */
816621Sbt150084 };
826621Sbt150084 
836621Sbt150084 /*
846621Sbt150084  * DMA attributes for transmit.
856621Sbt150084  */
866621Sbt150084 static ddi_dma_attr_t ixgbe_tx_dma_attr = {
876621Sbt150084 	DMA_ATTR_V0,			/* version number */
886621Sbt150084 	0x0000000000000000ull,		/* low address */
896621Sbt150084 	0xFFFFFFFFFFFFFFFFull,		/* high address */
906621Sbt150084 	0x00000000FFFFFFFFull,		/* dma counter max */
916621Sbt150084 	1,				/* alignment */
926621Sbt150084 	0x00000FFF,			/* burst sizes */
936621Sbt150084 	0x00000001,			/* minimum transfer size */
946621Sbt150084 	0x00000000FFFFFFFFull,		/* maximum transfer size */
956621Sbt150084 	0xFFFFFFFFFFFFFFFFull,		/* maximum segment size	 */
966621Sbt150084 	MAX_COOKIE,			/* scatter/gather list length */
976621Sbt150084 	0x00000001,			/* granularity */
986621Sbt150084 	DDI_DMA_FLAGERR			/* DMA flags */
996621Sbt150084 };
1006621Sbt150084 
1016621Sbt150084 /*
1026621Sbt150084  * DMA access attributes for descriptors.
1036621Sbt150084  */
1046621Sbt150084 static ddi_device_acc_attr_t ixgbe_desc_acc_attr = {
1056621Sbt150084 	DDI_DEVICE_ATTR_V0,
1066621Sbt150084 	DDI_STRUCTURE_LE_ACC,
10711236SStephen.Hanson@Sun.COM 	DDI_STRICTORDER_ACC
1086621Sbt150084 };
1096621Sbt150084 
1106621Sbt150084 /*
1116621Sbt150084  * DMA access attributes for buffers.
1126621Sbt150084  */
1136621Sbt150084 static ddi_device_acc_attr_t ixgbe_buf_acc_attr = {
1146621Sbt150084 	DDI_DEVICE_ATTR_V0,
1156621Sbt150084 	DDI_NEVERSWAP_ACC,
1166621Sbt150084 	DDI_STRICTORDER_ACC
1176621Sbt150084 };
1186621Sbt150084 
1196621Sbt150084 /*
1206621Sbt150084  * ixgbe_alloc_dma - Allocate DMA resources for all rx/tx rings.
1216621Sbt150084  */
1226621Sbt150084 int
ixgbe_alloc_dma(ixgbe_t * ixgbe)1236621Sbt150084 ixgbe_alloc_dma(ixgbe_t *ixgbe)
1246621Sbt150084 {
12510376SChenlu.Chen@Sun.COM 	ixgbe_rx_ring_t	*rx_ring;
12610376SChenlu.Chen@Sun.COM 	ixgbe_rx_data_t *rx_data;
1276621Sbt150084 	ixgbe_tx_ring_t *tx_ring;
1286621Sbt150084 	int i;
1296621Sbt150084 
1306621Sbt150084 	for (i = 0; i < ixgbe->num_rx_rings; i++) {
1316621Sbt150084 		/*
1326621Sbt150084 		 * Allocate receive desciptor ring and control block lists
1336621Sbt150084 		 */
1346621Sbt150084 		rx_ring = &ixgbe->rx_rings[i];
13510376SChenlu.Chen@Sun.COM 		rx_data = rx_ring->rx_data;
1366621Sbt150084 
13710376SChenlu.Chen@Sun.COM 		if (ixgbe_alloc_rbd_ring(rx_data) != IXGBE_SUCCESS)
1386621Sbt150084 			goto alloc_dma_failure;
1396621Sbt150084 
14010376SChenlu.Chen@Sun.COM 		if (ixgbe_alloc_rcb_lists(rx_data) != IXGBE_SUCCESS)
1416621Sbt150084 			goto alloc_dma_failure;
1426621Sbt150084 	}
1436621Sbt150084 
1446621Sbt150084 	for (i = 0; i < ixgbe->num_tx_rings; i++) {
1456621Sbt150084 		/*
1466621Sbt150084 		 * Allocate transmit desciptor ring and control block lists
1476621Sbt150084 		 */
1486621Sbt150084 		tx_ring = &ixgbe->tx_rings[i];
1496621Sbt150084 
1506621Sbt150084 		if (ixgbe_alloc_tbd_ring(tx_ring) != IXGBE_SUCCESS)
1516621Sbt150084 			goto alloc_dma_failure;
1526621Sbt150084 
1536621Sbt150084 		if (ixgbe_alloc_tcb_lists(tx_ring) != IXGBE_SUCCESS)
1546621Sbt150084 			goto alloc_dma_failure;
1556621Sbt150084 	}
1566621Sbt150084 
1576621Sbt150084 	return (IXGBE_SUCCESS);
1586621Sbt150084 
1596621Sbt150084 alloc_dma_failure:
1606621Sbt150084 	ixgbe_free_dma(ixgbe);
1616621Sbt150084 
1626621Sbt150084 	return (IXGBE_FAILURE);
1636621Sbt150084 }
1646621Sbt150084 
1656621Sbt150084 /*
1666621Sbt150084  * ixgbe_free_dma - Free all the DMA resources of all rx/tx rings.
1676621Sbt150084  */
1686621Sbt150084 void
ixgbe_free_dma(ixgbe_t * ixgbe)1696621Sbt150084 ixgbe_free_dma(ixgbe_t *ixgbe)
1706621Sbt150084 {
1716621Sbt150084 	ixgbe_rx_ring_t *rx_ring;
17210376SChenlu.Chen@Sun.COM 	ixgbe_rx_data_t *rx_data;
1736621Sbt150084 	ixgbe_tx_ring_t *tx_ring;
1746621Sbt150084 	int i;
1756621Sbt150084 
1766621Sbt150084 	/*
1776621Sbt150084 	 * Free DMA resources of rx rings
1786621Sbt150084 	 */
1796621Sbt150084 	for (i = 0; i < ixgbe->num_rx_rings; i++) {
1806621Sbt150084 		rx_ring = &ixgbe->rx_rings[i];
18110376SChenlu.Chen@Sun.COM 		rx_data = rx_ring->rx_data;
18210376SChenlu.Chen@Sun.COM 
18310376SChenlu.Chen@Sun.COM 		ixgbe_free_rbd_ring(rx_data);
18410376SChenlu.Chen@Sun.COM 		ixgbe_free_rcb_lists(rx_data);
1856621Sbt150084 	}
1866621Sbt150084 
1876621Sbt150084 	/*
1886621Sbt150084 	 * Free DMA resources of tx rings
1896621Sbt150084 	 */
1906621Sbt150084 	for (i = 0; i < ixgbe->num_tx_rings; i++) {
1916621Sbt150084 		tx_ring = &ixgbe->tx_rings[i];
1926621Sbt150084 		ixgbe_free_tbd_ring(tx_ring);
1936621Sbt150084 		ixgbe_free_tcb_lists(tx_ring);
1946621Sbt150084 	}
1956621Sbt150084 }
1966621Sbt150084 
19710376SChenlu.Chen@Sun.COM int
ixgbe_alloc_rx_ring_data(ixgbe_rx_ring_t * rx_ring)19810376SChenlu.Chen@Sun.COM ixgbe_alloc_rx_ring_data(ixgbe_rx_ring_t *rx_ring)
19910376SChenlu.Chen@Sun.COM {
20010376SChenlu.Chen@Sun.COM 	ixgbe_rx_data_t	*rx_data;
20110376SChenlu.Chen@Sun.COM 	ixgbe_t *ixgbe = rx_ring->ixgbe;
20210376SChenlu.Chen@Sun.COM 	uint32_t rcb_count;
20310376SChenlu.Chen@Sun.COM 
20410376SChenlu.Chen@Sun.COM 	/*
20510376SChenlu.Chen@Sun.COM 	 * Allocate memory for software receive rings
20610376SChenlu.Chen@Sun.COM 	 */
20710376SChenlu.Chen@Sun.COM 	rx_data = kmem_zalloc(sizeof (ixgbe_rx_data_t), KM_NOSLEEP);
20810376SChenlu.Chen@Sun.COM 
20910376SChenlu.Chen@Sun.COM 	if (rx_data == NULL) {
21010376SChenlu.Chen@Sun.COM 		ixgbe_error(ixgbe, "Allocate software receive rings failed");
21110376SChenlu.Chen@Sun.COM 		return (IXGBE_FAILURE);
21210376SChenlu.Chen@Sun.COM 	}
21310376SChenlu.Chen@Sun.COM 
21410376SChenlu.Chen@Sun.COM 	rx_data->rx_ring = rx_ring;
21510376SChenlu.Chen@Sun.COM 	mutex_init(&rx_data->recycle_lock, NULL,
21610376SChenlu.Chen@Sun.COM 	    MUTEX_DRIVER, DDI_INTR_PRI(ixgbe->intr_pri));
21710376SChenlu.Chen@Sun.COM 
21810376SChenlu.Chen@Sun.COM 	rx_data->ring_size = ixgbe->rx_ring_size;
21910376SChenlu.Chen@Sun.COM 	rx_data->free_list_size = ixgbe->rx_ring_size;
22010376SChenlu.Chen@Sun.COM 
22110376SChenlu.Chen@Sun.COM 	rx_data->rcb_head = 0;
22210376SChenlu.Chen@Sun.COM 	rx_data->rcb_tail = 0;
22310376SChenlu.Chen@Sun.COM 	rx_data->rcb_free = rx_data->free_list_size;
22410376SChenlu.Chen@Sun.COM 
22510376SChenlu.Chen@Sun.COM 	/*
22610376SChenlu.Chen@Sun.COM 	 * Allocate memory for the work list.
22710376SChenlu.Chen@Sun.COM 	 */
22810376SChenlu.Chen@Sun.COM 	rx_data->work_list = kmem_zalloc(sizeof (rx_control_block_t *) *
22910376SChenlu.Chen@Sun.COM 	    rx_data->ring_size, KM_NOSLEEP);
23010376SChenlu.Chen@Sun.COM 
23110376SChenlu.Chen@Sun.COM 	if (rx_data->work_list == NULL) {
23210376SChenlu.Chen@Sun.COM 		ixgbe_error(ixgbe,
23310376SChenlu.Chen@Sun.COM 		    "Could not allocate memory for rx work list");
23410376SChenlu.Chen@Sun.COM 		goto alloc_rx_data_failure;
23510376SChenlu.Chen@Sun.COM 	}
23610376SChenlu.Chen@Sun.COM 
23710376SChenlu.Chen@Sun.COM 	/*
23810376SChenlu.Chen@Sun.COM 	 * Allocate memory for the free list.
23910376SChenlu.Chen@Sun.COM 	 */
24010376SChenlu.Chen@Sun.COM 	rx_data->free_list = kmem_zalloc(sizeof (rx_control_block_t *) *
24110376SChenlu.Chen@Sun.COM 	    rx_data->free_list_size, KM_NOSLEEP);
24210376SChenlu.Chen@Sun.COM 
24310376SChenlu.Chen@Sun.COM 	if (rx_data->free_list == NULL) {
24410376SChenlu.Chen@Sun.COM 		ixgbe_error(ixgbe,
24510376SChenlu.Chen@Sun.COM 		    "Cound not allocate memory for rx free list");
24610376SChenlu.Chen@Sun.COM 		goto alloc_rx_data_failure;
24710376SChenlu.Chen@Sun.COM 	}
24810376SChenlu.Chen@Sun.COM 
24910376SChenlu.Chen@Sun.COM 	/*
25010376SChenlu.Chen@Sun.COM 	 * Allocate memory for the rx control blocks for work list and
25110376SChenlu.Chen@Sun.COM 	 * free list.
25210376SChenlu.Chen@Sun.COM 	 */
25310376SChenlu.Chen@Sun.COM 	rcb_count = rx_data->ring_size + rx_data->free_list_size;
25410376SChenlu.Chen@Sun.COM 	rx_data->rcb_area =
25510376SChenlu.Chen@Sun.COM 	    kmem_zalloc(sizeof (rx_control_block_t) * rcb_count,
25610376SChenlu.Chen@Sun.COM 	    KM_NOSLEEP);
25710376SChenlu.Chen@Sun.COM 
25810376SChenlu.Chen@Sun.COM 	if (rx_data->rcb_area == NULL) {
25910376SChenlu.Chen@Sun.COM 		ixgbe_error(ixgbe,
26010376SChenlu.Chen@Sun.COM 		    "Cound not allocate memory for rx control blocks");
26110376SChenlu.Chen@Sun.COM 		goto alloc_rx_data_failure;
26210376SChenlu.Chen@Sun.COM 	}
26310376SChenlu.Chen@Sun.COM 
26410376SChenlu.Chen@Sun.COM 	rx_ring->rx_data = rx_data;
26510376SChenlu.Chen@Sun.COM 	return (IXGBE_SUCCESS);
26610376SChenlu.Chen@Sun.COM 
26710376SChenlu.Chen@Sun.COM alloc_rx_data_failure:
26810376SChenlu.Chen@Sun.COM 	ixgbe_free_rx_ring_data(rx_data);
26910376SChenlu.Chen@Sun.COM 	return (IXGBE_FAILURE);
27010376SChenlu.Chen@Sun.COM }
27110376SChenlu.Chen@Sun.COM 
27210376SChenlu.Chen@Sun.COM void
ixgbe_free_rx_ring_data(ixgbe_rx_data_t * rx_data)27310376SChenlu.Chen@Sun.COM ixgbe_free_rx_ring_data(ixgbe_rx_data_t *rx_data)
27410376SChenlu.Chen@Sun.COM {
27510376SChenlu.Chen@Sun.COM 	uint32_t rcb_count;
27610376SChenlu.Chen@Sun.COM 
27710376SChenlu.Chen@Sun.COM 	if (rx_data == NULL)
27810376SChenlu.Chen@Sun.COM 		return;
27910376SChenlu.Chen@Sun.COM 
28010376SChenlu.Chen@Sun.COM 	ASSERT(rx_data->rcb_pending == 0);
28110376SChenlu.Chen@Sun.COM 
28210376SChenlu.Chen@Sun.COM 	rcb_count = rx_data->ring_size + rx_data->free_list_size;
28310376SChenlu.Chen@Sun.COM 	if (rx_data->rcb_area != NULL) {
28410376SChenlu.Chen@Sun.COM 		kmem_free(rx_data->rcb_area,
28510376SChenlu.Chen@Sun.COM 		    sizeof (rx_control_block_t) * rcb_count);
28610376SChenlu.Chen@Sun.COM 		rx_data->rcb_area = NULL;
28710376SChenlu.Chen@Sun.COM 	}
28810376SChenlu.Chen@Sun.COM 
28910376SChenlu.Chen@Sun.COM 	if (rx_data->work_list != NULL) {
29010376SChenlu.Chen@Sun.COM 		kmem_free(rx_data->work_list,
29110376SChenlu.Chen@Sun.COM 		    sizeof (rx_control_block_t *) * rx_data->ring_size);
29210376SChenlu.Chen@Sun.COM 		rx_data->work_list = NULL;
29310376SChenlu.Chen@Sun.COM 	}
29410376SChenlu.Chen@Sun.COM 
29510376SChenlu.Chen@Sun.COM 	if (rx_data->free_list != NULL) {
29610376SChenlu.Chen@Sun.COM 		kmem_free(rx_data->free_list,
29710376SChenlu.Chen@Sun.COM 		    sizeof (rx_control_block_t *) * rx_data->free_list_size);
29810376SChenlu.Chen@Sun.COM 		rx_data->free_list = NULL;
29910376SChenlu.Chen@Sun.COM 	}
30010376SChenlu.Chen@Sun.COM 
30110376SChenlu.Chen@Sun.COM 	mutex_destroy(&rx_data->recycle_lock);
30210376SChenlu.Chen@Sun.COM 	kmem_free(rx_data, sizeof (ixgbe_rx_data_t));
30310376SChenlu.Chen@Sun.COM }
30410376SChenlu.Chen@Sun.COM 
3056621Sbt150084 /*
3066621Sbt150084  * ixgbe_alloc_tbd_ring - Memory allocation for the tx descriptors of one ring.
3076621Sbt150084  */
3086621Sbt150084 static int
ixgbe_alloc_tbd_ring(ixgbe_tx_ring_t * tx_ring)3096621Sbt150084 ixgbe_alloc_tbd_ring(ixgbe_tx_ring_t *tx_ring)
3106621Sbt150084 {
3116621Sbt150084 	int ret;
3126621Sbt150084 	size_t size;
3136621Sbt150084 	size_t len;
3146621Sbt150084 	uint_t cookie_num;
3156621Sbt150084 	dev_info_t *devinfo;
3166621Sbt150084 	ddi_dma_cookie_t cookie;
3176621Sbt150084 	ixgbe_t *ixgbe = tx_ring->ixgbe;
3186621Sbt150084 
3196621Sbt150084 	devinfo = ixgbe->dip;
3206621Sbt150084 	size = sizeof (union ixgbe_adv_tx_desc) * tx_ring->ring_size;
3216621Sbt150084 
3226621Sbt150084 	/*
3236621Sbt150084 	 * If tx head write-back is enabled, an extra tbd is allocated
3246621Sbt150084 	 * to save the head write-back value
3256621Sbt150084 	 */
3266621Sbt150084 	if (ixgbe->tx_head_wb_enable) {
3276621Sbt150084 		size += sizeof (union ixgbe_adv_tx_desc);
3286621Sbt150084 	}
3296621Sbt150084 
3306621Sbt150084 	/*
3316621Sbt150084 	 * Allocate a DMA handle for the transmit descriptor
3326621Sbt150084 	 * memory area.
3336621Sbt150084 	 */
3346621Sbt150084 	ret = ddi_dma_alloc_handle(devinfo, &ixgbe_desc_dma_attr,
3356621Sbt150084 	    DDI_DMA_DONTWAIT, NULL,
3366621Sbt150084 	    &tx_ring->tbd_area.dma_handle);
3376621Sbt150084 
3386621Sbt150084 	if (ret != DDI_SUCCESS) {
3396621Sbt150084 		ixgbe_error(ixgbe,
3406621Sbt150084 		    "Could not allocate tbd dma handle: %x", ret);
3416621Sbt150084 		tx_ring->tbd_area.dma_handle = NULL;
3426621Sbt150084 
3436621Sbt150084 		return (IXGBE_FAILURE);
3446621Sbt150084 	}
3456621Sbt150084 
3466621Sbt150084 	/*
3476621Sbt150084 	 * Allocate memory to DMA data to and from the transmit
3486621Sbt150084 	 * descriptors.
3496621Sbt150084 	 */
3506621Sbt150084 	ret = ddi_dma_mem_alloc(tx_ring->tbd_area.dma_handle,
3516621Sbt150084 	    size, &ixgbe_desc_acc_attr, DDI_DMA_CONSISTENT,
3526621Sbt150084 	    DDI_DMA_DONTWAIT, NULL,
3536621Sbt150084 	    (caddr_t *)&tx_ring->tbd_area.address,
3546621Sbt150084 	    &len, &tx_ring->tbd_area.acc_handle);
3556621Sbt150084 
3566621Sbt150084 	if (ret != DDI_SUCCESS) {
3576621Sbt150084 		ixgbe_error(ixgbe,
3586621Sbt150084 		    "Could not allocate tbd dma memory: %x", ret);
3596621Sbt150084 		tx_ring->tbd_area.acc_handle = NULL;
3606621Sbt150084 		tx_ring->tbd_area.address = NULL;
3616621Sbt150084 		if (tx_ring->tbd_area.dma_handle != NULL) {
3626621Sbt150084 			ddi_dma_free_handle(&tx_ring->tbd_area.dma_handle);
3636621Sbt150084 			tx_ring->tbd_area.dma_handle = NULL;
3646621Sbt150084 		}
3656621Sbt150084 		return (IXGBE_FAILURE);
3666621Sbt150084 	}
3676621Sbt150084 
3686621Sbt150084 	/*
3696621Sbt150084 	 * Initialize the entire transmit buffer descriptor area to zero
3706621Sbt150084 	 */
3716621Sbt150084 	bzero(tx_ring->tbd_area.address, len);
3726621Sbt150084 
3736621Sbt150084 	/*
3746621Sbt150084 	 * Allocates DMA resources for the memory that was allocated by
3756621Sbt150084 	 * the ddi_dma_mem_alloc call. The DMA resources then get bound to the
3766621Sbt150084 	 * the memory address
3776621Sbt150084 	 */
3786621Sbt150084 	ret = ddi_dma_addr_bind_handle(tx_ring->tbd_area.dma_handle,
3796621Sbt150084 	    NULL, (caddr_t)tx_ring->tbd_area.address,
3806621Sbt150084 	    len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
3816621Sbt150084 	    DDI_DMA_DONTWAIT, NULL, &cookie, &cookie_num);
3826621Sbt150084 
3836621Sbt150084 	if (ret != DDI_DMA_MAPPED) {
3846621Sbt150084 		ixgbe_error(ixgbe,
3856621Sbt150084 		    "Could not bind tbd dma resource: %x", ret);
3866621Sbt150084 		tx_ring->tbd_area.dma_address = NULL;
3876621Sbt150084 		if (tx_ring->tbd_area.acc_handle != NULL) {
3886621Sbt150084 			ddi_dma_mem_free(&tx_ring->tbd_area.acc_handle);
3896621Sbt150084 			tx_ring->tbd_area.acc_handle = NULL;
3906621Sbt150084 			tx_ring->tbd_area.address = NULL;
3916621Sbt150084 		}
3926621Sbt150084 		if (tx_ring->tbd_area.dma_handle != NULL) {
3936621Sbt150084 			ddi_dma_free_handle(&tx_ring->tbd_area.dma_handle);
3946621Sbt150084 			tx_ring->tbd_area.dma_handle = NULL;
3956621Sbt150084 		}
3966621Sbt150084 		return (IXGBE_FAILURE);
3976621Sbt150084 	}
3986621Sbt150084 
3996621Sbt150084 	ASSERT(cookie_num == 1);
4006621Sbt150084 
4016621Sbt150084 	tx_ring->tbd_area.dma_address = cookie.dmac_laddress;
4026621Sbt150084 	tx_ring->tbd_area.size = len;
4036621Sbt150084 
4046621Sbt150084 	tx_ring->tbd_ring = (union ixgbe_adv_tx_desc *)(uintptr_t)
4056621Sbt150084 	    tx_ring->tbd_area.address;
4066621Sbt150084 
4076621Sbt150084 	return (IXGBE_SUCCESS);
4086621Sbt150084 }
4096621Sbt150084 
4106621Sbt150084 /*
4116621Sbt150084  * ixgbe_free_tbd_ring - Free the tx descriptors of one ring.
4126621Sbt150084  */
4136621Sbt150084 static void
ixgbe_free_tbd_ring(ixgbe_tx_ring_t * tx_ring)4146621Sbt150084 ixgbe_free_tbd_ring(ixgbe_tx_ring_t *tx_ring)
4156621Sbt150084 {
4166621Sbt150084 	if (tx_ring->tbd_area.dma_handle != NULL) {
4176621Sbt150084 		(void) ddi_dma_unbind_handle(tx_ring->tbd_area.dma_handle);
4186621Sbt150084 	}
4196621Sbt150084 	if (tx_ring->tbd_area.acc_handle != NULL) {
4206621Sbt150084 		ddi_dma_mem_free(&tx_ring->tbd_area.acc_handle);
4216621Sbt150084 		tx_ring->tbd_area.acc_handle = NULL;
4226621Sbt150084 	}
4236621Sbt150084 	if (tx_ring->tbd_area.dma_handle != NULL) {
4246621Sbt150084 		ddi_dma_free_handle(&tx_ring->tbd_area.dma_handle);
4256621Sbt150084 		tx_ring->tbd_area.dma_handle = NULL;
4266621Sbt150084 	}
4276621Sbt150084 	tx_ring->tbd_area.address = NULL;
4286621Sbt150084 	tx_ring->tbd_area.dma_address = NULL;
4296621Sbt150084 	tx_ring->tbd_area.size = 0;
4306621Sbt150084 
4316621Sbt150084 	tx_ring->tbd_ring = NULL;
4326621Sbt150084 }
4336621Sbt150084 
4346621Sbt150084 /*
4356621Sbt150084  * ixgbe_alloc_rbd_ring - Memory allocation for the rx descriptors of one ring.
4366621Sbt150084  */
4376621Sbt150084 static int
ixgbe_alloc_rbd_ring(ixgbe_rx_data_t * rx_data)43810376SChenlu.Chen@Sun.COM ixgbe_alloc_rbd_ring(ixgbe_rx_data_t *rx_data)
4396621Sbt150084 {
4406621Sbt150084 	int ret;
4416621Sbt150084 	size_t size;
4426621Sbt150084 	size_t len;
4436621Sbt150084 	uint_t cookie_num;
4446621Sbt150084 	dev_info_t *devinfo;
4456621Sbt150084 	ddi_dma_cookie_t cookie;
44610376SChenlu.Chen@Sun.COM 	ixgbe_t *ixgbe = rx_data->rx_ring->ixgbe;
4476621Sbt150084 
4486621Sbt150084 	devinfo = ixgbe->dip;
44910376SChenlu.Chen@Sun.COM 	size = sizeof (union ixgbe_adv_rx_desc) * rx_data->ring_size;
4506621Sbt150084 
4516621Sbt150084 	/*
4526621Sbt150084 	 * Allocate a new DMA handle for the receive descriptor
4536621Sbt150084 	 * memory area.
4546621Sbt150084 	 */
4556621Sbt150084 	ret = ddi_dma_alloc_handle(devinfo, &ixgbe_desc_dma_attr,
4566621Sbt150084 	    DDI_DMA_DONTWAIT, NULL,
45710376SChenlu.Chen@Sun.COM 	    &rx_data->rbd_area.dma_handle);
4586621Sbt150084 
4596621Sbt150084 	if (ret != DDI_SUCCESS) {
4606621Sbt150084 		ixgbe_error(ixgbe,
4616621Sbt150084 		    "Could not allocate rbd dma handle: %x", ret);
46210376SChenlu.Chen@Sun.COM 		rx_data->rbd_area.dma_handle = NULL;
4636621Sbt150084 		return (IXGBE_FAILURE);
4646621Sbt150084 	}
4656621Sbt150084 
4666621Sbt150084 	/*
4676621Sbt150084 	 * Allocate memory to DMA data to and from the receive
4686621Sbt150084 	 * descriptors.
4696621Sbt150084 	 */
47010376SChenlu.Chen@Sun.COM 	ret = ddi_dma_mem_alloc(rx_data->rbd_area.dma_handle,
4716621Sbt150084 	    size, &ixgbe_desc_acc_attr, DDI_DMA_CONSISTENT,
4726621Sbt150084 	    DDI_DMA_DONTWAIT, NULL,
47310376SChenlu.Chen@Sun.COM 	    (caddr_t *)&rx_data->rbd_area.address,
47410376SChenlu.Chen@Sun.COM 	    &len, &rx_data->rbd_area.acc_handle);
4756621Sbt150084 
4766621Sbt150084 	if (ret != DDI_SUCCESS) {
4776621Sbt150084 		ixgbe_error(ixgbe,
4786621Sbt150084 		    "Could not allocate rbd dma memory: %x", ret);
47910376SChenlu.Chen@Sun.COM 		rx_data->rbd_area.acc_handle = NULL;
48010376SChenlu.Chen@Sun.COM 		rx_data->rbd_area.address = NULL;
48110376SChenlu.Chen@Sun.COM 		if (rx_data->rbd_area.dma_handle != NULL) {
48210376SChenlu.Chen@Sun.COM 			ddi_dma_free_handle(&rx_data->rbd_area.dma_handle);
48310376SChenlu.Chen@Sun.COM 			rx_data->rbd_area.dma_handle = NULL;
4846621Sbt150084 		}
4856621Sbt150084 		return (IXGBE_FAILURE);
4866621Sbt150084 	}
4876621Sbt150084 
4886621Sbt150084 	/*
4896621Sbt150084 	 * Initialize the entire transmit buffer descriptor area to zero
4906621Sbt150084 	 */
49110376SChenlu.Chen@Sun.COM 	bzero(rx_data->rbd_area.address, len);
4926621Sbt150084 
4936621Sbt150084 	/*
4946621Sbt150084 	 * Allocates DMA resources for the memory that was allocated by
4956621Sbt150084 	 * the ddi_dma_mem_alloc call.
4966621Sbt150084 	 */
49710376SChenlu.Chen@Sun.COM 	ret = ddi_dma_addr_bind_handle(rx_data->rbd_area.dma_handle,
49810376SChenlu.Chen@Sun.COM 	    NULL, (caddr_t)rx_data->rbd_area.address,
4996621Sbt150084 	    len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
5006621Sbt150084 	    DDI_DMA_DONTWAIT, NULL, &cookie, &cookie_num);
5016621Sbt150084 
5026621Sbt150084 	if (ret != DDI_DMA_MAPPED) {
5036621Sbt150084 		ixgbe_error(ixgbe,
5046621Sbt150084 		    "Could not bind rbd dma resource: %x", ret);
50510376SChenlu.Chen@Sun.COM 		rx_data->rbd_area.dma_address = NULL;
50610376SChenlu.Chen@Sun.COM 		if (rx_data->rbd_area.acc_handle != NULL) {
50710376SChenlu.Chen@Sun.COM 			ddi_dma_mem_free(&rx_data->rbd_area.acc_handle);
50810376SChenlu.Chen@Sun.COM 			rx_data->rbd_area.acc_handle = NULL;
50910376SChenlu.Chen@Sun.COM 			rx_data->rbd_area.address = NULL;
5106621Sbt150084 		}
51110376SChenlu.Chen@Sun.COM 		if (rx_data->rbd_area.dma_handle != NULL) {
51210376SChenlu.Chen@Sun.COM 			ddi_dma_free_handle(&rx_data->rbd_area.dma_handle);
51310376SChenlu.Chen@Sun.COM 			rx_data->rbd_area.dma_handle = NULL;
5146621Sbt150084 		}
5156621Sbt150084 		return (IXGBE_FAILURE);
5166621Sbt150084 	}
5176621Sbt150084 
5186621Sbt150084 	ASSERT(cookie_num == 1);
5196621Sbt150084 
52010376SChenlu.Chen@Sun.COM 	rx_data->rbd_area.dma_address = cookie.dmac_laddress;
52110376SChenlu.Chen@Sun.COM 	rx_data->rbd_area.size = len;
5226621Sbt150084 
52310376SChenlu.Chen@Sun.COM 	rx_data->rbd_ring = (union ixgbe_adv_rx_desc *)(uintptr_t)
52410376SChenlu.Chen@Sun.COM 	    rx_data->rbd_area.address;
5256621Sbt150084 
5266621Sbt150084 	return (IXGBE_SUCCESS);
5276621Sbt150084 }
5286621Sbt150084 
5296621Sbt150084 /*
5306621Sbt150084  * ixgbe_free_rbd_ring - Free the rx descriptors of one ring.
5316621Sbt150084  */
5326621Sbt150084 static void
ixgbe_free_rbd_ring(ixgbe_rx_data_t * rx_data)53310376SChenlu.Chen@Sun.COM ixgbe_free_rbd_ring(ixgbe_rx_data_t *rx_data)
5346621Sbt150084 {
53510376SChenlu.Chen@Sun.COM 	if (rx_data->rbd_area.dma_handle != NULL) {
53610376SChenlu.Chen@Sun.COM 		(void) ddi_dma_unbind_handle(rx_data->rbd_area.dma_handle);
5376621Sbt150084 	}
53810376SChenlu.Chen@Sun.COM 	if (rx_data->rbd_area.acc_handle != NULL) {
53910376SChenlu.Chen@Sun.COM 		ddi_dma_mem_free(&rx_data->rbd_area.acc_handle);
54010376SChenlu.Chen@Sun.COM 		rx_data->rbd_area.acc_handle = NULL;
5416621Sbt150084 	}
54210376SChenlu.Chen@Sun.COM 	if (rx_data->rbd_area.dma_handle != NULL) {
54310376SChenlu.Chen@Sun.COM 		ddi_dma_free_handle(&rx_data->rbd_area.dma_handle);
54410376SChenlu.Chen@Sun.COM 		rx_data->rbd_area.dma_handle = NULL;
5456621Sbt150084 	}
54610376SChenlu.Chen@Sun.COM 	rx_data->rbd_area.address = NULL;
54710376SChenlu.Chen@Sun.COM 	rx_data->rbd_area.dma_address = NULL;
54810376SChenlu.Chen@Sun.COM 	rx_data->rbd_area.size = 0;
5496621Sbt150084 
55010376SChenlu.Chen@Sun.COM 	rx_data->rbd_ring = NULL;
5516621Sbt150084 }
5526621Sbt150084 
5536621Sbt150084 /*
5546621Sbt150084  * ixgbe_alloc_dma_buffer - Allocate DMA resources for a DMA buffer.
5556621Sbt150084  */
5566621Sbt150084 static int
ixgbe_alloc_dma_buffer(ixgbe_t * ixgbe,dma_buffer_t * buf,size_t size)5576621Sbt150084 ixgbe_alloc_dma_buffer(ixgbe_t *ixgbe, dma_buffer_t *buf, size_t size)
5586621Sbt150084 {
5596621Sbt150084 	int ret;
5606621Sbt150084 	dev_info_t *devinfo = ixgbe->dip;
5616621Sbt150084 	ddi_dma_cookie_t cookie;
5626621Sbt150084 	size_t len;
5636621Sbt150084 	uint_t cookie_num;
5646621Sbt150084 
5656621Sbt150084 	ret = ddi_dma_alloc_handle(devinfo,
5666621Sbt150084 	    &ixgbe_buf_dma_attr, DDI_DMA_DONTWAIT,
5676621Sbt150084 	    NULL, &buf->dma_handle);
5686621Sbt150084 
5696621Sbt150084 	if (ret != DDI_SUCCESS) {
5706621Sbt150084 		buf->dma_handle = NULL;
5716621Sbt150084 		ixgbe_error(ixgbe,
5726621Sbt150084 		    "Could not allocate dma buffer handle: %x", ret);
5736621Sbt150084 		return (IXGBE_FAILURE);
5746621Sbt150084 	}
5756621Sbt150084 
5766621Sbt150084 	ret = ddi_dma_mem_alloc(buf->dma_handle,
5776621Sbt150084 	    size, &ixgbe_buf_acc_attr, DDI_DMA_STREAMING,
5786621Sbt150084 	    DDI_DMA_DONTWAIT, NULL, &buf->address,
5796621Sbt150084 	    &len, &buf->acc_handle);
5806621Sbt150084 
5816621Sbt150084 	if (ret != DDI_SUCCESS) {
5826621Sbt150084 		buf->acc_handle = NULL;
5836621Sbt150084 		buf->address = NULL;
5846621Sbt150084 		if (buf->dma_handle != NULL) {
5856621Sbt150084 			ddi_dma_free_handle(&buf->dma_handle);
5866621Sbt150084 			buf->dma_handle = NULL;
5876621Sbt150084 		}
5886621Sbt150084 		ixgbe_error(ixgbe,
5896621Sbt150084 		    "Could not allocate dma buffer memory: %x", ret);
5906621Sbt150084 		return (IXGBE_FAILURE);
5916621Sbt150084 	}
5926621Sbt150084 
5936621Sbt150084 	ret = ddi_dma_addr_bind_handle(buf->dma_handle, NULL,
5946621Sbt150084 	    buf->address,
5956621Sbt150084 	    len, DDI_DMA_RDWR | DDI_DMA_STREAMING,
5966621Sbt150084 	    DDI_DMA_DONTWAIT, NULL, &cookie, &cookie_num);
5976621Sbt150084 
5986621Sbt150084 	if (ret != DDI_DMA_MAPPED) {
5996621Sbt150084 		buf->dma_address = NULL;
6006621Sbt150084 		if (buf->acc_handle != NULL) {
6016621Sbt150084 			ddi_dma_mem_free(&buf->acc_handle);
6026621Sbt150084 			buf->acc_handle = NULL;
6036621Sbt150084 			buf->address = NULL;
6046621Sbt150084 		}
6056621Sbt150084 		if (buf->dma_handle != NULL) {
6066621Sbt150084 			ddi_dma_free_handle(&buf->dma_handle);
6076621Sbt150084 			buf->dma_handle = NULL;
6086621Sbt150084 		}
6096621Sbt150084 		ixgbe_error(ixgbe,
6106621Sbt150084 		    "Could not bind dma buffer handle: %x", ret);
6116621Sbt150084 		return (IXGBE_FAILURE);
6126621Sbt150084 	}
6136621Sbt150084 
6146621Sbt150084 	ASSERT(cookie_num == 1);
6156621Sbt150084 
6166621Sbt150084 	buf->dma_address = cookie.dmac_laddress;
6176621Sbt150084 	buf->size = len;
6186621Sbt150084 	buf->len = 0;
6196621Sbt150084 
6206621Sbt150084 	return (IXGBE_SUCCESS);
6216621Sbt150084 }
6226621Sbt150084 
6236621Sbt150084 /*
6246621Sbt150084  * ixgbe_free_dma_buffer - Free one allocated area of dma memory and handle.
6256621Sbt150084  */
62610376SChenlu.Chen@Sun.COM void
ixgbe_free_dma_buffer(dma_buffer_t * buf)6276621Sbt150084 ixgbe_free_dma_buffer(dma_buffer_t *buf)
6286621Sbt150084 {
6296621Sbt150084 	if (buf->dma_handle != NULL) {
6306621Sbt150084 		(void) ddi_dma_unbind_handle(buf->dma_handle);
6316621Sbt150084 		buf->dma_address = NULL;
6326621Sbt150084 	} else {
6336621Sbt150084 		return;
6346621Sbt150084 	}
6356621Sbt150084 
6366621Sbt150084 	if (buf->acc_handle != NULL) {
6376621Sbt150084 		ddi_dma_mem_free(&buf->acc_handle);
6386621Sbt150084 		buf->acc_handle = NULL;
6396621Sbt150084 		buf->address = NULL;
6406621Sbt150084 	}
6416621Sbt150084 
6426621Sbt150084 	if (buf->dma_handle != NULL) {
6436621Sbt150084 		ddi_dma_free_handle(&buf->dma_handle);
6446621Sbt150084 		buf->dma_handle = NULL;
6456621Sbt150084 	}
6466621Sbt150084 
6476621Sbt150084 	buf->size = 0;
6486621Sbt150084 	buf->len = 0;
6496621Sbt150084 }
6506621Sbt150084 
6516621Sbt150084 /*
6526621Sbt150084  * ixgbe_alloc_tcb_lists - Memory allocation for the transmit control bolcks
6536621Sbt150084  * of one ring.
6546621Sbt150084  */
6556621Sbt150084 static int
ixgbe_alloc_tcb_lists(ixgbe_tx_ring_t * tx_ring)6566621Sbt150084 ixgbe_alloc_tcb_lists(ixgbe_tx_ring_t *tx_ring)
6576621Sbt150084 {
6586621Sbt150084 	int i;
6596621Sbt150084 	int ret;
6606621Sbt150084 	tx_control_block_t *tcb;
6616621Sbt150084 	dma_buffer_t *tx_buf;
6626621Sbt150084 	ixgbe_t *ixgbe = tx_ring->ixgbe;
6636621Sbt150084 	dev_info_t *devinfo = ixgbe->dip;
6646621Sbt150084 
6656621Sbt150084 	/*
6666621Sbt150084 	 * Allocate memory for the work list.
6676621Sbt150084 	 */
6686621Sbt150084 	tx_ring->work_list = kmem_zalloc(sizeof (tx_control_block_t *) *
6696621Sbt150084 	    tx_ring->ring_size, KM_NOSLEEP);
6706621Sbt150084 
6716621Sbt150084 	if (tx_ring->work_list == NULL) {
6726621Sbt150084 		ixgbe_error(ixgbe,
6736621Sbt150084 		    "Cound not allocate memory for tx work list");
6746621Sbt150084 		return (IXGBE_FAILURE);
6756621Sbt150084 	}
6766621Sbt150084 
6776621Sbt150084 	/*
6786621Sbt150084 	 * Allocate memory for the free list.
6796621Sbt150084 	 */
6806621Sbt150084 	tx_ring->free_list = kmem_zalloc(sizeof (tx_control_block_t *) *
6816621Sbt150084 	    tx_ring->free_list_size, KM_NOSLEEP);
6826621Sbt150084 
6836621Sbt150084 	if (tx_ring->free_list == NULL) {
6846621Sbt150084 		kmem_free(tx_ring->work_list,
6856621Sbt150084 		    sizeof (tx_control_block_t *) * tx_ring->ring_size);
6866621Sbt150084 		tx_ring->work_list = NULL;
6876621Sbt150084 
6886621Sbt150084 		ixgbe_error(ixgbe,
6896621Sbt150084 		    "Cound not allocate memory for tx free list");
6906621Sbt150084 		return (IXGBE_FAILURE);
6916621Sbt150084 	}
6926621Sbt150084 
6936621Sbt150084 	/*
6946621Sbt150084 	 * Allocate memory for the tx control blocks of free list.
6956621Sbt150084 	 */
6966621Sbt150084 	tx_ring->tcb_area =
6976621Sbt150084 	    kmem_zalloc(sizeof (tx_control_block_t) *
6986621Sbt150084 	    tx_ring->free_list_size, KM_NOSLEEP);
6996621Sbt150084 
7006621Sbt150084 	if (tx_ring->tcb_area == NULL) {
7016621Sbt150084 		kmem_free(tx_ring->work_list,
7026621Sbt150084 		    sizeof (tx_control_block_t *) * tx_ring->ring_size);
7036621Sbt150084 		tx_ring->work_list = NULL;
7046621Sbt150084 
7056621Sbt150084 		kmem_free(tx_ring->free_list,
7066621Sbt150084 		    sizeof (tx_control_block_t *) * tx_ring->free_list_size);
7076621Sbt150084 		tx_ring->free_list = NULL;
7086621Sbt150084 
7096621Sbt150084 		ixgbe_error(ixgbe,
7106621Sbt150084 		    "Cound not allocate memory for tx control blocks");
7116621Sbt150084 		return (IXGBE_FAILURE);
7126621Sbt150084 	}
7136621Sbt150084 
7146621Sbt150084 	/*
7156621Sbt150084 	 * Allocate dma memory for the tx control block of free list.
7166621Sbt150084 	 */
7176621Sbt150084 	tcb = tx_ring->tcb_area;
7186621Sbt150084 	for (i = 0; i < tx_ring->free_list_size; i++, tcb++) {
7196621Sbt150084 		ASSERT(tcb != NULL);
7206621Sbt150084 
7216621Sbt150084 		tx_ring->free_list[i] = tcb;
7226621Sbt150084 
7236621Sbt150084 		/*
7246621Sbt150084 		 * Pre-allocate dma handles for transmit. These dma handles
7256621Sbt150084 		 * will be dynamically bound to the data buffers passed down
7266621Sbt150084 		 * from the upper layers at the time of transmitting.
7276621Sbt150084 		 */
7286621Sbt150084 		ret = ddi_dma_alloc_handle(devinfo,
7296621Sbt150084 		    &ixgbe_tx_dma_attr,
7306621Sbt150084 		    DDI_DMA_DONTWAIT, NULL,
7316621Sbt150084 		    &tcb->tx_dma_handle);
7326621Sbt150084 		if (ret != DDI_SUCCESS) {
7336621Sbt150084 			tcb->tx_dma_handle = NULL;
7346621Sbt150084 			ixgbe_error(ixgbe,
7356621Sbt150084 			    "Could not allocate tx dma handle: %x", ret);
7366621Sbt150084 			goto alloc_tcb_lists_fail;
7376621Sbt150084 		}
7386621Sbt150084 
7396621Sbt150084 		/*
7406621Sbt150084 		 * Pre-allocate transmit buffers for packets that the
7416621Sbt150084 		 * size is less than bcopy_thresh.
7426621Sbt150084 		 */
7436621Sbt150084 		tx_buf = &tcb->tx_buf;
7446621Sbt150084 
7456621Sbt150084 		ret = ixgbe_alloc_dma_buffer(ixgbe,
7466621Sbt150084 		    tx_buf, ixgbe->tx_buf_size);
7476621Sbt150084 
7486621Sbt150084 		if (ret != IXGBE_SUCCESS) {
7496621Sbt150084 			ASSERT(tcb->tx_dma_handle != NULL);
7506621Sbt150084 			ddi_dma_free_handle(&tcb->tx_dma_handle);
7516621Sbt150084 			tcb->tx_dma_handle = NULL;
7526621Sbt150084 			ixgbe_error(ixgbe, "Allocate tx dma buffer failed");
7536621Sbt150084 			goto alloc_tcb_lists_fail;
7546621Sbt150084 		}
7559681SPaul.Guo@Sun.COM 
7569681SPaul.Guo@Sun.COM 		tcb->last_index = MAX_TX_RING_SIZE;
7576621Sbt150084 	}
7586621Sbt150084 
7596621Sbt150084 	return (IXGBE_SUCCESS);
7606621Sbt150084 
7616621Sbt150084 alloc_tcb_lists_fail:
7626621Sbt150084 	ixgbe_free_tcb_lists(tx_ring);
7636621Sbt150084 
7646621Sbt150084 	return (IXGBE_FAILURE);
7656621Sbt150084 }
7666621Sbt150084 
7676621Sbt150084 /*
7686621Sbt150084  * ixgbe_free_tcb_lists - Release the memory allocated for
7696621Sbt150084  * the transmit control bolcks of one ring.
7706621Sbt150084  */
7716621Sbt150084 static void
ixgbe_free_tcb_lists(ixgbe_tx_ring_t * tx_ring)7726621Sbt150084 ixgbe_free_tcb_lists(ixgbe_tx_ring_t *tx_ring)
7736621Sbt150084 {
7746621Sbt150084 	int i;
7756621Sbt150084 	tx_control_block_t *tcb;
7766621Sbt150084 
7776621Sbt150084 	tcb = tx_ring->tcb_area;
7786621Sbt150084 	if (tcb == NULL)
7796621Sbt150084 		return;
7806621Sbt150084 
7816621Sbt150084 	for (i = 0; i < tx_ring->free_list_size; i++, tcb++) {
7826621Sbt150084 		ASSERT(tcb != NULL);
7836621Sbt150084 
7846621Sbt150084 		/* Free the tx dma handle for dynamical binding */
7856621Sbt150084 		if (tcb->tx_dma_handle != NULL) {
7866621Sbt150084 			ddi_dma_free_handle(&tcb->tx_dma_handle);
7876621Sbt150084 			tcb->tx_dma_handle = NULL;
7886621Sbt150084 		} else {
7896621Sbt150084 			/*
7906621Sbt150084 			 * If the dma handle is NULL, then we don't
7916621Sbt150084 			 * have to check the remaining.
7926621Sbt150084 			 */
7936621Sbt150084 			break;
7946621Sbt150084 		}
7956621Sbt150084 
7966621Sbt150084 		ixgbe_free_dma_buffer(&tcb->tx_buf);
7976621Sbt150084 	}
7986621Sbt150084 
7996621Sbt150084 	if (tx_ring->tcb_area != NULL) {
8006621Sbt150084 		kmem_free(tx_ring->tcb_area,
8016621Sbt150084 		    sizeof (tx_control_block_t) * tx_ring->free_list_size);
8026621Sbt150084 		tx_ring->tcb_area = NULL;
8036621Sbt150084 	}
8046621Sbt150084 
8056621Sbt150084 	if (tx_ring->work_list != NULL) {
8066621Sbt150084 		kmem_free(tx_ring->work_list,
8076621Sbt150084 		    sizeof (tx_control_block_t *) * tx_ring->ring_size);
8086621Sbt150084 		tx_ring->work_list = NULL;
8096621Sbt150084 	}
8106621Sbt150084 
8116621Sbt150084 	if (tx_ring->free_list != NULL) {
8126621Sbt150084 		kmem_free(tx_ring->free_list,
8136621Sbt150084 		    sizeof (tx_control_block_t *) * tx_ring->free_list_size);
8146621Sbt150084 		tx_ring->free_list = NULL;
8156621Sbt150084 	}
8166621Sbt150084 }
8176621Sbt150084 
8186621Sbt150084 /*
8196621Sbt150084  * ixgbe_alloc_rcb_lists - Memory allocation for the receive control blocks
8206621Sbt150084  * of one ring.
8216621Sbt150084  */
8226621Sbt150084 static int
ixgbe_alloc_rcb_lists(ixgbe_rx_data_t * rx_data)82310376SChenlu.Chen@Sun.COM ixgbe_alloc_rcb_lists(ixgbe_rx_data_t *rx_data)
8246621Sbt150084 {
8256621Sbt150084 	int i;
8266621Sbt150084 	int ret;
8276621Sbt150084 	rx_control_block_t *rcb;
82810376SChenlu.Chen@Sun.COM 	ixgbe_t *ixgbe = rx_data->rx_ring->ixgbe;
8296621Sbt150084 	dma_buffer_t *rx_buf;
8306621Sbt150084 	uint32_t rcb_count;
8316621Sbt150084 
8326621Sbt150084 	/*
8336621Sbt150084 	 * Allocate memory for the rx control blocks for work list and
8346621Sbt150084 	 * free list.
8356621Sbt150084 	 */
83610376SChenlu.Chen@Sun.COM 	rcb_count = rx_data->ring_size + rx_data->free_list_size;
83710376SChenlu.Chen@Sun.COM 	rcb = rx_data->rcb_area;
8386621Sbt150084 
8396621Sbt150084 	for (i = 0; i < rcb_count; i++, rcb++) {
8406621Sbt150084 		ASSERT(rcb != NULL);
8416621Sbt150084 
84210376SChenlu.Chen@Sun.COM 		if (i < rx_data->ring_size) {
8436621Sbt150084 			/* Attach the rx control block to the work list */
84410376SChenlu.Chen@Sun.COM 			rx_data->work_list[i] = rcb;
8456621Sbt150084 		} else {
8466621Sbt150084 			/* Attach the rx control block to the free list */
84710376SChenlu.Chen@Sun.COM 			rx_data->free_list[i - rx_data->ring_size] = rcb;
8486621Sbt150084 		}
8496621Sbt150084 
8506621Sbt150084 		rx_buf = &rcb->rx_buf;
8516621Sbt150084 		ret = ixgbe_alloc_dma_buffer(ixgbe,
8526621Sbt150084 		    rx_buf, ixgbe->rx_buf_size);
8536621Sbt150084 
8546621Sbt150084 		if (ret != IXGBE_SUCCESS) {
8556621Sbt150084 			ixgbe_error(ixgbe, "Allocate rx dma buffer failed");
8566621Sbt150084 			goto alloc_rcb_lists_fail;
8576621Sbt150084 		}
8586621Sbt150084 
8596621Sbt150084 		rx_buf->size -= IPHDR_ALIGN_ROOM;
8606621Sbt150084 		rx_buf->address += IPHDR_ALIGN_ROOM;
8616621Sbt150084 		rx_buf->dma_address += IPHDR_ALIGN_ROOM;
8626621Sbt150084 
86310376SChenlu.Chen@Sun.COM 		rcb->ref_cnt = 1;
86410376SChenlu.Chen@Sun.COM 		rcb->rx_data = (ixgbe_rx_data_t *)rx_data;
8656621Sbt150084 		rcb->free_rtn.free_func = ixgbe_rx_recycle;
8666621Sbt150084 		rcb->free_rtn.free_arg = (char *)rcb;
867*11486SZhen.W@Sun.COM 		rcb->lro_prev = -1;
868*11486SZhen.W@Sun.COM 		rcb->lro_next = -1;
869*11486SZhen.W@Sun.COM 		rcb->lro_pkt = B_FALSE;
8706621Sbt150084 		rcb->mp = desballoc((unsigned char *)
8719353SSamuel.Tu@Sun.COM 		    rx_buf->address,
8729353SSamuel.Tu@Sun.COM 		    rx_buf->size,
8736621Sbt150084 		    0, &rcb->free_rtn);
8746621Sbt150084 	}
8756621Sbt150084 
8766621Sbt150084 	return (IXGBE_SUCCESS);
8776621Sbt150084 
8786621Sbt150084 alloc_rcb_lists_fail:
87910376SChenlu.Chen@Sun.COM 	ixgbe_free_rcb_lists(rx_data);
8806621Sbt150084 
8816621Sbt150084 	return (IXGBE_FAILURE);
8826621Sbt150084 }
8836621Sbt150084 
8846621Sbt150084 /*
8856621Sbt150084  * ixgbe_free_rcb_lists - Free the receive control blocks of one ring.
8866621Sbt150084  */
8876621Sbt150084 static void
ixgbe_free_rcb_lists(ixgbe_rx_data_t * rx_data)88810376SChenlu.Chen@Sun.COM ixgbe_free_rcb_lists(ixgbe_rx_data_t *rx_data)
8896621Sbt150084 {
89010376SChenlu.Chen@Sun.COM 	ixgbe_t *ixgbe;
8916621Sbt150084 	rx_control_block_t *rcb;
8926621Sbt150084 	uint32_t rcb_count;
89310376SChenlu.Chen@Sun.COM 	uint32_t ref_cnt;
89410376SChenlu.Chen@Sun.COM 	int i;
8956621Sbt150084 
89610376SChenlu.Chen@Sun.COM 	ixgbe = rx_data->rx_ring->ixgbe;
89710376SChenlu.Chen@Sun.COM 
89810376SChenlu.Chen@Sun.COM 	mutex_enter(&ixgbe->rx_pending_lock);
8996621Sbt150084 
90010376SChenlu.Chen@Sun.COM 	rcb = rx_data->rcb_area;
90110376SChenlu.Chen@Sun.COM 	rcb_count = rx_data->ring_size + rx_data->free_list_size;
90210376SChenlu.Chen@Sun.COM 
9036621Sbt150084 	for (i = 0; i < rcb_count; i++, rcb++) {
9046621Sbt150084 		ASSERT(rcb != NULL);
9056621Sbt150084 
90610376SChenlu.Chen@Sun.COM 		ref_cnt = atomic_dec_32_nv(&rcb->ref_cnt);
90710376SChenlu.Chen@Sun.COM 		if (ref_cnt == 0) {
90810376SChenlu.Chen@Sun.COM 			if (rcb->mp != NULL) {
90910376SChenlu.Chen@Sun.COM 				freemsg(rcb->mp);
91010376SChenlu.Chen@Sun.COM 				rcb->mp = NULL;
91110376SChenlu.Chen@Sun.COM 			}
91210376SChenlu.Chen@Sun.COM 			ixgbe_free_dma_buffer(&rcb->rx_buf);
91310376SChenlu.Chen@Sun.COM 		} else {
91410376SChenlu.Chen@Sun.COM 			atomic_inc_32(&rx_data->rcb_pending);
91510376SChenlu.Chen@Sun.COM 			atomic_inc_32(&ixgbe->rcb_pending);
9166621Sbt150084 		}
9176621Sbt150084 	}
9186621Sbt150084 
91910376SChenlu.Chen@Sun.COM 	mutex_exit(&ixgbe->rx_pending_lock);
9206621Sbt150084 }
9216621Sbt150084 
9226621Sbt150084 /*
9236621Sbt150084  * ixgbe_set_fma_flags - Set the attribute for fma support.
9246621Sbt150084  */
9256621Sbt150084 void
ixgbe_set_fma_flags(int dma_flag)92611236SStephen.Hanson@Sun.COM ixgbe_set_fma_flags(int dma_flag)
9276621Sbt150084 {
9286621Sbt150084 	if (dma_flag) {
9296621Sbt150084 		ixgbe_tx_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR;
9306621Sbt150084 		ixgbe_buf_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR;
9316621Sbt150084 		ixgbe_desc_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR;
9326621Sbt150084 	} else {
9336621Sbt150084 		ixgbe_tx_dma_attr.dma_attr_flags = 0;
9346621Sbt150084 		ixgbe_buf_dma_attr.dma_attr_flags = 0;
9356621Sbt150084 		ixgbe_desc_dma_attr.dma_attr_flags = 0;
9366621Sbt150084 	}
9376621Sbt150084 }
938