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 * 95882Syy150190 * Copyright(c) 1999 - 2008 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 /* 225882Syy150190 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 233526Sxy150489 * Use is subject to license terms of the CDDLv1. 243526Sxy150489 */ 253526Sxy150489 263526Sxy150489 #pragma ident "%Z%%M% %I% %E% SMI" 273526Sxy150489 283526Sxy150489 /* 293526Sxy150489 * ********************************************************************** 303526Sxy150489 * * 313526Sxy150489 * Module Name: * 323526Sxy150489 * e1000g_tx.c * 333526Sxy150489 * * 343526Sxy150489 * Abstract: * 354919Sxy150489 * This file contains some routines that take care of Transmit, * 364919Sxy150489 * make the hardware to send the data pointed by the packet out * 374919Sxy150489 * on to the physical medium. * 383526Sxy150489 * * 393526Sxy150489 * ********************************************************************** 403526Sxy150489 */ 413526Sxy150489 423526Sxy150489 #include "e1000g_sw.h" 433526Sxy150489 #include "e1000g_debug.h" 443526Sxy150489 453526Sxy150489 static boolean_t e1000g_send(struct e1000g *, mblk_t *); 464919Sxy150489 static int e1000g_tx_copy(e1000g_tx_ring_t *, 47*6986Smx205022 p_tx_sw_packet_t, mblk_t *, boolean_t); 484919Sxy150489 static int e1000g_tx_bind(e1000g_tx_ring_t *, 494919Sxy150489 p_tx_sw_packet_t, mblk_t *); 50*6986Smx205022 static boolean_t e1000g_retreive_context(mblk_t *, context_data_t *, size_t); 51*6986Smx205022 static boolean_t e1000g_check_context(e1000g_tx_ring_t *, context_data_t *); 523526Sxy150489 static int e1000g_fill_tx_ring(e1000g_tx_ring_t *, LIST_DESCRIBER *, 53*6986Smx205022 context_data_t *); 54*6986Smx205022 static void e1000g_fill_context_descriptor(context_data_t *, 553526Sxy150489 struct e1000_context_desc *); 564919Sxy150489 static int e1000g_fill_tx_desc(e1000g_tx_ring_t *, 574919Sxy150489 p_tx_sw_packet_t, uint64_t, size_t); 583526Sxy150489 static uint32_t e1000g_fill_82544_desc(uint64_t Address, size_t Length, 594919Sxy150489 p_desc_array_t desc_array); 604919Sxy150489 static int e1000g_tx_workaround_PCIX_82544(p_tx_sw_packet_t, uint64_t, size_t); 614919Sxy150489 static int e1000g_tx_workaround_jumbo_82544(p_tx_sw_packet_t, uint64_t, size_t); 623526Sxy150489 static void e1000g_82547_timeout(void *); 633526Sxy150489 static void e1000g_82547_tx_move_tail(e1000g_tx_ring_t *); 643526Sxy150489 static void e1000g_82547_tx_move_tail_work(e1000g_tx_ring_t *); 653526Sxy150489 664919Sxy150489 #ifndef E1000G_DEBUG 673526Sxy150489 #pragma inline(e1000g_tx_copy) 683526Sxy150489 #pragma inline(e1000g_tx_bind) 69*6986Smx205022 #pragma inline(e1000g_retreive_context) 70*6986Smx205022 #pragma inline(e1000g_check_context) 713526Sxy150489 #pragma inline(e1000g_fill_tx_ring) 723526Sxy150489 #pragma inline(e1000g_fill_context_descriptor) 733526Sxy150489 #pragma inline(e1000g_fill_tx_desc) 743526Sxy150489 #pragma inline(e1000g_fill_82544_desc) 753526Sxy150489 #pragma inline(e1000g_tx_workaround_PCIX_82544) 763526Sxy150489 #pragma inline(e1000g_tx_workaround_jumbo_82544) 774919Sxy150489 #pragma inline(e1000g_free_tx_swpkt) 783526Sxy150489 #endif 793526Sxy150489 803526Sxy150489 /* 814919Sxy150489 * e1000g_free_tx_swpkt - free up the tx sw packet 824919Sxy150489 * 834919Sxy150489 * Unbind the previously bound DMA handle for a given 844919Sxy150489 * transmit sw packet. And reset the sw packet data. 853526Sxy150489 */ 863526Sxy150489 void 874919Sxy150489 e1000g_free_tx_swpkt(register p_tx_sw_packet_t packet) 883526Sxy150489 { 893526Sxy150489 switch (packet->data_transfer_type) { 903526Sxy150489 case USE_BCOPY: 913526Sxy150489 packet->tx_buf->len = 0; 923526Sxy150489 break; 933526Sxy150489 #ifdef __sparc 943526Sxy150489 case USE_DVMA: 953526Sxy150489 dvma_unload(packet->tx_dma_handle, 0, -1); 963526Sxy150489 break; 973526Sxy150489 #endif 983526Sxy150489 case USE_DMA: 993526Sxy150489 ddi_dma_unbind_handle(packet->tx_dma_handle); 1003526Sxy150489 break; 1013526Sxy150489 default: 1023526Sxy150489 break; 1033526Sxy150489 } 1043526Sxy150489 1053526Sxy150489 /* 1063526Sxy150489 * The mblk has been stripped off the sw packet 1073526Sxy150489 * and will be freed in a triggered soft intr. 1083526Sxy150489 */ 1093526Sxy150489 ASSERT(packet->mp == NULL); 1103526Sxy150489 1113526Sxy150489 packet->data_transfer_type = USE_NONE; 1123526Sxy150489 packet->num_mblk_frag = 0; 1133526Sxy150489 packet->num_desc = 0; 1143526Sxy150489 } 1153526Sxy150489 1163526Sxy150489 mblk_t * 1173526Sxy150489 e1000g_m_tx(void *arg, mblk_t *mp) 1183526Sxy150489 { 1193526Sxy150489 struct e1000g *Adapter = (struct e1000g *)arg; 1203526Sxy150489 mblk_t *next; 1213526Sxy150489 1223526Sxy150489 rw_enter(&Adapter->chip_lock, RW_READER); 1233526Sxy150489 1245273Sgl147354 if ((Adapter->chip_state != E1000G_START) || 1255273Sgl147354 (Adapter->link_state != LINK_STATE_UP)) { 1263526Sxy150489 freemsgchain(mp); 1273526Sxy150489 mp = NULL; 1283526Sxy150489 } 1293526Sxy150489 1303526Sxy150489 while (mp != NULL) { 1313526Sxy150489 next = mp->b_next; 1323526Sxy150489 mp->b_next = NULL; 1333526Sxy150489 1343526Sxy150489 if (!e1000g_send(Adapter, mp)) { 1353526Sxy150489 mp->b_next = next; 1363526Sxy150489 break; 1373526Sxy150489 } 1383526Sxy150489 1393526Sxy150489 mp = next; 1403526Sxy150489 } 1413526Sxy150489 1423526Sxy150489 rw_exit(&Adapter->chip_lock); 1433526Sxy150489 return (mp); 1443526Sxy150489 } 1453526Sxy150489 1463526Sxy150489 /* 1474919Sxy150489 * e1000g_send - send packets onto the wire 1484919Sxy150489 * 1494919Sxy150489 * Called from e1000g_m_tx with an mblk ready to send. this 1504919Sxy150489 * routine sets up the transmit descriptors and sends data to 1514919Sxy150489 * the wire. It also pushes the just transmitted packet to 1524919Sxy150489 * the used tx sw packet list. 1533526Sxy150489 */ 1543526Sxy150489 static boolean_t 1553526Sxy150489 e1000g_send(struct e1000g *Adapter, mblk_t *mp) 1563526Sxy150489 { 1574919Sxy150489 struct e1000_hw *hw; 1584919Sxy150489 p_tx_sw_packet_t packet; 1593526Sxy150489 LIST_DESCRIBER pending_list; 1603526Sxy150489 size_t len; 1613526Sxy150489 size_t msg_size; 1623526Sxy150489 uint32_t frag_count; 1633526Sxy150489 int desc_count; 1643526Sxy150489 uint32_t desc_total; 165*6986Smx205022 boolean_t tx_undersize_flag; 1663526Sxy150489 mblk_t *nmp; 1673526Sxy150489 mblk_t *tmp; 1683526Sxy150489 e1000g_tx_ring_t *tx_ring; 169*6986Smx205022 context_data_t cur_context; 1703526Sxy150489 1714919Sxy150489 hw = &Adapter->shared; 1724919Sxy150489 tx_ring = Adapter->tx_ring; 1734919Sxy150489 1743526Sxy150489 /* Get the total size and frags number of the message */ 175*6986Smx205022 tx_undersize_flag = B_FALSE; 1763526Sxy150489 frag_count = 0; 1773526Sxy150489 msg_size = 0; 1783526Sxy150489 for (nmp = mp; nmp; nmp = nmp->b_cont) { 1793526Sxy150489 frag_count++; 1803526Sxy150489 msg_size += MBLKL(nmp); 1813526Sxy150489 } 1823526Sxy150489 183*6986Smx205022 /* retreive and compute information for context descriptor */ 184*6986Smx205022 if (!e1000g_retreive_context(mp, &cur_context, msg_size)) { 185*6986Smx205022 freemsg(mp); 186*6986Smx205022 return (B_TRUE); 187*6986Smx205022 } 188*6986Smx205022 189*6986Smx205022 /* 190*6986Smx205022 * Make sure the packet is less than the allowed size 191*6986Smx205022 */ 192*6986Smx205022 if (!cur_context.lso_flag && 193*6986Smx205022 (msg_size > Adapter->max_frame_size - ETHERFCSL)) { 1943526Sxy150489 /* 1953526Sxy150489 * For the over size packet, we'll just drop it. 1963526Sxy150489 * So we return B_TRUE here. 1973526Sxy150489 */ 1984919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 1993526Sxy150489 "Tx packet out of bound. length = %d \n", msg_size); 2004919Sxy150489 E1000G_STAT(tx_ring->stat_over_size); 2013526Sxy150489 freemsg(mp); 2023526Sxy150489 return (B_TRUE); 2033526Sxy150489 } 2043526Sxy150489 2053526Sxy150489 /* 2063526Sxy150489 * Check and reclaim tx descriptors. 2073526Sxy150489 * This low water mark check should be done all the time as 2083526Sxy150489 * Transmit interrupt delay can produce Transmit interrupts little 2093526Sxy150489 * late and that may cause few problems related to reaping Tx 2103526Sxy150489 * Descriptors... As you may run short of them before getting any 2113526Sxy150489 * transmit interrupt... 2123526Sxy150489 */ 2135882Syy150190 if (tx_ring->resched_needed || 2145882Syy150190 (tx_ring->tbd_avail < Adapter->tx_recycle_thresh)) { 2153526Sxy150489 (void) e1000g_recycle(tx_ring); 2165882Syy150190 E1000G_DEBUG_STAT(tx_ring->stat_recycle); 2173526Sxy150489 2185882Syy150190 if (tx_ring->tbd_avail < DEFAULT_TX_NO_RESOURCE) { 2195882Syy150190 E1000G_DEBUG_STAT(tx_ring->stat_lack_desc); 2205882Syy150190 goto tx_no_resource; 2215882Syy150190 } 2223526Sxy150489 } 2233526Sxy150489 2243526Sxy150489 /* 2253526Sxy150489 * If the message size is less than the minimum ethernet packet size, 2263526Sxy150489 * we'll use bcopy to send it, and padd it to 60 bytes later. 2273526Sxy150489 */ 2286394Scc210113 if (msg_size < ETHERMIN) { 2294919Sxy150489 E1000G_DEBUG_STAT(tx_ring->stat_under_size); 230*6986Smx205022 tx_undersize_flag = B_TRUE; 2313526Sxy150489 } 2323526Sxy150489 2333526Sxy150489 /* Initialize variables */ 2343526Sxy150489 desc_count = 1; /* The initial value should be greater than 0 */ 2353526Sxy150489 desc_total = 0; 2363526Sxy150489 QUEUE_INIT_LIST(&pending_list); 2373526Sxy150489 2383526Sxy150489 /* Process each mblk fragment and fill tx descriptors */ 2393526Sxy150489 packet = NULL; 2403526Sxy150489 nmp = mp; 2413526Sxy150489 while (nmp) { 2423526Sxy150489 tmp = nmp->b_cont; 2433526Sxy150489 2443526Sxy150489 len = MBLKL(nmp); 2453526Sxy150489 /* Check zero length mblks */ 2463526Sxy150489 if (len == 0) { 2474919Sxy150489 E1000G_DEBUG_STAT(tx_ring->stat_empty_frags); 2483526Sxy150489 /* 2493526Sxy150489 * If there're no packet buffers have been used, 2503526Sxy150489 * or we just completed processing a buffer, then 2513526Sxy150489 * skip the empty mblk fragment. 2523526Sxy150489 * Otherwise, there's still a pending buffer that 2533526Sxy150489 * needs to be processed (tx_copy). 2543526Sxy150489 */ 2553526Sxy150489 if (desc_count > 0) { 2563526Sxy150489 nmp = tmp; 2573526Sxy150489 continue; 2583526Sxy150489 } 2593526Sxy150489 } 2603526Sxy150489 2613526Sxy150489 /* 2623526Sxy150489 * Get a new TxSwPacket to process mblk buffers. 2633526Sxy150489 */ 2643526Sxy150489 if (desc_count > 0) { 2653526Sxy150489 mutex_enter(&tx_ring->freelist_lock); 2664919Sxy150489 packet = (p_tx_sw_packet_t) 2673526Sxy150489 QUEUE_POP_HEAD(&tx_ring->free_list); 2683526Sxy150489 mutex_exit(&tx_ring->freelist_lock); 2693526Sxy150489 2703526Sxy150489 if (packet == NULL) { 2714919Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_INFO_LEVEL, 2723526Sxy150489 "No Tx SwPacket available\n"); 2734919Sxy150489 E1000G_STAT(tx_ring->stat_no_swpkt); 2743526Sxy150489 goto tx_send_failed; 2753526Sxy150489 } 2763526Sxy150489 QUEUE_PUSH_TAIL(&pending_list, &packet->Link); 2773526Sxy150489 } 2783526Sxy150489 2793526Sxy150489 ASSERT(packet); 2803526Sxy150489 /* 2813526Sxy150489 * If the size of the fragment is less than the tx_bcopy_thresh 2823526Sxy150489 * we'll use bcopy; Otherwise, we'll use DMA binding. 2833526Sxy150489 */ 284*6986Smx205022 if ((len <= Adapter->tx_bcopy_thresh) || tx_undersize_flag) { 2853526Sxy150489 desc_count = 286*6986Smx205022 e1000g_tx_copy(tx_ring, packet, nmp, 287*6986Smx205022 tx_undersize_flag); 2884919Sxy150489 E1000G_DEBUG_STAT(tx_ring->stat_copy); 2893526Sxy150489 } else { 2903526Sxy150489 desc_count = 2914919Sxy150489 e1000g_tx_bind(tx_ring, packet, nmp); 2924919Sxy150489 E1000G_DEBUG_STAT(tx_ring->stat_bind); 2933526Sxy150489 } 2943526Sxy150489 2953526Sxy150489 if (desc_count > 0) 2963526Sxy150489 desc_total += desc_count; 2974919Sxy150489 else if (desc_count < 0) 2984919Sxy150489 goto tx_send_failed; 2993526Sxy150489 3003526Sxy150489 nmp = tmp; 3013526Sxy150489 } 3023526Sxy150489 3033526Sxy150489 /* Assign the message to the last sw packet */ 3043526Sxy150489 ASSERT(packet); 3053526Sxy150489 ASSERT(packet->mp == NULL); 3063526Sxy150489 packet->mp = mp; 3073526Sxy150489 3083526Sxy150489 /* Try to recycle the tx descriptors again */ 3094919Sxy150489 if (tx_ring->tbd_avail < (desc_total + 2)) { 3104919Sxy150489 E1000G_DEBUG_STAT(tx_ring->stat_recycle_retry); 3113526Sxy150489 (void) e1000g_recycle(tx_ring); 3123526Sxy150489 } 3133526Sxy150489 3143526Sxy150489 mutex_enter(&tx_ring->tx_lock); 3153526Sxy150489 3163526Sxy150489 /* 3173526Sxy150489 * If the number of available tx descriptors is not enough for transmit 3183526Sxy150489 * (one redundant descriptor and one hw checksum context descriptor are 3193526Sxy150489 * included), then return failure. 3203526Sxy150489 */ 3214919Sxy150489 if (tx_ring->tbd_avail < (desc_total + 2)) { 3224919Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_INFO_LEVEL, 3233526Sxy150489 "No Enough Tx descriptors\n"); 3244919Sxy150489 E1000G_STAT(tx_ring->stat_no_desc); 3253526Sxy150489 mutex_exit(&tx_ring->tx_lock); 3263526Sxy150489 goto tx_send_failed; 3273526Sxy150489 } 3283526Sxy150489 329*6986Smx205022 desc_count = e1000g_fill_tx_ring(tx_ring, &pending_list, &cur_context); 3303526Sxy150489 3313526Sxy150489 mutex_exit(&tx_ring->tx_lock); 3323526Sxy150489 3333526Sxy150489 ASSERT(desc_count > 0); 3343526Sxy150489 3353526Sxy150489 /* Send successful */ 3363526Sxy150489 return (B_TRUE); 3373526Sxy150489 3383526Sxy150489 tx_send_failed: 3395882Syy150190 /* 3405882Syy150190 * Enable Transmit interrupts, so that the interrupt routine can 3415882Syy150190 * call mac_tx_update() when transmit descriptors become available. 3425882Syy150190 */ 3435882Syy150190 tx_ring->resched_needed = B_TRUE; 3445882Syy150190 if (!Adapter->tx_intr_enable) 3455882Syy150190 e1000g_mask_tx_interrupt(Adapter); 3465882Syy150190 3473526Sxy150489 /* Free pending TxSwPackets */ 3484919Sxy150489 packet = (p_tx_sw_packet_t)QUEUE_GET_HEAD(&pending_list); 3493526Sxy150489 while (packet) { 3503526Sxy150489 packet->mp = NULL; 3514919Sxy150489 e1000g_free_tx_swpkt(packet); 3524919Sxy150489 packet = (p_tx_sw_packet_t) 3533526Sxy150489 QUEUE_GET_NEXT(&pending_list, &packet->Link); 3543526Sxy150489 } 3553526Sxy150489 3563526Sxy150489 /* Return pending TxSwPackets to the "Free" list */ 3573526Sxy150489 mutex_enter(&tx_ring->freelist_lock); 3583526Sxy150489 QUEUE_APPEND(&tx_ring->free_list, &pending_list); 3593526Sxy150489 mutex_exit(&tx_ring->freelist_lock); 3603526Sxy150489 3614919Sxy150489 E1000G_STAT(tx_ring->stat_send_fail); 3623526Sxy150489 3635882Syy150190 /* Message will be scheduled for re-transmit */ 3645882Syy150190 return (B_FALSE); 3653526Sxy150489 3663526Sxy150489 tx_no_resource: 3673526Sxy150489 /* 3683526Sxy150489 * Enable Transmit interrupts, so that the interrupt routine can 3693526Sxy150489 * call mac_tx_update() when transmit descriptors become available. 3703526Sxy150489 */ 3714919Sxy150489 tx_ring->resched_needed = B_TRUE; 3723526Sxy150489 if (!Adapter->tx_intr_enable) 3734919Sxy150489 e1000g_mask_tx_interrupt(Adapter); 3743526Sxy150489 3753526Sxy150489 /* Message will be scheduled for re-transmit */ 3763526Sxy150489 return (B_FALSE); 3773526Sxy150489 } 3783526Sxy150489 3794061Sxy150489 static boolean_t 380*6986Smx205022 e1000g_retreive_context(mblk_t *mp, context_data_t *cur_context, 381*6986Smx205022 size_t msg_size) 3824061Sxy150489 { 383*6986Smx205022 uintptr_t ip_start; 384*6986Smx205022 uintptr_t tcp_start; 385*6986Smx205022 mblk_t *nmp; 386*6986Smx205022 387*6986Smx205022 bzero(cur_context, sizeof (context_data_t)); 3884061Sxy150489 389*6986Smx205022 /* retrieve checksum info */ 390*6986Smx205022 hcksum_retrieve(mp, NULL, NULL, &cur_context->cksum_start, 391*6986Smx205022 &cur_context->cksum_stuff, NULL, NULL, &cur_context->cksum_flags); 392*6986Smx205022 /* retreive ethernet header size */ 393*6986Smx205022 if (((struct ether_vlan_header *)mp->b_rptr)->ether_tpid == 394*6986Smx205022 htons(ETHERTYPE_VLAN)) 395*6986Smx205022 cur_context->ether_header_size = 396*6986Smx205022 sizeof (struct ether_vlan_header); 397*6986Smx205022 else 398*6986Smx205022 cur_context->ether_header_size = 399*6986Smx205022 sizeof (struct ether_header); 4004061Sxy150489 401*6986Smx205022 if (cur_context->cksum_flags & HW_LSO) { 402*6986Smx205022 if ((cur_context->mss = DB_LSOMSS(mp)) != 0) { 403*6986Smx205022 /* free the invaid packet */ 404*6986Smx205022 if (!((cur_context->cksum_flags & HCK_PARTIALCKSUM) && 405*6986Smx205022 (cur_context->cksum_flags & HCK_IPV4_HDRCKSUM))) { 406*6986Smx205022 return (B_FALSE); 407*6986Smx205022 } 408*6986Smx205022 cur_context->lso_flag = B_TRUE; 409*6986Smx205022 /* 410*6986Smx205022 * Some fields are cleared for the hardware to fill 411*6986Smx205022 * in. We don't assume Ethernet header, IP header and 412*6986Smx205022 * TCP header are always in the same mblk fragment, 413*6986Smx205022 * while we assume each header is always within one 414*6986Smx205022 * mblk fragment and Ethernet header is always in the 415*6986Smx205022 * first mblk fragment. 416*6986Smx205022 */ 417*6986Smx205022 nmp = mp; 418*6986Smx205022 ip_start = (uintptr_t)(nmp->b_rptr) 419*6986Smx205022 + cur_context->ether_header_size; 420*6986Smx205022 if (ip_start >= (uintptr_t)(nmp->b_wptr)) { 421*6986Smx205022 ip_start = (uintptr_t)nmp->b_cont->b_rptr 422*6986Smx205022 + (ip_start - (uintptr_t)(nmp->b_wptr)); 423*6986Smx205022 nmp = nmp->b_cont; 424*6986Smx205022 } 425*6986Smx205022 tcp_start = ip_start + 426*6986Smx205022 IPH_HDR_LENGTH((ipha_t *)ip_start); 427*6986Smx205022 if (tcp_start >= (uintptr_t)(nmp->b_wptr)) { 428*6986Smx205022 tcp_start = (uintptr_t)nmp->b_cont->b_rptr 429*6986Smx205022 + (tcp_start - (uintptr_t)(nmp->b_wptr)); 430*6986Smx205022 nmp = nmp->b_cont; 431*6986Smx205022 } 432*6986Smx205022 cur_context->hdr_len = cur_context->ether_header_size 433*6986Smx205022 + IPH_HDR_LENGTH((ipha_t *)ip_start) 434*6986Smx205022 + TCP_HDR_LENGTH((tcph_t *)tcp_start); 435*6986Smx205022 ((ipha_t *)ip_start)->ipha_length = 0; 436*6986Smx205022 ((ipha_t *)ip_start)->ipha_hdr_checksum = 0; 437*6986Smx205022 /* calculate the TCP packet payload length */ 438*6986Smx205022 cur_context->pay_len = msg_size - cur_context->hdr_len; 439*6986Smx205022 } 440*6986Smx205022 } 441*6986Smx205022 return (B_TRUE); 442*6986Smx205022 } 4434061Sxy150489 444*6986Smx205022 static boolean_t 445*6986Smx205022 e1000g_check_context(e1000g_tx_ring_t *tx_ring, context_data_t *cur_context) 446*6986Smx205022 { 447*6986Smx205022 boolean_t context_reload; 448*6986Smx205022 context_data_t *pre_context; 449*6986Smx205022 struct e1000g *Adapter; 450*6986Smx205022 451*6986Smx205022 context_reload = B_FALSE; 452*6986Smx205022 pre_context = &tx_ring->pre_context; 453*6986Smx205022 Adapter = tx_ring->adapter; 454*6986Smx205022 455*6986Smx205022 /* 456*6986Smx205022 * The following code determine if the context descriptor is 457*6986Smx205022 * needed to be reloaded. The sequence of the conditions is 458*6986Smx205022 * made by their possibilities of changing. 459*6986Smx205022 */ 460*6986Smx205022 /* 461*6986Smx205022 * workaround for 82546EB, context descriptor must be reloaded 462*6986Smx205022 * per LSO/hw_cksum packet if LSO is enabled. 463*6986Smx205022 */ 464*6986Smx205022 if (Adapter->lso_premature_issue && 465*6986Smx205022 Adapter->lso_enable && 466*6986Smx205022 (cur_context->cksum_flags != 0)) { 467*6986Smx205022 468*6986Smx205022 context_reload = B_TRUE; 469*6986Smx205022 } else if (cur_context->lso_flag) { 470*6986Smx205022 if ((cur_context->cksum_flags != pre_context->cksum_flags) || 471*6986Smx205022 (cur_context->pay_len != pre_context->pay_len) || 472*6986Smx205022 (cur_context->mss != pre_context->mss) || 473*6986Smx205022 (cur_context->hdr_len != pre_context->hdr_len) || 474*6986Smx205022 (cur_context->cksum_stuff != pre_context->cksum_stuff) || 475*6986Smx205022 (cur_context->cksum_start != pre_context->cksum_start) || 476*6986Smx205022 (cur_context->ether_header_size != 477*6986Smx205022 pre_context->ether_header_size)) { 478*6986Smx205022 479*6986Smx205022 context_reload = B_TRUE; 480*6986Smx205022 } 481*6986Smx205022 } else if (cur_context->cksum_flags != 0) { 482*6986Smx205022 if ((cur_context->cksum_flags != pre_context->cksum_flags) || 483*6986Smx205022 (cur_context->cksum_stuff != pre_context->cksum_stuff) || 484*6986Smx205022 (cur_context->cksum_start != pre_context->cksum_start) || 485*6986Smx205022 (cur_context->ether_header_size != 486*6986Smx205022 pre_context->ether_header_size)) { 487*6986Smx205022 488*6986Smx205022 context_reload = B_TRUE; 4894061Sxy150489 } 4904061Sxy150489 } 4914061Sxy150489 492*6986Smx205022 return (context_reload); 4934061Sxy150489 } 4944061Sxy150489 4953526Sxy150489 static int 4963526Sxy150489 e1000g_fill_tx_ring(e1000g_tx_ring_t *tx_ring, LIST_DESCRIBER *pending_list, 497*6986Smx205022 context_data_t *cur_context) 4983526Sxy150489 { 4993526Sxy150489 struct e1000g *Adapter; 5004919Sxy150489 struct e1000_hw *hw; 5014919Sxy150489 p_tx_sw_packet_t first_packet; 5024919Sxy150489 p_tx_sw_packet_t packet; 503*6986Smx205022 p_tx_sw_packet_t previous_packet; 504*6986Smx205022 boolean_t context_reload; 5053526Sxy150489 struct e1000_tx_desc *first_data_desc; 5063526Sxy150489 struct e1000_tx_desc *next_desc; 5073526Sxy150489 struct e1000_tx_desc *descriptor; 5083526Sxy150489 int desc_count; 509*6986Smx205022 boolean_t buff_overrun_flag; 5103526Sxy150489 int i; 5113526Sxy150489 5123526Sxy150489 Adapter = tx_ring->adapter; 5134919Sxy150489 hw = &Adapter->shared; 5143526Sxy150489 5153526Sxy150489 desc_count = 0; 5164061Sxy150489 first_packet = NULL; 5173526Sxy150489 first_data_desc = NULL; 5183526Sxy150489 descriptor = NULL; 519*6986Smx205022 first_packet = NULL; 520*6986Smx205022 packet = NULL; 521*6986Smx205022 buff_overrun_flag = B_FALSE; 5223526Sxy150489 5233526Sxy150489 next_desc = tx_ring->tbd_next; 5243526Sxy150489 525*6986Smx205022 /* Context descriptor reload check */ 526*6986Smx205022 context_reload = e1000g_check_context(tx_ring, cur_context); 5274061Sxy150489 528*6986Smx205022 if (context_reload) { 5294919Sxy150489 first_packet = (p_tx_sw_packet_t)QUEUE_GET_HEAD(pending_list); 5304061Sxy150489 5313526Sxy150489 descriptor = next_desc; 5323526Sxy150489 533*6986Smx205022 e1000g_fill_context_descriptor(cur_context, 5344061Sxy150489 (struct e1000_context_desc *)descriptor); 5353526Sxy150489 5363526Sxy150489 /* Check the wrap-around case */ 5373526Sxy150489 if (descriptor == tx_ring->tbd_last) 5383526Sxy150489 next_desc = tx_ring->tbd_first; 5393526Sxy150489 else 5403526Sxy150489 next_desc++; 5413526Sxy150489 5423526Sxy150489 desc_count++; 5433526Sxy150489 } 5443526Sxy150489 5453526Sxy150489 first_data_desc = next_desc; 5463526Sxy150489 5474919Sxy150489 packet = (p_tx_sw_packet_t)QUEUE_GET_HEAD(pending_list); 5483526Sxy150489 while (packet) { 5493526Sxy150489 ASSERT(packet->num_desc); 5503526Sxy150489 5513526Sxy150489 for (i = 0; i < packet->num_desc; i++) { 5524919Sxy150489 ASSERT(tx_ring->tbd_avail > 0); 5533526Sxy150489 5543526Sxy150489 descriptor = next_desc; 5553526Sxy150489 descriptor->buffer_addr = 5564919Sxy150489 packet->desc[i].address; 5573526Sxy150489 descriptor->lower.data = 5584919Sxy150489 packet->desc[i].length; 5593526Sxy150489 5603526Sxy150489 /* Zero out status */ 5613526Sxy150489 descriptor->upper.data = 0; 5623526Sxy150489 5633526Sxy150489 descriptor->lower.data |= 5643526Sxy150489 E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; 5653526Sxy150489 /* must set RS on every outgoing descriptor */ 5663526Sxy150489 descriptor->lower.data |= 5673526Sxy150489 E1000_TXD_CMD_RS; 5683526Sxy150489 569*6986Smx205022 if (cur_context->lso_flag) 570*6986Smx205022 descriptor->lower.data |= E1000_TXD_CMD_TSE; 571*6986Smx205022 5723526Sxy150489 /* Check the wrap-around case */ 5733526Sxy150489 if (descriptor == tx_ring->tbd_last) 5743526Sxy150489 next_desc = tx_ring->tbd_first; 5753526Sxy150489 else 5763526Sxy150489 next_desc++; 5773526Sxy150489 5783526Sxy150489 desc_count++; 579*6986Smx205022 580*6986Smx205022 /* 581*6986Smx205022 * workaround for 82546EB errata 33, hang in PCI-X 582*6986Smx205022 * systems due to 2k Buffer Overrun during Transmit 583*6986Smx205022 * Operation. The workaround applies to all the Intel 584*6986Smx205022 * PCI-X chips. 585*6986Smx205022 */ 586*6986Smx205022 if (hw->bus.type == e1000_bus_type_pcix && 587*6986Smx205022 descriptor == first_data_desc && 588*6986Smx205022 ((descriptor->lower.data & E1000G_TBD_LENGTH_MASK) 589*6986Smx205022 > E1000_TX_BUFFER_OEVRRUN_THRESHOLD)) { 590*6986Smx205022 /* modified the first descriptor */ 591*6986Smx205022 descriptor->lower.data &= 592*6986Smx205022 ~E1000G_TBD_LENGTH_MASK; 593*6986Smx205022 descriptor->lower.flags.length = 594*6986Smx205022 E1000_TX_BUFFER_OEVRRUN_THRESHOLD; 595*6986Smx205022 596*6986Smx205022 /* insert a new descriptor */ 597*6986Smx205022 ASSERT(tx_ring->tbd_avail > 0); 598*6986Smx205022 next_desc->buffer_addr = 599*6986Smx205022 packet->desc[0].address + 600*6986Smx205022 E1000_TX_BUFFER_OEVRRUN_THRESHOLD; 601*6986Smx205022 next_desc->lower.data = 602*6986Smx205022 packet->desc[0].length - 603*6986Smx205022 E1000_TX_BUFFER_OEVRRUN_THRESHOLD; 604*6986Smx205022 605*6986Smx205022 /* Zero out status */ 606*6986Smx205022 next_desc->upper.data = 0; 607*6986Smx205022 608*6986Smx205022 next_desc->lower.data |= 609*6986Smx205022 E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; 610*6986Smx205022 /* must set RS on every outgoing descriptor */ 611*6986Smx205022 next_desc->lower.data |= 612*6986Smx205022 E1000_TXD_CMD_RS; 613*6986Smx205022 614*6986Smx205022 if (cur_context->lso_flag) 615*6986Smx205022 next_desc->lower.data |= 616*6986Smx205022 E1000_TXD_CMD_TSE; 617*6986Smx205022 618*6986Smx205022 descriptor = next_desc; 619*6986Smx205022 620*6986Smx205022 /* Check the wrap-around case */ 621*6986Smx205022 if (next_desc == tx_ring->tbd_last) 622*6986Smx205022 next_desc = tx_ring->tbd_first; 623*6986Smx205022 else 624*6986Smx205022 next_desc++; 625*6986Smx205022 626*6986Smx205022 desc_count++; 627*6986Smx205022 buff_overrun_flag = B_TRUE; 628*6986Smx205022 } 629*6986Smx205022 } 630*6986Smx205022 631*6986Smx205022 if (buff_overrun_flag) { 632*6986Smx205022 packet->num_desc++; 633*6986Smx205022 buff_overrun_flag = B_FALSE; 6343526Sxy150489 } 6353526Sxy150489 6363526Sxy150489 if (first_packet != NULL) { 6373526Sxy150489 /* 6383526Sxy150489 * Count the checksum context descriptor for 6393526Sxy150489 * the first SwPacket. 6403526Sxy150489 */ 6413526Sxy150489 first_packet->num_desc++; 6423526Sxy150489 first_packet = NULL; 6433526Sxy150489 } 6443526Sxy150489 645*6986Smx205022 previous_packet = packet; 6464919Sxy150489 packet = (p_tx_sw_packet_t) 6473526Sxy150489 QUEUE_GET_NEXT(pending_list, &packet->Link); 6483526Sxy150489 } 6493526Sxy150489 650*6986Smx205022 /* 651*6986Smx205022 * workaround for 82546EB errata 21, LSO Premature Descriptor Write Back 652*6986Smx205022 */ 653*6986Smx205022 if (Adapter->lso_premature_issue && cur_context->lso_flag && 654*6986Smx205022 ((descriptor->lower.data & E1000G_TBD_LENGTH_MASK) > 8)) { 655*6986Smx205022 /* modified the previous descriptor */ 656*6986Smx205022 descriptor->lower.data -= 4; 657*6986Smx205022 658*6986Smx205022 /* insert a new descriptor */ 659*6986Smx205022 ASSERT(tx_ring->tbd_avail > 0); 660*6986Smx205022 /* the lower 20 bits of lower.data is the length field */ 661*6986Smx205022 next_desc->buffer_addr = 662*6986Smx205022 descriptor->buffer_addr + 663*6986Smx205022 (descriptor->lower.data & E1000G_TBD_LENGTH_MASK); 664*6986Smx205022 next_desc->lower.data = 4; 665*6986Smx205022 666*6986Smx205022 /* Zero out status */ 667*6986Smx205022 next_desc->upper.data = 0; 668*6986Smx205022 /* It must be part of a LSO packet */ 669*6986Smx205022 next_desc->lower.data |= 670*6986Smx205022 E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D | 671*6986Smx205022 E1000_TXD_CMD_RS | E1000_TXD_CMD_TSE; 672*6986Smx205022 673*6986Smx205022 descriptor = next_desc; 674*6986Smx205022 675*6986Smx205022 /* Check the wrap-around case */ 676*6986Smx205022 if (descriptor == tx_ring->tbd_last) 677*6986Smx205022 next_desc = tx_ring->tbd_first; 678*6986Smx205022 else 679*6986Smx205022 next_desc++; 680*6986Smx205022 681*6986Smx205022 desc_count++; 682*6986Smx205022 /* update the number of descriptors */ 683*6986Smx205022 previous_packet->num_desc++; 684*6986Smx205022 } 685*6986Smx205022 6863526Sxy150489 ASSERT(descriptor); 6873526Sxy150489 688*6986Smx205022 if (cur_context->cksum_flags) { 689*6986Smx205022 if (cur_context->cksum_flags & HCK_IPV4_HDRCKSUM) 6903526Sxy150489 ((struct e1000_data_desc *)first_data_desc)-> 6914608Syy150190 upper.fields.popts |= E1000_TXD_POPTS_IXSM; 692*6986Smx205022 if (cur_context->cksum_flags & HCK_PARTIALCKSUM) 6933526Sxy150489 ((struct e1000_data_desc *)first_data_desc)-> 6944608Syy150190 upper.fields.popts |= E1000_TXD_POPTS_TXSM; 6953526Sxy150489 } 6963526Sxy150489 6973526Sxy150489 /* 6983526Sxy150489 * Last Descriptor of Packet needs End Of Packet (EOP), Report 699*6986Smx205022 * Status (RS) set. 7003526Sxy150489 */ 7014919Sxy150489 if (Adapter->tx_intr_delay) { 7023526Sxy150489 descriptor->lower.data |= E1000_TXD_CMD_IDE | 703*6986Smx205022 E1000_TXD_CMD_EOP; 7043526Sxy150489 } else { 705*6986Smx205022 descriptor->lower.data |= E1000_TXD_CMD_EOP; 706*6986Smx205022 } 707*6986Smx205022 708*6986Smx205022 /* Set append Ethernet CRC (IFCS) bits */ 709*6986Smx205022 if (cur_context->lso_flag) { 710*6986Smx205022 first_data_desc->lower.data |= E1000_TXD_CMD_IFCS; 711*6986Smx205022 } else { 712*6986Smx205022 descriptor->lower.data |= E1000_TXD_CMD_IFCS; 7133526Sxy150489 } 7143526Sxy150489 7153526Sxy150489 /* 7163526Sxy150489 * Sync the Tx descriptors DMA buffer 7173526Sxy150489 */ 7184919Sxy150489 (void) ddi_dma_sync(tx_ring->tbd_dma_handle, 7194919Sxy150489 0, 0, DDI_DMA_SYNC_FORDEV); 7203526Sxy150489 7213526Sxy150489 tx_ring->tbd_next = next_desc; 7223526Sxy150489 7233526Sxy150489 /* 7243526Sxy150489 * Advance the Transmit Descriptor Tail (Tdt), this tells the 7253526Sxy150489 * FX1000 that this frame is available to transmit. 7263526Sxy150489 */ 7274919Sxy150489 if (hw->mac.type == e1000_82547) 7283526Sxy150489 e1000g_82547_tx_move_tail(tx_ring); 7293526Sxy150489 else 7306735Scc210113 E1000_WRITE_REG(hw, E1000_TDT(0), 7313526Sxy150489 (uint32_t)(next_desc - tx_ring->tbd_first)); 7323526Sxy150489 7335273Sgl147354 if (e1000g_check_acc_handle(Adapter->osdep.reg_handle) != DDI_FM_OK) { 7345273Sgl147354 ddi_fm_service_impact(Adapter->dip, DDI_SERVICE_DEGRADED); 7355273Sgl147354 Adapter->chip_state = E1000G_ERROR; 7365273Sgl147354 } 7375273Sgl147354 7383526Sxy150489 /* Put the pending SwPackets to the "Used" list */ 7393526Sxy150489 mutex_enter(&tx_ring->usedlist_lock); 7403526Sxy150489 QUEUE_APPEND(&tx_ring->used_list, pending_list); 7414919Sxy150489 tx_ring->tbd_avail -= desc_count; 7423526Sxy150489 mutex_exit(&tx_ring->usedlist_lock); 7433526Sxy150489 744*6986Smx205022 /* update LSO related data */ 745*6986Smx205022 if (context_reload) 746*6986Smx205022 tx_ring->pre_context = *cur_context; 7474061Sxy150489 7483526Sxy150489 return (desc_count); 7493526Sxy150489 } 7503526Sxy150489 7513526Sxy150489 7523526Sxy150489 /* 7534919Sxy150489 * e1000g_tx_setup - setup tx data structures 7544919Sxy150489 * 7554919Sxy150489 * This routine initializes all of the transmit related 7564919Sxy150489 * structures. This includes the Transmit descriptors, 7574919Sxy150489 * and the tx_sw_packet structures. 7583526Sxy150489 */ 7593526Sxy150489 void 7604919Sxy150489 e1000g_tx_setup(struct e1000g *Adapter) 7613526Sxy150489 { 7623526Sxy150489 struct e1000_hw *hw; 7634919Sxy150489 p_tx_sw_packet_t packet; 7643526Sxy150489 UINT i; 7653526Sxy150489 uint32_t buf_high; 7663526Sxy150489 uint32_t buf_low; 7673526Sxy150489 uint32_t reg_tipg; 7683526Sxy150489 uint32_t reg_tctl; 7693526Sxy150489 uint32_t reg_tarc; 7703526Sxy150489 uint16_t speed, duplex; 7713526Sxy150489 int size; 7723526Sxy150489 e1000g_tx_ring_t *tx_ring; 7733526Sxy150489 7744919Sxy150489 hw = &Adapter->shared; 7753526Sxy150489 tx_ring = Adapter->tx_ring; 7763526Sxy150489 7773526Sxy150489 /* init the lists */ 7783526Sxy150489 /* 7793526Sxy150489 * Here we don't need to protect the lists using the 7804919Sxy150489 * usedlist_lock and freelist_lock, for they have 7813526Sxy150489 * been protected by the chip_lock. 7823526Sxy150489 */ 7833526Sxy150489 QUEUE_INIT_LIST(&tx_ring->used_list); 7843526Sxy150489 QUEUE_INIT_LIST(&tx_ring->free_list); 7853526Sxy150489 7863526Sxy150489 /* Go through and set up each SW_Packet */ 7873526Sxy150489 packet = tx_ring->packet_area; 7884919Sxy150489 for (i = 0; i < Adapter->tx_freelist_num; i++, packet++) { 7894919Sxy150489 /* Initialize this tx_sw_apcket area */ 7904919Sxy150489 e1000g_free_tx_swpkt(packet); 7914919Sxy150489 /* Add this tx_sw_packet to the free list */ 7923526Sxy150489 QUEUE_PUSH_TAIL(&tx_ring->free_list, 7933526Sxy150489 &packet->Link); 7943526Sxy150489 } 7953526Sxy150489 7963526Sxy150489 /* Setup TX descriptor pointers */ 7973526Sxy150489 tx_ring->tbd_next = tx_ring->tbd_first; 7983526Sxy150489 tx_ring->tbd_oldest = tx_ring->tbd_first; 7993526Sxy150489 8003526Sxy150489 /* 8013526Sxy150489 * Setup Hardware TX Registers 8023526Sxy150489 */ 8033526Sxy150489 /* Setup the Transmit Control Register (TCTL). */ 8043526Sxy150489 reg_tctl = E1000_TCTL_PSP | E1000_TCTL_EN | 8053526Sxy150489 (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT) | 8064919Sxy150489 (E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT) | 8074919Sxy150489 E1000_TCTL_RTLC; 8083526Sxy150489 8093526Sxy150489 /* Enable the MULR bit */ 8104919Sxy150489 if (hw->bus.type == e1000_bus_type_pci_express) 8113526Sxy150489 reg_tctl |= E1000_TCTL_MULR; 8123526Sxy150489 8134919Sxy150489 E1000_WRITE_REG(hw, E1000_TCTL, reg_tctl); 8143526Sxy150489 8154919Sxy150489 if ((hw->mac.type == e1000_82571) || (hw->mac.type == e1000_82572)) { 8163526Sxy150489 e1000_get_speed_and_duplex(hw, &speed, &duplex); 8173526Sxy150489 8186735Scc210113 reg_tarc = E1000_READ_REG(hw, E1000_TARC(0)); 8193526Sxy150489 reg_tarc |= (1 << 25); 8203526Sxy150489 if (speed == SPEED_1000) 8213526Sxy150489 reg_tarc |= (1 << 21); 8226735Scc210113 E1000_WRITE_REG(hw, E1000_TARC(0), reg_tarc); 8233526Sxy150489 8246735Scc210113 reg_tarc = E1000_READ_REG(hw, E1000_TARC(1)); 8253526Sxy150489 reg_tarc |= (1 << 25); 8263526Sxy150489 if (reg_tctl & E1000_TCTL_MULR) 8273526Sxy150489 reg_tarc &= ~(1 << 28); 8283526Sxy150489 else 8293526Sxy150489 reg_tarc |= (1 << 28); 8306735Scc210113 E1000_WRITE_REG(hw, E1000_TARC(1), reg_tarc); 8313526Sxy150489 8324919Sxy150489 } else if (hw->mac.type == e1000_80003es2lan) { 8336735Scc210113 reg_tarc = E1000_READ_REG(hw, E1000_TARC(0)); 8343526Sxy150489 reg_tarc |= 1; 8356735Scc210113 if (hw->phy.media_type == e1000_media_type_internal_serdes) 8363526Sxy150489 reg_tarc |= (1 << 20); 8376735Scc210113 E1000_WRITE_REG(hw, E1000_TARC(0), reg_tarc); 8383526Sxy150489 8396735Scc210113 reg_tarc = E1000_READ_REG(hw, E1000_TARC(1)); 8403526Sxy150489 reg_tarc |= 1; 8416735Scc210113 E1000_WRITE_REG(hw, E1000_TARC(1), reg_tarc); 8423526Sxy150489 } 8433526Sxy150489 8443526Sxy150489 /* Setup HW Base and Length of Tx descriptor area */ 8454919Sxy150489 size = (Adapter->tx_desc_num * sizeof (struct e1000_tx_desc)); 8466735Scc210113 E1000_WRITE_REG(hw, E1000_TDLEN(0), size); 8476735Scc210113 size = E1000_READ_REG(hw, E1000_TDLEN(0)); 8483526Sxy150489 8493526Sxy150489 buf_low = (uint32_t)tx_ring->tbd_dma_addr; 8503526Sxy150489 buf_high = (uint32_t)(tx_ring->tbd_dma_addr >> 32); 8513526Sxy150489 8526735Scc210113 E1000_WRITE_REG(hw, E1000_TDBAL(0), buf_low); 8536735Scc210113 E1000_WRITE_REG(hw, E1000_TDBAH(0), buf_high); 8543526Sxy150489 8553526Sxy150489 /* Setup our HW Tx Head & Tail descriptor pointers */ 8566735Scc210113 E1000_WRITE_REG(hw, E1000_TDH(0), 0); 8576735Scc210113 E1000_WRITE_REG(hw, E1000_TDT(0), 0); 8583526Sxy150489 8593526Sxy150489 /* Set the default values for the Tx Inter Packet Gap timer */ 8604919Sxy150489 if ((hw->mac.type == e1000_82542) && 8614919Sxy150489 ((hw->revision_id == E1000_REVISION_2) || 8624919Sxy150489 (hw->revision_id == E1000_REVISION_3))) { 8633526Sxy150489 reg_tipg = DEFAULT_82542_TIPG_IPGT; 8643526Sxy150489 reg_tipg |= 8653526Sxy150489 DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; 8663526Sxy150489 reg_tipg |= 8673526Sxy150489 DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; 8684919Sxy150489 } else { 8696735Scc210113 if (hw->phy.media_type == e1000_media_type_fiber) 8703526Sxy150489 reg_tipg = DEFAULT_82543_TIPG_IPGT_FIBER; 8713526Sxy150489 else 8723526Sxy150489 reg_tipg = DEFAULT_82543_TIPG_IPGT_COPPER; 8733526Sxy150489 reg_tipg |= 8743526Sxy150489 DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; 8753526Sxy150489 reg_tipg |= 8763526Sxy150489 DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; 8773526Sxy150489 } 8784919Sxy150489 E1000_WRITE_REG(hw, E1000_TIPG, reg_tipg); 8793526Sxy150489 8803526Sxy150489 /* Setup Transmit Interrupt Delay Value */ 8815882Syy150190 E1000_WRITE_REG(hw, E1000_TIDV, Adapter->tx_intr_delay); 8825882Syy150190 E1000G_DEBUGLOG_1(Adapter, E1000G_INFO_LEVEL, 8835882Syy150190 "E1000_TIDV: 0x%x\n", Adapter->tx_intr_delay); 8845882Syy150190 8855882Syy150190 if (hw->mac.type >= e1000_82540) { 8865882Syy150190 E1000_WRITE_REG(&Adapter->shared, E1000_TADV, 8875882Syy150190 Adapter->tx_intr_abs_delay); 8885882Syy150190 E1000G_DEBUGLOG_1(Adapter, E1000G_INFO_LEVEL, 8895882Syy150190 "E1000_TADV: 0x%x\n", Adapter->tx_intr_abs_delay); 8903526Sxy150489 } 8913526Sxy150489 8924919Sxy150489 tx_ring->tbd_avail = Adapter->tx_desc_num; 8934919Sxy150489 894*6986Smx205022 /* Initialize stored context information */ 895*6986Smx205022 bzero(&(tx_ring->pre_context), sizeof (context_data_t)); 8963526Sxy150489 } 8973526Sxy150489 8983526Sxy150489 /* 8994919Sxy150489 * e1000g_recycle - recycle the tx descriptors and tx sw packets 9003526Sxy150489 */ 9013526Sxy150489 int 9023526Sxy150489 e1000g_recycle(e1000g_tx_ring_t *tx_ring) 9033526Sxy150489 { 9043526Sxy150489 struct e1000g *Adapter; 9053526Sxy150489 LIST_DESCRIBER pending_list; 9064919Sxy150489 p_tx_sw_packet_t packet; 9073526Sxy150489 mblk_t *mp; 9083526Sxy150489 mblk_t *nmp; 9093526Sxy150489 struct e1000_tx_desc *descriptor; 9103526Sxy150489 int desc_count; 9115882Syy150190 int is_intr; 9123526Sxy150489 9133526Sxy150489 /* 9143526Sxy150489 * This function will examine each TxSwPacket in the 'used' queue 9153526Sxy150489 * if the e1000g is done with it then the associated resources (Tx 9163526Sxy150489 * Descriptors) will be "freed" and the TxSwPacket will be 9173526Sxy150489 * returned to the 'free' queue. 9183526Sxy150489 */ 9193526Sxy150489 Adapter = tx_ring->adapter; 9203526Sxy150489 9214919Sxy150489 packet = (p_tx_sw_packet_t)QUEUE_GET_HEAD(&tx_ring->used_list); 9223526Sxy150489 if (packet == NULL) { 9234919Sxy150489 tx_ring->recycle_fail = 0; 9244919Sxy150489 tx_ring->stall_watchdog = 0; 9253526Sxy150489 return (0); 9263526Sxy150489 } 9273526Sxy150489 9285882Syy150190 is_intr = servicing_interrupt(); 9295882Syy150190 9305882Syy150190 if (is_intr) 9315882Syy150190 mutex_enter(&tx_ring->usedlist_lock); 9325882Syy150190 else if (mutex_tryenter(&tx_ring->usedlist_lock) == 0) 9335882Syy150190 return (0); 9345882Syy150190 9355882Syy150190 desc_count = 0; 9365882Syy150190 QUEUE_INIT_LIST(&pending_list); 9375882Syy150190 9384919Sxy150489 /* Sync the Tx descriptor DMA buffer */ 9394919Sxy150489 (void) ddi_dma_sync(tx_ring->tbd_dma_handle, 9404919Sxy150489 0, 0, DDI_DMA_SYNC_FORKERNEL); 9415273Sgl147354 if (e1000g_check_dma_handle( 9425273Sgl147354 tx_ring->tbd_dma_handle) != DDI_FM_OK) { 9435882Syy150190 mutex_exit(&tx_ring->usedlist_lock); 9445273Sgl147354 ddi_fm_service_impact(Adapter->dip, DDI_SERVICE_DEGRADED); 9455273Sgl147354 Adapter->chip_state = E1000G_ERROR; 9465273Sgl147354 return (0); 9475273Sgl147354 } 9484919Sxy150489 9493526Sxy150489 /* 9503526Sxy150489 * While there are still TxSwPackets in the used queue check them 9513526Sxy150489 */ 9523526Sxy150489 while (packet = 9534919Sxy150489 (p_tx_sw_packet_t)QUEUE_GET_HEAD(&tx_ring->used_list)) { 9543526Sxy150489 9553526Sxy150489 /* 9563526Sxy150489 * Get hold of the next descriptor that the e1000g will 9573526Sxy150489 * report status back to (this will be the last descriptor 9584919Sxy150489 * of a given sw packet). We only want to free the 9594919Sxy150489 * sw packet (and it resources) if the e1000g is done 9603526Sxy150489 * with ALL of the descriptors. If the e1000g is done 9613526Sxy150489 * with the last one then it is done with all of them. 9623526Sxy150489 */ 9633526Sxy150489 ASSERT(packet->num_desc); 9644919Sxy150489 descriptor = tx_ring->tbd_oldest + (packet->num_desc - 1); 9653526Sxy150489 9663526Sxy150489 /* Check for wrap case */ 9673526Sxy150489 if (descriptor > tx_ring->tbd_last) 9684919Sxy150489 descriptor -= Adapter->tx_desc_num; 9693526Sxy150489 9703526Sxy150489 /* 9713526Sxy150489 * If the descriptor done bit is set free TxSwPacket and 9723526Sxy150489 * associated resources 9733526Sxy150489 */ 9743526Sxy150489 if (descriptor->upper.fields.status & E1000_TXD_STAT_DD) { 9753526Sxy150489 QUEUE_POP_HEAD(&tx_ring->used_list); 9763526Sxy150489 QUEUE_PUSH_TAIL(&pending_list, &packet->Link); 9773526Sxy150489 9783526Sxy150489 if (descriptor == tx_ring->tbd_last) 9793526Sxy150489 tx_ring->tbd_oldest = 9803526Sxy150489 tx_ring->tbd_first; 9813526Sxy150489 else 9823526Sxy150489 tx_ring->tbd_oldest = 9833526Sxy150489 descriptor + 1; 9843526Sxy150489 9853526Sxy150489 desc_count += packet->num_desc; 9863526Sxy150489 9875882Syy150190 if (is_intr && (desc_count >= Adapter->tx_recycle_num)) 9883526Sxy150489 break; 9893526Sxy150489 } else { 9903526Sxy150489 /* 9914919Sxy150489 * Found a sw packet that the e1000g is not done 9923526Sxy150489 * with then there is no reason to check the rest 9933526Sxy150489 * of the queue. 9943526Sxy150489 */ 9953526Sxy150489 break; 9963526Sxy150489 } 9973526Sxy150489 } 9983526Sxy150489 9994919Sxy150489 tx_ring->tbd_avail += desc_count; 10005882Syy150190 Adapter->tx_pkt_cnt += desc_count; 10014919Sxy150489 10023526Sxy150489 mutex_exit(&tx_ring->usedlist_lock); 10033526Sxy150489 10043526Sxy150489 if (desc_count == 0) { 10054919Sxy150489 tx_ring->recycle_fail++; 10064919Sxy150489 E1000G_DEBUG_STAT(tx_ring->stat_recycle_none); 10073526Sxy150489 return (0); 10083526Sxy150489 } 10093526Sxy150489 10104919Sxy150489 tx_ring->recycle_fail = 0; 10114919Sxy150489 tx_ring->stall_watchdog = 0; 10123526Sxy150489 10133526Sxy150489 mp = NULL; 10143526Sxy150489 nmp = NULL; 10154919Sxy150489 packet = (p_tx_sw_packet_t)QUEUE_GET_HEAD(&pending_list); 10163526Sxy150489 ASSERT(packet != NULL); 10173526Sxy150489 while (packet != NULL) { 10183526Sxy150489 if (packet->mp != NULL) { 10193526Sxy150489 ASSERT(packet->mp->b_next == NULL); 10203526Sxy150489 /* Assemble the message chain */ 10213526Sxy150489 if (mp == NULL) { 10223526Sxy150489 mp = packet->mp; 10233526Sxy150489 nmp = packet->mp; 10243526Sxy150489 } else { 10253526Sxy150489 nmp->b_next = packet->mp; 10263526Sxy150489 nmp = packet->mp; 10273526Sxy150489 } 10283526Sxy150489 /* Disconnect the message from the sw packet */ 10293526Sxy150489 packet->mp = NULL; 10303526Sxy150489 } 10313526Sxy150489 10323526Sxy150489 /* Free the TxSwPackets */ 10334919Sxy150489 e1000g_free_tx_swpkt(packet); 10343526Sxy150489 10354919Sxy150489 packet = (p_tx_sw_packet_t) 10363526Sxy150489 QUEUE_GET_NEXT(&pending_list, &packet->Link); 10373526Sxy150489 } 10383526Sxy150489 10393526Sxy150489 /* Return the TxSwPackets back to the FreeList */ 10403526Sxy150489 mutex_enter(&tx_ring->freelist_lock); 10413526Sxy150489 QUEUE_APPEND(&tx_ring->free_list, &pending_list); 10423526Sxy150489 mutex_exit(&tx_ring->freelist_lock); 10433526Sxy150489 10445882Syy150190 if (mp != NULL) 10455882Syy150190 freemsgchain(mp); 10465882Syy150190 10473526Sxy150489 return (desc_count); 10483526Sxy150489 } 10493526Sxy150489 /* 10503526Sxy150489 * 82544 Coexistence issue workaround: 10513526Sxy150489 * There are 2 issues. 10523526Sxy150489 * 1. If a 32 bit split completion happens from P64H2 and another 10533526Sxy150489 * agent drives a 64 bit request/split completion after ONLY 10543526Sxy150489 * 1 idle clock (BRCM/Emulex/Adaptec fiber channel cards) then 10553526Sxy150489 * 82544 has a problem where in to clock all the data in, it 10563526Sxy150489 * looks at REQ64# signal and since it has changed so fast (i.e. 1 10573526Sxy150489 * idle clock turn around), it will fail to clock all the data in. 10583526Sxy150489 * Data coming from certain ending addresses has exposure to this issue. 10593526Sxy150489 * 10603526Sxy150489 * To detect this issue, following equation can be used... 10613526Sxy150489 * SIZE[3:0] + ADDR[2:0] = SUM[3:0]. 10623526Sxy150489 * If SUM[3:0] is in between 1 to 4, we will have this issue. 10633526Sxy150489 * 10643526Sxy150489 * ROOT CAUSE: 10653526Sxy150489 * The erratum involves the 82544 PCIX elasticity FIFO implementations as 10663526Sxy150489 * 64-bit FIFO's and flushing of the final partial-bytes corresponding 10673526Sxy150489 * to the end of a requested read burst. Under a specific burst condition 10683526Sxy150489 * of ending-data alignment and 32-byte split-completions, the final 10693526Sxy150489 * byte(s) of split-completion data require an extra clock cycle to flush 10703526Sxy150489 * into 64-bit FIFO orientation. An incorrect logic dependency on the 10713526Sxy150489 * REQ64# signal occurring during during this clock cycle may cause the 10723526Sxy150489 * residual byte(s) to be lost, thereby rendering the internal DMA client 10733526Sxy150489 * forever awaiting the final byte(s) for an outbound data-fetch. The 10743526Sxy150489 * erratum is confirmed to *only* occur if certain subsequent external 10753526Sxy150489 * 64-bit PCIX bus transactions occur immediately (minimum possible bus 10763526Sxy150489 * turn- around) following the odd-aligned 32-bit split-completion 10773526Sxy150489 * containing the final byte(s). Intel has confirmed that this has been 10783526Sxy150489 * seen only with chipset/bridges which have the capability to provide 10793526Sxy150489 * 32-bit split-completion data, and in the presence of newer PCIX bus 10803526Sxy150489 * agents which fully-optimize the inter-transaction turn-around (zero 10813526Sxy150489 * additional initiator latency when pre-granted bus ownership). 10823526Sxy150489 * 10833526Sxy150489 * This issue does not exist in PCI bus mode, when any agent is operating 10843526Sxy150489 * in 32 bit only mode or on chipsets that do not do 32 bit split 10853526Sxy150489 * completions for 64 bit read requests (Serverworks chipsets). P64H2 does 10863526Sxy150489 * 32 bit split completions for any read request that has bit 2 set to 1 10873526Sxy150489 * for the requested address and read request size is more than 8 bytes. 10883526Sxy150489 * 10893526Sxy150489 * 2. Another issue is related to 82544 driving DACs under the similar 10903526Sxy150489 * scenario (32 bit split completion followed by 64 bit transaction with 10913526Sxy150489 * only 1 cycle turnaround). This issue is still being root caused. We 10923526Sxy150489 * think that both of these issues can be avoided if following workaround 10933526Sxy150489 * is implemented. It seems DAC issues is related to ending addresses being 10943526Sxy150489 * 0x9, 0xA, 0xB, 0xC and hence ending up at odd boundaries in elasticity 10953526Sxy150489 * FIFO which does not get flushed due to REQ64# dependency. We will only 10963526Sxy150489 * know the full story after it has been simulated successfully by HW team. 10973526Sxy150489 * 10983526Sxy150489 * WORKAROUND: 10993526Sxy150489 * Make sure we do not have ending address as 1,2,3,4(Hang) or 9,a,b,c(DAC) 11003526Sxy150489 */ 11013526Sxy150489 static uint32_t 11024919Sxy150489 e1000g_fill_82544_desc(uint64_t address, 11034919Sxy150489 size_t length, p_desc_array_t desc_array) 11043526Sxy150489 { 11053526Sxy150489 /* 11063526Sxy150489 * Since issue is sensitive to length and address. 11073526Sxy150489 * Let us first check the address... 11083526Sxy150489 */ 11093526Sxy150489 uint32_t safe_terminator; 11103526Sxy150489 11114919Sxy150489 if (length <= 4) { 11124919Sxy150489 desc_array->descriptor[0].address = address; 11134919Sxy150489 desc_array->descriptor[0].length = length; 11144919Sxy150489 desc_array->elements = 1; 11154919Sxy150489 return (desc_array->elements); 11163526Sxy150489 } 11173526Sxy150489 safe_terminator = 11184919Sxy150489 (uint32_t)((((uint32_t)address & 0x7) + 11194919Sxy150489 (length & 0xF)) & 0xF); 11203526Sxy150489 /* 11213526Sxy150489 * if it does not fall between 0x1 to 0x4 and 0x9 to 0xC then 11223526Sxy150489 * return 11233526Sxy150489 */ 11243526Sxy150489 if (safe_terminator == 0 || 11254919Sxy150489 (safe_terminator > 4 && safe_terminator < 9) || 11263526Sxy150489 (safe_terminator > 0xC && safe_terminator <= 0xF)) { 11274919Sxy150489 desc_array->descriptor[0].address = address; 11284919Sxy150489 desc_array->descriptor[0].length = length; 11294919Sxy150489 desc_array->elements = 1; 11304919Sxy150489 return (desc_array->elements); 11313526Sxy150489 } 11323526Sxy150489 11334919Sxy150489 desc_array->descriptor[0].address = address; 11344919Sxy150489 desc_array->descriptor[0].length = length - 4; 11354919Sxy150489 desc_array->descriptor[1].address = address + (length - 4); 11364919Sxy150489 desc_array->descriptor[1].length = 4; 11374919Sxy150489 desc_array->elements = 2; 11384919Sxy150489 return (desc_array->elements); 11393526Sxy150489 } 11403526Sxy150489 11413526Sxy150489 static int 11424919Sxy150489 e1000g_tx_copy(e1000g_tx_ring_t *tx_ring, p_tx_sw_packet_t packet, 1143*6986Smx205022 mblk_t *mp, boolean_t tx_undersize_flag) 11443526Sxy150489 { 11453526Sxy150489 size_t len; 11463526Sxy150489 size_t len1; 11473526Sxy150489 dma_buffer_t *tx_buf; 11483526Sxy150489 mblk_t *nmp; 11493526Sxy150489 boolean_t finished; 11503526Sxy150489 int desc_count; 11513526Sxy150489 11523526Sxy150489 desc_count = 0; 11533526Sxy150489 tx_buf = packet->tx_buf; 11543526Sxy150489 len = MBLKL(mp); 11553526Sxy150489 11563526Sxy150489 ASSERT((tx_buf->len + len) <= tx_buf->size); 11573526Sxy150489 11583526Sxy150489 if (len > 0) { 11593526Sxy150489 bcopy(mp->b_rptr, 11603526Sxy150489 tx_buf->address + tx_buf->len, 11613526Sxy150489 len); 11623526Sxy150489 tx_buf->len += len; 11633526Sxy150489 11643526Sxy150489 packet->num_mblk_frag++; 11653526Sxy150489 } 11663526Sxy150489 11673526Sxy150489 nmp = mp->b_cont; 11683526Sxy150489 if (nmp == NULL) { 11693526Sxy150489 finished = B_TRUE; 11703526Sxy150489 } else { 11713526Sxy150489 len1 = MBLKL(nmp); 11723526Sxy150489 if ((tx_buf->len + len1) > tx_buf->size) 11733526Sxy150489 finished = B_TRUE; 1174*6986Smx205022 else if (tx_undersize_flag) 11753526Sxy150489 finished = B_FALSE; 11764919Sxy150489 else if (len1 > tx_ring->adapter->tx_bcopy_thresh) 11773526Sxy150489 finished = B_TRUE; 11783526Sxy150489 else 11793526Sxy150489 finished = B_FALSE; 11803526Sxy150489 } 11813526Sxy150489 11823526Sxy150489 if (finished) { 11834919Sxy150489 E1000G_DEBUG_STAT_COND(tx_ring->stat_multi_copy, 11844919Sxy150489 (tx_buf->len > len)); 11853526Sxy150489 11863526Sxy150489 /* 11873526Sxy150489 * If the packet is smaller than 64 bytes, which is the 11883526Sxy150489 * minimum ethernet packet size, pad the packet to make 11893526Sxy150489 * it at least 60 bytes. The hardware will add 4 bytes 11903526Sxy150489 * for CRC. 11913526Sxy150489 */ 1192*6986Smx205022 if (tx_undersize_flag) { 11936394Scc210113 ASSERT(tx_buf->len < ETHERMIN); 11943526Sxy150489 11953526Sxy150489 bzero(tx_buf->address + tx_buf->len, 11966394Scc210113 ETHERMIN - tx_buf->len); 11976394Scc210113 tx_buf->len = ETHERMIN; 11983526Sxy150489 } 11993526Sxy150489 12003526Sxy150489 #ifdef __sparc 12014919Sxy150489 if (packet->dma_type == USE_DVMA) 12023526Sxy150489 dvma_sync(tx_buf->dma_handle, 0, DDI_DMA_SYNC_FORDEV); 12034919Sxy150489 else 12043526Sxy150489 (void) ddi_dma_sync(tx_buf->dma_handle, 0, 12053526Sxy150489 tx_buf->len, DDI_DMA_SYNC_FORDEV); 12064919Sxy150489 #else 12074919Sxy150489 (void) ddi_dma_sync(tx_buf->dma_handle, 0, 12084919Sxy150489 tx_buf->len, DDI_DMA_SYNC_FORDEV); 12094919Sxy150489 #endif 12103526Sxy150489 12113526Sxy150489 packet->data_transfer_type = USE_BCOPY; 12123526Sxy150489 12134919Sxy150489 desc_count = e1000g_fill_tx_desc(tx_ring, 12143526Sxy150489 packet, 12153526Sxy150489 tx_buf->dma_address, 12163526Sxy150489 tx_buf->len); 12173526Sxy150489 12183526Sxy150489 if (desc_count <= 0) 12193526Sxy150489 return (-1); 12203526Sxy150489 } 12213526Sxy150489 12223526Sxy150489 return (desc_count); 12233526Sxy150489 } 12243526Sxy150489 12253526Sxy150489 static int 12264919Sxy150489 e1000g_tx_bind(e1000g_tx_ring_t *tx_ring, p_tx_sw_packet_t packet, mblk_t *mp) 12273526Sxy150489 { 12283526Sxy150489 int j; 12293526Sxy150489 int mystat; 12303526Sxy150489 size_t len; 12313526Sxy150489 ddi_dma_cookie_t dma_cookie; 12323526Sxy150489 uint_t ncookies; 12333526Sxy150489 int desc_count; 12343526Sxy150489 uint32_t desc_total; 12353526Sxy150489 12363526Sxy150489 desc_total = 0; 12373526Sxy150489 len = MBLKL(mp); 12383526Sxy150489 12393526Sxy150489 /* 12403526Sxy150489 * ddi_dma_addr_bind_handle() allocates DMA resources for a 12413526Sxy150489 * memory object such that a device can perform DMA to or from 12423526Sxy150489 * the object. DMA resources are allocated considering the 12433526Sxy150489 * device's DMA attributes as expressed by ddi_dma_attr(9S) 12443526Sxy150489 * (see ddi_dma_alloc_handle(9F)). 12453526Sxy150489 * 12463526Sxy150489 * ddi_dma_addr_bind_handle() fills in the first DMA cookie 12473526Sxy150489 * pointed to by cookiep with the appropriate address, length, 12483526Sxy150489 * and bus type. *ccountp is set to the number of DMA cookies 12493526Sxy150489 * representing this DMA object. Subsequent DMA cookies must be 12503526Sxy150489 * retrieved by calling ddi_dma_nextcookie(9F) the number of 12513526Sxy150489 * times specified by *countp - 1. 12523526Sxy150489 */ 12533526Sxy150489 switch (packet->dma_type) { 12543526Sxy150489 #ifdef __sparc 12553526Sxy150489 case USE_DVMA: 12563526Sxy150489 dvma_kaddr_load(packet->tx_dma_handle, 12573526Sxy150489 (caddr_t)mp->b_rptr, len, 0, &dma_cookie); 12583526Sxy150489 12593526Sxy150489 dvma_sync(packet->tx_dma_handle, 0, 12603526Sxy150489 DDI_DMA_SYNC_FORDEV); 12613526Sxy150489 12623526Sxy150489 ncookies = 1; 12633526Sxy150489 packet->data_transfer_type = USE_DVMA; 12643526Sxy150489 break; 12653526Sxy150489 #endif 12663526Sxy150489 case USE_DMA: 12673526Sxy150489 if ((mystat = ddi_dma_addr_bind_handle( 12684608Syy150190 packet->tx_dma_handle, NULL, 12694608Syy150190 (caddr_t)mp->b_rptr, len, 12704608Syy150190 DDI_DMA_WRITE | DDI_DMA_STREAMING, 12714608Syy150190 DDI_DMA_DONTWAIT, 0, &dma_cookie, 12724608Syy150190 &ncookies)) != DDI_DMA_MAPPED) { 12733526Sxy150489 12744919Sxy150489 e1000g_log(tx_ring->adapter, CE_WARN, 12753526Sxy150489 "Couldn't bind mblk buffer to Tx DMA handle: " 12763526Sxy150489 "return: %X, Pkt: %X\n", 12773526Sxy150489 mystat, packet); 12783526Sxy150489 return (-1); 12793526Sxy150489 } 12803526Sxy150489 12813526Sxy150489 /* 12823526Sxy150489 * An implicit ddi_dma_sync() is done when the 12833526Sxy150489 * ddi_dma_addr_bind_handle() is called. So we 12843526Sxy150489 * don't need to explicitly call ddi_dma_sync() 12853526Sxy150489 * here any more. 12863526Sxy150489 */ 12873526Sxy150489 ASSERT(ncookies); 12884919Sxy150489 E1000G_DEBUG_STAT_COND(tx_ring->stat_multi_cookie, 12894919Sxy150489 (ncookies > 1)); 12903526Sxy150489 12913526Sxy150489 /* 12923526Sxy150489 * The data_transfer_type value must be set after the handle 12934919Sxy150489 * has been bound, for it will be used in e1000g_free_tx_swpkt() 12943526Sxy150489 * to decide whether we need to unbind the handle. 12953526Sxy150489 */ 12963526Sxy150489 packet->data_transfer_type = USE_DMA; 12973526Sxy150489 break; 12983526Sxy150489 default: 12993526Sxy150489 ASSERT(B_FALSE); 13003526Sxy150489 break; 13013526Sxy150489 } 13023526Sxy150489 13033526Sxy150489 packet->num_mblk_frag++; 13043526Sxy150489 13053526Sxy150489 /* 13063526Sxy150489 * Each address could span thru multpile cookie.. 13073526Sxy150489 * Each cookie will have one descriptor 13083526Sxy150489 */ 13093526Sxy150489 for (j = ncookies; j != 0; j--) { 13103526Sxy150489 13114919Sxy150489 desc_count = e1000g_fill_tx_desc(tx_ring, 13123526Sxy150489 packet, 13133526Sxy150489 dma_cookie.dmac_laddress, 13143526Sxy150489 dma_cookie.dmac_size); 13153526Sxy150489 13163526Sxy150489 if (desc_count <= 0) 13173526Sxy150489 return (-1); 13183526Sxy150489 13193526Sxy150489 desc_total += desc_count; 13203526Sxy150489 13213526Sxy150489 /* 13223526Sxy150489 * ddi_dma_nextcookie() retrieves subsequent DMA 13233526Sxy150489 * cookies for a DMA object. 13243526Sxy150489 * ddi_dma_nextcookie() fills in the 13253526Sxy150489 * ddi_dma_cookie(9S) structure pointed to by 13263526Sxy150489 * cookiep. The ddi_dma_cookie(9S) structure 13273526Sxy150489 * must be allocated prior to calling 13283526Sxy150489 * ddi_dma_nextcookie(). The DMA cookie count 13293526Sxy150489 * returned by ddi_dma_buf_bind_handle(9F), 13303526Sxy150489 * ddi_dma_addr_bind_handle(9F), or 13313526Sxy150489 * ddi_dma_getwin(9F) indicates the number of DMA 13323526Sxy150489 * cookies a DMA object consists of. If the 13333526Sxy150489 * resulting cookie count, N, is larger than 1, 13343526Sxy150489 * ddi_dma_nextcookie() must be called N-1 times 13353526Sxy150489 * to retrieve all DMA cookies. 13363526Sxy150489 */ 13373526Sxy150489 if (j > 1) { 13383526Sxy150489 ddi_dma_nextcookie(packet->tx_dma_handle, 13393526Sxy150489 &dma_cookie); 13403526Sxy150489 } 13413526Sxy150489 } 13423526Sxy150489 13433526Sxy150489 return (desc_total); 13443526Sxy150489 } 13453526Sxy150489 13463526Sxy150489 static void 1347*6986Smx205022 e1000g_fill_context_descriptor(context_data_t *cur_context, 1348*6986Smx205022 struct e1000_context_desc *context_desc) 13493526Sxy150489 { 1350*6986Smx205022 if (cur_context->cksum_flags & HCK_IPV4_HDRCKSUM) { 1351*6986Smx205022 context_desc->lower_setup.ip_fields.ipcss = 1352*6986Smx205022 cur_context->ether_header_size; 1353*6986Smx205022 context_desc->lower_setup.ip_fields.ipcso = 1354*6986Smx205022 cur_context->ether_header_size + 13553526Sxy150489 offsetof(struct ip, ip_sum); 1356*6986Smx205022 context_desc->lower_setup.ip_fields.ipcse = 1357*6986Smx205022 cur_context->ether_header_size + 1358*6986Smx205022 cur_context->cksum_start - 1; 13593526Sxy150489 } else 1360*6986Smx205022 context_desc->lower_setup.ip_config = 0; 13613526Sxy150489 1362*6986Smx205022 if (cur_context->cksum_flags & HCK_PARTIALCKSUM) { 13633526Sxy150489 /* 13643526Sxy150489 * The packet with same protocol has the following 13653526Sxy150489 * stuff and start offset: 13663526Sxy150489 * | Protocol | Stuff | Start | Checksum 13673526Sxy150489 * | | Offset | Offset | Enable 13683526Sxy150489 * | IPv4 + TCP | 0x24 | 0x14 | Yes 13693526Sxy150489 * | IPv4 + UDP | 0x1A | 0x14 | Yes 13703526Sxy150489 * | IPv6 + TCP | 0x20 | 0x10 | No 13713526Sxy150489 * | IPv6 + UDP | 0x14 | 0x10 | No 13723526Sxy150489 */ 1373*6986Smx205022 context_desc->upper_setup.tcp_fields.tucss = 1374*6986Smx205022 cur_context->cksum_start + cur_context->ether_header_size; 1375*6986Smx205022 context_desc->upper_setup.tcp_fields.tucso = 1376*6986Smx205022 cur_context->cksum_stuff + cur_context->ether_header_size; 1377*6986Smx205022 context_desc->upper_setup.tcp_fields.tucse = 0; 13783526Sxy150489 } else 1379*6986Smx205022 context_desc->upper_setup.tcp_config = 0; 13803526Sxy150489 1381*6986Smx205022 if (cur_context->lso_flag) { 1382*6986Smx205022 context_desc->tcp_seg_setup.fields.mss = cur_context->mss; 1383*6986Smx205022 context_desc->tcp_seg_setup.fields.hdr_len = 1384*6986Smx205022 cur_context->hdr_len; 1385*6986Smx205022 /* 1386*6986Smx205022 * workaround for 82546EB errata 23, status-writeback 1387*6986Smx205022 * reporting (RS) should not be set on context or 1388*6986Smx205022 * Null descriptors 1389*6986Smx205022 */ 1390*6986Smx205022 context_desc->cmd_and_length = E1000_TXD_CMD_DEXT 1391*6986Smx205022 | E1000_TXD_CMD_TSE | E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP 1392*6986Smx205022 | E1000_TXD_DTYP_C | cur_context->pay_len; 1393*6986Smx205022 } else { 1394*6986Smx205022 context_desc->cmd_and_length = E1000_TXD_CMD_DEXT 1395*6986Smx205022 | E1000_TXD_DTYP_C; 1396*6986Smx205022 /* 1397*6986Smx205022 * Zero out the options for TCP Segmentation Offload 1398*6986Smx205022 */ 1399*6986Smx205022 context_desc->tcp_seg_setup.data = 0; 1400*6986Smx205022 } 14013526Sxy150489 } 14023526Sxy150489 14033526Sxy150489 static int 14044919Sxy150489 e1000g_fill_tx_desc(e1000g_tx_ring_t *tx_ring, 14054919Sxy150489 p_tx_sw_packet_t packet, uint64_t address, size_t size) 14063526Sxy150489 { 14074919Sxy150489 struct e1000_hw *hw = &tx_ring->adapter->shared; 14084919Sxy150489 p_sw_desc_t desc; 14093526Sxy150489 14104919Sxy150489 if (hw->mac.type == e1000_82544) { 14114919Sxy150489 if (hw->bus.type == e1000_bus_type_pcix) 14124919Sxy150489 return (e1000g_tx_workaround_PCIX_82544(packet, 14134919Sxy150489 address, size)); 14143526Sxy150489 14154919Sxy150489 if (size > JUMBO_FRAG_LENGTH) 14164919Sxy150489 return (e1000g_tx_workaround_jumbo_82544(packet, 14174919Sxy150489 address, size)); 14183526Sxy150489 } 14193526Sxy150489 14204919Sxy150489 ASSERT(packet->num_desc < MAX_TX_DESC_PER_PACKET); 14214919Sxy150489 14224919Sxy150489 desc = &packet->desc[packet->num_desc]; 14234919Sxy150489 desc->address = address; 14244919Sxy150489 desc->length = size; 14254919Sxy150489 14264919Sxy150489 packet->num_desc++; 14274919Sxy150489 14284919Sxy150489 return (1); 14293526Sxy150489 } 14303526Sxy150489 14313526Sxy150489 static int 14324919Sxy150489 e1000g_tx_workaround_PCIX_82544(p_tx_sw_packet_t packet, 14334919Sxy150489 uint64_t address, size_t size) 14343526Sxy150489 { 14354919Sxy150489 p_sw_desc_t desc; 14363526Sxy150489 int desc_count; 14373526Sxy150489 long size_left; 14383526Sxy150489 size_t len; 14393526Sxy150489 uint32_t counter; 14403526Sxy150489 uint32_t array_elements; 14414919Sxy150489 desc_array_t desc_array; 14423526Sxy150489 14433526Sxy150489 /* 14443526Sxy150489 * Coexist Workaround for cordova: RP: 07/04/03 14453526Sxy150489 * 14463526Sxy150489 * RP: ERRATA: Workaround ISSUE: 14473526Sxy150489 * 8kb_buffer_Lockup CONTROLLER: Cordova Breakup 14483526Sxy150489 * Eachbuffer in to 8kb pieces until the 14493526Sxy150489 * remainder is < 8kb 14503526Sxy150489 */ 14513526Sxy150489 size_left = size; 14523526Sxy150489 desc_count = 0; 14533526Sxy150489 14543526Sxy150489 while (size_left > 0) { 14553526Sxy150489 if (size_left > MAX_TX_BUF_SIZE) 14563526Sxy150489 len = MAX_TX_BUF_SIZE; 14573526Sxy150489 else 14583526Sxy150489 len = size_left; 14593526Sxy150489 14603526Sxy150489 array_elements = e1000g_fill_82544_desc(address, 14613526Sxy150489 len, &desc_array); 14623526Sxy150489 14633526Sxy150489 for (counter = 0; counter < array_elements; counter++) { 14643526Sxy150489 ASSERT(packet->num_desc < MAX_TX_DESC_PER_PACKET); 14653526Sxy150489 /* 14663526Sxy150489 * Put in the buffer address 14673526Sxy150489 */ 14683526Sxy150489 desc = &packet->desc[packet->num_desc]; 14693526Sxy150489 14704919Sxy150489 desc->address = 14714919Sxy150489 desc_array.descriptor[counter].address; 14724919Sxy150489 desc->length = 14734919Sxy150489 desc_array.descriptor[counter].length; 14743526Sxy150489 14753526Sxy150489 packet->num_desc++; 14763526Sxy150489 desc_count++; 14773526Sxy150489 } /* for */ 14783526Sxy150489 14793526Sxy150489 /* 14803526Sxy150489 * Update the buffer address and length 14813526Sxy150489 */ 14823526Sxy150489 address += MAX_TX_BUF_SIZE; 14833526Sxy150489 size_left -= MAX_TX_BUF_SIZE; 14843526Sxy150489 } /* while */ 14853526Sxy150489 14863526Sxy150489 return (desc_count); 14873526Sxy150489 } 14883526Sxy150489 14893526Sxy150489 static int 14904919Sxy150489 e1000g_tx_workaround_jumbo_82544(p_tx_sw_packet_t packet, 14914919Sxy150489 uint64_t address, size_t size) 14923526Sxy150489 { 14934919Sxy150489 p_sw_desc_t desc; 14943526Sxy150489 int desc_count; 14953526Sxy150489 long size_left; 14963526Sxy150489 uint32_t offset; 14973526Sxy150489 14983526Sxy150489 /* 14993526Sxy150489 * Workaround for Jumbo Frames on Cordova 15003526Sxy150489 * PSD 06/01/2001 15013526Sxy150489 */ 15023526Sxy150489 size_left = size; 15033526Sxy150489 desc_count = 0; 15043526Sxy150489 offset = 0; 15053526Sxy150489 while (size_left > 0) { 15063526Sxy150489 ASSERT(packet->num_desc < MAX_TX_DESC_PER_PACKET); 15073526Sxy150489 15083526Sxy150489 desc = &packet->desc[packet->num_desc]; 15093526Sxy150489 15104919Sxy150489 desc->address = address + offset; 15113526Sxy150489 15123526Sxy150489 if (size_left > JUMBO_FRAG_LENGTH) 15134919Sxy150489 desc->length = JUMBO_FRAG_LENGTH; 15143526Sxy150489 else 15154919Sxy150489 desc->length = size_left; 15163526Sxy150489 15173526Sxy150489 packet->num_desc++; 15183526Sxy150489 desc_count++; 15193526Sxy150489 15204919Sxy150489 offset += desc->length; 15213526Sxy150489 size_left -= JUMBO_FRAG_LENGTH; 15223526Sxy150489 } 15233526Sxy150489 15243526Sxy150489 return (desc_count); 15253526Sxy150489 } 15263526Sxy150489 15274919Sxy150489 #pragma inline(e1000g_82547_tx_move_tail_work) 15284919Sxy150489 15293526Sxy150489 static void 15303526Sxy150489 e1000g_82547_tx_move_tail_work(e1000g_tx_ring_t *tx_ring) 15313526Sxy150489 { 15324919Sxy150489 struct e1000_hw *hw; 15333526Sxy150489 uint16_t hw_tdt; 15343526Sxy150489 uint16_t sw_tdt; 15353526Sxy150489 struct e1000_tx_desc *tx_desc; 15363526Sxy150489 uint16_t length = 0; 15373526Sxy150489 boolean_t eop = B_FALSE; 15383526Sxy150489 struct e1000g *Adapter; 15393526Sxy150489 15403526Sxy150489 Adapter = tx_ring->adapter; 15414919Sxy150489 hw = &Adapter->shared; 15423526Sxy150489 15436735Scc210113 hw_tdt = E1000_READ_REG(hw, E1000_TDT(0)); 15443526Sxy150489 sw_tdt = tx_ring->tbd_next - tx_ring->tbd_first; 15453526Sxy150489 15463526Sxy150489 while (hw_tdt != sw_tdt) { 15473526Sxy150489 tx_desc = &(tx_ring->tbd_first[hw_tdt]); 15483526Sxy150489 length += tx_desc->lower.flags.length; 15493526Sxy150489 eop = tx_desc->lower.data & E1000_TXD_CMD_EOP; 15504919Sxy150489 if (++hw_tdt == Adapter->tx_desc_num) 15513526Sxy150489 hw_tdt = 0; 15523526Sxy150489 15533526Sxy150489 if (eop) { 15543526Sxy150489 if ((Adapter->link_duplex == HALF_DUPLEX) && 15554919Sxy150489 (e1000_fifo_workaround_82547(hw, length) 15564919Sxy150489 != E1000_SUCCESS)) { 15573526Sxy150489 if (tx_ring->timer_enable_82547) { 15583526Sxy150489 ASSERT(tx_ring->timer_id_82547 == 0); 15593526Sxy150489 tx_ring->timer_id_82547 = 15603526Sxy150489 timeout(e1000g_82547_timeout, 15614608Syy150190 (void *)tx_ring, 15624608Syy150190 drv_usectohz(10000)); 15633526Sxy150489 } 15643526Sxy150489 return; 15653526Sxy150489 15663526Sxy150489 } else { 15676735Scc210113 E1000_WRITE_REG(hw, E1000_TDT(0), hw_tdt); 15684919Sxy150489 e1000_update_tx_fifo_head_82547(hw, length); 15693526Sxy150489 length = 0; 15703526Sxy150489 } 15713526Sxy150489 } 15723526Sxy150489 } 15733526Sxy150489 } 15743526Sxy150489 15753526Sxy150489 static void 15763526Sxy150489 e1000g_82547_timeout(void *arg) 15773526Sxy150489 { 15783526Sxy150489 e1000g_tx_ring_t *tx_ring; 15793526Sxy150489 15803526Sxy150489 tx_ring = (e1000g_tx_ring_t *)arg; 15813526Sxy150489 15823526Sxy150489 mutex_enter(&tx_ring->tx_lock); 15833526Sxy150489 15843526Sxy150489 tx_ring->timer_id_82547 = 0; 15853526Sxy150489 e1000g_82547_tx_move_tail_work(tx_ring); 15863526Sxy150489 15873526Sxy150489 mutex_exit(&tx_ring->tx_lock); 15883526Sxy150489 } 15893526Sxy150489 15903526Sxy150489 static void 15913526Sxy150489 e1000g_82547_tx_move_tail(e1000g_tx_ring_t *tx_ring) 15923526Sxy150489 { 15933526Sxy150489 timeout_id_t tid; 15943526Sxy150489 15953526Sxy150489 ASSERT(MUTEX_HELD(&tx_ring->tx_lock)); 15963526Sxy150489 15973526Sxy150489 tid = tx_ring->timer_id_82547; 15983526Sxy150489 tx_ring->timer_id_82547 = 0; 15993526Sxy150489 if (tid != 0) { 16003526Sxy150489 tx_ring->timer_enable_82547 = B_FALSE; 16013526Sxy150489 mutex_exit(&tx_ring->tx_lock); 16023526Sxy150489 16033526Sxy150489 (void) untimeout(tid); 16043526Sxy150489 16053526Sxy150489 mutex_enter(&tx_ring->tx_lock); 16063526Sxy150489 } 16073526Sxy150489 tx_ring->timer_enable_82547 = B_TRUE; 16083526Sxy150489 e1000g_82547_tx_move_tail_work(tx_ring); 16093526Sxy150489 } 1610