13dec9fcdSqs148142 /* 23dec9fcdSqs148142 * CDDL HEADER START 33dec9fcdSqs148142 * 43dec9fcdSqs148142 * The contents of this file are subject to the terms of the 53dec9fcdSqs148142 * Common Development and Distribution License (the "License"). 63dec9fcdSqs148142 * You may not use this file except in compliance with the License. 73dec9fcdSqs148142 * 83dec9fcdSqs148142 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93dec9fcdSqs148142 * or http://www.opensolaris.org/os/licensing. 103dec9fcdSqs148142 * See the License for the specific language governing permissions 113dec9fcdSqs148142 * and limitations under the License. 123dec9fcdSqs148142 * 133dec9fcdSqs148142 * When distributing Covered Code, include this CDDL HEADER in each 143dec9fcdSqs148142 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153dec9fcdSqs148142 * If applicable, add the following below this CDDL HEADER, with the 163dec9fcdSqs148142 * fields enclosed by brackets "[]" replaced with your own identifying 173dec9fcdSqs148142 * information: Portions Copyright [yyyy] [name of copyright owner] 183dec9fcdSqs148142 * 193dec9fcdSqs148142 * CDDL HEADER END 203dec9fcdSqs148142 */ 21c1374a13SSurya Prakki 223dec9fcdSqs148142 /* 230dc2366fSVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 243dec9fcdSqs148142 * Use is subject to license terms. 253dec9fcdSqs148142 */ 263dec9fcdSqs148142 273dec9fcdSqs148142 #include <hxge_impl.h> 283dec9fcdSqs148142 293dec9fcdSqs148142 extern uint32_t hxge_reclaim_pending; 303dec9fcdSqs148142 extern uint32_t hxge_bcopy_thresh; 313dec9fcdSqs148142 extern uint32_t hxge_dvma_thresh; 323dec9fcdSqs148142 extern uint32_t hxge_dma_stream_thresh; 333dec9fcdSqs148142 extern uint32_t hxge_tx_minfree; 343dec9fcdSqs148142 extern uint32_t hxge_tx_intr_thres; 353dec9fcdSqs148142 extern uint32_t hxge_tx_max_gathers; 363dec9fcdSqs148142 extern uint32_t hxge_tx_tiny_pack; 373dec9fcdSqs148142 extern uint32_t hxge_tx_use_bcopy; 383dec9fcdSqs148142 391ed83081SMichael Speer static int hxge_start(p_hxge_t hxgep, p_tx_ring_t tx_ring_p, p_mblk_t mp); 403dec9fcdSqs148142 411ed83081SMichael Speer void 421ed83081SMichael Speer hxge_tx_ring_task(void *arg) 431ed83081SMichael Speer { 441ed83081SMichael Speer p_tx_ring_t ring = (p_tx_ring_t)arg; 453dec9fcdSqs148142 461ed83081SMichael Speer MUTEX_ENTER(&ring->lock); 471ed83081SMichael Speer (void) hxge_txdma_reclaim(ring->hxgep, ring, 0); 481ed83081SMichael Speer MUTEX_EXIT(&ring->lock); 491ed83081SMichael Speer 501ed83081SMichael Speer mac_tx_ring_update(ring->hxgep->mach, ring->ring_handle); 511ed83081SMichael Speer } 521ed83081SMichael Speer 531ed83081SMichael Speer static void 541ed83081SMichael Speer hxge_tx_ring_dispatch(p_tx_ring_t ring) 551ed83081SMichael Speer { 561ed83081SMichael Speer /* 571ed83081SMichael Speer * Kick the ring task to reclaim some buffers. 581ed83081SMichael Speer */ 591ed83081SMichael Speer (void) ddi_taskq_dispatch(ring->taskq, 601ed83081SMichael Speer hxge_tx_ring_task, (void *)ring, DDI_SLEEP); 611ed83081SMichael Speer } 621ed83081SMichael Speer 631ed83081SMichael Speer mblk_t * 641ed83081SMichael Speer hxge_tx_ring_send(void *arg, mblk_t *mp) 651ed83081SMichael Speer { 661ed83081SMichael Speer p_hxge_ring_handle_t rhp = (p_hxge_ring_handle_t)arg; 671ed83081SMichael Speer p_hxge_t hxgep; 681ed83081SMichael Speer p_tx_ring_t tx_ring_p; 691ed83081SMichael Speer int status; 701ed83081SMichael Speer 711ed83081SMichael Speer ASSERT(rhp != NULL); 721ed83081SMichael Speer ASSERT((rhp->index >= 0) && (rhp->index < HXGE_MAX_TDCS)); 731ed83081SMichael Speer 741ed83081SMichael Speer hxgep = rhp->hxgep; 751ed83081SMichael Speer tx_ring_p = hxgep->tx_rings->rings[rhp->index]; 761ed83081SMichael Speer ASSERT(hxgep == tx_ring_p->hxgep); 771ed83081SMichael Speer 781ed83081SMichael Speer status = hxge_start(hxgep, tx_ring_p, mp); 791ed83081SMichael Speer if (status != 0) { 801ed83081SMichael Speer hxge_tx_ring_dispatch(tx_ring_p); 811ed83081SMichael Speer return (mp); 821ed83081SMichael Speer } 831ed83081SMichael Speer 841ed83081SMichael Speer return ((mblk_t *)NULL); 851ed83081SMichael Speer } 861ed83081SMichael Speer 871ed83081SMichael Speer static int 883dec9fcdSqs148142 hxge_start(p_hxge_t hxgep, p_tx_ring_t tx_ring_p, p_mblk_t mp) 893dec9fcdSqs148142 { 904d9de298SMichael Speer int dma_status, status = 0; 913dec9fcdSqs148142 p_tx_desc_t tx_desc_ring_vp; 923dec9fcdSqs148142 hpi_handle_t hpi_desc_handle; 933dec9fcdSqs148142 hxge_os_dma_handle_t tx_desc_dma_handle; 943dec9fcdSqs148142 p_tx_desc_t tx_desc_p; 953dec9fcdSqs148142 p_tx_msg_t tx_msg_ring; 963dec9fcdSqs148142 p_tx_msg_t tx_msg_p; 973dec9fcdSqs148142 tx_desc_t tx_desc, *tmp_desc_p; 983dec9fcdSqs148142 tx_desc_t sop_tx_desc, *sop_tx_desc_p; 993dec9fcdSqs148142 p_tx_pkt_header_t hdrp; 1003dec9fcdSqs148142 p_tx_pkt_hdr_all_t pkthdrp; 1013dec9fcdSqs148142 uint8_t npads = 0; 1023dec9fcdSqs148142 uint64_t dma_ioaddr; 1033dec9fcdSqs148142 uint32_t dma_flags; 1043dec9fcdSqs148142 int last_bidx; 1053dec9fcdSqs148142 uint8_t *b_rptr; 1063dec9fcdSqs148142 caddr_t kaddr; 1073dec9fcdSqs148142 uint32_t nmblks; 1083dec9fcdSqs148142 uint32_t ngathers; 1093dec9fcdSqs148142 uint32_t clen; 1103dec9fcdSqs148142 int len; 1113dec9fcdSqs148142 uint32_t pkt_len, pack_len, min_len; 1123dec9fcdSqs148142 uint32_t bcopy_thresh; 1133dec9fcdSqs148142 int i, cur_index, sop_index; 1143dec9fcdSqs148142 uint16_t tail_index; 1153dec9fcdSqs148142 boolean_t tail_wrap = B_FALSE; 1163dec9fcdSqs148142 hxge_dma_common_t desc_area; 1173dec9fcdSqs148142 hxge_os_dma_handle_t dma_handle; 1183dec9fcdSqs148142 ddi_dma_cookie_t dma_cookie; 1193dec9fcdSqs148142 hpi_handle_t hpi_handle; 1203dec9fcdSqs148142 p_mblk_t nmp; 1213dec9fcdSqs148142 p_mblk_t t_mp; 1223dec9fcdSqs148142 uint32_t ncookies; 1233dec9fcdSqs148142 boolean_t good_packet; 1243dec9fcdSqs148142 boolean_t mark_mode = B_FALSE; 1253dec9fcdSqs148142 p_hxge_stats_t statsp; 1263dec9fcdSqs148142 p_hxge_tx_ring_stats_t tdc_stats; 1273dec9fcdSqs148142 t_uscalar_t start_offset = 0; 1283dec9fcdSqs148142 t_uscalar_t stuff_offset = 0; 1293dec9fcdSqs148142 t_uscalar_t end_offset = 0; 1303dec9fcdSqs148142 t_uscalar_t value = 0; 1313dec9fcdSqs148142 t_uscalar_t cksum_flags = 0; 1323dec9fcdSqs148142 boolean_t cksum_on = B_FALSE; 1333dec9fcdSqs148142 uint32_t boff = 0; 1343dec9fcdSqs148142 uint64_t tot_xfer_len = 0, tmp_len = 0; 1353dec9fcdSqs148142 boolean_t header_set = B_FALSE; 1363dec9fcdSqs148142 tdc_tdr_kick_t kick; 137cf6ef894SMichael Speer uint32_t offset; 1383dec9fcdSqs148142 #ifdef HXGE_DEBUG 1393dec9fcdSqs148142 p_tx_desc_t tx_desc_ring_pp; 1403dec9fcdSqs148142 p_tx_desc_t tx_desc_pp; 1413dec9fcdSqs148142 tx_desc_t *save_desc_p; 1423dec9fcdSqs148142 int dump_len; 1433dec9fcdSqs148142 int sad_len; 1443dec9fcdSqs148142 uint64_t sad; 1453dec9fcdSqs148142 int xfer_len; 1463dec9fcdSqs148142 uint32_t msgsize; 1473dec9fcdSqs148142 #endif 1483dec9fcdSqs148142 1493dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 1503dec9fcdSqs148142 "==> hxge_start: tx dma channel %d", tx_ring_p->tdc)); 1513dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 1523dec9fcdSqs148142 "==> hxge_start: Starting tdc %d desc pending %d", 1533dec9fcdSqs148142 tx_ring_p->tdc, tx_ring_p->descs_pending)); 1543dec9fcdSqs148142 1553dec9fcdSqs148142 statsp = hxgep->statsp; 1563dec9fcdSqs148142 1573dec9fcdSqs148142 if (hxgep->statsp->port_stats.lb_mode == hxge_lb_normal) { 1583dec9fcdSqs148142 if (!statsp->mac_stats.link_up) { 1593dec9fcdSqs148142 freemsg(mp); 1603dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, "==> hxge_start: " 1613dec9fcdSqs148142 "link not up or LB mode")); 1623dec9fcdSqs148142 goto hxge_start_fail1; 1633dec9fcdSqs148142 } 1643dec9fcdSqs148142 } 1653dec9fcdSqs148142 1660dc2366fSVenugopal Iyer mac_hcksum_get(mp, &start_offset, &stuff_offset, &end_offset, &value, 1670dc2366fSVenugopal Iyer &cksum_flags); 1683dec9fcdSqs148142 if (!HXGE_IS_VLAN_PACKET(mp->b_rptr)) { 1693dec9fcdSqs148142 start_offset += sizeof (ether_header_t); 1703dec9fcdSqs148142 stuff_offset += sizeof (ether_header_t); 1713dec9fcdSqs148142 } else { 1723dec9fcdSqs148142 start_offset += sizeof (struct ether_vlan_header); 1733dec9fcdSqs148142 stuff_offset += sizeof (struct ether_vlan_header); 1743dec9fcdSqs148142 } 1753dec9fcdSqs148142 1763dec9fcdSqs148142 if (cksum_flags & HCK_PARTIALCKSUM) { 1773dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 1783dec9fcdSqs148142 "==> hxge_start: mp $%p len %d " 1793dec9fcdSqs148142 "cksum_flags 0x%x (partial checksum) ", 1803dec9fcdSqs148142 mp, MBLKL(mp), cksum_flags)); 1813dec9fcdSqs148142 cksum_on = B_TRUE; 1823dec9fcdSqs148142 } 1833dec9fcdSqs148142 1843dec9fcdSqs148142 MUTEX_ENTER(&tx_ring_p->lock); 1853dec9fcdSqs148142 start_again: 1863dec9fcdSqs148142 ngathers = 0; 1873dec9fcdSqs148142 sop_index = tx_ring_p->wr_index; 1883dec9fcdSqs148142 #ifdef HXGE_DEBUG 1893dec9fcdSqs148142 if (tx_ring_p->descs_pending) { 1903dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 1913dec9fcdSqs148142 "==> hxge_start: desc pending %d ", 1923dec9fcdSqs148142 tx_ring_p->descs_pending)); 1933dec9fcdSqs148142 } 1943dec9fcdSqs148142 1953dec9fcdSqs148142 dump_len = (int)(MBLKL(mp)); 1963dec9fcdSqs148142 dump_len = (dump_len > 128) ? 128: dump_len; 1973dec9fcdSqs148142 1983dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 1993dec9fcdSqs148142 "==> hxge_start: tdc %d: dumping ...: b_rptr $%p " 2003dec9fcdSqs148142 "(Before header reserve: ORIGINAL LEN %d)", 2013dec9fcdSqs148142 tx_ring_p->tdc, mp->b_rptr, dump_len)); 2023dec9fcdSqs148142 2033dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 2043dec9fcdSqs148142 "==> hxge_start: dump packets (IP ORIGINAL b_rptr $%p): %s", 2053dec9fcdSqs148142 mp->b_rptr, hxge_dump_packet((char *)mp->b_rptr, dump_len))); 2063dec9fcdSqs148142 #endif 2073dec9fcdSqs148142 2083dec9fcdSqs148142 tdc_stats = tx_ring_p->tdc_stats; 2093dec9fcdSqs148142 mark_mode = (tx_ring_p->descs_pending && 2103dec9fcdSqs148142 ((tx_ring_p->tx_ring_size - tx_ring_p->descs_pending) < 2113dec9fcdSqs148142 hxge_tx_minfree)); 2123dec9fcdSqs148142 2133dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 2143dec9fcdSqs148142 "TX Descriptor ring is channel %d mark mode %d", 2153dec9fcdSqs148142 tx_ring_p->tdc, mark_mode)); 2163dec9fcdSqs148142 2173dec9fcdSqs148142 if (!hxge_txdma_reclaim(hxgep, tx_ring_p, hxge_tx_minfree)) { 2183dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 2193dec9fcdSqs148142 "TX Descriptor ring is full: channel %d", tx_ring_p->tdc)); 2203dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 2213dec9fcdSqs148142 "TX Descriptor ring is full: channel %d", tx_ring_p->tdc)); 222*75d94465SJosef 'Jeff' Sipek (void) atomic_cas_32((uint32_t *)&tx_ring_p->queueing, 0, 1); 2233dec9fcdSqs148142 tdc_stats->tx_no_desc++; 2243dec9fcdSqs148142 MUTEX_EXIT(&tx_ring_p->lock); 2253dec9fcdSqs148142 status = 1; 2263dec9fcdSqs148142 goto hxge_start_fail1; 2273dec9fcdSqs148142 } 2283dec9fcdSqs148142 2293dec9fcdSqs148142 nmp = mp; 2303dec9fcdSqs148142 i = sop_index = tx_ring_p->wr_index; 2313dec9fcdSqs148142 nmblks = 0; 2323dec9fcdSqs148142 ngathers = 0; 2333dec9fcdSqs148142 pkt_len = 0; 2343dec9fcdSqs148142 pack_len = 0; 2353dec9fcdSqs148142 clen = 0; 2363dec9fcdSqs148142 last_bidx = -1; 2373dec9fcdSqs148142 good_packet = B_TRUE; 2383dec9fcdSqs148142 2393dec9fcdSqs148142 desc_area = tx_ring_p->tdc_desc; 2403dec9fcdSqs148142 hpi_handle = desc_area.hpi_handle; 2413dec9fcdSqs148142 hpi_desc_handle.regh = (hxge_os_acc_handle_t) 2423dec9fcdSqs148142 DMA_COMMON_ACC_HANDLE(desc_area); 243fe930412Sqs148142 hpi_desc_handle.hxgep = hxgep; 2443dec9fcdSqs148142 tx_desc_ring_vp = (p_tx_desc_t)DMA_COMMON_VPTR(desc_area); 2453dec9fcdSqs148142 #ifdef HXGE_DEBUG 246fe930412Sqs148142 #if defined(__i386) 247fe930412Sqs148142 tx_desc_ring_pp = (p_tx_desc_t)(uint32_t)DMA_COMMON_IOADDR(desc_area); 248fe930412Sqs148142 #else 2493dec9fcdSqs148142 tx_desc_ring_pp = (p_tx_desc_t)DMA_COMMON_IOADDR(desc_area); 2503dec9fcdSqs148142 #endif 251fe930412Sqs148142 #endif 2523dec9fcdSqs148142 tx_desc_dma_handle = (hxge_os_dma_handle_t)DMA_COMMON_HANDLE(desc_area); 2533dec9fcdSqs148142 tx_msg_ring = tx_ring_p->tx_msg_ring; 2543dec9fcdSqs148142 2553dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, "==> hxge_start: wr_index %d i %d", 2563dec9fcdSqs148142 sop_index, i)); 2573dec9fcdSqs148142 2583dec9fcdSqs148142 #ifdef HXGE_DEBUG 2593dec9fcdSqs148142 msgsize = msgdsize(nmp); 2603dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 2613dec9fcdSqs148142 "==> hxge_start(1): wr_index %d i %d msgdsize %d", 2623dec9fcdSqs148142 sop_index, i, msgsize)); 2633dec9fcdSqs148142 #endif 2643dec9fcdSqs148142 /* 2653dec9fcdSqs148142 * The first 16 bytes of the premapped buffer are reserved 2663dec9fcdSqs148142 * for header. No padding will be used. 2673dec9fcdSqs148142 */ 2683dec9fcdSqs148142 pkt_len = pack_len = boff = TX_PKT_HEADER_SIZE; 2693dec9fcdSqs148142 if (hxge_tx_use_bcopy) { 2703dec9fcdSqs148142 bcopy_thresh = (hxge_bcopy_thresh - TX_PKT_HEADER_SIZE); 2713dec9fcdSqs148142 } else { 2723dec9fcdSqs148142 bcopy_thresh = (TX_BCOPY_SIZE - TX_PKT_HEADER_SIZE); 2733dec9fcdSqs148142 } 2743dec9fcdSqs148142 while (nmp) { 2753dec9fcdSqs148142 good_packet = B_TRUE; 2763dec9fcdSqs148142 b_rptr = nmp->b_rptr; 2773dec9fcdSqs148142 len = MBLKL(nmp); 2783dec9fcdSqs148142 if (len <= 0) { 2793dec9fcdSqs148142 nmp = nmp->b_cont; 2803dec9fcdSqs148142 continue; 2813dec9fcdSqs148142 } 2823dec9fcdSqs148142 nmblks++; 2833dec9fcdSqs148142 2843dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, "==> hxge_start(1): nmblks %d " 2853dec9fcdSqs148142 "len %d pkt_len %d pack_len %d", 2863dec9fcdSqs148142 nmblks, len, pkt_len, pack_len)); 2873dec9fcdSqs148142 /* 2883dec9fcdSqs148142 * Hardware limits the transfer length to 4K. 2893dec9fcdSqs148142 * If len is more than 4K, we need to break 2903dec9fcdSqs148142 * nmp into two chunks: Make first chunk smaller 2913dec9fcdSqs148142 * than 4K. The second chunk will be broken into 2923dec9fcdSqs148142 * less than 4K (if needed) during the next pass. 2933dec9fcdSqs148142 */ 2943dec9fcdSqs148142 if (len > (TX_MAX_TRANSFER_LENGTH - TX_PKT_HEADER_SIZE)) { 2953dec9fcdSqs148142 if ((t_mp = dupb(nmp)) != NULL) { 2963dec9fcdSqs148142 nmp->b_wptr = nmp->b_rptr + 2973dec9fcdSqs148142 (TX_MAX_TRANSFER_LENGTH - 2983dec9fcdSqs148142 TX_PKT_HEADER_SIZE); 2993dec9fcdSqs148142 t_mp->b_rptr = nmp->b_wptr; 3003dec9fcdSqs148142 t_mp->b_cont = nmp->b_cont; 3013dec9fcdSqs148142 nmp->b_cont = t_mp; 3023dec9fcdSqs148142 len = MBLKL(nmp); 3033dec9fcdSqs148142 } else { 3043dec9fcdSqs148142 good_packet = B_FALSE; 3053dec9fcdSqs148142 goto hxge_start_fail2; 3063dec9fcdSqs148142 } 3073dec9fcdSqs148142 } 3083dec9fcdSqs148142 tx_desc.value = 0; 3093dec9fcdSqs148142 tx_desc_p = &tx_desc_ring_vp[i]; 3103dec9fcdSqs148142 #ifdef HXGE_DEBUG 3113dec9fcdSqs148142 tx_desc_pp = &tx_desc_ring_pp[i]; 3123dec9fcdSqs148142 #endif 3133dec9fcdSqs148142 tx_msg_p = &tx_msg_ring[i]; 3143dec9fcdSqs148142 #if defined(__i386) 3153dec9fcdSqs148142 hpi_desc_handle.regp = (uint32_t)tx_desc_p; 3163dec9fcdSqs148142 #else 3173dec9fcdSqs148142 hpi_desc_handle.regp = (uint64_t)tx_desc_p; 3183dec9fcdSqs148142 #endif 3193dec9fcdSqs148142 if (!header_set && 3203dec9fcdSqs148142 ((!hxge_tx_use_bcopy && (len > TX_BCOPY_SIZE)) || 3213dec9fcdSqs148142 (len >= bcopy_thresh))) { 3223dec9fcdSqs148142 header_set = B_TRUE; 3233dec9fcdSqs148142 bcopy_thresh += TX_PKT_HEADER_SIZE; 3243dec9fcdSqs148142 boff = 0; 3253dec9fcdSqs148142 pack_len = 0; 3263dec9fcdSqs148142 kaddr = (caddr_t)DMA_COMMON_VPTR(tx_msg_p->buf_dma); 3273dec9fcdSqs148142 hdrp = (p_tx_pkt_header_t)kaddr; 3283dec9fcdSqs148142 clen = pkt_len; 3293dec9fcdSqs148142 dma_handle = tx_msg_p->buf_dma_handle; 3303dec9fcdSqs148142 dma_ioaddr = DMA_COMMON_IOADDR(tx_msg_p->buf_dma); 331cf6ef894SMichael Speer offset = tx_msg_p->offset_index * hxge_bcopy_thresh; 3323dec9fcdSqs148142 (void) ddi_dma_sync(dma_handle, 333cf6ef894SMichael Speer offset, hxge_bcopy_thresh, DDI_DMA_SYNC_FORDEV); 3343dec9fcdSqs148142 3353dec9fcdSqs148142 tx_msg_p->flags.dma_type = USE_BCOPY; 3363dec9fcdSqs148142 goto hxge_start_control_header_only; 3373dec9fcdSqs148142 } 3383dec9fcdSqs148142 3393dec9fcdSqs148142 pkt_len += len; 3403dec9fcdSqs148142 pack_len += len; 3413dec9fcdSqs148142 3423dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 3433dec9fcdSqs148142 "==> hxge_start(3): desc entry %d DESC IOADDR $%p " 3443dec9fcdSqs148142 "desc_vp $%p tx_desc_p $%p desc_pp $%p tx_desc_pp $%p " 3453dec9fcdSqs148142 "len %d pkt_len %d pack_len %d", 3463dec9fcdSqs148142 i, 3473dec9fcdSqs148142 DMA_COMMON_IOADDR(desc_area), 3483dec9fcdSqs148142 tx_desc_ring_vp, tx_desc_p, 3493dec9fcdSqs148142 tx_desc_ring_pp, tx_desc_pp, 3503dec9fcdSqs148142 len, pkt_len, pack_len)); 3513dec9fcdSqs148142 3523dec9fcdSqs148142 if (len < bcopy_thresh) { 3533dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 3543dec9fcdSqs148142 "==> hxge_start(4): USE BCOPY: ")); 3553dec9fcdSqs148142 if (hxge_tx_tiny_pack) { 3563dec9fcdSqs148142 uint32_t blst = TXDMA_DESC_NEXT_INDEX(i, -1, 3573dec9fcdSqs148142 tx_ring_p->tx_wrap_mask); 3583dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 3593dec9fcdSqs148142 "==> hxge_start(5): pack")); 3603dec9fcdSqs148142 if ((pack_len <= bcopy_thresh) && 3613dec9fcdSqs148142 (last_bidx == blst)) { 3623dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 3633dec9fcdSqs148142 "==> hxge_start: pack(6) " 3643dec9fcdSqs148142 "(pkt_len %d pack_len %d)", 3653dec9fcdSqs148142 pkt_len, pack_len)); 3663dec9fcdSqs148142 i = blst; 3673dec9fcdSqs148142 tx_desc_p = &tx_desc_ring_vp[i]; 3683dec9fcdSqs148142 #ifdef HXGE_DEBUG 3693dec9fcdSqs148142 tx_desc_pp = &tx_desc_ring_pp[i]; 3703dec9fcdSqs148142 #endif 3713dec9fcdSqs148142 tx_msg_p = &tx_msg_ring[i]; 3723dec9fcdSqs148142 boff = pack_len - len; 3733dec9fcdSqs148142 ngathers--; 3743dec9fcdSqs148142 } else if (pack_len > bcopy_thresh && 3753dec9fcdSqs148142 header_set) { 3763dec9fcdSqs148142 pack_len = len; 3773dec9fcdSqs148142 boff = 0; 3783dec9fcdSqs148142 bcopy_thresh = hxge_bcopy_thresh; 3793dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 3803dec9fcdSqs148142 "==> hxge_start(7): > max NEW " 3813dec9fcdSqs148142 "bcopy thresh %d " 3823dec9fcdSqs148142 "pkt_len %d pack_len %d(next)", 3833dec9fcdSqs148142 bcopy_thresh, pkt_len, pack_len)); 3843dec9fcdSqs148142 } 3853dec9fcdSqs148142 last_bidx = i; 3863dec9fcdSqs148142 } 3873dec9fcdSqs148142 kaddr = (caddr_t)DMA_COMMON_VPTR(tx_msg_p->buf_dma); 3883dec9fcdSqs148142 if ((boff == TX_PKT_HEADER_SIZE) && (nmblks == 1)) { 3893dec9fcdSqs148142 hdrp = (p_tx_pkt_header_t)kaddr; 3903dec9fcdSqs148142 header_set = B_TRUE; 3913dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 3923dec9fcdSqs148142 "==> hxge_start(7_x2): " 3933dec9fcdSqs148142 "pkt_len %d pack_len %d (new hdrp $%p)", 3943dec9fcdSqs148142 pkt_len, pack_len, hdrp)); 3953dec9fcdSqs148142 } 3963dec9fcdSqs148142 tx_msg_p->flags.dma_type = USE_BCOPY; 3973dec9fcdSqs148142 kaddr += boff; 3983dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 3993dec9fcdSqs148142 "==> hxge_start(8): USE BCOPY: before bcopy " 4003dec9fcdSqs148142 "DESC IOADDR $%p entry %d bcopy packets %d " 4013dec9fcdSqs148142 "bcopy kaddr $%p bcopy ioaddr (SAD) $%p " 4023dec9fcdSqs148142 "bcopy clen %d bcopy boff %d", 4033dec9fcdSqs148142 DMA_COMMON_IOADDR(desc_area), i, 4043dec9fcdSqs148142 tdc_stats->tx_hdr_pkts, kaddr, dma_ioaddr, 4053dec9fcdSqs148142 clen, boff)); 4063dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 4073dec9fcdSqs148142 "==> hxge_start: 1USE BCOPY: ")); 4083dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 4093dec9fcdSqs148142 "==> hxge_start: 2USE BCOPY: ")); 4103dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, "==> hxge_start: " 4113dec9fcdSqs148142 "last USE BCOPY: copy from b_rptr $%p " 4123dec9fcdSqs148142 "to KADDR $%p (len %d offset %d", 4133dec9fcdSqs148142 b_rptr, kaddr, len, boff)); 4143dec9fcdSqs148142 bcopy(b_rptr, kaddr, len); 4153dec9fcdSqs148142 #ifdef HXGE_DEBUG 4163dec9fcdSqs148142 dump_len = (len > 128) ? 128: len; 4173dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 4183dec9fcdSqs148142 "==> hxge_start: dump packets " 4193dec9fcdSqs148142 "(After BCOPY len %d)" 4203dec9fcdSqs148142 "(b_rptr $%p): %s", len, nmp->b_rptr, 4213dec9fcdSqs148142 hxge_dump_packet((char *)nmp->b_rptr, 4223dec9fcdSqs148142 dump_len))); 4233dec9fcdSqs148142 #endif 4243dec9fcdSqs148142 dma_handle = tx_msg_p->buf_dma_handle; 4253dec9fcdSqs148142 dma_ioaddr = DMA_COMMON_IOADDR(tx_msg_p->buf_dma); 426cf6ef894SMichael Speer offset = tx_msg_p->offset_index * hxge_bcopy_thresh; 4273dec9fcdSqs148142 (void) ddi_dma_sync(dma_handle, 428cf6ef894SMichael Speer offset, hxge_bcopy_thresh, DDI_DMA_SYNC_FORDEV); 4293dec9fcdSqs148142 clen = len + boff; 4303dec9fcdSqs148142 tdc_stats->tx_hdr_pkts++; 4313dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, "==> hxge_start(9): " 4323dec9fcdSqs148142 "USE BCOPY: DESC IOADDR $%p entry %d " 4333dec9fcdSqs148142 "bcopy packets %d bcopy kaddr $%p " 4343dec9fcdSqs148142 "bcopy ioaddr (SAD) $%p bcopy clen %d " 4353dec9fcdSqs148142 "bcopy boff %d", 4363dec9fcdSqs148142 DMA_COMMON_IOADDR(desc_area), i, 4373dec9fcdSqs148142 tdc_stats->tx_hdr_pkts, kaddr, dma_ioaddr, 4383dec9fcdSqs148142 clen, boff)); 4393dec9fcdSqs148142 } else { 4403dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 4413dec9fcdSqs148142 "==> hxge_start(12): USE DVMA: len %d", len)); 4423dec9fcdSqs148142 tx_msg_p->flags.dma_type = USE_DMA; 4433dec9fcdSqs148142 dma_flags = DDI_DMA_WRITE; 4443dec9fcdSqs148142 if (len < hxge_dma_stream_thresh) { 4453dec9fcdSqs148142 dma_flags |= DDI_DMA_CONSISTENT; 4463dec9fcdSqs148142 } else { 4473dec9fcdSqs148142 dma_flags |= DDI_DMA_STREAMING; 4483dec9fcdSqs148142 } 4493dec9fcdSqs148142 4503dec9fcdSqs148142 dma_handle = tx_msg_p->dma_handle; 4514d9de298SMichael Speer dma_status = ddi_dma_addr_bind_handle(dma_handle, NULL, 4523dec9fcdSqs148142 (caddr_t)b_rptr, len, dma_flags, 4533dec9fcdSqs148142 DDI_DMA_DONTWAIT, NULL, 4543dec9fcdSqs148142 &dma_cookie, &ncookies); 4554d9de298SMichael Speer if (dma_status == DDI_DMA_MAPPED) { 4563dec9fcdSqs148142 dma_ioaddr = dma_cookie.dmac_laddress; 4573dec9fcdSqs148142 len = (int)dma_cookie.dmac_size; 4583dec9fcdSqs148142 clen = (uint32_t)dma_cookie.dmac_size; 4593dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 4603dec9fcdSqs148142 "==> hxge_start(12_1): " 4613dec9fcdSqs148142 "USE DVMA: len %d clen %d ngathers %d", 4623dec9fcdSqs148142 len, clen, ngathers)); 4633dec9fcdSqs148142 #if defined(__i386) 4643dec9fcdSqs148142 hpi_desc_handle.regp = (uint32_t)tx_desc_p; 4653dec9fcdSqs148142 #else 4663dec9fcdSqs148142 hpi_desc_handle.regp = (uint64_t)tx_desc_p; 4673dec9fcdSqs148142 #endif 4683dec9fcdSqs148142 while (ncookies > 1) { 4693dec9fcdSqs148142 ngathers++; 4703dec9fcdSqs148142 /* 4713dec9fcdSqs148142 * this is the fix for multiple 4723dec9fcdSqs148142 * cookies, which are basically 4733dec9fcdSqs148142 * a descriptor entry, we don't set 4743dec9fcdSqs148142 * SOP bit as well as related fields 4753dec9fcdSqs148142 */ 4763dec9fcdSqs148142 4773dec9fcdSqs148142 (void) hpi_txdma_desc_gather_set( 4783dec9fcdSqs148142 hpi_desc_handle, &tx_desc, 4793dec9fcdSqs148142 (ngathers -1), mark_mode, 4803dec9fcdSqs148142 ngathers, dma_ioaddr, clen); 4813dec9fcdSqs148142 tx_msg_p->tx_msg_size = clen; 4823dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 4833dec9fcdSqs148142 "==> hxge_start: DMA " 4843dec9fcdSqs148142 "ncookie %d ngathers %d " 4853dec9fcdSqs148142 "dma_ioaddr $%p len %d" 4863dec9fcdSqs148142 "desc $%p descp $%p (%d)", 4873dec9fcdSqs148142 ncookies, ngathers, 4883dec9fcdSqs148142 dma_ioaddr, clen, 4893dec9fcdSqs148142 *tx_desc_p, tx_desc_p, i)); 4903dec9fcdSqs148142 4913dec9fcdSqs148142 ddi_dma_nextcookie(dma_handle, 4923dec9fcdSqs148142 &dma_cookie); 4933dec9fcdSqs148142 dma_ioaddr = dma_cookie.dmac_laddress; 4943dec9fcdSqs148142 4953dec9fcdSqs148142 len = (int)dma_cookie.dmac_size; 4963dec9fcdSqs148142 clen = (uint32_t)dma_cookie.dmac_size; 4973dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 4983dec9fcdSqs148142 "==> hxge_start(12_2): " 4993dec9fcdSqs148142 "USE DVMA: len %d clen %d ", 5003dec9fcdSqs148142 len, clen)); 5013dec9fcdSqs148142 5023dec9fcdSqs148142 i = TXDMA_DESC_NEXT_INDEX(i, 1, 5033dec9fcdSqs148142 tx_ring_p->tx_wrap_mask); 5043dec9fcdSqs148142 tx_desc_p = &tx_desc_ring_vp[i]; 5053dec9fcdSqs148142 5063dec9fcdSqs148142 hpi_desc_handle.regp = 5073dec9fcdSqs148142 #if defined(__i386) 5083dec9fcdSqs148142 (uint32_t)tx_desc_p; 5093dec9fcdSqs148142 #else 5103dec9fcdSqs148142 (uint64_t)tx_desc_p; 5113dec9fcdSqs148142 #endif 5123dec9fcdSqs148142 tx_msg_p = &tx_msg_ring[i]; 5133dec9fcdSqs148142 tx_msg_p->flags.dma_type = USE_NONE; 5143dec9fcdSqs148142 tx_desc.value = 0; 5153dec9fcdSqs148142 ncookies--; 5163dec9fcdSqs148142 } 5173dec9fcdSqs148142 tdc_stats->tx_ddi_pkts++; 5183dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 5193dec9fcdSqs148142 "==> hxge_start: DMA: ddi packets %d", 5203dec9fcdSqs148142 tdc_stats->tx_ddi_pkts)); 5213dec9fcdSqs148142 } else { 5223dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 5233dec9fcdSqs148142 "dma mapping failed for %d " 5243dec9fcdSqs148142 "bytes addr $%p flags %x (%d)", 5253dec9fcdSqs148142 len, b_rptr, status, status)); 5263dec9fcdSqs148142 good_packet = B_FALSE; 5273dec9fcdSqs148142 tdc_stats->tx_dma_bind_fail++; 5283dec9fcdSqs148142 tx_msg_p->flags.dma_type = USE_NONE; 5294d9de298SMichael Speer status = 1; 5303dec9fcdSqs148142 goto hxge_start_fail2; 5313dec9fcdSqs148142 } 5323dec9fcdSqs148142 } /* ddi dvma */ 5333dec9fcdSqs148142 5343dec9fcdSqs148142 nmp = nmp->b_cont; 5353dec9fcdSqs148142 hxge_start_control_header_only: 5363dec9fcdSqs148142 #if defined(__i386) 5373dec9fcdSqs148142 hpi_desc_handle.regp = (uint32_t)tx_desc_p; 5383dec9fcdSqs148142 #else 5393dec9fcdSqs148142 hpi_desc_handle.regp = (uint64_t)tx_desc_p; 5403dec9fcdSqs148142 #endif 5413dec9fcdSqs148142 ngathers++; 5423dec9fcdSqs148142 5433dec9fcdSqs148142 if (ngathers == 1) { 5443dec9fcdSqs148142 #ifdef HXGE_DEBUG 5453dec9fcdSqs148142 save_desc_p = &sop_tx_desc; 5463dec9fcdSqs148142 #endif 5473dec9fcdSqs148142 sop_tx_desc_p = &sop_tx_desc; 5483dec9fcdSqs148142 sop_tx_desc_p->value = 0; 5493dec9fcdSqs148142 sop_tx_desc_p->bits.tr_len = clen; 550fe930412Sqs148142 sop_tx_desc_p->bits.sad = dma_ioaddr >> 32; 551fe930412Sqs148142 sop_tx_desc_p->bits.sad_l = dma_ioaddr & 0xffffffff; 5523dec9fcdSqs148142 } else { 5533dec9fcdSqs148142 #ifdef HXGE_DEBUG 5543dec9fcdSqs148142 save_desc_p = &tx_desc; 5553dec9fcdSqs148142 #endif 5563dec9fcdSqs148142 tmp_desc_p = &tx_desc; 5573dec9fcdSqs148142 tmp_desc_p->value = 0; 5583dec9fcdSqs148142 tmp_desc_p->bits.tr_len = clen; 559fe930412Sqs148142 tmp_desc_p->bits.sad = dma_ioaddr >> 32; 560fe930412Sqs148142 tmp_desc_p->bits.sad_l = dma_ioaddr & 0xffffffff; 5613dec9fcdSqs148142 5623dec9fcdSqs148142 tx_desc_p->value = tmp_desc_p->value; 5633dec9fcdSqs148142 } 5643dec9fcdSqs148142 5653dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 5663dec9fcdSqs148142 "==> hxge_start(13): Desc_entry %d ngathers %d " 5673dec9fcdSqs148142 "desc_vp $%p tx_desc_p $%p " 5683dec9fcdSqs148142 "len %d clen %d pkt_len %d pack_len %d nmblks %d " 5693dec9fcdSqs148142 "dma_ioaddr (SAD) $%p mark %d", 5703dec9fcdSqs148142 i, ngathers, tx_desc_ring_vp, tx_desc_p, 5713dec9fcdSqs148142 len, clen, pkt_len, pack_len, nmblks, 5723dec9fcdSqs148142 dma_ioaddr, mark_mode)); 5733dec9fcdSqs148142 5743dec9fcdSqs148142 #ifdef HXGE_DEBUG 5753dec9fcdSqs148142 hpi_desc_handle.hxgep = hxgep; 5763dec9fcdSqs148142 hpi_desc_handle.function.function = 0; 5773dec9fcdSqs148142 hpi_desc_handle.function.instance = hxgep->instance; 5783dec9fcdSqs148142 sad = save_desc_p->bits.sad; 579fe930412Sqs148142 sad = (sad << 32) | save_desc_p->bits.sad_l; 5803dec9fcdSqs148142 xfer_len = save_desc_p->bits.tr_len; 5813dec9fcdSqs148142 5823dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, "\n\t: value 0x%llx\n" 5833dec9fcdSqs148142 "\t\tsad $%p\ttr_len %d len %d\tnptrs %d\t" 5843dec9fcdSqs148142 "mark %d sop %d\n", 5853dec9fcdSqs148142 save_desc_p->value, sad, save_desc_p->bits.tr_len, 5863dec9fcdSqs148142 xfer_len, save_desc_p->bits.num_ptr, 5873dec9fcdSqs148142 save_desc_p->bits.mark, save_desc_p->bits.sop)); 5883dec9fcdSqs148142 5893dec9fcdSqs148142 hpi_txdma_dump_desc_one(hpi_desc_handle, NULL, i); 5903dec9fcdSqs148142 #endif 5913dec9fcdSqs148142 5923dec9fcdSqs148142 tx_msg_p->tx_msg_size = clen; 5933dec9fcdSqs148142 i = TXDMA_DESC_NEXT_INDEX(i, 1, tx_ring_p->tx_wrap_mask); 5943dec9fcdSqs148142 if (ngathers > hxge_tx_max_gathers) { 5953dec9fcdSqs148142 good_packet = B_FALSE; 5960dc2366fSVenugopal Iyer mac_hcksum_get(mp, &start_offset, &stuff_offset, 5970dc2366fSVenugopal Iyer &end_offset, &value, &cksum_flags); 5983dec9fcdSqs148142 5993dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, TX_CTL, 6003dec9fcdSqs148142 "==> hxge_start(14): pull msg - " 6013dec9fcdSqs148142 "len %d pkt_len %d ngathers %d", 6023dec9fcdSqs148142 len, pkt_len, ngathers)); 6033dec9fcdSqs148142 goto hxge_start_fail2; 6043dec9fcdSqs148142 } 6053dec9fcdSqs148142 } /* while (nmp) */ 6063dec9fcdSqs148142 6073dec9fcdSqs148142 tx_msg_p->tx_message = mp; 6083dec9fcdSqs148142 tx_desc_p = &tx_desc_ring_vp[sop_index]; 6093dec9fcdSqs148142 #if defined(__i386) 6103dec9fcdSqs148142 hpi_desc_handle.regp = (uint32_t)tx_desc_p; 6113dec9fcdSqs148142 #else 6123dec9fcdSqs148142 hpi_desc_handle.regp = (uint64_t)tx_desc_p; 6133dec9fcdSqs148142 #endif 6143dec9fcdSqs148142 6153dec9fcdSqs148142 pkthdrp = (p_tx_pkt_hdr_all_t)hdrp; 6163dec9fcdSqs148142 pkthdrp->reserved = 0; 6173dec9fcdSqs148142 hdrp->value = 0; 6183dec9fcdSqs148142 (void) hxge_fill_tx_hdr(mp, B_FALSE, cksum_on, 6193dec9fcdSqs148142 (pkt_len - TX_PKT_HEADER_SIZE), npads, pkthdrp); 620fe930412Sqs148142 621fe930412Sqs148142 /* 622fe930412Sqs148142 * Hardware header should not be counted as part of the frame 623fe930412Sqs148142 * when determining the frame size 624fe930412Sqs148142 */ 625fe930412Sqs148142 if ((pkt_len - TX_PKT_HEADER_SIZE) > (STD_FRAME_SIZE - ETHERFCSL)) { 6263dec9fcdSqs148142 tdc_stats->tx_jumbo_pkts++; 6273dec9fcdSqs148142 } 6283dec9fcdSqs148142 6293dec9fcdSqs148142 min_len = (hxgep->msg_min + TX_PKT_HEADER_SIZE + (npads * 2)); 6303dec9fcdSqs148142 if (pkt_len < min_len) { 6313dec9fcdSqs148142 /* Assume we use bcopy to premapped buffers */ 6323dec9fcdSqs148142 kaddr = (caddr_t)DMA_COMMON_VPTR(tx_msg_p->buf_dma); 6333dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, TX_CTL, 6343dec9fcdSqs148142 "==> hxge_start(14-1): < (msg_min + 16)" 6353dec9fcdSqs148142 "len %d pkt_len %d min_len %d bzero %d ngathers %d", 6363dec9fcdSqs148142 len, pkt_len, min_len, (min_len - pkt_len), ngathers)); 6373dec9fcdSqs148142 bzero((kaddr + pkt_len), (min_len - pkt_len)); 6383dec9fcdSqs148142 pkt_len = tx_msg_p->tx_msg_size = min_len; 6393dec9fcdSqs148142 6403dec9fcdSqs148142 sop_tx_desc_p->bits.tr_len = min_len; 6413dec9fcdSqs148142 6423dec9fcdSqs148142 HXGE_MEM_PIO_WRITE64(hpi_desc_handle, sop_tx_desc_p->value); 6433dec9fcdSqs148142 tx_desc_p->value = sop_tx_desc_p->value; 6443dec9fcdSqs148142 6453dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, TX_CTL, 6463dec9fcdSqs148142 "==> hxge_start(14-2): < msg_min - " 6473dec9fcdSqs148142 "len %d pkt_len %d min_len %d ngathers %d", 6483dec9fcdSqs148142 len, pkt_len, min_len, ngathers)); 6493dec9fcdSqs148142 } 6503dec9fcdSqs148142 6513dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, "==> hxge_start: cksum_flags 0x%x ", 6523dec9fcdSqs148142 cksum_flags)); 6533dec9fcdSqs148142 if (cksum_flags & HCK_PARTIALCKSUM) { 6543dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 6553dec9fcdSqs148142 "==> hxge_start: cksum_flags 0x%x (partial checksum) ", 6563dec9fcdSqs148142 cksum_flags)); 6573dec9fcdSqs148142 cksum_on = B_TRUE; 6583dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 6593dec9fcdSqs148142 "==> hxge_start: from IP cksum_flags 0x%x " 6603dec9fcdSqs148142 "(partial checksum) " 6613dec9fcdSqs148142 "start_offset %d stuff_offset %d", 6623dec9fcdSqs148142 cksum_flags, start_offset, stuff_offset)); 6633dec9fcdSqs148142 tmp_len = (uint64_t)(start_offset >> 1); 6643dec9fcdSqs148142 hdrp->value |= (tmp_len << TX_PKT_HEADER_L4START_SHIFT); 6653dec9fcdSqs148142 tmp_len = (uint64_t)(stuff_offset >> 1); 6663dec9fcdSqs148142 hdrp->value |= (tmp_len << TX_PKT_HEADER_L4STUFF_SHIFT); 6673dec9fcdSqs148142 6683dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 6693dec9fcdSqs148142 "==> hxge_start: from IP cksum_flags 0x%x " 6703dec9fcdSqs148142 "(partial checksum) " 6713dec9fcdSqs148142 "after SHIFT start_offset %d stuff_offset %d", 6723dec9fcdSqs148142 cksum_flags, start_offset, stuff_offset)); 6733dec9fcdSqs148142 } 6743dec9fcdSqs148142 6753dec9fcdSqs148142 /* 6763dec9fcdSqs148142 * pkt_len already includes 16 + paddings!! 6773dec9fcdSqs148142 * Update the control header length 6783dec9fcdSqs148142 */ 6793dec9fcdSqs148142 6803dec9fcdSqs148142 /* 6813dec9fcdSqs148142 * Note that Hydra is different from Neptune where 6823dec9fcdSqs148142 * tot_xfer_len = (pkt_len - TX_PKT_HEADER_SIZE); 6833dec9fcdSqs148142 */ 6843dec9fcdSqs148142 tot_xfer_len = pkt_len; 6853dec9fcdSqs148142 tmp_len = hdrp->value | 6863dec9fcdSqs148142 (tot_xfer_len << TX_PKT_HEADER_TOT_XFER_LEN_SHIFT); 6873dec9fcdSqs148142 6883dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 6893dec9fcdSqs148142 "==> hxge_start(15_x1): setting SOP " 6903dec9fcdSqs148142 "tot_xfer_len 0x%llx (%d) pkt_len %d tmp_len " 6913dec9fcdSqs148142 "0x%llx hdrp->value 0x%llx", 6923dec9fcdSqs148142 tot_xfer_len, tot_xfer_len, pkt_len, tmp_len, hdrp->value)); 6933dec9fcdSqs148142 #if defined(_BIG_ENDIAN) 6943dec9fcdSqs148142 hdrp->value = ddi_swap64(tmp_len); 6953dec9fcdSqs148142 #else 6963dec9fcdSqs148142 hdrp->value = tmp_len; 6973dec9fcdSqs148142 #endif 6983dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, 6993dec9fcdSqs148142 TX_CTL, "==> hxge_start(15_x2): setting SOP " 7003dec9fcdSqs148142 "after SWAP: tot_xfer_len 0x%llx pkt_len %d " 7013dec9fcdSqs148142 "tmp_len 0x%llx hdrp->value 0x%llx", 7023dec9fcdSqs148142 tot_xfer_len, pkt_len, tmp_len, hdrp->value)); 7033dec9fcdSqs148142 7043dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, "==> hxge_start(15): setting SOP " 7053dec9fcdSqs148142 "wr_index %d tot_xfer_len (%d) pkt_len %d npads %d", 7063dec9fcdSqs148142 sop_index, tot_xfer_len, pkt_len, npads)); 7073dec9fcdSqs148142 7083dec9fcdSqs148142 sop_tx_desc_p->bits.sop = 1; 7093dec9fcdSqs148142 sop_tx_desc_p->bits.mark = mark_mode; 7103dec9fcdSqs148142 sop_tx_desc_p->bits.num_ptr = ngathers; 7113dec9fcdSqs148142 7123dec9fcdSqs148142 if (mark_mode) 7133dec9fcdSqs148142 tdc_stats->tx_marks++; 7143dec9fcdSqs148142 7153dec9fcdSqs148142 HXGE_MEM_PIO_WRITE64(hpi_desc_handle, sop_tx_desc_p->value); 7163dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, "==> hxge_start(16): set SOP done")); 7173dec9fcdSqs148142 7183dec9fcdSqs148142 #ifdef HXGE_DEBUG 7193dec9fcdSqs148142 hpi_desc_handle.hxgep = hxgep; 7203dec9fcdSqs148142 hpi_desc_handle.function.function = 0; 7213dec9fcdSqs148142 hpi_desc_handle.function.instance = hxgep->instance; 7223dec9fcdSqs148142 7233dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, "\n\t: value 0x%llx\n" 7243dec9fcdSqs148142 "\t\tsad $%p\ttr_len %d len %d\tnptrs %d\tmark %d sop %d\n", 7253dec9fcdSqs148142 save_desc_p->value, sad, save_desc_p->bits.tr_len, 7263dec9fcdSqs148142 xfer_len, save_desc_p->bits.num_ptr, save_desc_p->bits.mark, 7273dec9fcdSqs148142 save_desc_p->bits.sop)); 7283dec9fcdSqs148142 (void) hpi_txdma_dump_desc_one(hpi_desc_handle, NULL, sop_index); 7293dec9fcdSqs148142 7303dec9fcdSqs148142 dump_len = (pkt_len > 128) ? 128: pkt_len; 7313dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 7323dec9fcdSqs148142 "==> hxge_start: dump packets(17) (after sop set, len " 7333dec9fcdSqs148142 " (len/dump_len/pkt_len/tot_xfer_len) %d/%d/%d/%d):\n" 7343dec9fcdSqs148142 "ptr $%p: %s", len, dump_len, pkt_len, tot_xfer_len, 7353dec9fcdSqs148142 (char *)hdrp, hxge_dump_packet((char *)hdrp, dump_len))); 7363dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 7373dec9fcdSqs148142 "==> hxge_start(18): TX desc sync: sop_index %d", sop_index)); 7383dec9fcdSqs148142 #endif 7393dec9fcdSqs148142 7403dec9fcdSqs148142 if ((ngathers == 1) || tx_ring_p->wr_index < i) { 7413dec9fcdSqs148142 (void) ddi_dma_sync(tx_desc_dma_handle, 7423dec9fcdSqs148142 sop_index * sizeof (tx_desc_t), 7433dec9fcdSqs148142 ngathers * sizeof (tx_desc_t), DDI_DMA_SYNC_FORDEV); 7443dec9fcdSqs148142 7453dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, "hxge_start(19): sync 1 " 7463dec9fcdSqs148142 "cs_off = 0x%02X cs_s_off = 0x%02X " 7473dec9fcdSqs148142 "pkt_len %d ngathers %d sop_index %d\n", 7483dec9fcdSqs148142 stuff_offset, start_offset, 7493dec9fcdSqs148142 pkt_len, ngathers, sop_index)); 7503dec9fcdSqs148142 } else { /* more than one descriptor and wrap around */ 7513dec9fcdSqs148142 uint32_t nsdescs = tx_ring_p->tx_ring_size - sop_index; 7523dec9fcdSqs148142 (void) ddi_dma_sync(tx_desc_dma_handle, 7533dec9fcdSqs148142 sop_index * sizeof (tx_desc_t), 7543dec9fcdSqs148142 nsdescs * sizeof (tx_desc_t), DDI_DMA_SYNC_FORDEV); 7553dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, "hxge_start(20): sync 1 " 7563dec9fcdSqs148142 "cs_off = 0x%02X cs_s_off = 0x%02X " 7573dec9fcdSqs148142 "pkt_len %d ngathers %d sop_index %d\n", 7583dec9fcdSqs148142 stuff_offset, start_offset, pkt_len, ngathers, sop_index)); 7593dec9fcdSqs148142 7603dec9fcdSqs148142 (void) ddi_dma_sync(tx_desc_dma_handle, 0, 7613dec9fcdSqs148142 (ngathers - nsdescs) * sizeof (tx_desc_t), 7623dec9fcdSqs148142 DDI_DMA_SYNC_FORDEV); 7633dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, "hxge_start(21): sync 2 " 7643dec9fcdSqs148142 "cs_off = 0x%02X cs_s_off = 0x%02X " 7653dec9fcdSqs148142 "pkt_len %d ngathers %d sop_index %d\n", 7663dec9fcdSqs148142 stuff_offset, start_offset, 7673dec9fcdSqs148142 pkt_len, ngathers, sop_index)); 7683dec9fcdSqs148142 } 7693dec9fcdSqs148142 7703dec9fcdSqs148142 tail_index = tx_ring_p->wr_index; 7713dec9fcdSqs148142 tail_wrap = tx_ring_p->wr_index_wrap; 7723dec9fcdSqs148142 7733dec9fcdSqs148142 tx_ring_p->wr_index = i; 7743dec9fcdSqs148142 if (tx_ring_p->wr_index <= tail_index) { 7753dec9fcdSqs148142 tx_ring_p->wr_index_wrap = ((tail_wrap == B_TRUE) ? 7763dec9fcdSqs148142 B_FALSE : B_TRUE); 7773dec9fcdSqs148142 } 7783dec9fcdSqs148142 7793dec9fcdSqs148142 tx_ring_p->descs_pending += ngathers; 7803dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, "==> hxge_start: TX kick: " 7813dec9fcdSqs148142 "channel %d wr_index %d wrap %d ngathers %d desc_pend %d", 7823dec9fcdSqs148142 tx_ring_p->tdc, tx_ring_p->wr_index, tx_ring_p->wr_index_wrap, 7833dec9fcdSqs148142 ngathers, tx_ring_p->descs_pending)); 7843dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, "==> hxge_start: TX KICKING: ")); 7853dec9fcdSqs148142 7863dec9fcdSqs148142 kick.value = 0; 7873dec9fcdSqs148142 kick.bits.wrap = tx_ring_p->wr_index_wrap; 7883dec9fcdSqs148142 kick.bits.tail = (uint16_t)tx_ring_p->wr_index; 7893dec9fcdSqs148142 7903dec9fcdSqs148142 /* Kick start the Transmit kick register */ 7913dec9fcdSqs148142 TXDMA_REG_WRITE64(HXGE_DEV_HPI_HANDLE(hxgep), 7923dec9fcdSqs148142 TDC_TDR_KICK, (uint8_t)tx_ring_p->tdc, kick.value); 7933dec9fcdSqs148142 tdc_stats->tx_starts++; 7943dec9fcdSqs148142 MUTEX_EXIT(&tx_ring_p->lock); 7953dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, "<== hxge_start")); 7963dec9fcdSqs148142 return (status); 7973dec9fcdSqs148142 7983dec9fcdSqs148142 hxge_start_fail2: 7993dec9fcdSqs148142 if (good_packet == B_FALSE) { 8003dec9fcdSqs148142 cur_index = sop_index; 8013dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, "==> hxge_start: clean up")); 8023dec9fcdSqs148142 for (i = 0; i < ngathers; i++) { 8033dec9fcdSqs148142 tx_desc_p = &tx_desc_ring_vp[cur_index]; 8043dec9fcdSqs148142 #if defined(__i386) 8053dec9fcdSqs148142 hpi_handle.regp = (uint32_t)tx_desc_p; 8063dec9fcdSqs148142 #else 8073dec9fcdSqs148142 hpi_handle.regp = (uint64_t)tx_desc_p; 8083dec9fcdSqs148142 #endif 8093dec9fcdSqs148142 tx_msg_p = &tx_msg_ring[cur_index]; 8103dec9fcdSqs148142 (void) hpi_txdma_desc_set_zero(hpi_handle, 1); 8113dec9fcdSqs148142 if (tx_msg_p->flags.dma_type == USE_DVMA) { 8123dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, 8133dec9fcdSqs148142 "tx_desc_p = %X index = %d", 8143dec9fcdSqs148142 tx_desc_p, tx_ring_p->rd_index)); 8153dec9fcdSqs148142 (void) dvma_unload(tx_msg_p->dvma_handle, 8163dec9fcdSqs148142 0, -1); 8173dec9fcdSqs148142 tx_msg_p->dvma_handle = NULL; 8183dec9fcdSqs148142 if (tx_ring_p->dvma_wr_index == 8193dec9fcdSqs148142 tx_ring_p->dvma_wrap_mask) 8203dec9fcdSqs148142 tx_ring_p->dvma_wr_index = 0; 8213dec9fcdSqs148142 else 8223dec9fcdSqs148142 tx_ring_p->dvma_wr_index++; 8233dec9fcdSqs148142 tx_ring_p->dvma_pending--; 8243dec9fcdSqs148142 } else if (tx_msg_p->flags.dma_type == USE_DMA) { 8253dec9fcdSqs148142 if (ddi_dma_unbind_handle( 8263dec9fcdSqs148142 tx_msg_p->dma_handle)) { 8273dec9fcdSqs148142 cmn_err(CE_WARN, "hxge_start: " 8283dec9fcdSqs148142 "ddi_dma_unbind_handle failed"); 8293dec9fcdSqs148142 } 8303dec9fcdSqs148142 } 8313dec9fcdSqs148142 tx_msg_p->flags.dma_type = USE_NONE; 8323dec9fcdSqs148142 cur_index = TXDMA_DESC_NEXT_INDEX(cur_index, 1, 8333dec9fcdSqs148142 tx_ring_p->tx_wrap_mask); 8343dec9fcdSqs148142 8353dec9fcdSqs148142 } 8363dec9fcdSqs148142 } 8373dec9fcdSqs148142 8383dec9fcdSqs148142 MUTEX_EXIT(&tx_ring_p->lock); 8393dec9fcdSqs148142 8403dec9fcdSqs148142 hxge_start_fail1: 8413dec9fcdSqs148142 /* Add FMA to check the access handle hxge_hregh */ 8423dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, TX_CTL, "<== hxge_start")); 8433dec9fcdSqs148142 return (status); 8443dec9fcdSqs148142 } 845