1*d14abf15SRobert Mustacchi /* 2*d14abf15SRobert Mustacchi * CDDL HEADER START 3*d14abf15SRobert Mustacchi * 4*d14abf15SRobert Mustacchi * The contents of this file are subject to the terms of the 5*d14abf15SRobert Mustacchi * Common Development and Distribution License (the "License"). 6*d14abf15SRobert Mustacchi * You may not use this file except in compliance with the License. 7*d14abf15SRobert Mustacchi * 8*d14abf15SRobert Mustacchi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*d14abf15SRobert Mustacchi * or http://www.opensolaris.org/os/licensing. 10*d14abf15SRobert Mustacchi * See the License for the specific language governing permissions 11*d14abf15SRobert Mustacchi * and limitations under the License. 12*d14abf15SRobert Mustacchi * 13*d14abf15SRobert Mustacchi * When distributing Covered Code, include this CDDL HEADER in each 14*d14abf15SRobert Mustacchi * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*d14abf15SRobert Mustacchi * If applicable, add the following below this CDDL HEADER, with the 16*d14abf15SRobert Mustacchi * fields enclosed by brackets "[]" replaced with your own identifying 17*d14abf15SRobert Mustacchi * information: Portions Copyright [yyyy] [name of copyright owner] 18*d14abf15SRobert Mustacchi * 19*d14abf15SRobert Mustacchi * CDDL HEADER END 20*d14abf15SRobert Mustacchi */ 21*d14abf15SRobert Mustacchi 22*d14abf15SRobert Mustacchi /* 23*d14abf15SRobert Mustacchi * Copyright 2014 QLogic Corporation 24*d14abf15SRobert Mustacchi * The contents of this file are subject to the terms of the 25*d14abf15SRobert Mustacchi * QLogic End User License (the "License"). 26*d14abf15SRobert Mustacchi * You may not use this file except in compliance with the License. 27*d14abf15SRobert Mustacchi * 28*d14abf15SRobert Mustacchi * You can obtain a copy of the License at 29*d14abf15SRobert Mustacchi * http://www.qlogic.com/Resources/Documents/DriverDownloadHelp/ 30*d14abf15SRobert Mustacchi * QLogic_End_User_Software_License.txt 31*d14abf15SRobert Mustacchi * See the License for the specific language governing permissions 32*d14abf15SRobert Mustacchi * and limitations under the License. 33*d14abf15SRobert Mustacchi */ 34*d14abf15SRobert Mustacchi 35*d14abf15SRobert Mustacchi /* 36*d14abf15SRobert Mustacchi * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. 37*d14abf15SRobert Mustacchi */ 38*d14abf15SRobert Mustacchi 39*d14abf15SRobert Mustacchi #include "bnxe.h" 40*d14abf15SRobert Mustacchi 41*d14abf15SRobert Mustacchi ddi_dma_attr_t bnxeTxDmaAttrib = 42*d14abf15SRobert Mustacchi { 43*d14abf15SRobert Mustacchi DMA_ATTR_V0, /* dma_attr_version */ 44*d14abf15SRobert Mustacchi 0, /* dma_attr_addr_lo */ 45*d14abf15SRobert Mustacchi 0xffffffffffffffff, /* dma_attr_addr_hi */ 46*d14abf15SRobert Mustacchi 0xffffffffffffffff, /* dma_attr_count_max */ 47*d14abf15SRobert Mustacchi BNXE_DMA_ALIGNMENT, /* dma_attr_align */ 48*d14abf15SRobert Mustacchi 0xffffffff, /* dma_attr_burstsizes */ 49*d14abf15SRobert Mustacchi 1, /* dma_attr_minxfer */ 50*d14abf15SRobert Mustacchi 0xffffffffffffffff, /* dma_attr_maxxfer */ 51*d14abf15SRobert Mustacchi 0xffffffffffffffff, /* dma_attr_seg */ 52*d14abf15SRobert Mustacchi BNXE_MAX_DMA_SGLLEN, /* dma_attr_sgllen */ 53*d14abf15SRobert Mustacchi 1, /* dma_attr_granular */ 54*d14abf15SRobert Mustacchi 0, /* dma_attr_flags */ 55*d14abf15SRobert Mustacchi }; 56*d14abf15SRobert Mustacchi 57*d14abf15SRobert Mustacchi ddi_dma_attr_t bnxeTxCbDmaAttrib = 58*d14abf15SRobert Mustacchi { 59*d14abf15SRobert Mustacchi DMA_ATTR_V0, /* dma_attr_version */ 60*d14abf15SRobert Mustacchi 0, /* dma_attr_addr_lo */ 61*d14abf15SRobert Mustacchi 0xffffffffffffffff, /* dma_attr_addr_hi */ 62*d14abf15SRobert Mustacchi 0xffffffffffffffff, /* dma_attr_count_max */ 63*d14abf15SRobert Mustacchi BNXE_DMA_ALIGNMENT, /* dma_attr_align */ 64*d14abf15SRobert Mustacchi 0xffffffff, /* dma_attr_burstsizes */ 65*d14abf15SRobert Mustacchi 1, /* dma_attr_minxfer */ 66*d14abf15SRobert Mustacchi 0xffffffffffffffff, /* dma_attr_maxxfer */ 67*d14abf15SRobert Mustacchi 0xffffffffffffffff, /* dma_attr_seg */ 68*d14abf15SRobert Mustacchi 1, /* dma_attr_sgllen */ 69*d14abf15SRobert Mustacchi 1, /* dma_attr_granular */ 70*d14abf15SRobert Mustacchi 0, /* dma_attr_flags */ 71*d14abf15SRobert Mustacchi }; 72*d14abf15SRobert Mustacchi 73*d14abf15SRobert Mustacchi 74*d14abf15SRobert Mustacchi static um_txpacket_t * BnxeTxPktAlloc(um_device_t * pUM, size_t size); 75*d14abf15SRobert Mustacchi 76*d14abf15SRobert Mustacchi 77*d14abf15SRobert Mustacchi static inline void BnxeTxPktUnmap(um_txpacket_t * pTxPkt) 78*d14abf15SRobert Mustacchi { 79*d14abf15SRobert Mustacchi int i; 80*d14abf15SRobert Mustacchi 81*d14abf15SRobert Mustacchi for (i = 0; i < pTxPkt->num_handles; i++) 82*d14abf15SRobert Mustacchi { 83*d14abf15SRobert Mustacchi ddi_dma_unbind_handle(pTxPkt->dmaHandles[i]); 84*d14abf15SRobert Mustacchi } 85*d14abf15SRobert Mustacchi 86*d14abf15SRobert Mustacchi pTxPkt->num_handles = 0; 87*d14abf15SRobert Mustacchi } 88*d14abf15SRobert Mustacchi 89*d14abf15SRobert Mustacchi 90*d14abf15SRobert Mustacchi static void BnxeTxPktsFree(um_txpacket_t * pTxPkt) 91*d14abf15SRobert Mustacchi { 92*d14abf15SRobert Mustacchi int i; 93*d14abf15SRobert Mustacchi 94*d14abf15SRobert Mustacchi if (pTxPkt->num_handles > 0) 95*d14abf15SRobert Mustacchi { 96*d14abf15SRobert Mustacchi BnxeTxPktUnmap(pTxPkt); 97*d14abf15SRobert Mustacchi } 98*d14abf15SRobert Mustacchi 99*d14abf15SRobert Mustacchi if (pTxPkt->pMblk != NULL) 100*d14abf15SRobert Mustacchi { 101*d14abf15SRobert Mustacchi freemsg(pTxPkt->pMblk); 102*d14abf15SRobert Mustacchi } 103*d14abf15SRobert Mustacchi 104*d14abf15SRobert Mustacchi for (i = 0; i < BNXE_MAX_DMA_HANDLES_PER_PKT; i++) 105*d14abf15SRobert Mustacchi { 106*d14abf15SRobert Mustacchi ddi_dma_free_handle(&pTxPkt->dmaHandles[i]); 107*d14abf15SRobert Mustacchi } 108*d14abf15SRobert Mustacchi 109*d14abf15SRobert Mustacchi pTxPkt->pMblk = NULL; 110*d14abf15SRobert Mustacchi pTxPkt->num_handles = 0; 111*d14abf15SRobert Mustacchi pTxPkt->frag_list.cnt = 0; 112*d14abf15SRobert Mustacchi 113*d14abf15SRobert Mustacchi ddi_dma_unbind_handle(pTxPkt->cbDmaHandle); 114*d14abf15SRobert Mustacchi ddi_dma_mem_free(&pTxPkt->cbDmaAccHandle); 115*d14abf15SRobert Mustacchi ddi_dma_free_handle(&pTxPkt->cbDmaHandle); 116*d14abf15SRobert Mustacchi kmem_free(pTxPkt, sizeof(um_txpacket_t)); 117*d14abf15SRobert Mustacchi } 118*d14abf15SRobert Mustacchi 119*d14abf15SRobert Mustacchi 120*d14abf15SRobert Mustacchi static void BnxeTxPktsFreeList(s_list_t * pPktList) 121*d14abf15SRobert Mustacchi { 122*d14abf15SRobert Mustacchi um_txpacket_t * pTxPkt; 123*d14abf15SRobert Mustacchi 124*d14abf15SRobert Mustacchi while (!s_list_is_empty(pPktList)) 125*d14abf15SRobert Mustacchi { 126*d14abf15SRobert Mustacchi pTxPkt = (um_txpacket_t *)s_list_pop_head(pPktList); 127*d14abf15SRobert Mustacchi BnxeTxPktsFree(pTxPkt); 128*d14abf15SRobert Mustacchi } 129*d14abf15SRobert Mustacchi } 130*d14abf15SRobert Mustacchi 131*d14abf15SRobert Mustacchi 132*d14abf15SRobert Mustacchi /* 133*d14abf15SRobert Mustacchi * Free the mblk and all frag mappings used by each packet in the list 134*d14abf15SRobert Mustacchi * and then put the entire list on the free queue for immediate use. 135*d14abf15SRobert Mustacchi */ 136*d14abf15SRobert Mustacchi void BnxeTxPktsReclaim(um_device_t * pUM, 137*d14abf15SRobert Mustacchi int idx, 138*d14abf15SRobert Mustacchi s_list_t * pPktList) 139*d14abf15SRobert Mustacchi { 140*d14abf15SRobert Mustacchi um_txpacket_t * pTxPkt; 141*d14abf15SRobert Mustacchi 142*d14abf15SRobert Mustacchi if (s_list_entry_cnt(pPktList) == 0) 143*d14abf15SRobert Mustacchi { 144*d14abf15SRobert Mustacchi return; 145*d14abf15SRobert Mustacchi } 146*d14abf15SRobert Mustacchi 147*d14abf15SRobert Mustacchi for (pTxPkt = (um_txpacket_t *)s_list_peek_head(pPktList); 148*d14abf15SRobert Mustacchi pTxPkt; 149*d14abf15SRobert Mustacchi pTxPkt = (um_txpacket_t *)s_list_next_entry(&pTxPkt->lm_pkt.link)) 150*d14abf15SRobert Mustacchi { 151*d14abf15SRobert Mustacchi if (pTxPkt->num_handles > 0) 152*d14abf15SRobert Mustacchi { 153*d14abf15SRobert Mustacchi BnxeTxPktUnmap(pTxPkt); 154*d14abf15SRobert Mustacchi } 155*d14abf15SRobert Mustacchi 156*d14abf15SRobert Mustacchi if (pTxPkt->pMblk != NULL) 157*d14abf15SRobert Mustacchi { 158*d14abf15SRobert Mustacchi freemsg(pTxPkt->pMblk); 159*d14abf15SRobert Mustacchi pTxPkt->pMblk = NULL; 160*d14abf15SRobert Mustacchi } 161*d14abf15SRobert Mustacchi } 162*d14abf15SRobert Mustacchi 163*d14abf15SRobert Mustacchi BNXE_LOCK_ENTER_FREETX(pUM, idx); 164*d14abf15SRobert Mustacchi s_list_add_tail(&pUM->txq[idx].freeTxDescQ, pPktList); 165*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_FREETX(pUM, idx); 166*d14abf15SRobert Mustacchi } 167*d14abf15SRobert Mustacchi 168*d14abf15SRobert Mustacchi 169*d14abf15SRobert Mustacchi /* Must be called with TX lock held!!! */ 170*d14abf15SRobert Mustacchi static int BnxeTxSendWaitingPkt(um_device_t * pUM, 171*d14abf15SRobert Mustacchi int idx) 172*d14abf15SRobert Mustacchi { 173*d14abf15SRobert Mustacchi TxQueue * pTxQ = &pUM->txq[idx]; 174*d14abf15SRobert Mustacchi lm_device_t * pLM = &pUM->lm_dev; 175*d14abf15SRobert Mustacchi lm_tx_chain_t * pLmTxChain; 176*d14abf15SRobert Mustacchi um_txpacket_t * pTxPkt; 177*d14abf15SRobert Mustacchi int rc; 178*d14abf15SRobert Mustacchi 179*d14abf15SRobert Mustacchi pLmTxChain = &pLM->tx_info.chain[idx]; 180*d14abf15SRobert Mustacchi 181*d14abf15SRobert Mustacchi while (s_list_entry_cnt(&pTxQ->waitTxDescQ)) 182*d14abf15SRobert Mustacchi { 183*d14abf15SRobert Mustacchi pTxPkt = (um_txpacket_t *)s_list_peek_head(&pTxQ->waitTxDescQ); 184*d14abf15SRobert Mustacchi 185*d14abf15SRobert Mustacchi if (pTxPkt->frag_list.cnt + 2 > pLmTxChain->bd_chain.bd_left) 186*d14abf15SRobert Mustacchi { 187*d14abf15SRobert Mustacchi return BNXE_TX_DEFERPKT; 188*d14abf15SRobert Mustacchi } 189*d14abf15SRobert Mustacchi 190*d14abf15SRobert Mustacchi pTxPkt = (um_txpacket_t *)s_list_pop_head(&pTxQ->waitTxDescQ); 191*d14abf15SRobert Mustacchi 192*d14abf15SRobert Mustacchi rc = lm_send_packet(pLM, idx, &pTxPkt->lm_pkt, &pTxPkt->frag_list); 193*d14abf15SRobert Mustacchi 194*d14abf15SRobert Mustacchi if (pUM->fmCapabilities && 195*d14abf15SRobert Mustacchi BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK) 196*d14abf15SRobert Mustacchi { 197*d14abf15SRobert Mustacchi ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); 198*d14abf15SRobert Mustacchi } 199*d14abf15SRobert Mustacchi 200*d14abf15SRobert Mustacchi if (rc != LM_STATUS_SUCCESS) 201*d14abf15SRobert Mustacchi { 202*d14abf15SRobert Mustacchi /* 203*d14abf15SRobert Mustacchi * Send failed (probably not enough BDs available)... 204*d14abf15SRobert Mustacchi * Put the packet back at the head of the wait queue. 205*d14abf15SRobert Mustacchi */ 206*d14abf15SRobert Mustacchi pTxQ->txFailed++; 207*d14abf15SRobert Mustacchi s_list_push_head(&pTxQ->waitTxDescQ, &pTxPkt->lm_pkt.link); 208*d14abf15SRobert Mustacchi return BNXE_TX_DEFERPKT; 209*d14abf15SRobert Mustacchi } 210*d14abf15SRobert Mustacchi } 211*d14abf15SRobert Mustacchi 212*d14abf15SRobert Mustacchi return BNXE_TX_GOODXMIT; 213*d14abf15SRobert Mustacchi } 214*d14abf15SRobert Mustacchi 215*d14abf15SRobert Mustacchi 216*d14abf15SRobert Mustacchi void BnxeTxRingProcess(um_device_t * pUM, 217*d14abf15SRobert Mustacchi int idx) 218*d14abf15SRobert Mustacchi { 219*d14abf15SRobert Mustacchi TxQueue * pTxQ = &pUM->txq[idx]; 220*d14abf15SRobert Mustacchi lm_device_t * pLM = &pUM->lm_dev; 221*d14abf15SRobert Mustacchi lm_tx_chain_t * pLmTxChain; 222*d14abf15SRobert Mustacchi s_list_t tmpList; 223*d14abf15SRobert Mustacchi u32_t pktsTxed; 224*d14abf15SRobert Mustacchi int rc; 225*d14abf15SRobert Mustacchi 226*d14abf15SRobert Mustacchi s_list_clear(&tmpList); 227*d14abf15SRobert Mustacchi 228*d14abf15SRobert Mustacchi BNXE_LOCK_ENTER_TX(pUM, idx); 229*d14abf15SRobert Mustacchi 230*d14abf15SRobert Mustacchi pktsTxed = lm_get_packets_sent(&pUM->lm_dev, idx, &tmpList); 231*d14abf15SRobert Mustacchi 232*d14abf15SRobert Mustacchi if (pUM->fmCapabilities && 233*d14abf15SRobert Mustacchi BnxeCheckAccHandle(pUM->lm_dev.vars.reg_handle[BAR_0]) != DDI_FM_OK) 234*d14abf15SRobert Mustacchi { 235*d14abf15SRobert Mustacchi ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); 236*d14abf15SRobert Mustacchi } 237*d14abf15SRobert Mustacchi 238*d14abf15SRobert Mustacchi if ((pktsTxed + s_list_entry_cnt(&pTxQ->sentTxQ)) >= 239*d14abf15SRobert Mustacchi pUM->devParams.maxTxFree) 240*d14abf15SRobert Mustacchi { 241*d14abf15SRobert Mustacchi s_list_add_tail(&tmpList, &pTxQ->sentTxQ); 242*d14abf15SRobert Mustacchi s_list_clear(&pTxQ->sentTxQ); 243*d14abf15SRobert Mustacchi } 244*d14abf15SRobert Mustacchi else 245*d14abf15SRobert Mustacchi { 246*d14abf15SRobert Mustacchi s_list_add_tail(&pTxQ->sentTxQ, &tmpList); 247*d14abf15SRobert Mustacchi s_list_clear(&tmpList); 248*d14abf15SRobert Mustacchi } 249*d14abf15SRobert Mustacchi 250*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_TX(pUM, idx); 251*d14abf15SRobert Mustacchi 252*d14abf15SRobert Mustacchi if (s_list_entry_cnt(&tmpList)) 253*d14abf15SRobert Mustacchi { 254*d14abf15SRobert Mustacchi BnxeTxPktsReclaim(pUM, idx, &tmpList); 255*d14abf15SRobert Mustacchi } 256*d14abf15SRobert Mustacchi 257*d14abf15SRobert Mustacchi if (pTxQ->noTxCredits == 0) 258*d14abf15SRobert Mustacchi { 259*d14abf15SRobert Mustacchi /* no need to notify the stack */ 260*d14abf15SRobert Mustacchi return; 261*d14abf15SRobert Mustacchi } 262*d14abf15SRobert Mustacchi 263*d14abf15SRobert Mustacchi pLmTxChain = &pUM->lm_dev.tx_info.chain[idx]; 264*d14abf15SRobert Mustacchi 265*d14abf15SRobert Mustacchi if (pTxQ->noTxCredits & BNXE_TX_RESOURCES_NO_CREDIT) 266*d14abf15SRobert Mustacchi { 267*d14abf15SRobert Mustacchi BNXE_LOCK_ENTER_TX(pUM, idx); 268*d14abf15SRobert Mustacchi rc = BnxeTxSendWaitingPkt(pUM, idx); 269*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_TX(pUM, idx); 270*d14abf15SRobert Mustacchi 271*d14abf15SRobert Mustacchi if ((rc == BNXE_TX_GOODXMIT) && 272*d14abf15SRobert Mustacchi (pLmTxChain->bd_chain.bd_left >= BNXE_MAX_DMA_FRAGS_PER_PKT)) 273*d14abf15SRobert Mustacchi { 274*d14abf15SRobert Mustacchi atomic_and_32(&pTxQ->noTxCredits, ~BNXE_TX_RESOURCES_NO_CREDIT); 275*d14abf15SRobert Mustacchi } 276*d14abf15SRobert Mustacchi } 277*d14abf15SRobert Mustacchi 278*d14abf15SRobert Mustacchi if ((pTxQ->noTxCredits & BNXE_TX_RESOURCES_NO_DESC) && 279*d14abf15SRobert Mustacchi (s_list_entry_cnt(&pTxQ->freeTxDescQ) > pTxQ->thresh_pdwm)) 280*d14abf15SRobert Mustacchi { 281*d14abf15SRobert Mustacchi atomic_and_32(&pTxQ->noTxCredits, ~BNXE_TX_RESOURCES_NO_DESC); 282*d14abf15SRobert Mustacchi } 283*d14abf15SRobert Mustacchi 284*d14abf15SRobert Mustacchi if (pTxQ->noTxCredits == 0) 285*d14abf15SRobert Mustacchi { 286*d14abf15SRobert Mustacchi if (idx == FCOE_CID(pLM)) 287*d14abf15SRobert Mustacchi { 288*d14abf15SRobert Mustacchi BnxeLogInfo(pUM, "FCoE tx credit ok, no upcall!"); 289*d14abf15SRobert Mustacchi } 290*d14abf15SRobert Mustacchi else 291*d14abf15SRobert Mustacchi { 292*d14abf15SRobert Mustacchi /* notify the stack that tx resources are now available */ 293*d14abf15SRobert Mustacchi #if defined(BNXE_RINGS) && (defined(__S11) || defined(__S12)) 294*d14abf15SRobert Mustacchi mac_tx_ring_update(pUM->pMac, pTxQ->ringHandle); 295*d14abf15SRobert Mustacchi #else 296*d14abf15SRobert Mustacchi mac_tx_update(pUM->pMac); 297*d14abf15SRobert Mustacchi #endif 298*d14abf15SRobert Mustacchi } 299*d14abf15SRobert Mustacchi } 300*d14abf15SRobert Mustacchi } 301*d14abf15SRobert Mustacchi 302*d14abf15SRobert Mustacchi 303*d14abf15SRobert Mustacchi static inline int BnxeTxPktMapFrag(um_device_t * pUM, 304*d14abf15SRobert Mustacchi um_txpacket_t * pTxPkt, 305*d14abf15SRobert Mustacchi mblk_t * pMblk) 306*d14abf15SRobert Mustacchi { 307*d14abf15SRobert Mustacchi ddi_dma_handle_t dmaHandle; 308*d14abf15SRobert Mustacchi ddi_dma_cookie_t cookie; 309*d14abf15SRobert Mustacchi lm_frag_t * pFrag; 310*d14abf15SRobert Mustacchi boolean_t partial; 311*d14abf15SRobert Mustacchi u32_t bindLen; 312*d14abf15SRobert Mustacchi u32_t count; 313*d14abf15SRobert Mustacchi int rc, i; 314*d14abf15SRobert Mustacchi 315*d14abf15SRobert Mustacchi if (pTxPkt->num_handles == BNXE_MAX_DMA_HANDLES_PER_PKT) 316*d14abf15SRobert Mustacchi { 317*d14abf15SRobert Mustacchi return BNXE_TX_RESOURCES_NO_OS_DMA_RES; 318*d14abf15SRobert Mustacchi } 319*d14abf15SRobert Mustacchi 320*d14abf15SRobert Mustacchi if (pTxPkt->frag_list.cnt >= BNXE_MAX_DMA_FRAGS_PER_PKT) 321*d14abf15SRobert Mustacchi { 322*d14abf15SRobert Mustacchi return BNXE_TX_RESOURCES_TOO_MANY_FRAGS; 323*d14abf15SRobert Mustacchi } 324*d14abf15SRobert Mustacchi 325*d14abf15SRobert Mustacchi dmaHandle = pTxPkt->dmaHandles[pTxPkt->num_handles]; 326*d14abf15SRobert Mustacchi 327*d14abf15SRobert Mustacchi if ((rc = ddi_dma_addr_bind_handle(dmaHandle, 328*d14abf15SRobert Mustacchi NULL, 329*d14abf15SRobert Mustacchi (caddr_t)pMblk->b_rptr, 330*d14abf15SRobert Mustacchi (pMblk->b_wptr - pMblk->b_rptr), 331*d14abf15SRobert Mustacchi (DDI_DMA_WRITE | DDI_DMA_STREAMING), 332*d14abf15SRobert Mustacchi DDI_DMA_DONTWAIT, 333*d14abf15SRobert Mustacchi NULL, 334*d14abf15SRobert Mustacchi &cookie, 335*d14abf15SRobert Mustacchi &count)) != DDI_DMA_MAPPED) 336*d14abf15SRobert Mustacchi { 337*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to bind DMA address for tx packet (%d)", rc); 338*d14abf15SRobert Mustacchi return BNXE_TX_RESOURCES_NO_OS_DMA_RES; 339*d14abf15SRobert Mustacchi } 340*d14abf15SRobert Mustacchi 341*d14abf15SRobert Mustacchi /* 342*d14abf15SRobert Mustacchi * ddi_dma_addr_bind_handle() correctly returns an error if the physical 343*d14abf15SRobert Mustacchi * fragment count exceeds the maximum fragment count specified in the 344*d14abf15SRobert Mustacchi * ddi_dma_attrib structure for the current pMblk. However, a packet can 345*d14abf15SRobert Mustacchi * span multiple mblk's. The purpose of the check below is to make sure we 346*d14abf15SRobert Mustacchi * do not overflow our fragment count limit based on what has already been 347*d14abf15SRobert Mustacchi * mapped from this packet. 348*d14abf15SRobert Mustacchi */ 349*d14abf15SRobert Mustacchi partial = ((pTxPkt->frag_list.cnt + count) > 350*d14abf15SRobert Mustacchi (pMblk->b_cont ? BNXE_MAX_DMA_FRAGS_PER_PKT - 1 351*d14abf15SRobert Mustacchi : BNXE_MAX_DMA_FRAGS_PER_PKT)); 352*d14abf15SRobert Mustacchi if (partial) 353*d14abf15SRobert Mustacchi { 354*d14abf15SRobert Mustacchi /* 355*d14abf15SRobert Mustacchi * Going to try a partial dma so (re)set count to the remaining number 356*d14abf15SRobert Mustacchi * of dma fragments that are available leaving one fragment at the end. 357*d14abf15SRobert Mustacchi */ 358*d14abf15SRobert Mustacchi count = (BNXE_MAX_DMA_FRAGS_PER_PKT - 1 - pTxPkt->frag_list.cnt); 359*d14abf15SRobert Mustacchi if (count == 0) 360*d14abf15SRobert Mustacchi { 361*d14abf15SRobert Mustacchi /* 362*d14abf15SRobert Mustacchi * No more dma fragments are available. This fragment was not 363*d14abf15SRobert Mustacchi * mapped and will be copied into the copy buffer along with the 364*d14abf15SRobert Mustacchi * rest of the packet data. 365*d14abf15SRobert Mustacchi */ 366*d14abf15SRobert Mustacchi ddi_dma_unbind_handle(dmaHandle); 367*d14abf15SRobert Mustacchi return BNXE_TX_RESOURCES_TOO_MANY_FRAGS; 368*d14abf15SRobert Mustacchi } 369*d14abf15SRobert Mustacchi } 370*d14abf15SRobert Mustacchi 371*d14abf15SRobert Mustacchi pFrag = &pTxPkt->frag_list.frag_arr[pTxPkt->frag_list.cnt]; 372*d14abf15SRobert Mustacchi pTxPkt->frag_list.cnt += count; 373*d14abf15SRobert Mustacchi 374*d14abf15SRobert Mustacchi /* map "count" dma fragments */ 375*d14abf15SRobert Mustacchi 376*d14abf15SRobert Mustacchi bindLen = 0; 377*d14abf15SRobert Mustacchi for (i = 0; i < (count - 1); i++) 378*d14abf15SRobert Mustacchi { 379*d14abf15SRobert Mustacchi pFrag->addr.as_u64 = cookie.dmac_laddress; 380*d14abf15SRobert Mustacchi bindLen += pFrag->size = cookie.dmac_size; 381*d14abf15SRobert Mustacchi 382*d14abf15SRobert Mustacchi pFrag++; 383*d14abf15SRobert Mustacchi 384*d14abf15SRobert Mustacchi ddi_dma_nextcookie(dmaHandle, &cookie); 385*d14abf15SRobert Mustacchi } 386*d14abf15SRobert Mustacchi 387*d14abf15SRobert Mustacchi pFrag->addr.as_u64 = cookie.dmac_laddress; 388*d14abf15SRobert Mustacchi bindLen += pFrag->size = cookie.dmac_size; 389*d14abf15SRobert Mustacchi 390*d14abf15SRobert Mustacchi pTxPkt->num_handles++; 391*d14abf15SRobert Mustacchi 392*d14abf15SRobert Mustacchi if (partial) 393*d14abf15SRobert Mustacchi { 394*d14abf15SRobert Mustacchi /* 395*d14abf15SRobert Mustacchi * Move the mblk's read pointer past the data that was bound to a DMA 396*d14abf15SRobert Mustacchi * fragment. Any remaining data will get copied into the copy buffer. 397*d14abf15SRobert Mustacchi */ 398*d14abf15SRobert Mustacchi pMblk->b_rptr += bindLen; 399*d14abf15SRobert Mustacchi return BNXE_TX_RESOURCES_TOO_MANY_FRAGS; 400*d14abf15SRobert Mustacchi } 401*d14abf15SRobert Mustacchi 402*d14abf15SRobert Mustacchi return 0; 403*d14abf15SRobert Mustacchi } 404*d14abf15SRobert Mustacchi 405*d14abf15SRobert Mustacchi 406*d14abf15SRobert Mustacchi static int BnxeTxPktCopy(um_device_t * pUM, 407*d14abf15SRobert Mustacchi TxQueue * pTxQ, 408*d14abf15SRobert Mustacchi um_txpacket_t * pTxPkt) 409*d14abf15SRobert Mustacchi { 410*d14abf15SRobert Mustacchi lm_frag_t * pCopyFrag = NULL; 411*d14abf15SRobert Mustacchi size_t msgSize; 412*d14abf15SRobert Mustacchi size_t copySize = 0; 413*d14abf15SRobert Mustacchi size_t pktLen = 0; 414*d14abf15SRobert Mustacchi boolean_t tryMap = B_TRUE; 415*d14abf15SRobert Mustacchi mblk_t * pMblk; 416*d14abf15SRobert Mustacchi caddr_t pTmp; 417*d14abf15SRobert Mustacchi int rc; 418*d14abf15SRobert Mustacchi 419*d14abf15SRobert Mustacchi /* Walk the chain to get the total pkt length... */ 420*d14abf15SRobert Mustacchi for (pMblk = pTxPkt->pMblk; pMblk; pMblk = pMblk->b_cont) 421*d14abf15SRobert Mustacchi { 422*d14abf15SRobert Mustacchi pktLen += MBLKL(pMblk); 423*d14abf15SRobert Mustacchi } 424*d14abf15SRobert Mustacchi 425*d14abf15SRobert Mustacchi /* 426*d14abf15SRobert Mustacchi * If the packet length is under the tx copy threshold then copy 427*d14abf15SRobert Mustacchi * the all data into the copy buffer. 428*d14abf15SRobert Mustacchi */ 429*d14abf15SRobert Mustacchi if (pktLen < pUM->devParams.txCopyThreshold) 430*d14abf15SRobert Mustacchi { 431*d14abf15SRobert Mustacchi ASSERT(pktLen <= pTxPkt->cbLength); 432*d14abf15SRobert Mustacchi 433*d14abf15SRobert Mustacchi pTmp = pTxPkt->pCbBuf; 434*d14abf15SRobert Mustacchi 435*d14abf15SRobert Mustacchi for (pMblk = pTxPkt->pMblk; pMblk; pMblk = pMblk->b_cont) 436*d14abf15SRobert Mustacchi { 437*d14abf15SRobert Mustacchi if ((msgSize = MBLKL(pMblk)) == 0) 438*d14abf15SRobert Mustacchi { 439*d14abf15SRobert Mustacchi continue; 440*d14abf15SRobert Mustacchi } 441*d14abf15SRobert Mustacchi 442*d14abf15SRobert Mustacchi bcopy(pMblk->b_rptr, pTmp, msgSize); 443*d14abf15SRobert Mustacchi pTmp += msgSize; 444*d14abf15SRobert Mustacchi } 445*d14abf15SRobert Mustacchi 446*d14abf15SRobert Mustacchi pCopyFrag = &pTxPkt->frag_list.frag_arr[0]; 447*d14abf15SRobert Mustacchi pCopyFrag->addr.as_u64 = pTxPkt->cbPhysAddr.as_u64; 448*d14abf15SRobert Mustacchi pCopyFrag->size = pktLen; 449*d14abf15SRobert Mustacchi pTxPkt->frag_list.cnt++; 450*d14abf15SRobert Mustacchi 451*d14abf15SRobert Mustacchi copySize = pktLen; 452*d14abf15SRobert Mustacchi pTxQ->txCopied++; 453*d14abf15SRobert Mustacchi 454*d14abf15SRobert Mustacchi /* Done! */ 455*d14abf15SRobert Mustacchi goto _BnxeTxPktCopy_DMA_SYNC_COPY_BUFFER; 456*d14abf15SRobert Mustacchi } 457*d14abf15SRobert Mustacchi 458*d14abf15SRobert Mustacchi /* Try to DMA map all the blocks... */ 459*d14abf15SRobert Mustacchi 460*d14abf15SRobert Mustacchi for (pMblk = pTxPkt->pMblk; pMblk; pMblk = pMblk->b_cont) 461*d14abf15SRobert Mustacchi { 462*d14abf15SRobert Mustacchi if ((msgSize = MBLKL(pMblk)) == 0) 463*d14abf15SRobert Mustacchi { 464*d14abf15SRobert Mustacchi continue; 465*d14abf15SRobert Mustacchi } 466*d14abf15SRobert Mustacchi 467*d14abf15SRobert Mustacchi if (tryMap) 468*d14abf15SRobert Mustacchi { 469*d14abf15SRobert Mustacchi if (BnxeTxPktMapFrag(pUM, pTxPkt, pMblk) == 0) 470*d14abf15SRobert Mustacchi { 471*d14abf15SRobert Mustacchi /* 472*d14abf15SRobert Mustacchi * The fragment was successfully mapped now move on to the 473*d14abf15SRobert Mustacchi * next one. Here we set pCopyFrag to NULL which represents 474*d14abf15SRobert Mustacchi * a break of continuous data in the copy buffer. If the 475*d14abf15SRobert Mustacchi * packet header was copied the first fragment points to the 476*d14abf15SRobert Mustacchi * beginning of the copy buffer. Since this block was mapped 477*d14abf15SRobert Mustacchi * any future blocks that have to be copied must be handled by 478*d14abf15SRobert Mustacchi * a new fragment even though the fragment is pointed to the 479*d14abf15SRobert Mustacchi * copied data in the copy buffer. 480*d14abf15SRobert Mustacchi */ 481*d14abf15SRobert Mustacchi pCopyFrag = NULL; 482*d14abf15SRobert Mustacchi continue; 483*d14abf15SRobert Mustacchi } 484*d14abf15SRobert Mustacchi else 485*d14abf15SRobert Mustacchi { 486*d14abf15SRobert Mustacchi /* 487*d14abf15SRobert Mustacchi * The frament was not mapped or was partially mapped. In 488*d14abf15SRobert Mustacchi * either case we will no longer try to map the remaining 489*d14abf15SRobert Mustacchi * blocks. All remaining packet data is copied. 490*d14abf15SRobert Mustacchi */ 491*d14abf15SRobert Mustacchi tryMap = B_FALSE; 492*d14abf15SRobert Mustacchi msgSize = MBLKL(pMblk); /* new msgSize with partial binding */ 493*d14abf15SRobert Mustacchi } 494*d14abf15SRobert Mustacchi } 495*d14abf15SRobert Mustacchi 496*d14abf15SRobert Mustacchi #if 0 497*d14abf15SRobert Mustacchi if ((copySize + msgSize) > pTxPkt->cbLength) 498*d14abf15SRobert Mustacchi { 499*d14abf15SRobert Mustacchi /* remaining packet is too large (length more than copy buffer) */ 500*d14abf15SRobert Mustacchi BnxeTxPktUnmap(pTxPkt); 501*d14abf15SRobert Mustacchi return -1; 502*d14abf15SRobert Mustacchi } 503*d14abf15SRobert Mustacchi #else 504*d14abf15SRobert Mustacchi ASSERT((copySize + msgSize) <= pTxPkt->cbLength); 505*d14abf15SRobert Mustacchi #endif 506*d14abf15SRobert Mustacchi 507*d14abf15SRobert Mustacchi bcopy(pMblk->b_rptr, (pTxPkt->pCbBuf + copySize), msgSize); 508*d14abf15SRobert Mustacchi 509*d14abf15SRobert Mustacchi /* 510*d14abf15SRobert Mustacchi * If pCopyFrag is already specified then simply update the copy size. 511*d14abf15SRobert Mustacchi * If not then set pCopyFrag to the next available fragment. 512*d14abf15SRobert Mustacchi */ 513*d14abf15SRobert Mustacchi if (pCopyFrag) 514*d14abf15SRobert Mustacchi { 515*d14abf15SRobert Mustacchi pCopyFrag->size += msgSize; 516*d14abf15SRobert Mustacchi } 517*d14abf15SRobert Mustacchi else 518*d14abf15SRobert Mustacchi { 519*d14abf15SRobert Mustacchi ASSERT((pTxPkt->frag_list.cnt + 1) <= BNXE_MAX_DMA_FRAGS_PER_PKT); 520*d14abf15SRobert Mustacchi pCopyFrag = &pTxPkt->frag_list.frag_arr[pTxPkt->frag_list.cnt++]; 521*d14abf15SRobert Mustacchi pCopyFrag->size = msgSize; 522*d14abf15SRobert Mustacchi pCopyFrag->addr.as_u64 = pTxPkt->cbPhysAddr.as_u64 + copySize; 523*d14abf15SRobert Mustacchi } 524*d14abf15SRobert Mustacchi 525*d14abf15SRobert Mustacchi /* update count of bytes in the copy buffer needed for DMA sync */ 526*d14abf15SRobert Mustacchi copySize += msgSize; 527*d14abf15SRobert Mustacchi } 528*d14abf15SRobert Mustacchi 529*d14abf15SRobert Mustacchi _BnxeTxPktCopy_DMA_SYNC_COPY_BUFFER: 530*d14abf15SRobert Mustacchi 531*d14abf15SRobert Mustacchi if (copySize > 0) 532*d14abf15SRobert Mustacchi { 533*d14abf15SRobert Mustacchi /* DMA sync the copy buffer before sending */ 534*d14abf15SRobert Mustacchi 535*d14abf15SRobert Mustacchi rc = ddi_dma_sync(pTxPkt->cbDmaHandle, 0, copySize, 536*d14abf15SRobert Mustacchi DDI_DMA_SYNC_FORDEV); 537*d14abf15SRobert Mustacchi 538*d14abf15SRobert Mustacchi if (pUM->fmCapabilities && 539*d14abf15SRobert Mustacchi BnxeCheckDmaHandle(pTxPkt->cbDmaHandle) != DDI_FM_OK) 540*d14abf15SRobert Mustacchi { 541*d14abf15SRobert Mustacchi ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); 542*d14abf15SRobert Mustacchi } 543*d14abf15SRobert Mustacchi 544*d14abf15SRobert Mustacchi if (rc != DDI_SUCCESS) 545*d14abf15SRobert Mustacchi { 546*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "(%d) Failed to dma sync tx copy (%p / %d)", 547*d14abf15SRobert Mustacchi rc, pTxPkt, copySize); 548*d14abf15SRobert Mustacchi } 549*d14abf15SRobert Mustacchi } 550*d14abf15SRobert Mustacchi 551*d14abf15SRobert Mustacchi if (pTxPkt->num_handles == 0) 552*d14abf15SRobert Mustacchi { 553*d14abf15SRobert Mustacchi freemsg(pTxPkt->pMblk); 554*d14abf15SRobert Mustacchi pTxPkt->pMblk = NULL; 555*d14abf15SRobert Mustacchi } 556*d14abf15SRobert Mustacchi 557*d14abf15SRobert Mustacchi return 0; 558*d14abf15SRobert Mustacchi } 559*d14abf15SRobert Mustacchi 560*d14abf15SRobert Mustacchi 561*d14abf15SRobert Mustacchi /* this code is derived from that shown in RFC 1071 Section 4.1 */ 562*d14abf15SRobert Mustacchi static inline u16_t BnxeCalcCksum(void * start, 563*d14abf15SRobert Mustacchi u32_t len, 564*d14abf15SRobert Mustacchi u16_t prev_sum) 565*d14abf15SRobert Mustacchi { 566*d14abf15SRobert Mustacchi u16_t * pword; 567*d14abf15SRobert Mustacchi u32_t sum = 0; 568*d14abf15SRobert Mustacchi 569*d14abf15SRobert Mustacchi pword = (u16_t *)start; 570*d14abf15SRobert Mustacchi 571*d14abf15SRobert Mustacchi for ( ; len > 1; len -= 2, pword++) 572*d14abf15SRobert Mustacchi { 573*d14abf15SRobert Mustacchi /* the inner loop */ 574*d14abf15SRobert Mustacchi sum += *pword; 575*d14abf15SRobert Mustacchi } 576*d14abf15SRobert Mustacchi 577*d14abf15SRobert Mustacchi /* add left-over byte, if any */ 578*d14abf15SRobert Mustacchi if (len) 579*d14abf15SRobert Mustacchi { 580*d14abf15SRobert Mustacchi sum += (u16_t)(*((u8_t *)pword)); 581*d14abf15SRobert Mustacchi } 582*d14abf15SRobert Mustacchi 583*d14abf15SRobert Mustacchi sum += prev_sum; 584*d14abf15SRobert Mustacchi 585*d14abf15SRobert Mustacchi /* fold 32-bit sum to 16 bits */ 586*d14abf15SRobert Mustacchi while (sum >> 16) 587*d14abf15SRobert Mustacchi { 588*d14abf15SRobert Mustacchi sum = ((sum & 0xffff) + (sum >> 16)); 589*d14abf15SRobert Mustacchi } 590*d14abf15SRobert Mustacchi 591*d14abf15SRobert Mustacchi return (u16_t)sum; 592*d14abf15SRobert Mustacchi } 593*d14abf15SRobert Mustacchi 594*d14abf15SRobert Mustacchi 595*d14abf15SRobert Mustacchi /* 596*d14abf15SRobert Mustacchi * Everest1 (i.e. 57710, 57711, 57711E) does not natively support UDP checksums 597*d14abf15SRobert Mustacchi * and does not know anything about the UDP header and where the checksum field 598*d14abf15SRobert Mustacchi * is located. It only knows about TCP. Therefore we "lie" to the hardware for 599*d14abf15SRobert Mustacchi * outgoing UDP packets w/ checksum offload. Since the checksum field offset 600*d14abf15SRobert Mustacchi * for TCP is 16 bytes and for UDP it is 6 bytes we pass a pointer to the 601*d14abf15SRobert Mustacchi * hardware that is 10 bytes less than the start of the UDP header. This allows 602*d14abf15SRobert Mustacchi * the hardware to write the checksum in the correct spot. But the hardware 603*d14abf15SRobert Mustacchi * will compute a checksum which includes the last 10 bytes of the IP header. 604*d14abf15SRobert Mustacchi * To correct this we tweak the stack computed pseudo checksum by folding in the 605*d14abf15SRobert Mustacchi * calculation of the inverse checksum for those final 10 bytes of the IP 606*d14abf15SRobert Mustacchi * header. This allows the correct checksum to be computed by the hardware. 607*d14abf15SRobert Mustacchi */ 608*d14abf15SRobert Mustacchi 609*d14abf15SRobert Mustacchi #define TCP_CS_OFFSET 16 610*d14abf15SRobert Mustacchi #define UDP_CS_OFFSET 6 611*d14abf15SRobert Mustacchi #define UDP_TCP_CS_OFFSET_DIFF (TCP_CS_OFFSET - UDP_CS_OFFSET) 612*d14abf15SRobert Mustacchi 613*d14abf15SRobert Mustacchi static inline u16_t BnxeUdpPseudoCsum(um_device_t * pUM, 614*d14abf15SRobert Mustacchi u8_t * pUdpHdr, 615*d14abf15SRobert Mustacchi u8_t * pIpHdr, 616*d14abf15SRobert Mustacchi u8_t ipHdrLen) 617*d14abf15SRobert Mustacchi { 618*d14abf15SRobert Mustacchi u32_t sum32; 619*d14abf15SRobert Mustacchi u16_t sum16; 620*d14abf15SRobert Mustacchi u16_t pseudo_cs; 621*d14abf15SRobert Mustacchi 622*d14abf15SRobert Mustacchi ASSERT(ipHdrLen >= UDP_TCP_CS_OFFSET_DIFF); 623*d14abf15SRobert Mustacchi 624*d14abf15SRobert Mustacchi /* calc cksum on last UDP_TCP_CS_OFFSET_DIFF bytes of ip header */ 625*d14abf15SRobert Mustacchi sum16 = BnxeCalcCksum(&pIpHdr[ipHdrLen - UDP_TCP_CS_OFFSET_DIFF], 626*d14abf15SRobert Mustacchi UDP_TCP_CS_OFFSET_DIFF, 0); 627*d14abf15SRobert Mustacchi 628*d14abf15SRobert Mustacchi /* substruct the calculated cksum from the udp pseudo cksum */ 629*d14abf15SRobert Mustacchi pseudo_cs = (*((u16_t *)&pUdpHdr[6])); 630*d14abf15SRobert Mustacchi sum16 = ~sum16; 631*d14abf15SRobert Mustacchi sum32 = (pseudo_cs + sum16); 632*d14abf15SRobert Mustacchi 633*d14abf15SRobert Mustacchi /* fold 32-bit sum to 16 bits */ 634*d14abf15SRobert Mustacchi while (sum32 >> 16) 635*d14abf15SRobert Mustacchi { 636*d14abf15SRobert Mustacchi sum32 = ((sum32 & 0xffff) + (sum32 >> 16)); 637*d14abf15SRobert Mustacchi } 638*d14abf15SRobert Mustacchi 639*d14abf15SRobert Mustacchi return ntohs((u16_t)sum32); 640*d14abf15SRobert Mustacchi } 641*d14abf15SRobert Mustacchi 642*d14abf15SRobert Mustacchi 643*d14abf15SRobert Mustacchi static inline u16_t BnxeGetVlanTag(mblk_t * pMblk) 644*d14abf15SRobert Mustacchi { 645*d14abf15SRobert Mustacchi ASSERT(MBLKL(pMblk) >= sizeof(struct ether_vlan_header)); 646*d14abf15SRobert Mustacchi return GLD_VTAG_VID(ntohs(((struct ether_vlan_header *)pMblk->b_rptr)->ether_tci)); 647*d14abf15SRobert Mustacchi } 648*d14abf15SRobert Mustacchi 649*d14abf15SRobert Mustacchi 650*d14abf15SRobert Mustacchi static inline int BnxeGetHdrInfo(um_device_t * pUM, 651*d14abf15SRobert Mustacchi um_txpacket_t * pTxPkt) 652*d14abf15SRobert Mustacchi { 653*d14abf15SRobert Mustacchi mblk_t * pMblk; 654*d14abf15SRobert Mustacchi size_t msgSize; 655*d14abf15SRobert Mustacchi uint32_t csStart; 656*d14abf15SRobert Mustacchi uint32_t csStuff; 657*d14abf15SRobert Mustacchi uint32_t csFlags; 658*d14abf15SRobert Mustacchi uint32_t lso; 659*d14abf15SRobert Mustacchi u8_t * pL2Hdr; 660*d14abf15SRobert Mustacchi uint32_t l2HdrLen; 661*d14abf15SRobert Mustacchi u8_t * pL3Hdr; 662*d14abf15SRobert Mustacchi u32_t l3HdrLen; 663*d14abf15SRobert Mustacchi u8_t * pL4Hdr; 664*d14abf15SRobert Mustacchi u32_t l4HdrLen; 665*d14abf15SRobert Mustacchi 666*d14abf15SRobert Mustacchi pMblk = pTxPkt->pMblk; 667*d14abf15SRobert Mustacchi msgSize = MBLKL(pMblk); 668*d14abf15SRobert Mustacchi 669*d14abf15SRobert Mustacchi /* At least the MAC header... */ 670*d14abf15SRobert Mustacchi #if 0 671*d14abf15SRobert Mustacchi if (msgSize < sizeof(struct ether_header)) 672*d14abf15SRobert Mustacchi { 673*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Invalid initial segment size in packet!"); 674*d14abf15SRobert Mustacchi return -1; 675*d14abf15SRobert Mustacchi } 676*d14abf15SRobert Mustacchi #else 677*d14abf15SRobert Mustacchi ASSERT(msgSize >= sizeof(struct ether_header)); 678*d14abf15SRobert Mustacchi #endif 679*d14abf15SRobert Mustacchi 680*d14abf15SRobert Mustacchi mac_hcksum_get(pMblk, &csStart, &csStuff, NULL, NULL, &csFlags); 681*d14abf15SRobert Mustacchi 682*d14abf15SRobert Mustacchi lso = DB_LSOFLAGS(pMblk) & HW_LSO; 683*d14abf15SRobert Mustacchi 684*d14abf15SRobert Mustacchi /* get the Ethernet header */ 685*d14abf15SRobert Mustacchi pL2Hdr = (u8_t *)pMblk->b_rptr; 686*d14abf15SRobert Mustacchi 687*d14abf15SRobert Mustacchi /* grab the destination mac addr */ 688*d14abf15SRobert Mustacchi memcpy(pTxPkt->tx_info.dst_mac_addr, pL2Hdr, 6); 689*d14abf15SRobert Mustacchi 690*d14abf15SRobert Mustacchi if (lso) 691*d14abf15SRobert Mustacchi { 692*d14abf15SRobert Mustacchi pTxPkt->tx_info.flags |= LM_TX_FLAG_TCP_LSO_FRAME; 693*d14abf15SRobert Mustacchi 694*d14abf15SRobert Mustacchi pTxPkt->tx_info.lso_mss = (u16_t)DB_LSOMSS(pMblk); 695*d14abf15SRobert Mustacchi } 696*d14abf15SRobert Mustacchi else if (!csFlags) 697*d14abf15SRobert Mustacchi { 698*d14abf15SRobert Mustacchi /* no offload requested, just check for VLAN */ 699*d14abf15SRobert Mustacchi 700*d14abf15SRobert Mustacchi if (((struct ether_header *)pMblk->b_rptr)->ether_type == 701*d14abf15SRobert Mustacchi htons(ETHERTYPE_VLAN)) 702*d14abf15SRobert Mustacchi { 703*d14abf15SRobert Mustacchi pTxPkt->tx_info.vlan_tag = BnxeGetVlanTag(pMblk); 704*d14abf15SRobert Mustacchi pTxPkt->tx_info.flags |= LM_TX_FLAG_VLAN_TAG_EXISTS; 705*d14abf15SRobert Mustacchi } 706*d14abf15SRobert Mustacchi 707*d14abf15SRobert Mustacchi return 0; 708*d14abf15SRobert Mustacchi } 709*d14abf15SRobert Mustacchi 710*d14abf15SRobert Mustacchi if (((struct ether_header *)pL2Hdr)->ether_type == htons(ETHERTYPE_VLAN)) 711*d14abf15SRobert Mustacchi { 712*d14abf15SRobert Mustacchi l2HdrLen = sizeof(struct ether_vlan_header); 713*d14abf15SRobert Mustacchi 714*d14abf15SRobert Mustacchi pTxPkt->tx_info.vlan_tag = BnxeGetVlanTag(pMblk); 715*d14abf15SRobert Mustacchi pTxPkt->tx_info.flags |= LM_TX_FLAG_VLAN_TAG_EXISTS; 716*d14abf15SRobert Mustacchi } 717*d14abf15SRobert Mustacchi else 718*d14abf15SRobert Mustacchi { 719*d14abf15SRobert Mustacchi l2HdrLen = sizeof(struct ether_header); 720*d14abf15SRobert Mustacchi } 721*d14abf15SRobert Mustacchi 722*d14abf15SRobert Mustacchi if (csFlags & HCK_IPV4_HDRCKSUM) 723*d14abf15SRobert Mustacchi { 724*d14abf15SRobert Mustacchi pTxPkt->tx_info.flags |= LM_TX_FLAG_COMPUTE_IP_CKSUM; 725*d14abf15SRobert Mustacchi } 726*d14abf15SRobert Mustacchi 727*d14abf15SRobert Mustacchi if (csFlags & HCK_PARTIALCKSUM) 728*d14abf15SRobert Mustacchi { 729*d14abf15SRobert Mustacchi pTxPkt->tx_info.flags |= LM_TX_FLAG_COMPUTE_TCP_UDP_CKSUM; 730*d14abf15SRobert Mustacchi 731*d14abf15SRobert Mustacchi l3HdrLen = csStart; 732*d14abf15SRobert Mustacchi l4HdrLen = (l2HdrLen + csStuff + sizeof(u16_t)); 733*d14abf15SRobert Mustacchi 734*d14abf15SRobert Mustacchi /* 735*d14abf15SRobert Mustacchi * For TCP, here we ignore the urgent pointer and size of the 736*d14abf15SRobert Mustacchi * options. We'll get that info later. 737*d14abf15SRobert Mustacchi */ 738*d14abf15SRobert Mustacchi } 739*d14abf15SRobert Mustacchi else if (lso) 740*d14abf15SRobert Mustacchi { 741*d14abf15SRobert Mustacchi /* Solaris doesn't do LSO if there is option in the IP header. */ 742*d14abf15SRobert Mustacchi l3HdrLen = sizeof(struct ip); 743*d14abf15SRobert Mustacchi l4HdrLen = (l2HdrLen + l3HdrLen + sizeof(struct tcphdr)); 744*d14abf15SRobert Mustacchi } 745*d14abf15SRobert Mustacchi else 746*d14abf15SRobert Mustacchi { 747*d14abf15SRobert Mustacchi return 0; 748*d14abf15SRobert Mustacchi } 749*d14abf15SRobert Mustacchi 750*d14abf15SRobert Mustacchi if (msgSize >= l4HdrLen) 751*d14abf15SRobert Mustacchi { 752*d14abf15SRobert Mustacchi /* the header is in the first block */ 753*d14abf15SRobert Mustacchi pL3Hdr = (pL2Hdr + l2HdrLen); 754*d14abf15SRobert Mustacchi } 755*d14abf15SRobert Mustacchi else 756*d14abf15SRobert Mustacchi { 757*d14abf15SRobert Mustacchi if ((msgSize <= l2HdrLen) && pMblk->b_cont && 758*d14abf15SRobert Mustacchi ((msgSize + MBLKL(pMblk->b_cont)) >= l4HdrLen)) 759*d14abf15SRobert Mustacchi { 760*d14abf15SRobert Mustacchi /* the header is in the second block */ 761*d14abf15SRobert Mustacchi pL3Hdr = pMblk->b_cont->b_rptr + (l2HdrLen - msgSize); 762*d14abf15SRobert Mustacchi } 763*d14abf15SRobert Mustacchi else 764*d14abf15SRobert Mustacchi { 765*d14abf15SRobert Mustacchi /* do a pullup to make sure headers are in the first block */ 766*d14abf15SRobert Mustacchi pUM->txMsgPullUp++; 767*d14abf15SRobert Mustacchi 768*d14abf15SRobert Mustacchi if ((pMblk = msgpullup(pMblk, l4HdrLen)) == NULL) 769*d14abf15SRobert Mustacchi { 770*d14abf15SRobert Mustacchi return -1; 771*d14abf15SRobert Mustacchi } 772*d14abf15SRobert Mustacchi 773*d14abf15SRobert Mustacchi freemsg(pTxPkt->pMblk); 774*d14abf15SRobert Mustacchi pTxPkt->pMblk = pMblk; 775*d14abf15SRobert Mustacchi 776*d14abf15SRobert Mustacchi pL3Hdr = (pMblk->b_rptr + l2HdrLen); 777*d14abf15SRobert Mustacchi } 778*d14abf15SRobert Mustacchi } 779*d14abf15SRobert Mustacchi 780*d14abf15SRobert Mustacchi /* must be IPv4 or IPv6 */ 781*d14abf15SRobert Mustacchi ASSERT((pL3Hdr[0] & 0xf0) == 0x60 || (pL3Hdr[0] & 0xf0) == 0x40); 782*d14abf15SRobert Mustacchi 783*d14abf15SRobert Mustacchi if ((pL3Hdr[0] & 0xf0) == 0x60) 784*d14abf15SRobert Mustacchi { 785*d14abf15SRobert Mustacchi pTxPkt->tx_info.flags |= LM_TX_FLAG_IPV6_PACKET; 786*d14abf15SRobert Mustacchi } 787*d14abf15SRobert Mustacchi 788*d14abf15SRobert Mustacchi if (lso || ((csStuff - csStart) == TCP_CS_OFFSET)) 789*d14abf15SRobert Mustacchi { 790*d14abf15SRobert Mustacchi /* get the TCP header */ 791*d14abf15SRobert Mustacchi pL4Hdr = (pL3Hdr + l3HdrLen); 792*d14abf15SRobert Mustacchi l4HdrLen = ((pL4Hdr[12] & 0xf0) >> 2); 793*d14abf15SRobert Mustacchi 794*d14abf15SRobert Mustacchi pTxPkt->tx_info.cs_any_offset = 0; 795*d14abf15SRobert Mustacchi pTxPkt->tx_info.tcp_nonce_sum_bit = (pL4Hdr[12] & 0x1); 796*d14abf15SRobert Mustacchi pTxPkt->tx_info.tcp_pseudo_csum = ntohs(*((u16_t *)&pL4Hdr[TCP_CS_OFFSET])); 797*d14abf15SRobert Mustacchi 798*d14abf15SRobert Mustacchi if (lso) 799*d14abf15SRobert Mustacchi { 800*d14abf15SRobert Mustacchi pTxPkt->tx_info.lso_ipid = ntohs(*((u16_t *)&pL3Hdr[4])); 801*d14abf15SRobert Mustacchi pTxPkt->tx_info.lso_tcp_send_seq = ntohl(*((u32_t *)&pL4Hdr[4])); 802*d14abf15SRobert Mustacchi pTxPkt->tx_info.lso_tcp_flags = pL4Hdr[13]; 803*d14abf15SRobert Mustacchi } 804*d14abf15SRobert Mustacchi } 805*d14abf15SRobert Mustacchi else 806*d14abf15SRobert Mustacchi { 807*d14abf15SRobert Mustacchi ASSERT((csStuff - csStart) == UDP_CS_OFFSET); 808*d14abf15SRobert Mustacchi 809*d14abf15SRobert Mustacchi /* get the UDP header */ 810*d14abf15SRobert Mustacchi pL4Hdr = pL3Hdr + l3HdrLen; 811*d14abf15SRobert Mustacchi 812*d14abf15SRobert Mustacchi l4HdrLen = sizeof(struct udphdr); 813*d14abf15SRobert Mustacchi 814*d14abf15SRobert Mustacchi pTxPkt->tx_info.cs_any_offset = UDP_TCP_CS_OFFSET_DIFF; 815*d14abf15SRobert Mustacchi pTxPkt->tx_info.tcp_nonce_sum_bit = 0; 816*d14abf15SRobert Mustacchi pTxPkt->tx_info.tcp_pseudo_csum = 817*d14abf15SRobert Mustacchi CHIP_IS_E1x(((lm_device_t *)pUM)) ? 818*d14abf15SRobert Mustacchi BnxeUdpPseudoCsum(pUM, pL4Hdr, pL3Hdr, l3HdrLen) : 819*d14abf15SRobert Mustacchi ntohs(*((u16_t *)&pL4Hdr[UDP_CS_OFFSET])); 820*d14abf15SRobert Mustacchi } 821*d14abf15SRobert Mustacchi 822*d14abf15SRobert Mustacchi pTxPkt->tx_info.lso_ip_hdr_len = l3HdrLen; 823*d14abf15SRobert Mustacchi pTxPkt->tx_info.lso_tcp_hdr_len = l4HdrLen; 824*d14abf15SRobert Mustacchi 825*d14abf15SRobert Mustacchi return 0; 826*d14abf15SRobert Mustacchi } 827*d14abf15SRobert Mustacchi 828*d14abf15SRobert Mustacchi 829*d14abf15SRobert Mustacchi int BnxeTxSendMblk(um_device_t * pUM, 830*d14abf15SRobert Mustacchi int idx, 831*d14abf15SRobert Mustacchi mblk_t * pMblk, 832*d14abf15SRobert Mustacchi u32_t flags, 833*d14abf15SRobert Mustacchi u16_t vlan_tag) 834*d14abf15SRobert Mustacchi { 835*d14abf15SRobert Mustacchi lm_device_t * pLM = &pUM->lm_dev; 836*d14abf15SRobert Mustacchi TxQueue * pTxQ = &pUM->txq[idx]; 837*d14abf15SRobert Mustacchi lm_tx_chain_t * pLmTxChain; 838*d14abf15SRobert Mustacchi um_txpacket_t * pTxPkt; 839*d14abf15SRobert Mustacchi s_list_t tmpList; 840*d14abf15SRobert Mustacchi u32_t numPkts; 841*d14abf15SRobert Mustacchi int rc; 842*d14abf15SRobert Mustacchi 843*d14abf15SRobert Mustacchi BNXE_LOCK_ENTER_FREETX(pUM, idx); 844*d14abf15SRobert Mustacchi 845*d14abf15SRobert Mustacchi pTxPkt = (um_txpacket_t *)s_list_pop_head(&pTxQ->freeTxDescQ); 846*d14abf15SRobert Mustacchi 847*d14abf15SRobert Mustacchi if (pTxQ->txLowWater > s_list_entry_cnt(&pTxQ->freeTxDescQ)) 848*d14abf15SRobert Mustacchi { 849*d14abf15SRobert Mustacchi pTxQ->txLowWater = s_list_entry_cnt(&pTxQ->freeTxDescQ); 850*d14abf15SRobert Mustacchi } 851*d14abf15SRobert Mustacchi 852*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_FREETX(pUM, idx); 853*d14abf15SRobert Mustacchi 854*d14abf15SRobert Mustacchi /* try to recycle if no more packet available */ 855*d14abf15SRobert Mustacchi if (pTxPkt == NULL) 856*d14abf15SRobert Mustacchi { 857*d14abf15SRobert Mustacchi pTxQ->txRecycle++; 858*d14abf15SRobert Mustacchi 859*d14abf15SRobert Mustacchi s_list_clear(&tmpList); 860*d14abf15SRobert Mustacchi 861*d14abf15SRobert Mustacchi BNXE_LOCK_ENTER_TX(pUM, idx); 862*d14abf15SRobert Mustacchi numPkts = lm_get_packets_sent(pLM, idx, &tmpList); 863*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_TX(pUM, idx); 864*d14abf15SRobert Mustacchi 865*d14abf15SRobert Mustacchi if (pUM->fmCapabilities && 866*d14abf15SRobert Mustacchi BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK) 867*d14abf15SRobert Mustacchi { 868*d14abf15SRobert Mustacchi ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); 869*d14abf15SRobert Mustacchi } 870*d14abf15SRobert Mustacchi 871*d14abf15SRobert Mustacchi if (!numPkts) 872*d14abf15SRobert Mustacchi { 873*d14abf15SRobert Mustacchi atomic_or_32(&pTxQ->noTxCredits, BNXE_TX_RESOURCES_NO_DESC); 874*d14abf15SRobert Mustacchi pTxQ->txBlocked++; 875*d14abf15SRobert Mustacchi return BNXE_TX_HDWRFULL; 876*d14abf15SRobert Mustacchi } 877*d14abf15SRobert Mustacchi 878*d14abf15SRobert Mustacchi /* steal the first packet from the list before reclaiming */ 879*d14abf15SRobert Mustacchi 880*d14abf15SRobert Mustacchi pTxPkt = (um_txpacket_t *)s_list_pop_head(&tmpList); 881*d14abf15SRobert Mustacchi 882*d14abf15SRobert Mustacchi if (pTxPkt->num_handles) 883*d14abf15SRobert Mustacchi { 884*d14abf15SRobert Mustacchi BnxeTxPktUnmap(pTxPkt); 885*d14abf15SRobert Mustacchi } 886*d14abf15SRobert Mustacchi 887*d14abf15SRobert Mustacchi if (pTxPkt->pMblk) 888*d14abf15SRobert Mustacchi { 889*d14abf15SRobert Mustacchi freemsg(pTxPkt->pMblk); 890*d14abf15SRobert Mustacchi pTxPkt->pMblk = NULL; 891*d14abf15SRobert Mustacchi } 892*d14abf15SRobert Mustacchi 893*d14abf15SRobert Mustacchi BnxeTxPktsReclaim(pUM, idx, &tmpList); 894*d14abf15SRobert Mustacchi } 895*d14abf15SRobert Mustacchi 896*d14abf15SRobert Mustacchi pTxPkt->lm_pkt.link.next = NULL; 897*d14abf15SRobert Mustacchi 898*d14abf15SRobert Mustacchi pTxPkt->tx_info.flags = 0; 899*d14abf15SRobert Mustacchi pTxPkt->tx_info.vlan_tag = 0; 900*d14abf15SRobert Mustacchi pTxPkt->frag_list.cnt = 0; 901*d14abf15SRobert Mustacchi pTxPkt->pMblk = pMblk; 902*d14abf15SRobert Mustacchi 903*d14abf15SRobert Mustacchi #if 0 904*d14abf15SRobert Mustacchi BnxeDumpPkt(pUM, 905*d14abf15SRobert Mustacchi (BNXE_FCOE(pUM) && (idx == FCOE_CID(&pUM->lm_dev))) ? 906*d14abf15SRobert Mustacchi "-> FCoE L2 TX ->" : "-> L2 TX ->", 907*d14abf15SRobert Mustacchi pMblk, B_TRUE); 908*d14abf15SRobert Mustacchi #endif 909*d14abf15SRobert Mustacchi 910*d14abf15SRobert Mustacchi if (idx == FCOE_CID(pLM)) 911*d14abf15SRobert Mustacchi { 912*d14abf15SRobert Mustacchi if (flags & PRV_TX_VLAN_TAG) 913*d14abf15SRobert Mustacchi { 914*d14abf15SRobert Mustacchi pTxPkt->tx_info.vlan_tag = vlan_tag; 915*d14abf15SRobert Mustacchi pTxPkt->tx_info.flags |= LM_TX_FLAG_INSERT_VLAN_TAG; 916*d14abf15SRobert Mustacchi } 917*d14abf15SRobert Mustacchi } 918*d14abf15SRobert Mustacchi else if (BnxeGetHdrInfo(pUM, pTxPkt)) 919*d14abf15SRobert Mustacchi { 920*d14abf15SRobert Mustacchi goto BnxeTxSendMblk_fail; 921*d14abf15SRobert Mustacchi } 922*d14abf15SRobert Mustacchi 923*d14abf15SRobert Mustacchi if (BnxeTxPktCopy(pUM, pTxQ, pTxPkt)) 924*d14abf15SRobert Mustacchi { 925*d14abf15SRobert Mustacchi goto BnxeTxSendMblk_fail; 926*d14abf15SRobert Mustacchi } 927*d14abf15SRobert Mustacchi 928*d14abf15SRobert Mustacchi /* Now try to send the packet... */ 929*d14abf15SRobert Mustacchi 930*d14abf15SRobert Mustacchi pLmTxChain = &pLM->tx_info.chain[idx]; 931*d14abf15SRobert Mustacchi 932*d14abf15SRobert Mustacchi BNXE_LOCK_ENTER_TX(pUM, idx); 933*d14abf15SRobert Mustacchi 934*d14abf15SRobert Mustacchi /* Try to reclaim sent packets if available BDs is lower than threshold */ 935*d14abf15SRobert Mustacchi if (pLmTxChain->bd_chain.bd_left < BNXE_MAX_DMA_FRAGS_PER_PKT + 2) 936*d14abf15SRobert Mustacchi { 937*d14abf15SRobert Mustacchi pTxQ->txRecycle++; 938*d14abf15SRobert Mustacchi 939*d14abf15SRobert Mustacchi s_list_clear(&tmpList); 940*d14abf15SRobert Mustacchi 941*d14abf15SRobert Mustacchi numPkts = lm_get_packets_sent(pLM, idx, &tmpList); 942*d14abf15SRobert Mustacchi 943*d14abf15SRobert Mustacchi if (pUM->fmCapabilities && 944*d14abf15SRobert Mustacchi BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK) 945*d14abf15SRobert Mustacchi { 946*d14abf15SRobert Mustacchi ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); 947*d14abf15SRobert Mustacchi } 948*d14abf15SRobert Mustacchi 949*d14abf15SRobert Mustacchi if (numPkts) 950*d14abf15SRobert Mustacchi { 951*d14abf15SRobert Mustacchi BnxeTxPktsReclaim(pUM, idx, &tmpList); 952*d14abf15SRobert Mustacchi } 953*d14abf15SRobert Mustacchi } 954*d14abf15SRobert Mustacchi 955*d14abf15SRobert Mustacchi /* 956*d14abf15SRobert Mustacchi * If there are no packets currently waiting to be sent and there are enough 957*d14abf15SRobert Mustacchi * BDs available to satisfy this packet then send it now. 958*d14abf15SRobert Mustacchi */ 959*d14abf15SRobert Mustacchi if (s_list_is_empty(&pTxQ->waitTxDescQ) && 960*d14abf15SRobert Mustacchi (pLmTxChain->bd_chain.bd_left >= pTxPkt->frag_list.cnt + 2)) 961*d14abf15SRobert Mustacchi { 962*d14abf15SRobert Mustacchi rc = lm_send_packet(pLM, idx, &pTxPkt->lm_pkt, &pTxPkt->frag_list); 963*d14abf15SRobert Mustacchi 964*d14abf15SRobert Mustacchi if (pUM->fmCapabilities && 965*d14abf15SRobert Mustacchi BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK) 966*d14abf15SRobert Mustacchi { 967*d14abf15SRobert Mustacchi ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); 968*d14abf15SRobert Mustacchi } 969*d14abf15SRobert Mustacchi 970*d14abf15SRobert Mustacchi if (pUM->fmCapabilities && 971*d14abf15SRobert Mustacchi BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_1]) != DDI_FM_OK) 972*d14abf15SRobert Mustacchi { 973*d14abf15SRobert Mustacchi ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); 974*d14abf15SRobert Mustacchi } 975*d14abf15SRobert Mustacchi 976*d14abf15SRobert Mustacchi if (rc == LM_STATUS_SUCCESS) 977*d14abf15SRobert Mustacchi { 978*d14abf15SRobert Mustacchi /* send completely successfully */ 979*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_TX(pUM, idx); 980*d14abf15SRobert Mustacchi return BNXE_TX_GOODXMIT; 981*d14abf15SRobert Mustacchi } 982*d14abf15SRobert Mustacchi 983*d14abf15SRobert Mustacchi /* 984*d14abf15SRobert Mustacchi * Send failed (probably not enough BDs available)... 985*d14abf15SRobert Mustacchi * Continue on with putting this packet on the wait queue. 986*d14abf15SRobert Mustacchi */ 987*d14abf15SRobert Mustacchi pTxQ->txFailed++; 988*d14abf15SRobert Mustacchi } 989*d14abf15SRobert Mustacchi 990*d14abf15SRobert Mustacchi #if 0 991*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "WAIT TX DESCQ %lu %d %d", 992*d14abf15SRobert Mustacchi s_list_entry_cnt(&pTxQ->waitTxDescQ), 993*d14abf15SRobert Mustacchi pLmTxChain->bd_chain.bd_left, pTxPkt->frag_list.cnt); 994*d14abf15SRobert Mustacchi #endif 995*d14abf15SRobert Mustacchi 996*d14abf15SRobert Mustacchi /* 997*d14abf15SRobert Mustacchi * If we got here then there are other packets waiting to be sent or there 998*d14abf15SRobert Mustacchi * aren't enough BDs available. In either case put this packet at the end 999*d14abf15SRobert Mustacchi * of the waiting queue. 1000*d14abf15SRobert Mustacchi */ 1001*d14abf15SRobert Mustacchi s_list_push_tail(&pTxQ->waitTxDescQ, &pTxPkt->lm_pkt.link); 1002*d14abf15SRobert Mustacchi 1003*d14abf15SRobert Mustacchi pTxQ->txWait++; 1004*d14abf15SRobert Mustacchi 1005*d14abf15SRobert Mustacchi /* 1006*d14abf15SRobert Mustacchi * If there appears to be a sufficient number of BDs available then make a 1007*d14abf15SRobert Mustacchi * quick attempt to send as many waiting packets as possible. 1008*d14abf15SRobert Mustacchi */ 1009*d14abf15SRobert Mustacchi if ((pLmTxChain->bd_chain.bd_left >= BNXE_MAX_DMA_FRAGS_PER_PKT) && 1010*d14abf15SRobert Mustacchi (BnxeTxSendWaitingPkt(pUM, idx) == BNXE_TX_GOODXMIT)) 1011*d14abf15SRobert Mustacchi { 1012*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_TX(pUM, idx); 1013*d14abf15SRobert Mustacchi return BNXE_TX_GOODXMIT; 1014*d14abf15SRobert Mustacchi } 1015*d14abf15SRobert Mustacchi 1016*d14abf15SRobert Mustacchi /* Couldn't send anything! */ 1017*d14abf15SRobert Mustacchi atomic_or_32(&pTxQ->noTxCredits, BNXE_TX_RESOURCES_NO_CREDIT); 1018*d14abf15SRobert Mustacchi pTxQ->txBlocked++; 1019*d14abf15SRobert Mustacchi 1020*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_TX(pUM, idx); 1021*d14abf15SRobert Mustacchi 1022*d14abf15SRobert Mustacchi return BNXE_TX_DEFERPKT; 1023*d14abf15SRobert Mustacchi 1024*d14abf15SRobert Mustacchi BnxeTxSendMblk_fail: 1025*d14abf15SRobert Mustacchi 1026*d14abf15SRobert Mustacchi pTxQ->txDiscards++; 1027*d14abf15SRobert Mustacchi 1028*d14abf15SRobert Mustacchi ASSERT(pTxPkt != NULL); 1029*d14abf15SRobert Mustacchi 1030*d14abf15SRobert Mustacchi if (pTxPkt->pMblk) 1031*d14abf15SRobert Mustacchi { 1032*d14abf15SRobert Mustacchi freemsg(pTxPkt->pMblk); 1033*d14abf15SRobert Mustacchi pTxPkt->pMblk = NULL; 1034*d14abf15SRobert Mustacchi } 1035*d14abf15SRobert Mustacchi 1036*d14abf15SRobert Mustacchi BNXE_LOCK_ENTER_FREETX(pUM, idx); 1037*d14abf15SRobert Mustacchi s_list_push_tail(&pTxQ->freeTxDescQ, &pTxPkt->lm_pkt.link); 1038*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_FREETX(pUM, idx); 1039*d14abf15SRobert Mustacchi 1040*d14abf15SRobert Mustacchi /* 1041*d14abf15SRobert Mustacchi * Yes GOODXMIT since mblk was free'd here and this triggers caller to 1042*d14abf15SRobert Mustacchi * try and send the next packet in its chain. 1043*d14abf15SRobert Mustacchi */ 1044*d14abf15SRobert Mustacchi return BNXE_TX_GOODXMIT; 1045*d14abf15SRobert Mustacchi } 1046*d14abf15SRobert Mustacchi 1047*d14abf15SRobert Mustacchi 1048*d14abf15SRobert Mustacchi static void BnxeTxPktsAbortIdx(um_device_t * pUM, 1049*d14abf15SRobert Mustacchi int idx) 1050*d14abf15SRobert Mustacchi { 1051*d14abf15SRobert Mustacchi s_list_t tmpList; 1052*d14abf15SRobert Mustacchi 1053*d14abf15SRobert Mustacchi BNXE_LOCK_ENTER_TX(pUM, idx); 1054*d14abf15SRobert Mustacchi lm_abort(&pUM->lm_dev, ABORT_OP_INDICATE_TX_CHAIN, idx); 1055*d14abf15SRobert Mustacchi tmpList = pUM->txq[idx].waitTxDescQ; 1056*d14abf15SRobert Mustacchi s_list_clear(&pUM->txq[idx].waitTxDescQ); 1057*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_TX(pUM, idx); 1058*d14abf15SRobert Mustacchi 1059*d14abf15SRobert Mustacchi BnxeTxPktsReclaim(pUM, idx, &tmpList); 1060*d14abf15SRobert Mustacchi } 1061*d14abf15SRobert Mustacchi 1062*d14abf15SRobert Mustacchi 1063*d14abf15SRobert Mustacchi void BnxeTxPktsAbort(um_device_t * pUM, 1064*d14abf15SRobert Mustacchi int cliIdx) 1065*d14abf15SRobert Mustacchi { 1066*d14abf15SRobert Mustacchi int idx; 1067*d14abf15SRobert Mustacchi 1068*d14abf15SRobert Mustacchi switch (cliIdx) 1069*d14abf15SRobert Mustacchi { 1070*d14abf15SRobert Mustacchi case LM_CLI_IDX_FCOE: 1071*d14abf15SRobert Mustacchi 1072*d14abf15SRobert Mustacchi BnxeTxPktsAbortIdx(pUM, FCOE_CID(&pUM->lm_dev)); 1073*d14abf15SRobert Mustacchi break; 1074*d14abf15SRobert Mustacchi 1075*d14abf15SRobert Mustacchi case LM_CLI_IDX_NDIS: 1076*d14abf15SRobert Mustacchi 1077*d14abf15SRobert Mustacchi LM_FOREACH_TSS_IDX(&pUM->lm_dev, idx) 1078*d14abf15SRobert Mustacchi { 1079*d14abf15SRobert Mustacchi BnxeTxPktsAbortIdx(pUM, idx); 1080*d14abf15SRobert Mustacchi } 1081*d14abf15SRobert Mustacchi 1082*d14abf15SRobert Mustacchi break; 1083*d14abf15SRobert Mustacchi 1084*d14abf15SRobert Mustacchi default: 1085*d14abf15SRobert Mustacchi 1086*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "ERROR: Invalid cliIdx for BnxeTxPktsAbort (%d)", cliIdx); 1087*d14abf15SRobert Mustacchi break; 1088*d14abf15SRobert Mustacchi } 1089*d14abf15SRobert Mustacchi } 1090*d14abf15SRobert Mustacchi 1091*d14abf15SRobert Mustacchi 1092*d14abf15SRobert Mustacchi static um_txpacket_t * BnxeTxPktAlloc(um_device_t * pUM, 1093*d14abf15SRobert Mustacchi size_t size) 1094*d14abf15SRobert Mustacchi { 1095*d14abf15SRobert Mustacchi um_txpacket_t * pTxPkt; 1096*d14abf15SRobert Mustacchi ddi_dma_cookie_t cookie; 1097*d14abf15SRobert Mustacchi u32_t count; 1098*d14abf15SRobert Mustacchi size_t length; 1099*d14abf15SRobert Mustacchi int rc, j; 1100*d14abf15SRobert Mustacchi 1101*d14abf15SRobert Mustacchi if ((pTxPkt = kmem_zalloc(sizeof(um_txpacket_t), KM_NOSLEEP)) == NULL) 1102*d14abf15SRobert Mustacchi { 1103*d14abf15SRobert Mustacchi return NULL; 1104*d14abf15SRobert Mustacchi } 1105*d14abf15SRobert Mustacchi 1106*d14abf15SRobert Mustacchi pTxPkt->lm_pkt.l2pkt_tx_info = &pTxPkt->tx_info; 1107*d14abf15SRobert Mustacchi 1108*d14abf15SRobert Mustacchi if ((rc = ddi_dma_alloc_handle(pUM->pDev, 1109*d14abf15SRobert Mustacchi &bnxeTxCbDmaAttrib, 1110*d14abf15SRobert Mustacchi DDI_DMA_DONTWAIT, 1111*d14abf15SRobert Mustacchi NULL, 1112*d14abf15SRobert Mustacchi &pTxPkt->cbDmaHandle)) != DDI_SUCCESS) 1113*d14abf15SRobert Mustacchi { 1114*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to alloc DMA handle for Tx Desc (%d)", rc); 1115*d14abf15SRobert Mustacchi kmem_free(pTxPkt, sizeof(um_txpacket_t)); 1116*d14abf15SRobert Mustacchi return NULL; 1117*d14abf15SRobert Mustacchi } 1118*d14abf15SRobert Mustacchi 1119*d14abf15SRobert Mustacchi if ((rc = ddi_dma_mem_alloc(pTxPkt->cbDmaHandle, 1120*d14abf15SRobert Mustacchi size, 1121*d14abf15SRobert Mustacchi &bnxeAccessAttribBUF, 1122*d14abf15SRobert Mustacchi DDI_DMA_STREAMING, 1123*d14abf15SRobert Mustacchi DDI_DMA_DONTWAIT, 1124*d14abf15SRobert Mustacchi NULL, 1125*d14abf15SRobert Mustacchi &pTxPkt->pCbBuf, 1126*d14abf15SRobert Mustacchi &length, 1127*d14abf15SRobert Mustacchi &pTxPkt->cbDmaAccHandle)) != DDI_SUCCESS) 1128*d14abf15SRobert Mustacchi { 1129*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to alloc DMA memory for Tx Desc (%d)", rc); 1130*d14abf15SRobert Mustacchi ddi_dma_free_handle(&pTxPkt->cbDmaHandle); 1131*d14abf15SRobert Mustacchi kmem_free(pTxPkt, sizeof(um_txpacket_t)); 1132*d14abf15SRobert Mustacchi return NULL; 1133*d14abf15SRobert Mustacchi } 1134*d14abf15SRobert Mustacchi 1135*d14abf15SRobert Mustacchi if ((rc = ddi_dma_addr_bind_handle(pTxPkt->cbDmaHandle, 1136*d14abf15SRobert Mustacchi NULL, 1137*d14abf15SRobert Mustacchi pTxPkt->pCbBuf, 1138*d14abf15SRobert Mustacchi length, 1139*d14abf15SRobert Mustacchi DDI_DMA_WRITE | DDI_DMA_STREAMING, 1140*d14abf15SRobert Mustacchi DDI_DMA_DONTWAIT, 1141*d14abf15SRobert Mustacchi NULL, 1142*d14abf15SRobert Mustacchi &cookie, 1143*d14abf15SRobert Mustacchi &count)) != DDI_DMA_MAPPED) 1144*d14abf15SRobert Mustacchi { 1145*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to bind DMA address for Tx Desc (%d)", rc); 1146*d14abf15SRobert Mustacchi ddi_dma_mem_free(&pTxPkt->cbDmaAccHandle); 1147*d14abf15SRobert Mustacchi ddi_dma_free_handle(&pTxPkt->cbDmaHandle); 1148*d14abf15SRobert Mustacchi kmem_free(pTxPkt, sizeof(um_txpacket_t)); 1149*d14abf15SRobert Mustacchi return NULL; 1150*d14abf15SRobert Mustacchi } 1151*d14abf15SRobert Mustacchi 1152*d14abf15SRobert Mustacchi pTxPkt->cbPhysAddr.as_u64 = cookie.dmac_laddress; 1153*d14abf15SRobert Mustacchi 1154*d14abf15SRobert Mustacchi for (j = 0; j < BNXE_MAX_DMA_HANDLES_PER_PKT; j++) 1155*d14abf15SRobert Mustacchi { 1156*d14abf15SRobert Mustacchi if ((rc = ddi_dma_alloc_handle(pUM->pDev, 1157*d14abf15SRobert Mustacchi &bnxeTxDmaAttrib, 1158*d14abf15SRobert Mustacchi DDI_DMA_DONTWAIT, 1159*d14abf15SRobert Mustacchi NULL, 1160*d14abf15SRobert Mustacchi &pTxPkt->dmaHandles[j])) != 1161*d14abf15SRobert Mustacchi DDI_SUCCESS) 1162*d14abf15SRobert Mustacchi { 1163*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to alloc DMA handles for Tx Pkt %d (%d)", 1164*d14abf15SRobert Mustacchi j, rc); 1165*d14abf15SRobert Mustacchi 1166*d14abf15SRobert Mustacchi for(--j; j >= 0; j--) /* unwind */ 1167*d14abf15SRobert Mustacchi { 1168*d14abf15SRobert Mustacchi ddi_dma_free_handle(&pTxPkt->dmaHandles[j]); 1169*d14abf15SRobert Mustacchi } 1170*d14abf15SRobert Mustacchi 1171*d14abf15SRobert Mustacchi ddi_dma_unbind_handle(pTxPkt->cbDmaHandle); 1172*d14abf15SRobert Mustacchi ddi_dma_mem_free(&pTxPkt->cbDmaAccHandle); 1173*d14abf15SRobert Mustacchi ddi_dma_free_handle(&pTxPkt->cbDmaHandle); 1174*d14abf15SRobert Mustacchi kmem_free(pTxPkt, sizeof(um_txpacket_t)); 1175*d14abf15SRobert Mustacchi return NULL; 1176*d14abf15SRobert Mustacchi } 1177*d14abf15SRobert Mustacchi } 1178*d14abf15SRobert Mustacchi 1179*d14abf15SRobert Mustacchi ASSERT(pTxPkt->pMblk == NULL); 1180*d14abf15SRobert Mustacchi ASSERT(pTxPkt->num_handles == 0); 1181*d14abf15SRobert Mustacchi ASSERT(pTxPkt->frag_list.cnt == 0); 1182*d14abf15SRobert Mustacchi pTxPkt->cbLength = size; 1183*d14abf15SRobert Mustacchi 1184*d14abf15SRobert Mustacchi return pTxPkt; 1185*d14abf15SRobert Mustacchi } 1186*d14abf15SRobert Mustacchi 1187*d14abf15SRobert Mustacchi 1188*d14abf15SRobert Mustacchi static int BnxeTxPktsInitIdx(um_device_t * pUM, 1189*d14abf15SRobert Mustacchi int idx) 1190*d14abf15SRobert Mustacchi { 1191*d14abf15SRobert Mustacchi lm_device_t * pLM = &pUM->lm_dev; 1192*d14abf15SRobert Mustacchi TxQueue * pTxQ; 1193*d14abf15SRobert Mustacchi um_txpacket_t * pTxPkt; 1194*d14abf15SRobert Mustacchi s_list_t tmpList; 1195*d14abf15SRobert Mustacchi int i; 1196*d14abf15SRobert Mustacchi 1197*d14abf15SRobert Mustacchi pTxQ = &pUM->txq[idx]; 1198*d14abf15SRobert Mustacchi 1199*d14abf15SRobert Mustacchi s_list_clear(&pTxQ->sentTxQ); 1200*d14abf15SRobert Mustacchi s_list_clear(&pTxQ->freeTxDescQ); 1201*d14abf15SRobert Mustacchi s_list_clear(&pTxQ->waitTxDescQ); 1202*d14abf15SRobert Mustacchi 1203*d14abf15SRobert Mustacchi pTxQ->desc_cnt = pUM->devParams.numTxDesc[LM_CHAIN_IDX_CLI(pLM, idx)]; 1204*d14abf15SRobert Mustacchi pTxQ->txLowWater = pUM->devParams.numTxDesc[LM_CHAIN_IDX_CLI(pLM, idx)]; 1205*d14abf15SRobert Mustacchi pTxQ->thresh_pdwm = BNXE_PDWM_THRESHOLD; 1206*d14abf15SRobert Mustacchi pTxQ->txFailed = 0; 1207*d14abf15SRobert Mustacchi pTxQ->txDiscards = 0; 1208*d14abf15SRobert Mustacchi pTxQ->txRecycle = 0; 1209*d14abf15SRobert Mustacchi pTxQ->txCopied = 0; 1210*d14abf15SRobert Mustacchi pTxQ->txBlocked = 0; 1211*d14abf15SRobert Mustacchi pTxQ->txWait = 0; 1212*d14abf15SRobert Mustacchi 1213*d14abf15SRobert Mustacchi if (pUM->devParams.lsoEnable) 1214*d14abf15SRobert Mustacchi { 1215*d14abf15SRobert Mustacchi for (i = 0; i < pTxQ->desc_cnt; i++) 1216*d14abf15SRobert Mustacchi { 1217*d14abf15SRobert Mustacchi pTxPkt = BnxeTxPktAlloc(pUM, 1218*d14abf15SRobert Mustacchi (BNXE_IP_MAXLEN + 1219*d14abf15SRobert Mustacchi sizeof(struct ether_vlan_header))); 1220*d14abf15SRobert Mustacchi if (pTxPkt == NULL) 1221*d14abf15SRobert Mustacchi { 1222*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to allocate all Tx Descs for LSO (%d/%d allocated), LSO is disabled", 1223*d14abf15SRobert Mustacchi i, pTxQ->desc_cnt); 1224*d14abf15SRobert Mustacchi 1225*d14abf15SRobert Mustacchi /* free existing in freeTxDescQ... */ 1226*d14abf15SRobert Mustacchi 1227*d14abf15SRobert Mustacchi BNXE_LOCK_ENTER_FREETX(pUM, idx); 1228*d14abf15SRobert Mustacchi tmpList = pTxQ->freeTxDescQ; 1229*d14abf15SRobert Mustacchi s_list_clear(&pTxQ->freeTxDescQ); 1230*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_FREETX(pUM, idx); 1231*d14abf15SRobert Mustacchi 1232*d14abf15SRobert Mustacchi BnxeTxPktsFreeList(&tmpList); 1233*d14abf15SRobert Mustacchi 1234*d14abf15SRobert Mustacchi pUM->devParams.lsoEnable = 0; /* Disabling LSO! */ 1235*d14abf15SRobert Mustacchi 1236*d14abf15SRobert Mustacchi break; 1237*d14abf15SRobert Mustacchi } 1238*d14abf15SRobert Mustacchi 1239*d14abf15SRobert Mustacchi BNXE_LOCK_ENTER_FREETX(pUM, idx); 1240*d14abf15SRobert Mustacchi s_list_push_tail(&pTxQ->freeTxDescQ, &pTxPkt->lm_pkt.link); 1241*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_FREETX(pUM, idx); 1242*d14abf15SRobert Mustacchi } 1243*d14abf15SRobert Mustacchi } 1244*d14abf15SRobert Mustacchi 1245*d14abf15SRobert Mustacchi if (!pUM->devParams.lsoEnable) 1246*d14abf15SRobert Mustacchi { 1247*d14abf15SRobert Mustacchi for (i = 0; i < pTxQ->desc_cnt; i++) 1248*d14abf15SRobert Mustacchi { 1249*d14abf15SRobert Mustacchi pTxPkt = BnxeTxPktAlloc(pUM, 1250*d14abf15SRobert Mustacchi (pUM->devParams.mtu[LM_CHAIN_IDX_CLI(pLM, idx)] + 1251*d14abf15SRobert Mustacchi sizeof(struct ether_vlan_header))); 1252*d14abf15SRobert Mustacchi if (pTxPkt == NULL) 1253*d14abf15SRobert Mustacchi { 1254*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Failed to allocate all Tx Descs (%d/%d allocated)", 1255*d14abf15SRobert Mustacchi i, pTxQ->desc_cnt); 1256*d14abf15SRobert Mustacchi 1257*d14abf15SRobert Mustacchi /* free existing in freeTxDescQ... */ 1258*d14abf15SRobert Mustacchi 1259*d14abf15SRobert Mustacchi BNXE_LOCK_ENTER_FREETX(pUM, idx); 1260*d14abf15SRobert Mustacchi tmpList = pTxQ->freeTxDescQ; 1261*d14abf15SRobert Mustacchi s_list_clear(&pTxQ->freeTxDescQ); 1262*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_FREETX(pUM, idx); 1263*d14abf15SRobert Mustacchi 1264*d14abf15SRobert Mustacchi BnxeTxPktsFreeList(&tmpList); 1265*d14abf15SRobert Mustacchi 1266*d14abf15SRobert Mustacchi return -1; 1267*d14abf15SRobert Mustacchi } 1268*d14abf15SRobert Mustacchi 1269*d14abf15SRobert Mustacchi BNXE_LOCK_ENTER_FREETX(pUM, idx); 1270*d14abf15SRobert Mustacchi s_list_push_tail(&pTxQ->freeTxDescQ, &pTxPkt->lm_pkt.link); 1271*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_FREETX(pUM, idx); 1272*d14abf15SRobert Mustacchi } 1273*d14abf15SRobert Mustacchi } 1274*d14abf15SRobert Mustacchi 1275*d14abf15SRobert Mustacchi return 0; 1276*d14abf15SRobert Mustacchi } 1277*d14abf15SRobert Mustacchi 1278*d14abf15SRobert Mustacchi 1279*d14abf15SRobert Mustacchi int BnxeTxPktsInit(um_device_t * pUM, 1280*d14abf15SRobert Mustacchi int cliIdx) 1281*d14abf15SRobert Mustacchi { 1282*d14abf15SRobert Mustacchi int idx, rc; 1283*d14abf15SRobert Mustacchi 1284*d14abf15SRobert Mustacchi switch (cliIdx) 1285*d14abf15SRobert Mustacchi { 1286*d14abf15SRobert Mustacchi case LM_CLI_IDX_FCOE: 1287*d14abf15SRobert Mustacchi 1288*d14abf15SRobert Mustacchi rc = BnxeTxPktsInitIdx(pUM, FCOE_CID(&pUM->lm_dev)); 1289*d14abf15SRobert Mustacchi break; 1290*d14abf15SRobert Mustacchi 1291*d14abf15SRobert Mustacchi case LM_CLI_IDX_NDIS: 1292*d14abf15SRobert Mustacchi 1293*d14abf15SRobert Mustacchi LM_FOREACH_TSS_IDX(&pUM->lm_dev, idx) 1294*d14abf15SRobert Mustacchi { 1295*d14abf15SRobert Mustacchi if ((rc = BnxeTxPktsInitIdx(pUM, idx)) < 0) 1296*d14abf15SRobert Mustacchi { 1297*d14abf15SRobert Mustacchi break; 1298*d14abf15SRobert Mustacchi } 1299*d14abf15SRobert Mustacchi } 1300*d14abf15SRobert Mustacchi 1301*d14abf15SRobert Mustacchi break; 1302*d14abf15SRobert Mustacchi 1303*d14abf15SRobert Mustacchi default: 1304*d14abf15SRobert Mustacchi 1305*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "ERROR: Invalid cliIdx for BnxeTxPktsFini (%d)", cliIdx); 1306*d14abf15SRobert Mustacchi rc = -1; 1307*d14abf15SRobert Mustacchi break; 1308*d14abf15SRobert Mustacchi } 1309*d14abf15SRobert Mustacchi 1310*d14abf15SRobert Mustacchi return rc; 1311*d14abf15SRobert Mustacchi } 1312*d14abf15SRobert Mustacchi 1313*d14abf15SRobert Mustacchi 1314*d14abf15SRobert Mustacchi static void BnxeTxPktsFiniIdx(um_device_t * pUM, 1315*d14abf15SRobert Mustacchi int idx) 1316*d14abf15SRobert Mustacchi { 1317*d14abf15SRobert Mustacchi lm_device_t * pLM = &pUM->lm_dev; 1318*d14abf15SRobert Mustacchi TxQueue * pTxQ; 1319*d14abf15SRobert Mustacchi s_list_t tmpList; 1320*d14abf15SRobert Mustacchi 1321*d14abf15SRobert Mustacchi pTxQ = &pUM->txq[idx]; 1322*d14abf15SRobert Mustacchi 1323*d14abf15SRobert Mustacchi BNXE_LOCK_ENTER_FREETX(pUM, idx); 1324*d14abf15SRobert Mustacchi tmpList = pTxQ->freeTxDescQ; 1325*d14abf15SRobert Mustacchi s_list_clear(&pTxQ->freeTxDescQ); 1326*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_FREETX(pUM, idx); 1327*d14abf15SRobert Mustacchi 1328*d14abf15SRobert Mustacchi BNXE_LOCK_ENTER_TX(pUM, idx); 1329*d14abf15SRobert Mustacchi s_list_add_tail(&tmpList, &pTxQ->sentTxQ); 1330*d14abf15SRobert Mustacchi s_list_clear(&pTxQ->sentTxQ); 1331*d14abf15SRobert Mustacchi BNXE_LOCK_EXIT_TX(pUM, idx); 1332*d14abf15SRobert Mustacchi 1333*d14abf15SRobert Mustacchi /* there could be more than originally allocated but less is bad */ 1334*d14abf15SRobert Mustacchi if (s_list_entry_cnt(&tmpList) < 1335*d14abf15SRobert Mustacchi pUM->devParams.numTxDesc[LM_CHAIN_IDX_CLI(pLM, idx)]) 1336*d14abf15SRobert Mustacchi { 1337*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "Missing TX descriptors (%lu / %d) (TxFail: %d)", 1338*d14abf15SRobert Mustacchi s_list_entry_cnt(&tmpList), pUM->devParams.numTxDesc, 1339*d14abf15SRobert Mustacchi pTxQ->txFailed); 1340*d14abf15SRobert Mustacchi } 1341*d14abf15SRobert Mustacchi 1342*d14abf15SRobert Mustacchi BnxeTxPktsFreeList(&tmpList); 1343*d14abf15SRobert Mustacchi } 1344*d14abf15SRobert Mustacchi 1345*d14abf15SRobert Mustacchi 1346*d14abf15SRobert Mustacchi void BnxeTxPktsFini(um_device_t * pUM, 1347*d14abf15SRobert Mustacchi int cliIdx) 1348*d14abf15SRobert Mustacchi { 1349*d14abf15SRobert Mustacchi int idx; 1350*d14abf15SRobert Mustacchi 1351*d14abf15SRobert Mustacchi switch (cliIdx) 1352*d14abf15SRobert Mustacchi { 1353*d14abf15SRobert Mustacchi case LM_CLI_IDX_FCOE: 1354*d14abf15SRobert Mustacchi 1355*d14abf15SRobert Mustacchi BnxeTxPktsFiniIdx(pUM, FCOE_CID(&pUM->lm_dev)); 1356*d14abf15SRobert Mustacchi break; 1357*d14abf15SRobert Mustacchi 1358*d14abf15SRobert Mustacchi case LM_CLI_IDX_NDIS: 1359*d14abf15SRobert Mustacchi 1360*d14abf15SRobert Mustacchi LM_FOREACH_TSS_IDX(&pUM->lm_dev, idx) 1361*d14abf15SRobert Mustacchi { 1362*d14abf15SRobert Mustacchi BnxeTxPktsFiniIdx(pUM, idx); 1363*d14abf15SRobert Mustacchi } 1364*d14abf15SRobert Mustacchi 1365*d14abf15SRobert Mustacchi break; 1366*d14abf15SRobert Mustacchi 1367*d14abf15SRobert Mustacchi default: 1368*d14abf15SRobert Mustacchi 1369*d14abf15SRobert Mustacchi BnxeLogWarn(pUM, "ERROR: Invalid cliIdx for BnxeTxPktsFini (%d)", cliIdx); 1370*d14abf15SRobert Mustacchi break; 1371*d14abf15SRobert Mustacchi } 1372*d14abf15SRobert Mustacchi } 1373*d14abf15SRobert Mustacchi 1374