108057504Sxy150489 /* 208057504Sxy150489 * This file is provided under a CDDLv1 license. When using or 308057504Sxy150489 * redistributing this file, you may do so under this license. 408057504Sxy150489 * In redistributing this file this license must be included 508057504Sxy150489 * and no other modification of this header file is permitted. 608057504Sxy150489 * 708057504Sxy150489 * CDDL LICENSE SUMMARY 808057504Sxy150489 * 9d5c3073dSchenlu chen - Sun Microsystems - Beijing China * Copyright(c) 1999 - 2009 Intel Corporation. All rights reserved. 1008057504Sxy150489 * 1108057504Sxy150489 * The contents of this file are subject to the terms of Version 1208057504Sxy150489 * 1.0 of the Common Development and Distribution License (the "License"). 1308057504Sxy150489 * 1408057504Sxy150489 * You should have received a copy of the License with this software. 1508057504Sxy150489 * You can obtain a copy of the License at 1608057504Sxy150489 * http://www.opensolaris.org/os/licensing. 1708057504Sxy150489 * See the License for the specific language governing permissions 1808057504Sxy150489 * and limitations under the License. 1908057504Sxy150489 */ 2008057504Sxy150489 2108057504Sxy150489 /* 220dc2366fSVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23da14cebeSEric Cheng * Use is subject to license terms. 2408057504Sxy150489 */ 2508057504Sxy150489 2608057504Sxy150489 /* 27*42cc51e0SRobert Mustacchi * Copyright 2016 Joyent, Inc. 285c68564dSBryan Cantrill */ 295c68564dSBryan Cantrill 305c68564dSBryan Cantrill /* 3108057504Sxy150489 * ********************************************************************** 3208057504Sxy150489 * * 3308057504Sxy150489 * Module Name: * 3408057504Sxy150489 * e1000g_tx.c * 3508057504Sxy150489 * * 3608057504Sxy150489 * Abstract: * 3725f2d433Sxy150489 * This file contains some routines that take care of Transmit, * 3825f2d433Sxy150489 * make the hardware to send the data pointed by the packet out * 3925f2d433Sxy150489 * on to the physical medium. * 4008057504Sxy150489 * * 4108057504Sxy150489 * ********************************************************************** 4208057504Sxy150489 */ 4308057504Sxy150489 4408057504Sxy150489 #include "e1000g_sw.h" 4508057504Sxy150489 #include "e1000g_debug.h" 4608057504Sxy150489 4708057504Sxy150489 static boolean_t e1000g_send(struct e1000g *, mblk_t *); 4825f2d433Sxy150489 static int e1000g_tx_copy(e1000g_tx_ring_t *, 49c7770590Smx205022 p_tx_sw_packet_t, mblk_t *, boolean_t); 5025f2d433Sxy150489 static int e1000g_tx_bind(e1000g_tx_ring_t *, 5125f2d433Sxy150489 p_tx_sw_packet_t, mblk_t *); 524d737963Sxiangtao you - Sun Microsystems - Beijing China static boolean_t e1000g_retrieve_context(mblk_t *, context_data_t *, size_t); 53c7770590Smx205022 static boolean_t e1000g_check_context(e1000g_tx_ring_t *, context_data_t *); 5408057504Sxy150489 static int e1000g_fill_tx_ring(e1000g_tx_ring_t *, LIST_DESCRIBER *, 55c7770590Smx205022 context_data_t *); 56c7770590Smx205022 static void e1000g_fill_context_descriptor(context_data_t *, 5708057504Sxy150489 struct e1000_context_desc *); 5825f2d433Sxy150489 static int e1000g_fill_tx_desc(e1000g_tx_ring_t *, 5925f2d433Sxy150489 p_tx_sw_packet_t, uint64_t, size_t); 6008057504Sxy150489 static uint32_t e1000g_fill_82544_desc(uint64_t Address, size_t Length, 6125f2d433Sxy150489 p_desc_array_t desc_array); 6225f2d433Sxy150489 static int e1000g_tx_workaround_PCIX_82544(p_tx_sw_packet_t, uint64_t, size_t); 6325f2d433Sxy150489 static int e1000g_tx_workaround_jumbo_82544(p_tx_sw_packet_t, uint64_t, size_t); 6408057504Sxy150489 static void e1000g_82547_timeout(void *); 6508057504Sxy150489 static void e1000g_82547_tx_move_tail(e1000g_tx_ring_t *); 6608057504Sxy150489 static void e1000g_82547_tx_move_tail_work(e1000g_tx_ring_t *); 6708057504Sxy150489 6825f2d433Sxy150489 #ifndef E1000G_DEBUG 6908057504Sxy150489 #pragma inline(e1000g_tx_copy) 7008057504Sxy150489 #pragma inline(e1000g_tx_bind) 714d737963Sxiangtao you - Sun Microsystems - Beijing China #pragma inline(e1000g_retrieve_context) 72c7770590Smx205022 #pragma inline(e1000g_check_context) 7308057504Sxy150489 #pragma inline(e1000g_fill_tx_ring) 7408057504Sxy150489 #pragma inline(e1000g_fill_context_descriptor) 7508057504Sxy150489 #pragma inline(e1000g_fill_tx_desc) 7608057504Sxy150489 #pragma inline(e1000g_fill_82544_desc) 7708057504Sxy150489 #pragma inline(e1000g_tx_workaround_PCIX_82544) 7808057504Sxy150489 #pragma inline(e1000g_tx_workaround_jumbo_82544) 7925f2d433Sxy150489 #pragma inline(e1000g_free_tx_swpkt) 8008057504Sxy150489 #endif 8108057504Sxy150489 8208057504Sxy150489 /* 8325f2d433Sxy150489 * e1000g_free_tx_swpkt - free up the tx sw packet 8425f2d433Sxy150489 * 8525f2d433Sxy150489 * Unbind the previously bound DMA handle for a given 8625f2d433Sxy150489 * transmit sw packet. And reset the sw packet data. 8708057504Sxy150489 */ 8808057504Sxy150489 void 8925f2d433Sxy150489 e1000g_free_tx_swpkt(register p_tx_sw_packet_t packet) 9008057504Sxy150489 { 9108057504Sxy150489 switch (packet->data_transfer_type) { 9208057504Sxy150489 case USE_BCOPY: 9308057504Sxy150489 packet->tx_buf->len = 0; 9408057504Sxy150489 break; 9508057504Sxy150489 #ifdef __sparc 9608057504Sxy150489 case USE_DVMA: 9708057504Sxy150489 dvma_unload(packet->tx_dma_handle, 0, -1); 9808057504Sxy150489 break; 9908057504Sxy150489 #endif 10008057504Sxy150489 case USE_DMA: 101fe62dec3SChen-Liang Xu (void) ddi_dma_unbind_handle(packet->tx_dma_handle); 10208057504Sxy150489 break; 10308057504Sxy150489 default: 10408057504Sxy150489 break; 10508057504Sxy150489 } 10608057504Sxy150489 10708057504Sxy150489 /* 10808057504Sxy150489 * The mblk has been stripped off the sw packet 10908057504Sxy150489 * and will be freed in a triggered soft intr. 11008057504Sxy150489 */ 11108057504Sxy150489 ASSERT(packet->mp == NULL); 11208057504Sxy150489 11308057504Sxy150489 packet->data_transfer_type = USE_NONE; 11408057504Sxy150489 packet->num_mblk_frag = 0; 11508057504Sxy150489 packet->num_desc = 0; 11608057504Sxy150489 } 11708057504Sxy150489 11808057504Sxy150489 mblk_t * 11908057504Sxy150489 e1000g_m_tx(void *arg, mblk_t *mp) 12008057504Sxy150489 { 12108057504Sxy150489 struct e1000g *Adapter = (struct e1000g *)arg; 12208057504Sxy150489 mblk_t *next; 12308057504Sxy150489 12408057504Sxy150489 rw_enter(&Adapter->chip_lock, RW_READER); 12508057504Sxy150489 126d5c3073dSchenlu chen - Sun Microsystems - Beijing China if ((Adapter->e1000g_state & E1000G_SUSPENDED) || 127d5c3073dSchenlu chen - Sun Microsystems - Beijing China !(Adapter->e1000g_state & E1000G_STARTED) || 1289b6541b3Sgl147354 (Adapter->link_state != LINK_STATE_UP)) { 12908057504Sxy150489 freemsgchain(mp); 13008057504Sxy150489 mp = NULL; 13108057504Sxy150489 } 13208057504Sxy150489 13308057504Sxy150489 while (mp != NULL) { 13408057504Sxy150489 next = mp->b_next; 13508057504Sxy150489 mp->b_next = NULL; 13608057504Sxy150489 13708057504Sxy150489 if (!e1000g_send(Adapter, mp)) { 13808057504Sxy150489 mp->b_next = next; 13908057504Sxy150489 break; 14008057504Sxy150489 } 14108057504Sxy150489 14208057504Sxy150489 mp = next; 14308057504Sxy150489 } 14408057504Sxy150489 14508057504Sxy150489 rw_exit(&Adapter->chip_lock); 14608057504Sxy150489 return (mp); 14708057504Sxy150489 } 14808057504Sxy150489 14908057504Sxy150489 /* 15025f2d433Sxy150489 * e1000g_send - send packets onto the wire 15125f2d433Sxy150489 * 15225f2d433Sxy150489 * Called from e1000g_m_tx with an mblk ready to send. this 15325f2d433Sxy150489 * routine sets up the transmit descriptors and sends data to 15425f2d433Sxy150489 * the wire. It also pushes the just transmitted packet to 15525f2d433Sxy150489 * the used tx sw packet list. 15608057504Sxy150489 */ 15708057504Sxy150489 static boolean_t 15808057504Sxy150489 e1000g_send(struct e1000g *Adapter, mblk_t *mp) 15908057504Sxy150489 { 16025f2d433Sxy150489 p_tx_sw_packet_t packet; 16108057504Sxy150489 LIST_DESCRIBER pending_list; 16208057504Sxy150489 size_t len; 16308057504Sxy150489 size_t msg_size; 16408057504Sxy150489 uint32_t frag_count; 16508057504Sxy150489 int desc_count; 16608057504Sxy150489 uint32_t desc_total; 16743a17687SMiles Xu, Sun Microsystems uint32_t bcopy_thresh; 16843a17687SMiles Xu, Sun Microsystems uint32_t hdr_frag_len; 169c7770590Smx205022 boolean_t tx_undersize_flag; 17008057504Sxy150489 mblk_t *nmp; 17108057504Sxy150489 mblk_t *tmp; 17243a17687SMiles Xu, Sun Microsystems mblk_t *new_mp; 17343a17687SMiles Xu, Sun Microsystems mblk_t *pre_mp; 1741b5c080fSchangqing li - Sun Microsystems - Beijing China mblk_t *next_mp; 17508057504Sxy150489 e1000g_tx_ring_t *tx_ring; 176c7770590Smx205022 context_data_t cur_context; 17708057504Sxy150489 17825f2d433Sxy150489 tx_ring = Adapter->tx_ring; 17943a17687SMiles Xu, Sun Microsystems bcopy_thresh = Adapter->tx_bcopy_thresh; 18025f2d433Sxy150489 18108057504Sxy150489 /* Get the total size and frags number of the message */ 182c7770590Smx205022 tx_undersize_flag = B_FALSE; 18308057504Sxy150489 frag_count = 0; 18408057504Sxy150489 msg_size = 0; 18508057504Sxy150489 for (nmp = mp; nmp; nmp = nmp->b_cont) { 18608057504Sxy150489 frag_count++; 18708057504Sxy150489 msg_size += MBLKL(nmp); 18808057504Sxy150489 } 18908057504Sxy150489 1904d737963Sxiangtao you - Sun Microsystems - Beijing China /* retrieve and compute information for context descriptor */ 1914d737963Sxiangtao you - Sun Microsystems - Beijing China if (!e1000g_retrieve_context(mp, &cur_context, msg_size)) { 192c7770590Smx205022 freemsg(mp); 193c7770590Smx205022 return (B_TRUE); 194c7770590Smx205022 } 195c7770590Smx205022 196c7770590Smx205022 /* 197c7770590Smx205022 * Make sure the packet is less than the allowed size 198c7770590Smx205022 */ 199c7770590Smx205022 if (!cur_context.lso_flag && 200c7770590Smx205022 (msg_size > Adapter->max_frame_size - ETHERFCSL)) { 20108057504Sxy150489 /* 20208057504Sxy150489 * For the over size packet, we'll just drop it. 20308057504Sxy150489 * So we return B_TRUE here. 20408057504Sxy150489 */ 20525f2d433Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 20608057504Sxy150489 "Tx packet out of bound. length = %d \n", msg_size); 20725f2d433Sxy150489 E1000G_STAT(tx_ring->stat_over_size); 20808057504Sxy150489 freemsg(mp); 20908057504Sxy150489 return (B_TRUE); 21008057504Sxy150489 } 21108057504Sxy150489 21208057504Sxy150489 /* 21308057504Sxy150489 * Check and reclaim tx descriptors. 21408057504Sxy150489 * This low water mark check should be done all the time as 21508057504Sxy150489 * Transmit interrupt delay can produce Transmit interrupts little 21608057504Sxy150489 * late and that may cause few problems related to reaping Tx 21708057504Sxy150489 * Descriptors... As you may run short of them before getting any 21808057504Sxy150489 * transmit interrupt... 21908057504Sxy150489 */ 220da14cebeSEric Cheng if (tx_ring->tbd_avail < DEFAULT_TX_NO_RESOURCE) { 22108057504Sxy150489 (void) e1000g_recycle(tx_ring); 22247b7744cSyy150190 E1000G_DEBUG_STAT(tx_ring->stat_recycle); 22308057504Sxy150489 22447b7744cSyy150190 if (tx_ring->tbd_avail < DEFAULT_TX_NO_RESOURCE) { 22525f2d433Sxy150489 E1000G_DEBUG_STAT(tx_ring->stat_lack_desc); 22608057504Sxy150489 goto tx_no_resource; 22708057504Sxy150489 } 22847b7744cSyy150190 } 22908057504Sxy150489 23008057504Sxy150489 /* 23108057504Sxy150489 * If the message size is less than the minimum ethernet packet size, 23208057504Sxy150489 * we'll use bcopy to send it, and padd it to 60 bytes later. 23308057504Sxy150489 */ 2349ce7e93cScc210113 if (msg_size < ETHERMIN) { 23525f2d433Sxy150489 E1000G_DEBUG_STAT(tx_ring->stat_under_size); 236c7770590Smx205022 tx_undersize_flag = B_TRUE; 23708057504Sxy150489 } 23808057504Sxy150489 23908057504Sxy150489 /* Initialize variables */ 24008057504Sxy150489 desc_count = 1; /* The initial value should be greater than 0 */ 24108057504Sxy150489 desc_total = 0; 2421b5c080fSchangqing li - Sun Microsystems - Beijing China new_mp = NULL; 24308057504Sxy150489 QUEUE_INIT_LIST(&pending_list); 24408057504Sxy150489 24508057504Sxy150489 /* Process each mblk fragment and fill tx descriptors */ 24643a17687SMiles Xu, Sun Microsystems /* 24743a17687SMiles Xu, Sun Microsystems * The software should guarantee LSO packet header(MAC+IP+TCP) 24843a17687SMiles Xu, Sun Microsystems * to be within one descriptor. Here we reallocate and refill the 24943a17687SMiles Xu, Sun Microsystems * the header if it's physical memory non-contiguous. 25043a17687SMiles Xu, Sun Microsystems */ 25143a17687SMiles Xu, Sun Microsystems if (cur_context.lso_flag) { 25243a17687SMiles Xu, Sun Microsystems /* find the last fragment of the header */ 25343a17687SMiles Xu, Sun Microsystems len = MBLKL(mp); 25443a17687SMiles Xu, Sun Microsystems ASSERT(len > 0); 2551b5c080fSchangqing li - Sun Microsystems - Beijing China next_mp = mp; 25643a17687SMiles Xu, Sun Microsystems pre_mp = NULL; 25743a17687SMiles Xu, Sun Microsystems while (len < cur_context.hdr_len) { 2581b5c080fSchangqing li - Sun Microsystems - Beijing China pre_mp = next_mp; 2591b5c080fSchangqing li - Sun Microsystems - Beijing China next_mp = next_mp->b_cont; 2601b5c080fSchangqing li - Sun Microsystems - Beijing China len += MBLKL(next_mp); 26143a17687SMiles Xu, Sun Microsystems } 26243a17687SMiles Xu, Sun Microsystems /* 26343a17687SMiles Xu, Sun Microsystems * If the header and the payload are in different mblks, 26443a17687SMiles Xu, Sun Microsystems * we simply force the header to be copied into pre-allocated 26543a17687SMiles Xu, Sun Microsystems * page-aligned buffer. 26643a17687SMiles Xu, Sun Microsystems */ 26743a17687SMiles Xu, Sun Microsystems if (len == cur_context.hdr_len) 26843a17687SMiles Xu, Sun Microsystems goto adjust_threshold; 26943a17687SMiles Xu, Sun Microsystems 2701b5c080fSchangqing li - Sun Microsystems - Beijing China hdr_frag_len = cur_context.hdr_len - (len - MBLKL(next_mp)); 27143a17687SMiles Xu, Sun Microsystems /* 27296ea4e93Schangqing li - Sun Microsystems - Beijing China * There are three cases we need to reallocate a mblk for the 27343a17687SMiles Xu, Sun Microsystems * last header fragment: 27496ea4e93Schangqing li - Sun Microsystems - Beijing China * 27543a17687SMiles Xu, Sun Microsystems * 1. the header is in multiple mblks and the last fragment 27643a17687SMiles Xu, Sun Microsystems * share the same mblk with the payload 27796ea4e93Schangqing li - Sun Microsystems - Beijing China * 27843a17687SMiles Xu, Sun Microsystems * 2. the header is in a single mblk shared with the payload 27943a17687SMiles Xu, Sun Microsystems * and the header is physical memory non-contiguous 28096ea4e93Schangqing li - Sun Microsystems - Beijing China * 28196ea4e93Schangqing li - Sun Microsystems - Beijing China * 3. there is 4 KB boundary within the header and 64 bytes 28296ea4e93Schangqing li - Sun Microsystems - Beijing China * following the end of the header bytes. The case may cause 28396ea4e93Schangqing li - Sun Microsystems - Beijing China * TCP data corruption issue. 28496ea4e93Schangqing li - Sun Microsystems - Beijing China * 28596ea4e93Schangqing li - Sun Microsystems - Beijing China * The workaround for the case #2 and case #3 is: 28696ea4e93Schangqing li - Sun Microsystems - Beijing China * Assuming standard Ethernet/IP/TCP headers of 54 bytes, 28796ea4e93Schangqing li - Sun Microsystems - Beijing China * this means that the buffer(containing the headers) should 28896ea4e93Schangqing li - Sun Microsystems - Beijing China * not start -118 bytes before a 4 KB boundary. For example, 28996ea4e93Schangqing li - Sun Microsystems - Beijing China * 128-byte alignment for this buffer could be used to fulfill 29096ea4e93Schangqing li - Sun Microsystems - Beijing China * this condition. 29143a17687SMiles Xu, Sun Microsystems */ 2921b5c080fSchangqing li - Sun Microsystems - Beijing China if ((next_mp != mp) || 29396ea4e93Schangqing li - Sun Microsystems - Beijing China (P2NPHASE((uintptr_t)next_mp->b_rptr, 29496ea4e93Schangqing li - Sun Microsystems - Beijing China E1000_LSO_FIRST_DESC_ALIGNMENT_BOUNDARY_4K) 29596ea4e93Schangqing li - Sun Microsystems - Beijing China < E1000_LSO_FIRST_DESC_ALIGNMENT)) { 29643a17687SMiles Xu, Sun Microsystems E1000G_DEBUG_STAT(tx_ring->stat_lso_header_fail); 29743a17687SMiles Xu, Sun Microsystems /* 29843a17687SMiles Xu, Sun Microsystems * reallocate the mblk for the last header fragment, 29943a17687SMiles Xu, Sun Microsystems * expect to bcopy into pre-allocated page-aligned 30043a17687SMiles Xu, Sun Microsystems * buffer 30143a17687SMiles Xu, Sun Microsystems */ 30243a17687SMiles Xu, Sun Microsystems new_mp = allocb(hdr_frag_len, NULL); 30343a17687SMiles Xu, Sun Microsystems if (!new_mp) 30443a17687SMiles Xu, Sun Microsystems return (B_FALSE); 3051b5c080fSchangqing li - Sun Microsystems - Beijing China bcopy(next_mp->b_rptr, new_mp->b_rptr, hdr_frag_len); 30643a17687SMiles Xu, Sun Microsystems /* link the new header fragment with the other parts */ 30743a17687SMiles Xu, Sun Microsystems new_mp->b_wptr = new_mp->b_rptr + hdr_frag_len; 3081b5c080fSchangqing li - Sun Microsystems - Beijing China new_mp->b_cont = next_mp; 30943a17687SMiles Xu, Sun Microsystems if (pre_mp) 31043a17687SMiles Xu, Sun Microsystems pre_mp->b_cont = new_mp; 31154e0d7a5SMiles Xu, Sun Microsystems else 31243a17687SMiles Xu, Sun Microsystems mp = new_mp; 3131b5c080fSchangqing li - Sun Microsystems - Beijing China next_mp->b_rptr += hdr_frag_len; 31443a17687SMiles Xu, Sun Microsystems frag_count++; 31543a17687SMiles Xu, Sun Microsystems } 31643a17687SMiles Xu, Sun Microsystems adjust_threshold: 31743a17687SMiles Xu, Sun Microsystems /* 31843a17687SMiles Xu, Sun Microsystems * adjust the bcopy threshhold to guarantee 31943a17687SMiles Xu, Sun Microsystems * the header to use bcopy way 32043a17687SMiles Xu, Sun Microsystems */ 32143a17687SMiles Xu, Sun Microsystems if (bcopy_thresh < cur_context.hdr_len) 32243a17687SMiles Xu, Sun Microsystems bcopy_thresh = cur_context.hdr_len; 32343a17687SMiles Xu, Sun Microsystems } 32443a17687SMiles Xu, Sun Microsystems 32508057504Sxy150489 packet = NULL; 32608057504Sxy150489 nmp = mp; 32708057504Sxy150489 while (nmp) { 32808057504Sxy150489 tmp = nmp->b_cont; 32908057504Sxy150489 33008057504Sxy150489 len = MBLKL(nmp); 33108057504Sxy150489 /* Check zero length mblks */ 33208057504Sxy150489 if (len == 0) { 33325f2d433Sxy150489 E1000G_DEBUG_STAT(tx_ring->stat_empty_frags); 33408057504Sxy150489 /* 33508057504Sxy150489 * If there're no packet buffers have been used, 33608057504Sxy150489 * or we just completed processing a buffer, then 33708057504Sxy150489 * skip the empty mblk fragment. 33808057504Sxy150489 * Otherwise, there's still a pending buffer that 33908057504Sxy150489 * needs to be processed (tx_copy). 34008057504Sxy150489 */ 34108057504Sxy150489 if (desc_count > 0) { 34208057504Sxy150489 nmp = tmp; 34308057504Sxy150489 continue; 34408057504Sxy150489 } 34508057504Sxy150489 } 34608057504Sxy150489 34708057504Sxy150489 /* 34808057504Sxy150489 * Get a new TxSwPacket to process mblk buffers. 34908057504Sxy150489 */ 35008057504Sxy150489 if (desc_count > 0) { 35108057504Sxy150489 mutex_enter(&tx_ring->freelist_lock); 35225f2d433Sxy150489 packet = (p_tx_sw_packet_t) 35308057504Sxy150489 QUEUE_POP_HEAD(&tx_ring->free_list); 35408057504Sxy150489 mutex_exit(&tx_ring->freelist_lock); 35508057504Sxy150489 35608057504Sxy150489 if (packet == NULL) { 35725f2d433Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_INFO_LEVEL, 35808057504Sxy150489 "No Tx SwPacket available\n"); 35925f2d433Sxy150489 E1000G_STAT(tx_ring->stat_no_swpkt); 36008057504Sxy150489 goto tx_send_failed; 36108057504Sxy150489 } 36208057504Sxy150489 QUEUE_PUSH_TAIL(&pending_list, &packet->Link); 36308057504Sxy150489 } 36408057504Sxy150489 36508057504Sxy150489 ASSERT(packet); 36608057504Sxy150489 /* 36708057504Sxy150489 * If the size of the fragment is less than the tx_bcopy_thresh 36808057504Sxy150489 * we'll use bcopy; Otherwise, we'll use DMA binding. 36908057504Sxy150489 */ 37043a17687SMiles Xu, Sun Microsystems if ((len <= bcopy_thresh) || tx_undersize_flag) { 37108057504Sxy150489 desc_count = 372c7770590Smx205022 e1000g_tx_copy(tx_ring, packet, nmp, 373c7770590Smx205022 tx_undersize_flag); 37425f2d433Sxy150489 E1000G_DEBUG_STAT(tx_ring->stat_copy); 37508057504Sxy150489 } else { 37608057504Sxy150489 desc_count = 37725f2d433Sxy150489 e1000g_tx_bind(tx_ring, packet, nmp); 37825f2d433Sxy150489 E1000G_DEBUG_STAT(tx_ring->stat_bind); 37908057504Sxy150489 } 38008057504Sxy150489 38108057504Sxy150489 if (desc_count > 0) 38208057504Sxy150489 desc_total += desc_count; 38325f2d433Sxy150489 else if (desc_count < 0) 38425f2d433Sxy150489 goto tx_send_failed; 38508057504Sxy150489 38608057504Sxy150489 nmp = tmp; 38708057504Sxy150489 } 38808057504Sxy150489 38908057504Sxy150489 /* Assign the message to the last sw packet */ 39008057504Sxy150489 ASSERT(packet); 39108057504Sxy150489 ASSERT(packet->mp == NULL); 39208057504Sxy150489 packet->mp = mp; 39308057504Sxy150489 39408057504Sxy150489 /* Try to recycle the tx descriptors again */ 39596ea4e93Schangqing li - Sun Microsystems - Beijing China if (tx_ring->tbd_avail < (desc_total + 3)) { 39625f2d433Sxy150489 E1000G_DEBUG_STAT(tx_ring->stat_recycle_retry); 39708057504Sxy150489 (void) e1000g_recycle(tx_ring); 39808057504Sxy150489 } 39908057504Sxy150489 40008057504Sxy150489 mutex_enter(&tx_ring->tx_lock); 40108057504Sxy150489 40208057504Sxy150489 /* 40308057504Sxy150489 * If the number of available tx descriptors is not enough for transmit 40408057504Sxy150489 * (one redundant descriptor and one hw checksum context descriptor are 40508057504Sxy150489 * included), then return failure. 40608057504Sxy150489 */ 40796ea4e93Schangqing li - Sun Microsystems - Beijing China if (tx_ring->tbd_avail < (desc_total + 3)) { 40825f2d433Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_INFO_LEVEL, 40908057504Sxy150489 "No Enough Tx descriptors\n"); 41025f2d433Sxy150489 E1000G_STAT(tx_ring->stat_no_desc); 41108057504Sxy150489 mutex_exit(&tx_ring->tx_lock); 41208057504Sxy150489 goto tx_send_failed; 41308057504Sxy150489 } 41408057504Sxy150489 415c7770590Smx205022 desc_count = e1000g_fill_tx_ring(tx_ring, &pending_list, &cur_context); 41608057504Sxy150489 41708057504Sxy150489 mutex_exit(&tx_ring->tx_lock); 41808057504Sxy150489 41908057504Sxy150489 ASSERT(desc_count > 0); 42008057504Sxy150489 42108057504Sxy150489 /* Send successful */ 42208057504Sxy150489 return (B_TRUE); 42308057504Sxy150489 42408057504Sxy150489 tx_send_failed: 4251b5c080fSchangqing li - Sun Microsystems - Beijing China /* Restore mp to original */ 4261b5c080fSchangqing li - Sun Microsystems - Beijing China if (new_mp) { 4271b5c080fSchangqing li - Sun Microsystems - Beijing China if (pre_mp) { 4281b5c080fSchangqing li - Sun Microsystems - Beijing China pre_mp->b_cont = next_mp; 4291b5c080fSchangqing li - Sun Microsystems - Beijing China } 4301b5c080fSchangqing li - Sun Microsystems - Beijing China new_mp->b_cont = NULL; 4311b5c080fSchangqing li - Sun Microsystems - Beijing China freemsg(new_mp); 4321b5c080fSchangqing li - Sun Microsystems - Beijing China 4331b5c080fSchangqing li - Sun Microsystems - Beijing China next_mp->b_rptr -= hdr_frag_len; 4341b5c080fSchangqing li - Sun Microsystems - Beijing China } 4351b5c080fSchangqing li - Sun Microsystems - Beijing China 43647b7744cSyy150190 /* 43747b7744cSyy150190 * Enable Transmit interrupts, so that the interrupt routine can 43847b7744cSyy150190 * call mac_tx_update() when transmit descriptors become available. 43947b7744cSyy150190 */ 440da14cebeSEric Cheng tx_ring->resched_timestamp = ddi_get_lbolt(); 44147b7744cSyy150190 tx_ring->resched_needed = B_TRUE; 44247b7744cSyy150190 if (!Adapter->tx_intr_enable) 44347b7744cSyy150190 e1000g_mask_tx_interrupt(Adapter); 44447b7744cSyy150190 44508057504Sxy150489 /* Free pending TxSwPackets */ 44625f2d433Sxy150489 packet = (p_tx_sw_packet_t)QUEUE_GET_HEAD(&pending_list); 44708057504Sxy150489 while (packet) { 44808057504Sxy150489 packet->mp = NULL; 44925f2d433Sxy150489 e1000g_free_tx_swpkt(packet); 45025f2d433Sxy150489 packet = (p_tx_sw_packet_t) 45108057504Sxy150489 QUEUE_GET_NEXT(&pending_list, &packet->Link); 45208057504Sxy150489 } 45308057504Sxy150489 45408057504Sxy150489 /* Return pending TxSwPackets to the "Free" list */ 45508057504Sxy150489 mutex_enter(&tx_ring->freelist_lock); 45608057504Sxy150489 QUEUE_APPEND(&tx_ring->free_list, &pending_list); 45708057504Sxy150489 mutex_exit(&tx_ring->freelist_lock); 45808057504Sxy150489 45925f2d433Sxy150489 E1000G_STAT(tx_ring->stat_send_fail); 46008057504Sxy150489 46147b7744cSyy150190 /* Message will be scheduled for re-transmit */ 46247b7744cSyy150190 return (B_FALSE); 46308057504Sxy150489 46408057504Sxy150489 tx_no_resource: 46508057504Sxy150489 /* 46608057504Sxy150489 * Enable Transmit interrupts, so that the interrupt routine can 46708057504Sxy150489 * call mac_tx_update() when transmit descriptors become available. 46808057504Sxy150489 */ 469da14cebeSEric Cheng tx_ring->resched_timestamp = ddi_get_lbolt(); 47025f2d433Sxy150489 tx_ring->resched_needed = B_TRUE; 47108057504Sxy150489 if (!Adapter->tx_intr_enable) 47225f2d433Sxy150489 e1000g_mask_tx_interrupt(Adapter); 47308057504Sxy150489 47408057504Sxy150489 /* Message will be scheduled for re-transmit */ 47508057504Sxy150489 return (B_FALSE); 47608057504Sxy150489 } 47708057504Sxy150489 4787941757cSxy150489 static boolean_t 4794d737963Sxiangtao you - Sun Microsystems - Beijing China e1000g_retrieve_context(mblk_t *mp, context_data_t *cur_context, 480c7770590Smx205022 size_t msg_size) 4817941757cSxy150489 { 482c7770590Smx205022 uintptr_t ip_start; 483c7770590Smx205022 uintptr_t tcp_start; 484c7770590Smx205022 mblk_t *nmp; 485da14cebeSEric Cheng uint32_t lsoflags; 486da14cebeSEric Cheng uint32_t mss; 4877941757cSxy150489 488c7770590Smx205022 bzero(cur_context, sizeof (context_data_t)); 4897941757cSxy150489 490da14cebeSEric Cheng /* first check lso information */ 4910dc2366fSVenugopal Iyer mac_lso_get(mp, &mss, &lsoflags); 492da14cebeSEric Cheng 493c7770590Smx205022 /* retrieve checksum info */ 4940dc2366fSVenugopal Iyer mac_hcksum_get(mp, &cur_context->cksum_start, 495c7770590Smx205022 &cur_context->cksum_stuff, NULL, NULL, &cur_context->cksum_flags); 4964d737963Sxiangtao you - Sun Microsystems - Beijing China /* retrieve ethernet header size */ 497fe62dec3SChen-Liang Xu if (((struct ether_vlan_header *)(uintptr_t)mp->b_rptr)->ether_tpid == 498c7770590Smx205022 htons(ETHERTYPE_VLAN)) 499c7770590Smx205022 cur_context->ether_header_size = 500c7770590Smx205022 sizeof (struct ether_vlan_header); 501c7770590Smx205022 else 502c7770590Smx205022 cur_context->ether_header_size = 503c7770590Smx205022 sizeof (struct ether_header); 5047941757cSxy150489 505da14cebeSEric Cheng if (lsoflags & HW_LSO) { 506da14cebeSEric Cheng ASSERT(mss != 0); 507da14cebeSEric Cheng 508da14cebeSEric Cheng /* free the invalid packet */ 509da14cebeSEric Cheng if (mss == 0 || 510da14cebeSEric Cheng !((cur_context->cksum_flags & HCK_PARTIALCKSUM) && 511c7770590Smx205022 (cur_context->cksum_flags & HCK_IPV4_HDRCKSUM))) { 512c7770590Smx205022 return (B_FALSE); 513c7770590Smx205022 } 514da14cebeSEric Cheng cur_context->mss = (uint16_t)mss; 515c7770590Smx205022 cur_context->lso_flag = B_TRUE; 516da14cebeSEric Cheng 517c7770590Smx205022 /* 518c7770590Smx205022 * Some fields are cleared for the hardware to fill 519c7770590Smx205022 * in. We don't assume Ethernet header, IP header and 520c7770590Smx205022 * TCP header are always in the same mblk fragment, 521c7770590Smx205022 * while we assume each header is always within one 522c7770590Smx205022 * mblk fragment and Ethernet header is always in the 523c7770590Smx205022 * first mblk fragment. 524c7770590Smx205022 */ 525c7770590Smx205022 nmp = mp; 526c7770590Smx205022 ip_start = (uintptr_t)(nmp->b_rptr) 527c7770590Smx205022 + cur_context->ether_header_size; 528c7770590Smx205022 if (ip_start >= (uintptr_t)(nmp->b_wptr)) { 529c7770590Smx205022 ip_start = (uintptr_t)nmp->b_cont->b_rptr 530c7770590Smx205022 + (ip_start - (uintptr_t)(nmp->b_wptr)); 531c7770590Smx205022 nmp = nmp->b_cont; 532c7770590Smx205022 } 533c7770590Smx205022 tcp_start = ip_start + 534c7770590Smx205022 IPH_HDR_LENGTH((ipha_t *)ip_start); 535c7770590Smx205022 if (tcp_start >= (uintptr_t)(nmp->b_wptr)) { 536c7770590Smx205022 tcp_start = (uintptr_t)nmp->b_cont->b_rptr 537c7770590Smx205022 + (tcp_start - (uintptr_t)(nmp->b_wptr)); 538c7770590Smx205022 nmp = nmp->b_cont; 539c7770590Smx205022 } 540c7770590Smx205022 cur_context->hdr_len = cur_context->ether_header_size 541c7770590Smx205022 + IPH_HDR_LENGTH((ipha_t *)ip_start) 542c7770590Smx205022 + TCP_HDR_LENGTH((tcph_t *)tcp_start); 543c7770590Smx205022 ((ipha_t *)ip_start)->ipha_length = 0; 544c7770590Smx205022 ((ipha_t *)ip_start)->ipha_hdr_checksum = 0; 545c7770590Smx205022 /* calculate the TCP packet payload length */ 546c7770590Smx205022 cur_context->pay_len = msg_size - cur_context->hdr_len; 547c7770590Smx205022 } 548c7770590Smx205022 return (B_TRUE); 549c7770590Smx205022 } 550c7770590Smx205022 551c7770590Smx205022 static boolean_t 552c7770590Smx205022 e1000g_check_context(e1000g_tx_ring_t *tx_ring, context_data_t *cur_context) 553c7770590Smx205022 { 554c7770590Smx205022 boolean_t context_reload; 555c7770590Smx205022 context_data_t *pre_context; 556c7770590Smx205022 struct e1000g *Adapter; 557c7770590Smx205022 558c7770590Smx205022 context_reload = B_FALSE; 559c7770590Smx205022 pre_context = &tx_ring->pre_context; 560c7770590Smx205022 Adapter = tx_ring->adapter; 561c7770590Smx205022 562c7770590Smx205022 /* 563c7770590Smx205022 * The following code determine if the context descriptor is 564c7770590Smx205022 * needed to be reloaded. The sequence of the conditions is 565c7770590Smx205022 * made by their possibilities of changing. 566c7770590Smx205022 */ 567c7770590Smx205022 /* 568c7770590Smx205022 * workaround for 82546EB, context descriptor must be reloaded 569c7770590Smx205022 * per LSO/hw_cksum packet if LSO is enabled. 570c7770590Smx205022 */ 571c7770590Smx205022 if (Adapter->lso_premature_issue && 572c7770590Smx205022 Adapter->lso_enable && 573c7770590Smx205022 (cur_context->cksum_flags != 0)) { 574c7770590Smx205022 575c7770590Smx205022 context_reload = B_TRUE; 576c7770590Smx205022 } else if (cur_context->lso_flag) { 57743a17687SMiles Xu, Sun Microsystems if ((cur_context->lso_flag != pre_context->lso_flag) || 57843a17687SMiles Xu, Sun Microsystems (cur_context->cksum_flags != pre_context->cksum_flags) || 579c7770590Smx205022 (cur_context->pay_len != pre_context->pay_len) || 580c7770590Smx205022 (cur_context->mss != pre_context->mss) || 581c7770590Smx205022 (cur_context->hdr_len != pre_context->hdr_len) || 582c7770590Smx205022 (cur_context->cksum_stuff != pre_context->cksum_stuff) || 583c7770590Smx205022 (cur_context->cksum_start != pre_context->cksum_start) || 584c7770590Smx205022 (cur_context->ether_header_size != 585c7770590Smx205022 pre_context->ether_header_size)) { 586c7770590Smx205022 587c7770590Smx205022 context_reload = B_TRUE; 588c7770590Smx205022 } 589c7770590Smx205022 } else if (cur_context->cksum_flags != 0) { 59043a17687SMiles Xu, Sun Microsystems if ((cur_context->lso_flag != pre_context->lso_flag) || 59143a17687SMiles Xu, Sun Microsystems (cur_context->cksum_flags != pre_context->cksum_flags) || 592c7770590Smx205022 (cur_context->cksum_stuff != pre_context->cksum_stuff) || 593c7770590Smx205022 (cur_context->cksum_start != pre_context->cksum_start) || 594c7770590Smx205022 (cur_context->ether_header_size != 595c7770590Smx205022 pre_context->ether_header_size)) { 596c7770590Smx205022 597c7770590Smx205022 context_reload = B_TRUE; 5987941757cSxy150489 } 5997941757cSxy150489 } 6007941757cSxy150489 601c7770590Smx205022 return (context_reload); 6027941757cSxy150489 } 6037941757cSxy150489 60408057504Sxy150489 static int 60508057504Sxy150489 e1000g_fill_tx_ring(e1000g_tx_ring_t *tx_ring, LIST_DESCRIBER *pending_list, 606c7770590Smx205022 context_data_t *cur_context) 60708057504Sxy150489 { 60808057504Sxy150489 struct e1000g *Adapter; 60925f2d433Sxy150489 struct e1000_hw *hw; 61025f2d433Sxy150489 p_tx_sw_packet_t first_packet; 61125f2d433Sxy150489 p_tx_sw_packet_t packet; 612c7770590Smx205022 p_tx_sw_packet_t previous_packet; 613c7770590Smx205022 boolean_t context_reload; 61408057504Sxy150489 struct e1000_tx_desc *first_data_desc; 61508057504Sxy150489 struct e1000_tx_desc *next_desc; 61608057504Sxy150489 struct e1000_tx_desc *descriptor; 6175c68564dSBryan Cantrill struct e1000_data_desc zeroed; 61808057504Sxy150489 int desc_count; 619c7770590Smx205022 boolean_t buff_overrun_flag; 62008057504Sxy150489 int i; 62108057504Sxy150489 62208057504Sxy150489 Adapter = tx_ring->adapter; 62325f2d433Sxy150489 hw = &Adapter->shared; 62408057504Sxy150489 62508057504Sxy150489 desc_count = 0; 6267941757cSxy150489 first_packet = NULL; 62708057504Sxy150489 first_data_desc = NULL; 62808057504Sxy150489 descriptor = NULL; 629c7770590Smx205022 first_packet = NULL; 630c7770590Smx205022 packet = NULL; 631c7770590Smx205022 buff_overrun_flag = B_FALSE; 6325c68564dSBryan Cantrill zeroed.upper.data = 0; 63308057504Sxy150489 63408057504Sxy150489 next_desc = tx_ring->tbd_next; 63508057504Sxy150489 636c7770590Smx205022 /* Context descriptor reload check */ 637c7770590Smx205022 context_reload = e1000g_check_context(tx_ring, cur_context); 6387941757cSxy150489 639c7770590Smx205022 if (context_reload) { 64025f2d433Sxy150489 first_packet = (p_tx_sw_packet_t)QUEUE_GET_HEAD(pending_list); 6417941757cSxy150489 64208057504Sxy150489 descriptor = next_desc; 64308057504Sxy150489 644c7770590Smx205022 e1000g_fill_context_descriptor(cur_context, 6457941757cSxy150489 (struct e1000_context_desc *)descriptor); 64608057504Sxy150489 64708057504Sxy150489 /* Check the wrap-around case */ 64808057504Sxy150489 if (descriptor == tx_ring->tbd_last) 64908057504Sxy150489 next_desc = tx_ring->tbd_first; 65008057504Sxy150489 else 65108057504Sxy150489 next_desc++; 65208057504Sxy150489 65308057504Sxy150489 desc_count++; 65408057504Sxy150489 } 65508057504Sxy150489 65608057504Sxy150489 first_data_desc = next_desc; 65708057504Sxy150489 6585c68564dSBryan Cantrill /* 6595c68564dSBryan Cantrill * According to the documentation, the packet options field (POPTS) is 6605c68564dSBryan Cantrill * "ignored except on the first data descriptor of a packet." However, 6615c68564dSBryan Cantrill * there is a bug in QEMU (638955) whereby the POPTS field within a 6625c68564dSBryan Cantrill * given data descriptor is used to interpret that data descriptor -- 6635c68564dSBryan Cantrill * regardless of whether or not the descriptor is the first in a packet 6645c68564dSBryan Cantrill * or not. For a packet that spans multiple descriptors, the (virtual) 6655c68564dSBryan Cantrill * HW checksum (either TCP/UDP or IP or both) will therefore _not_ be 6665c68564dSBryan Cantrill * performed on descriptors after the first, resulting in incorrect 6675c68564dSBryan Cantrill * checksums and mysteriously dropped/retransmitted packets. Other 6685c68564dSBryan Cantrill * drivers do not have this issue because they (harmlessly) set the 6695c68564dSBryan Cantrill * POPTS field on every data descriptor to be the intended options for 6705c68564dSBryan Cantrill * the entire packet. To circumvent this QEMU bug, we engage in this 6715c68564dSBryan Cantrill * same behavior iff the subsystem vendor and device IDs indicate that 6725c68564dSBryan Cantrill * this is an emulated QEMU device (1af4,1100). 6735c68564dSBryan Cantrill */ 6745c68564dSBryan Cantrill if (hw->subsystem_vendor_id == 0x1af4 && 6755c68564dSBryan Cantrill hw->subsystem_device_id == 0x1100 && 6765c68564dSBryan Cantrill cur_context->cksum_flags) { 6775c68564dSBryan Cantrill if (cur_context->cksum_flags & HCK_IPV4_HDRCKSUM) 6785c68564dSBryan Cantrill zeroed.upper.fields.popts |= E1000_TXD_POPTS_IXSM; 6795c68564dSBryan Cantrill 6805c68564dSBryan Cantrill if (cur_context->cksum_flags & HCK_PARTIALCKSUM) 6815c68564dSBryan Cantrill zeroed.upper.fields.popts |= E1000_TXD_POPTS_TXSM; 6825c68564dSBryan Cantrill } 6835c68564dSBryan Cantrill 68425f2d433Sxy150489 packet = (p_tx_sw_packet_t)QUEUE_GET_HEAD(pending_list); 68508057504Sxy150489 while (packet) { 68608057504Sxy150489 ASSERT(packet->num_desc); 68708057504Sxy150489 68808057504Sxy150489 for (i = 0; i < packet->num_desc; i++) { 68925f2d433Sxy150489 ASSERT(tx_ring->tbd_avail > 0); 69008057504Sxy150489 69108057504Sxy150489 descriptor = next_desc; 69208057504Sxy150489 descriptor->buffer_addr = 69325f2d433Sxy150489 packet->desc[i].address; 69408057504Sxy150489 descriptor->lower.data = 69525f2d433Sxy150489 packet->desc[i].length; 69608057504Sxy150489 69708057504Sxy150489 /* Zero out status */ 6985c68564dSBryan Cantrill descriptor->upper.data = zeroed.upper.data; 69908057504Sxy150489 70008057504Sxy150489 descriptor->lower.data |= 70108057504Sxy150489 E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; 70208057504Sxy150489 /* must set RS on every outgoing descriptor */ 70308057504Sxy150489 descriptor->lower.data |= 70408057504Sxy150489 E1000_TXD_CMD_RS; 70508057504Sxy150489 706c7770590Smx205022 if (cur_context->lso_flag) 707c7770590Smx205022 descriptor->lower.data |= E1000_TXD_CMD_TSE; 708c7770590Smx205022 70908057504Sxy150489 /* Check the wrap-around case */ 71008057504Sxy150489 if (descriptor == tx_ring->tbd_last) 71108057504Sxy150489 next_desc = tx_ring->tbd_first; 71208057504Sxy150489 else 71308057504Sxy150489 next_desc++; 71408057504Sxy150489 71508057504Sxy150489 desc_count++; 716c7770590Smx205022 717c7770590Smx205022 /* 718c7770590Smx205022 * workaround for 82546EB errata 33, hang in PCI-X 719c7770590Smx205022 * systems due to 2k Buffer Overrun during Transmit 720c7770590Smx205022 * Operation. The workaround applies to all the Intel 721c7770590Smx205022 * PCI-X chips. 722c7770590Smx205022 */ 723c7770590Smx205022 if (hw->bus.type == e1000_bus_type_pcix && 724c7770590Smx205022 descriptor == first_data_desc && 725c7770590Smx205022 ((descriptor->lower.data & E1000G_TBD_LENGTH_MASK) 726c7770590Smx205022 > E1000_TX_BUFFER_OEVRRUN_THRESHOLD)) { 727c7770590Smx205022 /* modified the first descriptor */ 728c7770590Smx205022 descriptor->lower.data &= 729c7770590Smx205022 ~E1000G_TBD_LENGTH_MASK; 730c7770590Smx205022 descriptor->lower.flags.length = 731c7770590Smx205022 E1000_TX_BUFFER_OEVRRUN_THRESHOLD; 732c7770590Smx205022 733c7770590Smx205022 /* insert a new descriptor */ 734c7770590Smx205022 ASSERT(tx_ring->tbd_avail > 0); 735c7770590Smx205022 next_desc->buffer_addr = 736c7770590Smx205022 packet->desc[0].address + 737c7770590Smx205022 E1000_TX_BUFFER_OEVRRUN_THRESHOLD; 738c7770590Smx205022 next_desc->lower.data = 739c7770590Smx205022 packet->desc[0].length - 740c7770590Smx205022 E1000_TX_BUFFER_OEVRRUN_THRESHOLD; 741c7770590Smx205022 742c7770590Smx205022 /* Zero out status */ 7435c68564dSBryan Cantrill next_desc->upper.data = zeroed.upper.data; 744c7770590Smx205022 745c7770590Smx205022 next_desc->lower.data |= 746c7770590Smx205022 E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; 747c7770590Smx205022 /* must set RS on every outgoing descriptor */ 748c7770590Smx205022 next_desc->lower.data |= 749c7770590Smx205022 E1000_TXD_CMD_RS; 750c7770590Smx205022 751c7770590Smx205022 if (cur_context->lso_flag) 752c7770590Smx205022 next_desc->lower.data |= 753c7770590Smx205022 E1000_TXD_CMD_TSE; 754c7770590Smx205022 755c7770590Smx205022 descriptor = next_desc; 756c7770590Smx205022 757c7770590Smx205022 /* Check the wrap-around case */ 758c7770590Smx205022 if (next_desc == tx_ring->tbd_last) 759c7770590Smx205022 next_desc = tx_ring->tbd_first; 760c7770590Smx205022 else 761c7770590Smx205022 next_desc++; 762c7770590Smx205022 763c7770590Smx205022 desc_count++; 764c7770590Smx205022 buff_overrun_flag = B_TRUE; 765c7770590Smx205022 } 766c7770590Smx205022 } 767c7770590Smx205022 768c7770590Smx205022 if (buff_overrun_flag) { 769c7770590Smx205022 packet->num_desc++; 770c7770590Smx205022 buff_overrun_flag = B_FALSE; 77108057504Sxy150489 } 77208057504Sxy150489 77308057504Sxy150489 if (first_packet != NULL) { 77408057504Sxy150489 /* 77508057504Sxy150489 * Count the checksum context descriptor for 77608057504Sxy150489 * the first SwPacket. 77708057504Sxy150489 */ 77808057504Sxy150489 first_packet->num_desc++; 77908057504Sxy150489 first_packet = NULL; 78008057504Sxy150489 } 78108057504Sxy150489 782d3d50737SRafael Vanoni packet->tickstamp = ddi_get_lbolt64(); 78354e0d7a5SMiles Xu, Sun Microsystems 784c7770590Smx205022 previous_packet = packet; 78525f2d433Sxy150489 packet = (p_tx_sw_packet_t) 78608057504Sxy150489 QUEUE_GET_NEXT(pending_list, &packet->Link); 78708057504Sxy150489 } 78808057504Sxy150489 789c7770590Smx205022 /* 790c7770590Smx205022 * workaround for 82546EB errata 21, LSO Premature Descriptor Write Back 791c7770590Smx205022 */ 792c7770590Smx205022 if (Adapter->lso_premature_issue && cur_context->lso_flag && 793c7770590Smx205022 ((descriptor->lower.data & E1000G_TBD_LENGTH_MASK) > 8)) { 794c7770590Smx205022 /* modified the previous descriptor */ 795c7770590Smx205022 descriptor->lower.data -= 4; 796c7770590Smx205022 797c7770590Smx205022 /* insert a new descriptor */ 798c7770590Smx205022 ASSERT(tx_ring->tbd_avail > 0); 799c7770590Smx205022 /* the lower 20 bits of lower.data is the length field */ 800c7770590Smx205022 next_desc->buffer_addr = 801c7770590Smx205022 descriptor->buffer_addr + 802c7770590Smx205022 (descriptor->lower.data & E1000G_TBD_LENGTH_MASK); 803c7770590Smx205022 next_desc->lower.data = 4; 804c7770590Smx205022 805c7770590Smx205022 /* Zero out status */ 8065c68564dSBryan Cantrill next_desc->upper.data = zeroed.upper.data; 807c7770590Smx205022 /* It must be part of a LSO packet */ 808c7770590Smx205022 next_desc->lower.data |= 809c7770590Smx205022 E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D | 810c7770590Smx205022 E1000_TXD_CMD_RS | E1000_TXD_CMD_TSE; 811c7770590Smx205022 812c7770590Smx205022 descriptor = next_desc; 813c7770590Smx205022 814c7770590Smx205022 /* Check the wrap-around case */ 815c7770590Smx205022 if (descriptor == tx_ring->tbd_last) 816c7770590Smx205022 next_desc = tx_ring->tbd_first; 817c7770590Smx205022 else 818c7770590Smx205022 next_desc++; 819c7770590Smx205022 820c7770590Smx205022 desc_count++; 821c7770590Smx205022 /* update the number of descriptors */ 822c7770590Smx205022 previous_packet->num_desc++; 823c7770590Smx205022 } 824c7770590Smx205022 82508057504Sxy150489 ASSERT(descriptor); 82608057504Sxy150489 827c7770590Smx205022 if (cur_context->cksum_flags) { 828c7770590Smx205022 if (cur_context->cksum_flags & HCK_IPV4_HDRCKSUM) 82908057504Sxy150489 ((struct e1000_data_desc *)first_data_desc)-> 83008057504Sxy150489 upper.fields.popts |= E1000_TXD_POPTS_IXSM; 831c7770590Smx205022 if (cur_context->cksum_flags & HCK_PARTIALCKSUM) 83208057504Sxy150489 ((struct e1000_data_desc *)first_data_desc)-> 83308057504Sxy150489 upper.fields.popts |= E1000_TXD_POPTS_TXSM; 83408057504Sxy150489 } 83508057504Sxy150489 83608057504Sxy150489 /* 83708057504Sxy150489 * Last Descriptor of Packet needs End Of Packet (EOP), Report 838c7770590Smx205022 * Status (RS) set. 83908057504Sxy150489 */ 84025f2d433Sxy150489 if (Adapter->tx_intr_delay) { 84108057504Sxy150489 descriptor->lower.data |= E1000_TXD_CMD_IDE | 842c7770590Smx205022 E1000_TXD_CMD_EOP; 84308057504Sxy150489 } else { 844c7770590Smx205022 descriptor->lower.data |= E1000_TXD_CMD_EOP; 845c7770590Smx205022 } 846c7770590Smx205022 847c7770590Smx205022 /* Set append Ethernet CRC (IFCS) bits */ 848c7770590Smx205022 if (cur_context->lso_flag) { 849c7770590Smx205022 first_data_desc->lower.data |= E1000_TXD_CMD_IFCS; 850c7770590Smx205022 } else { 851c7770590Smx205022 descriptor->lower.data |= E1000_TXD_CMD_IFCS; 85208057504Sxy150489 } 85308057504Sxy150489 85408057504Sxy150489 /* 85508057504Sxy150489 * Sync the Tx descriptors DMA buffer 85608057504Sxy150489 */ 85708057504Sxy150489 (void) ddi_dma_sync(tx_ring->tbd_dma_handle, 85825f2d433Sxy150489 0, 0, DDI_DMA_SYNC_FORDEV); 85908057504Sxy150489 86008057504Sxy150489 tx_ring->tbd_next = next_desc; 86108057504Sxy150489 86208057504Sxy150489 /* 86308057504Sxy150489 * Advance the Transmit Descriptor Tail (Tdt), this tells the 86408057504Sxy150489 * FX1000 that this frame is available to transmit. 86508057504Sxy150489 */ 86625f2d433Sxy150489 if (hw->mac.type == e1000_82547) 86708057504Sxy150489 e1000g_82547_tx_move_tail(tx_ring); 86808057504Sxy150489 else 869592a4d85Scc210113 E1000_WRITE_REG(hw, E1000_TDT(0), 87008057504Sxy150489 (uint32_t)(next_desc - tx_ring->tbd_first)); 87108057504Sxy150489 8729b6541b3Sgl147354 if (e1000g_check_acc_handle(Adapter->osdep.reg_handle) != DDI_FM_OK) { 8739b6541b3Sgl147354 ddi_fm_service_impact(Adapter->dip, DDI_SERVICE_DEGRADED); 874d5c3073dSchenlu chen - Sun Microsystems - Beijing China Adapter->e1000g_state |= E1000G_ERROR; 8759b6541b3Sgl147354 } 8769b6541b3Sgl147354 87708057504Sxy150489 /* Put the pending SwPackets to the "Used" list */ 87808057504Sxy150489 mutex_enter(&tx_ring->usedlist_lock); 87908057504Sxy150489 QUEUE_APPEND(&tx_ring->used_list, pending_list); 88025f2d433Sxy150489 tx_ring->tbd_avail -= desc_count; 88108057504Sxy150489 mutex_exit(&tx_ring->usedlist_lock); 88208057504Sxy150489 883c7770590Smx205022 /* update LSO related data */ 884c7770590Smx205022 if (context_reload) 885c7770590Smx205022 tx_ring->pre_context = *cur_context; 8867941757cSxy150489 88708057504Sxy150489 return (desc_count); 88808057504Sxy150489 } 88908057504Sxy150489 89008057504Sxy150489 /* 89125f2d433Sxy150489 * e1000g_tx_setup - setup tx data structures 89225f2d433Sxy150489 * 89325f2d433Sxy150489 * This routine initializes all of the transmit related 89425f2d433Sxy150489 * structures. This includes the Transmit descriptors, 89525f2d433Sxy150489 * and the tx_sw_packet structures. 89608057504Sxy150489 */ 89708057504Sxy150489 void 89825f2d433Sxy150489 e1000g_tx_setup(struct e1000g *Adapter) 89908057504Sxy150489 { 90008057504Sxy150489 struct e1000_hw *hw; 90125f2d433Sxy150489 p_tx_sw_packet_t packet; 9024d737963Sxiangtao you - Sun Microsystems - Beijing China uint32_t i; 90308057504Sxy150489 uint32_t buf_high; 90408057504Sxy150489 uint32_t buf_low; 90508057504Sxy150489 uint32_t reg_tipg; 90608057504Sxy150489 uint32_t reg_tctl; 90708057504Sxy150489 int size; 90808057504Sxy150489 e1000g_tx_ring_t *tx_ring; 90908057504Sxy150489 91025f2d433Sxy150489 hw = &Adapter->shared; 91108057504Sxy150489 tx_ring = Adapter->tx_ring; 91208057504Sxy150489 91308057504Sxy150489 /* init the lists */ 91408057504Sxy150489 /* 91508057504Sxy150489 * Here we don't need to protect the lists using the 91625f2d433Sxy150489 * usedlist_lock and freelist_lock, for they have 91708057504Sxy150489 * been protected by the chip_lock. 91808057504Sxy150489 */ 91908057504Sxy150489 QUEUE_INIT_LIST(&tx_ring->used_list); 92008057504Sxy150489 QUEUE_INIT_LIST(&tx_ring->free_list); 92108057504Sxy150489 92208057504Sxy150489 /* Go through and set up each SW_Packet */ 92308057504Sxy150489 packet = tx_ring->packet_area; 92425f2d433Sxy150489 for (i = 0; i < Adapter->tx_freelist_num; i++, packet++) { 92525f2d433Sxy150489 /* Initialize this tx_sw_apcket area */ 92625f2d433Sxy150489 e1000g_free_tx_swpkt(packet); 92725f2d433Sxy150489 /* Add this tx_sw_packet to the free list */ 92808057504Sxy150489 QUEUE_PUSH_TAIL(&tx_ring->free_list, 92908057504Sxy150489 &packet->Link); 93008057504Sxy150489 } 93108057504Sxy150489 93208057504Sxy150489 /* Setup TX descriptor pointers */ 93308057504Sxy150489 tx_ring->tbd_next = tx_ring->tbd_first; 93408057504Sxy150489 tx_ring->tbd_oldest = tx_ring->tbd_first; 93508057504Sxy150489 93608057504Sxy150489 /* 93708057504Sxy150489 * Setup Hardware TX Registers 93808057504Sxy150489 */ 93908057504Sxy150489 /* Setup the Transmit Control Register (TCTL). */ 940a2e9a830Scc210113 reg_tctl = E1000_READ_REG(hw, E1000_TCTL); 941a2e9a830Scc210113 reg_tctl |= E1000_TCTL_PSP | E1000_TCTL_EN | 94208057504Sxy150489 (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT) | 94325f2d433Sxy150489 (E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT) | 94425f2d433Sxy150489 E1000_TCTL_RTLC; 94508057504Sxy150489 94608057504Sxy150489 /* Enable the MULR bit */ 94725f2d433Sxy150489 if (hw->bus.type == e1000_bus_type_pci_express) 94808057504Sxy150489 reg_tctl |= E1000_TCTL_MULR; 94908057504Sxy150489 95025f2d433Sxy150489 E1000_WRITE_REG(hw, E1000_TCTL, reg_tctl); 95108057504Sxy150489 95208057504Sxy150489 /* Setup HW Base and Length of Tx descriptor area */ 95325f2d433Sxy150489 size = (Adapter->tx_desc_num * sizeof (struct e1000_tx_desc)); 954592a4d85Scc210113 E1000_WRITE_REG(hw, E1000_TDLEN(0), size); 955592a4d85Scc210113 size = E1000_READ_REG(hw, E1000_TDLEN(0)); 95608057504Sxy150489 95708057504Sxy150489 buf_low = (uint32_t)tx_ring->tbd_dma_addr; 95808057504Sxy150489 buf_high = (uint32_t)(tx_ring->tbd_dma_addr >> 32); 95908057504Sxy150489 960ede5269eSchenlu chen - Sun Microsystems - Beijing China /* 961ede5269eSchenlu chen - Sun Microsystems - Beijing China * Write the highest location first and work backward to the lowest. 962ede5269eSchenlu chen - Sun Microsystems - Beijing China * This is necessary for some adapter types to 963ede5269eSchenlu chen - Sun Microsystems - Beijing China * prevent write combining from occurring. 964ede5269eSchenlu chen - Sun Microsystems - Beijing China */ 965592a4d85Scc210113 E1000_WRITE_REG(hw, E1000_TDBAH(0), buf_high); 966ede5269eSchenlu chen - Sun Microsystems - Beijing China E1000_WRITE_REG(hw, E1000_TDBAL(0), buf_low); 96708057504Sxy150489 96808057504Sxy150489 /* Setup our HW Tx Head & Tail descriptor pointers */ 969592a4d85Scc210113 E1000_WRITE_REG(hw, E1000_TDH(0), 0); 970592a4d85Scc210113 E1000_WRITE_REG(hw, E1000_TDT(0), 0); 97108057504Sxy150489 97208057504Sxy150489 /* Set the default values for the Tx Inter Packet Gap timer */ 97325f2d433Sxy150489 if ((hw->mac.type == e1000_82542) && 97425f2d433Sxy150489 ((hw->revision_id == E1000_REVISION_2) || 97525f2d433Sxy150489 (hw->revision_id == E1000_REVISION_3))) { 97608057504Sxy150489 reg_tipg = DEFAULT_82542_TIPG_IPGT; 97708057504Sxy150489 reg_tipg |= 97808057504Sxy150489 DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; 97908057504Sxy150489 reg_tipg |= 98008057504Sxy150489 DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; 981a2e9a830Scc210113 } else if (hw->mac.type == e1000_80003es2lan) { 982a2e9a830Scc210113 reg_tipg = DEFAULT_82543_TIPG_IPGR1; 98335ae85e6Scc210113 reg_tipg |= DEFAULT_80003ES2LAN_TIPG_IPGR2 << 984a2e9a830Scc210113 E1000_TIPG_IPGR2_SHIFT; 98525f2d433Sxy150489 } else { 986592a4d85Scc210113 if (hw->phy.media_type == e1000_media_type_fiber) 98708057504Sxy150489 reg_tipg = DEFAULT_82543_TIPG_IPGT_FIBER; 98808057504Sxy150489 else 98908057504Sxy150489 reg_tipg = DEFAULT_82543_TIPG_IPGT_COPPER; 99008057504Sxy150489 reg_tipg |= 99108057504Sxy150489 DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; 99208057504Sxy150489 reg_tipg |= 99308057504Sxy150489 DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; 99408057504Sxy150489 } 99525f2d433Sxy150489 E1000_WRITE_REG(hw, E1000_TIPG, reg_tipg); 99608057504Sxy150489 99708057504Sxy150489 /* Setup Transmit Interrupt Delay Value */ 99825f2d433Sxy150489 E1000_WRITE_REG(hw, E1000_TIDV, Adapter->tx_intr_delay); 99947b7744cSyy150190 E1000G_DEBUGLOG_1(Adapter, E1000G_INFO_LEVEL, 100047b7744cSyy150190 "E1000_TIDV: 0x%x\n", Adapter->tx_intr_delay); 100147b7744cSyy150190 100247b7744cSyy150190 if (hw->mac.type >= e1000_82540) { 100347b7744cSyy150190 E1000_WRITE_REG(&Adapter->shared, E1000_TADV, 100447b7744cSyy150190 Adapter->tx_intr_abs_delay); 100547b7744cSyy150190 E1000G_DEBUGLOG_1(Adapter, E1000G_INFO_LEVEL, 100647b7744cSyy150190 "E1000_TADV: 0x%x\n", Adapter->tx_intr_abs_delay); 100708057504Sxy150489 } 100808057504Sxy150489 100925f2d433Sxy150489 tx_ring->tbd_avail = Adapter->tx_desc_num; 101025f2d433Sxy150489 1011c7770590Smx205022 /* Initialize stored context information */ 1012c7770590Smx205022 bzero(&(tx_ring->pre_context), sizeof (context_data_t)); 101308057504Sxy150489 } 101408057504Sxy150489 101508057504Sxy150489 /* 101625f2d433Sxy150489 * e1000g_recycle - recycle the tx descriptors and tx sw packets 101708057504Sxy150489 */ 101808057504Sxy150489 int 101908057504Sxy150489 e1000g_recycle(e1000g_tx_ring_t *tx_ring) 102008057504Sxy150489 { 102108057504Sxy150489 struct e1000g *Adapter; 102208057504Sxy150489 LIST_DESCRIBER pending_list; 102325f2d433Sxy150489 p_tx_sw_packet_t packet; 102408057504Sxy150489 mblk_t *mp; 102508057504Sxy150489 mblk_t *nmp; 102608057504Sxy150489 struct e1000_tx_desc *descriptor; 102708057504Sxy150489 int desc_count; 102854e0d7a5SMiles Xu, Sun Microsystems int64_t delta; 102908057504Sxy150489 103008057504Sxy150489 /* 103108057504Sxy150489 * This function will examine each TxSwPacket in the 'used' queue 103208057504Sxy150489 * if the e1000g is done with it then the associated resources (Tx 103308057504Sxy150489 * Descriptors) will be "freed" and the TxSwPacket will be 103408057504Sxy150489 * returned to the 'free' queue. 103508057504Sxy150489 */ 103608057504Sxy150489 Adapter = tx_ring->adapter; 103754e0d7a5SMiles Xu, Sun Microsystems delta = 0; 103808057504Sxy150489 103925f2d433Sxy150489 packet = (p_tx_sw_packet_t)QUEUE_GET_HEAD(&tx_ring->used_list); 104008057504Sxy150489 if (packet == NULL) { 104154e0d7a5SMiles Xu, Sun Microsystems Adapter->stall_flag = B_FALSE; 104208057504Sxy150489 return (0); 104308057504Sxy150489 } 104408057504Sxy150489 104547b7744cSyy150190 desc_count = 0; 104647b7744cSyy150190 QUEUE_INIT_LIST(&pending_list); 104747b7744cSyy150190 104825f2d433Sxy150489 /* Sync the Tx descriptor DMA buffer */ 104925f2d433Sxy150489 (void) ddi_dma_sync(tx_ring->tbd_dma_handle, 105025f2d433Sxy150489 0, 0, DDI_DMA_SYNC_FORKERNEL); 10519b6541b3Sgl147354 if (e1000g_check_dma_handle( 10529b6541b3Sgl147354 tx_ring->tbd_dma_handle) != DDI_FM_OK) { 10539b6541b3Sgl147354 ddi_fm_service_impact(Adapter->dip, DDI_SERVICE_DEGRADED); 1054d5c3073dSchenlu chen - Sun Microsystems - Beijing China Adapter->e1000g_state |= E1000G_ERROR; 10559b6541b3Sgl147354 return (0); 10569b6541b3Sgl147354 } 105725f2d433Sxy150489 105808057504Sxy150489 /* 105908057504Sxy150489 * While there are still TxSwPackets in the used queue check them 106008057504Sxy150489 */ 1061da14cebeSEric Cheng mutex_enter(&tx_ring->usedlist_lock); 1062fe62dec3SChen-Liang Xu while ((packet = 1063fe62dec3SChen-Liang Xu (p_tx_sw_packet_t)QUEUE_GET_HEAD(&tx_ring->used_list)) != NULL) { 106408057504Sxy150489 106508057504Sxy150489 /* 106608057504Sxy150489 * Get hold of the next descriptor that the e1000g will 106708057504Sxy150489 * report status back to (this will be the last descriptor 106825f2d433Sxy150489 * of a given sw packet). We only want to free the 106925f2d433Sxy150489 * sw packet (and it resources) if the e1000g is done 107008057504Sxy150489 * with ALL of the descriptors. If the e1000g is done 107108057504Sxy150489 * with the last one then it is done with all of them. 107208057504Sxy150489 */ 107308057504Sxy150489 ASSERT(packet->num_desc); 107425f2d433Sxy150489 descriptor = tx_ring->tbd_oldest + (packet->num_desc - 1); 107508057504Sxy150489 107608057504Sxy150489 /* Check for wrap case */ 107708057504Sxy150489 if (descriptor > tx_ring->tbd_last) 107825f2d433Sxy150489 descriptor -= Adapter->tx_desc_num; 107908057504Sxy150489 108008057504Sxy150489 /* 108108057504Sxy150489 * If the descriptor done bit is set free TxSwPacket and 108208057504Sxy150489 * associated resources 108308057504Sxy150489 */ 108408057504Sxy150489 if (descriptor->upper.fields.status & E1000_TXD_STAT_DD) { 108508057504Sxy150489 QUEUE_POP_HEAD(&tx_ring->used_list); 108608057504Sxy150489 QUEUE_PUSH_TAIL(&pending_list, &packet->Link); 108708057504Sxy150489 108808057504Sxy150489 if (descriptor == tx_ring->tbd_last) 108908057504Sxy150489 tx_ring->tbd_oldest = 109008057504Sxy150489 tx_ring->tbd_first; 109108057504Sxy150489 else 109208057504Sxy150489 tx_ring->tbd_oldest = 109308057504Sxy150489 descriptor + 1; 109408057504Sxy150489 109508057504Sxy150489 desc_count += packet->num_desc; 109608057504Sxy150489 } else { 109708057504Sxy150489 /* 109825f2d433Sxy150489 * Found a sw packet that the e1000g is not done 109908057504Sxy150489 * with then there is no reason to check the rest 110008057504Sxy150489 * of the queue. 110108057504Sxy150489 */ 1102d3d50737SRafael Vanoni delta = ddi_get_lbolt64() - packet->tickstamp; 110308057504Sxy150489 break; 110408057504Sxy150489 } 110508057504Sxy150489 } 110608057504Sxy150489 110725f2d433Sxy150489 tx_ring->tbd_avail += desc_count; 110847b7744cSyy150190 Adapter->tx_pkt_cnt += desc_count; 110925f2d433Sxy150489 111008057504Sxy150489 mutex_exit(&tx_ring->usedlist_lock); 111108057504Sxy150489 111208057504Sxy150489 if (desc_count == 0) { 111325f2d433Sxy150489 E1000G_DEBUG_STAT(tx_ring->stat_recycle_none); 111454e0d7a5SMiles Xu, Sun Microsystems /* 11155f0b6ff9Sguoqing zhu - Sun Microsystems - Beijing China * If the packet hasn't been sent out for seconds and 11165f0b6ff9Sguoqing zhu - Sun Microsystems - Beijing China * the transmitter is not under paused flowctrl condition, 111754e0d7a5SMiles Xu, Sun Microsystems * the transmitter is considered to be stalled. 111854e0d7a5SMiles Xu, Sun Microsystems */ 11195f0b6ff9Sguoqing zhu - Sun Microsystems - Beijing China if ((delta > Adapter->stall_threshold) && 11205f0b6ff9Sguoqing zhu - Sun Microsystems - Beijing China !(E1000_READ_REG(&Adapter->shared, 11215f0b6ff9Sguoqing zhu - Sun Microsystems - Beijing China E1000_STATUS) & E1000_STATUS_TXOFF)) { 112254e0d7a5SMiles Xu, Sun Microsystems Adapter->stall_flag = B_TRUE; 112354e0d7a5SMiles Xu, Sun Microsystems } 112408057504Sxy150489 return (0); 112508057504Sxy150489 } 112608057504Sxy150489 112754e0d7a5SMiles Xu, Sun Microsystems Adapter->stall_flag = B_FALSE; 112808057504Sxy150489 112908057504Sxy150489 mp = NULL; 113008057504Sxy150489 nmp = NULL; 113125f2d433Sxy150489 packet = (p_tx_sw_packet_t)QUEUE_GET_HEAD(&pending_list); 113208057504Sxy150489 ASSERT(packet != NULL); 113308057504Sxy150489 while (packet != NULL) { 113408057504Sxy150489 if (packet->mp != NULL) { 113508057504Sxy150489 ASSERT(packet->mp->b_next == NULL); 113608057504Sxy150489 /* Assemble the message chain */ 113708057504Sxy150489 if (mp == NULL) { 113808057504Sxy150489 mp = packet->mp; 113908057504Sxy150489 nmp = packet->mp; 114008057504Sxy150489 } else { 114108057504Sxy150489 nmp->b_next = packet->mp; 114208057504Sxy150489 nmp = packet->mp; 114308057504Sxy150489 } 114408057504Sxy150489 /* Disconnect the message from the sw packet */ 114508057504Sxy150489 packet->mp = NULL; 114608057504Sxy150489 } 114708057504Sxy150489 114808057504Sxy150489 /* Free the TxSwPackets */ 114925f2d433Sxy150489 e1000g_free_tx_swpkt(packet); 115008057504Sxy150489 115125f2d433Sxy150489 packet = (p_tx_sw_packet_t) 115208057504Sxy150489 QUEUE_GET_NEXT(&pending_list, &packet->Link); 115308057504Sxy150489 } 115408057504Sxy150489 115508057504Sxy150489 /* Return the TxSwPackets back to the FreeList */ 115608057504Sxy150489 mutex_enter(&tx_ring->freelist_lock); 115708057504Sxy150489 QUEUE_APPEND(&tx_ring->free_list, &pending_list); 115808057504Sxy150489 mutex_exit(&tx_ring->freelist_lock); 115908057504Sxy150489 116047b7744cSyy150190 if (mp != NULL) 116147b7744cSyy150190 freemsgchain(mp); 116247b7744cSyy150190 116308057504Sxy150489 return (desc_count); 116408057504Sxy150489 } 116508057504Sxy150489 /* 116608057504Sxy150489 * 82544 Coexistence issue workaround: 116708057504Sxy150489 * There are 2 issues. 116808057504Sxy150489 * 1. If a 32 bit split completion happens from P64H2 and another 116908057504Sxy150489 * agent drives a 64 bit request/split completion after ONLY 117008057504Sxy150489 * 1 idle clock (BRCM/Emulex/Adaptec fiber channel cards) then 117108057504Sxy150489 * 82544 has a problem where in to clock all the data in, it 117208057504Sxy150489 * looks at REQ64# signal and since it has changed so fast (i.e. 1 117308057504Sxy150489 * idle clock turn around), it will fail to clock all the data in. 117408057504Sxy150489 * Data coming from certain ending addresses has exposure to this issue. 117508057504Sxy150489 * 117608057504Sxy150489 * To detect this issue, following equation can be used... 117708057504Sxy150489 * SIZE[3:0] + ADDR[2:0] = SUM[3:0]. 117808057504Sxy150489 * If SUM[3:0] is in between 1 to 4, we will have this issue. 117908057504Sxy150489 * 118008057504Sxy150489 * ROOT CAUSE: 118108057504Sxy150489 * The erratum involves the 82544 PCIX elasticity FIFO implementations as 118208057504Sxy150489 * 64-bit FIFO's and flushing of the final partial-bytes corresponding 118308057504Sxy150489 * to the end of a requested read burst. Under a specific burst condition 118408057504Sxy150489 * of ending-data alignment and 32-byte split-completions, the final 118508057504Sxy150489 * byte(s) of split-completion data require an extra clock cycle to flush 118608057504Sxy150489 * into 64-bit FIFO orientation. An incorrect logic dependency on the 118708057504Sxy150489 * REQ64# signal occurring during during this clock cycle may cause the 118808057504Sxy150489 * residual byte(s) to be lost, thereby rendering the internal DMA client 118908057504Sxy150489 * forever awaiting the final byte(s) for an outbound data-fetch. The 119008057504Sxy150489 * erratum is confirmed to *only* occur if certain subsequent external 119108057504Sxy150489 * 64-bit PCIX bus transactions occur immediately (minimum possible bus 119208057504Sxy150489 * turn- around) following the odd-aligned 32-bit split-completion 119308057504Sxy150489 * containing the final byte(s). Intel has confirmed that this has been 119408057504Sxy150489 * seen only with chipset/bridges which have the capability to provide 119508057504Sxy150489 * 32-bit split-completion data, and in the presence of newer PCIX bus 119608057504Sxy150489 * agents which fully-optimize the inter-transaction turn-around (zero 119708057504Sxy150489 * additional initiator latency when pre-granted bus ownership). 119808057504Sxy150489 * 119908057504Sxy150489 * This issue does not exist in PCI bus mode, when any agent is operating 120008057504Sxy150489 * in 32 bit only mode or on chipsets that do not do 32 bit split 120108057504Sxy150489 * completions for 64 bit read requests (Serverworks chipsets). P64H2 does 120208057504Sxy150489 * 32 bit split completions for any read request that has bit 2 set to 1 120308057504Sxy150489 * for the requested address and read request size is more than 8 bytes. 120408057504Sxy150489 * 120508057504Sxy150489 * 2. Another issue is related to 82544 driving DACs under the similar 120608057504Sxy150489 * scenario (32 bit split completion followed by 64 bit transaction with 120708057504Sxy150489 * only 1 cycle turnaround). This issue is still being root caused. We 120808057504Sxy150489 * think that both of these issues can be avoided if following workaround 120908057504Sxy150489 * is implemented. It seems DAC issues is related to ending addresses being 121008057504Sxy150489 * 0x9, 0xA, 0xB, 0xC and hence ending up at odd boundaries in elasticity 121108057504Sxy150489 * FIFO which does not get flushed due to REQ64# dependency. We will only 121208057504Sxy150489 * know the full story after it has been simulated successfully by HW team. 121308057504Sxy150489 * 121408057504Sxy150489 * WORKAROUND: 121508057504Sxy150489 * Make sure we do not have ending address as 1,2,3,4(Hang) or 9,a,b,c(DAC) 121608057504Sxy150489 */ 121708057504Sxy150489 static uint32_t 121825f2d433Sxy150489 e1000g_fill_82544_desc(uint64_t address, 121925f2d433Sxy150489 size_t length, p_desc_array_t desc_array) 122008057504Sxy150489 { 122108057504Sxy150489 /* 122208057504Sxy150489 * Since issue is sensitive to length and address. 122308057504Sxy150489 * Let us first check the address... 122408057504Sxy150489 */ 122508057504Sxy150489 uint32_t safe_terminator; 122608057504Sxy150489 122725f2d433Sxy150489 if (length <= 4) { 122825f2d433Sxy150489 desc_array->descriptor[0].address = address; 1229fe62dec3SChen-Liang Xu desc_array->descriptor[0].length = (uint32_t)length; 123025f2d433Sxy150489 desc_array->elements = 1; 123125f2d433Sxy150489 return (desc_array->elements); 123208057504Sxy150489 } 123308057504Sxy150489 safe_terminator = 123425f2d433Sxy150489 (uint32_t)((((uint32_t)address & 0x7) + 123525f2d433Sxy150489 (length & 0xF)) & 0xF); 123608057504Sxy150489 /* 123708057504Sxy150489 * if it does not fall between 0x1 to 0x4 and 0x9 to 0xC then 123808057504Sxy150489 * return 123908057504Sxy150489 */ 124008057504Sxy150489 if (safe_terminator == 0 || 124125f2d433Sxy150489 (safe_terminator > 4 && safe_terminator < 9) || 124208057504Sxy150489 (safe_terminator > 0xC && safe_terminator <= 0xF)) { 124325f2d433Sxy150489 desc_array->descriptor[0].address = address; 1244fe62dec3SChen-Liang Xu desc_array->descriptor[0].length = (uint32_t)length; 124525f2d433Sxy150489 desc_array->elements = 1; 124625f2d433Sxy150489 return (desc_array->elements); 124708057504Sxy150489 } 124808057504Sxy150489 124925f2d433Sxy150489 desc_array->descriptor[0].address = address; 125025f2d433Sxy150489 desc_array->descriptor[0].length = length - 4; 125125f2d433Sxy150489 desc_array->descriptor[1].address = address + (length - 4); 125225f2d433Sxy150489 desc_array->descriptor[1].length = 4; 125325f2d433Sxy150489 desc_array->elements = 2; 125425f2d433Sxy150489 return (desc_array->elements); 125508057504Sxy150489 } 125608057504Sxy150489 125708057504Sxy150489 static int 125825f2d433Sxy150489 e1000g_tx_copy(e1000g_tx_ring_t *tx_ring, p_tx_sw_packet_t packet, 1259c7770590Smx205022 mblk_t *mp, boolean_t tx_undersize_flag) 126008057504Sxy150489 { 126108057504Sxy150489 size_t len; 126208057504Sxy150489 size_t len1; 126308057504Sxy150489 dma_buffer_t *tx_buf; 126408057504Sxy150489 mblk_t *nmp; 126508057504Sxy150489 boolean_t finished; 126608057504Sxy150489 int desc_count; 126708057504Sxy150489 126808057504Sxy150489 desc_count = 0; 126908057504Sxy150489 tx_buf = packet->tx_buf; 127008057504Sxy150489 len = MBLKL(mp); 127108057504Sxy150489 127208057504Sxy150489 ASSERT((tx_buf->len + len) <= tx_buf->size); 127308057504Sxy150489 127408057504Sxy150489 if (len > 0) { 127508057504Sxy150489 bcopy(mp->b_rptr, 127608057504Sxy150489 tx_buf->address + tx_buf->len, 127708057504Sxy150489 len); 127808057504Sxy150489 tx_buf->len += len; 127908057504Sxy150489 128008057504Sxy150489 packet->num_mblk_frag++; 128108057504Sxy150489 } 128208057504Sxy150489 128308057504Sxy150489 nmp = mp->b_cont; 128408057504Sxy150489 if (nmp == NULL) { 128508057504Sxy150489 finished = B_TRUE; 128608057504Sxy150489 } else { 128708057504Sxy150489 len1 = MBLKL(nmp); 128808057504Sxy150489 if ((tx_buf->len + len1) > tx_buf->size) 128908057504Sxy150489 finished = B_TRUE; 1290c7770590Smx205022 else if (tx_undersize_flag) 129108057504Sxy150489 finished = B_FALSE; 129225f2d433Sxy150489 else if (len1 > tx_ring->adapter->tx_bcopy_thresh) 129308057504Sxy150489 finished = B_TRUE; 129408057504Sxy150489 else 129508057504Sxy150489 finished = B_FALSE; 129608057504Sxy150489 } 129708057504Sxy150489 129808057504Sxy150489 if (finished) { 129925f2d433Sxy150489 E1000G_DEBUG_STAT_COND(tx_ring->stat_multi_copy, 130025f2d433Sxy150489 (tx_buf->len > len)); 130108057504Sxy150489 130208057504Sxy150489 /* 130308057504Sxy150489 * If the packet is smaller than 64 bytes, which is the 130408057504Sxy150489 * minimum ethernet packet size, pad the packet to make 130508057504Sxy150489 * it at least 60 bytes. The hardware will add 4 bytes 130608057504Sxy150489 * for CRC. 130708057504Sxy150489 */ 1308c7770590Smx205022 if (tx_undersize_flag) { 13099ce7e93cScc210113 ASSERT(tx_buf->len < ETHERMIN); 131008057504Sxy150489 131108057504Sxy150489 bzero(tx_buf->address + tx_buf->len, 13129ce7e93cScc210113 ETHERMIN - tx_buf->len); 13139ce7e93cScc210113 tx_buf->len = ETHERMIN; 131408057504Sxy150489 } 131508057504Sxy150489 131608057504Sxy150489 #ifdef __sparc 131725f2d433Sxy150489 if (packet->dma_type == USE_DVMA) 131808057504Sxy150489 dvma_sync(tx_buf->dma_handle, 0, DDI_DMA_SYNC_FORDEV); 131925f2d433Sxy150489 else 132008057504Sxy150489 (void) ddi_dma_sync(tx_buf->dma_handle, 0, 132108057504Sxy150489 tx_buf->len, DDI_DMA_SYNC_FORDEV); 132225f2d433Sxy150489 #else 132325f2d433Sxy150489 (void) ddi_dma_sync(tx_buf->dma_handle, 0, 132425f2d433Sxy150489 tx_buf->len, DDI_DMA_SYNC_FORDEV); 132525f2d433Sxy150489 #endif 132608057504Sxy150489 132708057504Sxy150489 packet->data_transfer_type = USE_BCOPY; 132808057504Sxy150489 132925f2d433Sxy150489 desc_count = e1000g_fill_tx_desc(tx_ring, 133008057504Sxy150489 packet, 133108057504Sxy150489 tx_buf->dma_address, 133208057504Sxy150489 tx_buf->len); 133308057504Sxy150489 133408057504Sxy150489 if (desc_count <= 0) 133508057504Sxy150489 return (-1); 133608057504Sxy150489 } 133708057504Sxy150489 133808057504Sxy150489 return (desc_count); 133908057504Sxy150489 } 134008057504Sxy150489 134108057504Sxy150489 static int 134225f2d433Sxy150489 e1000g_tx_bind(e1000g_tx_ring_t *tx_ring, p_tx_sw_packet_t packet, mblk_t *mp) 134308057504Sxy150489 { 134408057504Sxy150489 int j; 134508057504Sxy150489 int mystat; 134608057504Sxy150489 size_t len; 134708057504Sxy150489 ddi_dma_cookie_t dma_cookie; 134808057504Sxy150489 uint_t ncookies; 134908057504Sxy150489 int desc_count; 135008057504Sxy150489 uint32_t desc_total; 135108057504Sxy150489 135208057504Sxy150489 desc_total = 0; 135308057504Sxy150489 len = MBLKL(mp); 135408057504Sxy150489 135508057504Sxy150489 /* 135608057504Sxy150489 * ddi_dma_addr_bind_handle() allocates DMA resources for a 135708057504Sxy150489 * memory object such that a device can perform DMA to or from 135808057504Sxy150489 * the object. DMA resources are allocated considering the 135908057504Sxy150489 * device's DMA attributes as expressed by ddi_dma_attr(9S) 136008057504Sxy150489 * (see ddi_dma_alloc_handle(9F)). 136108057504Sxy150489 * 136208057504Sxy150489 * ddi_dma_addr_bind_handle() fills in the first DMA cookie 136308057504Sxy150489 * pointed to by cookiep with the appropriate address, length, 136408057504Sxy150489 * and bus type. *ccountp is set to the number of DMA cookies 136508057504Sxy150489 * representing this DMA object. Subsequent DMA cookies must be 136608057504Sxy150489 * retrieved by calling ddi_dma_nextcookie(9F) the number of 136708057504Sxy150489 * times specified by *countp - 1. 136808057504Sxy150489 */ 136908057504Sxy150489 switch (packet->dma_type) { 137008057504Sxy150489 #ifdef __sparc 137108057504Sxy150489 case USE_DVMA: 137208057504Sxy150489 dvma_kaddr_load(packet->tx_dma_handle, 137308057504Sxy150489 (caddr_t)mp->b_rptr, len, 0, &dma_cookie); 137408057504Sxy150489 137508057504Sxy150489 dvma_sync(packet->tx_dma_handle, 0, 137608057504Sxy150489 DDI_DMA_SYNC_FORDEV); 137708057504Sxy150489 137808057504Sxy150489 ncookies = 1; 137908057504Sxy150489 packet->data_transfer_type = USE_DVMA; 138008057504Sxy150489 break; 138108057504Sxy150489 #endif 138208057504Sxy150489 case USE_DMA: 138308057504Sxy150489 if ((mystat = ddi_dma_addr_bind_handle( 138408057504Sxy150489 packet->tx_dma_handle, NULL, 138508057504Sxy150489 (caddr_t)mp->b_rptr, len, 138608057504Sxy150489 DDI_DMA_WRITE | DDI_DMA_STREAMING, 138708057504Sxy150489 DDI_DMA_DONTWAIT, 0, &dma_cookie, 138808057504Sxy150489 &ncookies)) != DDI_DMA_MAPPED) { 138908057504Sxy150489 139025f2d433Sxy150489 e1000g_log(tx_ring->adapter, CE_WARN, 139108057504Sxy150489 "Couldn't bind mblk buffer to Tx DMA handle: " 139208057504Sxy150489 "return: %X, Pkt: %X\n", 139308057504Sxy150489 mystat, packet); 139408057504Sxy150489 return (-1); 139508057504Sxy150489 } 139608057504Sxy150489 139708057504Sxy150489 /* 139808057504Sxy150489 * An implicit ddi_dma_sync() is done when the 139908057504Sxy150489 * ddi_dma_addr_bind_handle() is called. So we 140008057504Sxy150489 * don't need to explicitly call ddi_dma_sync() 140108057504Sxy150489 * here any more. 140208057504Sxy150489 */ 140308057504Sxy150489 ASSERT(ncookies); 140425f2d433Sxy150489 E1000G_DEBUG_STAT_COND(tx_ring->stat_multi_cookie, 140525f2d433Sxy150489 (ncookies > 1)); 140608057504Sxy150489 140708057504Sxy150489 /* 140808057504Sxy150489 * The data_transfer_type value must be set after the handle 140925f2d433Sxy150489 * has been bound, for it will be used in e1000g_free_tx_swpkt() 141008057504Sxy150489 * to decide whether we need to unbind the handle. 141108057504Sxy150489 */ 141208057504Sxy150489 packet->data_transfer_type = USE_DMA; 141308057504Sxy150489 break; 141408057504Sxy150489 default: 141508057504Sxy150489 ASSERT(B_FALSE); 141608057504Sxy150489 break; 141708057504Sxy150489 } 141808057504Sxy150489 141908057504Sxy150489 packet->num_mblk_frag++; 142008057504Sxy150489 142108057504Sxy150489 /* 142208057504Sxy150489 * Each address could span thru multpile cookie.. 142308057504Sxy150489 * Each cookie will have one descriptor 142408057504Sxy150489 */ 142508057504Sxy150489 for (j = ncookies; j != 0; j--) { 142608057504Sxy150489 142725f2d433Sxy150489 desc_count = e1000g_fill_tx_desc(tx_ring, 142808057504Sxy150489 packet, 142908057504Sxy150489 dma_cookie.dmac_laddress, 143008057504Sxy150489 dma_cookie.dmac_size); 143108057504Sxy150489 143208057504Sxy150489 if (desc_count <= 0) 143308057504Sxy150489 return (-1); 143408057504Sxy150489 143508057504Sxy150489 desc_total += desc_count; 143608057504Sxy150489 143708057504Sxy150489 /* 143808057504Sxy150489 * ddi_dma_nextcookie() retrieves subsequent DMA 143908057504Sxy150489 * cookies for a DMA object. 144008057504Sxy150489 * ddi_dma_nextcookie() fills in the 144108057504Sxy150489 * ddi_dma_cookie(9S) structure pointed to by 144208057504Sxy150489 * cookiep. The ddi_dma_cookie(9S) structure 144308057504Sxy150489 * must be allocated prior to calling 144408057504Sxy150489 * ddi_dma_nextcookie(). The DMA cookie count 144508057504Sxy150489 * returned by ddi_dma_buf_bind_handle(9F), 144608057504Sxy150489 * ddi_dma_addr_bind_handle(9F), or 144708057504Sxy150489 * ddi_dma_getwin(9F) indicates the number of DMA 144808057504Sxy150489 * cookies a DMA object consists of. If the 144908057504Sxy150489 * resulting cookie count, N, is larger than 1, 145008057504Sxy150489 * ddi_dma_nextcookie() must be called N-1 times 145108057504Sxy150489 * to retrieve all DMA cookies. 145208057504Sxy150489 */ 145308057504Sxy150489 if (j > 1) { 145408057504Sxy150489 ddi_dma_nextcookie(packet->tx_dma_handle, 145508057504Sxy150489 &dma_cookie); 145608057504Sxy150489 } 145708057504Sxy150489 } 145808057504Sxy150489 145908057504Sxy150489 return (desc_total); 146008057504Sxy150489 } 146108057504Sxy150489 146208057504Sxy150489 static void 1463c7770590Smx205022 e1000g_fill_context_descriptor(context_data_t *cur_context, 1464c7770590Smx205022 struct e1000_context_desc *context_desc) 146508057504Sxy150489 { 1466c7770590Smx205022 if (cur_context->cksum_flags & HCK_IPV4_HDRCKSUM) { 1467c7770590Smx205022 context_desc->lower_setup.ip_fields.ipcss = 1468c7770590Smx205022 cur_context->ether_header_size; 1469c7770590Smx205022 context_desc->lower_setup.ip_fields.ipcso = 1470c7770590Smx205022 cur_context->ether_header_size + 147108057504Sxy150489 offsetof(struct ip, ip_sum); 1472c7770590Smx205022 context_desc->lower_setup.ip_fields.ipcse = 1473c7770590Smx205022 cur_context->ether_header_size + 1474c7770590Smx205022 cur_context->cksum_start - 1; 147508057504Sxy150489 } else 1476c7770590Smx205022 context_desc->lower_setup.ip_config = 0; 147708057504Sxy150489 1478c7770590Smx205022 if (cur_context->cksum_flags & HCK_PARTIALCKSUM) { 147908057504Sxy150489 /* 148008057504Sxy150489 * The packet with same protocol has the following 148108057504Sxy150489 * stuff and start offset: 148208057504Sxy150489 * | Protocol | Stuff | Start | Checksum 148308057504Sxy150489 * | | Offset | Offset | Enable 148408057504Sxy150489 * | IPv4 + TCP | 0x24 | 0x14 | Yes 148508057504Sxy150489 * | IPv4 + UDP | 0x1A | 0x14 | Yes 148608057504Sxy150489 * | IPv6 + TCP | 0x20 | 0x10 | No 148708057504Sxy150489 * | IPv6 + UDP | 0x14 | 0x10 | No 148808057504Sxy150489 */ 1489c7770590Smx205022 context_desc->upper_setup.tcp_fields.tucss = 1490c7770590Smx205022 cur_context->cksum_start + cur_context->ether_header_size; 1491c7770590Smx205022 context_desc->upper_setup.tcp_fields.tucso = 1492c7770590Smx205022 cur_context->cksum_stuff + cur_context->ether_header_size; 1493c7770590Smx205022 context_desc->upper_setup.tcp_fields.tucse = 0; 149408057504Sxy150489 } else 1495c7770590Smx205022 context_desc->upper_setup.tcp_config = 0; 149608057504Sxy150489 1497c7770590Smx205022 if (cur_context->lso_flag) { 1498c7770590Smx205022 context_desc->tcp_seg_setup.fields.mss = cur_context->mss; 1499c7770590Smx205022 context_desc->tcp_seg_setup.fields.hdr_len = 1500c7770590Smx205022 cur_context->hdr_len; 150108057504Sxy150489 /* 1502c7770590Smx205022 * workaround for 82546EB errata 23, status-writeback 1503c7770590Smx205022 * reporting (RS) should not be set on context or 1504c7770590Smx205022 * Null descriptors 150508057504Sxy150489 */ 1506c7770590Smx205022 context_desc->cmd_and_length = E1000_TXD_CMD_DEXT 1507c7770590Smx205022 | E1000_TXD_CMD_TSE | E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP 1508c7770590Smx205022 | E1000_TXD_DTYP_C | cur_context->pay_len; 1509c7770590Smx205022 } else { 1510c7770590Smx205022 context_desc->cmd_and_length = E1000_TXD_CMD_DEXT 1511c7770590Smx205022 | E1000_TXD_DTYP_C; 1512c7770590Smx205022 /* 1513c7770590Smx205022 * Zero out the options for TCP Segmentation Offload 1514c7770590Smx205022 */ 1515c7770590Smx205022 context_desc->tcp_seg_setup.data = 0; 1516c7770590Smx205022 } 151708057504Sxy150489 } 151808057504Sxy150489 151908057504Sxy150489 static int 152025f2d433Sxy150489 e1000g_fill_tx_desc(e1000g_tx_ring_t *tx_ring, 152125f2d433Sxy150489 p_tx_sw_packet_t packet, uint64_t address, size_t size) 152208057504Sxy150489 { 152325f2d433Sxy150489 struct e1000_hw *hw = &tx_ring->adapter->shared; 152425f2d433Sxy150489 p_sw_desc_t desc; 152508057504Sxy150489 152625f2d433Sxy150489 if (hw->mac.type == e1000_82544) { 152725f2d433Sxy150489 if (hw->bus.type == e1000_bus_type_pcix) 152825f2d433Sxy150489 return (e1000g_tx_workaround_PCIX_82544(packet, 152925f2d433Sxy150489 address, size)); 153008057504Sxy150489 153125f2d433Sxy150489 if (size > JUMBO_FRAG_LENGTH) 153225f2d433Sxy150489 return (e1000g_tx_workaround_jumbo_82544(packet, 153325f2d433Sxy150489 address, size)); 153425f2d433Sxy150489 } 153508057504Sxy150489 153608057504Sxy150489 ASSERT(packet->num_desc < MAX_TX_DESC_PER_PACKET); 153708057504Sxy150489 153808057504Sxy150489 desc = &packet->desc[packet->num_desc]; 153925f2d433Sxy150489 desc->address = address; 1540fe62dec3SChen-Liang Xu desc->length = (uint32_t)size; 154108057504Sxy150489 154208057504Sxy150489 packet->num_desc++; 154308057504Sxy150489 154425f2d433Sxy150489 return (1); 154508057504Sxy150489 } 154608057504Sxy150489 154708057504Sxy150489 static int 154825f2d433Sxy150489 e1000g_tx_workaround_PCIX_82544(p_tx_sw_packet_t packet, 154925f2d433Sxy150489 uint64_t address, size_t size) 155008057504Sxy150489 { 155125f2d433Sxy150489 p_sw_desc_t desc; 155208057504Sxy150489 int desc_count; 155308057504Sxy150489 long size_left; 155408057504Sxy150489 size_t len; 155508057504Sxy150489 uint32_t counter; 155608057504Sxy150489 uint32_t array_elements; 155725f2d433Sxy150489 desc_array_t desc_array; 155808057504Sxy150489 155908057504Sxy150489 /* 156008057504Sxy150489 * Coexist Workaround for cordova: RP: 07/04/03 156108057504Sxy150489 * 156208057504Sxy150489 * RP: ERRATA: Workaround ISSUE: 156308057504Sxy150489 * 8kb_buffer_Lockup CONTROLLER: Cordova Breakup 156408057504Sxy150489 * Eachbuffer in to 8kb pieces until the 156508057504Sxy150489 * remainder is < 8kb 156608057504Sxy150489 */ 156708057504Sxy150489 size_left = size; 156808057504Sxy150489 desc_count = 0; 156908057504Sxy150489 157008057504Sxy150489 while (size_left > 0) { 157108057504Sxy150489 if (size_left > MAX_TX_BUF_SIZE) 157208057504Sxy150489 len = MAX_TX_BUF_SIZE; 157308057504Sxy150489 else 157408057504Sxy150489 len = size_left; 157508057504Sxy150489 157608057504Sxy150489 array_elements = e1000g_fill_82544_desc(address, 157708057504Sxy150489 len, &desc_array); 157808057504Sxy150489 157908057504Sxy150489 for (counter = 0; counter < array_elements; counter++) { 158008057504Sxy150489 ASSERT(packet->num_desc < MAX_TX_DESC_PER_PACKET); 158108057504Sxy150489 /* 158208057504Sxy150489 * Put in the buffer address 158308057504Sxy150489 */ 158408057504Sxy150489 desc = &packet->desc[packet->num_desc]; 158508057504Sxy150489 158625f2d433Sxy150489 desc->address = 158725f2d433Sxy150489 desc_array.descriptor[counter].address; 158825f2d433Sxy150489 desc->length = 158925f2d433Sxy150489 desc_array.descriptor[counter].length; 159008057504Sxy150489 159108057504Sxy150489 packet->num_desc++; 159208057504Sxy150489 desc_count++; 159308057504Sxy150489 } /* for */ 159408057504Sxy150489 159508057504Sxy150489 /* 159608057504Sxy150489 * Update the buffer address and length 159708057504Sxy150489 */ 159808057504Sxy150489 address += MAX_TX_BUF_SIZE; 159908057504Sxy150489 size_left -= MAX_TX_BUF_SIZE; 160008057504Sxy150489 } /* while */ 160108057504Sxy150489 160208057504Sxy150489 return (desc_count); 160308057504Sxy150489 } 160408057504Sxy150489 160508057504Sxy150489 static int 160625f2d433Sxy150489 e1000g_tx_workaround_jumbo_82544(p_tx_sw_packet_t packet, 160725f2d433Sxy150489 uint64_t address, size_t size) 160808057504Sxy150489 { 160925f2d433Sxy150489 p_sw_desc_t desc; 161008057504Sxy150489 int desc_count; 161108057504Sxy150489 long size_left; 161208057504Sxy150489 uint32_t offset; 161308057504Sxy150489 161408057504Sxy150489 /* 161508057504Sxy150489 * Workaround for Jumbo Frames on Cordova 161608057504Sxy150489 * PSD 06/01/2001 161708057504Sxy150489 */ 161808057504Sxy150489 size_left = size; 161908057504Sxy150489 desc_count = 0; 162008057504Sxy150489 offset = 0; 162108057504Sxy150489 while (size_left > 0) { 162208057504Sxy150489 ASSERT(packet->num_desc < MAX_TX_DESC_PER_PACKET); 162308057504Sxy150489 162408057504Sxy150489 desc = &packet->desc[packet->num_desc]; 162508057504Sxy150489 162625f2d433Sxy150489 desc->address = address + offset; 162708057504Sxy150489 162808057504Sxy150489 if (size_left > JUMBO_FRAG_LENGTH) 162925f2d433Sxy150489 desc->length = JUMBO_FRAG_LENGTH; 163008057504Sxy150489 else 1631fe62dec3SChen-Liang Xu desc->length = (uint32_t)size_left; 163208057504Sxy150489 163308057504Sxy150489 packet->num_desc++; 163408057504Sxy150489 desc_count++; 163508057504Sxy150489 163625f2d433Sxy150489 offset += desc->length; 163708057504Sxy150489 size_left -= JUMBO_FRAG_LENGTH; 163808057504Sxy150489 } 163908057504Sxy150489 164008057504Sxy150489 return (desc_count); 164108057504Sxy150489 } 164208057504Sxy150489 164325f2d433Sxy150489 #pragma inline(e1000g_82547_tx_move_tail_work) 164425f2d433Sxy150489 164508057504Sxy150489 static void 164608057504Sxy150489 e1000g_82547_tx_move_tail_work(e1000g_tx_ring_t *tx_ring) 164708057504Sxy150489 { 164825f2d433Sxy150489 struct e1000_hw *hw; 164908057504Sxy150489 uint16_t hw_tdt; 165008057504Sxy150489 uint16_t sw_tdt; 165108057504Sxy150489 struct e1000_tx_desc *tx_desc; 165208057504Sxy150489 uint16_t length = 0; 165308057504Sxy150489 boolean_t eop = B_FALSE; 165408057504Sxy150489 struct e1000g *Adapter; 165508057504Sxy150489 165608057504Sxy150489 Adapter = tx_ring->adapter; 165725f2d433Sxy150489 hw = &Adapter->shared; 165808057504Sxy150489 1659592a4d85Scc210113 hw_tdt = E1000_READ_REG(hw, E1000_TDT(0)); 166008057504Sxy150489 sw_tdt = tx_ring->tbd_next - tx_ring->tbd_first; 166108057504Sxy150489 166208057504Sxy150489 while (hw_tdt != sw_tdt) { 166308057504Sxy150489 tx_desc = &(tx_ring->tbd_first[hw_tdt]); 166408057504Sxy150489 length += tx_desc->lower.flags.length; 166508057504Sxy150489 eop = tx_desc->lower.data & E1000_TXD_CMD_EOP; 166625f2d433Sxy150489 if (++hw_tdt == Adapter->tx_desc_num) 166708057504Sxy150489 hw_tdt = 0; 166808057504Sxy150489 166908057504Sxy150489 if (eop) { 167008057504Sxy150489 if ((Adapter->link_duplex == HALF_DUPLEX) && 167125f2d433Sxy150489 (e1000_fifo_workaround_82547(hw, length) 167225f2d433Sxy150489 != E1000_SUCCESS)) { 167308057504Sxy150489 if (tx_ring->timer_enable_82547) { 167408057504Sxy150489 ASSERT(tx_ring->timer_id_82547 == 0); 167508057504Sxy150489 tx_ring->timer_id_82547 = 167608057504Sxy150489 timeout(e1000g_82547_timeout, 16775633182fSyy150190 (void *)tx_ring, 167808057504Sxy150489 drv_usectohz(10000)); 167908057504Sxy150489 } 168008057504Sxy150489 return; 168108057504Sxy150489 168208057504Sxy150489 } else { 1683592a4d85Scc210113 E1000_WRITE_REG(hw, E1000_TDT(0), hw_tdt); 168425f2d433Sxy150489 e1000_update_tx_fifo_head_82547(hw, length); 168508057504Sxy150489 length = 0; 168608057504Sxy150489 } 168708057504Sxy150489 } 168808057504Sxy150489 } 168908057504Sxy150489 } 169008057504Sxy150489 169108057504Sxy150489 static void 169208057504Sxy150489 e1000g_82547_timeout(void *arg) 169308057504Sxy150489 { 169408057504Sxy150489 e1000g_tx_ring_t *tx_ring; 169508057504Sxy150489 169608057504Sxy150489 tx_ring = (e1000g_tx_ring_t *)arg; 169708057504Sxy150489 169808057504Sxy150489 mutex_enter(&tx_ring->tx_lock); 169908057504Sxy150489 170008057504Sxy150489 tx_ring->timer_id_82547 = 0; 170108057504Sxy150489 e1000g_82547_tx_move_tail_work(tx_ring); 170208057504Sxy150489 170308057504Sxy150489 mutex_exit(&tx_ring->tx_lock); 170408057504Sxy150489 } 170508057504Sxy150489 170608057504Sxy150489 static void 170708057504Sxy150489 e1000g_82547_tx_move_tail(e1000g_tx_ring_t *tx_ring) 170808057504Sxy150489 { 170908057504Sxy150489 timeout_id_t tid; 171008057504Sxy150489 171108057504Sxy150489 ASSERT(MUTEX_HELD(&tx_ring->tx_lock)); 171208057504Sxy150489 171308057504Sxy150489 tid = tx_ring->timer_id_82547; 171408057504Sxy150489 tx_ring->timer_id_82547 = 0; 171508057504Sxy150489 if (tid != 0) { 171608057504Sxy150489 tx_ring->timer_enable_82547 = B_FALSE; 171708057504Sxy150489 mutex_exit(&tx_ring->tx_lock); 171808057504Sxy150489 171908057504Sxy150489 (void) untimeout(tid); 172008057504Sxy150489 172108057504Sxy150489 mutex_enter(&tx_ring->tx_lock); 172208057504Sxy150489 } 172308057504Sxy150489 tx_ring->timer_enable_82547 = B_TRUE; 172408057504Sxy150489 e1000g_82547_tx_move_tail_work(tx_ring); 172508057504Sxy150489 } 1726*42cc51e0SRobert Mustacchi 1727*42cc51e0SRobert Mustacchi /* 1728*42cc51e0SRobert Mustacchi * This is part of a workaround for the I219, see e1000g_flush_desc_rings() for 1729*42cc51e0SRobert Mustacchi * more information. 1730*42cc51e0SRobert Mustacchi * 1731*42cc51e0SRobert Mustacchi * We need to clear any potential pending descriptors from the tx_ring. As 1732*42cc51e0SRobert Mustacchi * we're about to reset the device, we don't care about the data that we give it 1733*42cc51e0SRobert Mustacchi * itself. 1734*42cc51e0SRobert Mustacchi */ 1735*42cc51e0SRobert Mustacchi void 1736*42cc51e0SRobert Mustacchi e1000g_flush_tx_ring(struct e1000g *Adapter) 1737*42cc51e0SRobert Mustacchi { 1738*42cc51e0SRobert Mustacchi struct e1000_hw *hw = &Adapter->shared; 1739*42cc51e0SRobert Mustacchi e1000g_tx_ring_t *tx_ring = &Adapter->tx_ring[0]; 1740*42cc51e0SRobert Mustacchi uint32_t tctl, txd_lower = E1000_TXD_CMD_IFCS; 1741*42cc51e0SRobert Mustacchi uint16_t size = 512; 1742*42cc51e0SRobert Mustacchi struct e1000_tx_desc *desc; 1743*42cc51e0SRobert Mustacchi 1744*42cc51e0SRobert Mustacchi tctl = E1000_READ_REG(hw, E1000_TCTL); 1745*42cc51e0SRobert Mustacchi E1000_WRITE_REG(hw, E1000_TCTL, tctl | E1000_TCTL_EN); 1746*42cc51e0SRobert Mustacchi 1747*42cc51e0SRobert Mustacchi desc = tx_ring->tbd_next; 1748*42cc51e0SRobert Mustacchi if (tx_ring->tbd_next == tx_ring->tbd_last) 1749*42cc51e0SRobert Mustacchi tx_ring->tbd_next = tx_ring->tbd_first; 1750*42cc51e0SRobert Mustacchi else 1751*42cc51e0SRobert Mustacchi tx_ring->tbd_next++; 1752*42cc51e0SRobert Mustacchi 1753*42cc51e0SRobert Mustacchi /* We just need to set any valid address, so we use the ring itself */ 1754*42cc51e0SRobert Mustacchi desc->buffer_addr = tx_ring->tbd_dma_addr; 1755*42cc51e0SRobert Mustacchi desc->lower.data = LE_32(txd_lower | size); 1756*42cc51e0SRobert Mustacchi desc->upper.data = 0; 1757*42cc51e0SRobert Mustacchi 1758*42cc51e0SRobert Mustacchi (void) ddi_dma_sync(tx_ring->tbd_dma_handle, 1759*42cc51e0SRobert Mustacchi 0, 0, DDI_DMA_SYNC_FORDEV); 1760*42cc51e0SRobert Mustacchi E1000_WRITE_REG(hw, E1000_TDT(0), 1761*42cc51e0SRobert Mustacchi (uint32_t)(tx_ring->tbd_next - tx_ring->tbd_first)); 1762*42cc51e0SRobert Mustacchi (void) E1000_READ_REG(hw, E1000_STATUS); 1763*42cc51e0SRobert Mustacchi usec_delay(250); 1764*42cc51e0SRobert Mustacchi } 1765