OSDN Git Service

original
[gb-231r1-is01/GB_2.3_IS01.git] / system / wlan / ti / sta_dk_4_0_4_32 / common / src / TNETW_Driver / Data_Srv / Tx_HW_Queue / txHwQueueCalc.c
diff --git a/system/wlan/ti/sta_dk_4_0_4_32/common/src/TNETW_Driver/Data_Srv/Tx_HW_Queue/txHwQueueCalc.c b/system/wlan/ti/sta_dk_4_0_4_32/common/src/TNETW_Driver/Data_Srv/Tx_HW_Queue/txHwQueueCalc.c
new file mode 100644 (file)
index 0000000..08d757f
--- /dev/null
@@ -0,0 +1,363 @@
+/****************************************************************************
+**+-----------------------------------------------------------------------+**
+**|                                                                       |**
+**| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved.      |**
+**| All rights reserved.                                                  |**
+**|                                                                       |**
+**| Redistribution and use in source and binary forms, with or without    |**
+**| modification, are permitted provided that the following conditions    |**
+**| are met:                                                              |**
+**|                                                                       |**
+**|  * Redistributions of source code must retain the above copyright     |**
+**|    notice, this list of conditions and the following disclaimer.      |**
+**|  * Redistributions in binary form must reproduce the above copyright  |**
+**|    notice, this list of conditions and the following disclaimer in    |**
+**|    the documentation and/or other materials provided with the         |**
+**|    distribution.                                                      |**
+**|  * Neither the name Texas Instruments nor the names of its            |**
+**|    contributors may be used to endorse or promote products derived    |**
+**|    from this software without specific prior written permission.      |**
+**|                                                                       |**
+**| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   |**
+**| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     |**
+**| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |**
+**| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  |**
+**| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |**
+**| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      |**
+**| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |**
+**| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |**
+**| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   |**
+**| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |**
+**| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  |**
+**|                                                                       |**
+**+-----------------------------------------------------------------------+**
+****************************************************************************/
+
+/****************************************************************************
+ *
+ *   MODULE:  txHwQueueCalc.c
+ *   
+ *   PURPOSE: 
+ *             Calculates the fragmentation threshold and number of HW memory blocks
+ *               required for the transmitted packet.
+ * 
+ *      DESCRIPTION:  
+ *   ============
+ *             This is a sub-module of the Tx-HW-Queue module.
+ *             When the Tx-HW-Queue is requested to allocate HW resources for a Tx 
+ *               packet (see txHwQueue_alloc()), it first calls this module to get
+ *               the number of HW memory blocks required for the packet.
+ *             First the fragmentation threshold is calculated, and then the number
+ *               blocks. Both values are written in the provided control block of
+ *               the packet (in the descriptor structure to be copied to the FW).
+ *
+ ****************************************************************************/
+
+#include "public_types.h"
+#include "802_11Defs.h"
+#include "ratesTypes.h"
+#include "whalCommon.h"
+#include "whalParams.h"
+#include "whalCtrl_api.h"
+#include "txHwQueue_api.h"  
+#include "utils.h"
+#include "txHwQueue.h"         /* Local definitions */
+#include "txHwQueueCalc.h"  /* Local definitions */
+
+
+
+
+/****************************************************************************
+ *                      txHwQueueCalc_BlocksNum()  
+ ****************************************************************************
+ * DESCRIPTION:        
+ * ============
+ *     Calculate the fragmentation threshold and the number of HW blocks
+ *       required for the whole FW Tx processing of the packet.
+ *
+ ****************************************************************************/
+void txHwQueueCalc_BlocksNum(TI_HANDLE hTxHwQueue, txCtrlBlkEntry_t *pPktCtrlBlk)
+{
+       TxHwQueueObj_t *pTxHwQueue = (TxHwQueueObj_t *)hTxHwQueue;
+    UINT16 memBlocks;
+    UINT16 numMpdus;
+    UINT16 numMemBlocksPerFullFrag;
+    UINT16 payloadDataLen;
+    UINT16 fragThreshold;
+
+       /* Calculate the fragmentation threshold. */
+       fragThreshold = CalcFragThreshold(pTxHwQueue, pPktCtrlBlk);
+
+    payloadDataLen  = pPktCtrlBlk->txDescriptor.length + MAX_MSDU_SECURITY_LENGTH; 
+
+    if (payloadDataLen > fragThreshold)
+       {
+#ifdef TI_DBG
+        if (fragThreshold == 0)
+        {
+            WLAN_OS_REPORT(("ERROR !!!!!!!!! fragThreshold==0 !!!!!!"));
+            return;
+        }
+#endif
+
+               numMemBlocksPerFullFrag = ((fragThreshold + MAX_MPDU_HEADER_AND_SECURITY) / HW_BLOCK_SIZE) + 1;
+        numMpdus = payloadDataLen / fragThreshold;
+        memBlocks = numMpdus * numMemBlocksPerFullFrag;
+        payloadDataLen -= numMpdus * fragThreshold;
+               numMpdus++;
+       }
+       else
+       {
+               numMemBlocksPerFullFrag = 0;
+               memBlocks = 0;
+               numMpdus = 1;
+       }
+
+    memBlocks += (payloadDataLen / HW_BLOCK_SIZE) + 1;
+
+       /* If fragmentation needed, add spare blocks for FW internal copy purposes. */
+    if (numMpdus > 1)
+        memBlocks += min(numMpdus, numMemBlocksPerFullFrag); 
+
+  #ifdef TI_DBG
+    if (memBlocks > 255)
+        WLAN_REPORT_ERROR (pTxHwQueue->hReport, TX_HW_QUEUE_MODULE_LOG,  
+            ("txHwQueueCalc_BlocksNum(): number of required blocks is bigger than 255 = %d\n", memBlocks));
+  #endif
+
+       /* Copy the frag-threshold and HW blocks number to the descriptor. */
+    pPktCtrlBlk->txDescriptor.numMemBlks = (UINT8)memBlocks;
+       pPktCtrlBlk->txDescriptor.fragThreshold = fragThreshold;
+
+       WLAN_REPORT_INFORMATION(pTxHwQueue->hReport, TX_HW_QUEUE_MODULE_LOG,  
+               ("txHwQueueCalc_BlocksNum(): FragThresh=%d, NumBlks=%d, NumMpdus=%d, DataLen=%d\n",
+                 fragThreshold, memBlocks, numMpdus, payloadDataLen));
+}
+
+
+
+
+/****************************************************************************
+ *               CalcFragThreshold()
+ ****************************************************************************
+   DESCRIPTION:  Calculates the frag threshold per frame according to the frag threshold 
+                  defined by the user and the TxOp fragmentation (if WME is used).
+
+   PARAMETERS:   pTxHwQueue - The module object.
+                                pPktCtrlBlk    - The current packet control block (including descriptor).
+   
+   RETURNS:      The final fragmentation threshold.
+ ****************************************************************************/
+static UINT16 CalcFragThreshold(TxHwQueueObj_t *pTxHwQueue, txCtrlBlkEntry_t *pPktCtrlBlk)
+{
+    UINT32 txOpLimit;
+    UINT16 fragThreshold, uMaxHdrLen;
+    WlanParams_T *pWlanParams = &(pTxHwQueue->pWhalParams->WlanParams);
+    dot11_header_t *pDot11Hdr = (dot11_header_t*)((UINT8 *)pPktCtrlBlk->txPktParams.pFrame + TX_TOTAL_OFFSET_BEFORE_DATA);
+
+    /* 
+     *       It is prohibited by the standard to fragment multicast/broadcast 
+     *       frames both in Infrastructure and Independent BSS types
+     */
+    
+    /* check for multicast packet in the destination address (address1 or address3)*/
+    if (MAC_MULTICAST(GET_DA_FROM_DOT11_HEADER_T(pDot11Hdr))) 
+            return MAX_FRAG_THRESHOLD;
+
+    /* For 4X don't fragment (use max frag threshold). */
+    if (pWlanParams->Enable4x)
+        return MAX_FRAG_THRESHOLD;
+
+    /* Non-QOS mode */
+    if (IS_LEGACY_DATA (pPktCtrlBlk->txPktParams.headerFrameCtrl))
+    {
+        /* use "legacy" mode for the WLAN header length */ 
+        uMaxHdrLen = WLAN_HDR_LEN;
+        /* Use "legacy" fragmentation */
+        fragThreshold = pWlanParams->FragmentThreshold;
+    } 
+
+    /* QOS mode */
+    else
+    {
+        uMaxHdrLen = WLAN_QOS_HDR_LEN;
+
+        txOpLimit = pTxHwQueue->pWhalParams->AcParams.ac[pPktCtrlBlk->txDescriptor.xmitQueue].txopLimit;
+
+        if (txOpLimit == 0)
+        {
+            /* 
+             * If working in WME and TXOP limit is not set for this AC - 
+             * Use "legacy" fragmentation and substract the over head of the QoS header
+             */
+            /* TODO yuval - check why 2 is needed */
+            fragThreshold = pWlanParams->FragmentThreshold - DIFF_HEADER_LENGTH_LEGACY_TO_QOS;
+        }
+        else
+
+        {
+            /*
+             * If TXOP-limit value is set (may require fragmentation for the time limit) -
+             * calculate the fragmentation threshold for the given TXOP-limit
+             */
+            fragThreshold = GetTxOpFragThreshold (pTxHwQueue, pPktCtrlBlk, txOpLimit, pWlanParams);
+        }
+    }
+
+    /* If the frag threshold is below minimal frag, use minimal frag threshold */
+    if (fragThreshold < MIN_FRAG_THRESH)
+        fragThreshold = MIN_FRAG_THRESH;
+
+    /* Subtract header length and CRC length */
+    fragThreshold -= uMaxHdrLen + FCS_LENGTH;
+
+    /* Return the frag threshold. */
+    /* Note that security overheads are excluded as they are allowed to exceed the time limit. */
+    return fragThreshold;
+}
+
+
+
+
+
+/****************************************************************************
+ *                      GetTxOpFragThreshold()
+ ****************************************************************************
+   DESCRIPTION:  Calculates the fragmentation threshold caused by the TxOpLimit.
+
+   PARAMETERS:   pTxHwQueue - The module object.
+                                pPktCtrlBlk    - The current packet control block (including descriptor structure).
+   
+   RETURNS:      The fragmentation threshold calculated for the TXOP limit.
+ ****************************************************************************/
+static UINT16 GetTxOpFragThreshold(TxHwQueueObj_t *pTxHwQueue, txCtrlBlkEntry_t *pPktCtrlBlk, 
+                                                                  UINT16 txOpLimit, WlanParams_T *pWlanParams)
+{
+    UINT16  fragDataTime; 
+       UINT16  txOpFragThresh; 
+       UINT16  plcpHdrTimeBRate;
+       UINT16  plcpHdrTime;
+       UINT16  durationOverhead;
+       UINT16  rateMbps; 
+    rate_e     initialRate;
+       BOOL    rtsSet;
+       rate_e  ctrlFrameRate = pTxHwQueue->pWhalParams->BssInfoParams.txCtrlFrmRateDriverFormat;
+       uint8   ackPolicy;
+
+       initialRate = ConvertRateTnetToDriver(pPktCtrlBlk->txDescriptor.rate);
+
+#ifdef TI_DBG
+       if (initialRate == DRV_RATE_INVALID)
+       {
+               WLAN_REPORT_ERROR(pTxHwQueue->hReport, TX_HW_QUEUE_MODULE_LOG,  
+                       ("GetTxOpFragThreshold(): Unexpected Tx-Rate = %d\n", initialRate));
+       }
+#endif
+
+    rateMbps = TxMemCalcRateValueTable[initialRate]; /* Convert from driver enum to Mbps value */
+
+    /* Set the PLCP header time for B rates according to the preamble type. */
+       if ( (pWlanParams->preamble == PREAMBLE_LONG) || (initialRate == DRV_RATE_1M) )
+        plcpHdrTimeBRate = LONG_PREAMBLE_MICROSECONDS;
+    else
+        plcpHdrTimeBRate = SHORT_PREAMBLE_MICROSECONDS;
+
+       /* Get PLCP header duration overhead. */
+       if (initialRate >= DRV_RATE_6M) /* If it's an OFDM rate. */
+               plcpHdrTime = OFDM_PLCP_HDR_MICROSECONDS;
+    else
+        plcpHdrTime = plcpHdrTimeBRate;
+
+       durationOverhead = plcpHdrTime;
+       
+       /* Add ACK overhead if not using No-ACK. */
+       {    
+        TxDescCtrl_t tmpTxDesc;
+        COPY_UNALIGNED_LONG(&tmpTxDesc, &(pPktCtrlBlk->txDescriptor.txAttr));
+        ackPolicy = tmpTxDesc.ackPolicy;
+    }
+    if ( !ackPolicy )
+       {
+        durationOverhead += TxMemCalcAckDurationTable[initialRate] + plcpHdrTime; 
+               if (initialRate >= DRV_RATE_6M)
+                   durationOverhead += OFDM_SIGNAL_EXT_MICROSECONDS; /* If OFDM add SIFS extra 6 uSec. */
+    }
+
+       /* If packet length bigger than RTS threshold, add RTS time to the duration overhead. */
+    if (pPktCtrlBlk->txDescriptor.length > pWlanParams->RtsThreshold)
+       {
+        durationOverhead += RTS_FRAG_DATA_TIME;
+               rtsSet = TRUE;
+       }
+       else
+               rtsSet = FALSE;
+
+       /* If protection CTS required for OFDM packet or RTS needed, add CTS time to duration overhead. */
+    if ( (pWlanParams->CtsToSelf && (initialRate >= DRV_RATE_6M))  ||  rtsSet )
+        durationOverhead += TxMemCalcAckDurationTable[ctrlFrameRate] + plcpHdrTimeBRate;
+       
+       /* If the TXOP time is longer than the packet overheads, get the delta (fragment body time). */
+    if (txOpLimit > durationOverhead)
+        fragDataTime = txOpLimit - durationOverhead;
+       
+       /* Else, Can't get into the TXOP limit time. The minimal frag threshold (256) will be used. */
+    else
+               fragDataTime = 0;  
+
+       /* Calculate the fragmentation threshold in data bytes from the required duration and rate. */
+    txOpFragThresh = fragDataTime * rateMbps / BIT_TO_BYTE_FACTOR;
+
+    /* If rate is 5.5M, a value of 55 is used so compensate for the 10 times factor. */
+    if (rateMbps == 55) 
+        txOpFragThresh = txOpFragThresh / 10;
+
+    /* Firmware requires the fragmentation threshold to be an EVEN number */
+    txOpFragThresh &= ~1;
+
+       WLAN_REPORT_INFORMATION(pTxHwQueue->hReport, TX_HW_QUEUE_MODULE_LOG,  
+               ("GetTxOpFragThreshold(): FragThresh=%d, Rate=%d, TXOP=%d, Overhead=%d, NoACK=%d, CTS=%d, RTS=%d\n",
+                 txOpFragThresh, initialRate, txOpLimit, durationOverhead, ackPolicy,
+                 pWlanParams->CtsToSelf, rtsSet));
+    
+    return (txOpFragThresh);
+}
+
+
+
+
+/****************************************************************************
+ *                      ConvertRateTnetToDriver
+ ****************************************************************************
+ * DESCRIPTION: Convert the given rate from TNET format (Tx-descriptor) to driver format.
+ *                     
+ * INPUTS:     txDescRate - Rate value in Tx-descriptor format
+ * 
+ * OUTPUT:     None
+ * 
+ * RETURNS:    The converted rate in driver format. 
+ ****************************************************************************/
+static rate_e ConvertRateTnetToDriver (UINT16 tnetRate)
+{
+       switch (tnetRate)
+       {
+               case HW_BIT_RATE_1MBPS:         return DRV_RATE_1M;
+               case HW_BIT_RATE_2MBPS:         return DRV_RATE_2M;
+               case HW_BIT_RATE_5_5MBPS:       return DRV_RATE_5_5M;
+               case HW_BIT_RATE_6MBPS:         return DRV_RATE_6M;
+               case HW_BIT_RATE_9MBPS:         return DRV_RATE_9M;
+               case HW_BIT_RATE_11MBPS:        return DRV_RATE_11M;
+               case HW_BIT_RATE_12MBPS:        return DRV_RATE_12M;
+               case HW_BIT_RATE_18MBPS:        return DRV_RATE_18M;
+               case HW_BIT_RATE_22MBPS:        return DRV_RATE_22M;
+               case HW_BIT_RATE_24MBPS:        return DRV_RATE_24M;
+               case HW_BIT_RATE_36MBPS:        return DRV_RATE_36M;
+               case HW_BIT_RATE_48MBPS:        return DRV_RATE_48M;
+               case HW_BIT_RATE_54MBPS:        return DRV_RATE_54M;
+
+               default:                                        return DRV_RATE_INVALID;
+       }
+}
+
+
+
+