• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2 **+-----------------------------------------------------------------------+**
3 **|                                                                       |**
4 **| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved.      |**
5 **| All rights reserved.                                                  |**
6 **|                                                                       |**
7 **| Redistribution and use in source and binary forms, with or without    |**
8 **| modification, are permitted provided that the following conditions    |**
9 **| are met:                                                              |**
10 **|                                                                       |**
11 **|  * Redistributions of source code must retain the above copyright     |**
12 **|    notice, this list of conditions and the following disclaimer.      |**
13 **|  * Redistributions in binary form must reproduce the above copyright  |**
14 **|    notice, this list of conditions and the following disclaimer in    |**
15 **|    the documentation and/or other materials provided with the         |**
16 **|    distribution.                                                      |**
17 **|  * Neither the name Texas Instruments nor the names of its            |**
18 **|    contributors may be used to endorse or promote products derived    |**
19 **|    from this software without specific prior written permission.      |**
20 **|                                                                       |**
21 **| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   |**
22 **| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     |**
23 **| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |**
24 **| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  |**
25 **| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |**
26 **| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      |**
27 **| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |**
28 **| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |**
29 **| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   |**
30 **| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |**
31 **| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  |**
32 **|                                                                       |**
33 **+-----------------------------------------------------------------------+**
34 ****************************************************************************/
35 
36 /****************************************************************************
37  *
38  *   MODULE:	TNETW_Driver_Tx.c
39  *
40  *   PURPOSE:	TNETW_Driver Tx API functions needed externally to the driver.
41  *
42  ****************************************************************************/
43 
44 #include "whalParams.h"
45 #include "report.h"
46 #include "TNETW_Driver_api.h"
47 #include "txCtrlBlk_api.h"
48 #include "txHwQueue_api.h"
49 #include "txXfer_api.h"
50 #include "txResult_api.h"
51 #include "TNETW_Driver.h"
52 
53 
54 static systemStatus_e ConvertTxResultStatus(TxDescStatus_enum txResultStatus);
55 
56 
57 /****************************************************************************
58  *					Tx Control Block API functions							*
59  ****************************************************************************/
60 
TnetwDrv_txCtrlBlk_alloc(TI_HANDLE hTnetwDrv)61 txCtrlBlkEntry_t *TnetwDrv_txCtrlBlk_alloc(TI_HANDLE hTnetwDrv)
62 {
63 	TnetwDrv_t *pTnetwDrv = (TnetwDrv_t *)hTnetwDrv;
64 
65 	return txCtrlBlk_alloc(pTnetwDrv->hTxCtrlBlk);
66 }
67 
68 
TnetwDrv_txCtrlBlk_free(TI_HANDLE hTnetwDrv,txCtrlBlkEntry_t * pCurrentEntry)69 void TnetwDrv_txCtrlBlk_free(TI_HANDLE hTnetwDrv, txCtrlBlkEntry_t *pCurrentEntry)
70 {
71 	TnetwDrv_t *pTnetwDrv = (TnetwDrv_t *)hTnetwDrv;
72 
73 	txCtrlBlk_free(pTnetwDrv->hTxCtrlBlk, pCurrentEntry);
74 }
75 
76 
TnetwDrv_txCtrlBlk_GetPointer(TI_HANDLE hTnetwDrv,UINT8 descId)77 txCtrlBlkEntry_t *TnetwDrv_txCtrlBlk_GetPointer(TI_HANDLE hTnetwDrv, UINT8 descId)
78 {
79 	TnetwDrv_t *pTnetwDrv = (TnetwDrv_t *)hTnetwDrv;
80 
81 	return txCtrlBlk_GetPointer(pTnetwDrv->hTxCtrlBlk, descId);
82 }
83 
84 
85 
86 /****************************************************************************
87  *						Tx HW Queue API functions							*
88  ****************************************************************************/
89 
TnetwDrv_txHwQueue_alloc(TI_HANDLE hTnetwDrv,txCtrlBlkEntry_t * pPktCtrlBlk)90 TI_STATUS  TnetwDrv_txHwQueue_alloc(TI_HANDLE hTnetwDrv, txCtrlBlkEntry_t *pPktCtrlBlk)
91 {
92 	TnetwDrv_t *pTnetwDrv = (TnetwDrv_t *)hTnetwDrv;
93 
94 	return txHwQueue_alloc(pTnetwDrv->hTxHwQueue, pPktCtrlBlk);
95 }
96 
97 
TnetwDrv_txHwQueue_free(TI_HANDLE hTnetwDrv,txCtrlBlkEntry_t * pPktCtrlBlk)98 TI_STATUS  TnetwDrv_txHwQueue_free(TI_HANDLE hTnetwDrv, txCtrlBlkEntry_t *pPktCtrlBlk)
99 {
100 	TnetwDrv_t *pTnetwDrv = (TnetwDrv_t *)hTnetwDrv;
101 
102 	return txHwQueue_free(pTnetwDrv->hTxHwQueue, pPktCtrlBlk);
103 }
104 
105 
TnetwDrv_txHwQueue_GetUsedHwBlks(TI_HANDLE hTnetwDrv,int TxQid)106 UINT8  TnetwDrv_txHwQueue_GetUsedHwBlks(TI_HANDLE hTnetwDrv, int TxQid)
107 {
108 	TnetwDrv_t *pTnetwDrv = (TnetwDrv_t *)hTnetwDrv;
109 
110 	return txHwQueue_GetUsedHwBlks(pTnetwDrv->hTxHwQueue, TxQid);
111 }
112 
113 
114 
115 /****************************************************************************
116  *							Tx Xfer API functions							*
117  ****************************************************************************/
118 
TnetwDrv_txXfer_sendPacket(TI_HANDLE hTnetwDrv,const void * aFrame,UINT16 aLength,UINT8 aQueueId,UINT8 aTxRateClassId,UINT16 aMaxTransmitRate,BOOL aMore,UINT32 aPacketId,UINT8 aPowerLevel,UINT32 aExpiryTime,void * aReserved)119 systemStatus_e	TnetwDrv_txXfer_sendPacket(TI_HANDLE hTnetwDrv,
120 				const void	*aFrame,		/* Pointer to the packet content. points to */
121                                             /* the place that the actual packet begins. */
122                                             /* a size of TX_TOTAL_OFFSET_BEFORE_DATA    */
123                                             /* must be saved before that pointer        */
124 				UINT16		aLength,		/* MSDU length from first byte of MAC		*/
125 											/*   header to last byteof frame body.		*/
126 				UINT8		aQueueId,		/* Tx queue as defined in ConfigureQueue.	*/
127 				UINT8		aTxRateClassId,	/* Tx rate class ID	defined in txRatePolicy.*/
128 				UINT16		aMaxTransmitRate,/* A bit mask that specifies the initial	*/
129 											/*     (highest) rate to use.				*/
130 				BOOL		aMore,			/* Tells if there is another packet	coming	*/
131 											/*   shortly after this one.				*/
132 				UINT32		aPacketId,		/* Packet identifier used as a context by	*/
133 											/*   the host driver.					*/
134 				UINT8	       aPowerLevel,	/* Transmission power level.				*/
135 				UINT32		aExpiryTime,	/* Time left for this MSDU to live.			*/
136 				void	   	     *aReserved)  	/* Optional parameters pointer.				*/
137 
138 {
139 	TnetwDrv_t *pTnetwDrv = (TnetwDrv_t *)hTnetwDrv;
140 	TxDescCtrl_t txAttr, *pTxAttr = &txAttr;  /* A union for setting the txAttr bit fields. */
141     dot11_header_t      *pDot11Hdr;
142 	systemStatus_e      status;
143 	txCtrlBlkEntry_t    *pPktCtrlBlk;
144     WhalParams_T *pWhalParams = (WhalParams_T *)(pTnetwDrv->hWhalParams);
145     BOOL                bIsMultiCastAndIBSS; /* used for the Ack policy */
146 
147 #ifdef TI_DBG
148 	/* If queue number is invalid return ERROR. */
149 	if (aQueueId >= MAX_NUM_OF_TX_QUEUES)
150 	{
151 		WLAN_REPORT_ERROR(pTnetwDrv->hReport, TNETW_DRV_MODULE_LOG,
152 			("TnetwDrv_txXfer_sendPacket(): Invalid aQueueId = %d !!!\n", aQueueId));
153 		return SEND_PACKET_ERROR;
154 	}
155 #endif
156 
157 	/*****************************************************************************************/
158 	/*  1) Allocates a Control-Block for the packet Tx parameters and descriptor.            */
159 	/*****************************************************************************************/
160 
161 	pPktCtrlBlk = TnetwDrv_txCtrlBlk_alloc(pTnetwDrv);
162 
163 #ifdef TI_DBG
164 	pTnetwDrv->dbgCountSentPackets[aQueueId]++;	/* Count packets sent from upper driver. */
165 #endif
166 	/* If null entry (not expected to happen) return ERROR. */
167 	if (!pPktCtrlBlk)
168 	{
169 #ifdef TI_DBG
170 		WLAN_REPORT_ERROR(pTnetwDrv->hReport, TNETW_DRV_MODULE_LOG,
171 			("TnetwDrv_txXfer_sendPacket(): Tx Ctrl-Blk allocation failed!!!\n"));
172 #endif
173 		return SEND_PACKET_ERROR;
174 	}
175 
176 	/*****************************************************************************************/
177 	/*  2) Set the packet control block parameters (including descriptor structure).         */
178 	/*****************************************************************************************/
179 
180 	/* Note that the following params are currently not used:	aMore, aPowerLevel, aReserved. */
181 
182 	/* Note that the following descriptor params are for future use, so they are left zeroed:
183 		 pktType and xferPadding fields in txAttr, and tid. */
184 
185 	/* Note that the other params are set later in the Tx process (e.g. fragThresh and numMemBlks). */
186 
187     /* aFrame points to the start of the data, but we need to reserve place for descriptor + TNETWIF_WRITE_OFFSET_BYTES */
188 	pPktCtrlBlk->txPktParams.pFrame = (void*)((UINT8 *)aFrame - TX_TOTAL_OFFSET_BEFORE_DATA);
189 
190 	pPktCtrlBlk->txDescriptor.length = aLength;
191 	pPktCtrlBlk->txDescriptor.xmitQueue = aQueueId;
192 	pPktCtrlBlk->txDescriptor.rate = aMaxTransmitRate;
193 	pPktCtrlBlk->txPktParams.packetId = aPacketId;
194 	pPktCtrlBlk->txDescriptor.expiryTime = aExpiryTime << SHIFT_BETWEEN_TU_AND_USEC;  /* Convert TUs to microseconds. */
195 
196 	pDot11Hdr = (dot11_header_t*)(aFrame); /* aFrame points to the start of the data */
197 	pPktCtrlBlk->txPktParams.headerFrameCtrl = pDot11Hdr->fc;  /* Save frame-control field from MAC header. */
198 
199 	/* Set descriptor control bit-mask fields and write the whole word to the descriptor. */
200 	*(uint16 *)pTxAttr = 0; /* Clear temporary union. */
201 	txAttr.ratePolicy = aTxRateClassId;
202 
203     /* Configure the Ack policy */
204     bIsMultiCastAndIBSS = ((BSS_INDEPENDENT == (bssType_e)(whal_ParamsGetReqBssType(pWhalParams)))
205                             && (MAC_MULTICAST(GET_DA_FROM_DOT11_HEADER_T(pDot11Hdr))));
206     txAttr.ackPolicy = TnetwDrv_txGetAckPolicy(pTnetwDrv, aQueueId , bIsMultiCastAndIBSS);
207 
208 	if (IS_QOS_FRAME(pDot11Hdr->fc))  /* Check if frame is QoS-Data or QoS-Null. */
209 		txAttr.qosFrame = 1;
210 
211 	/* if this is a management frame, request immediate TX complete indication */
212 	if ( (pDot11Hdr->fc & DOT11_FC_TYPE_MASK) == DOT11_FC_TYPE_MGMT )
213 	{
214 		txAttr.txCmpltRequired = 1;
215 	}
216 
217 	pPktCtrlBlk->txDescriptor.txAttr = *(uint16 *)pTxAttr;
218 
219 	pPktCtrlBlk->txPktParams.flags = 0;
220 
221 
222 	/************************************************************************************************/
223 	/*  3) Call HwQueue for Hw resources allocation. If not available free CtrlBlk and return BUSY. */
224 	/************************************************************************************************/
225 
226 	/* Note that the HwQueue calls first the fragThreshold and numMemBlks calculation. */
227 
228 	if ( TnetwDrv_txHwQueue_alloc(pTnetwDrv, pPktCtrlBlk) != OK )
229 	{
230 		TnetwDrv_txCtrlBlk_free(pTnetwDrv, pPktCtrlBlk);
231 		return SEND_PACKET_BUSY;
232 	}
233 
234 #ifdef TI_DBG
235 	/* Just for debug, write per queue sequence number to packet ctrl-blk (after allocation success!). */
236 	pTnetwDrv->dbgPktSeqNum[aQueueId]++;
237 	pPktCtrlBlk->txPktParams.dbgPktSeqNum = pTnetwDrv->dbgPktSeqNum[aQueueId];
238 
239 	pTnetwDrv->dbgCountQueueAvailable[aQueueId]++;	/* Count packets sent and queue not busy. */
240 #endif
241 
242 
243 	/*****************************************************************************************/
244 	/*  4) Copy the descriptor to the frame .                      */
245 	/*****************************************************************************************/
246 
247     os_memoryCopy(pTnetwDrv->hOs, (void *)((UINT8*)aFrame - sizeof(DbTescriptor)), &(pPktCtrlBlk->txDescriptor), sizeof(DbTescriptor));
248 
249 
250 	/*****************************************************************************************/
251 	/*  5) Call the Tx-Xfer to start packet transfer to the FW and return its result.        */
252 	/*****************************************************************************************/
253 
254 	status = txXfer_sendPacket(pTnetwDrv->hTxXfer, pPktCtrlBlk);
255 
256 	/* If the packet was transfered in this context and Tx-complete already occured, free the ctrl-blk. */
257 	if (status == SEND_PACKET_XFER_DONE)
258 	{
259 		if (pPktCtrlBlk->txPktParams.flags & TX_CTRL_BLK_FLAGS_TX_COMPLETE_ISSUED)
260 			TnetwDrv_txCtrlBlk_free(pTnetwDrv, pPktCtrlBlk);
261 		else
262 			pPktCtrlBlk->txPktParams.flags |= TX_CTRL_BLK_FLAGS_XFER_DONE_ISSUED;
263 	}
264 
265 #ifdef TI_DBG
266 	if (status == SEND_PACKET_XFER_DONE)
267 		pTnetwDrv->dbgCountXferDone[aQueueId]++;
268 	else if (status == SEND_PACKET_SUCCESS)
269 		pTnetwDrv->dbgCountXferSuccess[aQueueId]++;
270 	else if (status == SEND_PACKET_PENDING)
271 		pTnetwDrv->dbgCountXferPending[aQueueId]++;
272 	else
273 		pTnetwDrv->dbgCountXferError[aQueueId]++;
274 #endif
275 
276 
277 	return status;
278 }
279 
280 
281 
282 
283 /****************************************************************************
284  *				Tx API functions needed for GWSI interface					*
285  ****************************************************************************/
286 
TnetwDrv_txGetAckPolicy(TI_HANDLE hTnetwDrv,int TxQid,BOOL bIsMultiCastAndIBSS)287 UINT8  TnetwDrv_txGetAckPolicy(TI_HANDLE hTnetwDrv, int TxQid ,  BOOL bIsMultiCastAndIBSS)
288 {
289 	TnetwDrv_t *pTnetwDrv = (TnetwDrv_t *)hTnetwDrv;
290 	WhalParams_T *pWhalParams = (WhalParams_T *)(pTnetwDrv->hWhalParams);
291 
292     /* If we are in IBSS and we are transmitting a Multicast/Broadcast frame -> we don't expect an Ack packet */
293     if (bIsMultiCastAndIBSS)
294     {
295         return ACK_POLICY_NO_ACK;
296     }
297 
298 	return (pWhalParams->QueuesParams.queues[TxQid].ackPolicy);
299 }
300 
301 /*************************************************************************
302 *                        TnetwDrv_TxXferDone                                 *
303 **************************************************************************
304 * DESCRIPTION:
305   ============
306 	Called  upon Xfer-Done of transmitted packet.
307 	Calls the upper driver's Xfer-Done handler.
308 
309 *
310 * INPUT:     hDummyHandle - Just to support the CB API.
311 *			 pPktCtrlBlk -  The packet's control block pointer.
312 *
313 * OUTPUT:
314 *
315 * RETURN:
316 
317 *************************************************************************/
TnetwDrv_TxXferDone(TI_HANDLE hTnetwDrv,txCtrlBlkEntry_t * pPktCtrlBlk)318 void TnetwDrv_TxXferDone(TI_HANDLE hTnetwDrv, txCtrlBlkEntry_t *pPktCtrlBlk)
319 {
320 	/* Make a working copy of TNETDriver Handle */
321 	TnetwDrv_t *pTnetwDrv = (TnetwDrv_t *)hTnetwDrv;
322 
323 
324 #ifdef TI_DBG
325 	pTnetwDrv->dbgCountXferDoneCB[pPktCtrlBlk->txDescriptor.xmitQueue]++;
326 #endif
327 	/* If the pointed entry is already free, print error and exit (not expected to happen). */
328 	if (pPktCtrlBlk->pNextFreeEntry != NULL)
329 	{
330 #ifdef TI_DBG
331 		WLAN_REPORT_ERROR(pTnetwDrv->hReport, TNETW_DRV_MODULE_LOG,
332 			("TnetwDrv_TxXferDone(): Pkt already free!!, DescID=%d, dbgPktSeqNum=%d, flags=%d, packetId=0x%x, Queue=%d\n",
333 			pPktCtrlBlk->txDescriptor.descID, pPktCtrlBlk->txPktParams.dbgPktSeqNum, pPktCtrlBlk->txPktParams.flags,
334 			pPktCtrlBlk->txPktParams.packetId, pPktCtrlBlk->txDescriptor.xmitQueue));
335 #endif
336 		return;
337 	}
338 
339 	/* If Tx-complete already occurred, free the ctrl-blk. */
340 	/* Note that this may happen when the Xfer-SM delays the Xfer-Done (for pipeline sequence). */
341 	if (pPktCtrlBlk->txPktParams.flags & TX_CTRL_BLK_FLAGS_TX_COMPLETE_ISSUED)
342 		TnetwDrv_txCtrlBlk_free(pTnetwDrv, pPktCtrlBlk);
343 	else
344 		pPktCtrlBlk->txPktParams.flags |= TX_CTRL_BLK_FLAGS_XFER_DONE_ISSUED;
345 
346 	/* Call the upper driver's Xfer-Done handler with the packet-ID. */
347 	/* Note that depending on the type of compilation, the upper layers vary: */
348 	/* It may be either CoreAdaptTx or GWSIAdaptTx */
349 	/* Both functions are called the same */
350 	SendPacketTransfer (pTnetwDrv->hUser, pPktCtrlBlk->txPktParams.packetId);
351 }
352 
353 
354 
355 /*************************************************************************
356 *                        TnetwDrv_TxComplete                                 *
357 **************************************************************************
358 * DESCRIPTION:
359   ============
360 	Called upon Tx-complete of transmitted packet.
361 	Handles it as follows:
362 	1) Update the HwQueue to free queue resources.
363 	2) Call the upper driver's tx-complete handler.
364 	3) Free the packet's Control-Block if Xfer-Done already occured.
365 
366 *
367 * INPUT:   hDummyHandle -  Just to support the CB API.
368 *		   pTxResultInfo - The packet's Tx result information.
369 *
370 * OUTPUT:
371 *
372 * RETURN:
373 
374 *************************************************************************/
TnetwDrv_TxComplete(TI_HANDLE hTnetwDrv,TxResultDescriptor_t * pTxResultInfo)375 void TnetwDrv_TxComplete(TI_HANDLE hTnetwDrv, TxResultDescriptor_t *pTxResultInfo)
376 {
377 	txCtrlBlkEntry_t *pPktCtrlBlk;
378 	/* Make a working copy of TNETDriver Handle */
379 	TnetwDrv_t *pTnetwDrv = (TnetwDrv_t *)hTnetwDrv;
380 
381 	/* Get the packet's control block pointer by the descId index. */
382 	pPktCtrlBlk = TnetwDrv_txCtrlBlk_GetPointer(pTnetwDrv, pTxResultInfo->descID);
383 
384 #ifdef TI_DBG
385 	WLAN_REPORT_INFORMATION(pTnetwDrv->hReport, TNETW_DRV_MODULE_LOG,
386 		("TnetwDrv_TxComplete(): DescID=%d, dbgPktSeqNum=%d, flags=%d, packetId=0x%x, Queue=%d\n",
387 		pTxResultInfo->descID, pPktCtrlBlk->txPktParams.dbgPktSeqNum, pPktCtrlBlk->txPktParams.flags,
388 		pPktCtrlBlk->txPktParams.packetId, pPktCtrlBlk->txDescriptor.xmitQueue));
389 
390 	pTnetwDrv->dbgCountTxCompleteCB[pPktCtrlBlk->txDescriptor.xmitQueue]++;
391 #endif
392 	/* If the pointed entry is already free, print error and exit (not expected to happen). */
393 	if (pPktCtrlBlk->pNextFreeEntry != NULL)
394 	{
395 #ifdef TI_DBG
396 		WLAN_REPORT_ERROR(pTnetwDrv->hReport, TNETW_DRV_MODULE_LOG,
397 			("TnetwDrv_TxComplete(): Pkt already free!!, DescID=%d, dbgPktSeqNum=%d, flags=%d, packetId=0x%x, Queue=%d\n",
398 			pTxResultInfo->descID, pPktCtrlBlk->txPktParams.dbgPktSeqNum, pPktCtrlBlk->txPktParams.flags,
399 			pPktCtrlBlk->txPktParams.packetId, pPktCtrlBlk->txDescriptor.xmitQueue));
400 #endif
401 		return;
402 	}
403 
404 	/* Update the HwQueue to free queue resources. */
405 	TnetwDrv_txHwQueue_free(pTnetwDrv, pPktCtrlBlk);
406 
407 	/* @@@ Note: Add Security Sequence Number handling. */
408 	/* Update the TKIP/AES sequence-number according to the Tx data packet security-seq-num. */
409 	/* Note: The FW always provides the last used seq-num so no need to check if the current
410 			 packet is data and WEP is on. */
411 	whalCtrl_updateSecuritySeqNum(pTnetwDrv->hHalCtrl, pTxResultInfo->lsbSecuritySequenceNumber);
412 
413 	/* Call the upper driver's tx-complete handler. */
414 	/* Note that depending on the type of compilation, the upper layeres varry: */
415 	/* It may be either CoreAdaptTx or GWSIAdaptTx */
416 	/* Both functions are called the same */
417 	SendPacketComplete (pTnetwDrv->hUser,
418                         ConvertTxResultStatus((TxDescStatus_enum)pTxResultInfo->status),
419 					    pPktCtrlBlk->txPktParams.packetId,
420 					    pTxResultInfo->actualRate,
421 					    pTxResultInfo->ackFailures,
422 					    (UINT32)pTxResultInfo->mediumUsage,
423 					    pTxResultInfo->fwHandlingTime,
424 					    pTxResultInfo->mediumDelay);
425 
426 	/* If Xfer-Done already occured, free the ctrl-blk (otherwise Xfer-Done will do it). */
427 	/* Note that the Xfer-SM may delay the Xfer-Done (for pipeline sequence). */
428 	if (pPktCtrlBlk->txPktParams.flags & TX_CTRL_BLK_FLAGS_XFER_DONE_ISSUED)
429 		TnetwDrv_txCtrlBlk_free(pTnetwDrv, pPktCtrlBlk);
430 	else
431 		pPktCtrlBlk->txPktParams.flags |= TX_CTRL_BLK_FLAGS_TX_COMPLETE_ISSUED;
432 }
433 
434 
435 /*************************************************************************
436 *                        TnetwDrv_RecoveryCtrlBlk                        *
437 **************************************************************************
438 * DESCRIPTION:
439   ============
440 	Called upon recovery.
441 	Handles it as follows:
442 	1) Update the HwQueue to free queue resources.
443 	3) Free the packet's Control-Block if Xfer-Done already occured.
444 
445 *
446 * INPUT:   hDummyHandle -  Just to support the CB API.
447 *
448 * OUTPUT:
449 *
450 * RETURN:
451 
452 *************************************************************************/
TnetwDrv_RecoveryCtrlBlk(TI_HANDLE hTnetwDrv)453 void TnetwDrv_RecoveryCtrlBlk(TI_HANDLE hTnetwDrv)
454 {
455 	txCtrlBlkEntry_t *pPktCtrlBlk;
456 	/* Make a working copy of TNETDriver Handle */
457 	TnetwDrv_t *pTnetwDrv = (TnetwDrv_t *)hTnetwDrv;
458 	UINT32 entry;
459     const UINT32 MAX_CTRL_BLK_ENTRY = 64;
460 
461 	for (entry = 0; entry < MAX_CTRL_BLK_ENTRY-1; entry++)
462 	{
463 		/* Get the packet's control block pointer by the descId index. */
464 		pPktCtrlBlk = TnetwDrv_txCtrlBlk_GetPointer(pTnetwDrv, entry);
465 		if (pPktCtrlBlk->pNextFreeEntry == NULL)
466 		{
467 			TnetwDrv_txHwQueue_free(pTnetwDrv, pPktCtrlBlk);
468 			TnetwDrv_txCtrlBlk_free(pTnetwDrv, pPktCtrlBlk);
469 		}
470 	}
471 }
472 
473 
474 /*************************************************************************
475 *                        TnetwDrv_TxXferDebug                                *
476 **************************************************************************
477 * DESCRIPTION:
478   ============
479     Called upon issuing interrupt to firmware.
480     Calls the upper driver's Xfer-Debug handler.
481 
482 *
483 * INPUT:     hDummyHandle - Just to support the CB API.
484 *            pPktCtrlBlk  - The packet's control block pointer.
485              uDebugInfo   - Additional debug info
486 *
487 * OUTPUT:
488 *
489 * RETURN:
490 
491 *************************************************************************/
492 #ifdef TI_DBG
TnetwDrv_TxXferDebug(TI_HANDLE hTnetwDrv,txCtrlBlkEntry_t * pPktCtrlBlk,UINT32 uDebugInfo)493 void TnetwDrv_TxXferDebug (TI_HANDLE hTnetwDrv, txCtrlBlkEntry_t *pPktCtrlBlk, UINT32 uDebugInfo)
494 {
495     TnetwDrv_t *pTnetwDrv = (TnetwDrv_t *)hTnetwDrv;
496        /* Call the upper driver's Xfer-Done handler with the packet-ID. */
497 	/* Note that depending on the type of compilation, the upper layeres varry: */
498 	/* It may be either CoreAdaptTx or GWSIAdaptTx */
499 	/* Both functions are called the same */
500     SendPacketDebug (pTnetwDrv->hUser, pPktCtrlBlk->txPktParams.packetId, uDebugInfo);
501 }
502 #endif
503 
504 
505 /****************************************************************************
506  *                      ConvertTxResultStatus
507  ****************************************************************************
508  * DESCRIPTION: Convert the status bit field in the TxDone descriptor, indexed
509  *				by the given index, to a driver status bit field
510  *
511  * INPUTS:	txResultStatus - Status value received from the FW
512  *
513  * OUTPUT:	None
514  *
515  * RETURNS:	The converted value
516  ****************************************************************************/
ConvertTxResultStatus(TxDescStatus_enum txResultStatus)517 systemStatus_e ConvertTxResultStatus(TxDescStatus_enum txResultStatus)
518 {
519 	/* Convert Tx-Result from FW to GWSI values. */
520 	/* Note: only 1 bit in the entire status field should be set */
521 	switch (txResultStatus)
522 	{
523 		case TX_SUCCESS:
524 			return SEND_COMPLETE_SUCCESS;
525 
526 		case TX_RETRY_EXCEEDED:
527 			return SEND_COMPLETE_RETRY_EXCEEDED;
528 
529 		case TX_TIMEOUT:
530 			return SEND_COMPLETE_LIFETIME_EXCEEDED;
531 
532 		default:
533 			return SEND_COMPLETE_NO_LINK;
534 	}
535 }
536 
537 
538 /****************************************************************************
539  *                      TnetwDrv_printInfo()
540  ****************************************************************************
541  * DESCRIPTION:	 Print the txXfer object main fields.
542  ****************************************************************************/
TnetwDrv_printInfo(TI_HANDLE hTnetwDrv)543 void TnetwDrv_printInfo(TI_HANDLE hTnetwDrv)
544 {
545 #ifdef TI_DBG
546     TnetwDrv_t *pTnetwDrv = (TnetwDrv_t *)hTnetwDrv;
547     int qIndex;
548 
549     WLAN_OS_REPORT(("TNETW Driver  Tx Counters per Queue:\n"));
550     WLAN_OS_REPORT(("===========================\n"));
551 
552     WLAN_OS_REPORT(("-------------- packets sent from upper driver ---------------\n"));
553     for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
554         WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTnetwDrv->dbgCountSentPackets[qIndex]));
555 
556     WLAN_OS_REPORT(("-------------- packets sent and queue not busy ---------------\n"));
557     for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
558         WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTnetwDrv->dbgCountQueueAvailable[qIndex]));
559 
560     WLAN_OS_REPORT(("-------------- XferDone value returned from Xfer ---------------\n"));
561     for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
562         WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTnetwDrv->dbgCountXferDone[qIndex]));
563 
564     WLAN_OS_REPORT(("-------------- Success value returned from Xfer ---------------\n"));
565     for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
566         WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTnetwDrv->dbgCountXferSuccess[qIndex]));
567 
568     WLAN_OS_REPORT(("-------------- Pending value returned from Xfer ---------------\n"));
569     for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
570         WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTnetwDrv->dbgCountXferPending[qIndex]));
571 
572     WLAN_OS_REPORT(("-------------- Error value returned from Xfer ---------------\n"));
573     for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
574         WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTnetwDrv->dbgCountXferError[qIndex]));
575 
576     WLAN_OS_REPORT(("-------------- XferDone callback calls ---------------\n"));
577     for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
578         WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTnetwDrv->dbgCountXferDoneCB[qIndex]));
579 
580     WLAN_OS_REPORT(("-------------- TxComplete callback calls ---------------\n"));
581     for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
582         WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTnetwDrv->dbgCountTxCompleteCB[qIndex]));
583 #endif /* TI_DBG */
584 }
585