PageRenderTime 54ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/drivers/net/wireless/tiwlan1251/common/src/TNETW_Driver/Data_Srv/Tx_HW_Queue/txHwQueueCalc.c

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