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