xref: /titanic_51/usr/src/uts/common/io/bnxe/bnxe_tx.c (revision d14abf155341d55053c76eeec58b787a456b753b)
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