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
BnxeTxPktUnmap(um_txpacket_t * pTxPkt)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
BnxeTxPktsFree(um_txpacket_t * pTxPkt)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
BnxeTxPktsFreeList(s_list_t * pPktList)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 */
BnxeTxPktsReclaim(um_device_t * pUM,int idx,s_list_t * pPktList)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!!! */
BnxeTxSendWaitingPkt(um_device_t * pUM,int idx)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
BnxeTxRingProcess(um_device_t * pUM,int idx)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
BnxeTxPktMapFrag(um_device_t * pUM,um_txpacket_t * pTxPkt,mblk_t * pMblk)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
BnxeTxPktCopy(um_device_t * pUM,TxQueue * pTxQ,um_txpacket_t * pTxPkt)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 */
BnxeCalcCksum(void * start,u32_t len,u16_t prev_sum)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
BnxeUdpPseudoCsum(um_device_t * pUM,u8_t * pUdpHdr,u8_t * pIpHdr,u8_t ipHdrLen)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
BnxeGetVlanTag(mblk_t * pMblk)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
BnxeGetHdrInfo(um_device_t * pUM,um_txpacket_t * pTxPkt)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
BnxeTxSendMblk(um_device_t * pUM,int idx,mblk_t * pMblk,u32_t flags,u16_t vlan_tag)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
BnxeTxPktsAbortIdx(um_device_t * pUM,int idx)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
BnxeTxPktsAbort(um_device_t * pUM,int cliIdx)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
BnxeTxPktAlloc(um_device_t * pUM,size_t size)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
BnxeTxPktsInitIdx(um_device_t * pUM,int idx)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
BnxeTxPktsInit(um_device_t * pUM,int cliIdx)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
BnxeTxPktsFiniIdx(um_device_t * pUM,int idx)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
BnxeTxPktsFini(um_device_t * pUM,int cliIdx)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