xref: /onnv-gate/usr/src/uts/common/io/e1000g/e1000g_alloc.c (revision 12853:636a63adb7b9)
13526Sxy150489 /*
23526Sxy150489  * This file is provided under a CDDLv1 license.  When using or
33526Sxy150489  * redistributing this file, you may do so under this license.
43526Sxy150489  * In redistributing this file this license must be included
53526Sxy150489  * and no other modification of this header file is permitted.
63526Sxy150489  *
73526Sxy150489  * CDDL LICENSE SUMMARY
83526Sxy150489  *
98850SMin.Xu@Sun.COM  * Copyright(c) 1999 - 2009 Intel Corporation. All rights reserved.
103526Sxy150489  *
113526Sxy150489  * The contents of this file are subject to the terms of Version
123526Sxy150489  * 1.0 of the Common Development and Distribution License (the "License").
133526Sxy150489  *
143526Sxy150489  * You should have received a copy of the License with this software.
153526Sxy150489  * You can obtain a copy of the License at
163526Sxy150489  *	http://www.opensolaris.org/os/licensing.
173526Sxy150489  * See the License for the specific language governing permissions
183526Sxy150489  * and limitations under the License.
193526Sxy150489  */
203526Sxy150489 
213526Sxy150489 /*
22*12853SChangqing.Li@Sun.COM  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
233526Sxy150489  */
243526Sxy150489 
253526Sxy150489 /*
263526Sxy150489  * **********************************************************************
273526Sxy150489  * Module Name:								*
284919Sxy150489  *   e1000g_alloc.c							*
293526Sxy150489  *									*
303526Sxy150489  * Abstract:								*
314919Sxy150489  *   This file contains some routines that take care of			*
324919Sxy150489  *   memory allocation for descriptors and buffers.			*
333526Sxy150489  *									*
343526Sxy150489  * **********************************************************************
353526Sxy150489  */
363526Sxy150489 
373526Sxy150489 #include "e1000g_sw.h"
383526Sxy150489 #include "e1000g_debug.h"
393526Sxy150489 
403526Sxy150489 #define	TX_SW_PKT_AREA_SZ \
414919Sxy150489 	(sizeof (tx_sw_packet_t) * Adapter->tx_freelist_num)
423526Sxy150489 
433526Sxy150489 static int e1000g_alloc_tx_descriptors(e1000g_tx_ring_t *);
448850SMin.Xu@Sun.COM static int e1000g_alloc_rx_descriptors(e1000g_rx_data_t *);
453526Sxy150489 static void e1000g_free_tx_descriptors(e1000g_tx_ring_t *);
468850SMin.Xu@Sun.COM static void e1000g_free_rx_descriptors(e1000g_rx_data_t *);
473526Sxy150489 static int e1000g_alloc_tx_packets(e1000g_tx_ring_t *);
488850SMin.Xu@Sun.COM static int e1000g_alloc_rx_packets(e1000g_rx_data_t *);
493526Sxy150489 static void e1000g_free_tx_packets(e1000g_tx_ring_t *);
50*12853SChangqing.Li@Sun.COM static void e1000g_free_rx_packets(e1000g_rx_data_t *, boolean_t);
514919Sxy150489 static int e1000g_alloc_dma_buffer(struct e1000g *,
524919Sxy150489     dma_buffer_t *, size_t, ddi_dma_attr_t *p_dma_attr);
538178SChenlu.Chen@Sun.COM 
548178SChenlu.Chen@Sun.COM /*
558178SChenlu.Chen@Sun.COM  * In order to avoid address error crossing 64KB boundary
568178SChenlu.Chen@Sun.COM  * during PCI-X packets receving, e1000g_alloc_dma_buffer_82546
578178SChenlu.Chen@Sun.COM  * is used by some necessary adapter types.
588178SChenlu.Chen@Sun.COM  */
598178SChenlu.Chen@Sun.COM static int e1000g_alloc_dma_buffer_82546(struct e1000g *,
608178SChenlu.Chen@Sun.COM     dma_buffer_t *, size_t, ddi_dma_attr_t *p_dma_attr);
618178SChenlu.Chen@Sun.COM static int e1000g_dma_mem_alloc_82546(dma_buffer_t *buf,
628178SChenlu.Chen@Sun.COM     size_t size, size_t *len);
638178SChenlu.Chen@Sun.COM static boolean_t e1000g_cross_64k_bound(void *, uintptr_t);
648178SChenlu.Chen@Sun.COM 
653526Sxy150489 static void e1000g_free_dma_buffer(dma_buffer_t *);
663526Sxy150489 #ifdef __sparc
673526Sxy150489 static int e1000g_alloc_dvma_buffer(struct e1000g *, dma_buffer_t *, size_t);
683526Sxy150489 static void e1000g_free_dvma_buffer(dma_buffer_t *);
693526Sxy150489 #endif
703526Sxy150489 static int e1000g_alloc_descriptors(struct e1000g *Adapter);
714919Sxy150489 static void e1000g_free_descriptors(struct e1000g *Adapter);
723526Sxy150489 static int e1000g_alloc_packets(struct e1000g *Adapter);
734919Sxy150489 static void e1000g_free_packets(struct e1000g *Adapter);
748850SMin.Xu@Sun.COM static p_rx_sw_packet_t e1000g_alloc_rx_sw_packet(e1000g_rx_data_t *,
754919Sxy150489     ddi_dma_attr_t *p_dma_attr);
764919Sxy150489 
774919Sxy150489 /* DMA access attributes for descriptors <Little Endian> */
784919Sxy150489 static ddi_device_acc_attr_t e1000g_desc_acc_attr = {
794919Sxy150489 	DDI_DEVICE_ATTR_V0,
804919Sxy150489 	DDI_STRUCTURE_LE_ACC,
8111236SStephen.Hanson@Sun.COM 	DDI_STRICTORDER_ACC
824919Sxy150489 };
834919Sxy150489 
844919Sxy150489 /* DMA access attributes for DMA buffers */
854919Sxy150489 #ifdef __sparc
864919Sxy150489 static ddi_device_acc_attr_t e1000g_buf_acc_attr = {
874919Sxy150489 	DDI_DEVICE_ATTR_V0,
884919Sxy150489 	DDI_STRUCTURE_BE_ACC,
894919Sxy150489 	DDI_STRICTORDER_ACC,
904919Sxy150489 };
914919Sxy150489 #else
924919Sxy150489 static ddi_device_acc_attr_t e1000g_buf_acc_attr = {
934919Sxy150489 	DDI_DEVICE_ATTR_V0,
944919Sxy150489 	DDI_STRUCTURE_LE_ACC,
954919Sxy150489 	DDI_STRICTORDER_ACC,
964919Sxy150489 };
974919Sxy150489 #endif
984919Sxy150489 
994919Sxy150489 /* DMA attributes for tx mblk buffers */
1004919Sxy150489 static ddi_dma_attr_t e1000g_tx_dma_attr = {
1014919Sxy150489 	DMA_ATTR_V0,		/* version of this structure */
1024919Sxy150489 	0,			/* lowest usable address */
1034919Sxy150489 	0xffffffffffffffffULL,	/* highest usable address */
1044919Sxy150489 	0x7fffffff,		/* maximum DMAable byte count */
1054919Sxy150489 	1,			/* alignment in bytes */
1064919Sxy150489 	0x7ff,			/* burst sizes (any?) */
1074919Sxy150489 	1,			/* minimum transfer */
1084919Sxy150489 	0xffffffffU,		/* maximum transfer */
1094919Sxy150489 	0xffffffffffffffffULL,	/* maximum segment length */
1107607STed.You@Sun.COM 	MAX_COOKIES,		/* maximum number of segments */
1114919Sxy150489 	1,			/* granularity */
1125273Sgl147354 	DDI_DMA_FLAGERR,	/* dma_attr_flags */
1134919Sxy150489 };
1144919Sxy150489 
1154919Sxy150489 /* DMA attributes for pre-allocated rx/tx buffers */
1164919Sxy150489 static ddi_dma_attr_t e1000g_buf_dma_attr = {
1174919Sxy150489 	DMA_ATTR_V0,		/* version of this structure */
1184919Sxy150489 	0,			/* lowest usable address */
1194919Sxy150489 	0xffffffffffffffffULL,	/* highest usable address */
1204919Sxy150489 	0x7fffffff,		/* maximum DMAable byte count */
1214919Sxy150489 	1,			/* alignment in bytes */
1224919Sxy150489 	0x7ff,			/* burst sizes (any?) */
1234919Sxy150489 	1,			/* minimum transfer */
1244919Sxy150489 	0xffffffffU,		/* maximum transfer */
1254919Sxy150489 	0xffffffffffffffffULL,	/* maximum segment length */
1264919Sxy150489 	1,			/* maximum number of segments */
1274919Sxy150489 	1,			/* granularity */
1285273Sgl147354 	DDI_DMA_FLAGERR,	/* dma_attr_flags */
1294919Sxy150489 };
1304919Sxy150489 
1314919Sxy150489 /* DMA attributes for rx/tx descriptors */
1324919Sxy150489 static ddi_dma_attr_t e1000g_desc_dma_attr = {
1334919Sxy150489 	DMA_ATTR_V0,		/* version of this structure */
1344919Sxy150489 	0,			/* lowest usable address */
1354919Sxy150489 	0xffffffffffffffffULL,	/* highest usable address */
1364919Sxy150489 	0x7fffffff,		/* maximum DMAable byte count */
1378178SChenlu.Chen@Sun.COM 	E1000_MDALIGN,		/* default alignment is 4k but can be changed */
1384919Sxy150489 	0x7ff,			/* burst sizes (any?) */
1394919Sxy150489 	1,			/* minimum transfer */
1404919Sxy150489 	0xffffffffU,		/* maximum transfer */
1414919Sxy150489 	0xffffffffffffffffULL,	/* maximum segment length */
1424919Sxy150489 	1,			/* maximum number of segments */
1434919Sxy150489 	1,			/* granularity */
1445273Sgl147354 	DDI_DMA_FLAGERR,	/* dma_attr_flags */
1454919Sxy150489 };
1463526Sxy150489 
1473526Sxy150489 #ifdef __sparc
1483526Sxy150489 static ddi_dma_lim_t e1000g_dma_limits = {
1493526Sxy150489 	(uint_t)0,		/* dlim_addr_lo */
1503526Sxy150489 	(uint_t)0xffffffff,	/* dlim_addr_hi */
1513526Sxy150489 	(uint_t)0xffffffff,	/* dlim_cntr_max */
1523526Sxy150489 	(uint_t)0xfc00fc,	/* dlim_burstsizes for 32 and 64 bit xfers */
1533526Sxy150489 	0x1,			/* dlim_minxfer */
1543526Sxy150489 	1024			/* dlim_speed */
1553526Sxy150489 };
1563526Sxy150489 #endif
1573526Sxy150489 
1583526Sxy150489 #ifdef __sparc
1593526Sxy150489 static dma_type_t e1000g_dma_type = USE_DVMA;
1603526Sxy150489 #else
1613526Sxy150489 static dma_type_t e1000g_dma_type = USE_DMA;
1623526Sxy150489 #endif
1633526Sxy150489 
1643526Sxy150489 extern krwlock_t e1000g_dma_type_lock;
1653526Sxy150489 
1664919Sxy150489 
1673526Sxy150489 int
e1000g_alloc_dma_resources(struct e1000g * Adapter)1683526Sxy150489 e1000g_alloc_dma_resources(struct e1000g *Adapter)
1693526Sxy150489 {
1704919Sxy150489 	int result;
1714919Sxy150489 
1724919Sxy150489 	result = DDI_FAILURE;
1733526Sxy150489 
1744919Sxy150489 	while ((result != DDI_SUCCESS) &&
1754919Sxy150489 	    (Adapter->tx_desc_num >= MIN_NUM_TX_DESCRIPTOR) &&
1764919Sxy150489 	    (Adapter->rx_desc_num >= MIN_NUM_RX_DESCRIPTOR) &&
177*12853SChangqing.Li@Sun.COM 	    (Adapter->tx_freelist_num >= MIN_NUM_TX_FREELIST)) {
1784919Sxy150489 
1794919Sxy150489 		result = e1000g_alloc_descriptors(Adapter);
1804919Sxy150489 
1814919Sxy150489 		if (result == DDI_SUCCESS) {
1824919Sxy150489 			result = e1000g_alloc_packets(Adapter);
1834919Sxy150489 
1844919Sxy150489 			if (result != DDI_SUCCESS)
1854919Sxy150489 				e1000g_free_descriptors(Adapter);
1864919Sxy150489 		}
1873526Sxy150489 
1884919Sxy150489 		/*
1894919Sxy150489 		 * If the allocation fails due to resource shortage,
1904919Sxy150489 		 * we'll reduce the numbers of descriptors/buffers by
1914919Sxy150489 		 * half, and try the allocation again.
1924919Sxy150489 		 */
1934919Sxy150489 		if (result != DDI_SUCCESS) {
1944919Sxy150489 			/*
1954919Sxy150489 			 * We must ensure the number of descriptors
1964919Sxy150489 			 * is always a multiple of 8.
1974919Sxy150489 			 */
1984919Sxy150489 			Adapter->tx_desc_num =
1994919Sxy150489 			    (Adapter->tx_desc_num >> 4) << 3;
2004919Sxy150489 			Adapter->rx_desc_num =
2014919Sxy150489 			    (Adapter->rx_desc_num >> 4) << 3;
2023526Sxy150489 
2034919Sxy150489 			Adapter->tx_freelist_num >>= 1;
2044919Sxy150489 		}
2053526Sxy150489 	}
2063526Sxy150489 
2074919Sxy150489 	return (result);
2083526Sxy150489 }
2093526Sxy150489 
2103526Sxy150489 /*
2114919Sxy150489  * e1000g_alloc_descriptors - allocate DMA buffers for descriptors
2124919Sxy150489  *
2134919Sxy150489  * This routine allocates neccesary DMA buffers for
2144919Sxy150489  *	Transmit Descriptor Area
2154919Sxy150489  *	Receive Descrpitor Area
2163526Sxy150489  */
2173526Sxy150489 static int
e1000g_alloc_descriptors(struct e1000g * Adapter)2183526Sxy150489 e1000g_alloc_descriptors(struct e1000g *Adapter)
2193526Sxy150489 {
2203526Sxy150489 	int result;
2213526Sxy150489 	e1000g_tx_ring_t *tx_ring;
2228850SMin.Xu@Sun.COM 	e1000g_rx_data_t *rx_data;
2233526Sxy150489 
2248417SChenlu.Chen@Sun.COM 	if (Adapter->mem_workaround_82546 &&
2258417SChenlu.Chen@Sun.COM 	    ((Adapter->shared.mac.type == e1000_82545) ||
2268178SChenlu.Chen@Sun.COM 	    (Adapter->shared.mac.type == e1000_82546) ||
2278417SChenlu.Chen@Sun.COM 	    (Adapter->shared.mac.type == e1000_82546_rev_3))) {
2288178SChenlu.Chen@Sun.COM 		/* Align on a 64k boundary for these adapter types */
2298178SChenlu.Chen@Sun.COM 		Adapter->desc_align = E1000_MDALIGN_82546;
2308178SChenlu.Chen@Sun.COM 	} else {
2318178SChenlu.Chen@Sun.COM 		/* Align on a 4k boundary for all other adapter types */
2328178SChenlu.Chen@Sun.COM 		Adapter->desc_align = E1000_MDALIGN;
2338178SChenlu.Chen@Sun.COM 	}
2348178SChenlu.Chen@Sun.COM 
2353526Sxy150489 	tx_ring = Adapter->tx_ring;
2363526Sxy150489 
2373526Sxy150489 	result = e1000g_alloc_tx_descriptors(tx_ring);
2383526Sxy150489 	if (result != DDI_SUCCESS)
2393526Sxy150489 		return (DDI_FAILURE);
2403526Sxy150489 
2418850SMin.Xu@Sun.COM 	rx_data = Adapter->rx_ring->rx_data;
2423526Sxy150489 
2438850SMin.Xu@Sun.COM 	result = e1000g_alloc_rx_descriptors(rx_data);
2443526Sxy150489 	if (result != DDI_SUCCESS) {
2453526Sxy150489 		e1000g_free_tx_descriptors(tx_ring);
2463526Sxy150489 		return (DDI_FAILURE);
2473526Sxy150489 	}
2483526Sxy150489 
2493526Sxy150489 	return (DDI_SUCCESS);
2503526Sxy150489 }
2513526Sxy150489 
2524919Sxy150489 static void
e1000g_free_descriptors(struct e1000g * Adapter)2534919Sxy150489 e1000g_free_descriptors(struct e1000g *Adapter)
2544919Sxy150489 {
2554919Sxy150489 	e1000g_tx_ring_t *tx_ring;
2568850SMin.Xu@Sun.COM 	e1000g_rx_data_t *rx_data;
2574919Sxy150489 
2584919Sxy150489 	tx_ring = Adapter->tx_ring;
2598850SMin.Xu@Sun.COM 	rx_data = Adapter->rx_ring->rx_data;
2604919Sxy150489 
2614919Sxy150489 	e1000g_free_tx_descriptors(tx_ring);
2628850SMin.Xu@Sun.COM 	e1000g_free_rx_descriptors(rx_data);
2634919Sxy150489 }
2644919Sxy150489 
2653526Sxy150489 static int
e1000g_alloc_tx_descriptors(e1000g_tx_ring_t * tx_ring)2663526Sxy150489 e1000g_alloc_tx_descriptors(e1000g_tx_ring_t *tx_ring)
2673526Sxy150489 {
2683526Sxy150489 	int mystat;
2693526Sxy150489 	boolean_t alloc_flag;
2703526Sxy150489 	size_t size;
2713526Sxy150489 	size_t len;
2723526Sxy150489 	uintptr_t templong;
2733526Sxy150489 	uint_t cookie_count;
2743526Sxy150489 	dev_info_t *devinfo;
2753526Sxy150489 	ddi_dma_cookie_t cookie;
2763526Sxy150489 	struct e1000g *Adapter;
2774919Sxy150489 	ddi_dma_attr_t dma_attr;
2783526Sxy150489 
2793526Sxy150489 	Adapter = tx_ring->adapter;
2804919Sxy150489 	devinfo = Adapter->dip;
2813526Sxy150489 
2823526Sxy150489 	alloc_flag = B_FALSE;
2834919Sxy150489 	dma_attr = e1000g_desc_dma_attr;
2843526Sxy150489 
2853526Sxy150489 	/*
2863526Sxy150489 	 * Solaris 7 has a problem with allocating physically contiguous memory
2873526Sxy150489 	 * that is aligned on a 4K boundary. The transmit and rx descriptors
2883526Sxy150489 	 * need to aligned on a 4kbyte boundary. We first try to allocate the
2893526Sxy150489 	 * memory with DMA attributes set to 4K alignment and also no scatter/
2903526Sxy150489 	 * gather mechanism specified. In most cases, this does not allocate
2913526Sxy150489 	 * memory aligned at a 4Kbyte boundary. We then try asking for memory
2923526Sxy150489 	 * aligned on 4K boundary with scatter/gather set to 2. This works when
2933526Sxy150489 	 * the amount of memory is less than 4k i.e a page size. If neither of
2943526Sxy150489 	 * these options work or if the number of descriptors is greater than
2953526Sxy150489 	 * 4K, ie more than 256 descriptors, we allocate 4k extra memory and
2963526Sxy150489 	 * and then align the memory at a 4k boundary.
2973526Sxy150489 	 */
2984919Sxy150489 	size = sizeof (struct e1000_tx_desc) * Adapter->tx_desc_num;
2993526Sxy150489 
3003526Sxy150489 	/*
3013526Sxy150489 	 * Memory allocation for the transmit buffer descriptors.
3023526Sxy150489 	 */
3034919Sxy150489 	dma_attr.dma_attr_sgllen = 1;
3048178SChenlu.Chen@Sun.COM 	dma_attr.dma_attr_align = Adapter->desc_align;
3053526Sxy150489 
3063526Sxy150489 	/*
3073526Sxy150489 	 * Allocate a new DMA handle for the transmit descriptor
3083526Sxy150489 	 * memory area.
3093526Sxy150489 	 */
3104919Sxy150489 	mystat = ddi_dma_alloc_handle(devinfo, &dma_attr,
3113526Sxy150489 	    DDI_DMA_DONTWAIT, 0,
3123526Sxy150489 	    &tx_ring->tbd_dma_handle);
3133526Sxy150489 
3143526Sxy150489 	if (mystat != DDI_SUCCESS) {
3154919Sxy150489 		E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
3163526Sxy150489 		    "Could not allocate tbd dma handle: %d", mystat);
3173526Sxy150489 		tx_ring->tbd_dma_handle = NULL;
3183526Sxy150489 		return (DDI_FAILURE);
3193526Sxy150489 	}
3203526Sxy150489 
3213526Sxy150489 	/*
3223526Sxy150489 	 * Allocate memory to DMA data to and from the transmit
3233526Sxy150489 	 * descriptors.
3243526Sxy150489 	 */
3253526Sxy150489 	mystat = ddi_dma_mem_alloc(tx_ring->tbd_dma_handle,
3263526Sxy150489 	    size,
3274919Sxy150489 	    &e1000g_desc_acc_attr, DDI_DMA_CONSISTENT,
3283526Sxy150489 	    DDI_DMA_DONTWAIT, 0,
3293526Sxy150489 	    (caddr_t *)&tx_ring->tbd_area,
3303526Sxy150489 	    &len, &tx_ring->tbd_acc_handle);
3313526Sxy150489 
3323526Sxy150489 	if ((mystat != DDI_SUCCESS) ||
3338178SChenlu.Chen@Sun.COM 	    ((uintptr_t)tx_ring->tbd_area & (Adapter->desc_align - 1))) {
3343526Sxy150489 		if (mystat == DDI_SUCCESS) {
3353526Sxy150489 			ddi_dma_mem_free(&tx_ring->tbd_acc_handle);
3363526Sxy150489 			tx_ring->tbd_acc_handle = NULL;
3373526Sxy150489 			tx_ring->tbd_area = NULL;
3383526Sxy150489 		}
3393526Sxy150489 		if (tx_ring->tbd_dma_handle != NULL) {
3403526Sxy150489 			ddi_dma_free_handle(&tx_ring->tbd_dma_handle);
3413526Sxy150489 			tx_ring->tbd_dma_handle = NULL;
3423526Sxy150489 		}
3433526Sxy150489 		alloc_flag = B_FALSE;
3443526Sxy150489 	} else
3453526Sxy150489 		alloc_flag = B_TRUE;
3463526Sxy150489 
3473526Sxy150489 	/*
3483526Sxy150489 	 * Initialize the entire transmit buffer descriptor area to zero
3493526Sxy150489 	 */
3503526Sxy150489 	if (alloc_flag)
3513526Sxy150489 		bzero(tx_ring->tbd_area, len);
3523526Sxy150489 
3533526Sxy150489 	/*
3543526Sxy150489 	 * If the previous DMA attributes setting could not give us contiguous
3553526Sxy150489 	 * memory or the number of descriptors is greater than the page size,
3568178SChenlu.Chen@Sun.COM 	 * we allocate extra memory and then align it at appropriate boundary.
3573526Sxy150489 	 */
3583526Sxy150489 	if (!alloc_flag) {
3598178SChenlu.Chen@Sun.COM 		size = size + Adapter->desc_align;
3603526Sxy150489 
3613526Sxy150489 		/*
3623526Sxy150489 		 * DMA attributes set to no scatter/gather and 16 bit alignment
3633526Sxy150489 		 */
3644919Sxy150489 		dma_attr.dma_attr_align = 1;
3654919Sxy150489 		dma_attr.dma_attr_sgllen = 1;
3663526Sxy150489 
3673526Sxy150489 		/*
3683526Sxy150489 		 * Allocate a new DMA handle for the transmit descriptor memory
3693526Sxy150489 		 * area.
3703526Sxy150489 		 */
3714919Sxy150489 		mystat = ddi_dma_alloc_handle(devinfo, &dma_attr,
3723526Sxy150489 		    DDI_DMA_DONTWAIT, 0,
3733526Sxy150489 		    &tx_ring->tbd_dma_handle);
3743526Sxy150489 
3753526Sxy150489 		if (mystat != DDI_SUCCESS) {
3764919Sxy150489 			E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
3773526Sxy150489 			    "Could not re-allocate tbd dma handle: %d", mystat);
3783526Sxy150489 			tx_ring->tbd_dma_handle = NULL;
3793526Sxy150489 			return (DDI_FAILURE);
3803526Sxy150489 		}
3813526Sxy150489 
3823526Sxy150489 		/*
3833526Sxy150489 		 * Allocate memory to DMA data to and from the transmit
3843526Sxy150489 		 * descriptors.
3853526Sxy150489 		 */
3863526Sxy150489 		mystat = ddi_dma_mem_alloc(tx_ring->tbd_dma_handle,
3873526Sxy150489 		    size,
3884919Sxy150489 		    &e1000g_desc_acc_attr, DDI_DMA_CONSISTENT,
3893526Sxy150489 		    DDI_DMA_DONTWAIT, 0,
3903526Sxy150489 		    (caddr_t *)&tx_ring->tbd_area,
3913526Sxy150489 		    &len, &tx_ring->tbd_acc_handle);
3923526Sxy150489 
3933526Sxy150489 		if (mystat != DDI_SUCCESS) {
3944919Sxy150489 			E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
3953526Sxy150489 			    "Could not allocate tbd dma memory: %d", mystat);
3963526Sxy150489 			tx_ring->tbd_acc_handle = NULL;
3973526Sxy150489 			tx_ring->tbd_area = NULL;
3983526Sxy150489 			if (tx_ring->tbd_dma_handle != NULL) {
3993526Sxy150489 				ddi_dma_free_handle(&tx_ring->tbd_dma_handle);
4003526Sxy150489 				tx_ring->tbd_dma_handle = NULL;
4013526Sxy150489 			}
4023526Sxy150489 			return (DDI_FAILURE);
4033526Sxy150489 		} else
4043526Sxy150489 			alloc_flag = B_TRUE;
4053526Sxy150489 
4063526Sxy150489 		/*
4073526Sxy150489 		 * Initialize the entire transmit buffer descriptor area to zero
4083526Sxy150489 		 */
4093526Sxy150489 		bzero(tx_ring->tbd_area, len);
4103526Sxy150489 		/*
4113526Sxy150489 		 * Memory has been allocated with the ddi_dma_mem_alloc call,
4128178SChenlu.Chen@Sun.COM 		 * but has not been aligned.
4138178SChenlu.Chen@Sun.COM 		 * We now align it on the appropriate boundary.
4143526Sxy150489 		 */
4158178SChenlu.Chen@Sun.COM 		templong = P2NPHASE((uintptr_t)tx_ring->tbd_area,
4168178SChenlu.Chen@Sun.COM 		    Adapter->desc_align);
4173526Sxy150489 		len = size - templong;
4183526Sxy150489 		templong += (uintptr_t)tx_ring->tbd_area;
4193526Sxy150489 		tx_ring->tbd_area = (struct e1000_tx_desc *)templong;
4203526Sxy150489 	}	/* alignment workaround */
4213526Sxy150489 
4223526Sxy150489 	/*
4233526Sxy150489 	 * Transmit buffer descriptor memory allocation succeeded
4243526Sxy150489 	 */
4253526Sxy150489 	ASSERT(alloc_flag);
4263526Sxy150489 
4273526Sxy150489 	/*
4283526Sxy150489 	 * Allocates DMA resources for the memory that was allocated by
4293526Sxy150489 	 * the ddi_dma_mem_alloc call. The DMA resources then get bound to the
4303526Sxy150489 	 * the memory address
4313526Sxy150489 	 */
4323526Sxy150489 	mystat = ddi_dma_addr_bind_handle(tx_ring->tbd_dma_handle,
4333526Sxy150489 	    (struct as *)NULL, (caddr_t)tx_ring->tbd_area,
4343526Sxy150489 	    len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
4354919Sxy150489 	    DDI_DMA_DONTWAIT, 0, &cookie, &cookie_count);
4363526Sxy150489 
4373526Sxy150489 	if (mystat != DDI_SUCCESS) {
4384919Sxy150489 		E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
4393526Sxy150489 		    "Could not bind tbd dma resource: %d", mystat);
4403526Sxy150489 		if (tx_ring->tbd_acc_handle != NULL) {
4413526Sxy150489 			ddi_dma_mem_free(&tx_ring->tbd_acc_handle);
4423526Sxy150489 			tx_ring->tbd_acc_handle = NULL;
4433526Sxy150489 			tx_ring->tbd_area = NULL;
4443526Sxy150489 		}
4453526Sxy150489 		if (tx_ring->tbd_dma_handle != NULL) {
4463526Sxy150489 			ddi_dma_free_handle(&tx_ring->tbd_dma_handle);
4473526Sxy150489 			tx_ring->tbd_dma_handle = NULL;
4483526Sxy150489 		}
4493526Sxy150489 		return (DDI_FAILURE);
4503526Sxy150489 	}
4513526Sxy150489 
4523526Sxy150489 	ASSERT(cookie_count == 1);	/* 1 cookie */
4533526Sxy150489 
4543526Sxy150489 	if (cookie_count != 1) {
4554919Sxy150489 		E1000G_DEBUGLOG_2(Adapter, E1000G_WARN_LEVEL,
4563526Sxy150489 		    "Could not bind tbd dma resource in a single frag. "
4573526Sxy150489 		    "Count - %d Len - %d", cookie_count, len);
4583526Sxy150489 		e1000g_free_tx_descriptors(tx_ring);
4593526Sxy150489 		return (DDI_FAILURE);
4603526Sxy150489 	}
4613526Sxy150489 
4623526Sxy150489 	tx_ring->tbd_dma_addr = cookie.dmac_laddress;
4633526Sxy150489 	tx_ring->tbd_first = tx_ring->tbd_area;
4643526Sxy150489 	tx_ring->tbd_last = tx_ring->tbd_first +
4654919Sxy150489 	    (Adapter->tx_desc_num - 1);
4663526Sxy150489 
4673526Sxy150489 	return (DDI_SUCCESS);
4683526Sxy150489 }
4693526Sxy150489 
4703526Sxy150489 static int
e1000g_alloc_rx_descriptors(e1000g_rx_data_t * rx_data)4718850SMin.Xu@Sun.COM e1000g_alloc_rx_descriptors(e1000g_rx_data_t *rx_data)
4723526Sxy150489 {
4733526Sxy150489 	int mystat;
4743526Sxy150489 	boolean_t alloc_flag;
4753526Sxy150489 	size_t size;
4763526Sxy150489 	size_t len;
4773526Sxy150489 	uintptr_t templong;
4783526Sxy150489 	uint_t cookie_count;
4793526Sxy150489 	dev_info_t *devinfo;
4803526Sxy150489 	ddi_dma_cookie_t cookie;
4813526Sxy150489 	struct e1000g *Adapter;
4824919Sxy150489 	ddi_dma_attr_t dma_attr;
4833526Sxy150489 
4848850SMin.Xu@Sun.COM 	Adapter = rx_data->rx_ring->adapter;
4854919Sxy150489 	devinfo = Adapter->dip;
4863526Sxy150489 
4873526Sxy150489 	alloc_flag = B_FALSE;
4884919Sxy150489 	dma_attr = e1000g_desc_dma_attr;
4893526Sxy150489 
4903526Sxy150489 	/*
4913526Sxy150489 	 * Memory allocation for the receive buffer descriptors.
4923526Sxy150489 	 */
4934919Sxy150489 	size = (sizeof (struct e1000_rx_desc)) * Adapter->rx_desc_num;
4943526Sxy150489 
4953526Sxy150489 	/*
4968178SChenlu.Chen@Sun.COM 	 * Asking for aligned memory with DMA attributes set for suitable value
4973526Sxy150489 	 */
4984919Sxy150489 	dma_attr.dma_attr_sgllen = 1;
4998178SChenlu.Chen@Sun.COM 	dma_attr.dma_attr_align = Adapter->desc_align;
5003526Sxy150489 
5013526Sxy150489 	/*
5024919Sxy150489 	 * Allocate a new DMA handle for the receive descriptors
5033526Sxy150489 	 */
5044919Sxy150489 	mystat = ddi_dma_alloc_handle(devinfo, &dma_attr,
5053526Sxy150489 	    DDI_DMA_DONTWAIT, 0,
5068850SMin.Xu@Sun.COM 	    &rx_data->rbd_dma_handle);
5073526Sxy150489 
5083526Sxy150489 	if (mystat != DDI_SUCCESS) {
5094919Sxy150489 		E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
5103526Sxy150489 		    "Could not allocate rbd dma handle: %d", mystat);
5118850SMin.Xu@Sun.COM 		rx_data->rbd_dma_handle = NULL;
5123526Sxy150489 		return (DDI_FAILURE);
5133526Sxy150489 	}
5143526Sxy150489 	/*
5153526Sxy150489 	 * Allocate memory to DMA data to and from the receive
5163526Sxy150489 	 * descriptors.
5173526Sxy150489 	 */
5188850SMin.Xu@Sun.COM 	mystat = ddi_dma_mem_alloc(rx_data->rbd_dma_handle,
5193526Sxy150489 	    size,
5204919Sxy150489 	    &e1000g_desc_acc_attr, DDI_DMA_CONSISTENT,
5213526Sxy150489 	    DDI_DMA_DONTWAIT, 0,
5228850SMin.Xu@Sun.COM 	    (caddr_t *)&rx_data->rbd_area,
5238850SMin.Xu@Sun.COM 	    &len, &rx_data->rbd_acc_handle);
5243526Sxy150489 
5253526Sxy150489 	/*
5263526Sxy150489 	 * Check if memory allocation succeeded and also if the
5273526Sxy150489 	 * allocated memory is aligned correctly.
5283526Sxy150489 	 */
5293526Sxy150489 	if ((mystat != DDI_SUCCESS) ||
5308850SMin.Xu@Sun.COM 	    ((uintptr_t)rx_data->rbd_area & (Adapter->desc_align - 1))) {
5313526Sxy150489 		if (mystat == DDI_SUCCESS) {
5328850SMin.Xu@Sun.COM 			ddi_dma_mem_free(&rx_data->rbd_acc_handle);
5338850SMin.Xu@Sun.COM 			rx_data->rbd_acc_handle = NULL;
5348850SMin.Xu@Sun.COM 			rx_data->rbd_area = NULL;
5353526Sxy150489 		}
5368850SMin.Xu@Sun.COM 		if (rx_data->rbd_dma_handle != NULL) {
5378850SMin.Xu@Sun.COM 			ddi_dma_free_handle(&rx_data->rbd_dma_handle);
5388850SMin.Xu@Sun.COM 			rx_data->rbd_dma_handle = NULL;
5393526Sxy150489 		}
5403526Sxy150489 		alloc_flag = B_FALSE;
5413526Sxy150489 	} else
5423526Sxy150489 		alloc_flag = B_TRUE;
5433526Sxy150489 
5443526Sxy150489 	/*
5453526Sxy150489 	 * Initialize the allocated receive descriptor memory to zero.
5463526Sxy150489 	 */
5473526Sxy150489 	if (alloc_flag)
5488850SMin.Xu@Sun.COM 		bzero((caddr_t)rx_data->rbd_area, len);
5493526Sxy150489 
5503526Sxy150489 	/*
5514919Sxy150489 	 * If memory allocation did not succeed, do the alignment ourselves
5523526Sxy150489 	 */
5533526Sxy150489 	if (!alloc_flag) {
5544919Sxy150489 		dma_attr.dma_attr_align = 1;
5554919Sxy150489 		dma_attr.dma_attr_sgllen = 1;
5568178SChenlu.Chen@Sun.COM 		size = size + Adapter->desc_align;
5573526Sxy150489 		/*
5584919Sxy150489 		 * Allocate a new DMA handle for the receive descriptor.
5593526Sxy150489 		 */
5604919Sxy150489 		mystat = ddi_dma_alloc_handle(devinfo, &dma_attr,
5613526Sxy150489 		    DDI_DMA_DONTWAIT, 0,
5628850SMin.Xu@Sun.COM 		    &rx_data->rbd_dma_handle);
5633526Sxy150489 
5643526Sxy150489 		if (mystat != DDI_SUCCESS) {
5654919Sxy150489 			E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
5663526Sxy150489 			    "Could not re-allocate rbd dma handle: %d", mystat);
5678850SMin.Xu@Sun.COM 			rx_data->rbd_dma_handle = NULL;
5683526Sxy150489 			return (DDI_FAILURE);
5693526Sxy150489 		}
5703526Sxy150489 		/*
5713526Sxy150489 		 * Allocate memory to DMA data to and from the receive
5723526Sxy150489 		 * descriptors.
5733526Sxy150489 		 */
5748850SMin.Xu@Sun.COM 		mystat = ddi_dma_mem_alloc(rx_data->rbd_dma_handle,
5753526Sxy150489 		    size,
5764919Sxy150489 		    &e1000g_desc_acc_attr, DDI_DMA_CONSISTENT,
5773526Sxy150489 		    DDI_DMA_DONTWAIT, 0,
5788850SMin.Xu@Sun.COM 		    (caddr_t *)&rx_data->rbd_area,
5798850SMin.Xu@Sun.COM 		    &len, &rx_data->rbd_acc_handle);
5803526Sxy150489 
5813526Sxy150489 		if (mystat != DDI_SUCCESS) {
5824919Sxy150489 			E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
5833526Sxy150489 			    "Could not allocate rbd dma memory: %d", mystat);
5848850SMin.Xu@Sun.COM 			rx_data->rbd_acc_handle = NULL;
5858850SMin.Xu@Sun.COM 			rx_data->rbd_area = NULL;
5868850SMin.Xu@Sun.COM 			if (rx_data->rbd_dma_handle != NULL) {
5878850SMin.Xu@Sun.COM 				ddi_dma_free_handle(&rx_data->rbd_dma_handle);
5888850SMin.Xu@Sun.COM 				rx_data->rbd_dma_handle = NULL;
5893526Sxy150489 			}
5903526Sxy150489 			return (DDI_FAILURE);
5913526Sxy150489 		} else
5923526Sxy150489 			alloc_flag = B_TRUE;
5933526Sxy150489 
5943526Sxy150489 		/*
5953526Sxy150489 		 * Initialize the allocated receive descriptor memory to zero.
5963526Sxy150489 		 */
5978850SMin.Xu@Sun.COM 		bzero((caddr_t)rx_data->rbd_area, len);
5988850SMin.Xu@Sun.COM 		templong = P2NPHASE((uintptr_t)rx_data->rbd_area,
5998178SChenlu.Chen@Sun.COM 		    Adapter->desc_align);
6003526Sxy150489 		len = size - templong;
6018850SMin.Xu@Sun.COM 		templong += (uintptr_t)rx_data->rbd_area;
6028850SMin.Xu@Sun.COM 		rx_data->rbd_area = (struct e1000_rx_desc *)templong;
6033526Sxy150489 	}	/* alignment workaround */
6043526Sxy150489 
6053526Sxy150489 	/*
6063526Sxy150489 	 * The memory allocation of the receive descriptors succeeded
6073526Sxy150489 	 */
6083526Sxy150489 	ASSERT(alloc_flag);
6093526Sxy150489 
6103526Sxy150489 	/*
6113526Sxy150489 	 * Allocates DMA resources for the memory that was allocated by
6123526Sxy150489 	 * the ddi_dma_mem_alloc call.
6133526Sxy150489 	 */
6148850SMin.Xu@Sun.COM 	mystat = ddi_dma_addr_bind_handle(rx_data->rbd_dma_handle,
6158850SMin.Xu@Sun.COM 	    (struct as *)NULL, (caddr_t)rx_data->rbd_area,
6164349Sxy150489 	    len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
6174919Sxy150489 	    DDI_DMA_DONTWAIT, 0, &cookie, &cookie_count);
6183526Sxy150489 
6193526Sxy150489 	if (mystat != DDI_SUCCESS) {
6204919Sxy150489 		E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
6213526Sxy150489 		    "Could not bind rbd dma resource: %d", mystat);
6228850SMin.Xu@Sun.COM 		if (rx_data->rbd_acc_handle != NULL) {
6238850SMin.Xu@Sun.COM 			ddi_dma_mem_free(&rx_data->rbd_acc_handle);
6248850SMin.Xu@Sun.COM 			rx_data->rbd_acc_handle = NULL;
6258850SMin.Xu@Sun.COM 			rx_data->rbd_area = NULL;
6263526Sxy150489 		}
6278850SMin.Xu@Sun.COM 		if (rx_data->rbd_dma_handle != NULL) {
6288850SMin.Xu@Sun.COM 			ddi_dma_free_handle(&rx_data->rbd_dma_handle);
6298850SMin.Xu@Sun.COM 			rx_data->rbd_dma_handle = NULL;
6303526Sxy150489 		}
6313526Sxy150489 		return (DDI_FAILURE);
6323526Sxy150489 	}
6333526Sxy150489 
6343526Sxy150489 	ASSERT(cookie_count == 1);
6353526Sxy150489 	if (cookie_count != 1) {
6364919Sxy150489 		E1000G_DEBUGLOG_2(Adapter, E1000G_WARN_LEVEL,
6373526Sxy150489 		    "Could not bind rbd dma resource in a single frag. "
6383526Sxy150489 		    "Count - %d Len - %d", cookie_count, len);
6398850SMin.Xu@Sun.COM 		e1000g_free_rx_descriptors(rx_data);
6403526Sxy150489 		return (DDI_FAILURE);
6413526Sxy150489 	}
6424919Sxy150489 
6438850SMin.Xu@Sun.COM 	rx_data->rbd_dma_addr = cookie.dmac_laddress;
6448850SMin.Xu@Sun.COM 	rx_data->rbd_first = rx_data->rbd_area;
6458850SMin.Xu@Sun.COM 	rx_data->rbd_last = rx_data->rbd_first +
6464919Sxy150489 	    (Adapter->rx_desc_num - 1);
6473526Sxy150489 
6483526Sxy150489 	return (DDI_SUCCESS);
6493526Sxy150489 }
6503526Sxy150489 
6513526Sxy150489 static void
e1000g_free_rx_descriptors(e1000g_rx_data_t * rx_data)6528850SMin.Xu@Sun.COM e1000g_free_rx_descriptors(e1000g_rx_data_t *rx_data)
6533526Sxy150489 {
6548850SMin.Xu@Sun.COM 	if (rx_data->rbd_dma_handle != NULL) {
6558850SMin.Xu@Sun.COM 		(void) ddi_dma_unbind_handle(rx_data->rbd_dma_handle);
6563526Sxy150489 	}
6578850SMin.Xu@Sun.COM 	if (rx_data->rbd_acc_handle != NULL) {
6588850SMin.Xu@Sun.COM 		ddi_dma_mem_free(&rx_data->rbd_acc_handle);
6598850SMin.Xu@Sun.COM 		rx_data->rbd_acc_handle = NULL;
6608850SMin.Xu@Sun.COM 		rx_data->rbd_area = NULL;
6613526Sxy150489 	}
6628850SMin.Xu@Sun.COM 	if (rx_data->rbd_dma_handle != NULL) {
6638850SMin.Xu@Sun.COM 		ddi_dma_free_handle(&rx_data->rbd_dma_handle);
6648850SMin.Xu@Sun.COM 		rx_data->rbd_dma_handle = NULL;
6653526Sxy150489 	}
6668850SMin.Xu@Sun.COM 	rx_data->rbd_dma_addr = NULL;
6678850SMin.Xu@Sun.COM 	rx_data->rbd_first = NULL;
6688850SMin.Xu@Sun.COM 	rx_data->rbd_last = NULL;
6693526Sxy150489 }
6703526Sxy150489 
6713526Sxy150489 static void
e1000g_free_tx_descriptors(e1000g_tx_ring_t * tx_ring)6723526Sxy150489 e1000g_free_tx_descriptors(e1000g_tx_ring_t *tx_ring)
6733526Sxy150489 {
6743526Sxy150489 	if (tx_ring->tbd_dma_handle != NULL) {
6757426SChenliang.Xu@Sun.COM 		(void) ddi_dma_unbind_handle(tx_ring->tbd_dma_handle);
6763526Sxy150489 	}
6773526Sxy150489 	if (tx_ring->tbd_acc_handle != NULL) {
6783526Sxy150489 		ddi_dma_mem_free(&tx_ring->tbd_acc_handle);
6793526Sxy150489 		tx_ring->tbd_acc_handle = NULL;
6803526Sxy150489 		tx_ring->tbd_area = NULL;
6813526Sxy150489 	}
6823526Sxy150489 	if (tx_ring->tbd_dma_handle != NULL) {
6833526Sxy150489 		ddi_dma_free_handle(&tx_ring->tbd_dma_handle);
6843526Sxy150489 		tx_ring->tbd_dma_handle = NULL;
6853526Sxy150489 	}
6863526Sxy150489 	tx_ring->tbd_dma_addr = NULL;
6873526Sxy150489 	tx_ring->tbd_first = NULL;
6883526Sxy150489 	tx_ring->tbd_last = NULL;
6893526Sxy150489 }
6903526Sxy150489 
6913526Sxy150489 
6923526Sxy150489 /*
6934919Sxy150489  * e1000g_alloc_packets - allocate DMA buffers for rx/tx
6944919Sxy150489  *
6954919Sxy150489  * This routine allocates neccesary buffers for
6964919Sxy150489  *	 Transmit sw packet structure
6974919Sxy150489  *	 DMA handle for Transmit
6984919Sxy150489  *	 DMA buffer for Transmit
6994919Sxy150489  *	 Receive sw packet structure
7004919Sxy150489  *	 DMA buffer for Receive
7013526Sxy150489  */
7023526Sxy150489 static int
e1000g_alloc_packets(struct e1000g * Adapter)7033526Sxy150489 e1000g_alloc_packets(struct e1000g *Adapter)
7043526Sxy150489 {
7053526Sxy150489 	int result;
7063526Sxy150489 	e1000g_tx_ring_t *tx_ring;
7078850SMin.Xu@Sun.COM 	e1000g_rx_data_t *rx_data;
7083526Sxy150489 
7093526Sxy150489 	tx_ring = Adapter->tx_ring;
7108850SMin.Xu@Sun.COM 	rx_data = Adapter->rx_ring->rx_data;
7113526Sxy150489 
7123526Sxy150489 again:
7133526Sxy150489 	rw_enter(&e1000g_dma_type_lock, RW_READER);
7143526Sxy150489 
7153526Sxy150489 	result = e1000g_alloc_tx_packets(tx_ring);
7163526Sxy150489 	if (result != DDI_SUCCESS) {
7173526Sxy150489 		if (e1000g_dma_type == USE_DVMA) {
7183526Sxy150489 			rw_exit(&e1000g_dma_type_lock);
7193526Sxy150489 
7203526Sxy150489 			rw_enter(&e1000g_dma_type_lock, RW_WRITER);
7213526Sxy150489 			e1000g_dma_type = USE_DMA;
7223526Sxy150489 			rw_exit(&e1000g_dma_type_lock);
7233526Sxy150489 
7244919Sxy150489 			E1000G_DEBUGLOG_0(Adapter, E1000G_INFO_LEVEL,
7253526Sxy150489 			    "No enough dvma resource for Tx packets, "
7263526Sxy150489 			    "trying to allocate dma buffers...\n");
7273526Sxy150489 			goto again;
7283526Sxy150489 		}
7293526Sxy150489 		rw_exit(&e1000g_dma_type_lock);
7303526Sxy150489 
7314919Sxy150489 		E1000G_DEBUGLOG_0(Adapter, E1000G_WARN_LEVEL,
7323526Sxy150489 		    "Failed to allocate dma buffers for Tx packets\n");
7333526Sxy150489 		return (DDI_FAILURE);
7343526Sxy150489 	}
7353526Sxy150489 
7368850SMin.Xu@Sun.COM 	result = e1000g_alloc_rx_packets(rx_data);
7373526Sxy150489 	if (result != DDI_SUCCESS) {
7383526Sxy150489 		e1000g_free_tx_packets(tx_ring);
7393526Sxy150489 		if (e1000g_dma_type == USE_DVMA) {
7403526Sxy150489 			rw_exit(&e1000g_dma_type_lock);
7413526Sxy150489 
7423526Sxy150489 			rw_enter(&e1000g_dma_type_lock, RW_WRITER);
7433526Sxy150489 			e1000g_dma_type = USE_DMA;
7443526Sxy150489 			rw_exit(&e1000g_dma_type_lock);
7453526Sxy150489 
7464919Sxy150489 			E1000G_DEBUGLOG_0(Adapter, E1000G_INFO_LEVEL,
7473526Sxy150489 			    "No enough dvma resource for Rx packets, "
7483526Sxy150489 			    "trying to allocate dma buffers...\n");
7493526Sxy150489 			goto again;
7503526Sxy150489 		}
7513526Sxy150489 		rw_exit(&e1000g_dma_type_lock);
7523526Sxy150489 
7534919Sxy150489 		E1000G_DEBUGLOG_0(Adapter, E1000G_WARN_LEVEL,
7543526Sxy150489 		    "Failed to allocate dma buffers for Rx packets\n");
7553526Sxy150489 		return (DDI_FAILURE);
7563526Sxy150489 	}
7573526Sxy150489 
7583526Sxy150489 	rw_exit(&e1000g_dma_type_lock);
7593526Sxy150489 
7603526Sxy150489 	return (DDI_SUCCESS);
7613526Sxy150489 }
7623526Sxy150489 
7634919Sxy150489 static void
e1000g_free_packets(struct e1000g * Adapter)7644919Sxy150489 e1000g_free_packets(struct e1000g *Adapter)
7654919Sxy150489 {
7664919Sxy150489 	e1000g_tx_ring_t *tx_ring;
7678850SMin.Xu@Sun.COM 	e1000g_rx_data_t *rx_data;
7684919Sxy150489 
7694919Sxy150489 	tx_ring = Adapter->tx_ring;
7708850SMin.Xu@Sun.COM 	rx_data = Adapter->rx_ring->rx_data;
7714919Sxy150489 
7724919Sxy150489 	e1000g_free_tx_packets(tx_ring);
773*12853SChangqing.Li@Sun.COM 	e1000g_free_rx_packets(rx_data, B_FALSE);
7744919Sxy150489 }
7754919Sxy150489 
7763526Sxy150489 #ifdef __sparc
7773526Sxy150489 static int
e1000g_alloc_dvma_buffer(struct e1000g * Adapter,dma_buffer_t * buf,size_t size)7783526Sxy150489 e1000g_alloc_dvma_buffer(struct e1000g *Adapter,
7793526Sxy150489     dma_buffer_t *buf, size_t size)
7803526Sxy150489 {
7813526Sxy150489 	int mystat;
7823526Sxy150489 	dev_info_t *devinfo;
7833526Sxy150489 	ddi_dma_cookie_t cookie;
7843526Sxy150489 
7854349Sxy150489 	if (e1000g_force_detach)
7864349Sxy150489 		devinfo = Adapter->priv_dip;
7874349Sxy150489 	else
7884349Sxy150489 		devinfo = Adapter->dip;
7893526Sxy150489 
7903526Sxy150489 	mystat = dvma_reserve(devinfo,
7913526Sxy150489 	    &e1000g_dma_limits,
7923526Sxy150489 	    Adapter->dvma_page_num,
7933526Sxy150489 	    &buf->dma_handle);
7943526Sxy150489 
7953526Sxy150489 	if (mystat != DDI_SUCCESS) {
7963526Sxy150489 		buf->dma_handle = NULL;
7974919Sxy150489 		E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
7983526Sxy150489 		    "Could not allocate dvma buffer handle: %d\n", mystat);
7993526Sxy150489 		return (DDI_FAILURE);
8003526Sxy150489 	}
8013526Sxy150489 
8023526Sxy150489 	buf->address = kmem_alloc(size, KM_NOSLEEP);
8033526Sxy150489 
8043526Sxy150489 	if (buf->address == NULL) {
8053526Sxy150489 		if (buf->dma_handle != NULL) {
8063526Sxy150489 			dvma_release(buf->dma_handle);
8073526Sxy150489 			buf->dma_handle = NULL;
8083526Sxy150489 		}
8094919Sxy150489 		E1000G_DEBUGLOG_0(Adapter, E1000G_WARN_LEVEL,
8103526Sxy150489 		    "Could not allocate dvma buffer memory\n");
8113526Sxy150489 		return (DDI_FAILURE);
8123526Sxy150489 	}
8133526Sxy150489 
8143526Sxy150489 	dvma_kaddr_load(buf->dma_handle,
8153526Sxy150489 	    buf->address, size, 0, &cookie);
8163526Sxy150489 
8173526Sxy150489 	buf->dma_address = cookie.dmac_laddress;
8183526Sxy150489 	buf->size = size;
8193526Sxy150489 	buf->len = 0;
8203526Sxy150489 
8213526Sxy150489 	return (DDI_SUCCESS);
8223526Sxy150489 }
8233526Sxy150489 
8243526Sxy150489 static void
e1000g_free_dvma_buffer(dma_buffer_t * buf)8253526Sxy150489 e1000g_free_dvma_buffer(dma_buffer_t *buf)
8263526Sxy150489 {
8273526Sxy150489 	if (buf->dma_handle != NULL) {
8283526Sxy150489 		dvma_unload(buf->dma_handle, 0, -1);
8293526Sxy150489 	} else {
8303526Sxy150489 		return;
8313526Sxy150489 	}
8323526Sxy150489 
8333526Sxy150489 	buf->dma_address = NULL;
8343526Sxy150489 
8353526Sxy150489 	if (buf->address != NULL) {
8363526Sxy150489 		kmem_free(buf->address, buf->size);
8373526Sxy150489 		buf->address = NULL;
8383526Sxy150489 	}
8393526Sxy150489 
8403526Sxy150489 	if (buf->dma_handle != NULL) {
8413526Sxy150489 		dvma_release(buf->dma_handle);
8423526Sxy150489 		buf->dma_handle = NULL;
8433526Sxy150489 	}
8443526Sxy150489 
8453526Sxy150489 	buf->size = 0;
8463526Sxy150489 	buf->len = 0;
8473526Sxy150489 }
8483526Sxy150489 #endif
8493526Sxy150489 
8503526Sxy150489 static int
e1000g_alloc_dma_buffer(struct e1000g * Adapter,dma_buffer_t * buf,size_t size,ddi_dma_attr_t * p_dma_attr)8513526Sxy150489 e1000g_alloc_dma_buffer(struct e1000g *Adapter,
8524919Sxy150489     dma_buffer_t *buf, size_t size, ddi_dma_attr_t *p_dma_attr)
8533526Sxy150489 {
8543526Sxy150489 	int mystat;
8553526Sxy150489 	dev_info_t *devinfo;
8563526Sxy150489 	ddi_dma_cookie_t cookie;
8573526Sxy150489 	size_t len;
8583526Sxy150489 	uint_t count;
8593526Sxy150489 
8604349Sxy150489 	if (e1000g_force_detach)
8614349Sxy150489 		devinfo = Adapter->priv_dip;
8624349Sxy150489 	else
8634349Sxy150489 		devinfo = Adapter->dip;
8643526Sxy150489 
8653526Sxy150489 	mystat = ddi_dma_alloc_handle(devinfo,
8664919Sxy150489 	    p_dma_attr,
8673526Sxy150489 	    DDI_DMA_DONTWAIT, 0,
8683526Sxy150489 	    &buf->dma_handle);
8693526Sxy150489 
8703526Sxy150489 	if (mystat != DDI_SUCCESS) {
8713526Sxy150489 		buf->dma_handle = NULL;
8724919Sxy150489 		E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
8733526Sxy150489 		    "Could not allocate dma buffer handle: %d\n", mystat);
8743526Sxy150489 		return (DDI_FAILURE);
8753526Sxy150489 	}
8763526Sxy150489 
8773526Sxy150489 	mystat = ddi_dma_mem_alloc(buf->dma_handle,
8784919Sxy150489 	    size, &e1000g_buf_acc_attr, DDI_DMA_STREAMING,
8793526Sxy150489 	    DDI_DMA_DONTWAIT, 0,
8803526Sxy150489 	    &buf->address,
8813526Sxy150489 	    &len, &buf->acc_handle);
8823526Sxy150489 
8833526Sxy150489 	if (mystat != DDI_SUCCESS) {
8843526Sxy150489 		buf->acc_handle = NULL;
8853526Sxy150489 		buf->address = NULL;
8863526Sxy150489 		if (buf->dma_handle != NULL) {
8873526Sxy150489 			ddi_dma_free_handle(&buf->dma_handle);
8883526Sxy150489 			buf->dma_handle = NULL;
8893526Sxy150489 		}
8904919Sxy150489 		E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
8913526Sxy150489 		    "Could not allocate dma buffer memory: %d\n", mystat);
8923526Sxy150489 		return (DDI_FAILURE);
8933526Sxy150489 	}
8943526Sxy150489 
8953526Sxy150489 	mystat = ddi_dma_addr_bind_handle(buf->dma_handle,
8963526Sxy150489 	    (struct as *)NULL,
8973526Sxy150489 	    buf->address,
89811402SChangqing.Li@Sun.COM 	    len, DDI_DMA_RDWR | DDI_DMA_STREAMING,
8994919Sxy150489 	    DDI_DMA_DONTWAIT, 0, &cookie, &count);
9003526Sxy150489 
9013526Sxy150489 	if (mystat != DDI_SUCCESS) {
9023526Sxy150489 		if (buf->acc_handle != NULL) {
9033526Sxy150489 			ddi_dma_mem_free(&buf->acc_handle);
9043526Sxy150489 			buf->acc_handle = NULL;
9053526Sxy150489 			buf->address = NULL;
9063526Sxy150489 		}
9073526Sxy150489 		if (buf->dma_handle != NULL) {
9083526Sxy150489 			ddi_dma_free_handle(&buf->dma_handle);
9093526Sxy150489 			buf->dma_handle = NULL;
9103526Sxy150489 		}
9114919Sxy150489 		E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
9123526Sxy150489 		    "Could not bind buffer dma handle: %d\n", mystat);
9133526Sxy150489 		return (DDI_FAILURE);
9143526Sxy150489 	}
9153526Sxy150489 
9163526Sxy150489 	ASSERT(count == 1);
9173526Sxy150489 	if (count != 1) {
9183526Sxy150489 		if (buf->dma_handle != NULL) {
9197426SChenliang.Xu@Sun.COM 			(void) ddi_dma_unbind_handle(buf->dma_handle);
9203526Sxy150489 		}
9213526Sxy150489 		if (buf->acc_handle != NULL) {
9223526Sxy150489 			ddi_dma_mem_free(&buf->acc_handle);
9233526Sxy150489 			buf->acc_handle = NULL;
9243526Sxy150489 			buf->address = NULL;
9253526Sxy150489 		}
9263526Sxy150489 		if (buf->dma_handle != NULL) {
9273526Sxy150489 			ddi_dma_free_handle(&buf->dma_handle);
9283526Sxy150489 			buf->dma_handle = NULL;
9293526Sxy150489 		}
9304919Sxy150489 		E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
9313526Sxy150489 		    "Could not bind buffer as a single frag. "
9323526Sxy150489 		    "Count = %d\n", count);
9333526Sxy150489 		return (DDI_FAILURE);
9343526Sxy150489 	}
9353526Sxy150489 
9363526Sxy150489 	buf->dma_address = cookie.dmac_laddress;
9373526Sxy150489 	buf->size = len;
9383526Sxy150489 	buf->len = 0;
9393526Sxy150489 
9403526Sxy150489 	return (DDI_SUCCESS);
9413526Sxy150489 }
9423526Sxy150489 
9438178SChenlu.Chen@Sun.COM /*
9448178SChenlu.Chen@Sun.COM  * e1000g_alloc_dma_buffer_82546 - allocate a dma buffer along with all
9458178SChenlu.Chen@Sun.COM  * necessary handles.  Same as e1000g_alloc_dma_buffer() except ensure
9468178SChenlu.Chen@Sun.COM  * that buffer that doesn't cross a 64k boundary.
9478178SChenlu.Chen@Sun.COM  */
9488178SChenlu.Chen@Sun.COM static int
e1000g_alloc_dma_buffer_82546(struct e1000g * Adapter,dma_buffer_t * buf,size_t size,ddi_dma_attr_t * p_dma_attr)9498178SChenlu.Chen@Sun.COM e1000g_alloc_dma_buffer_82546(struct e1000g *Adapter,
9508178SChenlu.Chen@Sun.COM     dma_buffer_t *buf, size_t size, ddi_dma_attr_t *p_dma_attr)
9518178SChenlu.Chen@Sun.COM {
9528178SChenlu.Chen@Sun.COM 	int mystat;
9538178SChenlu.Chen@Sun.COM 	dev_info_t *devinfo;
9548178SChenlu.Chen@Sun.COM 	ddi_dma_cookie_t cookie;
9558178SChenlu.Chen@Sun.COM 	size_t len;
9568178SChenlu.Chen@Sun.COM 	uint_t count;
9578178SChenlu.Chen@Sun.COM 
9588178SChenlu.Chen@Sun.COM 	if (e1000g_force_detach)
9598178SChenlu.Chen@Sun.COM 		devinfo = Adapter->priv_dip;
9608178SChenlu.Chen@Sun.COM 	else
9618178SChenlu.Chen@Sun.COM 		devinfo = Adapter->dip;
9628178SChenlu.Chen@Sun.COM 
9638178SChenlu.Chen@Sun.COM 	mystat = ddi_dma_alloc_handle(devinfo,
9648178SChenlu.Chen@Sun.COM 	    p_dma_attr,
9658178SChenlu.Chen@Sun.COM 	    DDI_DMA_DONTWAIT, 0,
9668178SChenlu.Chen@Sun.COM 	    &buf->dma_handle);
9678178SChenlu.Chen@Sun.COM 
9688178SChenlu.Chen@Sun.COM 	if (mystat != DDI_SUCCESS) {
9698178SChenlu.Chen@Sun.COM 		buf->dma_handle = NULL;
9708178SChenlu.Chen@Sun.COM 		E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
9718178SChenlu.Chen@Sun.COM 		    "Could not allocate dma buffer handle: %d\n", mystat);
9728178SChenlu.Chen@Sun.COM 		return (DDI_FAILURE);
9738178SChenlu.Chen@Sun.COM 	}
9748178SChenlu.Chen@Sun.COM 
9758178SChenlu.Chen@Sun.COM 	mystat = e1000g_dma_mem_alloc_82546(buf, size, &len);
9768178SChenlu.Chen@Sun.COM 	if (mystat != DDI_SUCCESS) {
9778178SChenlu.Chen@Sun.COM 		buf->acc_handle = NULL;
9788178SChenlu.Chen@Sun.COM 		buf->address = NULL;
9798178SChenlu.Chen@Sun.COM 		if (buf->dma_handle != NULL) {
9808178SChenlu.Chen@Sun.COM 			ddi_dma_free_handle(&buf->dma_handle);
9818178SChenlu.Chen@Sun.COM 			buf->dma_handle = NULL;
9828178SChenlu.Chen@Sun.COM 		}
9838178SChenlu.Chen@Sun.COM 		E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
9848178SChenlu.Chen@Sun.COM 		    "Could not allocate dma buffer memory: %d\n", mystat);
9858178SChenlu.Chen@Sun.COM 		return (DDI_FAILURE);
9868178SChenlu.Chen@Sun.COM 	}
9878178SChenlu.Chen@Sun.COM 
9888178SChenlu.Chen@Sun.COM 	mystat = ddi_dma_addr_bind_handle(buf->dma_handle,
9898178SChenlu.Chen@Sun.COM 	    (struct as *)NULL,
9908178SChenlu.Chen@Sun.COM 	    buf->address,
9918178SChenlu.Chen@Sun.COM 	    len, DDI_DMA_READ | DDI_DMA_STREAMING,
9928178SChenlu.Chen@Sun.COM 	    DDI_DMA_DONTWAIT, 0, &cookie, &count);
9938178SChenlu.Chen@Sun.COM 
9948178SChenlu.Chen@Sun.COM 	if (mystat != DDI_SUCCESS) {
9958178SChenlu.Chen@Sun.COM 		if (buf->acc_handle != NULL) {
9968178SChenlu.Chen@Sun.COM 			ddi_dma_mem_free(&buf->acc_handle);
9978178SChenlu.Chen@Sun.COM 			buf->acc_handle = NULL;
9988178SChenlu.Chen@Sun.COM 			buf->address = NULL;
9998178SChenlu.Chen@Sun.COM 		}
10008178SChenlu.Chen@Sun.COM 		if (buf->dma_handle != NULL) {
10018178SChenlu.Chen@Sun.COM 			ddi_dma_free_handle(&buf->dma_handle);
10028178SChenlu.Chen@Sun.COM 			buf->dma_handle = NULL;
10038178SChenlu.Chen@Sun.COM 		}
10048178SChenlu.Chen@Sun.COM 		E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
10058178SChenlu.Chen@Sun.COM 		    "Could not bind buffer dma handle: %d\n", mystat);
10068178SChenlu.Chen@Sun.COM 		return (DDI_FAILURE);
10078178SChenlu.Chen@Sun.COM 	}
10088178SChenlu.Chen@Sun.COM 
10098178SChenlu.Chen@Sun.COM 	ASSERT(count == 1);
10108178SChenlu.Chen@Sun.COM 	if (count != 1) {
10118178SChenlu.Chen@Sun.COM 		if (buf->dma_handle != NULL) {
101211143SGuoqing.Zhu@Sun.COM 			(void) ddi_dma_unbind_handle(buf->dma_handle);
10138178SChenlu.Chen@Sun.COM 		}
10148178SChenlu.Chen@Sun.COM 		if (buf->acc_handle != NULL) {
10158178SChenlu.Chen@Sun.COM 			ddi_dma_mem_free(&buf->acc_handle);
10168178SChenlu.Chen@Sun.COM 			buf->acc_handle = NULL;
10178178SChenlu.Chen@Sun.COM 			buf->address = NULL;
10188178SChenlu.Chen@Sun.COM 		}
10198178SChenlu.Chen@Sun.COM 		if (buf->dma_handle != NULL) {
10208178SChenlu.Chen@Sun.COM 			ddi_dma_free_handle(&buf->dma_handle);
10218178SChenlu.Chen@Sun.COM 			buf->dma_handle = NULL;
10228178SChenlu.Chen@Sun.COM 		}
10238178SChenlu.Chen@Sun.COM 		E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
10248178SChenlu.Chen@Sun.COM 		    "Could not bind buffer as a single frag. "
10258178SChenlu.Chen@Sun.COM 		    "Count = %d\n", count);
10268178SChenlu.Chen@Sun.COM 		return (DDI_FAILURE);
10278178SChenlu.Chen@Sun.COM 	}
10288178SChenlu.Chen@Sun.COM 
10298178SChenlu.Chen@Sun.COM 	buf->dma_address = cookie.dmac_laddress;
10308178SChenlu.Chen@Sun.COM 	buf->size = len;
10318178SChenlu.Chen@Sun.COM 	buf->len = 0;
10328178SChenlu.Chen@Sun.COM 
10338178SChenlu.Chen@Sun.COM 	return (DDI_SUCCESS);
10348178SChenlu.Chen@Sun.COM }
10358178SChenlu.Chen@Sun.COM 
10368178SChenlu.Chen@Sun.COM /*
10378178SChenlu.Chen@Sun.COM  * e1000g_dma_mem_alloc_82546 - allocate a dma buffer, making up to
10388178SChenlu.Chen@Sun.COM  * ALLOC_RETRY attempts to get a buffer that doesn't cross a 64k boundary.
10398178SChenlu.Chen@Sun.COM  */
10408178SChenlu.Chen@Sun.COM static int
e1000g_dma_mem_alloc_82546(dma_buffer_t * buf,size_t size,size_t * len)10418178SChenlu.Chen@Sun.COM e1000g_dma_mem_alloc_82546(dma_buffer_t *buf, size_t size, size_t *len)
10428178SChenlu.Chen@Sun.COM {
10438178SChenlu.Chen@Sun.COM #define	ALLOC_RETRY	10
10448178SChenlu.Chen@Sun.COM 	int stat;
10458178SChenlu.Chen@Sun.COM 	int cnt = 0;
10468178SChenlu.Chen@Sun.COM 	ddi_acc_handle_t hold[ALLOC_RETRY];
10478178SChenlu.Chen@Sun.COM 
10488178SChenlu.Chen@Sun.COM 	while (cnt < ALLOC_RETRY) {
10498178SChenlu.Chen@Sun.COM 		hold[cnt] = NULL;
10508178SChenlu.Chen@Sun.COM 
10518178SChenlu.Chen@Sun.COM 		/* allocate memory */
10528178SChenlu.Chen@Sun.COM 		stat = ddi_dma_mem_alloc(buf->dma_handle, size,
10538178SChenlu.Chen@Sun.COM 		    &e1000g_buf_acc_attr, DDI_DMA_STREAMING, DDI_DMA_DONTWAIT,
10548178SChenlu.Chen@Sun.COM 		    0, &buf->address, len, &buf->acc_handle);
10558178SChenlu.Chen@Sun.COM 
10568178SChenlu.Chen@Sun.COM 		if (stat != DDI_SUCCESS) {
10578178SChenlu.Chen@Sun.COM 			break;
10588178SChenlu.Chen@Sun.COM 		}
10598178SChenlu.Chen@Sun.COM 
10608178SChenlu.Chen@Sun.COM 		/*
10618178SChenlu.Chen@Sun.COM 		 * Check 64k bounday:
10628178SChenlu.Chen@Sun.COM 		 * if it is bad, hold it and retry
10638178SChenlu.Chen@Sun.COM 		 * if it is good, exit loop
10648178SChenlu.Chen@Sun.COM 		 */
10658178SChenlu.Chen@Sun.COM 		if (e1000g_cross_64k_bound(buf->address, *len)) {
10668178SChenlu.Chen@Sun.COM 			hold[cnt] = buf->acc_handle;
10678178SChenlu.Chen@Sun.COM 			stat = DDI_FAILURE;
10688178SChenlu.Chen@Sun.COM 		} else {
10698178SChenlu.Chen@Sun.COM 			break;
10708178SChenlu.Chen@Sun.COM 		}
10718178SChenlu.Chen@Sun.COM 
10728178SChenlu.Chen@Sun.COM 		cnt++;
10738178SChenlu.Chen@Sun.COM 	}
10748178SChenlu.Chen@Sun.COM 
10758178SChenlu.Chen@Sun.COM 	/* Release any held buffers crossing 64k bounday */
10768178SChenlu.Chen@Sun.COM 	for (--cnt; cnt >= 0; cnt--) {
10778178SChenlu.Chen@Sun.COM 		if (hold[cnt])
10788178SChenlu.Chen@Sun.COM 			ddi_dma_mem_free(&hold[cnt]);
10798178SChenlu.Chen@Sun.COM 	}
10808178SChenlu.Chen@Sun.COM 
10818178SChenlu.Chen@Sun.COM 	return (stat);
10828178SChenlu.Chen@Sun.COM }
10838178SChenlu.Chen@Sun.COM 
10848178SChenlu.Chen@Sun.COM /*
10858178SChenlu.Chen@Sun.COM  * e1000g_cross_64k_bound - If starting and ending address cross a 64k boundary
10868178SChenlu.Chen@Sun.COM  * return true; otherwise return false
10878178SChenlu.Chen@Sun.COM  */
10888178SChenlu.Chen@Sun.COM static boolean_t
e1000g_cross_64k_bound(void * addr,uintptr_t len)10898178SChenlu.Chen@Sun.COM e1000g_cross_64k_bound(void *addr, uintptr_t len)
10908178SChenlu.Chen@Sun.COM {
10918178SChenlu.Chen@Sun.COM 	uintptr_t start = (uintptr_t)addr;
10928178SChenlu.Chen@Sun.COM 	uintptr_t end = start + len - 1;
10938178SChenlu.Chen@Sun.COM 
10948178SChenlu.Chen@Sun.COM 	return (((start ^ end) >> 16) == 0 ? B_FALSE : B_TRUE);
10958178SChenlu.Chen@Sun.COM }
10968178SChenlu.Chen@Sun.COM 
10973526Sxy150489 static void
e1000g_free_dma_buffer(dma_buffer_t * buf)10983526Sxy150489 e1000g_free_dma_buffer(dma_buffer_t *buf)
10993526Sxy150489 {
11003526Sxy150489 	if (buf->dma_handle != NULL) {
11017426SChenliang.Xu@Sun.COM 		(void) ddi_dma_unbind_handle(buf->dma_handle);
11023526Sxy150489 	} else {
11033526Sxy150489 		return;
11043526Sxy150489 	}
11053526Sxy150489 
11063526Sxy150489 	buf->dma_address = NULL;
11073526Sxy150489 
11083526Sxy150489 	if (buf->acc_handle != NULL) {
11093526Sxy150489 		ddi_dma_mem_free(&buf->acc_handle);
11103526Sxy150489 		buf->acc_handle = NULL;
11113526Sxy150489 		buf->address = NULL;
11123526Sxy150489 	}
11133526Sxy150489 
11143526Sxy150489 	if (buf->dma_handle != NULL) {
11153526Sxy150489 		ddi_dma_free_handle(&buf->dma_handle);
11163526Sxy150489 		buf->dma_handle = NULL;
11173526Sxy150489 	}
11183526Sxy150489 
11193526Sxy150489 	buf->size = 0;
11203526Sxy150489 	buf->len = 0;
11213526Sxy150489 }
11223526Sxy150489 
11233526Sxy150489 static int
e1000g_alloc_tx_packets(e1000g_tx_ring_t * tx_ring)11243526Sxy150489 e1000g_alloc_tx_packets(e1000g_tx_ring_t *tx_ring)
11253526Sxy150489 {
11263526Sxy150489 	int j;
11274919Sxy150489 	p_tx_sw_packet_t packet;
11283526Sxy150489 	int mystat;
11293526Sxy150489 	dma_buffer_t *tx_buf;
11304919Sxy150489 	struct e1000g *Adapter;
11314919Sxy150489 	dev_info_t *devinfo;
11324919Sxy150489 	ddi_dma_attr_t dma_attr;
11334919Sxy150489 
11344919Sxy150489 	Adapter = tx_ring->adapter;
11354919Sxy150489 	devinfo = Adapter->dip;
11364919Sxy150489 	dma_attr = e1000g_buf_dma_attr;
11373526Sxy150489 
11383526Sxy150489 	/*
11393526Sxy150489 	 * Memory allocation for the Transmit software structure, the transmit
11403526Sxy150489 	 * software packet. This structure stores all the relevant information
11413526Sxy150489 	 * for transmitting a single packet.
11423526Sxy150489 	 */
11433526Sxy150489 	tx_ring->packet_area =
11443526Sxy150489 	    kmem_zalloc(TX_SW_PKT_AREA_SZ, KM_NOSLEEP);
11453526Sxy150489 
11463526Sxy150489 	if (tx_ring->packet_area == NULL)
11473526Sxy150489 		return (DDI_FAILURE);
11483526Sxy150489 
11493526Sxy150489 	for (j = 0, packet = tx_ring->packet_area;
11504919Sxy150489 	    j < Adapter->tx_freelist_num; j++, packet++) {
11513526Sxy150489 
11523526Sxy150489 		ASSERT(packet != NULL);
11533526Sxy150489 
11543526Sxy150489 		/*
11553526Sxy150489 		 * Pre-allocate dma handles for transmit. These dma handles
11563526Sxy150489 		 * will be dynamically bound to the data buffers passed down
11573526Sxy150489 		 * from the upper layers at the time of transmitting. The
11583526Sxy150489 		 * dynamic binding only applies for the packets that are larger
11593526Sxy150489 		 * than the tx_bcopy_thresh.
11603526Sxy150489 		 */
11613526Sxy150489 		switch (e1000g_dma_type) {
11623526Sxy150489 #ifdef __sparc
11633526Sxy150489 		case USE_DVMA:
11643526Sxy150489 			mystat = dvma_reserve(devinfo,
11653526Sxy150489 			    &e1000g_dma_limits,
11663526Sxy150489 			    Adapter->dvma_page_num,
11673526Sxy150489 			    &packet->tx_dma_handle);
11683526Sxy150489 			break;
11693526Sxy150489 #endif
11703526Sxy150489 		case USE_DMA:
11713526Sxy150489 			mystat = ddi_dma_alloc_handle(devinfo,
11724919Sxy150489 			    &e1000g_tx_dma_attr,
11733526Sxy150489 			    DDI_DMA_DONTWAIT, 0,
11743526Sxy150489 			    &packet->tx_dma_handle);
11753526Sxy150489 			break;
11763526Sxy150489 		default:
11773526Sxy150489 			ASSERT(B_FALSE);
11783526Sxy150489 			break;
11793526Sxy150489 		}
11803526Sxy150489 		if (mystat != DDI_SUCCESS) {
11813526Sxy150489 			packet->tx_dma_handle = NULL;
11824919Sxy150489 			E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
11833526Sxy150489 			    "Could not allocate tx dma handle: %d\n", mystat);
11843526Sxy150489 			goto tx_pkt_fail;
11853526Sxy150489 		}
11863526Sxy150489 
11873526Sxy150489 		/*
11883526Sxy150489 		 * Pre-allocate transmit buffers for small packets that the
11893526Sxy150489 		 * size is less than tx_bcopy_thresh. The data of those small
11903526Sxy150489 		 * packets will be bcopy() to the transmit buffers instead of
11913526Sxy150489 		 * using dynamical DMA binding. For small packets, bcopy will
11923526Sxy150489 		 * bring better performance than DMA binding.
11933526Sxy150489 		 */
11943526Sxy150489 		tx_buf = packet->tx_buf;
11953526Sxy150489 
11963526Sxy150489 		switch (e1000g_dma_type) {
11973526Sxy150489 #ifdef __sparc
11983526Sxy150489 		case USE_DVMA:
11993526Sxy150489 			mystat = e1000g_alloc_dvma_buffer(Adapter,
12004919Sxy150489 			    tx_buf, Adapter->tx_buffer_size);
12013526Sxy150489 			break;
12023526Sxy150489 #endif
12033526Sxy150489 		case USE_DMA:
12043526Sxy150489 			mystat = e1000g_alloc_dma_buffer(Adapter,
12054919Sxy150489 			    tx_buf, Adapter->tx_buffer_size, &dma_attr);
12063526Sxy150489 			break;
12073526Sxy150489 		default:
12083526Sxy150489 			ASSERT(B_FALSE);
12093526Sxy150489 			break;
12103526Sxy150489 		}
12113526Sxy150489 		if (mystat != DDI_SUCCESS) {
12123526Sxy150489 			ASSERT(packet->tx_dma_handle != NULL);
12133526Sxy150489 			switch (e1000g_dma_type) {
12143526Sxy150489 #ifdef __sparc
12153526Sxy150489 			case USE_DVMA:
12163526Sxy150489 				dvma_release(packet->tx_dma_handle);
12173526Sxy150489 				break;
12183526Sxy150489 #endif
12193526Sxy150489 			case USE_DMA:
12203526Sxy150489 				ddi_dma_free_handle(&packet->tx_dma_handle);
12213526Sxy150489 				break;
12223526Sxy150489 			default:
12233526Sxy150489 				ASSERT(B_FALSE);
12243526Sxy150489 				break;
12253526Sxy150489 			}
12263526Sxy150489 			packet->tx_dma_handle = NULL;
12274919Sxy150489 			E1000G_DEBUGLOG_0(Adapter, E1000G_WARN_LEVEL,
12283526Sxy150489 			    "Allocate Tx buffer fail\n");
12293526Sxy150489 			goto tx_pkt_fail;
12303526Sxy150489 		}
12313526Sxy150489 
12323526Sxy150489 		packet->dma_type = e1000g_dma_type;
12333526Sxy150489 	} /* for */
12343526Sxy150489 
12353526Sxy150489 	return (DDI_SUCCESS);
12363526Sxy150489 
12373526Sxy150489 tx_pkt_fail:
12383526Sxy150489 	e1000g_free_tx_packets(tx_ring);
12393526Sxy150489 
12403526Sxy150489 	return (DDI_FAILURE);
12413526Sxy150489 }
12423526Sxy150489 
1243*12853SChangqing.Li@Sun.COM 
1244*12853SChangqing.Li@Sun.COM int
e1000g_increase_rx_packets(e1000g_rx_data_t * rx_data)1245*12853SChangqing.Li@Sun.COM e1000g_increase_rx_packets(e1000g_rx_data_t *rx_data)
1246*12853SChangqing.Li@Sun.COM {
1247*12853SChangqing.Li@Sun.COM 	int i;
1248*12853SChangqing.Li@Sun.COM 	p_rx_sw_packet_t packet;
1249*12853SChangqing.Li@Sun.COM 	p_rx_sw_packet_t cur, next;
1250*12853SChangqing.Li@Sun.COM 	struct e1000g *Adapter;
1251*12853SChangqing.Li@Sun.COM 	ddi_dma_attr_t dma_attr;
1252*12853SChangqing.Li@Sun.COM 
1253*12853SChangqing.Li@Sun.COM 	Adapter = rx_data->rx_ring->adapter;
1254*12853SChangqing.Li@Sun.COM 	dma_attr = e1000g_buf_dma_attr;
1255*12853SChangqing.Li@Sun.COM 	dma_attr.dma_attr_align = Adapter->rx_buf_align;
1256*12853SChangqing.Li@Sun.COM 	cur = NULL;
1257*12853SChangqing.Li@Sun.COM 
1258*12853SChangqing.Li@Sun.COM 	for (i = 0; i < RX_FREELIST_INCREASE_SIZE; i++) {
1259*12853SChangqing.Li@Sun.COM 		packet = e1000g_alloc_rx_sw_packet(rx_data, &dma_attr);
1260*12853SChangqing.Li@Sun.COM 		if (packet == NULL)
1261*12853SChangqing.Li@Sun.COM 			break;
1262*12853SChangqing.Li@Sun.COM 		packet->next = cur;
1263*12853SChangqing.Li@Sun.COM 		cur = packet;
1264*12853SChangqing.Li@Sun.COM 	}
1265*12853SChangqing.Li@Sun.COM 	Adapter->rx_freelist_num += i;
1266*12853SChangqing.Li@Sun.COM 	rx_data->avail_freepkt += i;
1267*12853SChangqing.Li@Sun.COM 
1268*12853SChangqing.Li@Sun.COM 	while (cur != NULL) {
1269*12853SChangqing.Li@Sun.COM 		QUEUE_PUSH_TAIL(&rx_data->free_list, &cur->Link);
1270*12853SChangqing.Li@Sun.COM 		next = cur->next;
1271*12853SChangqing.Li@Sun.COM 		cur->next = rx_data->packet_area;
1272*12853SChangqing.Li@Sun.COM 		rx_data->packet_area = cur;
1273*12853SChangqing.Li@Sun.COM 
1274*12853SChangqing.Li@Sun.COM 		cur = next;
1275*12853SChangqing.Li@Sun.COM 	}
1276*12853SChangqing.Li@Sun.COM 
1277*12853SChangqing.Li@Sun.COM 	return (DDI_SUCCESS);
1278*12853SChangqing.Li@Sun.COM }
1279*12853SChangqing.Li@Sun.COM 
1280*12853SChangqing.Li@Sun.COM 
12813526Sxy150489 static int
e1000g_alloc_rx_packets(e1000g_rx_data_t * rx_data)12828850SMin.Xu@Sun.COM e1000g_alloc_rx_packets(e1000g_rx_data_t *rx_data)
12833526Sxy150489 {
12843526Sxy150489 	int i;
12854919Sxy150489 	p_rx_sw_packet_t packet;
12863526Sxy150489 	struct e1000g *Adapter;
12873526Sxy150489 	uint32_t packet_num;
12884919Sxy150489 	ddi_dma_attr_t dma_attr;
12893526Sxy150489 
12908850SMin.Xu@Sun.COM 	Adapter = rx_data->rx_ring->adapter;
12914919Sxy150489 	dma_attr = e1000g_buf_dma_attr;
12926735Scc210113 	dma_attr.dma_attr_align = Adapter->rx_buf_align;
12933526Sxy150489 
12943526Sxy150489 	/*
12954919Sxy150489 	 * Allocate memory for the rx_sw_packet structures. Each one of these
12963526Sxy150489 	 * structures will contain a virtual and physical address to an actual
12974919Sxy150489 	 * receive buffer in host memory. Since we use one rx_sw_packet per
12984919Sxy150489 	 * received packet, the maximum number of rx_sw_packet that we'll
12998850SMin.Xu@Sun.COM 	 * need is equal to the number of receive descriptors plus the freelist
13008850SMin.Xu@Sun.COM 	 * size.
13013526Sxy150489 	 */
1302*12853SChangqing.Li@Sun.COM 	packet_num = Adapter->rx_desc_num + RX_FREELIST_INCREASE_SIZE;
13038850SMin.Xu@Sun.COM 	rx_data->packet_area = NULL;
13043526Sxy150489 
13053526Sxy150489 	for (i = 0; i < packet_num; i++) {
13068850SMin.Xu@Sun.COM 		packet = e1000g_alloc_rx_sw_packet(rx_data, &dma_attr);
13073526Sxy150489 		if (packet == NULL)
13083526Sxy150489 			goto rx_pkt_fail;
13093526Sxy150489 
13108850SMin.Xu@Sun.COM 		packet->next = rx_data->packet_area;
13118850SMin.Xu@Sun.COM 		rx_data->packet_area = packet;
13123526Sxy150489 	}
13133526Sxy150489 
1314*12853SChangqing.Li@Sun.COM 	Adapter->rx_freelist_num = RX_FREELIST_INCREASE_SIZE;
13153526Sxy150489 	return (DDI_SUCCESS);
13163526Sxy150489 
13173526Sxy150489 rx_pkt_fail:
1318*12853SChangqing.Li@Sun.COM 	e1000g_free_rx_packets(rx_data, B_TRUE);
13193526Sxy150489 	return (DDI_FAILURE);
13203526Sxy150489 }
13213526Sxy150489 
1322*12853SChangqing.Li@Sun.COM 
13234919Sxy150489 static p_rx_sw_packet_t
e1000g_alloc_rx_sw_packet(e1000g_rx_data_t * rx_data,ddi_dma_attr_t * p_dma_attr)13248850SMin.Xu@Sun.COM e1000g_alloc_rx_sw_packet(e1000g_rx_data_t *rx_data, ddi_dma_attr_t *p_dma_attr)
13253526Sxy150489 {
13263526Sxy150489 	int mystat;
13274919Sxy150489 	p_rx_sw_packet_t packet;
13283526Sxy150489 	dma_buffer_t *rx_buf;
13293526Sxy150489 	struct e1000g *Adapter;
13303526Sxy150489 
13318850SMin.Xu@Sun.COM 	Adapter = rx_data->rx_ring->adapter;
13323526Sxy150489 
13334919Sxy150489 	packet = kmem_zalloc(sizeof (rx_sw_packet_t), KM_NOSLEEP);
13343526Sxy150489 	if (packet == NULL) {
13354919Sxy150489 		E1000G_DEBUGLOG_0(Adapter, E1000G_WARN_LEVEL,
13363526Sxy150489 		    "Cound not allocate memory for Rx SwPacket\n");
13373526Sxy150489 		return (NULL);
13383526Sxy150489 	}
13393526Sxy150489 
13403526Sxy150489 	rx_buf = packet->rx_buf;
13413526Sxy150489 
13423526Sxy150489 	switch (e1000g_dma_type) {
13433526Sxy150489 #ifdef __sparc
13443526Sxy150489 	case USE_DVMA:
13453526Sxy150489 		mystat = e1000g_alloc_dvma_buffer(Adapter,
13464919Sxy150489 		    rx_buf, Adapter->rx_buffer_size);
13473526Sxy150489 		break;
13483526Sxy150489 #endif
13493526Sxy150489 	case USE_DMA:
13508417SChenlu.Chen@Sun.COM 		if (Adapter->mem_workaround_82546 &&
13518417SChenlu.Chen@Sun.COM 		    ((Adapter->shared.mac.type == e1000_82545) ||
13528178SChenlu.Chen@Sun.COM 		    (Adapter->shared.mac.type == e1000_82546) ||
13538417SChenlu.Chen@Sun.COM 		    (Adapter->shared.mac.type == e1000_82546_rev_3))) {
13548178SChenlu.Chen@Sun.COM 			mystat = e1000g_alloc_dma_buffer_82546(Adapter,
13558178SChenlu.Chen@Sun.COM 			    rx_buf, Adapter->rx_buffer_size, p_dma_attr);
13568178SChenlu.Chen@Sun.COM 		} else {
13578178SChenlu.Chen@Sun.COM 			mystat = e1000g_alloc_dma_buffer(Adapter,
13588178SChenlu.Chen@Sun.COM 			    rx_buf, Adapter->rx_buffer_size, p_dma_attr);
13598178SChenlu.Chen@Sun.COM 		}
13603526Sxy150489 		break;
13613526Sxy150489 	default:
13623526Sxy150489 		ASSERT(B_FALSE);
13633526Sxy150489 		break;
13643526Sxy150489 	}
13653526Sxy150489 
13663526Sxy150489 	if (mystat != DDI_SUCCESS) {
13673526Sxy150489 		if (packet != NULL)
13684919Sxy150489 			kmem_free(packet, sizeof (rx_sw_packet_t));
13693526Sxy150489 
13704919Sxy150489 		E1000G_DEBUGLOG_0(Adapter, E1000G_WARN_LEVEL,
13713526Sxy150489 		    "Failed to allocate Rx buffer\n");
13723526Sxy150489 		return (NULL);
13733526Sxy150489 	}
13743526Sxy150489 
13753526Sxy150489 	rx_buf->size -= E1000G_IPALIGNROOM;
13763526Sxy150489 	rx_buf->address += E1000G_IPALIGNROOM;
13773526Sxy150489 	rx_buf->dma_address += E1000G_IPALIGNROOM;
13783526Sxy150489 
13798850SMin.Xu@Sun.COM 	packet->rx_data = (caddr_t)rx_data;
13803526Sxy150489 	packet->free_rtn.free_func = e1000g_rxfree_func;
13813526Sxy150489 	packet->free_rtn.free_arg = (char *)packet;
13823526Sxy150489 	/*
13833526Sxy150489 	 * esballoc is changed to desballoc which
13843526Sxy150489 	 * is undocumented call but as per sun,
13853526Sxy150489 	 * we can use it. It gives better efficiency.
13863526Sxy150489 	 */
13873526Sxy150489 	packet->mp = desballoc((unsigned char *)
13888995SMin.Xu@Sun.COM 	    rx_buf->address,
13898995SMin.Xu@Sun.COM 	    rx_buf->size,
13903526Sxy150489 	    BPRI_MED, &packet->free_rtn);
13913526Sxy150489 
13923526Sxy150489 	packet->dma_type = e1000g_dma_type;
13938850SMin.Xu@Sun.COM 	packet->ref_cnt = 1;
13943526Sxy150489 
13953526Sxy150489 	return (packet);
13963526Sxy150489 }
13973526Sxy150489 
13983526Sxy150489 void
e1000g_free_rx_sw_packet(p_rx_sw_packet_t packet,boolean_t full_release)13998850SMin.Xu@Sun.COM e1000g_free_rx_sw_packet(p_rx_sw_packet_t packet, boolean_t full_release)
14003526Sxy150489 {
14013526Sxy150489 	dma_buffer_t *rx_buf;
14023526Sxy150489 
14033526Sxy150489 	if (packet->mp != NULL) {
14043526Sxy150489 		freemsg(packet->mp);
14053526Sxy150489 		packet->mp = NULL;
14063526Sxy150489 	}
14073526Sxy150489 
14083526Sxy150489 	rx_buf = packet->rx_buf;
14093526Sxy150489 
14103526Sxy150489 	switch (packet->dma_type) {
14113526Sxy150489 #ifdef __sparc
14123526Sxy150489 	case USE_DVMA:
14138850SMin.Xu@Sun.COM 		if (rx_buf->address != NULL) {
14148850SMin.Xu@Sun.COM 			rx_buf->size += E1000G_IPALIGNROOM;
14158850SMin.Xu@Sun.COM 			rx_buf->address -= E1000G_IPALIGNROOM;
14168850SMin.Xu@Sun.COM 		}
14173526Sxy150489 		e1000g_free_dvma_buffer(rx_buf);
14183526Sxy150489 		break;
14193526Sxy150489 #endif
14203526Sxy150489 	case USE_DMA:
14213526Sxy150489 		e1000g_free_dma_buffer(rx_buf);
14223526Sxy150489 		break;
14233526Sxy150489 	default:
14243526Sxy150489 		break;
14253526Sxy150489 	}
14263526Sxy150489 
14273526Sxy150489 	packet->dma_type = USE_NONE;
14283526Sxy150489 
14298850SMin.Xu@Sun.COM 	if (!full_release)
14308850SMin.Xu@Sun.COM 		return;
14318850SMin.Xu@Sun.COM 
14324919Sxy150489 	kmem_free(packet, sizeof (rx_sw_packet_t));
14333526Sxy150489 }
14343526Sxy150489 
14353526Sxy150489 static void
e1000g_free_rx_packets(e1000g_rx_data_t * rx_data,boolean_t full_release)1436*12853SChangqing.Li@Sun.COM e1000g_free_rx_packets(e1000g_rx_data_t *rx_data, boolean_t full_release)
14373526Sxy150489 {
14388850SMin.Xu@Sun.COM 	p_rx_sw_packet_t packet, next_packet;
14398850SMin.Xu@Sun.COM 	uint32_t ref_cnt;
14403526Sxy150489 
14418850SMin.Xu@Sun.COM 	mutex_enter(&e1000g_rx_detach_lock);
14424349Sxy150489 
14438850SMin.Xu@Sun.COM 	packet = rx_data->packet_area;
14448850SMin.Xu@Sun.COM 	while (packet != NULL) {
14454349Sxy150489 		next_packet = packet->next;
14464349Sxy150489 
14478850SMin.Xu@Sun.COM 		ref_cnt = atomic_dec_32_nv(&packet->ref_cnt);
14488850SMin.Xu@Sun.COM 		if (ref_cnt > 0) {
14498850SMin.Xu@Sun.COM 			atomic_inc_32(&rx_data->pending_count);
14508850SMin.Xu@Sun.COM 			atomic_inc_32(&e1000g_mblks_pending);
14514349Sxy150489 		} else {
1452*12853SChangqing.Li@Sun.COM 			e1000g_free_rx_sw_packet(packet, full_release);
14533526Sxy150489 		}
14548850SMin.Xu@Sun.COM 
14558850SMin.Xu@Sun.COM 		packet = next_packet;
14563526Sxy150489 	}
14573526Sxy150489 
14588850SMin.Xu@Sun.COM 	mutex_exit(&e1000g_rx_detach_lock);
14598850SMin.Xu@Sun.COM }
14603526Sxy150489 
14613526Sxy150489 
14623526Sxy150489 static void
e1000g_free_tx_packets(e1000g_tx_ring_t * tx_ring)14633526Sxy150489 e1000g_free_tx_packets(e1000g_tx_ring_t *tx_ring)
14643526Sxy150489 {
14653526Sxy150489 	int j;
14663526Sxy150489 	struct e1000g *Adapter;
14674919Sxy150489 	p_tx_sw_packet_t packet;
14683526Sxy150489 	dma_buffer_t *tx_buf;
14693526Sxy150489 
14703526Sxy150489 	Adapter = tx_ring->adapter;
14713526Sxy150489 
14723526Sxy150489 	for (j = 0, packet = tx_ring->packet_area;
14734919Sxy150489 	    j < Adapter->tx_freelist_num; j++, packet++) {
14743526Sxy150489 
14753526Sxy150489 		if (packet == NULL)
14763526Sxy150489 			break;
14773526Sxy150489 
14783526Sxy150489 		/* Free the Tx DMA handle for dynamical binding */
14793526Sxy150489 		if (packet->tx_dma_handle != NULL) {
14803526Sxy150489 			switch (packet->dma_type) {
14813526Sxy150489 #ifdef __sparc
14823526Sxy150489 			case USE_DVMA:
14833526Sxy150489 				dvma_release(packet->tx_dma_handle);
14843526Sxy150489 				break;
14853526Sxy150489 #endif
14863526Sxy150489 			case USE_DMA:
14873526Sxy150489 				ddi_dma_free_handle(&packet->tx_dma_handle);
14883526Sxy150489 				break;
14893526Sxy150489 			default:
14903526Sxy150489 				ASSERT(B_FALSE);
14913526Sxy150489 				break;
14923526Sxy150489 			}
14933526Sxy150489 			packet->tx_dma_handle = NULL;
14943526Sxy150489 		} else {
14953526Sxy150489 			/*
14963526Sxy150489 			 * If the dma handle is NULL, then we don't
14973526Sxy150489 			 * need to check the packets left. For they
14983526Sxy150489 			 * have not been initialized or have been freed.
14993526Sxy150489 			 */
15003526Sxy150489 			break;
15013526Sxy150489 		}
15023526Sxy150489 
15033526Sxy150489 		tx_buf = packet->tx_buf;
15043526Sxy150489 
15053526Sxy150489 		switch (packet->dma_type) {
15063526Sxy150489 #ifdef __sparc
15073526Sxy150489 		case USE_DVMA:
15083526Sxy150489 			e1000g_free_dvma_buffer(tx_buf);
15093526Sxy150489 			break;
15103526Sxy150489 #endif
15113526Sxy150489 		case USE_DMA:
15123526Sxy150489 			e1000g_free_dma_buffer(tx_buf);
15133526Sxy150489 			break;
15143526Sxy150489 		default:
15153526Sxy150489 			ASSERT(B_FALSE);
15163526Sxy150489 			break;
15173526Sxy150489 		}
15183526Sxy150489 
15193526Sxy150489 		packet->dma_type = USE_NONE;
15203526Sxy150489 	}
15213526Sxy150489 	if (tx_ring->packet_area != NULL) {
15223526Sxy150489 		kmem_free(tx_ring->packet_area, TX_SW_PKT_AREA_SZ);
15233526Sxy150489 		tx_ring->packet_area = NULL;
15243526Sxy150489 	}
15253526Sxy150489 }
15263526Sxy150489 
15273526Sxy150489 /*
15284919Sxy150489  * e1000g_release_dma_resources - release allocated DMA resources
15294919Sxy150489  *
15304919Sxy150489  * This function releases any pending buffers that has been
15314919Sxy150489  * previously allocated
15323526Sxy150489  */
15333526Sxy150489 void
e1000g_release_dma_resources(struct e1000g * Adapter)15344919Sxy150489 e1000g_release_dma_resources(struct e1000g *Adapter)
15353526Sxy150489 {
15364919Sxy150489 	e1000g_free_descriptors(Adapter);
15374919Sxy150489 	e1000g_free_packets(Adapter);
15383526Sxy150489 }
15395273Sgl147354 
15407426SChenliang.Xu@Sun.COM /* ARGSUSED */
15415273Sgl147354 void
e1000g_set_fma_flags(int dma_flag)154211236SStephen.Hanson@Sun.COM e1000g_set_fma_flags(int dma_flag)
15435273Sgl147354 {
15445273Sgl147354 	if (dma_flag) {
15455273Sgl147354 		e1000g_tx_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR;
15465273Sgl147354 		e1000g_buf_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR;
15475273Sgl147354 		e1000g_desc_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR;
15485273Sgl147354 	} else {
15495273Sgl147354 		e1000g_tx_dma_attr.dma_attr_flags = 0;
15505273Sgl147354 		e1000g_buf_dma_attr.dma_attr_flags = 0;
15515273Sgl147354 		e1000g_desc_dma_attr.dma_attr_flags = 0;
15525273Sgl147354 	}
15535273Sgl147354 }
1554