Home | History | Annotate | Download | only in Tx_HW_Queue
      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  ****************************************************************************/
     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  ****************************************************************************/
    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  ****************************************************************************/
    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  ****************************************************************************/
    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