xref: /titanic_52/usr/src/uts/common/io/ixgbe/ixgbe_buf.c (revision ffd8e8832e01f996f32459073f4dd308fe5265ba)
19da57d7bSbt150084 /*
29da57d7bSbt150084  * CDDL HEADER START
39da57d7bSbt150084  *
473cd555cSBin Tu - Sun Microsystems - Beijing China  * Copyright(c) 2007-2009 Intel Corporation. All rights reserved.
59da57d7bSbt150084  * The contents of this file are subject to the terms of the
69da57d7bSbt150084  * Common Development and Distribution License (the "License").
79da57d7bSbt150084  * You may not use this file except in compliance with the License.
89da57d7bSbt150084  *
99da57d7bSbt150084  * You can obtain a copy of the license at:
109da57d7bSbt150084  *      http://www.opensolaris.org/os/licensing.
119da57d7bSbt150084  * See the License for the specific language governing permissions
129da57d7bSbt150084  * and limitations under the License.
139da57d7bSbt150084  *
149da57d7bSbt150084  * When using or redistributing this file, you may do so under the
159da57d7bSbt150084  * License only. No other modification of this header is permitted.
169da57d7bSbt150084  *
179da57d7bSbt150084  * If applicable, add the following below this CDDL HEADER, with the
189da57d7bSbt150084  * fields enclosed by brackets "[]" replaced with your own identifying
199da57d7bSbt150084  * information: Portions Copyright [yyyy] [name of copyright owner]
209da57d7bSbt150084  *
219da57d7bSbt150084  * CDDL HEADER END
229da57d7bSbt150084  */
239da57d7bSbt150084 
249da57d7bSbt150084 /*
25*ffd8e883SWinson Wang - Sun Microsystems - Beijing China  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
2673cd555cSBin Tu - Sun Microsystems - Beijing China  * Use is subject to license terms.
279da57d7bSbt150084  */
289da57d7bSbt150084 
299da57d7bSbt150084 #include "ixgbe_sw.h"
309da57d7bSbt150084 
319da57d7bSbt150084 static int ixgbe_alloc_tbd_ring(ixgbe_tx_ring_t *);
329da57d7bSbt150084 static void ixgbe_free_tbd_ring(ixgbe_tx_ring_t *);
33ea65739eSchenlu chen - Sun Microsystems - Beijing China static int ixgbe_alloc_rbd_ring(ixgbe_rx_data_t *);
34ea65739eSchenlu chen - Sun Microsystems - Beijing China static void ixgbe_free_rbd_ring(ixgbe_rx_data_t *);
359da57d7bSbt150084 static int ixgbe_alloc_dma_buffer(ixgbe_t *, dma_buffer_t *, size_t);
369da57d7bSbt150084 static int ixgbe_alloc_tcb_lists(ixgbe_tx_ring_t *);
379da57d7bSbt150084 static void ixgbe_free_tcb_lists(ixgbe_tx_ring_t *);
38ea65739eSchenlu chen - Sun Microsystems - Beijing China static int ixgbe_alloc_rcb_lists(ixgbe_rx_data_t *);
39ea65739eSchenlu chen - Sun Microsystems - Beijing China static void ixgbe_free_rcb_lists(ixgbe_rx_data_t *);
409da57d7bSbt150084 
419da57d7bSbt150084 #ifdef __sparc
429da57d7bSbt150084 #define	IXGBE_DMA_ALIGNMENT	0x0000000000002000ull
439da57d7bSbt150084 #else
449da57d7bSbt150084 #define	IXGBE_DMA_ALIGNMENT	0x0000000000001000ull
459da57d7bSbt150084 #endif
469da57d7bSbt150084 
479da57d7bSbt150084 /*
489da57d7bSbt150084  * DMA attributes for tx/rx descriptors.
499da57d7bSbt150084  */
509da57d7bSbt150084 static ddi_dma_attr_t ixgbe_desc_dma_attr = {
519da57d7bSbt150084 	DMA_ATTR_V0,			/* version number */
529da57d7bSbt150084 	0x0000000000000000ull,		/* low address */
539da57d7bSbt150084 	0xFFFFFFFFFFFFFFFFull,		/* high address */
549da57d7bSbt150084 	0x00000000FFFFFFFFull,		/* dma counter max */
559da57d7bSbt150084 	IXGBE_DMA_ALIGNMENT,		/* alignment */
569da57d7bSbt150084 	0x00000FFF,			/* burst sizes */
579da57d7bSbt150084 	0x00000001,			/* minimum transfer size */
589da57d7bSbt150084 	0x00000000FFFFFFFFull,		/* maximum transfer size */
599da57d7bSbt150084 	0xFFFFFFFFFFFFFFFFull,		/* maximum segment size */
609da57d7bSbt150084 	1,				/* scatter/gather list length */
619da57d7bSbt150084 	0x00000001,			/* granularity */
629da57d7bSbt150084 	DDI_DMA_FLAGERR			/* DMA flags */
639da57d7bSbt150084 };
649da57d7bSbt150084 
659da57d7bSbt150084 /*
669da57d7bSbt150084  * DMA attributes for tx/rx buffers.
679da57d7bSbt150084  */
689da57d7bSbt150084 static ddi_dma_attr_t ixgbe_buf_dma_attr = {
699da57d7bSbt150084 	DMA_ATTR_V0,			/* version number */
709da57d7bSbt150084 	0x0000000000000000ull,		/* low address */
719da57d7bSbt150084 	0xFFFFFFFFFFFFFFFFull,		/* high address */
729da57d7bSbt150084 	0x00000000FFFFFFFFull,		/* dma counter max */
739da57d7bSbt150084 	IXGBE_DMA_ALIGNMENT,		/* alignment */
749da57d7bSbt150084 	0x00000FFF,			/* burst sizes */
759da57d7bSbt150084 	0x00000001,			/* minimum transfer size */
769da57d7bSbt150084 	0x00000000FFFFFFFFull,		/* maximum transfer size */
779da57d7bSbt150084 	0xFFFFFFFFFFFFFFFFull,		/* maximum segment size	 */
789da57d7bSbt150084 	1,				/* scatter/gather list length */
799da57d7bSbt150084 	0x00000001,			/* granularity */
809da57d7bSbt150084 	DDI_DMA_FLAGERR			/* DMA flags */
819da57d7bSbt150084 };
829da57d7bSbt150084 
839da57d7bSbt150084 /*
849da57d7bSbt150084  * DMA attributes for transmit.
859da57d7bSbt150084  */
869da57d7bSbt150084 static ddi_dma_attr_t ixgbe_tx_dma_attr = {
879da57d7bSbt150084 	DMA_ATTR_V0,			/* version number */
889da57d7bSbt150084 	0x0000000000000000ull,		/* low address */
899da57d7bSbt150084 	0xFFFFFFFFFFFFFFFFull,		/* high address */
909da57d7bSbt150084 	0x00000000FFFFFFFFull,		/* dma counter max */
919da57d7bSbt150084 	1,				/* alignment */
929da57d7bSbt150084 	0x00000FFF,			/* burst sizes */
939da57d7bSbt150084 	0x00000001,			/* minimum transfer size */
949da57d7bSbt150084 	0x00000000FFFFFFFFull,		/* maximum transfer size */
959da57d7bSbt150084 	0xFFFFFFFFFFFFFFFFull,		/* maximum segment size	 */
969da57d7bSbt150084 	MAX_COOKIE,			/* scatter/gather list length */
979da57d7bSbt150084 	0x00000001,			/* granularity */
989da57d7bSbt150084 	DDI_DMA_FLAGERR			/* DMA flags */
999da57d7bSbt150084 };
1009da57d7bSbt150084 
1019da57d7bSbt150084 /*
1029da57d7bSbt150084  * DMA access attributes for descriptors.
1039da57d7bSbt150084  */
1049da57d7bSbt150084 static ddi_device_acc_attr_t ixgbe_desc_acc_attr = {
1059da57d7bSbt150084 	DDI_DEVICE_ATTR_V0,
1069da57d7bSbt150084 	DDI_STRUCTURE_LE_ACC,
107837c1ac4SStephen Hanson 	DDI_STRICTORDER_ACC
1089da57d7bSbt150084 };
1099da57d7bSbt150084 
1109da57d7bSbt150084 /*
1119da57d7bSbt150084  * DMA access attributes for buffers.
1129da57d7bSbt150084  */
1139da57d7bSbt150084 static ddi_device_acc_attr_t ixgbe_buf_acc_attr = {
1149da57d7bSbt150084 	DDI_DEVICE_ATTR_V0,
1159da57d7bSbt150084 	DDI_NEVERSWAP_ACC,
1169da57d7bSbt150084 	DDI_STRICTORDER_ACC
1179da57d7bSbt150084 };
1189da57d7bSbt150084 
1199da57d7bSbt150084 /*
1209da57d7bSbt150084  * ixgbe_alloc_dma - Allocate DMA resources for all rx/tx rings.
1219da57d7bSbt150084  */
1229da57d7bSbt150084 int
1239da57d7bSbt150084 ixgbe_alloc_dma(ixgbe_t *ixgbe)
1249da57d7bSbt150084 {
1259da57d7bSbt150084 	ixgbe_rx_ring_t	*rx_ring;
126ea65739eSchenlu chen - Sun Microsystems - Beijing China 	ixgbe_rx_data_t *rx_data;
1279da57d7bSbt150084 	ixgbe_tx_ring_t *tx_ring;
1289da57d7bSbt150084 	int i;
1299da57d7bSbt150084 
1309da57d7bSbt150084 	for (i = 0; i < ixgbe->num_rx_rings; i++) {
1319da57d7bSbt150084 		/*
1329da57d7bSbt150084 		 * Allocate receive desciptor ring and control block lists
1339da57d7bSbt150084 		 */
1349da57d7bSbt150084 		rx_ring = &ixgbe->rx_rings[i];
135ea65739eSchenlu chen - Sun Microsystems - Beijing China 		rx_data = rx_ring->rx_data;
1369da57d7bSbt150084 
137ea65739eSchenlu chen - Sun Microsystems - Beijing China 		if (ixgbe_alloc_rbd_ring(rx_data) != IXGBE_SUCCESS)
1389da57d7bSbt150084 			goto alloc_dma_failure;
1399da57d7bSbt150084 
140ea65739eSchenlu chen - Sun Microsystems - Beijing China 		if (ixgbe_alloc_rcb_lists(rx_data) != IXGBE_SUCCESS)
1419da57d7bSbt150084 			goto alloc_dma_failure;
1429da57d7bSbt150084 	}
1439da57d7bSbt150084 
1449da57d7bSbt150084 	for (i = 0; i < ixgbe->num_tx_rings; i++) {
1459da57d7bSbt150084 		/*
1469da57d7bSbt150084 		 * Allocate transmit desciptor ring and control block lists
1479da57d7bSbt150084 		 */
1489da57d7bSbt150084 		tx_ring = &ixgbe->tx_rings[i];
1499da57d7bSbt150084 
1509da57d7bSbt150084 		if (ixgbe_alloc_tbd_ring(tx_ring) != IXGBE_SUCCESS)
1519da57d7bSbt150084 			goto alloc_dma_failure;
1529da57d7bSbt150084 
1539da57d7bSbt150084 		if (ixgbe_alloc_tcb_lists(tx_ring) != IXGBE_SUCCESS)
1549da57d7bSbt150084 			goto alloc_dma_failure;
1559da57d7bSbt150084 	}
1569da57d7bSbt150084 
1579da57d7bSbt150084 	return (IXGBE_SUCCESS);
1589da57d7bSbt150084 
1599da57d7bSbt150084 alloc_dma_failure:
1609da57d7bSbt150084 	ixgbe_free_dma(ixgbe);
1619da57d7bSbt150084 
1629da57d7bSbt150084 	return (IXGBE_FAILURE);
1639da57d7bSbt150084 }
1649da57d7bSbt150084 
1659da57d7bSbt150084 /*
1669da57d7bSbt150084  * ixgbe_free_dma - Free all the DMA resources of all rx/tx rings.
1679da57d7bSbt150084  */
1689da57d7bSbt150084 void
1699da57d7bSbt150084 ixgbe_free_dma(ixgbe_t *ixgbe)
1709da57d7bSbt150084 {
1719da57d7bSbt150084 	ixgbe_rx_ring_t *rx_ring;
172ea65739eSchenlu chen - Sun Microsystems - Beijing China 	ixgbe_rx_data_t *rx_data;
1739da57d7bSbt150084 	ixgbe_tx_ring_t *tx_ring;
1749da57d7bSbt150084 	int i;
1759da57d7bSbt150084 
1769da57d7bSbt150084 	/*
1779da57d7bSbt150084 	 * Free DMA resources of rx rings
1789da57d7bSbt150084 	 */
1799da57d7bSbt150084 	for (i = 0; i < ixgbe->num_rx_rings; i++) {
1809da57d7bSbt150084 		rx_ring = &ixgbe->rx_rings[i];
181ea65739eSchenlu chen - Sun Microsystems - Beijing China 		rx_data = rx_ring->rx_data;
182ea65739eSchenlu chen - Sun Microsystems - Beijing China 
183ea65739eSchenlu chen - Sun Microsystems - Beijing China 		ixgbe_free_rbd_ring(rx_data);
184ea65739eSchenlu chen - Sun Microsystems - Beijing China 		ixgbe_free_rcb_lists(rx_data);
1859da57d7bSbt150084 	}
1869da57d7bSbt150084 
1879da57d7bSbt150084 	/*
1889da57d7bSbt150084 	 * Free DMA resources of tx rings
1899da57d7bSbt150084 	 */
1909da57d7bSbt150084 	for (i = 0; i < ixgbe->num_tx_rings; i++) {
1919da57d7bSbt150084 		tx_ring = &ixgbe->tx_rings[i];
1929da57d7bSbt150084 		ixgbe_free_tbd_ring(tx_ring);
1939da57d7bSbt150084 		ixgbe_free_tcb_lists(tx_ring);
1949da57d7bSbt150084 	}
1959da57d7bSbt150084 }
1969da57d7bSbt150084 
197ea65739eSchenlu chen - Sun Microsystems - Beijing China int
198ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_alloc_rx_ring_data(ixgbe_rx_ring_t *rx_ring)
199ea65739eSchenlu chen - Sun Microsystems - Beijing China {
200ea65739eSchenlu chen - Sun Microsystems - Beijing China 	ixgbe_rx_data_t	*rx_data;
201ea65739eSchenlu chen - Sun Microsystems - Beijing China 	ixgbe_t *ixgbe = rx_ring->ixgbe;
202ea65739eSchenlu chen - Sun Microsystems - Beijing China 	uint32_t rcb_count;
203ea65739eSchenlu chen - Sun Microsystems - Beijing China 
204ea65739eSchenlu chen - Sun Microsystems - Beijing China 	/*
205ea65739eSchenlu chen - Sun Microsystems - Beijing China 	 * Allocate memory for software receive rings
206ea65739eSchenlu chen - Sun Microsystems - Beijing China 	 */
207ea65739eSchenlu chen - Sun Microsystems - Beijing China 	rx_data = kmem_zalloc(sizeof (ixgbe_rx_data_t), KM_NOSLEEP);
208ea65739eSchenlu chen - Sun Microsystems - Beijing China 
209ea65739eSchenlu chen - Sun Microsystems - Beijing China 	if (rx_data == NULL) {
210ea65739eSchenlu chen - Sun Microsystems - Beijing China 		ixgbe_error(ixgbe, "Allocate software receive rings failed");
211ea65739eSchenlu chen - Sun Microsystems - Beijing China 		return (IXGBE_FAILURE);
212ea65739eSchenlu chen - Sun Microsystems - Beijing China 	}
213ea65739eSchenlu chen - Sun Microsystems - Beijing China 
214ea65739eSchenlu chen - Sun Microsystems - Beijing China 	rx_data->rx_ring = rx_ring;
215ea65739eSchenlu chen - Sun Microsystems - Beijing China 	mutex_init(&rx_data->recycle_lock, NULL,
216ea65739eSchenlu chen - Sun Microsystems - Beijing China 	    MUTEX_DRIVER, DDI_INTR_PRI(ixgbe->intr_pri));
217ea65739eSchenlu chen - Sun Microsystems - Beijing China 
218ea65739eSchenlu chen - Sun Microsystems - Beijing China 	rx_data->ring_size = ixgbe->rx_ring_size;
219ea65739eSchenlu chen - Sun Microsystems - Beijing China 	rx_data->free_list_size = ixgbe->rx_ring_size;
220ea65739eSchenlu chen - Sun Microsystems - Beijing China 
221ea65739eSchenlu chen - Sun Microsystems - Beijing China 	rx_data->rcb_head = 0;
222ea65739eSchenlu chen - Sun Microsystems - Beijing China 	rx_data->rcb_tail = 0;
223ea65739eSchenlu chen - Sun Microsystems - Beijing China 	rx_data->rcb_free = rx_data->free_list_size;
224ea65739eSchenlu chen - Sun Microsystems - Beijing China 
225ea65739eSchenlu chen - Sun Microsystems - Beijing China 	/*
226ea65739eSchenlu chen - Sun Microsystems - Beijing China 	 * Allocate memory for the work list.
227ea65739eSchenlu chen - Sun Microsystems - Beijing China 	 */
228ea65739eSchenlu chen - Sun Microsystems - Beijing China 	rx_data->work_list = kmem_zalloc(sizeof (rx_control_block_t *) *
229ea65739eSchenlu chen - Sun Microsystems - Beijing China 	    rx_data->ring_size, KM_NOSLEEP);
230ea65739eSchenlu chen - Sun Microsystems - Beijing China 
231ea65739eSchenlu chen - Sun Microsystems - Beijing China 	if (rx_data->work_list == NULL) {
232ea65739eSchenlu chen - Sun Microsystems - Beijing China 		ixgbe_error(ixgbe,
233ea65739eSchenlu chen - Sun Microsystems - Beijing China 		    "Could not allocate memory for rx work list");
234ea65739eSchenlu chen - Sun Microsystems - Beijing China 		goto alloc_rx_data_failure;
235ea65739eSchenlu chen - Sun Microsystems - Beijing China 	}
236ea65739eSchenlu chen - Sun Microsystems - Beijing China 
237ea65739eSchenlu chen - Sun Microsystems - Beijing China 	/*
238ea65739eSchenlu chen - Sun Microsystems - Beijing China 	 * Allocate memory for the free list.
239ea65739eSchenlu chen - Sun Microsystems - Beijing China 	 */
240ea65739eSchenlu chen - Sun Microsystems - Beijing China 	rx_data->free_list = kmem_zalloc(sizeof (rx_control_block_t *) *
241ea65739eSchenlu chen - Sun Microsystems - Beijing China 	    rx_data->free_list_size, KM_NOSLEEP);
242ea65739eSchenlu chen - Sun Microsystems - Beijing China 
243ea65739eSchenlu chen - Sun Microsystems - Beijing China 	if (rx_data->free_list == NULL) {
244ea65739eSchenlu chen - Sun Microsystems - Beijing China 		ixgbe_error(ixgbe,
245ea65739eSchenlu chen - Sun Microsystems - Beijing China 		    "Cound not allocate memory for rx free list");
246ea65739eSchenlu chen - Sun Microsystems - Beijing China 		goto alloc_rx_data_failure;
247ea65739eSchenlu chen - Sun Microsystems - Beijing China 	}
248ea65739eSchenlu chen - Sun Microsystems - Beijing China 
249ea65739eSchenlu chen - Sun Microsystems - Beijing China 	/*
250ea65739eSchenlu chen - Sun Microsystems - Beijing China 	 * Allocate memory for the rx control blocks for work list and
251ea65739eSchenlu chen - Sun Microsystems - Beijing China 	 * free list.
252ea65739eSchenlu chen - Sun Microsystems - Beijing China 	 */
253ea65739eSchenlu chen - Sun Microsystems - Beijing China 	rcb_count = rx_data->ring_size + rx_data->free_list_size;
254ea65739eSchenlu chen - Sun Microsystems - Beijing China 	rx_data->rcb_area =
255ea65739eSchenlu chen - Sun Microsystems - Beijing China 	    kmem_zalloc(sizeof (rx_control_block_t) * rcb_count,
256ea65739eSchenlu chen - Sun Microsystems - Beijing China 	    KM_NOSLEEP);
257ea65739eSchenlu chen - Sun Microsystems - Beijing China 
258ea65739eSchenlu chen - Sun Microsystems - Beijing China 	if (rx_data->rcb_area == NULL) {
259ea65739eSchenlu chen - Sun Microsystems - Beijing China 		ixgbe_error(ixgbe,
260ea65739eSchenlu chen - Sun Microsystems - Beijing China 		    "Cound not allocate memory for rx control blocks");
261ea65739eSchenlu chen - Sun Microsystems - Beijing China 		goto alloc_rx_data_failure;
262ea65739eSchenlu chen - Sun Microsystems - Beijing China 	}
263ea65739eSchenlu chen - Sun Microsystems - Beijing China 
264ea65739eSchenlu chen - Sun Microsystems - Beijing China 	rx_ring->rx_data = rx_data;
265ea65739eSchenlu chen - Sun Microsystems - Beijing China 	return (IXGBE_SUCCESS);
266ea65739eSchenlu chen - Sun Microsystems - Beijing China 
267ea65739eSchenlu chen - Sun Microsystems - Beijing China alloc_rx_data_failure:
268ea65739eSchenlu chen - Sun Microsystems - Beijing China 	ixgbe_free_rx_ring_data(rx_data);
269ea65739eSchenlu chen - Sun Microsystems - Beijing China 	return (IXGBE_FAILURE);
270ea65739eSchenlu chen - Sun Microsystems - Beijing China }
271ea65739eSchenlu chen - Sun Microsystems - Beijing China 
272ea65739eSchenlu chen - Sun Microsystems - Beijing China void
273ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_free_rx_ring_data(ixgbe_rx_data_t *rx_data)
274ea65739eSchenlu chen - Sun Microsystems - Beijing China {
275ea65739eSchenlu chen - Sun Microsystems - Beijing China 	uint32_t rcb_count;
276ea65739eSchenlu chen - Sun Microsystems - Beijing China 
277ea65739eSchenlu chen - Sun Microsystems - Beijing China 	if (rx_data == NULL)
278ea65739eSchenlu chen - Sun Microsystems - Beijing China 		return;
279ea65739eSchenlu chen - Sun Microsystems - Beijing China 
280ea65739eSchenlu chen - Sun Microsystems - Beijing China 	ASSERT(rx_data->rcb_pending == 0);
281ea65739eSchenlu chen - Sun Microsystems - Beijing China 
282ea65739eSchenlu chen - Sun Microsystems - Beijing China 	rcb_count = rx_data->ring_size + rx_data->free_list_size;
283ea65739eSchenlu chen - Sun Microsystems - Beijing China 	if (rx_data->rcb_area != NULL) {
284ea65739eSchenlu chen - Sun Microsystems - Beijing China 		kmem_free(rx_data->rcb_area,
285ea65739eSchenlu chen - Sun Microsystems - Beijing China 		    sizeof (rx_control_block_t) * rcb_count);
286ea65739eSchenlu chen - Sun Microsystems - Beijing China 		rx_data->rcb_area = NULL;
287ea65739eSchenlu chen - Sun Microsystems - Beijing China 	}
288ea65739eSchenlu chen - Sun Microsystems - Beijing China 
289ea65739eSchenlu chen - Sun Microsystems - Beijing China 	if (rx_data->work_list != NULL) {
290ea65739eSchenlu chen - Sun Microsystems - Beijing China 		kmem_free(rx_data->work_list,
291ea65739eSchenlu chen - Sun Microsystems - Beijing China 		    sizeof (rx_control_block_t *) * rx_data->ring_size);
292ea65739eSchenlu chen - Sun Microsystems - Beijing China 		rx_data->work_list = NULL;
293ea65739eSchenlu chen - Sun Microsystems - Beijing China 	}
294ea65739eSchenlu chen - Sun Microsystems - Beijing China 
295ea65739eSchenlu chen - Sun Microsystems - Beijing China 	if (rx_data->free_list != NULL) {
296ea65739eSchenlu chen - Sun Microsystems - Beijing China 		kmem_free(rx_data->free_list,
297ea65739eSchenlu chen - Sun Microsystems - Beijing China 		    sizeof (rx_control_block_t *) * rx_data->free_list_size);
298ea65739eSchenlu chen - Sun Microsystems - Beijing China 		rx_data->free_list = NULL;
299ea65739eSchenlu chen - Sun Microsystems - Beijing China 	}
300ea65739eSchenlu chen - Sun Microsystems - Beijing China 
301ea65739eSchenlu chen - Sun Microsystems - Beijing China 	mutex_destroy(&rx_data->recycle_lock);
302ea65739eSchenlu chen - Sun Microsystems - Beijing China 	kmem_free(rx_data, sizeof (ixgbe_rx_data_t));
303ea65739eSchenlu chen - Sun Microsystems - Beijing China }
304ea65739eSchenlu chen - Sun Microsystems - Beijing China 
3059da57d7bSbt150084 /*
3069da57d7bSbt150084  * ixgbe_alloc_tbd_ring - Memory allocation for the tx descriptors of one ring.
3079da57d7bSbt150084  */
3089da57d7bSbt150084 static int
3099da57d7bSbt150084 ixgbe_alloc_tbd_ring(ixgbe_tx_ring_t *tx_ring)
3109da57d7bSbt150084 {
3119da57d7bSbt150084 	int ret;
3129da57d7bSbt150084 	size_t size;
3139da57d7bSbt150084 	size_t len;
3149da57d7bSbt150084 	uint_t cookie_num;
3159da57d7bSbt150084 	dev_info_t *devinfo;
3169da57d7bSbt150084 	ddi_dma_cookie_t cookie;
3179da57d7bSbt150084 	ixgbe_t *ixgbe = tx_ring->ixgbe;
3189da57d7bSbt150084 
3199da57d7bSbt150084 	devinfo = ixgbe->dip;
3209da57d7bSbt150084 	size = sizeof (union ixgbe_adv_tx_desc) * tx_ring->ring_size;
3219da57d7bSbt150084 
3229da57d7bSbt150084 	/*
3239da57d7bSbt150084 	 * If tx head write-back is enabled, an extra tbd is allocated
3249da57d7bSbt150084 	 * to save the head write-back value
3259da57d7bSbt150084 	 */
3269da57d7bSbt150084 	if (ixgbe->tx_head_wb_enable) {
3279da57d7bSbt150084 		size += sizeof (union ixgbe_adv_tx_desc);
3289da57d7bSbt150084 	}
3299da57d7bSbt150084 
3309da57d7bSbt150084 	/*
3319da57d7bSbt150084 	 * Allocate a DMA handle for the transmit descriptor
3329da57d7bSbt150084 	 * memory area.
3339da57d7bSbt150084 	 */
3349da57d7bSbt150084 	ret = ddi_dma_alloc_handle(devinfo, &ixgbe_desc_dma_attr,
3359da57d7bSbt150084 	    DDI_DMA_DONTWAIT, NULL,
3369da57d7bSbt150084 	    &tx_ring->tbd_area.dma_handle);
3379da57d7bSbt150084 
3389da57d7bSbt150084 	if (ret != DDI_SUCCESS) {
3399da57d7bSbt150084 		ixgbe_error(ixgbe,
3409da57d7bSbt150084 		    "Could not allocate tbd dma handle: %x", ret);
3419da57d7bSbt150084 		tx_ring->tbd_area.dma_handle = NULL;
3429da57d7bSbt150084 
3439da57d7bSbt150084 		return (IXGBE_FAILURE);
3449da57d7bSbt150084 	}
3459da57d7bSbt150084 
3469da57d7bSbt150084 	/*
3479da57d7bSbt150084 	 * Allocate memory to DMA data to and from the transmit
3489da57d7bSbt150084 	 * descriptors.
3499da57d7bSbt150084 	 */
3509da57d7bSbt150084 	ret = ddi_dma_mem_alloc(tx_ring->tbd_area.dma_handle,
3519da57d7bSbt150084 	    size, &ixgbe_desc_acc_attr, DDI_DMA_CONSISTENT,
3529da57d7bSbt150084 	    DDI_DMA_DONTWAIT, NULL,
3539da57d7bSbt150084 	    (caddr_t *)&tx_ring->tbd_area.address,
3549da57d7bSbt150084 	    &len, &tx_ring->tbd_area.acc_handle);
3559da57d7bSbt150084 
3569da57d7bSbt150084 	if (ret != DDI_SUCCESS) {
3579da57d7bSbt150084 		ixgbe_error(ixgbe,
3589da57d7bSbt150084 		    "Could not allocate tbd dma memory: %x", ret);
3599da57d7bSbt150084 		tx_ring->tbd_area.acc_handle = NULL;
3609da57d7bSbt150084 		tx_ring->tbd_area.address = NULL;
3619da57d7bSbt150084 		if (tx_ring->tbd_area.dma_handle != NULL) {
3629da57d7bSbt150084 			ddi_dma_free_handle(&tx_ring->tbd_area.dma_handle);
3639da57d7bSbt150084 			tx_ring->tbd_area.dma_handle = NULL;
3649da57d7bSbt150084 		}
3659da57d7bSbt150084 		return (IXGBE_FAILURE);
3669da57d7bSbt150084 	}
3679da57d7bSbt150084 
3689da57d7bSbt150084 	/*
3699da57d7bSbt150084 	 * Initialize the entire transmit buffer descriptor area to zero
3709da57d7bSbt150084 	 */
3719da57d7bSbt150084 	bzero(tx_ring->tbd_area.address, len);
3729da57d7bSbt150084 
3739da57d7bSbt150084 	/*
3749da57d7bSbt150084 	 * Allocates DMA resources for the memory that was allocated by
3759da57d7bSbt150084 	 * the ddi_dma_mem_alloc call. The DMA resources then get bound to the
3769da57d7bSbt150084 	 * the memory address
3779da57d7bSbt150084 	 */
3789da57d7bSbt150084 	ret = ddi_dma_addr_bind_handle(tx_ring->tbd_area.dma_handle,
3799da57d7bSbt150084 	    NULL, (caddr_t)tx_ring->tbd_area.address,
3809da57d7bSbt150084 	    len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
3819da57d7bSbt150084 	    DDI_DMA_DONTWAIT, NULL, &cookie, &cookie_num);
3829da57d7bSbt150084 
3839da57d7bSbt150084 	if (ret != DDI_DMA_MAPPED) {
3849da57d7bSbt150084 		ixgbe_error(ixgbe,
3859da57d7bSbt150084 		    "Could not bind tbd dma resource: %x", ret);
3869da57d7bSbt150084 		tx_ring->tbd_area.dma_address = NULL;
3879da57d7bSbt150084 		if (tx_ring->tbd_area.acc_handle != NULL) {
3889da57d7bSbt150084 			ddi_dma_mem_free(&tx_ring->tbd_area.acc_handle);
3899da57d7bSbt150084 			tx_ring->tbd_area.acc_handle = NULL;
3909da57d7bSbt150084 			tx_ring->tbd_area.address = NULL;
3919da57d7bSbt150084 		}
3929da57d7bSbt150084 		if (tx_ring->tbd_area.dma_handle != NULL) {
3939da57d7bSbt150084 			ddi_dma_free_handle(&tx_ring->tbd_area.dma_handle);
3949da57d7bSbt150084 			tx_ring->tbd_area.dma_handle = NULL;
3959da57d7bSbt150084 		}
3969da57d7bSbt150084 		return (IXGBE_FAILURE);
3979da57d7bSbt150084 	}
3989da57d7bSbt150084 
3999da57d7bSbt150084 	ASSERT(cookie_num == 1);
4009da57d7bSbt150084 
4019da57d7bSbt150084 	tx_ring->tbd_area.dma_address = cookie.dmac_laddress;
4029da57d7bSbt150084 	tx_ring->tbd_area.size = len;
4039da57d7bSbt150084 
4049da57d7bSbt150084 	tx_ring->tbd_ring = (union ixgbe_adv_tx_desc *)(uintptr_t)
4059da57d7bSbt150084 	    tx_ring->tbd_area.address;
4069da57d7bSbt150084 
4079da57d7bSbt150084 	return (IXGBE_SUCCESS);
4089da57d7bSbt150084 }
4099da57d7bSbt150084 
4109da57d7bSbt150084 /*
4119da57d7bSbt150084  * ixgbe_free_tbd_ring - Free the tx descriptors of one ring.
4129da57d7bSbt150084  */
4139da57d7bSbt150084 static void
4149da57d7bSbt150084 ixgbe_free_tbd_ring(ixgbe_tx_ring_t *tx_ring)
4159da57d7bSbt150084 {
4169da57d7bSbt150084 	if (tx_ring->tbd_area.dma_handle != NULL) {
4179da57d7bSbt150084 		(void) ddi_dma_unbind_handle(tx_ring->tbd_area.dma_handle);
4189da57d7bSbt150084 	}
4199da57d7bSbt150084 	if (tx_ring->tbd_area.acc_handle != NULL) {
4209da57d7bSbt150084 		ddi_dma_mem_free(&tx_ring->tbd_area.acc_handle);
4219da57d7bSbt150084 		tx_ring->tbd_area.acc_handle = NULL;
4229da57d7bSbt150084 	}
4239da57d7bSbt150084 	if (tx_ring->tbd_area.dma_handle != NULL) {
4249da57d7bSbt150084 		ddi_dma_free_handle(&tx_ring->tbd_area.dma_handle);
4259da57d7bSbt150084 		tx_ring->tbd_area.dma_handle = NULL;
4269da57d7bSbt150084 	}
4279da57d7bSbt150084 	tx_ring->tbd_area.address = NULL;
4289da57d7bSbt150084 	tx_ring->tbd_area.dma_address = NULL;
4299da57d7bSbt150084 	tx_ring->tbd_area.size = 0;
4309da57d7bSbt150084 
4319da57d7bSbt150084 	tx_ring->tbd_ring = NULL;
4329da57d7bSbt150084 }
4339da57d7bSbt150084 
4349da57d7bSbt150084 /*
4359da57d7bSbt150084  * ixgbe_alloc_rbd_ring - Memory allocation for the rx descriptors of one ring.
4369da57d7bSbt150084  */
4379da57d7bSbt150084 static int
438ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_alloc_rbd_ring(ixgbe_rx_data_t *rx_data)
4399da57d7bSbt150084 {
4409da57d7bSbt150084 	int ret;
4419da57d7bSbt150084 	size_t size;
4429da57d7bSbt150084 	size_t len;
4439da57d7bSbt150084 	uint_t cookie_num;
4449da57d7bSbt150084 	dev_info_t *devinfo;
4459da57d7bSbt150084 	ddi_dma_cookie_t cookie;
446ea65739eSchenlu chen - Sun Microsystems - Beijing China 	ixgbe_t *ixgbe = rx_data->rx_ring->ixgbe;
4479da57d7bSbt150084 
4489da57d7bSbt150084 	devinfo = ixgbe->dip;
449ea65739eSchenlu chen - Sun Microsystems - Beijing China 	size = sizeof (union ixgbe_adv_rx_desc) * rx_data->ring_size;
4509da57d7bSbt150084 
4519da57d7bSbt150084 	/*
4529da57d7bSbt150084 	 * Allocate a new DMA handle for the receive descriptor
4539da57d7bSbt150084 	 * memory area.
4549da57d7bSbt150084 	 */
4559da57d7bSbt150084 	ret = ddi_dma_alloc_handle(devinfo, &ixgbe_desc_dma_attr,
4569da57d7bSbt150084 	    DDI_DMA_DONTWAIT, NULL,
457ea65739eSchenlu chen - Sun Microsystems - Beijing China 	    &rx_data->rbd_area.dma_handle);
4589da57d7bSbt150084 
4599da57d7bSbt150084 	if (ret != DDI_SUCCESS) {
4609da57d7bSbt150084 		ixgbe_error(ixgbe,
4619da57d7bSbt150084 		    "Could not allocate rbd dma handle: %x", ret);
462ea65739eSchenlu chen - Sun Microsystems - Beijing China 		rx_data->rbd_area.dma_handle = NULL;
4639da57d7bSbt150084 		return (IXGBE_FAILURE);
4649da57d7bSbt150084 	}
4659da57d7bSbt150084 
4669da57d7bSbt150084 	/*
4679da57d7bSbt150084 	 * Allocate memory to DMA data to and from the receive
4689da57d7bSbt150084 	 * descriptors.
4699da57d7bSbt150084 	 */
470ea65739eSchenlu chen - Sun Microsystems - Beijing China 	ret = ddi_dma_mem_alloc(rx_data->rbd_area.dma_handle,
4719da57d7bSbt150084 	    size, &ixgbe_desc_acc_attr, DDI_DMA_CONSISTENT,
4729da57d7bSbt150084 	    DDI_DMA_DONTWAIT, NULL,
473ea65739eSchenlu chen - Sun Microsystems - Beijing China 	    (caddr_t *)&rx_data->rbd_area.address,
474ea65739eSchenlu chen - Sun Microsystems - Beijing China 	    &len, &rx_data->rbd_area.acc_handle);
4759da57d7bSbt150084 
4769da57d7bSbt150084 	if (ret != DDI_SUCCESS) {
4779da57d7bSbt150084 		ixgbe_error(ixgbe,
4789da57d7bSbt150084 		    "Could not allocate rbd dma memory: %x", ret);
479ea65739eSchenlu chen - Sun Microsystems - Beijing China 		rx_data->rbd_area.acc_handle = NULL;
480ea65739eSchenlu chen - Sun Microsystems - Beijing China 		rx_data->rbd_area.address = NULL;
481ea65739eSchenlu chen - Sun Microsystems - Beijing China 		if (rx_data->rbd_area.dma_handle != NULL) {
482ea65739eSchenlu chen - Sun Microsystems - Beijing China 			ddi_dma_free_handle(&rx_data->rbd_area.dma_handle);
483ea65739eSchenlu chen - Sun Microsystems - Beijing China 			rx_data->rbd_area.dma_handle = NULL;
4849da57d7bSbt150084 		}
4859da57d7bSbt150084 		return (IXGBE_FAILURE);
4869da57d7bSbt150084 	}
4879da57d7bSbt150084 
4889da57d7bSbt150084 	/*
4899da57d7bSbt150084 	 * Initialize the entire transmit buffer descriptor area to zero
4909da57d7bSbt150084 	 */
491ea65739eSchenlu chen - Sun Microsystems - Beijing China 	bzero(rx_data->rbd_area.address, len);
4929da57d7bSbt150084 
4939da57d7bSbt150084 	/*
4949da57d7bSbt150084 	 * Allocates DMA resources for the memory that was allocated by
4959da57d7bSbt150084 	 * the ddi_dma_mem_alloc call.
4969da57d7bSbt150084 	 */
497ea65739eSchenlu chen - Sun Microsystems - Beijing China 	ret = ddi_dma_addr_bind_handle(rx_data->rbd_area.dma_handle,
498ea65739eSchenlu chen - Sun Microsystems - Beijing China 	    NULL, (caddr_t)rx_data->rbd_area.address,
4999da57d7bSbt150084 	    len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
5009da57d7bSbt150084 	    DDI_DMA_DONTWAIT, NULL, &cookie, &cookie_num);
5019da57d7bSbt150084 
5029da57d7bSbt150084 	if (ret != DDI_DMA_MAPPED) {
5039da57d7bSbt150084 		ixgbe_error(ixgbe,
5049da57d7bSbt150084 		    "Could not bind rbd dma resource: %x", ret);
505ea65739eSchenlu chen - Sun Microsystems - Beijing China 		rx_data->rbd_area.dma_address = NULL;
506ea65739eSchenlu chen - Sun Microsystems - Beijing China 		if (rx_data->rbd_area.acc_handle != NULL) {
507ea65739eSchenlu chen - Sun Microsystems - Beijing China 			ddi_dma_mem_free(&rx_data->rbd_area.acc_handle);
508ea65739eSchenlu chen - Sun Microsystems - Beijing China 			rx_data->rbd_area.acc_handle = NULL;
509ea65739eSchenlu chen - Sun Microsystems - Beijing China 			rx_data->rbd_area.address = NULL;
5109da57d7bSbt150084 		}
511ea65739eSchenlu chen - Sun Microsystems - Beijing China 		if (rx_data->rbd_area.dma_handle != NULL) {
512ea65739eSchenlu chen - Sun Microsystems - Beijing China 			ddi_dma_free_handle(&rx_data->rbd_area.dma_handle);
513ea65739eSchenlu chen - Sun Microsystems - Beijing China 			rx_data->rbd_area.dma_handle = NULL;
5149da57d7bSbt150084 		}
5159da57d7bSbt150084 		return (IXGBE_FAILURE);
5169da57d7bSbt150084 	}
5179da57d7bSbt150084 
5189da57d7bSbt150084 	ASSERT(cookie_num == 1);
5199da57d7bSbt150084 
520ea65739eSchenlu chen - Sun Microsystems - Beijing China 	rx_data->rbd_area.dma_address = cookie.dmac_laddress;
521ea65739eSchenlu chen - Sun Microsystems - Beijing China 	rx_data->rbd_area.size = len;
5229da57d7bSbt150084 
523ea65739eSchenlu chen - Sun Microsystems - Beijing China 	rx_data->rbd_ring = (union ixgbe_adv_rx_desc *)(uintptr_t)
524ea65739eSchenlu chen - Sun Microsystems - Beijing China 	    rx_data->rbd_area.address;
5259da57d7bSbt150084 
5269da57d7bSbt150084 	return (IXGBE_SUCCESS);
5279da57d7bSbt150084 }
5289da57d7bSbt150084 
5299da57d7bSbt150084 /*
5309da57d7bSbt150084  * ixgbe_free_rbd_ring - Free the rx descriptors of one ring.
5319da57d7bSbt150084  */
5329da57d7bSbt150084 static void
533ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_free_rbd_ring(ixgbe_rx_data_t *rx_data)
5349da57d7bSbt150084 {
535ea65739eSchenlu chen - Sun Microsystems - Beijing China 	if (rx_data->rbd_area.dma_handle != NULL) {
536ea65739eSchenlu chen - Sun Microsystems - Beijing China 		(void) ddi_dma_unbind_handle(rx_data->rbd_area.dma_handle);
5379da57d7bSbt150084 	}
538ea65739eSchenlu chen - Sun Microsystems - Beijing China 	if (rx_data->rbd_area.acc_handle != NULL) {
539ea65739eSchenlu chen - Sun Microsystems - Beijing China 		ddi_dma_mem_free(&rx_data->rbd_area.acc_handle);
540ea65739eSchenlu chen - Sun Microsystems - Beijing China 		rx_data->rbd_area.acc_handle = NULL;
5419da57d7bSbt150084 	}
542ea65739eSchenlu chen - Sun Microsystems - Beijing China 	if (rx_data->rbd_area.dma_handle != NULL) {
543ea65739eSchenlu chen - Sun Microsystems - Beijing China 		ddi_dma_free_handle(&rx_data->rbd_area.dma_handle);
544ea65739eSchenlu chen - Sun Microsystems - Beijing China 		rx_data->rbd_area.dma_handle = NULL;
5459da57d7bSbt150084 	}
546ea65739eSchenlu chen - Sun Microsystems - Beijing China 	rx_data->rbd_area.address = NULL;
547ea65739eSchenlu chen - Sun Microsystems - Beijing China 	rx_data->rbd_area.dma_address = NULL;
548ea65739eSchenlu chen - Sun Microsystems - Beijing China 	rx_data->rbd_area.size = 0;
5499da57d7bSbt150084 
550ea65739eSchenlu chen - Sun Microsystems - Beijing China 	rx_data->rbd_ring = NULL;
5519da57d7bSbt150084 }
5529da57d7bSbt150084 
5539da57d7bSbt150084 /*
5549da57d7bSbt150084  * ixgbe_alloc_dma_buffer - Allocate DMA resources for a DMA buffer.
5559da57d7bSbt150084  */
5569da57d7bSbt150084 static int
5579da57d7bSbt150084 ixgbe_alloc_dma_buffer(ixgbe_t *ixgbe, dma_buffer_t *buf, size_t size)
5589da57d7bSbt150084 {
5599da57d7bSbt150084 	int ret;
5609da57d7bSbt150084 	dev_info_t *devinfo = ixgbe->dip;
5619da57d7bSbt150084 	ddi_dma_cookie_t cookie;
5629da57d7bSbt150084 	size_t len;
5639da57d7bSbt150084 	uint_t cookie_num;
5649da57d7bSbt150084 
5659da57d7bSbt150084 	ret = ddi_dma_alloc_handle(devinfo,
5669da57d7bSbt150084 	    &ixgbe_buf_dma_attr, DDI_DMA_DONTWAIT,
5679da57d7bSbt150084 	    NULL, &buf->dma_handle);
5689da57d7bSbt150084 
5699da57d7bSbt150084 	if (ret != DDI_SUCCESS) {
5709da57d7bSbt150084 		buf->dma_handle = NULL;
5719da57d7bSbt150084 		ixgbe_error(ixgbe,
5729da57d7bSbt150084 		    "Could not allocate dma buffer handle: %x", ret);
5739da57d7bSbt150084 		return (IXGBE_FAILURE);
5749da57d7bSbt150084 	}
5759da57d7bSbt150084 
5769da57d7bSbt150084 	ret = ddi_dma_mem_alloc(buf->dma_handle,
5779da57d7bSbt150084 	    size, &ixgbe_buf_acc_attr, DDI_DMA_STREAMING,
5789da57d7bSbt150084 	    DDI_DMA_DONTWAIT, NULL, &buf->address,
5799da57d7bSbt150084 	    &len, &buf->acc_handle);
5809da57d7bSbt150084 
5819da57d7bSbt150084 	if (ret != DDI_SUCCESS) {
5829da57d7bSbt150084 		buf->acc_handle = NULL;
5839da57d7bSbt150084 		buf->address = NULL;
5849da57d7bSbt150084 		if (buf->dma_handle != NULL) {
5859da57d7bSbt150084 			ddi_dma_free_handle(&buf->dma_handle);
5869da57d7bSbt150084 			buf->dma_handle = NULL;
5879da57d7bSbt150084 		}
5889da57d7bSbt150084 		ixgbe_error(ixgbe,
5899da57d7bSbt150084 		    "Could not allocate dma buffer memory: %x", ret);
5909da57d7bSbt150084 		return (IXGBE_FAILURE);
5919da57d7bSbt150084 	}
5929da57d7bSbt150084 
5939da57d7bSbt150084 	ret = ddi_dma_addr_bind_handle(buf->dma_handle, NULL,
5949da57d7bSbt150084 	    buf->address,
5959da57d7bSbt150084 	    len, DDI_DMA_RDWR | DDI_DMA_STREAMING,
5969da57d7bSbt150084 	    DDI_DMA_DONTWAIT, NULL, &cookie, &cookie_num);
5979da57d7bSbt150084 
5989da57d7bSbt150084 	if (ret != DDI_DMA_MAPPED) {
5999da57d7bSbt150084 		buf->dma_address = NULL;
6009da57d7bSbt150084 		if (buf->acc_handle != NULL) {
6019da57d7bSbt150084 			ddi_dma_mem_free(&buf->acc_handle);
6029da57d7bSbt150084 			buf->acc_handle = NULL;
6039da57d7bSbt150084 			buf->address = NULL;
6049da57d7bSbt150084 		}
6059da57d7bSbt150084 		if (buf->dma_handle != NULL) {
6069da57d7bSbt150084 			ddi_dma_free_handle(&buf->dma_handle);
6079da57d7bSbt150084 			buf->dma_handle = NULL;
6089da57d7bSbt150084 		}
6099da57d7bSbt150084 		ixgbe_error(ixgbe,
6109da57d7bSbt150084 		    "Could not bind dma buffer handle: %x", ret);
6119da57d7bSbt150084 		return (IXGBE_FAILURE);
6129da57d7bSbt150084 	}
6139da57d7bSbt150084 
6149da57d7bSbt150084 	ASSERT(cookie_num == 1);
6159da57d7bSbt150084 
6169da57d7bSbt150084 	buf->dma_address = cookie.dmac_laddress;
6179da57d7bSbt150084 	buf->size = len;
6189da57d7bSbt150084 	buf->len = 0;
6199da57d7bSbt150084 
6209da57d7bSbt150084 	return (IXGBE_SUCCESS);
6219da57d7bSbt150084 }
6229da57d7bSbt150084 
6239da57d7bSbt150084 /*
6249da57d7bSbt150084  * ixgbe_free_dma_buffer - Free one allocated area of dma memory and handle.
6259da57d7bSbt150084  */
626ea65739eSchenlu chen - Sun Microsystems - Beijing China void
6279da57d7bSbt150084 ixgbe_free_dma_buffer(dma_buffer_t *buf)
6289da57d7bSbt150084 {
6299da57d7bSbt150084 	if (buf->dma_handle != NULL) {
6309da57d7bSbt150084 		(void) ddi_dma_unbind_handle(buf->dma_handle);
6319da57d7bSbt150084 		buf->dma_address = NULL;
6329da57d7bSbt150084 	} else {
6339da57d7bSbt150084 		return;
6349da57d7bSbt150084 	}
6359da57d7bSbt150084 
6369da57d7bSbt150084 	if (buf->acc_handle != NULL) {
6379da57d7bSbt150084 		ddi_dma_mem_free(&buf->acc_handle);
6389da57d7bSbt150084 		buf->acc_handle = NULL;
6399da57d7bSbt150084 		buf->address = NULL;
6409da57d7bSbt150084 	}
6419da57d7bSbt150084 
6429da57d7bSbt150084 	if (buf->dma_handle != NULL) {
6439da57d7bSbt150084 		ddi_dma_free_handle(&buf->dma_handle);
6449da57d7bSbt150084 		buf->dma_handle = NULL;
6459da57d7bSbt150084 	}
6469da57d7bSbt150084 
6479da57d7bSbt150084 	buf->size = 0;
6489da57d7bSbt150084 	buf->len = 0;
6499da57d7bSbt150084 }
6509da57d7bSbt150084 
6519da57d7bSbt150084 /*
6529da57d7bSbt150084  * ixgbe_alloc_tcb_lists - Memory allocation for the transmit control bolcks
6539da57d7bSbt150084  * of one ring.
6549da57d7bSbt150084  */
6559da57d7bSbt150084 static int
6569da57d7bSbt150084 ixgbe_alloc_tcb_lists(ixgbe_tx_ring_t *tx_ring)
6579da57d7bSbt150084 {
6589da57d7bSbt150084 	int i;
6599da57d7bSbt150084 	int ret;
6609da57d7bSbt150084 	tx_control_block_t *tcb;
6619da57d7bSbt150084 	dma_buffer_t *tx_buf;
6629da57d7bSbt150084 	ixgbe_t *ixgbe = tx_ring->ixgbe;
6639da57d7bSbt150084 	dev_info_t *devinfo = ixgbe->dip;
6649da57d7bSbt150084 
6659da57d7bSbt150084 	/*
6669da57d7bSbt150084 	 * Allocate memory for the work list.
6679da57d7bSbt150084 	 */
6689da57d7bSbt150084 	tx_ring->work_list = kmem_zalloc(sizeof (tx_control_block_t *) *
6699da57d7bSbt150084 	    tx_ring->ring_size, KM_NOSLEEP);
6709da57d7bSbt150084 
6719da57d7bSbt150084 	if (tx_ring->work_list == NULL) {
6729da57d7bSbt150084 		ixgbe_error(ixgbe,
6739da57d7bSbt150084 		    "Cound not allocate memory for tx work list");
6749da57d7bSbt150084 		return (IXGBE_FAILURE);
6759da57d7bSbt150084 	}
6769da57d7bSbt150084 
6779da57d7bSbt150084 	/*
6789da57d7bSbt150084 	 * Allocate memory for the free list.
6799da57d7bSbt150084 	 */
6809da57d7bSbt150084 	tx_ring->free_list = kmem_zalloc(sizeof (tx_control_block_t *) *
6819da57d7bSbt150084 	    tx_ring->free_list_size, KM_NOSLEEP);
6829da57d7bSbt150084 
6839da57d7bSbt150084 	if (tx_ring->free_list == NULL) {
6849da57d7bSbt150084 		kmem_free(tx_ring->work_list,
6859da57d7bSbt150084 		    sizeof (tx_control_block_t *) * tx_ring->ring_size);
6869da57d7bSbt150084 		tx_ring->work_list = NULL;
6879da57d7bSbt150084 
6889da57d7bSbt150084 		ixgbe_error(ixgbe,
6899da57d7bSbt150084 		    "Cound not allocate memory for tx free list");
6909da57d7bSbt150084 		return (IXGBE_FAILURE);
6919da57d7bSbt150084 	}
6929da57d7bSbt150084 
6939da57d7bSbt150084 	/*
6949da57d7bSbt150084 	 * Allocate memory for the tx control blocks of free list.
6959da57d7bSbt150084 	 */
6969da57d7bSbt150084 	tx_ring->tcb_area =
6979da57d7bSbt150084 	    kmem_zalloc(sizeof (tx_control_block_t) *
6989da57d7bSbt150084 	    tx_ring->free_list_size, KM_NOSLEEP);
6999da57d7bSbt150084 
7009da57d7bSbt150084 	if (tx_ring->tcb_area == NULL) {
7019da57d7bSbt150084 		kmem_free(tx_ring->work_list,
7029da57d7bSbt150084 		    sizeof (tx_control_block_t *) * tx_ring->ring_size);
7039da57d7bSbt150084 		tx_ring->work_list = NULL;
7049da57d7bSbt150084 
7059da57d7bSbt150084 		kmem_free(tx_ring->free_list,
7069da57d7bSbt150084 		    sizeof (tx_control_block_t *) * tx_ring->free_list_size);
7079da57d7bSbt150084 		tx_ring->free_list = NULL;
7089da57d7bSbt150084 
7099da57d7bSbt150084 		ixgbe_error(ixgbe,
7109da57d7bSbt150084 		    "Cound not allocate memory for tx control blocks");
7119da57d7bSbt150084 		return (IXGBE_FAILURE);
7129da57d7bSbt150084 	}
7139da57d7bSbt150084 
7149da57d7bSbt150084 	/*
7159da57d7bSbt150084 	 * Allocate dma memory for the tx control block of free list.
7169da57d7bSbt150084 	 */
7179da57d7bSbt150084 	tcb = tx_ring->tcb_area;
7189da57d7bSbt150084 	for (i = 0; i < tx_ring->free_list_size; i++, tcb++) {
7199da57d7bSbt150084 		ASSERT(tcb != NULL);
7209da57d7bSbt150084 
7219da57d7bSbt150084 		tx_ring->free_list[i] = tcb;
7229da57d7bSbt150084 
7239da57d7bSbt150084 		/*
7249da57d7bSbt150084 		 * Pre-allocate dma handles for transmit. These dma handles
7259da57d7bSbt150084 		 * will be dynamically bound to the data buffers passed down
7269da57d7bSbt150084 		 * from the upper layers at the time of transmitting.
7279da57d7bSbt150084 		 */
7289da57d7bSbt150084 		ret = ddi_dma_alloc_handle(devinfo,
7299da57d7bSbt150084 		    &ixgbe_tx_dma_attr,
7309da57d7bSbt150084 		    DDI_DMA_DONTWAIT, NULL,
7319da57d7bSbt150084 		    &tcb->tx_dma_handle);
7329da57d7bSbt150084 		if (ret != DDI_SUCCESS) {
7339da57d7bSbt150084 			tcb->tx_dma_handle = NULL;
7349da57d7bSbt150084 			ixgbe_error(ixgbe,
7359da57d7bSbt150084 			    "Could not allocate tx dma handle: %x", ret);
7369da57d7bSbt150084 			goto alloc_tcb_lists_fail;
7379da57d7bSbt150084 		}
7389da57d7bSbt150084 
7399da57d7bSbt150084 		/*
7409da57d7bSbt150084 		 * Pre-allocate transmit buffers for packets that the
7419da57d7bSbt150084 		 * size is less than bcopy_thresh.
7429da57d7bSbt150084 		 */
7439da57d7bSbt150084 		tx_buf = &tcb->tx_buf;
7449da57d7bSbt150084 
7459da57d7bSbt150084 		ret = ixgbe_alloc_dma_buffer(ixgbe,
7469da57d7bSbt150084 		    tx_buf, ixgbe->tx_buf_size);
7479da57d7bSbt150084 
7489da57d7bSbt150084 		if (ret != IXGBE_SUCCESS) {
7499da57d7bSbt150084 			ASSERT(tcb->tx_dma_handle != NULL);
7509da57d7bSbt150084 			ddi_dma_free_handle(&tcb->tx_dma_handle);
7519da57d7bSbt150084 			tcb->tx_dma_handle = NULL;
7529da57d7bSbt150084 			ixgbe_error(ixgbe, "Allocate tx dma buffer failed");
7539da57d7bSbt150084 			goto alloc_tcb_lists_fail;
7549da57d7bSbt150084 		}
755edf70dc9SPaul Guo 
756edf70dc9SPaul Guo 		tcb->last_index = MAX_TX_RING_SIZE;
7579da57d7bSbt150084 	}
7589da57d7bSbt150084 
7599da57d7bSbt150084 	return (IXGBE_SUCCESS);
7609da57d7bSbt150084 
7619da57d7bSbt150084 alloc_tcb_lists_fail:
7629da57d7bSbt150084 	ixgbe_free_tcb_lists(tx_ring);
7639da57d7bSbt150084 
7649da57d7bSbt150084 	return (IXGBE_FAILURE);
7659da57d7bSbt150084 }
7669da57d7bSbt150084 
7679da57d7bSbt150084 /*
7689da57d7bSbt150084  * ixgbe_free_tcb_lists - Release the memory allocated for
7699da57d7bSbt150084  * the transmit control bolcks of one ring.
7709da57d7bSbt150084  */
7719da57d7bSbt150084 static void
7729da57d7bSbt150084 ixgbe_free_tcb_lists(ixgbe_tx_ring_t *tx_ring)
7739da57d7bSbt150084 {
7749da57d7bSbt150084 	int i;
7759da57d7bSbt150084 	tx_control_block_t *tcb;
7769da57d7bSbt150084 
7779da57d7bSbt150084 	tcb = tx_ring->tcb_area;
7789da57d7bSbt150084 	if (tcb == NULL)
7799da57d7bSbt150084 		return;
7809da57d7bSbt150084 
7819da57d7bSbt150084 	for (i = 0; i < tx_ring->free_list_size; i++, tcb++) {
7829da57d7bSbt150084 		ASSERT(tcb != NULL);
7839da57d7bSbt150084 
7849da57d7bSbt150084 		/* Free the tx dma handle for dynamical binding */
7859da57d7bSbt150084 		if (tcb->tx_dma_handle != NULL) {
7869da57d7bSbt150084 			ddi_dma_free_handle(&tcb->tx_dma_handle);
7879da57d7bSbt150084 			tcb->tx_dma_handle = NULL;
7889da57d7bSbt150084 		} else {
7899da57d7bSbt150084 			/*
7909da57d7bSbt150084 			 * If the dma handle is NULL, then we don't
7919da57d7bSbt150084 			 * have to check the remaining.
7929da57d7bSbt150084 			 */
7939da57d7bSbt150084 			break;
7949da57d7bSbt150084 		}
7959da57d7bSbt150084 
7969da57d7bSbt150084 		ixgbe_free_dma_buffer(&tcb->tx_buf);
7979da57d7bSbt150084 	}
7989da57d7bSbt150084 
7999da57d7bSbt150084 	if (tx_ring->tcb_area != NULL) {
8009da57d7bSbt150084 		kmem_free(tx_ring->tcb_area,
8019da57d7bSbt150084 		    sizeof (tx_control_block_t) * tx_ring->free_list_size);
8029da57d7bSbt150084 		tx_ring->tcb_area = NULL;
8039da57d7bSbt150084 	}
8049da57d7bSbt150084 
8059da57d7bSbt150084 	if (tx_ring->work_list != NULL) {
8069da57d7bSbt150084 		kmem_free(tx_ring->work_list,
8079da57d7bSbt150084 		    sizeof (tx_control_block_t *) * tx_ring->ring_size);
8089da57d7bSbt150084 		tx_ring->work_list = NULL;
8099da57d7bSbt150084 	}
8109da57d7bSbt150084 
8119da57d7bSbt150084 	if (tx_ring->free_list != NULL) {
8129da57d7bSbt150084 		kmem_free(tx_ring->free_list,
8139da57d7bSbt150084 		    sizeof (tx_control_block_t *) * tx_ring->free_list_size);
8149da57d7bSbt150084 		tx_ring->free_list = NULL;
8159da57d7bSbt150084 	}
8169da57d7bSbt150084 }
8179da57d7bSbt150084 
8189da57d7bSbt150084 /*
8199da57d7bSbt150084  * ixgbe_alloc_rcb_lists - Memory allocation for the receive control blocks
8209da57d7bSbt150084  * of one ring.
8219da57d7bSbt150084  */
8229da57d7bSbt150084 static int
823ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_alloc_rcb_lists(ixgbe_rx_data_t *rx_data)
8249da57d7bSbt150084 {
8259da57d7bSbt150084 	int i;
8269da57d7bSbt150084 	int ret;
8279da57d7bSbt150084 	rx_control_block_t *rcb;
828ea65739eSchenlu chen - Sun Microsystems - Beijing China 	ixgbe_t *ixgbe = rx_data->rx_ring->ixgbe;
8299da57d7bSbt150084 	dma_buffer_t *rx_buf;
8309da57d7bSbt150084 	uint32_t rcb_count;
8319da57d7bSbt150084 
8329da57d7bSbt150084 	/*
8339da57d7bSbt150084 	 * Allocate memory for the rx control blocks for work list and
8349da57d7bSbt150084 	 * free list.
8359da57d7bSbt150084 	 */
836ea65739eSchenlu chen - Sun Microsystems - Beijing China 	rcb_count = rx_data->ring_size + rx_data->free_list_size;
837ea65739eSchenlu chen - Sun Microsystems - Beijing China 	rcb = rx_data->rcb_area;
8389da57d7bSbt150084 
8399da57d7bSbt150084 	for (i = 0; i < rcb_count; i++, rcb++) {
8409da57d7bSbt150084 		ASSERT(rcb != NULL);
8419da57d7bSbt150084 
842ea65739eSchenlu chen - Sun Microsystems - Beijing China 		if (i < rx_data->ring_size) {
8439da57d7bSbt150084 			/* Attach the rx control block to the work list */
844ea65739eSchenlu chen - Sun Microsystems - Beijing China 			rx_data->work_list[i] = rcb;
8459da57d7bSbt150084 		} else {
8469da57d7bSbt150084 			/* Attach the rx control block to the free list */
847ea65739eSchenlu chen - Sun Microsystems - Beijing China 			rx_data->free_list[i - rx_data->ring_size] = rcb;
8489da57d7bSbt150084 		}
8499da57d7bSbt150084 
8509da57d7bSbt150084 		rx_buf = &rcb->rx_buf;
8519da57d7bSbt150084 		ret = ixgbe_alloc_dma_buffer(ixgbe,
8529da57d7bSbt150084 		    rx_buf, ixgbe->rx_buf_size);
8539da57d7bSbt150084 
8549da57d7bSbt150084 		if (ret != IXGBE_SUCCESS) {
8559da57d7bSbt150084 			ixgbe_error(ixgbe, "Allocate rx dma buffer failed");
8569da57d7bSbt150084 			goto alloc_rcb_lists_fail;
8579da57d7bSbt150084 		}
8589da57d7bSbt150084 
8599da57d7bSbt150084 		rx_buf->size -= IPHDR_ALIGN_ROOM;
8609da57d7bSbt150084 		rx_buf->address += IPHDR_ALIGN_ROOM;
8619da57d7bSbt150084 		rx_buf->dma_address += IPHDR_ALIGN_ROOM;
8629da57d7bSbt150084 
863ea65739eSchenlu chen - Sun Microsystems - Beijing China 		rcb->ref_cnt = 1;
864ea65739eSchenlu chen - Sun Microsystems - Beijing China 		rcb->rx_data = (ixgbe_rx_data_t *)rx_data;
8659da57d7bSbt150084 		rcb->free_rtn.free_func = ixgbe_rx_recycle;
8669da57d7bSbt150084 		rcb->free_rtn.free_arg = (char *)rcb;
867*ffd8e883SWinson Wang - Sun Microsystems - Beijing China 		rcb->lro_prev = -1;
868*ffd8e883SWinson Wang - Sun Microsystems - Beijing China 		rcb->lro_next = -1;
869*ffd8e883SWinson Wang - Sun Microsystems - Beijing China 		rcb->lro_pkt = B_FALSE;
8709da57d7bSbt150084 		rcb->mp = desballoc((unsigned char *)
87173cd555cSBin Tu - Sun Microsystems - Beijing China 		    rx_buf->address,
87273cd555cSBin Tu - Sun Microsystems - Beijing China 		    rx_buf->size,
8739da57d7bSbt150084 		    0, &rcb->free_rtn);
8749da57d7bSbt150084 	}
8759da57d7bSbt150084 
8769da57d7bSbt150084 	return (IXGBE_SUCCESS);
8779da57d7bSbt150084 
8789da57d7bSbt150084 alloc_rcb_lists_fail:
879ea65739eSchenlu chen - Sun Microsystems - Beijing China 	ixgbe_free_rcb_lists(rx_data);
8809da57d7bSbt150084 
8819da57d7bSbt150084 	return (IXGBE_FAILURE);
8829da57d7bSbt150084 }
8839da57d7bSbt150084 
8849da57d7bSbt150084 /*
8859da57d7bSbt150084  * ixgbe_free_rcb_lists - Free the receive control blocks of one ring.
8869da57d7bSbt150084  */
8879da57d7bSbt150084 static void
888ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_free_rcb_lists(ixgbe_rx_data_t *rx_data)
8899da57d7bSbt150084 {
890ea65739eSchenlu chen - Sun Microsystems - Beijing China 	ixgbe_t *ixgbe;
8919da57d7bSbt150084 	rx_control_block_t *rcb;
8929da57d7bSbt150084 	uint32_t rcb_count;
893ea65739eSchenlu chen - Sun Microsystems - Beijing China 	uint32_t ref_cnt;
894ea65739eSchenlu chen - Sun Microsystems - Beijing China 	int i;
8959da57d7bSbt150084 
896ea65739eSchenlu chen - Sun Microsystems - Beijing China 	ixgbe = rx_data->rx_ring->ixgbe;
8979da57d7bSbt150084 
898ea65739eSchenlu chen - Sun Microsystems - Beijing China 	mutex_enter(&ixgbe->rx_pending_lock);
899ea65739eSchenlu chen - Sun Microsystems - Beijing China 
900ea65739eSchenlu chen - Sun Microsystems - Beijing China 	rcb = rx_data->rcb_area;
901ea65739eSchenlu chen - Sun Microsystems - Beijing China 	rcb_count = rx_data->ring_size + rx_data->free_list_size;
902ea65739eSchenlu chen - Sun Microsystems - Beijing China 
9039da57d7bSbt150084 	for (i = 0; i < rcb_count; i++, rcb++) {
9049da57d7bSbt150084 		ASSERT(rcb != NULL);
9059da57d7bSbt150084 
906ea65739eSchenlu chen - Sun Microsystems - Beijing China 		ref_cnt = atomic_dec_32_nv(&rcb->ref_cnt);
907ea65739eSchenlu chen - Sun Microsystems - Beijing China 		if (ref_cnt == 0) {
9089da57d7bSbt150084 			if (rcb->mp != NULL) {
9099da57d7bSbt150084 				freemsg(rcb->mp);
9109da57d7bSbt150084 				rcb->mp = NULL;
9119da57d7bSbt150084 			}
9129da57d7bSbt150084 			ixgbe_free_dma_buffer(&rcb->rx_buf);
913ea65739eSchenlu chen - Sun Microsystems - Beijing China 		} else {
914ea65739eSchenlu chen - Sun Microsystems - Beijing China 			atomic_inc_32(&rx_data->rcb_pending);
915ea65739eSchenlu chen - Sun Microsystems - Beijing China 			atomic_inc_32(&ixgbe->rcb_pending);
916ea65739eSchenlu chen - Sun Microsystems - Beijing China 		}
9179da57d7bSbt150084 	}
9189da57d7bSbt150084 
919ea65739eSchenlu chen - Sun Microsystems - Beijing China 	mutex_exit(&ixgbe->rx_pending_lock);
9209da57d7bSbt150084 }
9219da57d7bSbt150084 
9229da57d7bSbt150084 /*
9239da57d7bSbt150084  * ixgbe_set_fma_flags - Set the attribute for fma support.
9249da57d7bSbt150084  */
9259da57d7bSbt150084 void
926837c1ac4SStephen Hanson ixgbe_set_fma_flags(int dma_flag)
9279da57d7bSbt150084 {
9289da57d7bSbt150084 	if (dma_flag) {
9299da57d7bSbt150084 		ixgbe_tx_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR;
9309da57d7bSbt150084 		ixgbe_buf_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR;
9319da57d7bSbt150084 		ixgbe_desc_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR;
9329da57d7bSbt150084 	} else {
9339da57d7bSbt150084 		ixgbe_tx_dma_attr.dma_attr_flags = 0;
9349da57d7bSbt150084 		ixgbe_buf_dma_attr.dma_attr_flags = 0;
9359da57d7bSbt150084 		ixgbe_desc_dma_attr.dma_attr_flags = 0;
9369da57d7bSbt150084 	}
9379da57d7bSbt150084 }
938