xref: /onnv-gate/usr/src/uts/common/io/e1000g/e1000g_tx.c (revision 12246:4d28e30f7dd0)
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  *
98479SChenlu.Chen@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 /*
2211878SVenu.Iyer@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
238275SEric Cheng  * Use is subject to license terms.
243526Sxy150489  */
253526Sxy150489 
263526Sxy150489 /*
273526Sxy150489  * **********************************************************************
283526Sxy150489  *									*
293526Sxy150489  * Module Name:								*
303526Sxy150489  *   e1000g_tx.c							*
313526Sxy150489  *									*
323526Sxy150489  * Abstract:								*
334919Sxy150489  *   This file contains some routines that take care of Transmit,	*
344919Sxy150489  *   make the hardware to send the data pointed by the packet out	*
354919Sxy150489  *   on to the physical medium.						*
363526Sxy150489  *									*
373526Sxy150489  * **********************************************************************
383526Sxy150489  */
393526Sxy150489 
403526Sxy150489 #include "e1000g_sw.h"
413526Sxy150489 #include "e1000g_debug.h"
423526Sxy150489 
433526Sxy150489 static boolean_t e1000g_send(struct e1000g *, mblk_t *);
444919Sxy150489 static int e1000g_tx_copy(e1000g_tx_ring_t *,
456986Smx205022     p_tx_sw_packet_t, mblk_t *, boolean_t);
464919Sxy150489 static int e1000g_tx_bind(e1000g_tx_ring_t *,
474919Sxy150489     p_tx_sw_packet_t, mblk_t *);
487607STed.You@Sun.COM static boolean_t e1000g_retrieve_context(mblk_t *, context_data_t *, size_t);
496986Smx205022 static boolean_t e1000g_check_context(e1000g_tx_ring_t *, context_data_t *);
503526Sxy150489 static int e1000g_fill_tx_ring(e1000g_tx_ring_t *, LIST_DESCRIBER *,
516986Smx205022     context_data_t *);
526986Smx205022 static void e1000g_fill_context_descriptor(context_data_t *,
533526Sxy150489     struct e1000_context_desc *);
544919Sxy150489 static int e1000g_fill_tx_desc(e1000g_tx_ring_t *,
554919Sxy150489     p_tx_sw_packet_t, uint64_t, size_t);
563526Sxy150489 static uint32_t e1000g_fill_82544_desc(uint64_t Address, size_t Length,
574919Sxy150489     p_desc_array_t desc_array);
584919Sxy150489 static int e1000g_tx_workaround_PCIX_82544(p_tx_sw_packet_t, uint64_t, size_t);
594919Sxy150489 static int e1000g_tx_workaround_jumbo_82544(p_tx_sw_packet_t, uint64_t, size_t);
603526Sxy150489 static void e1000g_82547_timeout(void *);
613526Sxy150489 static void e1000g_82547_tx_move_tail(e1000g_tx_ring_t *);
623526Sxy150489 static void e1000g_82547_tx_move_tail_work(e1000g_tx_ring_t *);
633526Sxy150489 
644919Sxy150489 #ifndef E1000G_DEBUG
653526Sxy150489 #pragma inline(e1000g_tx_copy)
663526Sxy150489 #pragma inline(e1000g_tx_bind)
677607STed.You@Sun.COM #pragma inline(e1000g_retrieve_context)
686986Smx205022 #pragma inline(e1000g_check_context)
693526Sxy150489 #pragma inline(e1000g_fill_tx_ring)
703526Sxy150489 #pragma inline(e1000g_fill_context_descriptor)
713526Sxy150489 #pragma inline(e1000g_fill_tx_desc)
723526Sxy150489 #pragma inline(e1000g_fill_82544_desc)
733526Sxy150489 #pragma inline(e1000g_tx_workaround_PCIX_82544)
743526Sxy150489 #pragma inline(e1000g_tx_workaround_jumbo_82544)
754919Sxy150489 #pragma inline(e1000g_free_tx_swpkt)
763526Sxy150489 #endif
773526Sxy150489 
783526Sxy150489 /*
794919Sxy150489  * e1000g_free_tx_swpkt	- free up the tx sw packet
804919Sxy150489  *
814919Sxy150489  * Unbind the previously bound DMA handle for a given
824919Sxy150489  * transmit sw packet. And reset the sw packet data.
833526Sxy150489  */
843526Sxy150489 void
e1000g_free_tx_swpkt(register p_tx_sw_packet_t packet)854919Sxy150489 e1000g_free_tx_swpkt(register p_tx_sw_packet_t packet)
863526Sxy150489 {
873526Sxy150489 	switch (packet->data_transfer_type) {
883526Sxy150489 	case USE_BCOPY:
893526Sxy150489 		packet->tx_buf->len = 0;
903526Sxy150489 		break;
913526Sxy150489 #ifdef __sparc
923526Sxy150489 	case USE_DVMA:
933526Sxy150489 		dvma_unload(packet->tx_dma_handle, 0, -1);
943526Sxy150489 		break;
953526Sxy150489 #endif
963526Sxy150489 	case USE_DMA:
977426SChenliang.Xu@Sun.COM 		(void) ddi_dma_unbind_handle(packet->tx_dma_handle);
983526Sxy150489 		break;
993526Sxy150489 	default:
1003526Sxy150489 		break;
1013526Sxy150489 	}
1023526Sxy150489 
1033526Sxy150489 	/*
1043526Sxy150489 	 * The mblk has been stripped off the sw packet
1053526Sxy150489 	 * and will be freed in a triggered soft intr.
1063526Sxy150489 	 */
1073526Sxy150489 	ASSERT(packet->mp == NULL);
1083526Sxy150489 
1093526Sxy150489 	packet->data_transfer_type = USE_NONE;
1103526Sxy150489 	packet->num_mblk_frag = 0;
1113526Sxy150489 	packet->num_desc = 0;
1123526Sxy150489 }
1133526Sxy150489 
1143526Sxy150489 mblk_t *
e1000g_m_tx(void * arg,mblk_t * mp)1153526Sxy150489 e1000g_m_tx(void *arg, mblk_t *mp)
1163526Sxy150489 {
1173526Sxy150489 	struct e1000g *Adapter = (struct e1000g *)arg;
1183526Sxy150489 	mblk_t *next;
1193526Sxy150489 
1203526Sxy150489 	rw_enter(&Adapter->chip_lock, RW_READER);
1213526Sxy150489 
1228479SChenlu.Chen@Sun.COM 	if ((Adapter->e1000g_state & E1000G_SUSPENDED) ||
1238479SChenlu.Chen@Sun.COM 	    !(Adapter->e1000g_state & E1000G_STARTED) ||
1245273Sgl147354 	    (Adapter->link_state != LINK_STATE_UP)) {
1253526Sxy150489 		freemsgchain(mp);
1263526Sxy150489 		mp = NULL;
1273526Sxy150489 	}
1283526Sxy150489 
1293526Sxy150489 	while (mp != NULL) {
1303526Sxy150489 		next = mp->b_next;
1313526Sxy150489 		mp->b_next = NULL;
1323526Sxy150489 
1333526Sxy150489 		if (!e1000g_send(Adapter, mp)) {
1343526Sxy150489 			mp->b_next = next;
1353526Sxy150489 			break;
1363526Sxy150489 		}
1373526Sxy150489 
1383526Sxy150489 		mp = next;
1393526Sxy150489 	}
1403526Sxy150489 
1413526Sxy150489 	rw_exit(&Adapter->chip_lock);
1423526Sxy150489 	return (mp);
1433526Sxy150489 }
1443526Sxy150489 
1453526Sxy150489 /*
1464919Sxy150489  * e1000g_send -  send packets onto the wire
1474919Sxy150489  *
1484919Sxy150489  * Called from e1000g_m_tx with an mblk ready to send. this
1494919Sxy150489  * routine sets up the transmit descriptors and sends data to
1504919Sxy150489  * the wire. It also pushes the just transmitted packet to
1514919Sxy150489  * the used tx sw packet list.
1523526Sxy150489  */
1533526Sxy150489 static boolean_t
e1000g_send(struct e1000g * Adapter,mblk_t * mp)1543526Sxy150489 e1000g_send(struct e1000g *Adapter, mblk_t *mp)
1553526Sxy150489 {
1564919Sxy150489 	p_tx_sw_packet_t packet;
1573526Sxy150489 	LIST_DESCRIBER pending_list;
1583526Sxy150489 	size_t len;
1593526Sxy150489 	size_t msg_size;
1603526Sxy150489 	uint32_t frag_count;
1613526Sxy150489 	int desc_count;
1623526Sxy150489 	uint32_t desc_total;
1638073SMin.Xu@Sun.COM 	uint32_t bcopy_thresh;
1648073SMin.Xu@Sun.COM 	uint32_t hdr_frag_len;
1656986Smx205022 	boolean_t tx_undersize_flag;
1663526Sxy150489 	mblk_t *nmp;
1673526Sxy150489 	mblk_t *tmp;
1688073SMin.Xu@Sun.COM 	mblk_t *new_mp;
1698073SMin.Xu@Sun.COM 	mblk_t *pre_mp;
17010589SChangqing.Li@Sun.COM 	mblk_t *next_mp;
1713526Sxy150489 	e1000g_tx_ring_t *tx_ring;
1726986Smx205022 	context_data_t cur_context;
1733526Sxy150489 
1744919Sxy150489 	tx_ring = Adapter->tx_ring;
1758073SMin.Xu@Sun.COM 	bcopy_thresh = Adapter->tx_bcopy_thresh;
1764919Sxy150489 
1773526Sxy150489 	/* Get the total size and frags number of the message */
1786986Smx205022 	tx_undersize_flag = B_FALSE;
1793526Sxy150489 	frag_count = 0;
1803526Sxy150489 	msg_size = 0;
1813526Sxy150489 	for (nmp = mp; nmp; nmp = nmp->b_cont) {
1823526Sxy150489 		frag_count++;
1833526Sxy150489 		msg_size += MBLKL(nmp);
1843526Sxy150489 	}
1853526Sxy150489 
1867607STed.You@Sun.COM 	/* retrieve and compute information for context descriptor */
1877607STed.You@Sun.COM 	if (!e1000g_retrieve_context(mp, &cur_context, msg_size)) {
1886986Smx205022 		freemsg(mp);
1896986Smx205022 		return (B_TRUE);
1906986Smx205022 	}
1916986Smx205022 
1926986Smx205022 	/*
1936986Smx205022 	 * Make sure the packet is less than the allowed size
1946986Smx205022 	 */
1956986Smx205022 	if (!cur_context.lso_flag &&
1966986Smx205022 	    (msg_size > Adapter->max_frame_size - ETHERFCSL)) {
1973526Sxy150489 		/*
1983526Sxy150489 		 * For the over size packet, we'll just drop it.
1993526Sxy150489 		 * So we return B_TRUE here.
2003526Sxy150489 		 */
2014919Sxy150489 		E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
2023526Sxy150489 		    "Tx packet out of bound. length = %d \n", msg_size);
2034919Sxy150489 		E1000G_STAT(tx_ring->stat_over_size);
2043526Sxy150489 		freemsg(mp);
2053526Sxy150489 		return (B_TRUE);
2063526Sxy150489 	}
2073526Sxy150489 
2083526Sxy150489 	/*
2093526Sxy150489 	 * Check and reclaim tx descriptors.
2103526Sxy150489 	 * This low water mark check should be done all the time as
2113526Sxy150489 	 * Transmit interrupt delay can produce Transmit interrupts little
2123526Sxy150489 	 * late and that may cause few problems related to reaping Tx
2133526Sxy150489 	 * Descriptors... As you may run short of them before getting any
2143526Sxy150489 	 * transmit interrupt...
2153526Sxy150489 	 */
2168275SEric Cheng 	if (tx_ring->tbd_avail < DEFAULT_TX_NO_RESOURCE) {
2173526Sxy150489 		(void) e1000g_recycle(tx_ring);
2185882Syy150190 		E1000G_DEBUG_STAT(tx_ring->stat_recycle);
2193526Sxy150489 
2205882Syy150190 		if (tx_ring->tbd_avail < DEFAULT_TX_NO_RESOURCE) {
2215882Syy150190 			E1000G_DEBUG_STAT(tx_ring->stat_lack_desc);
2225882Syy150190 			goto tx_no_resource;
2235882Syy150190 		}
2243526Sxy150489 	}
2253526Sxy150489 
2263526Sxy150489 	/*
2273526Sxy150489 	 * If the message size is less than the minimum ethernet packet size,
2283526Sxy150489 	 * we'll use bcopy to send it, and padd it to 60 bytes later.
2293526Sxy150489 	 */
2306394Scc210113 	if (msg_size < ETHERMIN) {
2314919Sxy150489 		E1000G_DEBUG_STAT(tx_ring->stat_under_size);
2326986Smx205022 		tx_undersize_flag = B_TRUE;
2333526Sxy150489 	}
2343526Sxy150489 
2353526Sxy150489 	/* Initialize variables */
2363526Sxy150489 	desc_count = 1;	/* The initial value should be greater than 0 */
2373526Sxy150489 	desc_total = 0;
23810589SChangqing.Li@Sun.COM 	new_mp = NULL;
2393526Sxy150489 	QUEUE_INIT_LIST(&pending_list);
2403526Sxy150489 
2413526Sxy150489 	/* Process each mblk fragment and fill tx descriptors */
2428073SMin.Xu@Sun.COM 	/*
2438073SMin.Xu@Sun.COM 	 * The software should guarantee LSO packet header(MAC+IP+TCP)
2448073SMin.Xu@Sun.COM 	 * to be within one descriptor. Here we reallocate and refill the
2458073SMin.Xu@Sun.COM 	 * the header if it's physical memory non-contiguous.
2468073SMin.Xu@Sun.COM 	 */
2478073SMin.Xu@Sun.COM 	if (cur_context.lso_flag) {
2488073SMin.Xu@Sun.COM 		/* find the last fragment of the header */
2498073SMin.Xu@Sun.COM 		len = MBLKL(mp);
2508073SMin.Xu@Sun.COM 		ASSERT(len > 0);
25110589SChangqing.Li@Sun.COM 		next_mp = mp;
2528073SMin.Xu@Sun.COM 		pre_mp = NULL;
2538073SMin.Xu@Sun.COM 		while (len < cur_context.hdr_len) {
25410589SChangqing.Li@Sun.COM 			pre_mp = next_mp;
25510589SChangqing.Li@Sun.COM 			next_mp = next_mp->b_cont;
25610589SChangqing.Li@Sun.COM 			len += MBLKL(next_mp);
2578073SMin.Xu@Sun.COM 		}
2588073SMin.Xu@Sun.COM 		/*
2598073SMin.Xu@Sun.COM 		 * If the header and the payload are in different mblks,
2608073SMin.Xu@Sun.COM 		 * we simply force the header to be copied into pre-allocated
2618073SMin.Xu@Sun.COM 		 * page-aligned buffer.
2628073SMin.Xu@Sun.COM 		 */
2638073SMin.Xu@Sun.COM 		if (len == cur_context.hdr_len)
2648073SMin.Xu@Sun.COM 			goto adjust_threshold;
2658073SMin.Xu@Sun.COM 
26610589SChangqing.Li@Sun.COM 		hdr_frag_len = cur_context.hdr_len - (len - MBLKL(next_mp));
2678073SMin.Xu@Sun.COM 		/*
268*12246SChangqing.Li@Sun.COM 		 * There are three cases we need to reallocate a mblk for the
2698073SMin.Xu@Sun.COM 		 * last header fragment:
270*12246SChangqing.Li@Sun.COM 		 *
2718073SMin.Xu@Sun.COM 		 * 1. the header is in multiple mblks and the last fragment
2728073SMin.Xu@Sun.COM 		 * share the same mblk with the payload
273*12246SChangqing.Li@Sun.COM 		 *
2748073SMin.Xu@Sun.COM 		 * 2. the header is in a single mblk shared with the payload
2758073SMin.Xu@Sun.COM 		 * and the header is physical memory non-contiguous
276*12246SChangqing.Li@Sun.COM 		 *
277*12246SChangqing.Li@Sun.COM 		 * 3. there is 4 KB boundary within the header and 64 bytes
278*12246SChangqing.Li@Sun.COM 		 * following the end of the header bytes. The case may cause
279*12246SChangqing.Li@Sun.COM 		 * TCP data corruption issue.
280*12246SChangqing.Li@Sun.COM 		 *
281*12246SChangqing.Li@Sun.COM 		 * The workaround for the case #2 and case #3 is:
282*12246SChangqing.Li@Sun.COM 		 *   Assuming standard Ethernet/IP/TCP headers of 54 bytes,
283*12246SChangqing.Li@Sun.COM 		 *   this means that the buffer(containing the headers) should
284*12246SChangqing.Li@Sun.COM 		 *   not start -118 bytes before a 4 KB boundary. For example,
285*12246SChangqing.Li@Sun.COM 		 *   128-byte alignment for this buffer could be used to fulfill
286*12246SChangqing.Li@Sun.COM 		 *   this condition.
2878073SMin.Xu@Sun.COM 		 */
28810589SChangqing.Li@Sun.COM 		if ((next_mp != mp) ||
289*12246SChangqing.Li@Sun.COM 		    (P2NPHASE((uintptr_t)next_mp->b_rptr,
290*12246SChangqing.Li@Sun.COM 		    E1000_LSO_FIRST_DESC_ALIGNMENT_BOUNDARY_4K)
291*12246SChangqing.Li@Sun.COM 		    < E1000_LSO_FIRST_DESC_ALIGNMENT)) {
2928073SMin.Xu@Sun.COM 			E1000G_DEBUG_STAT(tx_ring->stat_lso_header_fail);
2938073SMin.Xu@Sun.COM 			/*
2948073SMin.Xu@Sun.COM 			 * reallocate the mblk for the last header fragment,
2958073SMin.Xu@Sun.COM 			 * expect to bcopy into pre-allocated page-aligned
2968073SMin.Xu@Sun.COM 			 * buffer
2978073SMin.Xu@Sun.COM 			 */
2988073SMin.Xu@Sun.COM 			new_mp = allocb(hdr_frag_len, NULL);
2998073SMin.Xu@Sun.COM 			if (!new_mp)
3008073SMin.Xu@Sun.COM 				return (B_FALSE);
30110589SChangqing.Li@Sun.COM 			bcopy(next_mp->b_rptr, new_mp->b_rptr, hdr_frag_len);
3028073SMin.Xu@Sun.COM 			/* link the new header fragment with the other parts */
3038073SMin.Xu@Sun.COM 			new_mp->b_wptr = new_mp->b_rptr + hdr_frag_len;
30410589SChangqing.Li@Sun.COM 			new_mp->b_cont = next_mp;
3058073SMin.Xu@Sun.COM 			if (pre_mp)
3068073SMin.Xu@Sun.COM 				pre_mp->b_cont = new_mp;
3078850SMin.Xu@Sun.COM 			else
3088850SMin.Xu@Sun.COM 				mp = new_mp;
30910589SChangqing.Li@Sun.COM 			next_mp->b_rptr += hdr_frag_len;
31010589SChangqing.Li@Sun.COM 			frag_count++;
3118073SMin.Xu@Sun.COM 		}
3128073SMin.Xu@Sun.COM adjust_threshold:
3138073SMin.Xu@Sun.COM 		/*
3148073SMin.Xu@Sun.COM 		 * adjust the bcopy threshhold to guarantee
3158073SMin.Xu@Sun.COM 		 * the header to use bcopy way
3168073SMin.Xu@Sun.COM 		 */
3178073SMin.Xu@Sun.COM 		if (bcopy_thresh < cur_context.hdr_len)
3188073SMin.Xu@Sun.COM 			bcopy_thresh = cur_context.hdr_len;
3198073SMin.Xu@Sun.COM 	}
3208073SMin.Xu@Sun.COM 
3213526Sxy150489 	packet = NULL;
3223526Sxy150489 	nmp = mp;
3233526Sxy150489 	while (nmp) {
3243526Sxy150489 		tmp = nmp->b_cont;
3253526Sxy150489 
3263526Sxy150489 		len = MBLKL(nmp);
3273526Sxy150489 		/* Check zero length mblks */
3283526Sxy150489 		if (len == 0) {
3294919Sxy150489 			E1000G_DEBUG_STAT(tx_ring->stat_empty_frags);
3303526Sxy150489 			/*
3313526Sxy150489 			 * If there're no packet buffers have been used,
3323526Sxy150489 			 * or we just completed processing a buffer, then
3333526Sxy150489 			 * skip the empty mblk fragment.
3343526Sxy150489 			 * Otherwise, there's still a pending buffer that
3353526Sxy150489 			 * needs to be processed (tx_copy).
3363526Sxy150489 			 */
3373526Sxy150489 			if (desc_count > 0) {
3383526Sxy150489 				nmp = tmp;
3393526Sxy150489 				continue;
3403526Sxy150489 			}
3413526Sxy150489 		}
3423526Sxy150489 
3433526Sxy150489 		/*
3443526Sxy150489 		 * Get a new TxSwPacket to process mblk buffers.
3453526Sxy150489 		 */
3463526Sxy150489 		if (desc_count > 0) {
3473526Sxy150489 			mutex_enter(&tx_ring->freelist_lock);
3484919Sxy150489 			packet = (p_tx_sw_packet_t)
3493526Sxy150489 			    QUEUE_POP_HEAD(&tx_ring->free_list);
3503526Sxy150489 			mutex_exit(&tx_ring->freelist_lock);
3513526Sxy150489 
3523526Sxy150489 			if (packet == NULL) {
3534919Sxy150489 				E1000G_DEBUGLOG_0(Adapter, E1000G_INFO_LEVEL,
3543526Sxy150489 				    "No Tx SwPacket available\n");
3554919Sxy150489 				E1000G_STAT(tx_ring->stat_no_swpkt);
3563526Sxy150489 				goto tx_send_failed;
3573526Sxy150489 			}
3583526Sxy150489 			QUEUE_PUSH_TAIL(&pending_list, &packet->Link);
3593526Sxy150489 		}
3603526Sxy150489 
3613526Sxy150489 		ASSERT(packet);
3623526Sxy150489 		/*
3633526Sxy150489 		 * If the size of the fragment is less than the tx_bcopy_thresh
3643526Sxy150489 		 * we'll use bcopy; Otherwise, we'll use DMA binding.
3653526Sxy150489 		 */
3668073SMin.Xu@Sun.COM 		if ((len <= bcopy_thresh) || tx_undersize_flag) {
3673526Sxy150489 			desc_count =
3686986Smx205022 			    e1000g_tx_copy(tx_ring, packet, nmp,
3696986Smx205022 			    tx_undersize_flag);
3704919Sxy150489 			E1000G_DEBUG_STAT(tx_ring->stat_copy);
3713526Sxy150489 		} else {
3723526Sxy150489 			desc_count =
3734919Sxy150489 			    e1000g_tx_bind(tx_ring, packet, nmp);
3744919Sxy150489 			E1000G_DEBUG_STAT(tx_ring->stat_bind);
3753526Sxy150489 		}
3763526Sxy150489 
3773526Sxy150489 		if (desc_count > 0)
3783526Sxy150489 			desc_total += desc_count;
3794919Sxy150489 		else if (desc_count < 0)
3804919Sxy150489 			goto tx_send_failed;
3813526Sxy150489 
3823526Sxy150489 		nmp = tmp;
3833526Sxy150489 	}
3843526Sxy150489 
3853526Sxy150489 	/* Assign the message to the last sw packet */
3863526Sxy150489 	ASSERT(packet);
3873526Sxy150489 	ASSERT(packet->mp == NULL);
3883526Sxy150489 	packet->mp = mp;
3893526Sxy150489 
3903526Sxy150489 	/* Try to recycle the tx descriptors again */
391*12246SChangqing.Li@Sun.COM 	if (tx_ring->tbd_avail < (desc_total + 3)) {
3924919Sxy150489 		E1000G_DEBUG_STAT(tx_ring->stat_recycle_retry);
3933526Sxy150489 		(void) e1000g_recycle(tx_ring);
3943526Sxy150489 	}
3953526Sxy150489 
3963526Sxy150489 	mutex_enter(&tx_ring->tx_lock);
3973526Sxy150489 
3983526Sxy150489 	/*
3993526Sxy150489 	 * If the number of available tx descriptors is not enough for transmit
4003526Sxy150489 	 * (one redundant descriptor and one hw checksum context descriptor are
4013526Sxy150489 	 * included), then return failure.
4023526Sxy150489 	 */
403*12246SChangqing.Li@Sun.COM 	if (tx_ring->tbd_avail < (desc_total + 3)) {
4044919Sxy150489 		E1000G_DEBUGLOG_0(Adapter, E1000G_INFO_LEVEL,
4053526Sxy150489 		    "No Enough Tx descriptors\n");
4064919Sxy150489 		E1000G_STAT(tx_ring->stat_no_desc);
4073526Sxy150489 		mutex_exit(&tx_ring->tx_lock);
4083526Sxy150489 		goto tx_send_failed;
4093526Sxy150489 	}
4103526Sxy150489 
4116986Smx205022 	desc_count = e1000g_fill_tx_ring(tx_ring, &pending_list, &cur_context);
4123526Sxy150489 
4133526Sxy150489 	mutex_exit(&tx_ring->tx_lock);
4143526Sxy150489 
4153526Sxy150489 	ASSERT(desc_count > 0);
4163526Sxy150489 
4173526Sxy150489 	/* Send successful */
4183526Sxy150489 	return (B_TRUE);
4193526Sxy150489 
4203526Sxy150489 tx_send_failed:
42110589SChangqing.Li@Sun.COM 	/* Restore mp to original */
42210589SChangqing.Li@Sun.COM 	if (new_mp) {
42310589SChangqing.Li@Sun.COM 		if (pre_mp) {
42410589SChangqing.Li@Sun.COM 			pre_mp->b_cont = next_mp;
42510589SChangqing.Li@Sun.COM 		}
42610589SChangqing.Li@Sun.COM 		new_mp->b_cont = NULL;
42710589SChangqing.Li@Sun.COM 		freemsg(new_mp);
42810589SChangqing.Li@Sun.COM 
42910589SChangqing.Li@Sun.COM 		next_mp->b_rptr -= hdr_frag_len;
43010589SChangqing.Li@Sun.COM 	}
43110589SChangqing.Li@Sun.COM 
4325882Syy150190 	/*
4335882Syy150190 	 * Enable Transmit interrupts, so that the interrupt routine can
4345882Syy150190 	 * call mac_tx_update() when transmit descriptors become available.
4355882Syy150190 	 */
4368275SEric Cheng 	tx_ring->resched_timestamp = ddi_get_lbolt();
4375882Syy150190 	tx_ring->resched_needed = B_TRUE;
4385882Syy150190 	if (!Adapter->tx_intr_enable)
4395882Syy150190 		e1000g_mask_tx_interrupt(Adapter);
4405882Syy150190 
4413526Sxy150489 	/* Free pending TxSwPackets */
4424919Sxy150489 	packet = (p_tx_sw_packet_t)QUEUE_GET_HEAD(&pending_list);
4433526Sxy150489 	while (packet) {
4443526Sxy150489 		packet->mp = NULL;
4454919Sxy150489 		e1000g_free_tx_swpkt(packet);
4464919Sxy150489 		packet = (p_tx_sw_packet_t)
4473526Sxy150489 		    QUEUE_GET_NEXT(&pending_list, &packet->Link);
4483526Sxy150489 	}
4493526Sxy150489 
4503526Sxy150489 	/* Return pending TxSwPackets to the "Free" list */
4513526Sxy150489 	mutex_enter(&tx_ring->freelist_lock);
4523526Sxy150489 	QUEUE_APPEND(&tx_ring->free_list, &pending_list);
4533526Sxy150489 	mutex_exit(&tx_ring->freelist_lock);
4543526Sxy150489 
4554919Sxy150489 	E1000G_STAT(tx_ring->stat_send_fail);
4563526Sxy150489 
4575882Syy150190 	/* Message will be scheduled for re-transmit */
4585882Syy150190 	return (B_FALSE);
4593526Sxy150489 
4603526Sxy150489 tx_no_resource:
4613526Sxy150489 	/*
4623526Sxy150489 	 * Enable Transmit interrupts, so that the interrupt routine can
4633526Sxy150489 	 * call mac_tx_update() when transmit descriptors become available.
4643526Sxy150489 	 */
4658275SEric Cheng 	tx_ring->resched_timestamp = ddi_get_lbolt();
4664919Sxy150489 	tx_ring->resched_needed = B_TRUE;
4673526Sxy150489 	if (!Adapter->tx_intr_enable)
4684919Sxy150489 		e1000g_mask_tx_interrupt(Adapter);
4693526Sxy150489 
4703526Sxy150489 	/* Message will be scheduled for re-transmit */
4713526Sxy150489 	return (B_FALSE);
4723526Sxy150489 }
4733526Sxy150489 
4744061Sxy150489 static boolean_t
e1000g_retrieve_context(mblk_t * mp,context_data_t * cur_context,size_t msg_size)4757607STed.You@Sun.COM e1000g_retrieve_context(mblk_t *mp, context_data_t *cur_context,
4766986Smx205022     size_t msg_size)
4774061Sxy150489 {
4786986Smx205022 	uintptr_t ip_start;
4796986Smx205022 	uintptr_t tcp_start;
4806986Smx205022 	mblk_t *nmp;
4818275SEric Cheng 	uint32_t lsoflags;
4828275SEric Cheng 	uint32_t mss;
4836986Smx205022 
4846986Smx205022 	bzero(cur_context, sizeof (context_data_t));
4854061Sxy150489 
4868275SEric Cheng 	/* first check lso information */
48711878SVenu.Iyer@Sun.COM 	mac_lso_get(mp, &mss, &lsoflags);
4888275SEric Cheng 
4896986Smx205022 	/* retrieve checksum info */
49011878SVenu.Iyer@Sun.COM 	mac_hcksum_get(mp, &cur_context->cksum_start,
4916986Smx205022 	    &cur_context->cksum_stuff, NULL, NULL, &cur_context->cksum_flags);
4927607STed.You@Sun.COM 	/* retrieve ethernet header size */
4937426SChenliang.Xu@Sun.COM 	if (((struct ether_vlan_header *)(uintptr_t)mp->b_rptr)->ether_tpid ==
4946986Smx205022 	    htons(ETHERTYPE_VLAN))
4956986Smx205022 		cur_context->ether_header_size =
4966986Smx205022 		    sizeof (struct ether_vlan_header);
4976986Smx205022 	else
4986986Smx205022 		cur_context->ether_header_size =
4996986Smx205022 		    sizeof (struct ether_header);
5004061Sxy150489 
5018275SEric Cheng 	if (lsoflags & HW_LSO) {
5028275SEric Cheng 		ASSERT(mss != 0);
5038275SEric Cheng 
5048275SEric Cheng 		/* free the invalid packet */
5058275SEric Cheng 		if (mss == 0 ||
5068275SEric Cheng 		    !((cur_context->cksum_flags & HCK_PARTIALCKSUM) &&
5078275SEric Cheng 		    (cur_context->cksum_flags & HCK_IPV4_HDRCKSUM))) {
5088275SEric Cheng 			return (B_FALSE);
5096986Smx205022 		}
5108275SEric Cheng 		cur_context->mss = (uint16_t)mss;
5118275SEric Cheng 		cur_context->lso_flag = B_TRUE;
5128275SEric Cheng 
5138275SEric Cheng 		/*
5148275SEric Cheng 		 * Some fields are cleared for the hardware to fill
5158275SEric Cheng 		 * in. We don't assume Ethernet header, IP header and
5168275SEric Cheng 		 * TCP header are always in the same mblk fragment,
5178275SEric Cheng 		 * while we assume each header is always within one
5188275SEric Cheng 		 * mblk fragment and Ethernet header is always in the
5198275SEric Cheng 		 * first mblk fragment.
5208275SEric Cheng 		 */
5218275SEric Cheng 		nmp = mp;
5228275SEric Cheng 		ip_start = (uintptr_t)(nmp->b_rptr)
5238275SEric Cheng 		    + cur_context->ether_header_size;
5248275SEric Cheng 		if (ip_start >= (uintptr_t)(nmp->b_wptr)) {
5258275SEric Cheng 			ip_start = (uintptr_t)nmp->b_cont->b_rptr
5268275SEric Cheng 			    + (ip_start - (uintptr_t)(nmp->b_wptr));
5278275SEric Cheng 			nmp = nmp->b_cont;
5288275SEric Cheng 		}
5298275SEric Cheng 		tcp_start = ip_start +
5308275SEric Cheng 		    IPH_HDR_LENGTH((ipha_t *)ip_start);
5318275SEric Cheng 		if (tcp_start >= (uintptr_t)(nmp->b_wptr)) {
5328275SEric Cheng 			tcp_start = (uintptr_t)nmp->b_cont->b_rptr
5338275SEric Cheng 			    + (tcp_start - (uintptr_t)(nmp->b_wptr));
5348275SEric Cheng 			nmp = nmp->b_cont;
5358275SEric Cheng 		}
5368275SEric Cheng 		cur_context->hdr_len = cur_context->ether_header_size
5378275SEric Cheng 		    + IPH_HDR_LENGTH((ipha_t *)ip_start)
5388275SEric Cheng 		    + TCP_HDR_LENGTH((tcph_t *)tcp_start);
5398275SEric Cheng 		((ipha_t *)ip_start)->ipha_length = 0;
5408275SEric Cheng 		((ipha_t *)ip_start)->ipha_hdr_checksum = 0;
5418275SEric Cheng 		/* calculate the TCP packet payload length */
5428275SEric Cheng 		cur_context->pay_len = msg_size - cur_context->hdr_len;
5436986Smx205022 	}
5446986Smx205022 	return (B_TRUE);
5456986Smx205022 }
5464061Sxy150489 
5476986Smx205022 static boolean_t
e1000g_check_context(e1000g_tx_ring_t * tx_ring,context_data_t * cur_context)5486986Smx205022 e1000g_check_context(e1000g_tx_ring_t *tx_ring, context_data_t *cur_context)
5496986Smx205022 {
5506986Smx205022 	boolean_t context_reload;
5516986Smx205022 	context_data_t *pre_context;
5526986Smx205022 	struct e1000g *Adapter;
5536986Smx205022 
5546986Smx205022 	context_reload = B_FALSE;
5556986Smx205022 	pre_context = &tx_ring->pre_context;
5566986Smx205022 	Adapter = tx_ring->adapter;
5576986Smx205022 
5586986Smx205022 	/*
5596986Smx205022 	 * The following code determine if the context descriptor is
5606986Smx205022 	 * needed to be reloaded. The sequence of the conditions is
5616986Smx205022 	 * made by their possibilities of changing.
5626986Smx205022 	 */
5636986Smx205022 	/*
5646986Smx205022 	 * workaround for 82546EB, context descriptor must be reloaded
5656986Smx205022 	 * per LSO/hw_cksum packet if LSO is enabled.
5666986Smx205022 	 */
5676986Smx205022 	if (Adapter->lso_premature_issue &&
5686986Smx205022 	    Adapter->lso_enable &&
5696986Smx205022 	    (cur_context->cksum_flags != 0)) {
5706986Smx205022 
5716986Smx205022 		context_reload = B_TRUE;
5726986Smx205022 	} else if (cur_context->lso_flag) {
5738073SMin.Xu@Sun.COM 		if ((cur_context->lso_flag != pre_context->lso_flag) ||
5748073SMin.Xu@Sun.COM 		    (cur_context->cksum_flags != pre_context->cksum_flags) ||
5756986Smx205022 		    (cur_context->pay_len != pre_context->pay_len) ||
5766986Smx205022 		    (cur_context->mss != pre_context->mss) ||
5776986Smx205022 		    (cur_context->hdr_len != pre_context->hdr_len) ||
5786986Smx205022 		    (cur_context->cksum_stuff != pre_context->cksum_stuff) ||
5796986Smx205022 		    (cur_context->cksum_start != pre_context->cksum_start) ||
5806986Smx205022 		    (cur_context->ether_header_size !=
5816986Smx205022 		    pre_context->ether_header_size)) {
5826986Smx205022 
5836986Smx205022 			context_reload = B_TRUE;
5846986Smx205022 		}
5856986Smx205022 	} else if (cur_context->cksum_flags != 0) {
5868073SMin.Xu@Sun.COM 		if ((cur_context->lso_flag != pre_context->lso_flag) ||
5878073SMin.Xu@Sun.COM 		    (cur_context->cksum_flags != pre_context->cksum_flags) ||
5886986Smx205022 		    (cur_context->cksum_stuff != pre_context->cksum_stuff) ||
5896986Smx205022 		    (cur_context->cksum_start != pre_context->cksum_start) ||
5906986Smx205022 		    (cur_context->ether_header_size !=
5916986Smx205022 		    pre_context->ether_header_size)) {
5926986Smx205022 
5936986Smx205022 			context_reload = B_TRUE;
5944061Sxy150489 		}
5954061Sxy150489 	}
5964061Sxy150489 
5976986Smx205022 	return (context_reload);
5984061Sxy150489 }
5994061Sxy150489 
6003526Sxy150489 static int
e1000g_fill_tx_ring(e1000g_tx_ring_t * tx_ring,LIST_DESCRIBER * pending_list,context_data_t * cur_context)6013526Sxy150489 e1000g_fill_tx_ring(e1000g_tx_ring_t *tx_ring, LIST_DESCRIBER *pending_list,
6026986Smx205022     context_data_t *cur_context)
6033526Sxy150489 {
6043526Sxy150489 	struct e1000g *Adapter;
6054919Sxy150489 	struct e1000_hw *hw;
6064919Sxy150489 	p_tx_sw_packet_t first_packet;
6074919Sxy150489 	p_tx_sw_packet_t packet;
6086986Smx205022 	p_tx_sw_packet_t previous_packet;
6096986Smx205022 	boolean_t context_reload;
6103526Sxy150489 	struct e1000_tx_desc *first_data_desc;
6113526Sxy150489 	struct e1000_tx_desc *next_desc;
6123526Sxy150489 	struct e1000_tx_desc *descriptor;
6133526Sxy150489 	int desc_count;
6146986Smx205022 	boolean_t buff_overrun_flag;
6153526Sxy150489 	int i;
6163526Sxy150489 
6173526Sxy150489 	Adapter = tx_ring->adapter;
6184919Sxy150489 	hw = &Adapter->shared;
6193526Sxy150489 
6203526Sxy150489 	desc_count = 0;
6214061Sxy150489 	first_packet = NULL;
6223526Sxy150489 	first_data_desc = NULL;
6233526Sxy150489 	descriptor = NULL;
6246986Smx205022 	first_packet = NULL;
6256986Smx205022 	packet = NULL;
6266986Smx205022 	buff_overrun_flag = B_FALSE;
6273526Sxy150489 
6283526Sxy150489 	next_desc = tx_ring->tbd_next;
6293526Sxy150489 
6306986Smx205022 	/* Context descriptor reload check */
6316986Smx205022 	context_reload = e1000g_check_context(tx_ring, cur_context);
6324061Sxy150489 
6336986Smx205022 	if (context_reload) {
6344919Sxy150489 		first_packet = (p_tx_sw_packet_t)QUEUE_GET_HEAD(pending_list);
6354061Sxy150489 
6363526Sxy150489 		descriptor = next_desc;
6373526Sxy150489 
6386986Smx205022 		e1000g_fill_context_descriptor(cur_context,
6394061Sxy150489 		    (struct e1000_context_desc *)descriptor);
6403526Sxy150489 
6413526Sxy150489 		/* Check the wrap-around case */
6423526Sxy150489 		if (descriptor == tx_ring->tbd_last)
6433526Sxy150489 			next_desc = tx_ring->tbd_first;
6443526Sxy150489 		else
6453526Sxy150489 			next_desc++;
6463526Sxy150489 
6473526Sxy150489 		desc_count++;
6483526Sxy150489 	}
6493526Sxy150489 
6503526Sxy150489 	first_data_desc = next_desc;
6513526Sxy150489 
6524919Sxy150489 	packet = (p_tx_sw_packet_t)QUEUE_GET_HEAD(pending_list);
6533526Sxy150489 	while (packet) {
6543526Sxy150489 		ASSERT(packet->num_desc);
6553526Sxy150489 
6563526Sxy150489 		for (i = 0; i < packet->num_desc; i++) {
6574919Sxy150489 			ASSERT(tx_ring->tbd_avail > 0);
6583526Sxy150489 
6593526Sxy150489 			descriptor = next_desc;
6603526Sxy150489 			descriptor->buffer_addr =
6614919Sxy150489 			    packet->desc[i].address;
6623526Sxy150489 			descriptor->lower.data =
6634919Sxy150489 			    packet->desc[i].length;
6643526Sxy150489 
6653526Sxy150489 			/* Zero out status */
6663526Sxy150489 			descriptor->upper.data = 0;
6673526Sxy150489 
6683526Sxy150489 			descriptor->lower.data |=
6693526Sxy150489 			    E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
6703526Sxy150489 			/* must set RS on every outgoing descriptor */
6713526Sxy150489 			descriptor->lower.data |=
6723526Sxy150489 			    E1000_TXD_CMD_RS;
6733526Sxy150489 
6746986Smx205022 			if (cur_context->lso_flag)
6756986Smx205022 				descriptor->lower.data |= E1000_TXD_CMD_TSE;
6766986Smx205022 
6773526Sxy150489 			/* Check the wrap-around case */
6783526Sxy150489 			if (descriptor == tx_ring->tbd_last)
6793526Sxy150489 				next_desc = tx_ring->tbd_first;
6803526Sxy150489 			else
6813526Sxy150489 				next_desc++;
6823526Sxy150489 
6833526Sxy150489 			desc_count++;
6846986Smx205022 
6856986Smx205022 			/*
6866986Smx205022 			 * workaround for 82546EB errata 33, hang in PCI-X
6876986Smx205022 			 * systems due to 2k Buffer Overrun during Transmit
6886986Smx205022 			 * Operation. The workaround applies to all the Intel
6896986Smx205022 			 * PCI-X chips.
6906986Smx205022 			 */
6916986Smx205022 			if (hw->bus.type == e1000_bus_type_pcix &&
6926986Smx205022 			    descriptor == first_data_desc &&
6936986Smx205022 			    ((descriptor->lower.data & E1000G_TBD_LENGTH_MASK)
6946986Smx205022 			    > E1000_TX_BUFFER_OEVRRUN_THRESHOLD)) {
6956986Smx205022 				/* modified the first descriptor */
6966986Smx205022 				descriptor->lower.data &=
6976986Smx205022 				    ~E1000G_TBD_LENGTH_MASK;
6986986Smx205022 				descriptor->lower.flags.length =
6996986Smx205022 				    E1000_TX_BUFFER_OEVRRUN_THRESHOLD;
7006986Smx205022 
7016986Smx205022 				/* insert a new descriptor */
7026986Smx205022 				ASSERT(tx_ring->tbd_avail > 0);
7036986Smx205022 				next_desc->buffer_addr =
7046986Smx205022 				    packet->desc[0].address +
7056986Smx205022 				    E1000_TX_BUFFER_OEVRRUN_THRESHOLD;
7066986Smx205022 				next_desc->lower.data =
7076986Smx205022 				    packet->desc[0].length -
7086986Smx205022 				    E1000_TX_BUFFER_OEVRRUN_THRESHOLD;
7096986Smx205022 
7106986Smx205022 				/* Zero out status */
7116986Smx205022 				next_desc->upper.data = 0;
7126986Smx205022 
7136986Smx205022 				next_desc->lower.data |=
7146986Smx205022 				    E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
7156986Smx205022 				/* must set RS on every outgoing descriptor */
7166986Smx205022 				next_desc->lower.data |=
7176986Smx205022 				    E1000_TXD_CMD_RS;
7186986Smx205022 
7196986Smx205022 				if (cur_context->lso_flag)
7206986Smx205022 					next_desc->lower.data |=
7216986Smx205022 					    E1000_TXD_CMD_TSE;
7226986Smx205022 
7236986Smx205022 				descriptor = next_desc;
7246986Smx205022 
7256986Smx205022 				/* Check the wrap-around case */
7266986Smx205022 				if (next_desc == tx_ring->tbd_last)
7276986Smx205022 					next_desc = tx_ring->tbd_first;
7286986Smx205022 				else
7296986Smx205022 					next_desc++;
7306986Smx205022 
7316986Smx205022 				desc_count++;
7326986Smx205022 				buff_overrun_flag = B_TRUE;
7336986Smx205022 			}
7346986Smx205022 		}
7356986Smx205022 
7366986Smx205022 		if (buff_overrun_flag) {
7376986Smx205022 			packet->num_desc++;
7386986Smx205022 			buff_overrun_flag = B_FALSE;
7393526Sxy150489 		}
7403526Sxy150489 
7413526Sxy150489 		if (first_packet != NULL) {
7423526Sxy150489 			/*
7433526Sxy150489 			 * Count the checksum context descriptor for
7443526Sxy150489 			 * the first SwPacket.
7453526Sxy150489 			 */
7463526Sxy150489 			first_packet->num_desc++;
7473526Sxy150489 			first_packet = NULL;
7483526Sxy150489 		}
7493526Sxy150489 
75011066Srafael.vanoni@sun.com 		packet->tickstamp = ddi_get_lbolt64();
7518850SMin.Xu@Sun.COM 
7526986Smx205022 		previous_packet = packet;
7534919Sxy150489 		packet = (p_tx_sw_packet_t)
7543526Sxy150489 		    QUEUE_GET_NEXT(pending_list, &packet->Link);
7553526Sxy150489 	}
7563526Sxy150489 
7576986Smx205022 	/*
7586986Smx205022 	 * workaround for 82546EB errata 21, LSO Premature Descriptor Write Back
7596986Smx205022 	 */
7606986Smx205022 	if (Adapter->lso_premature_issue && cur_context->lso_flag &&
7616986Smx205022 	    ((descriptor->lower.data & E1000G_TBD_LENGTH_MASK) > 8)) {
7626986Smx205022 		/* modified the previous descriptor */
7636986Smx205022 		descriptor->lower.data -= 4;
7646986Smx205022 
7656986Smx205022 		/* insert a new descriptor */
7666986Smx205022 		ASSERT(tx_ring->tbd_avail > 0);
7676986Smx205022 		/* the lower 20 bits of lower.data is the length field */
7686986Smx205022 		next_desc->buffer_addr =
7696986Smx205022 		    descriptor->buffer_addr +
7706986Smx205022 		    (descriptor->lower.data & E1000G_TBD_LENGTH_MASK);
7716986Smx205022 		next_desc->lower.data = 4;
7726986Smx205022 
7736986Smx205022 		/* Zero out status */
7746986Smx205022 		next_desc->upper.data = 0;
7756986Smx205022 		/* It must be part of a LSO packet */
7766986Smx205022 		next_desc->lower.data |=
7776986Smx205022 		    E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D |
7786986Smx205022 		    E1000_TXD_CMD_RS | E1000_TXD_CMD_TSE;
7796986Smx205022 
7806986Smx205022 		descriptor = next_desc;
7816986Smx205022 
7826986Smx205022 		/* Check the wrap-around case */
7836986Smx205022 		if (descriptor == tx_ring->tbd_last)
7846986Smx205022 			next_desc = tx_ring->tbd_first;
7856986Smx205022 		else
7866986Smx205022 			next_desc++;
7876986Smx205022 
7886986Smx205022 		desc_count++;
7896986Smx205022 		/* update the number of descriptors */
7906986Smx205022 		previous_packet->num_desc++;
7916986Smx205022 	}
7926986Smx205022 
7933526Sxy150489 	ASSERT(descriptor);
7943526Sxy150489 
7956986Smx205022 	if (cur_context->cksum_flags) {
7966986Smx205022 		if (cur_context->cksum_flags & HCK_IPV4_HDRCKSUM)
7973526Sxy150489 			((struct e1000_data_desc *)first_data_desc)->
7984608Syy150190 			    upper.fields.popts |= E1000_TXD_POPTS_IXSM;
7996986Smx205022 		if (cur_context->cksum_flags & HCK_PARTIALCKSUM)
8003526Sxy150489 			((struct e1000_data_desc *)first_data_desc)->
8014608Syy150190 			    upper.fields.popts |= E1000_TXD_POPTS_TXSM;
8023526Sxy150489 	}
8033526Sxy150489 
8043526Sxy150489 	/*
8053526Sxy150489 	 * Last Descriptor of Packet needs End Of Packet (EOP), Report
8066986Smx205022 	 * Status (RS) set.
8073526Sxy150489 	 */
8084919Sxy150489 	if (Adapter->tx_intr_delay) {
8093526Sxy150489 		descriptor->lower.data |= E1000_TXD_CMD_IDE |
8106986Smx205022 		    E1000_TXD_CMD_EOP;
8113526Sxy150489 	} else {
8126986Smx205022 		descriptor->lower.data |= E1000_TXD_CMD_EOP;
8136986Smx205022 	}
8146986Smx205022 
8156986Smx205022 	/* Set append Ethernet CRC (IFCS) bits */
8166986Smx205022 	if (cur_context->lso_flag) {
8176986Smx205022 		first_data_desc->lower.data |= E1000_TXD_CMD_IFCS;
8186986Smx205022 	} else {
8196986Smx205022 		descriptor->lower.data |= E1000_TXD_CMD_IFCS;
8203526Sxy150489 	}
8213526Sxy150489 
8223526Sxy150489 	/*
8233526Sxy150489 	 * Sync the Tx descriptors DMA buffer
8243526Sxy150489 	 */
8254919Sxy150489 	(void) ddi_dma_sync(tx_ring->tbd_dma_handle,
8264919Sxy150489 	    0, 0, DDI_DMA_SYNC_FORDEV);
8273526Sxy150489 
8283526Sxy150489 	tx_ring->tbd_next = next_desc;
8293526Sxy150489 
8303526Sxy150489 	/*
8313526Sxy150489 	 * Advance the Transmit Descriptor Tail (Tdt), this tells the
8323526Sxy150489 	 * FX1000 that this frame is available to transmit.
8333526Sxy150489 	 */
8344919Sxy150489 	if (hw->mac.type == e1000_82547)
8353526Sxy150489 		e1000g_82547_tx_move_tail(tx_ring);
8363526Sxy150489 	else
8376735Scc210113 		E1000_WRITE_REG(hw, E1000_TDT(0),
8383526Sxy150489 		    (uint32_t)(next_desc - tx_ring->tbd_first));
8393526Sxy150489 
8405273Sgl147354 	if (e1000g_check_acc_handle(Adapter->osdep.reg_handle) != DDI_FM_OK) {
8415273Sgl147354 		ddi_fm_service_impact(Adapter->dip, DDI_SERVICE_DEGRADED);
8428479SChenlu.Chen@Sun.COM 		Adapter->e1000g_state |= E1000G_ERROR;
8435273Sgl147354 	}
8445273Sgl147354 
8453526Sxy150489 	/* Put the pending SwPackets to the "Used" list */
8463526Sxy150489 	mutex_enter(&tx_ring->usedlist_lock);
8473526Sxy150489 	QUEUE_APPEND(&tx_ring->used_list, pending_list);
8484919Sxy150489 	tx_ring->tbd_avail -= desc_count;
8493526Sxy150489 	mutex_exit(&tx_ring->usedlist_lock);
8503526Sxy150489 
8516986Smx205022 	/* update LSO related data */
8526986Smx205022 	if (context_reload)
8536986Smx205022 		tx_ring->pre_context = *cur_context;
8544061Sxy150489 
8553526Sxy150489 	return (desc_count);
8563526Sxy150489 }
8573526Sxy150489 
8583526Sxy150489 /*
8594919Sxy150489  * e1000g_tx_setup - setup tx data structures
8604919Sxy150489  *
8614919Sxy150489  * This routine initializes all of the transmit related
8624919Sxy150489  * structures. This includes the Transmit descriptors,
8634919Sxy150489  * and the tx_sw_packet structures.
8643526Sxy150489  */
8653526Sxy150489 void
e1000g_tx_setup(struct e1000g * Adapter)8664919Sxy150489 e1000g_tx_setup(struct e1000g *Adapter)
8673526Sxy150489 {
8683526Sxy150489 	struct e1000_hw *hw;
8694919Sxy150489 	p_tx_sw_packet_t packet;
8707607STed.You@Sun.COM 	uint32_t i;
8713526Sxy150489 	uint32_t buf_high;
8723526Sxy150489 	uint32_t buf_low;
8733526Sxy150489 	uint32_t reg_tipg;
8743526Sxy150489 	uint32_t reg_tctl;
8753526Sxy150489 	int size;
8763526Sxy150489 	e1000g_tx_ring_t *tx_ring;
8773526Sxy150489 
8784919Sxy150489 	hw = &Adapter->shared;
8793526Sxy150489 	tx_ring = Adapter->tx_ring;
8803526Sxy150489 
8813526Sxy150489 	/* init the lists */
8823526Sxy150489 	/*
8833526Sxy150489 	 * Here we don't need to protect the lists using the
8844919Sxy150489 	 * usedlist_lock and freelist_lock, for they have
8853526Sxy150489 	 * been protected by the chip_lock.
8863526Sxy150489 	 */
8873526Sxy150489 	QUEUE_INIT_LIST(&tx_ring->used_list);
8883526Sxy150489 	QUEUE_INIT_LIST(&tx_ring->free_list);
8893526Sxy150489 
8903526Sxy150489 	/* Go through and set up each SW_Packet */
8913526Sxy150489 	packet = tx_ring->packet_area;
8924919Sxy150489 	for (i = 0; i < Adapter->tx_freelist_num; i++, packet++) {
8934919Sxy150489 		/* Initialize this tx_sw_apcket area */
8944919Sxy150489 		e1000g_free_tx_swpkt(packet);
8954919Sxy150489 		/* Add this tx_sw_packet to the free list */
8963526Sxy150489 		QUEUE_PUSH_TAIL(&tx_ring->free_list,
8973526Sxy150489 		    &packet->Link);
8983526Sxy150489 	}
8993526Sxy150489 
9003526Sxy150489 	/* Setup TX descriptor pointers */
9013526Sxy150489 	tx_ring->tbd_next = tx_ring->tbd_first;
9023526Sxy150489 	tx_ring->tbd_oldest = tx_ring->tbd_first;
9033526Sxy150489 
9043526Sxy150489 	/*
9053526Sxy150489 	 * Setup Hardware TX Registers
9063526Sxy150489 	 */
9073526Sxy150489 	/* Setup the Transmit Control Register (TCTL). */
9087133Scc210113 	reg_tctl = E1000_READ_REG(hw, E1000_TCTL);
9097133Scc210113 	reg_tctl |= E1000_TCTL_PSP | E1000_TCTL_EN |
9103526Sxy150489 	    (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT) |
9114919Sxy150489 	    (E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT) |
9124919Sxy150489 	    E1000_TCTL_RTLC;
9133526Sxy150489 
9143526Sxy150489 	/* Enable the MULR bit */
9154919Sxy150489 	if (hw->bus.type == e1000_bus_type_pci_express)
9163526Sxy150489 		reg_tctl |= E1000_TCTL_MULR;
9173526Sxy150489 
9184919Sxy150489 	E1000_WRITE_REG(hw, E1000_TCTL, reg_tctl);
9193526Sxy150489 
9203526Sxy150489 	/* Setup HW Base and Length of Tx descriptor area */
9214919Sxy150489 	size = (Adapter->tx_desc_num * sizeof (struct e1000_tx_desc));
9226735Scc210113 	E1000_WRITE_REG(hw, E1000_TDLEN(0), size);
9236735Scc210113 	size = E1000_READ_REG(hw, E1000_TDLEN(0));
9243526Sxy150489 
9253526Sxy150489 	buf_low = (uint32_t)tx_ring->tbd_dma_addr;
9263526Sxy150489 	buf_high = (uint32_t)(tx_ring->tbd_dma_addr >> 32);
9273526Sxy150489 
9288178SChenlu.Chen@Sun.COM 	/*
9298178SChenlu.Chen@Sun.COM 	 * Write the highest location first and work backward to the lowest.
9308178SChenlu.Chen@Sun.COM 	 * This is necessary for some adapter types to
9318178SChenlu.Chen@Sun.COM 	 * prevent write combining from occurring.
9328178SChenlu.Chen@Sun.COM 	 */
9338178SChenlu.Chen@Sun.COM 	E1000_WRITE_REG(hw, E1000_TDBAH(0), buf_high);
9346735Scc210113 	E1000_WRITE_REG(hw, E1000_TDBAL(0), buf_low);
9353526Sxy150489 
9363526Sxy150489 	/* Setup our HW Tx Head & Tail descriptor pointers */
9376735Scc210113 	E1000_WRITE_REG(hw, E1000_TDH(0), 0);
9386735Scc210113 	E1000_WRITE_REG(hw, E1000_TDT(0), 0);
9393526Sxy150489 
9403526Sxy150489 	/* Set the default values for the Tx Inter Packet Gap timer */
9414919Sxy150489 	if ((hw->mac.type == e1000_82542) &&
9424919Sxy150489 	    ((hw->revision_id == E1000_REVISION_2) ||
9434919Sxy150489 	    (hw->revision_id == E1000_REVISION_3))) {
9443526Sxy150489 		reg_tipg = DEFAULT_82542_TIPG_IPGT;
9453526Sxy150489 		reg_tipg |=
9463526Sxy150489 		    DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT;
9473526Sxy150489 		reg_tipg |=
9483526Sxy150489 		    DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
9497133Scc210113 	} else if (hw->mac.type == e1000_80003es2lan) {
9507133Scc210113 		reg_tipg = DEFAULT_82543_TIPG_IPGR1;
9517140Scc210113 		reg_tipg |= DEFAULT_80003ES2LAN_TIPG_IPGR2 <<
9527133Scc210113 		    E1000_TIPG_IPGR2_SHIFT;
9534919Sxy150489 	} else {
9546735Scc210113 		if (hw->phy.media_type == e1000_media_type_fiber)
9553526Sxy150489 			reg_tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
9563526Sxy150489 		else
9573526Sxy150489 			reg_tipg = DEFAULT_82543_TIPG_IPGT_COPPER;
9583526Sxy150489 		reg_tipg |=
9593526Sxy150489 		    DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT;
9603526Sxy150489 		reg_tipg |=
9613526Sxy150489 		    DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
9623526Sxy150489 	}
9634919Sxy150489 	E1000_WRITE_REG(hw, E1000_TIPG, reg_tipg);
9643526Sxy150489 
9653526Sxy150489 	/* Setup Transmit Interrupt Delay Value */
9665882Syy150190 	E1000_WRITE_REG(hw, E1000_TIDV, Adapter->tx_intr_delay);
9675882Syy150190 	E1000G_DEBUGLOG_1(Adapter, E1000G_INFO_LEVEL,
9685882Syy150190 	    "E1000_TIDV: 0x%x\n", Adapter->tx_intr_delay);
9695882Syy150190 
9705882Syy150190 	if (hw->mac.type >= e1000_82540) {
9715882Syy150190 		E1000_WRITE_REG(&Adapter->shared, E1000_TADV,
9725882Syy150190 		    Adapter->tx_intr_abs_delay);
9735882Syy150190 		E1000G_DEBUGLOG_1(Adapter, E1000G_INFO_LEVEL,
9745882Syy150190 		    "E1000_TADV: 0x%x\n", Adapter->tx_intr_abs_delay);
9753526Sxy150489 	}
9763526Sxy150489 
9774919Sxy150489 	tx_ring->tbd_avail = Adapter->tx_desc_num;
9784919Sxy150489 
9796986Smx205022 	/* Initialize stored context information */
9806986Smx205022 	bzero(&(tx_ring->pre_context), sizeof (context_data_t));
9813526Sxy150489 }
9823526Sxy150489 
9833526Sxy150489 /*
9844919Sxy150489  * e1000g_recycle - recycle the tx descriptors and tx sw packets
9853526Sxy150489  */
9863526Sxy150489 int
e1000g_recycle(e1000g_tx_ring_t * tx_ring)9873526Sxy150489 e1000g_recycle(e1000g_tx_ring_t *tx_ring)
9883526Sxy150489 {
9893526Sxy150489 	struct e1000g *Adapter;
9903526Sxy150489 	LIST_DESCRIBER pending_list;
9914919Sxy150489 	p_tx_sw_packet_t packet;
9923526Sxy150489 	mblk_t *mp;
9933526Sxy150489 	mblk_t *nmp;
9943526Sxy150489 	struct e1000_tx_desc *descriptor;
9953526Sxy150489 	int desc_count;
9968850SMin.Xu@Sun.COM 	int64_t delta;
9973526Sxy150489 
9983526Sxy150489 	/*
9993526Sxy150489 	 * This function will examine each TxSwPacket in the 'used' queue
10003526Sxy150489 	 * if the e1000g is done with it then the associated resources (Tx
10013526Sxy150489 	 * Descriptors) will be "freed" and the TxSwPacket will be
10023526Sxy150489 	 * returned to the 'free' queue.
10033526Sxy150489 	 */
10043526Sxy150489 	Adapter = tx_ring->adapter;
10058850SMin.Xu@Sun.COM 	delta = 0;
10063526Sxy150489 
10074919Sxy150489 	packet = (p_tx_sw_packet_t)QUEUE_GET_HEAD(&tx_ring->used_list);
10083526Sxy150489 	if (packet == NULL) {
10098850SMin.Xu@Sun.COM 		Adapter->stall_flag = B_FALSE;
10103526Sxy150489 		return (0);
10113526Sxy150489 	}
10123526Sxy150489 
10135882Syy150190 	desc_count = 0;
10145882Syy150190 	QUEUE_INIT_LIST(&pending_list);
10155882Syy150190 
10164919Sxy150489 	/* Sync the Tx descriptor DMA buffer */
10174919Sxy150489 	(void) ddi_dma_sync(tx_ring->tbd_dma_handle,
10184919Sxy150489 	    0, 0, DDI_DMA_SYNC_FORKERNEL);
10195273Sgl147354 	if (e1000g_check_dma_handle(
10205273Sgl147354 	    tx_ring->tbd_dma_handle) != DDI_FM_OK) {
10215273Sgl147354 		ddi_fm_service_impact(Adapter->dip, DDI_SERVICE_DEGRADED);
10228479SChenlu.Chen@Sun.COM 		Adapter->e1000g_state |= E1000G_ERROR;
10235273Sgl147354 		return (0);
10245273Sgl147354 	}
10254919Sxy150489 
10263526Sxy150489 	/*
10273526Sxy150489 	 * While there are still TxSwPackets in the used queue check them
10283526Sxy150489 	 */
10298275SEric Cheng 	mutex_enter(&tx_ring->usedlist_lock);
10307426SChenliang.Xu@Sun.COM 	while ((packet =
10317426SChenliang.Xu@Sun.COM 	    (p_tx_sw_packet_t)QUEUE_GET_HEAD(&tx_ring->used_list)) != NULL) {
10323526Sxy150489 
10333526Sxy150489 		/*
10343526Sxy150489 		 * Get hold of the next descriptor that the e1000g will
10353526Sxy150489 		 * report status back to (this will be the last descriptor
10364919Sxy150489 		 * of a given sw packet). We only want to free the
10374919Sxy150489 		 * sw packet (and it resources) if the e1000g is done
10383526Sxy150489 		 * with ALL of the descriptors.  If the e1000g is done
10393526Sxy150489 		 * with the last one then it is done with all of them.
10403526Sxy150489 		 */
10413526Sxy150489 		ASSERT(packet->num_desc);
10424919Sxy150489 		descriptor = tx_ring->tbd_oldest + (packet->num_desc - 1);
10433526Sxy150489 
10443526Sxy150489 		/* Check for wrap case */
10453526Sxy150489 		if (descriptor > tx_ring->tbd_last)
10464919Sxy150489 			descriptor -= Adapter->tx_desc_num;
10473526Sxy150489 
10483526Sxy150489 		/*
10493526Sxy150489 		 * If the descriptor done bit is set free TxSwPacket and
10503526Sxy150489 		 * associated resources
10513526Sxy150489 		 */
10523526Sxy150489 		if (descriptor->upper.fields.status & E1000_TXD_STAT_DD) {
10533526Sxy150489 			QUEUE_POP_HEAD(&tx_ring->used_list);
10543526Sxy150489 			QUEUE_PUSH_TAIL(&pending_list, &packet->Link);
10553526Sxy150489 
10563526Sxy150489 			if (descriptor == tx_ring->tbd_last)
10573526Sxy150489 				tx_ring->tbd_oldest =
10583526Sxy150489 				    tx_ring->tbd_first;
10593526Sxy150489 			else
10603526Sxy150489 				tx_ring->tbd_oldest =
10613526Sxy150489 				    descriptor + 1;
10623526Sxy150489 
10633526Sxy150489 			desc_count += packet->num_desc;
10643526Sxy150489 		} else {
10653526Sxy150489 			/*
10664919Sxy150489 			 * Found a sw packet that the e1000g is not done
10673526Sxy150489 			 * with then there is no reason to check the rest
10683526Sxy150489 			 * of the queue.
10693526Sxy150489 			 */
107011066Srafael.vanoni@sun.com 			delta = ddi_get_lbolt64() - packet->tickstamp;
10713526Sxy150489 			break;
10723526Sxy150489 		}
10733526Sxy150489 	}
10743526Sxy150489 
10754919Sxy150489 	tx_ring->tbd_avail += desc_count;
10765882Syy150190 	Adapter->tx_pkt_cnt += desc_count;
10774919Sxy150489 
10783526Sxy150489 	mutex_exit(&tx_ring->usedlist_lock);
10793526Sxy150489 
10803526Sxy150489 	if (desc_count == 0) {
10814919Sxy150489 		E1000G_DEBUG_STAT(tx_ring->stat_recycle_none);
10828850SMin.Xu@Sun.COM 		/*
108310434SGuoqing.Zhu@Sun.COM 		 * If the packet hasn't been sent out for seconds and
108410434SGuoqing.Zhu@Sun.COM 		 * the transmitter is not under paused flowctrl condition,
10858850SMin.Xu@Sun.COM 		 * the transmitter is considered to be stalled.
10868850SMin.Xu@Sun.COM 		 */
108710434SGuoqing.Zhu@Sun.COM 		if ((delta > Adapter->stall_threshold) &&
108810434SGuoqing.Zhu@Sun.COM 		    !(E1000_READ_REG(&Adapter->shared,
108910434SGuoqing.Zhu@Sun.COM 		    E1000_STATUS) & E1000_STATUS_TXOFF)) {
10908850SMin.Xu@Sun.COM 			Adapter->stall_flag = B_TRUE;
10918850SMin.Xu@Sun.COM 		}
10923526Sxy150489 		return (0);
10933526Sxy150489 	}
10943526Sxy150489 
10958850SMin.Xu@Sun.COM 	Adapter->stall_flag = B_FALSE;
10963526Sxy150489 
10973526Sxy150489 	mp = NULL;
10983526Sxy150489 	nmp = NULL;
10994919Sxy150489 	packet = (p_tx_sw_packet_t)QUEUE_GET_HEAD(&pending_list);
11003526Sxy150489 	ASSERT(packet != NULL);
11013526Sxy150489 	while (packet != NULL) {
11023526Sxy150489 		if (packet->mp != NULL) {
11033526Sxy150489 			ASSERT(packet->mp->b_next == NULL);
11043526Sxy150489 			/* Assemble the message chain */
11053526Sxy150489 			if (mp == NULL) {
11063526Sxy150489 				mp = packet->mp;
11073526Sxy150489 				nmp = packet->mp;
11083526Sxy150489 			} else {
11093526Sxy150489 				nmp->b_next = packet->mp;
11103526Sxy150489 				nmp = packet->mp;
11113526Sxy150489 			}
11123526Sxy150489 			/* Disconnect the message from the sw packet */
11133526Sxy150489 			packet->mp = NULL;
11143526Sxy150489 		}
11153526Sxy150489 
11163526Sxy150489 		/* Free the TxSwPackets */
11174919Sxy150489 		e1000g_free_tx_swpkt(packet);
11183526Sxy150489 
11194919Sxy150489 		packet = (p_tx_sw_packet_t)
11203526Sxy150489 		    QUEUE_GET_NEXT(&pending_list, &packet->Link);
11213526Sxy150489 	}
11223526Sxy150489 
11233526Sxy150489 	/* Return the TxSwPackets back to the FreeList */
11243526Sxy150489 	mutex_enter(&tx_ring->freelist_lock);
11253526Sxy150489 	QUEUE_APPEND(&tx_ring->free_list, &pending_list);
11263526Sxy150489 	mutex_exit(&tx_ring->freelist_lock);
11273526Sxy150489 
11285882Syy150190 	if (mp != NULL)
11295882Syy150190 		freemsgchain(mp);
11305882Syy150190 
11313526Sxy150489 	return (desc_count);
11323526Sxy150489 }
11333526Sxy150489 /*
11343526Sxy150489  * 82544 Coexistence issue workaround:
11353526Sxy150489  *    There are 2 issues.
11363526Sxy150489  *    1. If a 32 bit split completion happens from P64H2 and another
11373526Sxy150489  *	agent drives a 64 bit request/split completion after ONLY
11383526Sxy150489  *	1 idle clock (BRCM/Emulex/Adaptec fiber channel cards) then
11393526Sxy150489  *	82544 has a problem where in to clock all the data in, it
11403526Sxy150489  *	looks at REQ64# signal and since it has changed so fast (i.e. 1
11413526Sxy150489  *	idle clock turn around), it will fail to clock all the data in.
11423526Sxy150489  *	Data coming from certain ending addresses has exposure to this issue.
11433526Sxy150489  *
11443526Sxy150489  * To detect this issue, following equation can be used...
11453526Sxy150489  *	SIZE[3:0] + ADDR[2:0] = SUM[3:0].
11463526Sxy150489  *	If SUM[3:0] is in between 1 to 4, we will have this issue.
11473526Sxy150489  *
11483526Sxy150489  * ROOT CAUSE:
11493526Sxy150489  *	The erratum involves the 82544 PCIX elasticity FIFO implementations as
11503526Sxy150489  *	64-bit FIFO's and flushing of the final partial-bytes corresponding
11513526Sxy150489  *	to the end of a requested read burst. Under a specific burst condition
11523526Sxy150489  *	of ending-data alignment and 32-byte split-completions, the final
11533526Sxy150489  *	byte(s) of split-completion data require an extra clock cycle to flush
11543526Sxy150489  *	into 64-bit FIFO orientation.  An incorrect logic dependency on the
11553526Sxy150489  *	REQ64# signal occurring during during this clock cycle may cause the
11563526Sxy150489  *	residual byte(s) to be lost, thereby rendering the internal DMA client
11573526Sxy150489  *	forever awaiting the final byte(s) for an outbound data-fetch.  The
11583526Sxy150489  *	erratum is confirmed to *only* occur if certain subsequent external
11593526Sxy150489  *	64-bit PCIX bus transactions occur immediately (minimum possible bus
11603526Sxy150489  *	turn- around) following the odd-aligned 32-bit split-completion
11613526Sxy150489  *	containing the final byte(s).  Intel has confirmed that this has been
11623526Sxy150489  *	seen only with chipset/bridges which have the capability to provide
11633526Sxy150489  *	32-bit split-completion data, and in the presence of newer PCIX bus
11643526Sxy150489  *	agents which fully-optimize the inter-transaction turn-around (zero
11653526Sxy150489  *	additional initiator latency when pre-granted bus ownership).
11663526Sxy150489  *
11673526Sxy150489  *   	This issue does not exist in PCI bus mode, when any agent is operating
11683526Sxy150489  *	in 32 bit only mode or on chipsets that do not do 32 bit split
11693526Sxy150489  *	completions for 64 bit read requests (Serverworks chipsets). P64H2 does
11703526Sxy150489  *	32 bit split completions for any read request that has bit 2 set to 1
11713526Sxy150489  *	for the requested address and read request size is more than 8 bytes.
11723526Sxy150489  *
11733526Sxy150489  *   2. Another issue is related to 82544 driving DACs under the similar
11743526Sxy150489  *	scenario (32 bit split completion followed by 64 bit transaction with
11753526Sxy150489  *	only 1 cycle turnaround). This issue is still being root caused. We
11763526Sxy150489  *	think that both of these issues can be avoided if following workaround
11773526Sxy150489  *	is implemented. It seems DAC issues is related to ending addresses being
11783526Sxy150489  *	0x9, 0xA, 0xB, 0xC and hence ending up at odd boundaries in elasticity
11793526Sxy150489  *	FIFO which does not get flushed due to REQ64# dependency. We will only
11803526Sxy150489  *	know the full story after it has been simulated successfully by HW team.
11813526Sxy150489  *
11823526Sxy150489  * WORKAROUND:
11833526Sxy150489  *	Make sure we do not have ending address as 1,2,3,4(Hang) or 9,a,b,c(DAC)
11843526Sxy150489  */
11853526Sxy150489 static uint32_t
e1000g_fill_82544_desc(uint64_t address,size_t length,p_desc_array_t desc_array)11864919Sxy150489 e1000g_fill_82544_desc(uint64_t address,
11874919Sxy150489     size_t length, p_desc_array_t desc_array)
11883526Sxy150489 {
11893526Sxy150489 	/*
11903526Sxy150489 	 * Since issue is sensitive to length and address.
11913526Sxy150489 	 * Let us first check the address...
11923526Sxy150489 	 */
11933526Sxy150489 	uint32_t safe_terminator;
11943526Sxy150489 
11954919Sxy150489 	if (length <= 4) {
11964919Sxy150489 		desc_array->descriptor[0].address = address;
11977426SChenliang.Xu@Sun.COM 		desc_array->descriptor[0].length = (uint32_t)length;
11984919Sxy150489 		desc_array->elements = 1;
11994919Sxy150489 		return (desc_array->elements);
12003526Sxy150489 	}
12013526Sxy150489 	safe_terminator =
12024919Sxy150489 	    (uint32_t)((((uint32_t)address & 0x7) +
12034919Sxy150489 	    (length & 0xF)) & 0xF);
12043526Sxy150489 	/*
12053526Sxy150489 	 * if it does not fall between 0x1 to 0x4 and 0x9 to 0xC then
12063526Sxy150489 	 * return
12073526Sxy150489 	 */
12083526Sxy150489 	if (safe_terminator == 0 ||
12094919Sxy150489 	    (safe_terminator > 4 && safe_terminator < 9) ||
12103526Sxy150489 	    (safe_terminator > 0xC && safe_terminator <= 0xF)) {
12114919Sxy150489 		desc_array->descriptor[0].address = address;
12127426SChenliang.Xu@Sun.COM 		desc_array->descriptor[0].length = (uint32_t)length;
12134919Sxy150489 		desc_array->elements = 1;
12144919Sxy150489 		return (desc_array->elements);
12153526Sxy150489 	}
12163526Sxy150489 
12174919Sxy150489 	desc_array->descriptor[0].address = address;
12184919Sxy150489 	desc_array->descriptor[0].length = length - 4;
12194919Sxy150489 	desc_array->descriptor[1].address = address + (length - 4);
12204919Sxy150489 	desc_array->descriptor[1].length = 4;
12214919Sxy150489 	desc_array->elements = 2;
12224919Sxy150489 	return (desc_array->elements);
12233526Sxy150489 }
12243526Sxy150489 
12253526Sxy150489 static int
e1000g_tx_copy(e1000g_tx_ring_t * tx_ring,p_tx_sw_packet_t packet,mblk_t * mp,boolean_t tx_undersize_flag)12264919Sxy150489 e1000g_tx_copy(e1000g_tx_ring_t *tx_ring, p_tx_sw_packet_t packet,
12276986Smx205022     mblk_t *mp, boolean_t tx_undersize_flag)
12283526Sxy150489 {
12293526Sxy150489 	size_t len;
12303526Sxy150489 	size_t len1;
12313526Sxy150489 	dma_buffer_t *tx_buf;
12323526Sxy150489 	mblk_t *nmp;
12333526Sxy150489 	boolean_t finished;
12343526Sxy150489 	int desc_count;
12353526Sxy150489 
12363526Sxy150489 	desc_count = 0;
12373526Sxy150489 	tx_buf = packet->tx_buf;
12383526Sxy150489 	len = MBLKL(mp);
12393526Sxy150489 
12403526Sxy150489 	ASSERT((tx_buf->len + len) <= tx_buf->size);
12413526Sxy150489 
12423526Sxy150489 	if (len > 0) {
12433526Sxy150489 		bcopy(mp->b_rptr,
12443526Sxy150489 		    tx_buf->address + tx_buf->len,
12453526Sxy150489 		    len);
12463526Sxy150489 		tx_buf->len += len;
12473526Sxy150489 
12483526Sxy150489 		packet->num_mblk_frag++;
12493526Sxy150489 	}
12503526Sxy150489 
12513526Sxy150489 	nmp = mp->b_cont;
12523526Sxy150489 	if (nmp == NULL) {
12533526Sxy150489 		finished = B_TRUE;
12543526Sxy150489 	} else {
12553526Sxy150489 		len1 = MBLKL(nmp);
12563526Sxy150489 		if ((tx_buf->len + len1) > tx_buf->size)
12573526Sxy150489 			finished = B_TRUE;
12586986Smx205022 		else if (tx_undersize_flag)
12593526Sxy150489 			finished = B_FALSE;
12604919Sxy150489 		else if (len1 > tx_ring->adapter->tx_bcopy_thresh)
12613526Sxy150489 			finished = B_TRUE;
12623526Sxy150489 		else
12633526Sxy150489 			finished = B_FALSE;
12643526Sxy150489 	}
12653526Sxy150489 
12663526Sxy150489 	if (finished) {
12674919Sxy150489 		E1000G_DEBUG_STAT_COND(tx_ring->stat_multi_copy,
12684919Sxy150489 		    (tx_buf->len > len));
12693526Sxy150489 
12703526Sxy150489 		/*
12713526Sxy150489 		 * If the packet is smaller than 64 bytes, which is the
12723526Sxy150489 		 * minimum ethernet packet size, pad the packet to make
12733526Sxy150489 		 * it at least 60 bytes. The hardware will add 4 bytes
12743526Sxy150489 		 * for CRC.
12753526Sxy150489 		 */
12766986Smx205022 		if (tx_undersize_flag) {
12776394Scc210113 			ASSERT(tx_buf->len < ETHERMIN);
12783526Sxy150489 
12793526Sxy150489 			bzero(tx_buf->address + tx_buf->len,
12806394Scc210113 			    ETHERMIN - tx_buf->len);
12816394Scc210113 			tx_buf->len = ETHERMIN;
12823526Sxy150489 		}
12833526Sxy150489 
12843526Sxy150489 #ifdef __sparc
12854919Sxy150489 		if (packet->dma_type == USE_DVMA)
12863526Sxy150489 			dvma_sync(tx_buf->dma_handle, 0, DDI_DMA_SYNC_FORDEV);
12874919Sxy150489 		else
12883526Sxy150489 			(void) ddi_dma_sync(tx_buf->dma_handle, 0,
12893526Sxy150489 			    tx_buf->len, DDI_DMA_SYNC_FORDEV);
12904919Sxy150489 #else
12914919Sxy150489 		(void) ddi_dma_sync(tx_buf->dma_handle, 0,
12924919Sxy150489 		    tx_buf->len, DDI_DMA_SYNC_FORDEV);
12934919Sxy150489 #endif
12943526Sxy150489 
12953526Sxy150489 		packet->data_transfer_type = USE_BCOPY;
12963526Sxy150489 
12974919Sxy150489 		desc_count = e1000g_fill_tx_desc(tx_ring,
12983526Sxy150489 		    packet,
12993526Sxy150489 		    tx_buf->dma_address,
13003526Sxy150489 		    tx_buf->len);
13013526Sxy150489 
13023526Sxy150489 		if (desc_count <= 0)
13033526Sxy150489 			return (-1);
13043526Sxy150489 	}
13053526Sxy150489 
13063526Sxy150489 	return (desc_count);
13073526Sxy150489 }
13083526Sxy150489 
13093526Sxy150489 static int
e1000g_tx_bind(e1000g_tx_ring_t * tx_ring,p_tx_sw_packet_t packet,mblk_t * mp)13104919Sxy150489 e1000g_tx_bind(e1000g_tx_ring_t *tx_ring, p_tx_sw_packet_t packet, mblk_t *mp)
13113526Sxy150489 {
13123526Sxy150489 	int j;
13133526Sxy150489 	int mystat;
13143526Sxy150489 	size_t len;
13153526Sxy150489 	ddi_dma_cookie_t dma_cookie;
13163526Sxy150489 	uint_t ncookies;
13173526Sxy150489 	int desc_count;
13183526Sxy150489 	uint32_t desc_total;
13193526Sxy150489 
13203526Sxy150489 	desc_total = 0;
13213526Sxy150489 	len = MBLKL(mp);
13223526Sxy150489 
13233526Sxy150489 	/*
13243526Sxy150489 	 * ddi_dma_addr_bind_handle() allocates  DMA  resources  for  a
13253526Sxy150489 	 * memory  object such that a device can perform DMA to or from
13263526Sxy150489 	 * the object.  DMA resources  are  allocated  considering  the
13273526Sxy150489 	 * device's  DMA  attributes  as  expressed by ddi_dma_attr(9S)
13283526Sxy150489 	 * (see ddi_dma_alloc_handle(9F)).
13293526Sxy150489 	 *
13303526Sxy150489 	 * ddi_dma_addr_bind_handle() fills in  the  first  DMA  cookie
13313526Sxy150489 	 * pointed  to by cookiep with the appropriate address, length,
13323526Sxy150489 	 * and bus type. *ccountp is set to the number of DMA  cookies
13333526Sxy150489 	 * representing this DMA object. Subsequent DMA cookies must be
13343526Sxy150489 	 * retrieved by calling ddi_dma_nextcookie(9F)  the  number  of
13353526Sxy150489 	 * times specified by *countp - 1.
13363526Sxy150489 	 */
13373526Sxy150489 	switch (packet->dma_type) {
13383526Sxy150489 #ifdef __sparc
13393526Sxy150489 	case USE_DVMA:
13403526Sxy150489 		dvma_kaddr_load(packet->tx_dma_handle,
13413526Sxy150489 		    (caddr_t)mp->b_rptr, len, 0, &dma_cookie);
13423526Sxy150489 
13433526Sxy150489 		dvma_sync(packet->tx_dma_handle, 0,
13443526Sxy150489 		    DDI_DMA_SYNC_FORDEV);
13453526Sxy150489 
13463526Sxy150489 		ncookies = 1;
13473526Sxy150489 		packet->data_transfer_type = USE_DVMA;
13483526Sxy150489 		break;
13493526Sxy150489 #endif
13503526Sxy150489 	case USE_DMA:
13513526Sxy150489 		if ((mystat = ddi_dma_addr_bind_handle(
13524608Syy150190 		    packet->tx_dma_handle, NULL,
13534608Syy150190 		    (caddr_t)mp->b_rptr, len,
13544608Syy150190 		    DDI_DMA_WRITE | DDI_DMA_STREAMING,
13554608Syy150190 		    DDI_DMA_DONTWAIT, 0, &dma_cookie,
13564608Syy150190 		    &ncookies)) != DDI_DMA_MAPPED) {
13573526Sxy150489 
13584919Sxy150489 			e1000g_log(tx_ring->adapter, CE_WARN,
13593526Sxy150489 			    "Couldn't bind mblk buffer to Tx DMA handle: "
13603526Sxy150489 			    "return: %X, Pkt: %X\n",
13613526Sxy150489 			    mystat, packet);
13623526Sxy150489 			return (-1);
13633526Sxy150489 		}
13643526Sxy150489 
13653526Sxy150489 		/*
13663526Sxy150489 		 * An implicit ddi_dma_sync() is done when the
13673526Sxy150489 		 * ddi_dma_addr_bind_handle() is called. So we
13683526Sxy150489 		 * don't need to explicitly call ddi_dma_sync()
13693526Sxy150489 		 * here any more.
13703526Sxy150489 		 */
13713526Sxy150489 		ASSERT(ncookies);
13724919Sxy150489 		E1000G_DEBUG_STAT_COND(tx_ring->stat_multi_cookie,
13734919Sxy150489 		    (ncookies > 1));
13743526Sxy150489 
13753526Sxy150489 		/*
13763526Sxy150489 		 * The data_transfer_type value must be set after the handle
13774919Sxy150489 		 * has been bound, for it will be used in e1000g_free_tx_swpkt()
13783526Sxy150489 		 * to decide whether we need to unbind the handle.
13793526Sxy150489 		 */
13803526Sxy150489 		packet->data_transfer_type = USE_DMA;
13813526Sxy150489 		break;
13823526Sxy150489 	default:
13833526Sxy150489 		ASSERT(B_FALSE);
13843526Sxy150489 		break;
13853526Sxy150489 	}
13863526Sxy150489 
13873526Sxy150489 	packet->num_mblk_frag++;
13883526Sxy150489 
13893526Sxy150489 	/*
13903526Sxy150489 	 * Each address could span thru multpile cookie..
13913526Sxy150489 	 * Each cookie will have one descriptor
13923526Sxy150489 	 */
13933526Sxy150489 	for (j = ncookies; j != 0; j--) {
13943526Sxy150489 
13954919Sxy150489 		desc_count = e1000g_fill_tx_desc(tx_ring,
13963526Sxy150489 		    packet,
13973526Sxy150489 		    dma_cookie.dmac_laddress,
13983526Sxy150489 		    dma_cookie.dmac_size);
13993526Sxy150489 
14003526Sxy150489 		if (desc_count <= 0)
14013526Sxy150489 			return (-1);
14023526Sxy150489 
14033526Sxy150489 		desc_total += desc_count;
14043526Sxy150489 
14053526Sxy150489 		/*
14063526Sxy150489 		 * ddi_dma_nextcookie() retrieves subsequent DMA
14073526Sxy150489 		 * cookies for a DMA object.
14083526Sxy150489 		 * ddi_dma_nextcookie() fills in the
14093526Sxy150489 		 * ddi_dma_cookie(9S) structure pointed to by
14103526Sxy150489 		 * cookiep.  The ddi_dma_cookie(9S) structure
14113526Sxy150489 		 * must be allocated prior to calling
14123526Sxy150489 		 * ddi_dma_nextcookie(). The DMA cookie count
14133526Sxy150489 		 * returned by ddi_dma_buf_bind_handle(9F),
14143526Sxy150489 		 * ddi_dma_addr_bind_handle(9F), or
14153526Sxy150489 		 * ddi_dma_getwin(9F) indicates the number of DMA
14163526Sxy150489 		 * cookies a DMA object consists of.  If the
14173526Sxy150489 		 * resulting cookie count, N, is larger than 1,
14183526Sxy150489 		 * ddi_dma_nextcookie() must be called N-1 times
14193526Sxy150489 		 * to retrieve all DMA cookies.
14203526Sxy150489 		 */
14213526Sxy150489 		if (j > 1) {
14223526Sxy150489 			ddi_dma_nextcookie(packet->tx_dma_handle,
14233526Sxy150489 			    &dma_cookie);
14243526Sxy150489 		}
14253526Sxy150489 	}
14263526Sxy150489 
14273526Sxy150489 	return (desc_total);
14283526Sxy150489 }
14293526Sxy150489 
14303526Sxy150489 static void
e1000g_fill_context_descriptor(context_data_t * cur_context,struct e1000_context_desc * context_desc)14316986Smx205022 e1000g_fill_context_descriptor(context_data_t *cur_context,
14326986Smx205022     struct e1000_context_desc *context_desc)
14333526Sxy150489 {
14346986Smx205022 	if (cur_context->cksum_flags & HCK_IPV4_HDRCKSUM) {
14356986Smx205022 		context_desc->lower_setup.ip_fields.ipcss =
14366986Smx205022 		    cur_context->ether_header_size;
14376986Smx205022 		context_desc->lower_setup.ip_fields.ipcso =
14386986Smx205022 		    cur_context->ether_header_size +
14393526Sxy150489 		    offsetof(struct ip, ip_sum);
14406986Smx205022 		context_desc->lower_setup.ip_fields.ipcse =
14416986Smx205022 		    cur_context->ether_header_size +
14426986Smx205022 		    cur_context->cksum_start - 1;
14433526Sxy150489 	} else
14446986Smx205022 		context_desc->lower_setup.ip_config = 0;
14453526Sxy150489 
14466986Smx205022 	if (cur_context->cksum_flags & HCK_PARTIALCKSUM) {
14473526Sxy150489 		/*
14483526Sxy150489 		 * The packet with same protocol has the following
14493526Sxy150489 		 * stuff and start offset:
14503526Sxy150489 		 * |  Protocol  | Stuff  | Start  | Checksum
14513526Sxy150489 		 * |		| Offset | Offset | Enable
14523526Sxy150489 		 * | IPv4 + TCP |  0x24  |  0x14  |  Yes
14533526Sxy150489 		 * | IPv4 + UDP |  0x1A  |  0x14  |  Yes
14543526Sxy150489 		 * | IPv6 + TCP |  0x20  |  0x10  |  No
14553526Sxy150489 		 * | IPv6 + UDP |  0x14  |  0x10  |  No
14563526Sxy150489 		 */
14576986Smx205022 		context_desc->upper_setup.tcp_fields.tucss =
14586986Smx205022 		    cur_context->cksum_start + cur_context->ether_header_size;
14596986Smx205022 		context_desc->upper_setup.tcp_fields.tucso =
14606986Smx205022 		    cur_context->cksum_stuff + cur_context->ether_header_size;
14616986Smx205022 		context_desc->upper_setup.tcp_fields.tucse = 0;
14623526Sxy150489 	} else
14636986Smx205022 		context_desc->upper_setup.tcp_config = 0;
14643526Sxy150489 
14656986Smx205022 	if (cur_context->lso_flag) {
14666986Smx205022 		context_desc->tcp_seg_setup.fields.mss = cur_context->mss;
14676986Smx205022 		context_desc->tcp_seg_setup.fields.hdr_len =
14686986Smx205022 		    cur_context->hdr_len;
14696986Smx205022 		/*
14706986Smx205022 		 * workaround for 82546EB errata 23, status-writeback
14716986Smx205022 		 * reporting (RS) should not be set on context or
14726986Smx205022 		 * Null descriptors
14736986Smx205022 		 */
14746986Smx205022 		context_desc->cmd_and_length = E1000_TXD_CMD_DEXT
14756986Smx205022 		    | E1000_TXD_CMD_TSE | E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP
14766986Smx205022 		    | E1000_TXD_DTYP_C | cur_context->pay_len;
14776986Smx205022 	} else {
14786986Smx205022 		context_desc->cmd_and_length = E1000_TXD_CMD_DEXT
14796986Smx205022 		    | E1000_TXD_DTYP_C;
14806986Smx205022 		/*
14816986Smx205022 		 * Zero out the options for TCP Segmentation Offload
14826986Smx205022 		 */
14836986Smx205022 		context_desc->tcp_seg_setup.data = 0;
14846986Smx205022 	}
14853526Sxy150489 }
14863526Sxy150489 
14873526Sxy150489 static int
e1000g_fill_tx_desc(e1000g_tx_ring_t * tx_ring,p_tx_sw_packet_t packet,uint64_t address,size_t size)14884919Sxy150489 e1000g_fill_tx_desc(e1000g_tx_ring_t *tx_ring,
14894919Sxy150489     p_tx_sw_packet_t packet, uint64_t address, size_t size)
14903526Sxy150489 {
14914919Sxy150489 	struct e1000_hw *hw = &tx_ring->adapter->shared;
14924919Sxy150489 	p_sw_desc_t desc;
14933526Sxy150489 
14944919Sxy150489 	if (hw->mac.type == e1000_82544) {
14954919Sxy150489 		if (hw->bus.type == e1000_bus_type_pcix)
14964919Sxy150489 			return (e1000g_tx_workaround_PCIX_82544(packet,
14974919Sxy150489 			    address, size));
14983526Sxy150489 
14994919Sxy150489 		if (size > JUMBO_FRAG_LENGTH)
15004919Sxy150489 			return (e1000g_tx_workaround_jumbo_82544(packet,
15014919Sxy150489 			    address, size));
15023526Sxy150489 	}
15033526Sxy150489 
15044919Sxy150489 	ASSERT(packet->num_desc < MAX_TX_DESC_PER_PACKET);
15054919Sxy150489 
15064919Sxy150489 	desc = &packet->desc[packet->num_desc];
15074919Sxy150489 	desc->address = address;
15087426SChenliang.Xu@Sun.COM 	desc->length = (uint32_t)size;
15094919Sxy150489 
15104919Sxy150489 	packet->num_desc++;
15114919Sxy150489 
15124919Sxy150489 	return (1);
15133526Sxy150489 }
15143526Sxy150489 
15153526Sxy150489 static int
e1000g_tx_workaround_PCIX_82544(p_tx_sw_packet_t packet,uint64_t address,size_t size)15164919Sxy150489 e1000g_tx_workaround_PCIX_82544(p_tx_sw_packet_t packet,
15174919Sxy150489     uint64_t address, size_t size)
15183526Sxy150489 {
15194919Sxy150489 	p_sw_desc_t desc;
15203526Sxy150489 	int desc_count;
15213526Sxy150489 	long size_left;
15223526Sxy150489 	size_t len;
15233526Sxy150489 	uint32_t counter;
15243526Sxy150489 	uint32_t array_elements;
15254919Sxy150489 	desc_array_t desc_array;
15263526Sxy150489 
15273526Sxy150489 	/*
15283526Sxy150489 	 * Coexist Workaround for cordova: RP: 07/04/03
15293526Sxy150489 	 *
15303526Sxy150489 	 * RP: ERRATA: Workaround ISSUE:
15313526Sxy150489 	 * 8kb_buffer_Lockup CONTROLLER: Cordova Breakup
15323526Sxy150489 	 * Eachbuffer in to 8kb pieces until the
15333526Sxy150489 	 * remainder is < 8kb
15343526Sxy150489 	 */
15353526Sxy150489 	size_left = size;
15363526Sxy150489 	desc_count = 0;
15373526Sxy150489 
15383526Sxy150489 	while (size_left > 0) {
15393526Sxy150489 		if (size_left > MAX_TX_BUF_SIZE)
15403526Sxy150489 			len = MAX_TX_BUF_SIZE;
15413526Sxy150489 		else
15423526Sxy150489 			len = size_left;
15433526Sxy150489 
15443526Sxy150489 		array_elements = e1000g_fill_82544_desc(address,
15453526Sxy150489 		    len, &desc_array);
15463526Sxy150489 
15473526Sxy150489 		for (counter = 0; counter < array_elements; counter++) {
15483526Sxy150489 			ASSERT(packet->num_desc < MAX_TX_DESC_PER_PACKET);
15493526Sxy150489 			/*
15503526Sxy150489 			 * Put in the buffer address
15513526Sxy150489 			 */
15523526Sxy150489 			desc = &packet->desc[packet->num_desc];
15533526Sxy150489 
15544919Sxy150489 			desc->address =
15554919Sxy150489 			    desc_array.descriptor[counter].address;
15564919Sxy150489 			desc->length =
15574919Sxy150489 			    desc_array.descriptor[counter].length;
15583526Sxy150489 
15593526Sxy150489 			packet->num_desc++;
15603526Sxy150489 			desc_count++;
15613526Sxy150489 		} /* for */
15623526Sxy150489 
15633526Sxy150489 		/*
15643526Sxy150489 		 * Update the buffer address and length
15653526Sxy150489 		 */
15663526Sxy150489 		address += MAX_TX_BUF_SIZE;
15673526Sxy150489 		size_left -= MAX_TX_BUF_SIZE;
15683526Sxy150489 	} /* while */
15693526Sxy150489 
15703526Sxy150489 	return (desc_count);
15713526Sxy150489 }
15723526Sxy150489 
15733526Sxy150489 static int
e1000g_tx_workaround_jumbo_82544(p_tx_sw_packet_t packet,uint64_t address,size_t size)15744919Sxy150489 e1000g_tx_workaround_jumbo_82544(p_tx_sw_packet_t packet,
15754919Sxy150489     uint64_t address, size_t size)
15763526Sxy150489 {
15774919Sxy150489 	p_sw_desc_t desc;
15783526Sxy150489 	int desc_count;
15793526Sxy150489 	long size_left;
15803526Sxy150489 	uint32_t offset;
15813526Sxy150489 
15823526Sxy150489 	/*
15833526Sxy150489 	 * Workaround for Jumbo Frames on Cordova
15843526Sxy150489 	 * PSD 06/01/2001
15853526Sxy150489 	 */
15863526Sxy150489 	size_left = size;
15873526Sxy150489 	desc_count = 0;
15883526Sxy150489 	offset = 0;
15893526Sxy150489 	while (size_left > 0) {
15903526Sxy150489 		ASSERT(packet->num_desc < MAX_TX_DESC_PER_PACKET);
15913526Sxy150489 
15923526Sxy150489 		desc = &packet->desc[packet->num_desc];
15933526Sxy150489 
15944919Sxy150489 		desc->address = address + offset;
15953526Sxy150489 
15963526Sxy150489 		if (size_left > JUMBO_FRAG_LENGTH)
15974919Sxy150489 			desc->length = JUMBO_FRAG_LENGTH;
15983526Sxy150489 		else
15997426SChenliang.Xu@Sun.COM 			desc->length = (uint32_t)size_left;
16003526Sxy150489 
16013526Sxy150489 		packet->num_desc++;
16023526Sxy150489 		desc_count++;
16033526Sxy150489 
16044919Sxy150489 		offset += desc->length;
16053526Sxy150489 		size_left -= JUMBO_FRAG_LENGTH;
16063526Sxy150489 	}
16073526Sxy150489 
16083526Sxy150489 	return (desc_count);
16093526Sxy150489 }
16103526Sxy150489 
16114919Sxy150489 #pragma inline(e1000g_82547_tx_move_tail_work)
16124919Sxy150489 
16133526Sxy150489 static void
e1000g_82547_tx_move_tail_work(e1000g_tx_ring_t * tx_ring)16143526Sxy150489 e1000g_82547_tx_move_tail_work(e1000g_tx_ring_t *tx_ring)
16153526Sxy150489 {
16164919Sxy150489 	struct e1000_hw *hw;
16173526Sxy150489 	uint16_t hw_tdt;
16183526Sxy150489 	uint16_t sw_tdt;
16193526Sxy150489 	struct e1000_tx_desc *tx_desc;
16203526Sxy150489 	uint16_t length = 0;
16213526Sxy150489 	boolean_t eop = B_FALSE;
16223526Sxy150489 	struct e1000g *Adapter;
16233526Sxy150489 
16243526Sxy150489 	Adapter = tx_ring->adapter;
16254919Sxy150489 	hw = &Adapter->shared;
16263526Sxy150489 
16276735Scc210113 	hw_tdt = E1000_READ_REG(hw, E1000_TDT(0));
16283526Sxy150489 	sw_tdt = tx_ring->tbd_next - tx_ring->tbd_first;
16293526Sxy150489 
16303526Sxy150489 	while (hw_tdt != sw_tdt) {
16313526Sxy150489 		tx_desc = &(tx_ring->tbd_first[hw_tdt]);
16323526Sxy150489 		length += tx_desc->lower.flags.length;
16333526Sxy150489 		eop = tx_desc->lower.data & E1000_TXD_CMD_EOP;
16344919Sxy150489 		if (++hw_tdt == Adapter->tx_desc_num)
16353526Sxy150489 			hw_tdt = 0;
16363526Sxy150489 
16373526Sxy150489 		if (eop) {
16383526Sxy150489 			if ((Adapter->link_duplex == HALF_DUPLEX) &&
16394919Sxy150489 			    (e1000_fifo_workaround_82547(hw, length)
16404919Sxy150489 			    != E1000_SUCCESS)) {
16413526Sxy150489 				if (tx_ring->timer_enable_82547) {
16423526Sxy150489 					ASSERT(tx_ring->timer_id_82547 == 0);
16433526Sxy150489 					tx_ring->timer_id_82547 =
16443526Sxy150489 					    timeout(e1000g_82547_timeout,
16454608Syy150190 					    (void *)tx_ring,
16464608Syy150190 					    drv_usectohz(10000));
16473526Sxy150489 				}
16483526Sxy150489 				return;
16493526Sxy150489 
16503526Sxy150489 			} else {
16516735Scc210113 				E1000_WRITE_REG(hw, E1000_TDT(0), hw_tdt);
16524919Sxy150489 				e1000_update_tx_fifo_head_82547(hw, length);
16533526Sxy150489 				length = 0;
16543526Sxy150489 			}
16553526Sxy150489 		}
16563526Sxy150489 	}
16573526Sxy150489 }
16583526Sxy150489 
16593526Sxy150489 static void
e1000g_82547_timeout(void * arg)16603526Sxy150489 e1000g_82547_timeout(void *arg)
16613526Sxy150489 {
16623526Sxy150489 	e1000g_tx_ring_t *tx_ring;
16633526Sxy150489 
16643526Sxy150489 	tx_ring = (e1000g_tx_ring_t *)arg;
16653526Sxy150489 
16663526Sxy150489 	mutex_enter(&tx_ring->tx_lock);
16673526Sxy150489 
16683526Sxy150489 	tx_ring->timer_id_82547 = 0;
16693526Sxy150489 	e1000g_82547_tx_move_tail_work(tx_ring);
16703526Sxy150489 
16713526Sxy150489 	mutex_exit(&tx_ring->tx_lock);
16723526Sxy150489 }
16733526Sxy150489 
16743526Sxy150489 static void
e1000g_82547_tx_move_tail(e1000g_tx_ring_t * tx_ring)16753526Sxy150489 e1000g_82547_tx_move_tail(e1000g_tx_ring_t *tx_ring)
16763526Sxy150489 {
16773526Sxy150489 	timeout_id_t tid;
16783526Sxy150489 
16793526Sxy150489 	ASSERT(MUTEX_HELD(&tx_ring->tx_lock));
16803526Sxy150489 
16813526Sxy150489 	tid = tx_ring->timer_id_82547;
16823526Sxy150489 	tx_ring->timer_id_82547 = 0;
16833526Sxy150489 	if (tid != 0) {
16843526Sxy150489 		tx_ring->timer_enable_82547 = B_FALSE;
16853526Sxy150489 		mutex_exit(&tx_ring->tx_lock);
16863526Sxy150489 
16873526Sxy150489 		(void) untimeout(tid);
16883526Sxy150489 
16893526Sxy150489 		mutex_enter(&tx_ring->tx_lock);
16903526Sxy150489 	}
16913526Sxy150489 	tx_ring->timer_enable_82547 = B_TRUE;
16923526Sxy150489 	e1000g_82547_tx_move_tail_work(tx_ring);
16933526Sxy150489 }
1694