• 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:  txHwQueueCalc.c
39  *
40  *   PURPOSE:
41  *		Calculates the fragmentation threshold and number of HW memory blocks
42  *		  required for the transmitted packet.
43  *
44  *	 DESCRIPTION:
45  *   ============
46  *		This is a sub-module of the Tx-HW-Queue module.
47  *		When the Tx-HW-Queue is requested to allocate HW resources for a Tx
48  *		  packet (see txHwQueue_alloc()), it first calls this module to get
49  *		  the number of HW memory blocks required for the packet.
50  *		First the fragmentation threshold is calculated, and then the number
51  *		  blocks. Both values are written in the provided control block of
52  *		  the packet (in the descriptor structure to be copied to the FW).
53  *
54  ****************************************************************************/
55 
56 #include "public_types.h"
57 #include "802_11Defs.h"
58 #include "ratesTypes.h"
59 #include "whalCommon.h"
60 #include "whalParams.h"
61 #include "whalCtrl_api.h"
62 #include "txHwQueue_api.h"
63 #include "utils.h"
64 #include "txHwQueue.h"		/* Local definitions */
65 #include "txHwQueueCalc.h"  /* Local definitions */
66 
67 
68 
69 
70 /****************************************************************************
71  *                      txHwQueueCalc_BlocksNum()
72  ****************************************************************************
73  * DESCRIPTION:
74  * ============
75  *	Calculate the fragmentation threshold and the number of HW blocks
76  *	  required for the whole FW Tx processing of the packet.
77  *
78  ****************************************************************************/
txHwQueueCalc_BlocksNum(TI_HANDLE hTxHwQueue,txCtrlBlkEntry_t * pPktCtrlBlk)79 void txHwQueueCalc_BlocksNum(TI_HANDLE hTxHwQueue, txCtrlBlkEntry_t *pPktCtrlBlk)
80 {
81 	TxHwQueueObj_t *pTxHwQueue = (TxHwQueueObj_t *)hTxHwQueue;
82     UINT16 memBlocks;
83     UINT16 numMpdus;
84     UINT16 numMemBlocksPerFullFrag;
85     UINT16 payloadDataLen;
86     UINT16 fragThreshold;
87 
88 	/* Calculate the fragmentation threshold. */
89 	fragThreshold = CalcFragThreshold(pTxHwQueue, pPktCtrlBlk);
90 
91     payloadDataLen  = pPktCtrlBlk->txDescriptor.length + MAX_MSDU_SECURITY_LENGTH;
92 
93     if (payloadDataLen > fragThreshold)
94 	{
95 #ifdef TI_DBG
96         if (fragThreshold == 0)
97         {
98             WLAN_OS_REPORT(("ERROR !!!!!!!!! fragThreshold==0 !!!!!!"));
99             return;
100         }
101 #endif
102 
103 		numMemBlocksPerFullFrag = ((fragThreshold + MAX_MPDU_HEADER_AND_SECURITY) / HW_BLOCK_SIZE) + 1;
104         numMpdus = payloadDataLen / fragThreshold;
105         memBlocks = numMpdus * numMemBlocksPerFullFrag;
106         payloadDataLen -= numMpdus * fragThreshold;
107 		numMpdus++;
108 	}
109 	else
110 	{
111 		numMemBlocksPerFullFrag = 0;
112 		memBlocks = 0;
113 		numMpdus = 1;
114 	}
115 
116     memBlocks += (payloadDataLen / HW_BLOCK_SIZE) + 1;
117 
118 	/* If fragmentation needed, add spare blocks for FW internal copy purposes. */
119     if (numMpdus > 1)
120         memBlocks += min(numMpdus, numMemBlocksPerFullFrag);
121 
122   #ifdef TI_DBG
123     if (memBlocks > 255)
124         WLAN_REPORT_ERROR (pTxHwQueue->hReport, TX_HW_QUEUE_MODULE_LOG,
125             ("txHwQueueCalc_BlocksNum(): number of required blocks is bigger than 255 = %d\n", memBlocks));
126   #endif
127 
128 	/* Copy the frag-threshold and HW blocks number to the descriptor. */
129     pPktCtrlBlk->txDescriptor.numMemBlks = (UINT8)memBlocks;
130 	pPktCtrlBlk->txDescriptor.fragThreshold = fragThreshold;
131 
132 	WLAN_REPORT_INFORMATION(pTxHwQueue->hReport, TX_HW_QUEUE_MODULE_LOG,
133 		("txHwQueueCalc_BlocksNum(): FragThresh=%d, NumBlks=%d, NumMpdus=%d, DataLen=%d\n",
134 		  fragThreshold, memBlocks, numMpdus, payloadDataLen));
135 }
136 
137 
138 
139 
140 /****************************************************************************
141  *               CalcFragThreshold()
142  ****************************************************************************
143    DESCRIPTION:  Calculates the frag threshold per frame according to the frag threshold
144                   defined by the user and the TxOp fragmentation (if WME is used).
145 
146    PARAMETERS:   pTxHwQueue - The module object.
147 				 pPktCtrlBlk	- The current packet control block (including descriptor).
148 
149    RETURNS:      The final fragmentation threshold.
150  ****************************************************************************/
CalcFragThreshold(TxHwQueueObj_t * pTxHwQueue,txCtrlBlkEntry_t * pPktCtrlBlk)151 static UINT16 CalcFragThreshold(TxHwQueueObj_t *pTxHwQueue, txCtrlBlkEntry_t *pPktCtrlBlk)
152 {
153     UINT32 txOpLimit;
154     UINT16 fragThreshold, uMaxHdrLen;
155     WlanParams_T *pWlanParams = &(pTxHwQueue->pWhalParams->WlanParams);
156     dot11_header_t *pDot11Hdr = (dot11_header_t*)((UINT8 *)pPktCtrlBlk->txPktParams.pFrame + TX_TOTAL_OFFSET_BEFORE_DATA);
157 
158     /*
159      *       It is prohibited by the standard to fragment multicast/broadcast
160      *       frames both in Infrastructure and Independent BSS types
161      */
162 
163     /* check for multicast packet in the destination address (address1 or address3)*/
164     if (MAC_MULTICAST(GET_DA_FROM_DOT11_HEADER_T(pDot11Hdr)))
165             return MAX_FRAG_THRESHOLD;
166 
167     /* For 4X don't fragment (use max frag threshold). */
168     if (pWlanParams->Enable4x)
169         return MAX_FRAG_THRESHOLD;
170 
171     /* Non-QOS mode */
172     if (IS_LEGACY_DATA (pPktCtrlBlk->txPktParams.headerFrameCtrl))
173     {
174         /* use "legacy" mode for the WLAN header length */
175         uMaxHdrLen = WLAN_HDR_LEN;
176         /* Use "legacy" fragmentation */
177         fragThreshold = pWlanParams->FragmentThreshold;
178     }
179 
180     /* QOS mode */
181     else
182     {
183         uMaxHdrLen = WLAN_QOS_HDR_LEN;
184 
185         txOpLimit = pTxHwQueue->pWhalParams->AcParams.ac[pPktCtrlBlk->txDescriptor.xmitQueue].txopLimit;
186 
187         if (txOpLimit == 0)
188         {
189             /*
190              * If working in WME and TXOP limit is not set for this AC -
191              * Use "legacy" fragmentation and substract the over head of the QoS header
192              */
193             /* TODO yuval - check why 2 is needed */
194             fragThreshold = pWlanParams->FragmentThreshold - DIFF_HEADER_LENGTH_LEGACY_TO_QOS;
195         }
196         else
197 
198         {
199             /*
200              * If TXOP-limit value is set (may require fragmentation for the time limit) -
201              * calculate the fragmentation threshold for the given TXOP-limit
202              */
203             fragThreshold = GetTxOpFragThreshold (pTxHwQueue, pPktCtrlBlk, txOpLimit, pWlanParams);
204         }
205     }
206 
207     /* If the frag threshold is below minimal frag, use minimal frag threshold */
208     if (fragThreshold < MIN_FRAG_THRESH)
209         fragThreshold = MIN_FRAG_THRESH;
210 
211     /* Subtract header length and CRC length */
212     fragThreshold -= uMaxHdrLen + FCS_LENGTH;
213 
214     /* Return the frag threshold. */
215     /* Note that security overheads are excluded as they are allowed to exceed the time limit. */
216     return fragThreshold;
217 }
218 
219 
220 
221 
222 
223 /****************************************************************************
224  *                      GetTxOpFragThreshold()
225  ****************************************************************************
226    DESCRIPTION:  Calculates the fragmentation threshold caused by the TxOpLimit.
227 
228    PARAMETERS:   pTxHwQueue - The module object.
229 				 pPktCtrlBlk	- The current packet control block (including descriptor structure).
230 
231    RETURNS:      The fragmentation threshold calculated for the TXOP limit.
232  ****************************************************************************/
GetTxOpFragThreshold(TxHwQueueObj_t * pTxHwQueue,txCtrlBlkEntry_t * pPktCtrlBlk,UINT16 txOpLimit,WlanParams_T * pWlanParams)233 static UINT16 GetTxOpFragThreshold(TxHwQueueObj_t *pTxHwQueue, txCtrlBlkEntry_t *pPktCtrlBlk,
234 								   UINT16 txOpLimit, WlanParams_T *pWlanParams)
235 {
236     UINT16  fragDataTime;
237 	UINT16  txOpFragThresh;
238 	UINT16	plcpHdrTimeBRate;
239 	UINT16	plcpHdrTime;
240 	UINT16  durationOverhead;
241 	UINT16  rateMbps;
242     rate_e	initialRate;
243 	BOOL	rtsSet;
244 	rate_e  ctrlFrameRate = pTxHwQueue->pWhalParams->BssInfoParams.txCtrlFrmRateDriverFormat;
245 	uint8   ackPolicy;
246 
247 	initialRate = ConvertRateTnetToDriver(pPktCtrlBlk->txDescriptor.rate);
248 
249 #ifdef TI_DBG
250 	if (initialRate == DRV_RATE_INVALID)
251 	{
252 		WLAN_REPORT_ERROR(pTxHwQueue->hReport, TX_HW_QUEUE_MODULE_LOG,
253 			("GetTxOpFragThreshold(): Unexpected Tx-Rate = %d\n", initialRate));
254 	}
255 #endif
256 
257     rateMbps = TxMemCalcRateValueTable[initialRate]; /* Convert from driver enum to Mbps value */
258 
259     /* Set the PLCP header time for B rates according to the preamble type. */
260 	if ( (pWlanParams->preamble == PREAMBLE_LONG) || (initialRate == DRV_RATE_1M) )
261         plcpHdrTimeBRate = LONG_PREAMBLE_MICROSECONDS;
262     else
263         plcpHdrTimeBRate = SHORT_PREAMBLE_MICROSECONDS;
264 
265 	/* Get PLCP header duration overhead. */
266 	if (initialRate >= DRV_RATE_6M)	/* If it's an OFDM rate. */
267 		plcpHdrTime = OFDM_PLCP_HDR_MICROSECONDS;
268     else
269         plcpHdrTime = plcpHdrTimeBRate;
270 
271 	durationOverhead = plcpHdrTime;
272 
273 	/* Add ACK overhead if not using No-ACK. */
274 	{
275         TxDescCtrl_t tmpTxDesc;
276         COPY_UNALIGNED_LONG(&tmpTxDesc, &(pPktCtrlBlk->txDescriptor.txAttr));
277         ackPolicy = tmpTxDesc.ackPolicy;
278     }
279     if ( !ackPolicy )
280 	{
281         durationOverhead += TxMemCalcAckDurationTable[initialRate] + plcpHdrTime;
282 		if (initialRate >= DRV_RATE_6M)
283 		    durationOverhead += OFDM_SIGNAL_EXT_MICROSECONDS; /* If OFDM add SIFS extra 6 uSec. */
284     }
285 
286 	/* If packet length bigger than RTS threshold, add RTS time to the duration overhead. */
287     if (pPktCtrlBlk->txDescriptor.length > pWlanParams->RtsThreshold)
288 	{
289         durationOverhead += RTS_FRAG_DATA_TIME;
290 		rtsSet = TRUE;
291 	}
292 	else
293 		rtsSet = FALSE;
294 
295 	/* If protection CTS required for OFDM packet or RTS needed, add CTS time to duration overhead. */
296     if ( (pWlanParams->CtsToSelf && (initialRate >= DRV_RATE_6M))  ||  rtsSet )
297         durationOverhead += TxMemCalcAckDurationTable[ctrlFrameRate] + plcpHdrTimeBRate;
298 
299 	/* If the TXOP time is longer than the packet overheads, get the delta (fragment body time). */
300     if (txOpLimit > durationOverhead)
301         fragDataTime = txOpLimit - durationOverhead;
302 
303 	/* Else, Can't get into the TXOP limit time. The minimal frag threshold (256) will be used. */
304     else
305 		fragDataTime = 0;
306 
307 	/* Calculate the fragmentation threshold in data bytes from the required duration and rate. */
308     txOpFragThresh = fragDataTime * rateMbps / BIT_TO_BYTE_FACTOR;
309 
310     /* If rate is 5.5M, a value of 55 is used so compensate for the 10 times factor. */
311     if (rateMbps == 55)
312         txOpFragThresh = txOpFragThresh / 10;
313 
314     /* Firmware requires the fragmentation threshold to be an EVEN number */
315     txOpFragThresh &= ~1;
316 
317 	WLAN_REPORT_INFORMATION(pTxHwQueue->hReport, TX_HW_QUEUE_MODULE_LOG,
318 		("GetTxOpFragThreshold(): FragThresh=%d, Rate=%d, TXOP=%d, Overhead=%d, NoACK=%d, CTS=%d, RTS=%d\n",
319 		  txOpFragThresh, initialRate, txOpLimit, durationOverhead, ackPolicy,
320 		  pWlanParams->CtsToSelf, rtsSet));
321 
322     return (txOpFragThresh);
323 }
324 
325 
326 
327 
328 /****************************************************************************
329  *                      ConvertRateTnetToDriver
330  ****************************************************************************
331  * DESCRIPTION: Convert the given rate from TNET format (Tx-descriptor) to driver format.
332  *
333  * INPUTS:	txDescRate - Rate value in Tx-descriptor format
334  *
335  * OUTPUT:	None
336  *
337  * RETURNS:	The converted rate in driver format.
338  ****************************************************************************/
ConvertRateTnetToDriver(UINT16 tnetRate)339 static rate_e ConvertRateTnetToDriver (UINT16 tnetRate)
340 {
341 	switch (tnetRate)
342 	{
343 		case HW_BIT_RATE_1MBPS:		return DRV_RATE_1M;
344 		case HW_BIT_RATE_2MBPS:		return DRV_RATE_2M;
345 		case HW_BIT_RATE_5_5MBPS:	return DRV_RATE_5_5M;
346 		case HW_BIT_RATE_6MBPS:		return DRV_RATE_6M;
347 		case HW_BIT_RATE_9MBPS:		return DRV_RATE_9M;
348 		case HW_BIT_RATE_11MBPS:	return DRV_RATE_11M;
349 		case HW_BIT_RATE_12MBPS:	return DRV_RATE_12M;
350 		case HW_BIT_RATE_18MBPS:	return DRV_RATE_18M;
351 		case HW_BIT_RATE_22MBPS:	return DRV_RATE_22M;
352 		case HW_BIT_RATE_24MBPS:	return DRV_RATE_24M;
353 		case HW_BIT_RATE_36MBPS:	return DRV_RATE_36M;
354 		case HW_BIT_RATE_48MBPS:	return DRV_RATE_48M;
355 		case HW_BIT_RATE_54MBPS:	return DRV_RATE_54M;
356 
357 		default:					return DRV_RATE_INVALID;
358 	}
359 }
360 
361 
362 
363 
364