16f3e57acSmx205022 /* 247693af9Smx205022 * CDDL HEADER START 347693af9Smx205022 * 447693af9Smx205022 * The contents of this file are subject to the terms of the 547693af9Smx205022 * Common Development and Distribution License (the "License"). 647693af9Smx205022 * You may not use this file except in compliance with the License. 747693af9Smx205022 * 847693af9Smx205022 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 947693af9Smx205022 * or http://www.opensolaris.org/os/licensing. 1047693af9Smx205022 * See the License for the specific language governing permissions 1147693af9Smx205022 * and limitations under the License. 1247693af9Smx205022 * 1347693af9Smx205022 * When distributing Covered Code, include this CDDL HEADER in each 1447693af9Smx205022 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1547693af9Smx205022 * If applicable, add the following below this CDDL HEADER, with the 1647693af9Smx205022 * fields enclosed by brackets "[]" replaced with your own identifying 1747693af9Smx205022 * information: Portions Copyright [yyyy] [name of copyright owner] 1847693af9Smx205022 * 1947693af9Smx205022 * CDDL HEADER END 206f3e57acSmx205022 */ 216f3e57acSmx205022 226f3e57acSmx205022 /* 23*0dc2366fSVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 2447693af9Smx205022 * Use is subject to license terms. 256f3e57acSmx205022 */ 266f3e57acSmx205022 276f3e57acSmx205022 #include "nge.h" 286f3e57acSmx205022 296f3e57acSmx205022 #define TXD_OWN 0x80000000 306f3e57acSmx205022 #define TXD_ERR 0x40000000 316f3e57acSmx205022 #define TXD_END 0x20000000 326f3e57acSmx205022 #define TXD_BCNT_MSK 0x00003FFF 336f3e57acSmx205022 346f3e57acSmx205022 356f3e57acSmx205022 #undef NGE_DBG 366f3e57acSmx205022 #define NGE_DBG NGE_DBG_SEND 376f3e57acSmx205022 386f3e57acSmx205022 #define NGE_TXSWD_RECYCLE(sd) {\ 396f3e57acSmx205022 (sd)->mp = NULL; \ 406f3e57acSmx205022 (sd)->frags = 0; \ 416f3e57acSmx205022 (sd)->mp_hndl.head = NULL; \ 426f3e57acSmx205022 (sd)->mp_hndl.tail = NULL; \ 436f3e57acSmx205022 (sd)->flags = HOST_OWN; \ 446f3e57acSmx205022 } 456f3e57acSmx205022 466f3e57acSmx205022 476f3e57acSmx205022 static size_t nge_tx_dmah_pop(nge_dmah_list_t *, nge_dmah_list_t *, size_t); 486f3e57acSmx205022 static void nge_tx_dmah_push(nge_dmah_list_t *, nge_dmah_list_t *); 496f3e57acSmx205022 506f3e57acSmx205022 516f3e57acSmx205022 void nge_tx_recycle_all(nge_t *ngep); 526f3e57acSmx205022 #pragma no_inline(nge_tx_recycle_all) 536f3e57acSmx205022 546f3e57acSmx205022 void 556f3e57acSmx205022 nge_tx_recycle_all(nge_t *ngep) 566f3e57acSmx205022 { 576f3e57acSmx205022 send_ring_t *srp; 586f3e57acSmx205022 sw_tx_sbd_t *ssbdp; 596f3e57acSmx205022 nge_dmah_node_t *dmah; 606f3e57acSmx205022 uint32_t slot; 616f3e57acSmx205022 uint32_t nslots; 626f3e57acSmx205022 636f3e57acSmx205022 srp = ngep->send; 646f3e57acSmx205022 nslots = srp->desc.nslots; 656f3e57acSmx205022 666f3e57acSmx205022 for (slot = 0; slot < nslots; ++slot) { 676f3e57acSmx205022 686f3e57acSmx205022 ssbdp = srp->sw_sbds + slot; 696f3e57acSmx205022 706f3e57acSmx205022 DMA_ZERO(ssbdp->desc); 716f3e57acSmx205022 726f3e57acSmx205022 if (ssbdp->mp != NULL) { 736f3e57acSmx205022 746f3e57acSmx205022 for (dmah = ssbdp->mp_hndl.head; dmah != NULL; 756f3e57acSmx205022 dmah = dmah->next) 766f3e57acSmx205022 (void) ddi_dma_unbind_handle(dmah->hndl); 776f3e57acSmx205022 786f3e57acSmx205022 freemsg(ssbdp->mp); 796f3e57acSmx205022 } 806f3e57acSmx205022 816f3e57acSmx205022 NGE_TXSWD_RECYCLE(ssbdp); 826f3e57acSmx205022 } 8351fc88a8SWinson Wang - Sun Microsystems - Beijing China if (ngep->nge_mac_state == NGE_MAC_STARTED && 8451fc88a8SWinson Wang - Sun Microsystems - Beijing China ngep->resched_needed == 1) { 8551fc88a8SWinson Wang - Sun Microsystems - Beijing China ngep->resched_needed = 0; 8651fc88a8SWinson Wang - Sun Microsystems - Beijing China mac_tx_update(ngep->mh); 8751fc88a8SWinson Wang - Sun Microsystems - Beijing China } 8851fc88a8SWinson Wang - Sun Microsystems - Beijing China 896f3e57acSmx205022 } 906f3e57acSmx205022 916f3e57acSmx205022 static size_t 926f3e57acSmx205022 nge_tx_dmah_pop(nge_dmah_list_t *src, nge_dmah_list_t *dst, size_t num) 936f3e57acSmx205022 { 946f3e57acSmx205022 nge_dmah_node_t *node; 956f3e57acSmx205022 966f3e57acSmx205022 for (node = src->head; node != NULL && --num != 0; node = node->next) 976f3e57acSmx205022 ; 986f3e57acSmx205022 996f3e57acSmx205022 if (num == 0) { 1006f3e57acSmx205022 1016f3e57acSmx205022 dst->head = src->head; 1026f3e57acSmx205022 dst->tail = node; 1036f3e57acSmx205022 1046f3e57acSmx205022 if ((src->head = node->next) == NULL) 1056f3e57acSmx205022 src->tail = NULL; 1066f3e57acSmx205022 1076f3e57acSmx205022 node->next = NULL; 1086f3e57acSmx205022 } 1096f3e57acSmx205022 1106f3e57acSmx205022 return (num); 1116f3e57acSmx205022 } 1126f3e57acSmx205022 1136f3e57acSmx205022 static void 1146f3e57acSmx205022 nge_tx_dmah_push(nge_dmah_list_t *src, nge_dmah_list_t *dst) 1156f3e57acSmx205022 { 1166f3e57acSmx205022 if (dst->tail != NULL) 1176f3e57acSmx205022 dst->tail->next = src->head; 1186f3e57acSmx205022 else 1196f3e57acSmx205022 dst->head = src->head; 1206f3e57acSmx205022 1216f3e57acSmx205022 dst->tail = src->tail; 1226f3e57acSmx205022 } 1236f3e57acSmx205022 1246f3e57acSmx205022 static void 125a55f7119SMiles Xu, Sun Microsystems nge_tx_desc_sync(nge_t *ngep, uint32_t start_index, uint32_t bds, uint_t type) 1266f3e57acSmx205022 { 1276f3e57acSmx205022 send_ring_t *srp = ngep->send; 1286f3e57acSmx205022 const size_t txd_size = ngep->desc_attr.txd_size; 1296f3e57acSmx205022 const uint64_t end = srp->desc.nslots * txd_size; 130a55f7119SMiles Xu, Sun Microsystems uint64_t start; 131a55f7119SMiles Xu, Sun Microsystems uint64_t num; 1326f3e57acSmx205022 133a55f7119SMiles Xu, Sun Microsystems start = start_index * txd_size; 134a55f7119SMiles Xu, Sun Microsystems num = bds * txd_size; 1356f3e57acSmx205022 1366f3e57acSmx205022 if (start + num <= end) 1376f3e57acSmx205022 (void) ddi_dma_sync(srp->desc.dma_hdl, start, num, type); 1386f3e57acSmx205022 else { 1396f3e57acSmx205022 1406f3e57acSmx205022 (void) ddi_dma_sync(srp->desc.dma_hdl, start, 0, type); 1416f3e57acSmx205022 (void) ddi_dma_sync(srp->desc.dma_hdl, 0, start + num - end, 1426f3e57acSmx205022 type); 1436f3e57acSmx205022 } 1446f3e57acSmx205022 } 1456f3e57acSmx205022 1466f3e57acSmx205022 /* 1476f3e57acSmx205022 * Reclaim the resource after tx's completion 1486f3e57acSmx205022 */ 1496f3e57acSmx205022 void 1506f3e57acSmx205022 nge_tx_recycle(nge_t *ngep, boolean_t is_intr) 1516f3e57acSmx205022 { 1526f3e57acSmx205022 int resched; 1536f3e57acSmx205022 uint32_t stflg; 154a55f7119SMiles Xu, Sun Microsystems uint32_t free; 155a55f7119SMiles Xu, Sun Microsystems uint32_t slot; 156a55f7119SMiles Xu, Sun Microsystems uint32_t used; 157a55f7119SMiles Xu, Sun Microsystems uint32_t next; 158a55f7119SMiles Xu, Sun Microsystems uint32_t nslots; 1596f3e57acSmx205022 mblk_t *mp; 1606f3e57acSmx205022 sw_tx_sbd_t *ssbdp; 1616f3e57acSmx205022 void *hw_sbd_p; 1626f3e57acSmx205022 send_ring_t *srp; 1636f3e57acSmx205022 nge_dmah_node_t *dme; 1646f3e57acSmx205022 nge_dmah_list_t dmah; 1656f3e57acSmx205022 1666f3e57acSmx205022 srp = ngep->send; 1676f3e57acSmx205022 1686f3e57acSmx205022 if (is_intr) { 1696f3e57acSmx205022 if (mutex_tryenter(srp->tc_lock) == 0) 1706f3e57acSmx205022 return; 1716f3e57acSmx205022 } else 1726f3e57acSmx205022 mutex_enter(srp->tc_lock); 1736f3e57acSmx205022 mutex_enter(srp->tx_lock); 1746f3e57acSmx205022 1756f3e57acSmx205022 next = srp->tx_next; 1766f3e57acSmx205022 used = srp->tx_flow; 1776f3e57acSmx205022 free = srp->tx_free; 1786f3e57acSmx205022 1796f3e57acSmx205022 mutex_exit(srp->tx_lock); 1806f3e57acSmx205022 1816f3e57acSmx205022 slot = srp->tc_next; 1826f3e57acSmx205022 nslots = srp->desc.nslots; 1836f3e57acSmx205022 1846f3e57acSmx205022 used = nslots - free - used; 1856f3e57acSmx205022 1866f3e57acSmx205022 ASSERT(slot == NEXT_INDEX(next, free, nslots)); 18751fc88a8SWinson Wang - Sun Microsystems - Beijing China if (used == 0) { 18851fc88a8SWinson Wang - Sun Microsystems - Beijing China ngep->watchdog = 0; 18951fc88a8SWinson Wang - Sun Microsystems - Beijing China mutex_exit(srp->tc_lock); 19051fc88a8SWinson Wang - Sun Microsystems - Beijing China return; 19151fc88a8SWinson Wang - Sun Microsystems - Beijing China } 1926f3e57acSmx205022 19351fc88a8SWinson Wang - Sun Microsystems - Beijing China if (used > srp->tx_hwmark && ngep->resched_needed == 0) 1946f3e57acSmx205022 used = srp->tx_hwmark; 1956f3e57acSmx205022 1966f3e57acSmx205022 nge_tx_desc_sync(ngep, slot, used, DDI_DMA_SYNC_FORKERNEL); 1976f3e57acSmx205022 1986f3e57acSmx205022 /* 1996f3e57acSmx205022 * Look through the send ring by bd's status part 2006f3e57acSmx205022 * to find all the bds which has been transmitted sucessfully 2016f3e57acSmx205022 * then reclaim all resouces associated with these bds 2026f3e57acSmx205022 */ 2036f3e57acSmx205022 2046f3e57acSmx205022 mp = NULL; 2056f3e57acSmx205022 dmah.head = NULL; 2066f3e57acSmx205022 dmah.tail = NULL; 2076f3e57acSmx205022 2086f3e57acSmx205022 for (free = 0; used-- != 0; slot = NEXT(slot, nslots), ++free) { 2096f3e57acSmx205022 2106f3e57acSmx205022 ssbdp = &srp->sw_sbds[slot]; 2116f3e57acSmx205022 hw_sbd_p = DMA_VPTR(ssbdp->desc); 2126f3e57acSmx205022 21373236167SWinson Wang - Sun Microsystems - Beijing China if (ssbdp->flags == HOST_OWN) 2146f3e57acSmx205022 break; 2159fa05d92SWinson Wang - Sun Microsystems - Beijing China stflg = ngep->desc_attr.txd_check(hw_sbd_p); 21673236167SWinson Wang - Sun Microsystems - Beijing China if ((stflg & TXD_OWN) != 0) 21773236167SWinson Wang - Sun Microsystems - Beijing China break; 218cb824541SWinson Wang - Sun Microsystems - Beijing China DMA_ZERO(ssbdp->desc); 2196f3e57acSmx205022 if (ssbdp->mp != NULL) { 2206f3e57acSmx205022 ssbdp->mp->b_next = mp; 2216f3e57acSmx205022 mp = ssbdp->mp; 2226f3e57acSmx205022 2236f3e57acSmx205022 if (ssbdp->mp_hndl.head != NULL) 2246f3e57acSmx205022 nge_tx_dmah_push(&ssbdp->mp_hndl, &dmah); 2256f3e57acSmx205022 } 2266f3e57acSmx205022 2276f3e57acSmx205022 NGE_TXSWD_RECYCLE(ssbdp); 2286f3e57acSmx205022 } 2296f3e57acSmx205022 2306f3e57acSmx205022 /* 2316f3e57acSmx205022 * We're about to release one or more places :-) 2326f3e57acSmx205022 * These ASSERTions check that our invariants still hold: 2336f3e57acSmx205022 * there must always be at least one free place 2346f3e57acSmx205022 * at this point, there must be at least one place NOT free 2356f3e57acSmx205022 * we're not about to free more places than were claimed! 2366f3e57acSmx205022 */ 2376f3e57acSmx205022 23851fc88a8SWinson Wang - Sun Microsystems - Beijing China if (free == 0) { 23951fc88a8SWinson Wang - Sun Microsystems - Beijing China mutex_exit(srp->tc_lock); 24051fc88a8SWinson Wang - Sun Microsystems - Beijing China return; 24151fc88a8SWinson Wang - Sun Microsystems - Beijing China } 24251fc88a8SWinson Wang - Sun Microsystems - Beijing China 2436f3e57acSmx205022 mutex_enter(srp->tx_lock); 2446f3e57acSmx205022 2456f3e57acSmx205022 srp->tx_free += free; 2466f3e57acSmx205022 ngep->watchdog = (srp->desc.nslots - srp->tx_free != 0); 2476f3e57acSmx205022 2486f3e57acSmx205022 srp->tc_next = slot; 2496f3e57acSmx205022 2506f3e57acSmx205022 ASSERT(srp->tx_free <= nslots); 2516f3e57acSmx205022 ASSERT(srp->tc_next == NEXT_INDEX(srp->tx_next, srp->tx_free, nslots)); 2526f3e57acSmx205022 2536f3e57acSmx205022 resched = (ngep->resched_needed != 0 && srp->tx_hwmark <= srp->tx_free); 2546f3e57acSmx205022 2556f3e57acSmx205022 mutex_exit(srp->tx_lock); 2566f3e57acSmx205022 mutex_exit(srp->tc_lock); 2576f3e57acSmx205022 2586f3e57acSmx205022 /* unbind/free mblks */ 2596f3e57acSmx205022 2606f3e57acSmx205022 for (dme = dmah.head; dme != NULL; dme = dme->next) 2616f3e57acSmx205022 (void) ddi_dma_unbind_handle(dme->hndl); 2626ad24245SWinson Wang - Sun Microsystems - Beijing China if (dmah.head != NULL) { 2636f3e57acSmx205022 mutex_enter(&srp->dmah_lock); 2646f3e57acSmx205022 nge_tx_dmah_push(&dmah, &srp->dmah_free); 2656f3e57acSmx205022 mutex_exit(&srp->dmah_lock); 2666ad24245SWinson Wang - Sun Microsystems - Beijing China } 2676f3e57acSmx205022 freemsgchain(mp); 2686f3e57acSmx205022 2696f3e57acSmx205022 /* 2706f3e57acSmx205022 * up to this place, we maybe have reclaim some resouce 2716f3e57acSmx205022 * if there is a requirement to report to gld, report this. 2726f3e57acSmx205022 */ 2736f3e57acSmx205022 2746f3e57acSmx205022 if (resched) 2756f3e57acSmx205022 (void) ddi_intr_trigger_softint(ngep->resched_hdl, NULL); 2766f3e57acSmx205022 } 2776f3e57acSmx205022 278a55f7119SMiles Xu, Sun Microsystems static uint32_t 279a55f7119SMiles Xu, Sun Microsystems nge_tx_alloc(nge_t *ngep, uint32_t num) 2806f3e57acSmx205022 { 281a55f7119SMiles Xu, Sun Microsystems uint32_t start; 2826f3e57acSmx205022 send_ring_t *srp; 2836f3e57acSmx205022 284a55f7119SMiles Xu, Sun Microsystems start = (uint32_t)-1; 2856f3e57acSmx205022 srp = ngep->send; 2866f3e57acSmx205022 2876f3e57acSmx205022 mutex_enter(srp->tx_lock); 2886f3e57acSmx205022 2896f3e57acSmx205022 if (srp->tx_free < srp->tx_lwmark) { 2906f3e57acSmx205022 2916f3e57acSmx205022 mutex_exit(srp->tx_lock); 2926f3e57acSmx205022 nge_tx_recycle(ngep, B_FALSE); 2936f3e57acSmx205022 mutex_enter(srp->tx_lock); 2946f3e57acSmx205022 } 2956f3e57acSmx205022 2966f3e57acSmx205022 if (srp->tx_free >= num) { 2976f3e57acSmx205022 2986f3e57acSmx205022 start = srp->tx_next; 2996f3e57acSmx205022 3006f3e57acSmx205022 srp->tx_next = NEXT_INDEX(start, num, srp->desc.nslots); 3016f3e57acSmx205022 srp->tx_free -= num; 3026f3e57acSmx205022 srp->tx_flow += num; 3036f3e57acSmx205022 } 3046f3e57acSmx205022 3056f3e57acSmx205022 mutex_exit(srp->tx_lock); 3066f3e57acSmx205022 return (start); 3076f3e57acSmx205022 } 3086f3e57acSmx205022 3096f3e57acSmx205022 static void 310a55f7119SMiles Xu, Sun Microsystems nge_tx_start(nge_t *ngep, uint32_t slotnum) 3116f3e57acSmx205022 { 3126f3e57acSmx205022 nge_mode_cntl mode_cntl; 3136f3e57acSmx205022 send_ring_t *srp; 3146f3e57acSmx205022 3156f3e57acSmx205022 srp = ngep->send; 3166f3e57acSmx205022 3176f3e57acSmx205022 /* 3186f3e57acSmx205022 * Because there can be multiple concurrent threads in 3196f3e57acSmx205022 * transit through this code, we only want to notify the 3206f3e57acSmx205022 * hardware once the last one is departing ... 3216f3e57acSmx205022 */ 3226f3e57acSmx205022 3236f3e57acSmx205022 mutex_enter(srp->tx_lock); 3246f3e57acSmx205022 3256f3e57acSmx205022 srp->tx_flow -= slotnum; 3266f3e57acSmx205022 if (srp->tx_flow == 0) { 3276f3e57acSmx205022 3286f3e57acSmx205022 /* 3296f3e57acSmx205022 * Bump the watchdog counter, thus guaranteeing that it's 3306f3e57acSmx205022 * nonzero (watchdog activated). Note that non-synchonised 3316f3e57acSmx205022 * access here means we may race with the reclaim() code 3326f3e57acSmx205022 * above, but the outcome will be harmless. At worst, the 3336f3e57acSmx205022 * counter may not get reset on a partial reclaim; but the 3346f3e57acSmx205022 * large trigger threshold makes false positives unlikely 3356f3e57acSmx205022 */ 33651fc88a8SWinson Wang - Sun Microsystems - Beijing China if (ngep->watchdog == 0) 33751fc88a8SWinson Wang - Sun Microsystems - Beijing China ngep->watchdog = 1; 3386f3e57acSmx205022 3396f3e57acSmx205022 mode_cntl.mode_val = nge_reg_get32(ngep, NGE_MODE_CNTL); 3406f3e57acSmx205022 mode_cntl.mode_bits.txdm = NGE_SET; 3416f3e57acSmx205022 mode_cntl.mode_bits.tx_rcom_en = NGE_SET; 3426f3e57acSmx205022 nge_reg_put32(ngep, NGE_MODE_CNTL, mode_cntl.mode_val); 3436f3e57acSmx205022 } 3446f3e57acSmx205022 mutex_exit(srp->tx_lock); 3456f3e57acSmx205022 } 3466f3e57acSmx205022 3476f3e57acSmx205022 static enum send_status 3486f3e57acSmx205022 nge_send_copy(nge_t *ngep, mblk_t *mp, send_ring_t *srp); 3496f3e57acSmx205022 #pragma inline(nge_send_copy) 3506f3e57acSmx205022 3516f3e57acSmx205022 static enum send_status 3526f3e57acSmx205022 nge_send_copy(nge_t *ngep, mblk_t *mp, send_ring_t *srp) 3536f3e57acSmx205022 { 3546f3e57acSmx205022 size_t totlen; 3556f3e57acSmx205022 size_t mblen; 3566f3e57acSmx205022 uint32_t flags; 357a55f7119SMiles Xu, Sun Microsystems uint32_t bds; 358a55f7119SMiles Xu, Sun Microsystems uint32_t start_index; 3596f3e57acSmx205022 char *txb; 3606f3e57acSmx205022 mblk_t *bp; 3616f3e57acSmx205022 void *hw_sbd_p; 3626f3e57acSmx205022 sw_tx_sbd_t *ssbdp; 36351fc88a8SWinson Wang - Sun Microsystems - Beijing China boolean_t tfint; 3646f3e57acSmx205022 365*0dc2366fSVenugopal Iyer mac_hcksum_get(mp, NULL, NULL, NULL, NULL, &flags); 3666f3e57acSmx205022 bds = 0x1; 3676f3e57acSmx205022 368a55f7119SMiles Xu, Sun Microsystems if ((uint32_t)-1 == (start_index = nge_tx_alloc(ngep, bds))) 3696f3e57acSmx205022 return (SEND_COPY_FAIL); 3706f3e57acSmx205022 3716f3e57acSmx205022 ASSERT(start_index < srp->desc.nslots); 3726f3e57acSmx205022 3736f3e57acSmx205022 /* 3746f3e57acSmx205022 * up to this point, there's nothing that can fail, 3756f3e57acSmx205022 * so we can go straight to claiming our 3766f3e57acSmx205022 * already-reserved place son the train. 3776f3e57acSmx205022 * 3786f3e57acSmx205022 * This is the point of no return! 3796f3e57acSmx205022 */ 3806f3e57acSmx205022 38151fc88a8SWinson Wang - Sun Microsystems - Beijing China tfint = ((start_index % ngep->tfint_threshold) == 0); 3826f3e57acSmx205022 bp = mp; 3836f3e57acSmx205022 totlen = 0; 3846f3e57acSmx205022 ssbdp = &srp->sw_sbds[start_index]; 3856f3e57acSmx205022 ASSERT(ssbdp->flags == HOST_OWN); 3866f3e57acSmx205022 3876f3e57acSmx205022 txb = DMA_VPTR(ssbdp->pbuf); 3886f3e57acSmx205022 totlen = 0; 3896f3e57acSmx205022 for (; bp != NULL; bp = bp->b_cont) { 3906f3e57acSmx205022 if ((mblen = MBLKL(bp)) == 0) 3916f3e57acSmx205022 continue; 3926f3e57acSmx205022 if ((totlen += mblen) <= ngep->max_sdu) { 3936f3e57acSmx205022 bcopy(bp->b_rptr, txb, mblen); 3946f3e57acSmx205022 txb += mblen; 3956f3e57acSmx205022 } 3966f3e57acSmx205022 } 3976f3e57acSmx205022 3986f3e57acSmx205022 DMA_SYNC(ssbdp->pbuf, DDI_DMA_SYNC_FORDEV); 3996f3e57acSmx205022 4006f3e57acSmx205022 /* Fill & sync hw desc */ 4016f3e57acSmx205022 4026f3e57acSmx205022 hw_sbd_p = DMA_VPTR(ssbdp->desc); 4036f3e57acSmx205022 4046f3e57acSmx205022 ngep->desc_attr.txd_fill(hw_sbd_p, &ssbdp->pbuf.cookie, totlen, 40551fc88a8SWinson Wang - Sun Microsystems - Beijing China flags, B_TRUE, tfint); 4066f3e57acSmx205022 nge_tx_desc_sync(ngep, start_index, bds, DDI_DMA_SYNC_FORDEV); 4076f3e57acSmx205022 4086f3e57acSmx205022 ssbdp->flags = CONTROLER_OWN; 4096f3e57acSmx205022 4106f3e57acSmx205022 nge_tx_start(ngep, bds); 4116f3e57acSmx205022 4126f3e57acSmx205022 /* 4136f3e57acSmx205022 * The return status indicates that the message can be freed 4146f3e57acSmx205022 * right away, as we've already copied the contents ... 4156f3e57acSmx205022 */ 4166f3e57acSmx205022 4176f3e57acSmx205022 freemsg(mp); 4186f3e57acSmx205022 return (SEND_COPY_SUCESS); 4196f3e57acSmx205022 } 4206f3e57acSmx205022 4216f3e57acSmx205022 /* 4226f3e57acSmx205022 * static enum send_status 4236f3e57acSmx205022 * nge_send_mapped(nge_t *ngep, mblk_t *mp, size_t fragno); 4246f3e57acSmx205022 * #pragma inline(nge_send_mapped) 4256f3e57acSmx205022 */ 4266f3e57acSmx205022 4276f3e57acSmx205022 static enum send_status 4286f3e57acSmx205022 nge_send_mapped(nge_t *ngep, mblk_t *mp, size_t fragno) 4296f3e57acSmx205022 { 4306f3e57acSmx205022 int err; 4316f3e57acSmx205022 boolean_t end; 4326f3e57acSmx205022 uint32_t i; 4336f3e57acSmx205022 uint32_t j; 4346f3e57acSmx205022 uint32_t ncookies; 4356f3e57acSmx205022 uint32_t slot; 4366f3e57acSmx205022 uint32_t nslots; 4376f3e57acSmx205022 uint32_t mblen; 4386f3e57acSmx205022 uint32_t flags; 439a55f7119SMiles Xu, Sun Microsystems uint32_t start_index; 440a55f7119SMiles Xu, Sun Microsystems uint32_t end_index; 4416f3e57acSmx205022 mblk_t *bp; 4426f3e57acSmx205022 void *hw_sbd_p; 4436f3e57acSmx205022 send_ring_t *srp; 4446f3e57acSmx205022 nge_dmah_node_t *dmah; 4456f3e57acSmx205022 nge_dmah_node_t *dmer; 4466f3e57acSmx205022 nge_dmah_list_t dmah_list; 4476f3e57acSmx205022 ddi_dma_cookie_t cookie[NGE_MAX_COOKIES * NGE_MAP_FRAGS]; 44851fc88a8SWinson Wang - Sun Microsystems - Beijing China boolean_t tfint; 4496f3e57acSmx205022 4506f3e57acSmx205022 srp = ngep->send; 4516f3e57acSmx205022 nslots = srp->desc.nslots; 4526f3e57acSmx205022 4536f3e57acSmx205022 mutex_enter(&srp->dmah_lock); 4546f3e57acSmx205022 err = nge_tx_dmah_pop(&srp->dmah_free, &dmah_list, fragno); 4556f3e57acSmx205022 mutex_exit(&srp->dmah_lock); 4566f3e57acSmx205022 4576f3e57acSmx205022 if (err != 0) { 4586f3e57acSmx205022 4596f3e57acSmx205022 return (SEND_MAP_FAIL); 4606f3e57acSmx205022 } 4616f3e57acSmx205022 4626f3e57acSmx205022 /* 4636f3e57acSmx205022 * Pre-scan the message chain, noting the total number of bytes, 4646f3e57acSmx205022 * the number of fragments by pre-doing dma addr bind 4656f3e57acSmx205022 * if the fragment is larger than NGE_COPY_SIZE. 4666f3e57acSmx205022 * This way has the following advantages: 4676f3e57acSmx205022 * 1. Acquire the detailed information of resouce 4686f3e57acSmx205022 * need to send the message 4696f3e57acSmx205022 * 4706f3e57acSmx205022 * 2. If can not pre-apply enough resouce, fails at once 4716f3e57acSmx205022 * and the driver will chose copy way to send out the 4726f3e57acSmx205022 * message 4736f3e57acSmx205022 */ 4746f3e57acSmx205022 4756f3e57acSmx205022 slot = 0; 4766f3e57acSmx205022 dmah = dmah_list.head; 4776f3e57acSmx205022 478*0dc2366fSVenugopal Iyer mac_hcksum_get(mp, NULL, NULL, NULL, NULL, &flags); 4796f3e57acSmx205022 4806f3e57acSmx205022 for (bp = mp; bp != NULL; bp = bp->b_cont) { 4816f3e57acSmx205022 4826f3e57acSmx205022 mblen = MBLKL(bp); 4836f3e57acSmx205022 if (mblen == 0) 4846f3e57acSmx205022 continue; 4856f3e57acSmx205022 4866f3e57acSmx205022 err = ddi_dma_addr_bind_handle(dmah->hndl, 4876f3e57acSmx205022 NULL, (caddr_t)bp->b_rptr, mblen, 4886f3e57acSmx205022 DDI_DMA_STREAMING | DDI_DMA_WRITE, 4896f3e57acSmx205022 DDI_DMA_DONTWAIT, NULL, cookie + slot, &ncookies); 4906f3e57acSmx205022 4916f3e57acSmx205022 /* 4926f3e57acSmx205022 * If there can not map successfully, it is uncessary 4936f3e57acSmx205022 * sending the message by map way. Sending the message 4946f3e57acSmx205022 * by copy way. 4956f3e57acSmx205022 * 4966f3e57acSmx205022 * By referring to intel's suggestion, it is better 4976f3e57acSmx205022 * the number of cookies should be less than 4. 4986f3e57acSmx205022 */ 4996f3e57acSmx205022 if (err != DDI_DMA_MAPPED || ncookies > NGE_MAX_COOKIES) { 5006f3e57acSmx205022 NGE_DEBUG(("err(%x) map tx bulk fails" 5016f3e57acSmx205022 " cookie(%x), ncookies(%x)", 5026f3e57acSmx205022 err, cookie[slot].dmac_laddress, ncookies)); 5036f3e57acSmx205022 goto map_fail; 5046f3e57acSmx205022 } 5056f3e57acSmx205022 5066f3e57acSmx205022 /* 5076f3e57acSmx205022 * Check How many bds a cookie will consume 5086f3e57acSmx205022 */ 5096f3e57acSmx205022 for (end_index = slot + ncookies; 5106f3e57acSmx205022 ++slot != end_index; 5116f3e57acSmx205022 ddi_dma_nextcookie(dmah->hndl, cookie + slot)) 5126f3e57acSmx205022 ; 5136f3e57acSmx205022 5146f3e57acSmx205022 dmah = dmah->next; 5156f3e57acSmx205022 } 5166f3e57acSmx205022 5176f3e57acSmx205022 /* 5186f3e57acSmx205022 * Now allocate tx descriptors and fill them 5196f3e57acSmx205022 * IMPORTANT: 5206f3e57acSmx205022 * Up to the point where it claims a place, It is impossibel 5216f3e57acSmx205022 * to fail. 5226f3e57acSmx205022 * 5236f3e57acSmx205022 * In this version, there's no setup to be done here, and there's 5246f3e57acSmx205022 * nothing that can fail, so we can go straight to claiming our 5256f3e57acSmx205022 * already-reserved places on the train. 5266f3e57acSmx205022 * 5276f3e57acSmx205022 * This is the point of no return! 5286f3e57acSmx205022 */ 5296f3e57acSmx205022 5306f3e57acSmx205022 531a55f7119SMiles Xu, Sun Microsystems if ((uint32_t)-1 == (start_index = nge_tx_alloc(ngep, slot))) 5326f3e57acSmx205022 goto map_fail; 5336f3e57acSmx205022 5346f3e57acSmx205022 ASSERT(start_index < nslots); 5356f3e57acSmx205022 5366f3e57acSmx205022 /* fill&sync hw desc, going in reverse order */ 5376f3e57acSmx205022 5386f3e57acSmx205022 end = B_TRUE; 5396f3e57acSmx205022 end_index = NEXT_INDEX(start_index, slot - 1, nslots); 5406f3e57acSmx205022 5416f3e57acSmx205022 for (i = slot - 1, j = end_index; start_index - j != 0; 5426f3e57acSmx205022 j = PREV(j, nslots), --i) { 5436f3e57acSmx205022 54451fc88a8SWinson Wang - Sun Microsystems - Beijing China tfint = ((j % ngep->tfint_threshold) == 0); 5456f3e57acSmx205022 hw_sbd_p = DMA_VPTR(srp->sw_sbds[j].desc); 5466f3e57acSmx205022 ngep->desc_attr.txd_fill(hw_sbd_p, cookie + i, 54751fc88a8SWinson Wang - Sun Microsystems - Beijing China cookie[i].dmac_size, 0, end, tfint); 5486f3e57acSmx205022 5496f3e57acSmx205022 end = B_FALSE; 5506f3e57acSmx205022 } 5516f3e57acSmx205022 5526f3e57acSmx205022 hw_sbd_p = DMA_VPTR(srp->sw_sbds[j].desc); 55351fc88a8SWinson Wang - Sun Microsystems - Beijing China tfint = ((j % ngep->tfint_threshold) == 0); 5546f3e57acSmx205022 ngep->desc_attr.txd_fill(hw_sbd_p, cookie + i, cookie[i].dmac_size, 55551fc88a8SWinson Wang - Sun Microsystems - Beijing China flags, end, tfint); 5566f3e57acSmx205022 5576f3e57acSmx205022 nge_tx_desc_sync(ngep, start_index, slot, DDI_DMA_SYNC_FORDEV); 5586f3e57acSmx205022 5596f3e57acSmx205022 /* fill sw desc */ 5606f3e57acSmx205022 5616f3e57acSmx205022 for (j = start_index; end_index - j != 0; j = NEXT(j, nslots)) { 5626f3e57acSmx205022 5636f3e57acSmx205022 srp->sw_sbds[j].flags = CONTROLER_OWN; 5646f3e57acSmx205022 } 5656f3e57acSmx205022 5666f3e57acSmx205022 srp->sw_sbds[j].mp = mp; 5676f3e57acSmx205022 srp->sw_sbds[j].mp_hndl = dmah_list; 568a55f7119SMiles Xu, Sun Microsystems srp->sw_sbds[j].frags = (uint32_t)fragno; 5696f3e57acSmx205022 srp->sw_sbds[j].flags = CONTROLER_OWN; 5706f3e57acSmx205022 5716f3e57acSmx205022 nge_tx_start(ngep, slot); 5726f3e57acSmx205022 5736f3e57acSmx205022 /* 5746f3e57acSmx205022 * The return status indicates that the message can not be freed 5756f3e57acSmx205022 * right away, until we can make assure the message has been sent 5766f3e57acSmx205022 * out sucessfully. 5776f3e57acSmx205022 */ 5786f3e57acSmx205022 return (SEND_MAP_SUCCESS); 5796f3e57acSmx205022 5806f3e57acSmx205022 map_fail: 5816f3e57acSmx205022 for (dmer = dmah_list.head; dmah - dmer != 0; dmer = dmer->next) 5826f3e57acSmx205022 (void) ddi_dma_unbind_handle(dmer->hndl); 5836f3e57acSmx205022 5846f3e57acSmx205022 mutex_enter(&srp->dmah_lock); 5856f3e57acSmx205022 nge_tx_dmah_push(&dmah_list, &srp->dmah_free); 5866f3e57acSmx205022 mutex_exit(&srp->dmah_lock); 5876f3e57acSmx205022 5886f3e57acSmx205022 return (SEND_MAP_FAIL); 5896f3e57acSmx205022 } 5906f3e57acSmx205022 5916f3e57acSmx205022 static boolean_t 5926f3e57acSmx205022 nge_send(nge_t *ngep, mblk_t *mp) 5936f3e57acSmx205022 { 5946f3e57acSmx205022 mblk_t *bp; 5956f3e57acSmx205022 send_ring_t *srp; 5966f3e57acSmx205022 enum send_status status; 5976f3e57acSmx205022 uint32_t mblen = 0; 5986f3e57acSmx205022 uint32_t frags = 0; 5996f3e57acSmx205022 nge_statistics_t *nstp = &ngep->statistics; 6006f3e57acSmx205022 nge_sw_statistics_t *sw_stp = &nstp->sw_statistics; 6016f3e57acSmx205022 6026f3e57acSmx205022 ASSERT(mp != NULL); 6036f3e57acSmx205022 ASSERT(ngep->nge_mac_state == NGE_MAC_STARTED); 6046f3e57acSmx205022 6056f3e57acSmx205022 srp = ngep->send; 6066f3e57acSmx205022 /* 6076f3e57acSmx205022 * 1.Check the number of the fragments of the messages 6086f3e57acSmx205022 * If the total number is larger than 3, 6096f3e57acSmx205022 * Chose copy way 6106f3e57acSmx205022 * 6116f3e57acSmx205022 * 2. Check the length of the message whether is larger than 6126f3e57acSmx205022 * NGE_TX_COPY_SIZE, if so, choose the map way. 6136f3e57acSmx205022 */ 6146f3e57acSmx205022 for (frags = 0, bp = mp; bp != NULL; bp = bp->b_cont) { 6156f3e57acSmx205022 if (MBLKL(bp) == 0) 6166f3e57acSmx205022 continue; 6176f3e57acSmx205022 frags++; 6186f3e57acSmx205022 mblen += MBLKL(bp); 6196f3e57acSmx205022 } 6206f3e57acSmx205022 if (mblen > (ngep->max_sdu) || mblen == 0) { 6216f3e57acSmx205022 freemsg(mp); 6226f3e57acSmx205022 return (B_TRUE); 6236f3e57acSmx205022 } 6246f3e57acSmx205022 if ((mblen > ngep->param_txbcopy_threshold) && 6256ad24245SWinson Wang - Sun Microsystems - Beijing China (frags <= NGE_MAP_FRAGS) && 6266f3e57acSmx205022 (srp->tx_free > frags * NGE_MAX_COOKIES)) { 6276f3e57acSmx205022 status = nge_send_mapped(ngep, mp, frags); 6286f3e57acSmx205022 if (status == SEND_MAP_FAIL) 6296f3e57acSmx205022 status = nge_send_copy(ngep, mp, srp); 6306f3e57acSmx205022 } else { 6316f3e57acSmx205022 status = nge_send_copy(ngep, mp, srp); 6326f3e57acSmx205022 } 6336f3e57acSmx205022 if (status == SEND_COPY_FAIL) { 6346f3e57acSmx205022 nge_tx_recycle(ngep, B_FALSE); 6356f3e57acSmx205022 status = nge_send_copy(ngep, mp, srp); 6366f3e57acSmx205022 if (status == SEND_COPY_FAIL) { 6376f3e57acSmx205022 ngep->resched_needed = 1; 6386f3e57acSmx205022 NGE_DEBUG(("nge_send: send fail!")); 6396f3e57acSmx205022 return (B_FALSE); 6406f3e57acSmx205022 } 6416f3e57acSmx205022 } 6426f3e57acSmx205022 /* Update the software statistics */ 6436f3e57acSmx205022 sw_stp->obytes += mblen + ETHERFCSL; 6446f3e57acSmx205022 sw_stp->xmit_count ++; 6456f3e57acSmx205022 6466f3e57acSmx205022 return (B_TRUE); 6476f3e57acSmx205022 } 6486f3e57acSmx205022 6496f3e57acSmx205022 /* 6506f3e57acSmx205022 * nge_m_tx : Send a chain of packets. 6516f3e57acSmx205022 */ 6526f3e57acSmx205022 mblk_t * 6536f3e57acSmx205022 nge_m_tx(void *arg, mblk_t *mp) 6546f3e57acSmx205022 { 6556f3e57acSmx205022 nge_t *ngep = arg; 6566f3e57acSmx205022 mblk_t *next; 6576f3e57acSmx205022 6586f3e57acSmx205022 rw_enter(ngep->rwlock, RW_READER); 6596f3e57acSmx205022 ASSERT(mp != NULL); 6606f3e57acSmx205022 if (ngep->nge_chip_state != NGE_CHIP_RUNNING) { 6616f3e57acSmx205022 freemsgchain(mp); 6626f3e57acSmx205022 mp = NULL; 6636f3e57acSmx205022 } 6646f3e57acSmx205022 while (mp != NULL) { 6656f3e57acSmx205022 next = mp->b_next; 6666f3e57acSmx205022 mp->b_next = NULL; 6676f3e57acSmx205022 6686f3e57acSmx205022 if (!nge_send(ngep, mp)) { 6696f3e57acSmx205022 mp->b_next = next; 6706f3e57acSmx205022 break; 6716f3e57acSmx205022 } 6726f3e57acSmx205022 6736f3e57acSmx205022 mp = next; 6746f3e57acSmx205022 } 6756f3e57acSmx205022 rw_exit(ngep->rwlock); 6766f3e57acSmx205022 6776f3e57acSmx205022 return (mp); 6786f3e57acSmx205022 } 6796f3e57acSmx205022 6806f3e57acSmx205022 /* ARGSUSED */ 6816f3e57acSmx205022 uint_t 6826f3e57acSmx205022 nge_reschedule(caddr_t args1, caddr_t args2) 6836f3e57acSmx205022 { 6846f3e57acSmx205022 nge_t *ngep; 6856f3e57acSmx205022 uint_t rslt; 6866f3e57acSmx205022 6876f3e57acSmx205022 ngep = (nge_t *)args1; 6886f3e57acSmx205022 rslt = DDI_INTR_UNCLAIMED; 6896f3e57acSmx205022 6906f3e57acSmx205022 /* 6916f3e57acSmx205022 * when softintr is trigged, checking whether this 6926f3e57acSmx205022 * is caused by our expected interrupt 6936f3e57acSmx205022 */ 6946f3e57acSmx205022 if (ngep->nge_mac_state == NGE_MAC_STARTED && 6956f3e57acSmx205022 ngep->resched_needed == 1) { 6966f3e57acSmx205022 ngep->resched_needed = 0; 6976f3e57acSmx205022 ++ngep->statistics.sw_statistics.tx_resched; 6986f3e57acSmx205022 mac_tx_update(ngep->mh); 6996f3e57acSmx205022 rslt = DDI_INTR_CLAIMED; 7006f3e57acSmx205022 } 7016f3e57acSmx205022 return (rslt); 7026f3e57acSmx205022 } 7036f3e57acSmx205022 7046f3e57acSmx205022 uint32_t 7059fa05d92SWinson Wang - Sun Microsystems - Beijing China nge_hot_txd_check(const void *hwd) 7066f3e57acSmx205022 { 7076f3e57acSmx205022 uint32_t err_flag; 7086f3e57acSmx205022 const hot_tx_bd * htbdp; 7096f3e57acSmx205022 7106f3e57acSmx205022 htbdp = hwd; 7119fa05d92SWinson Wang - Sun Microsystems - Beijing China err_flag = htbdp->control_status.cntl_val; 7126f3e57acSmx205022 return (err_flag); 7136f3e57acSmx205022 } 7146f3e57acSmx205022 7156f3e57acSmx205022 uint32_t 7169fa05d92SWinson Wang - Sun Microsystems - Beijing China nge_sum_txd_check(const void *hwd) 7176f3e57acSmx205022 { 7186f3e57acSmx205022 uint32_t err_flag; 7196f3e57acSmx205022 const sum_tx_bd * htbdp; 7206f3e57acSmx205022 7216f3e57acSmx205022 htbdp = hwd; 7229fa05d92SWinson Wang - Sun Microsystems - Beijing China err_flag = htbdp->control_status.cntl_val; 7236f3e57acSmx205022 return (err_flag); 7246f3e57acSmx205022 } 7256f3e57acSmx205022 7266f3e57acSmx205022 7276f3e57acSmx205022 /* 7286f3e57acSmx205022 * Filling the contents of Tx's data descriptor 7296f3e57acSmx205022 * before transmitting. 7306f3e57acSmx205022 */ 7316f3e57acSmx205022 7326f3e57acSmx205022 void 7336f3e57acSmx205022 nge_hot_txd_fill(void *hwdesc, const ddi_dma_cookie_t *cookie, 73451fc88a8SWinson Wang - Sun Microsystems - Beijing China size_t length, uint32_t sum_flag, boolean_t end, boolean_t tfint) 7356f3e57acSmx205022 { 7366f3e57acSmx205022 hot_tx_bd * hw_sbd_p = hwdesc; 7376f3e57acSmx205022 7386f3e57acSmx205022 hw_sbd_p->host_buf_addr_hi = cookie->dmac_laddress >> 32; 7396f3e57acSmx205022 hw_sbd_p->host_buf_addr_lo = cookie->dmac_laddress; 7406f3e57acSmx205022 7416f3e57acSmx205022 /* 7426f3e57acSmx205022 * Setting the length of the packet 7436f3e57acSmx205022 * Note: the length filled in the part should be 7446f3e57acSmx205022 * the original length subtract 1; 7456f3e57acSmx205022 */ 7466f3e57acSmx205022 7476f3e57acSmx205022 hw_sbd_p->control_status.control_sum_bits.bcnt = length - 1; 7486f3e57acSmx205022 7496f3e57acSmx205022 /* setting ip checksum */ 7506f3e57acSmx205022 if (sum_flag & HCK_IPV4_HDRCKSUM) 7516f3e57acSmx205022 hw_sbd_p->control_status.control_sum_bits.ip_hsum 7526f3e57acSmx205022 = NGE_SET; 7536f3e57acSmx205022 /* setting tcp checksum */ 7546f3e57acSmx205022 if (sum_flag & HCK_FULLCKSUM) 7556f3e57acSmx205022 hw_sbd_p->control_status.control_sum_bits.tcp_hsum 7566f3e57acSmx205022 = NGE_SET; 7576f3e57acSmx205022 /* 7586f3e57acSmx205022 * indicating the end of BDs 7596f3e57acSmx205022 */ 76051fc88a8SWinson Wang - Sun Microsystems - Beijing China if (tfint) 76151fc88a8SWinson Wang - Sun Microsystems - Beijing China hw_sbd_p->control_status.control_sum_bits.inten = NGE_SET; 7626f3e57acSmx205022 if (end) 7636f3e57acSmx205022 hw_sbd_p->control_status.control_sum_bits.end = NGE_SET; 7646f3e57acSmx205022 7656f3e57acSmx205022 membar_producer(); 7666f3e57acSmx205022 7676f3e57acSmx205022 /* pass desc to HW */ 7686f3e57acSmx205022 hw_sbd_p->control_status.control_sum_bits.own = NGE_SET; 7696f3e57acSmx205022 } 7706f3e57acSmx205022 7716f3e57acSmx205022 void 7726f3e57acSmx205022 nge_sum_txd_fill(void *hwdesc, const ddi_dma_cookie_t *cookie, 77351fc88a8SWinson Wang - Sun Microsystems - Beijing China size_t length, uint32_t sum_flag, boolean_t end, boolean_t tfint) 7746f3e57acSmx205022 { 7756f3e57acSmx205022 sum_tx_bd * hw_sbd_p = hwdesc; 7766f3e57acSmx205022 7776f3e57acSmx205022 hw_sbd_p->host_buf_addr = cookie->dmac_address; 7786f3e57acSmx205022 7796f3e57acSmx205022 /* 7806f3e57acSmx205022 * Setting the length of the packet 7816f3e57acSmx205022 * Note: the length filled in the part should be 7826f3e57acSmx205022 * the original length subtract 1; 7836f3e57acSmx205022 */ 7846f3e57acSmx205022 7856f3e57acSmx205022 hw_sbd_p->control_status.control_sum_bits.bcnt = length - 1; 7866f3e57acSmx205022 7876f3e57acSmx205022 /* setting ip checksum */ 7886f3e57acSmx205022 if (sum_flag & HCK_IPV4_HDRCKSUM) 7896f3e57acSmx205022 hw_sbd_p->control_status.control_sum_bits.ip_hsum 7906f3e57acSmx205022 = NGE_SET; 7916f3e57acSmx205022 /* setting tcp checksum */ 7926f3e57acSmx205022 if (sum_flag & HCK_FULLCKSUM) 7936f3e57acSmx205022 hw_sbd_p->control_status.control_sum_bits.tcp_hsum 7946f3e57acSmx205022 = NGE_SET; 7956f3e57acSmx205022 /* 7966f3e57acSmx205022 * indicating the end of BDs 7976f3e57acSmx205022 */ 79851fc88a8SWinson Wang - Sun Microsystems - Beijing China if (tfint) 79951fc88a8SWinson Wang - Sun Microsystems - Beijing China hw_sbd_p->control_status.control_sum_bits.inten = NGE_SET; 8006f3e57acSmx205022 if (end) 8016f3e57acSmx205022 hw_sbd_p->control_status.control_sum_bits.end = NGE_SET; 8026f3e57acSmx205022 8036f3e57acSmx205022 membar_producer(); 8046f3e57acSmx205022 8056f3e57acSmx205022 /* pass desc to HW */ 8066f3e57acSmx205022 hw_sbd_p->control_status.control_sum_bits.own = NGE_SET; 8076f3e57acSmx205022 } 808