Home | History | Annotate | Download | only in 4X
      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:													   */
     39 /*		PURPOSE:		 						   */
     40 /*																		   */
     41 /***************************************************************************/
     42 #include "fourX.h"
     43 #include "report.h"
     44 #include "osApi.h"
     45 #include "utils.h"
     46 #include "802_11Defs.h"
     47 
     48 
     49 static Wlan4XType_t fourX_parseRxFrame(fourX_t* pFourX, mem_MSDU_T* msduPtr);
     50 
     51 static TI_STATUS fourX_MakeConcatDecision(fourX_t*				pFourX,
     52 										   MsduList_t*			pMsduList,
     53 										   hwTxInformation_t*	pHwTxInformation,
     54 										   UINT32					numOfReadyMsdu,
     55 										   UINT16*				concatFlags,
     56                                            UINT32*              numOfMsduToConcat);
     57 
     58 static TI_STATUS fourX_prepareMsduListToConcat(fourX_t*		pFourX,
     59 											   mem_MSDU_T**	returnMsduPtr,
     60 											   MsduList_t*  pMsduList,
     61                                                UINT32       maxNumMsduToConcat);
     62 
     63 
     64 /*************************************************************************
     65 *                        concat_create                                 *
     66 **************************************************************************
     67 * DESCRIPTION:	This function initializes the Ctrl data module.
     68 *
     69 * INPUT:		hOs - handle to Os Abstraction Layer
     70 *
     71 * OUTPUT:		TxCmplt_CB - call back function that return to configMngr
     72 *				in order to register in the Hal
     73 *
     74 * RETURN:		Handle to the allocated Ctrl data control block
     75 ************************************************************************/
     76 
     77 fourX_t* fourX_create(TI_HANDLE hOs)
     78 {
     79 	fourX_t*			pFourX;
     80 	deConcatenator_t*	pDeConcatenator;
     81 	concatenator_t*		pConcatenator;
     82 	ackEmul_t*			pAckEmul;
     83 
     84 
     85 	if( hOs  == NULL )
     86 	{
     87 	    WLAN_OS_REPORT(("FATAL ERROR: fourX_create(): OS handle Error - Aborting\n"));
     88 		return NULL;
     89 	}
     90 
     91 	/* alocate concatenator block */
     92 	pFourX = os_memoryAlloc(hOs, (sizeof(fourX_t)));
     93 
     94 	/* create 4x sub moduls */
     95 	pConcatenator = concat_create(hOs);
     96 	pDeConcatenator = deConcat_create(hOs);
     97 	pAckEmul = ackEmul_create(hOs);
     98 
     99 
    100 	if ( (!pFourX) || (!pConcatenator) || (!pDeConcatenator) || (!pAckEmul))
    101 	{
    102 		utils_nullMemoryFree(hOs, pDeConcatenator, sizeof(deConcatenator_t));
    103 		utils_nullMemoryFree(hOs, pConcatenator, sizeof(concatenator_t));
    104 		utils_nullMemoryFree(hOs, pAckEmul, sizeof(ackEmul_t));
    105 		utils_nullMemoryFree(hOs, pFourX, sizeof(fourX_t));
    106 	    WLAN_OS_REPORT(("FATAL ERROR: fourX_create(): Error Creating fourX module- Aborting\n"));
    107 		return(NULL);
    108 	}
    109 
    110 	/* reset control module control block */
    111 	os_memoryZero(hOs, pFourX, (sizeof(fourX_t)));
    112 
    113 	pFourX->pConcatenator = pConcatenator;
    114 	pFourX->pDeConcatenator = pDeConcatenator;
    115 	pFourX->pAckEmul = pAckEmul;
    116 
    117 	pFourX->hOs = hOs;
    118 
    119 	return(pFourX);
    120 }
    121 
    122 /***************************************************************************
    123 *							ctrlData_config				                   *
    124 ****************************************************************************
    125 * DESCRIPTION:	This function configures the Ctrl Data module
    126 *
    127 * INPUTS:		hCtrlData - The object
    128 *				hOs - Handle to the Os Abstraction Layer
    129 *				hReport - Handle to the Report object
    130 * 				ctrlDataInitParams - pointer to Ctrl module init parameters
    131 * OUTPUT:
    132 *
    133 * RETURNS:		OK - Configuration succesfull
    134 *				NOK - Configuration unsuccesfull
    135 ***************************************************************************/
    136 TI_STATUS fourX_config(fourX_t*				pFourX,
    137 					   TI_HANDLE			hOs,
    138 					   TI_HANDLE			hReport,
    139 					   TI_HANDLE			hMemMngr,
    140 					   TI_HANDLE			hWhalCtrl,
    141 					   TI_HANDLE			hTxData,
    142 					   fourXInitParams_t*	fourXInitParams)
    143 {
    144 	/* check parameters validity */
    145 	if( (pFourX == NULL) || (hOs == NULL) || (hReport == NULL) ||
    146 		(hMemMngr == NULL) || (hWhalCtrl == NULL) || (hTxData == NULL))
    147 	{
    148 	    WLAN_OS_REPORT(("FATAL ERROR: fourX_config(): Parameters Error - Aborting\n"));
    149 		return NOK;
    150 	}
    151 
    152 	/* set objects handles */
    153 	pFourX->hOs = hOs;
    154 	pFourX->hReport = hReport;
    155 	pFourX->hMemMngr = hMemMngr;
    156 	pFourX->hWhalCtrl = hWhalCtrl;
    157 	pFourX->hTxData = hTxData;
    158 
    159 	/* configure 4x parameters - TODO USE fourXInitParams */
    160 	pFourX->desiredConcatenationEnable = DESIRED_CONCATENATION_ENABLE_DEF;
    161 	pFourX->desiredCWMinEnable = DESIRED_CWMIN_ENABLE_DEF;
    162 	pFourX->desiredCWComboEnable = DESIRED_CWCOMBO_ENABLE_DEF;
    163 	pFourX->desiredAckEmulationEnable = DESIRED_ACKEMULATION_ENABLE_DEF;
    164 	pFourX->desiredERP_ProtectionEnable = DESIRED_ERP_PROTECTION_ENABLE_DEF;
    165 	pFourX->desiredMaxConcatSize = MAX_CONCAT_SIZE_DEF;
    166 	pFourX->desiredCWMin = CW_MIN_DEF;
    167 	pFourX->desiredCWMax = CW_MAX_DEF;
    168 
    169 
    170 	/* configure 4x sub modules */
    171 	concat_config(pFourX->pConcatenator, hOs, hReport, hMemMngr);
    172 	deConcat_config(pFourX->pDeConcatenator, hOs, hReport, hMemMngr);
    173 	ackEmul_config(pFourX->pAckEmul,hWhalCtrl,hOs,hReport,hMemMngr);
    174 
    175 
    176 	WLAN_REPORT_INIT(pFourX->hReport, FOUR_X_MODULE_LOG,
    177 		(".....fouorX configured successfully\n"));
    178 
    179 	return OK;
    180 }
    181 
    182 /***************************************************************************
    183 *							ctrlData_unLoad				                   *
    184 ****************************************************************************
    185 * DESCRIPTION:	This function unload the Ctrl data module.
    186 *
    187 * INPUTS:		hCtrlData - the object
    188 *
    189 * OUTPUT:
    190 *
    191 * RETURNS:		OK - Unload succesfull
    192 *				NOK - Unload unsuccesfull
    193 ***************************************************************************/
    194 
    195 TI_STATUS fourX_destroy(fourX_t* pFourX)
    196 {
    197 	concat_destroy(pFourX->pConcatenator);
    198 	deConcat_destroy(pFourX->pDeConcatenator);
    199 	ackEmul_destroy(pFourX->pAckEmul);
    200 
    201 	/* free control module controll block */
    202 	os_memoryFree(pFourX->hOs, pFourX, sizeof(fourX_t));
    203 
    204 	return OK;
    205 }
    206 
    207 
    208 static Wlan4XType_t fourX_parseRxFrame(fourX_t* pFourX, mem_MSDU_T* msduPtr)
    209 {
    210     dot114xMsdu_t*	pdot114xHeader;
    211 	UINT8			tiSnapDataArray[8] = {0xAA,0xAA,0x03,0x08,0x00,0x28,0x60,0xD0};
    212 
    213 	/* Check frame len validity */
    214 	if(msduPtr->dataLen < sizeof(dot114xMsdu_t))
    215 		return NOT_4X_MSDU;
    216 
    217     pdot114xHeader = (dot114xMsdu_t*)memMgr_BufData(msduPtr->firstBDPtr);
    218 
    219     /*
    220        Verify a TI SNAP header.
    221     */
    222     if( os_memoryCompare(pFourX->hOs,
    223 						 (void*)&(pdot114xHeader->msduHeader.snapHeader),
    224 						 tiSnapDataArray,
    225 						 sizeof(Wlan_LlcHeader_T)) != 0)
    226 	{
    227 		return NOT_4X_MSDU;
    228 	}
    229 
    230     switch (pdot114xHeader->header4x.type)
    231 	{
    232 
    233     case CONCATENATION :
    234         return CONCATENATION;
    235 /*		break; - unreachable*/
    236 
    237     case MANAGMENT_4X :
    238         return MANAGMENT_4X;
    239 /*		break; - unreachable*/
    240 
    241     default:
    242 		return NOT_4X_MSDU;
    243 /*		break; - unreachable*/
    244 
    245     }
    246 }
    247 
    248 TI_STATUS fourX_rxMsdu(fourX_t*	pFourX, mem_MSDU_T**	rxMsduPtr)
    249 {
    250     Wlan4XType_t	type4xMsdu;
    251 	mem_MSDU_T*		currMsduPtr;
    252 
    253 	type4xMsdu = fourX_parseRxFrame(pFourX, *rxMsduPtr);
    254 
    255 	switch (type4xMsdu)
    256 	{
    257 		case CONCATENATION :
    258 		   /*
    259 			* Deconcatenate Msdu
    260 			*/
    261             WLAN_REPORT_INFORMATION(pFourX->hReport, FOUR_X_MODULE_LOG,
    262 			        (" Received Concat msdu \n"));
    263 			if(deConcat_deConcatMsdu(pFourX->pDeConcatenator, rxMsduPtr) != OK)
    264 			{
    265 		        WLAN_REPORT_ERROR(pFourX->hReport, FOUR_X_MODULE_LOG,
    266 			        (" Failed to deconcat packet \n"));
    267 
    268 				return NOK;
    269 			}
    270 			break;
    271 
    272 		case MANAGMENT_4X :
    273 			break;
    274 
    275 		default:
    276 			break;
    277 
    278     }
    279 
    280 	if(pFourX->ackEmulationEnable)
    281 	{
    282 		/* call ack emulation for each packet */
    283 		currMsduPtr = *rxMsduPtr;
    284 		while(currMsduPtr)
    285 		{
    286 			wdrv_ackEmulationRxPacket(pFourX->pAckEmul, currMsduPtr);
    287 			currMsduPtr = currMsduPtr->nextMSDUinList;
    288 		}
    289 	}
    290 	return OK;
    291 
    292 }
    293 
    294 #define NUM_MSDU_TO_COPY 8
    295 
    296 /***************************************************************************
    297 *							fourX_CopyReplace
    298 ****************************************************************************
    299 * DESCRIPTION:	This function copy OS data blocks to local data blocks
    300 *				in the MSDU in order to release OS resources and to enable
    301 *				high stream of data from the OS
    302 *
    303 * INPUTS:
    304 *
    305 * OUTPUT:
    306 *
    307 * RETURNS:
    308 ***************************************************************************/
    309 TI_STATUS fourX_CopyReplace(fourX_t* pFourX, mem_MSDU_T **pMsdu, MsduList_t *pMsduList, mem_MSDU_T **pNewMsdu)
    310 {
    311 	mem_MSDU_T		*pOrigMsdu;
    312 
    313 	pOrigMsdu = (*pMsdu);
    314 
    315 	/*
    316 	 * The copy is to new msdu pointed by pMsdu
    317 	 */
    318 	if(txData_copyPacketToMsdu(pFourX->hTxData, pMsdu, 0 /* dont FreeOldMsdu */) != OK)
    319 	{
    320 		/* no msdu to transmit */
    321 		WLAN_REPORT_INFORMATION(pFourX->hReport, FOUR_X_MODULE_LOG,
    322 			(" fourX_CopyReplace() : txData_copyPacketToMsdu FAILED  \n"));
    323 
    324 		return NOK;
    325 	}
    326 
    327 	/*
    328 	 * Still use the old Msdu with its pointers, so swap the BDs of the new and the orig Msdu
    329 	 */
    330 	wlan_memMngrSwapMsdu(pFourX->hMemMngr, pOrigMsdu, (*pMsdu));
    331 
    332 	/* return the new msdu to free later */
    333 	(*pNewMsdu) = (*pMsdu);
    334 	/* use the orig Msdu */
    335 	(*pMsdu) = pOrigMsdu;
    336 
    337 	return OK;
    338 }
    339 
    340 
    341 /***************************************************************************
    342 *							fourX_CopyOsData
    343 ****************************************************************************
    344 * DESCRIPTION:	This function scan the Msdu list and copy OS data blocks to
    345 *				local data blocks .
    346 *				in the MSDU in order to release OS resources and to enable
    347 *				high stream of data from the OS
    348 *
    349 * INPUTS:
    350 *
    351 * OUTPUT:
    352 *
    353 * RETURNS:
    354 ***************************************************************************/
    355 UINT32 fourX_CopyOsData(fourX_t* pFourX, MsduList_t *pMsduList)
    356 {
    357 	int NumMsduToCopy = 0;
    358 	mem_MSDU_T *pMsdu;
    359 	mem_MSDU_T *pNewMsdu=NULL;
    360 	mem_MSDU_T *pMsduFreeList=NULL;
    361 	mem_MSDU_T *pMsduFreeCurr=NULL;
    362 	mem_MSDU_T *pKeepNext=NULL;
    363 	int i;
    364 	int NumOfCopiedPackets=0;
    365 
    366 	os_protectLock(pMsduList->hOs, pMsduList->hCriticalSectionProtect); /* START OF CRITICAL SECTION */
    367 
    368 	if (pMsduList->CurrNumOfMsdu == 0)
    369 	{
    370 		pFourX->counters.count6 = 0;
    371 		pFourX->counters.count7 = 0;
    372 		os_protectUnlock(pMsduList->hOs, pMsduList->hCriticalSectionProtect); /* END OF CRITICAL SECTION */
    373 		return 0;
    374 	}
    375 
    376 	/*
    377 	 * Find how many msdu to copy
    378 	 */
    379 	if (pMsduList->CurrNumOfMsdu <= NUM_MSDU_TO_COPY)
    380 		NumMsduToCopy = pMsduList->CurrNumOfMsdu;
    381 	else
    382 		NumMsduToCopy = NUM_MSDU_TO_COPY;
    383 
    384 	pMsdu=pMsduList->first;
    385 
    386 	/*
    387 	 * Start the copy
    388 	 */
    389 	for (i=0; (i<NumMsduToCopy) ; i++)
    390 	{
    391 		if (pMsdu == NULL)
    392 		{
    393 			WLAN_REPORT_ERROR(pFourX->hReport, FOUR_X_MODULE_LOG,
    394 				(" fourX_CopyMsdu() : fourX_CopyReplace FAILED, pMsdu is NULL i=%d, Num=%d (Actual=%d) \n", i, NumMsduToCopy, pMsduList->CurrNumOfMsdu));
    395 
    396 			break;
    397 		}
    398 		/*
    399 		 * Already copied - skip it
    400 		 */
    401 		if (pMsdu->freeFunc == NULL)
    402 		{
    403 			pMsdu=pMsdu->nextMSDUinList;
    404 			NumOfCopiedPackets++;
    405 			continue;
    406 		}
    407 
    408 		WLAN_REPORT_INFORMATION(pFourX->hReport, FOUR_X_MODULE_LOG,
    409 			(" fourX_CopyMsdu() : i=%d, CopyReplace 0x%x\n", i , pMsdu));
    410 
    411 		/*
    412 		 * Copy and replace in the list
    413 		 */
    414 		if(fourX_CopyReplace(pFourX, &pMsdu, pMsduList, &pNewMsdu) != OK)
    415 		{
    416 			/* no msdu to transmit */
    417 			WLAN_REPORT_ERROR(pFourX->hReport, FOUR_X_MODULE_LOG,
    418 				(" fourX_CopyMsdu() : fourX_CopyReplace FAILED  \n"));
    419 
    420 			break;
    421 		}
    422 
    423 		/*
    424 		 * Enter the new Msdu to the free list
    425 		 */
    426 		if (pMsduFreeList == NULL)
    427 		{
    428 			pMsduFreeList = pNewMsdu;
    429 		}
    430 		else
    431 		{
    432 			pMsduFreeCurr = pMsduFreeList;
    433 			while (pMsduFreeCurr->nextMSDUinList != NULL)
    434 				pMsduFreeCurr = pMsduFreeCurr->nextMSDUinList;
    435 			pMsduFreeCurr->nextMSDUinList = pNewMsdu;
    436 		}
    437 		pNewMsdu->nextMSDUinList = NULL;
    438 
    439 		/* copy the next msdu */
    440 		pMsdu=pMsdu->nextMSDUinList;
    441 		NumOfCopiedPackets++;
    442 	}
    443 
    444 	pFourX->counters.count6 = pMsduList->CurrNumOfMsdu;
    445 	pFourX->counters.count7 = i;
    446 
    447 	/* !!!! This is the right place for the unlock */
    448 	os_protectUnlock(pMsduList->hOs, pMsduList->hCriticalSectionProtect); /* END OF CRITICAL SECTION */
    449 
    450 	/*
    451 	 * free loop, do not call the free inside lock !!!
    452 	 */
    453 	pMsduFreeCurr = pMsduFreeList;
    454 	while (pMsduFreeCurr != NULL)
    455 	{
    456 		pKeepNext = pMsduFreeCurr->nextMSDUinList;
    457 
    458 		wlan_memMngrFreeMSDU(pFourX->hMemMngr, memMgr_MsduHandle(pMsduFreeCurr));
    459 
    460 		pMsduFreeCurr=pKeepNext;
    461 	}
    462 
    463 	return NumOfCopiedPackets;
    464 }
    465 
    466 
    467 
    468 TI_STATUS fourX_txMsduDeQueue(fourX_t*				pFourX,
    469 							  mem_MSDU_T**			returnMsduPtr,
    470 							  MsduList_t*			pMsduList,
    471 							  hwTxInformation_t*	pHwTxInformation)
    472 {
    473 	TI_STATUS		status;
    474 	mem_MSDU_T*		firstMsduPtr;
    475 	UINT16			concatFlags = 0;
    476     UINT32          numOfMsduToConcat;
    477 	UINT32			numMsdu = 0;
    478 
    479 	*returnMsduPtr = NULL;
    480 
    481 
    482 #ifdef NO_COPY_NDIS_BUFFERS
    483 	/*
    484 	 * Scan the Msdu list and copy OS data blocks to local data blocks .
    485 	 * in the MSDU in order to release OS resources and to enable
    486 	 * high stream of data from the OS.
    487 	 */
    488 	numMsdu = fourX_CopyOsData(pFourX, pMsduList);
    489 	/* This function copied up to 8 or numOfMsdu in list packets from OS to Shared memory
    490 	 * As there is NDISfreeFunc after the copy, New un-copied packets can enter the msduList,
    491 	 * but the scheduler was blocked from entering the send again.
    492 	 */
    493 #else
    494 
    495 	if (pMsduList->CurrNumOfMsdu < NUM_MSDU_TO_COPY )
    496 		numMsdu = pMsduList->CurrNumOfMsdu;
    497 	else
    498 		numMsdu = NUM_MSDU_TO_COPY;
    499 #endif
    500 
    501 	/*if(pFourX->concatenationEnable != TRUE)*/
    502 	status = fourX_MakeConcatDecision(pFourX,pMsduList,pHwTxInformation,numMsdu,
    503                                        &concatFlags,&numOfMsduToConcat);
    504 
    505 
    506 	switch(status)
    507 	{
    508 	case MAKE_CONCATENATION:
    509 
    510 	   /*
    511 		* Make Concatenation
    512 		*/
    513 
    514 		fourX_prepareMsduListToConcat(pFourX,
    515 									  &firstMsduPtr,
    516 									  pMsduList,
    517                                       numOfMsduToConcat);
    518 
    519 		if(firstMsduPtr == NULL)
    520 			return NOK;
    521 
    522 
    523 		return concat_concatMsduList(pFourX->pConcatenator,
    524 							  firstMsduPtr,
    525 							  returnMsduPtr,
    526 							  concatFlags);
    527 
    528 
    529 	case SEND_ONE_MSDU:
    530 
    531 	   /*
    532 		* Send Only One Msdu
    533 		*/
    534 
    535 		if((msduList_GetFirst( pMsduList, returnMsduPtr )) != OK)
    536 		{
    537 			/* msdu list is empty - should never reach here */
    538 			WLAN_REPORT_ERROR(pFourX->hReport, FOUR_X_MODULE_LOG,
    539 				(" fourX_txMsduDeQueue:msduList_GetFirst() : No Msdu to get in list \n"));
    540 
    541 			return NOK;
    542 		}
    543 
    544 		return OK;
    545 
    546 	case DO_NOT_SEND_MSDU:
    547 
    548 	   /*
    549 		* Don't Send any Msdu
    550 		*/
    551 
    552 		return NOK;
    553 
    554 	default:
    555 		break;
    556 
    557 	}
    558 	return OK;
    559 }
    560 
    561 TI_STATUS fourX_txMsduBeforInsertToQueue(fourX_t* pFourX,
    562 										 mem_MSDU_T** msduPtr)
    563 {
    564 /* no ACK emulation !!!!!!!!!!!!!!!!!! */
    565 #if 0
    566 	UINT32 discardPacket;
    567 	if(pFourX->ackEmulationEnable)
    568 	{
    569 		wdrv_ackEmulationTxPacket(pFourX->pAckEmul, *msduPtr, &discardPacket);
    570 		if (discardPacket == TRUE)
    571 		{
    572 			wlan_memMngrFreeMSDU(pFourX->hMemMngr, (*msduPtr)->handle);
    573 			(*msduPtr) = NULL;
    574 			return OK;
    575 		}
    576 	}
    577 #endif
    578 	return OK;
    579 }
    580 
    581 static TI_STATUS fourX_prepareMsduListToConcat(fourX_t*		pFourX,
    582 											   mem_MSDU_T**	returnMsduPtr,
    583 											   MsduList_t*	pMsduList,
    584                                                UINT32       maxNumMsduToConcat)
    585 {
    586 	mem_MSDU_T*		currentMsduPtr;
    587 	mem_MSDU_T*		PrevMsduPtr=NULL;
    588 	UINT32			totalLen = 0;
    589 	BOOL			firsdMsduInList = TRUE;
    590 	UINT32			numOfMsdu = 0;
    591 
    592 
    593 	*returnMsduPtr = NULL;
    594 
    595 	while(maxNumMsduToConcat--)
    596 	{
    597 		/* prepare a link list of msdu in the concatenator format */
    598 		if((msduList_WatchFirst( pMsduList, &currentMsduPtr )) != OK)
    599 		{
    600 			/* msdu list is empty - can return now */
    601 			WLAN_REPORT_INFORMATION(pFourX->hReport, FOUR_X_MODULE_LOG,
    602 				(" fourX_txMsduDeQueue: msduList_WatchFirst() : No Msdu to watch \n"));
    603 			break;
    604 		}
    605 		totalLen += currentMsduPtr->dataLen;
    606 
    607 		if(totalLen > 4032/*pFourX->currentMaxConcatSize*/)
    608 			break;
    609 
    610 		if((msduList_GetFirst( pMsduList, &currentMsduPtr )) != OK)
    611 		{
    612 			/* msdu list is empty - should never reach here */
    613 			WLAN_REPORT_ERROR(pFourX->hReport, FOUR_X_MODULE_LOG,
    614 				(" fourX_txMsduDeQueue:msduList_GetFirst() : No Msdu to get in list \n"));
    615 			break;
    616 		}
    617 
    618 		/* In this phase, the free func should be NULL !!!!!!!!!!! */
    619 		if (currentMsduPtr->freeFunc)
    620 		{
    621 			WLAN_REPORT_ERROR(pFourX->hReport, FOUR_X_MODULE_LOG,
    622 				(" fourX_txMsduDeQueue:msduList_GetFirst() : fourX_prepareMsduListToConcat, free funct is not NULL !!!!!!!\n"));
    623 		}
    624 
    625 		numOfMsdu++;
    626 
    627 		if(firsdMsduInList == TRUE)
    628 		{
    629 			*returnMsduPtr = currentMsduPtr;
    630 			firsdMsduInList = FALSE;
    631 		}
    632 		else
    633 		{
    634 			PrevMsduPtr->nextMSDUinList = currentMsduPtr;
    635 		}
    636 
    637 		PrevMsduPtr = currentMsduPtr;
    638 	}
    639 
    640 	return OK;
    641 }
    642 
    643 static TI_STATUS fourX_MakeConcatDecision(fourX_t*				pFourX,
    644 										   MsduList_t*			pMsduList,
    645 										   hwTxInformation_t*	pHwTxInformation,
    646 										   UINT32					numOfReadyMsdu,
    647 										   UINT16*				concatFlags,
    648                                            UINT32*              numOfMsduToConcat)
    649 {
    650 	memMgrResources_t memMgrResources;
    651 
    652 #ifdef TNETW_MASTER_MODE
    653 	UINT32 limitResourcees;
    654 #endif
    655 
    656 	*numOfMsduToConcat = 0;
    657 
    658 	/* get MemoryMgr resources for concatenation */
    659 	wlan_memMngrGetMemMgrResources(pFourX->hMemMngr, &memMgrResources);
    660 
    661 #ifdef TNETW_MASTER_MODE
    662 	limitResourcees = MIN(memMgrResources.numOfFreeBufPool2 ,(MIN(memMgrResources.numOfFreeBufPool1-1 , pHwTxInformation->hwNumOfFreeBDs)));
    663 
    664 
    665 
    666 	/* No free space in HW to send */
    667     if( (pHwTxInformation->hwNumOfFreeMsdu == 0) || (limitResourcees < 2) )
    668     {
    669         pFourX->counters.count1++;
    670         return DO_NOT_SEND_MSDU;
    671 	}
    672 
    673     /*
    674 	 * Phase 1: At least 3 waiting msdu for concat (and enough space in HW)
    675 	 * --------------------------------------------------------------------
    676 	 * In case there are 2 msdu the decision will be later
    677      * We have resources to send, decide if to concat, send single or wait.
    678      */
    679     if(  numOfReadyMsdu >= 3 )
    680     {
    681         pFourX->counters.count2++;
    682         /* We have enough msdus to concat. */
    683 		*concatFlags = *concatFlags | WLAN_4X_CONCAT_MORE_BIT;
    684 
    685 		/* not enough free bd to send or concat - need at least 2 msdu and 2 bd for each + concat header bd */
    686 		if (limitResourcees < 5)
    687 			return DO_NOT_SEND_MSDU;
    688 
    689 		/* minimum 2 bd for each msdu and one for cocat header */
    690 		*numOfMsduToConcat = MIN( (limitResourcees - 1)>>1, numOfReadyMsdu);
    691 
    692 		/* minimum 2 msdu to concat */
    693 		if (*numOfMsduToConcat < 2)
    694 			return SEND_ONE_MSDU;
    695 
    696 		return MAKE_CONCATENATION;
    697     }
    698 
    699 
    700 	/*
    701 	 * Phase 2: Less than 3 waiting msdu, and the HW already has Msdu to send
    702 	 * ----------------------------------------------------------------------
    703 	 * It is allowed to delay the msdu and continue queueing more MSDU
    704 	 */
    705 	if(pHwTxInformation->hwNumOfBusyMsdu > 1)
    706 	{
    707         pFourX->counters.count3++;
    708 	   /*
    709 		* ACX has enough packets to send, delay the current sending.
    710 		*/
    711 		return DO_NOT_SEND_MSDU;
    712 	}
    713 
    714 	/*
    715 	 * Phase 3: Less than 3 waiting msdu, and the HW is free to send
    716 	 * -------------------------------------------------------------
    717 	 * It is NOT allowed to delay the msdu, so send it
    718 	 */
    719     else
    720     {
    721 	   /*
    722 		* Phase 4: There are 2 msdu to concat and the HW is free to send
    723 		* --------------------------------------------------------------
    724         */
    725         if(  numOfReadyMsdu > 1 )
    726 		{
    727             pFourX->counters.count4++;
    728             /* We have enough msdus to concat. */
    729             *concatFlags = *concatFlags | WLAN_4X_CONCAT_MORE_BIT;
    730 
    731 			/* not enough free bd to send or concat - need at least 2 msdu and 2 bd for each + concat header bd */
    732 			if (limitResourcees < 5)
    733 				return DO_NOT_SEND_MSDU;
    734 
    735 			/* minimum 2 bd for each msdu and one for cocat header */
    736 			*numOfMsduToConcat = MIN( (limitResourcees - 1)>>1, numOfReadyMsdu);
    737 
    738 			/* minimum 2 msdu to concat */
    739 			if (*numOfMsduToConcat < 2)
    740 				return SEND_ONE_MSDU;
    741 
    742 	         return MAKE_CONCATENATION;
    743         }
    744 	   /*
    745 		* Phase 5: There are only one msdu to send, send it (no concatination)
    746 		* --------------------------------------------------------------------
    747 		*/
    748         else
    749         {
    750             pFourX->counters.count5++;
    751 			/*
    752 			 * There space in HW and only one MSDU to send, send it as single.
    753 			 */
    754             return SEND_ONE_MSDU;
    755         }
    756     }
    757 
    758 
    759 #else /* SLAVE_MODE */
    760 		if((pHwTxInformation->hwTotalAvailMem > 4095) && (numOfReadyMsdu > 1))
    761 			{
    762 				*concatFlags = *concatFlags | WLAN_4X_CONCAT_MORE_BIT;
    763 				return MAKE_CONCATENATION;
    764 			}
    765 		else
    766         {
    767 			if(pHwTxInformation->hwTotalAvailMem > pMsduList->first->dataLen)
    768 				return SEND_ONE_MSDU;
    769 			else
    770 				return DO_NOT_SEND_MSDU;
    771         }
    772 
    773 #endif /* MASTER/SALVE modes */
    774 
    775 
    776 
    777 }
    778 
    779 
    780 /* debug functions */
    781 void fourX_printParams(fourX_t* pFourX)
    782 {
    783 
    784 	WLAN_OS_REPORT(("          FOUR X Parameters          \n"));
    785 	WLAN_OS_REPORT(("-------------------------------------\n"));
    786 
    787 	WLAN_OS_REPORT(("hOs                           = 0x%X\n",pFourX->hOs  ));
    788 	WLAN_OS_REPORT(("hReport                       = 0x%X\n",pFourX->hReport  ));
    789 	WLAN_OS_REPORT(("hMemMngr                      = 0x%X\n\n",pFourX->hMemMngr  ));
    790 
    791 	WLAN_OS_REPORT(("concatenationEnable           = %d\n",pFourX->concatenationEnable  ));
    792 	WLAN_OS_REPORT(("CWMinEnable                   = %d\n",pFourX->CWMinEnable  ));
    793 	WLAN_OS_REPORT(("CWComboEnable                 = %d\n",pFourX->CWComboEnable  ));
    794 	WLAN_OS_REPORT(("ackEmulationEnable            = %d\n",pFourX->ackEmulationEnable  ));
    795 	WLAN_OS_REPORT(("ERP_ProtectionEnable          = %d\n\n",pFourX->ERP_ProtectionEnable  ));
    796 
    797 	WLAN_OS_REPORT(("desiredConcatenationEnable    = %d\n",pFourX->desiredConcatenationEnable  ));
    798 	WLAN_OS_REPORT(("desiredCWMinEnable            = %d\n",pFourX->desiredCWMinEnable  ));
    799 	WLAN_OS_REPORT(("desiredCWComboEnable          = %d\n",pFourX->desiredCWComboEnable  ));
    800 	WLAN_OS_REPORT(("desiredAckEmulationEnable     = %d\n",pFourX->desiredAckEmulationEnable  ));
    801 	WLAN_OS_REPORT(("desiredERP_ProtectionEnable   = %d\n\n",pFourX->desiredERP_ProtectionEnable  ));
    802 
    803 	WLAN_OS_REPORT(("desiredMaxConcatSize          = %d\n",pFourX->desiredMaxConcatSize  ));
    804 	WLAN_OS_REPORT(("desiredCWMin                  = %d\n",pFourX->desiredCWMin  ));
    805 	WLAN_OS_REPORT(("desiredCWMax                  = %d\n\n",pFourX->desiredCWMax  ));
    806 
    807 
    808 	/* AP supported features */
    809 
    810 
    811 	/* 4x parameters */
    812 	WLAN_OS_REPORT(("currentMaxConcatSize          = %d\n",pFourX->currentMaxConcatSize  ));
    813 	WLAN_OS_REPORT(("currentCWMin                  = %d\n",pFourX->currentCWMin  ));
    814 	WLAN_OS_REPORT(("currentCWMax                  = %d\n\n",pFourX->currentCWMax  ));
    815 
    816 
    817 	WLAN_OS_REPORT(("ApFourX_Capabilities.fourXProtocolVersion        = %d\n", pFourX->ApFourX_Capabilities.fourXProtocolVersion));
    818 	WLAN_OS_REPORT(("-------------------------------------------------\n"));
    819 
    820 	WLAN_OS_REPORT(("AP_Cap.concatenationParams.enableDisable          = %d\n", pFourX->ApFourX_Capabilities.concatenationParams.enableDisable));
    821 	WLAN_OS_REPORT(("AP_Cap.concatenationParams.concatenationSize      = %d\n", pFourX->ApFourX_Capabilities.concatenationParams.concatenationSize));
    822 
    823 	WLAN_OS_REPORT(("AP_Cap.contentionWindowParams.enableDisable       = %d\n", pFourX->ApFourX_Capabilities.contentionWindowParams.enableDisable));
    824 	WLAN_OS_REPORT(("AP_Cap.contentionWindowParams.CWMin               = %d\n", pFourX->ApFourX_Capabilities.contentionWindowParams.CWMin));
    825 	WLAN_OS_REPORT(("AP_Cap.contentionWindowParams.CWMax               = %d\n", pFourX->ApFourX_Capabilities.contentionWindowParams.CWMax));
    826 
    827 	WLAN_OS_REPORT(("AP_Cap.CWCombParams.enableDisable                 = %d\n", pFourX->ApFourX_Capabilities.CWCombParams.enableDisable));
    828 	WLAN_OS_REPORT(("AP_Cap.CWCombParams.DIFS                          = %d\n", pFourX->ApFourX_Capabilities.CWCombParams.DIFS));
    829 	WLAN_OS_REPORT(("AP_Cap.CWCombParams.SLOT                          = %d\n", pFourX->ApFourX_Capabilities.CWCombParams.SLOT));
    830 	WLAN_OS_REPORT(("AP_Cap.CWCombParams.CWMin                         = %d\n", pFourX->ApFourX_Capabilities.CWCombParams.CWMin));
    831 
    832 	WLAN_OS_REPORT(("AP_Cap.ackEmulationParams.enableDisable           = %d\n", pFourX->ApFourX_Capabilities.ackEmulationParams.enableDisable));
    833 
    834 	WLAN_OS_REPORT(("AP_Cap.ERP_ProtectionParams.enableDisable         = %d\n", pFourX->ApFourX_Capabilities.ERP_ProtectionParams.enableDisable));
    835 
    836    	WLAN_OS_REPORT(("No Free Msdu in ACX   = %d\n", pFourX->counters.count1));
    837    	WLAN_OS_REPORT(("Concat more than 2    = %d\n", pFourX->counters.count2));
    838    	WLAN_OS_REPORT(("Delay sending         = %d\n", pFourX->counters.count3));
    839    	WLAN_OS_REPORT(("Concat less than 3    = %d\n", pFourX->counters.count4));
    840    	WLAN_OS_REPORT(("send one msdu         = %d\n", pFourX->counters.count5));
    841 
    842 	WLAN_OS_REPORT(("Msdu in Queue Total   = %d\n", pFourX->counters.count6));
    843 	WLAN_OS_REPORT(("Msdu in Queue Copied  = %d\n", pFourX->counters.count7));
    844 
    845 }
    846