summaryrefslogtreecommitdiff
path: root/wilink_6_1/TWD/Data_Service
diff options
context:
space:
mode:
Diffstat (limited to 'wilink_6_1/TWD/Data_Service')
-rw-r--r--wilink_6_1/TWD/Data_Service/Export_Inc/RxQueue_api.h59
-rw-r--r--wilink_6_1/TWD/Data_Service/Export_Inc/txCtrlBlk_api.h61
-rw-r--r--wilink_6_1/TWD/Data_Service/Export_Inc/txHwQueue_api.h71
-rw-r--r--wilink_6_1/TWD/Data_Service/RxQueue.c823
-rw-r--r--wilink_6_1/TWD/Data_Service/txCtrlBlk.c281
-rw-r--r--wilink_6_1/TWD/Data_Service/txHwQueue.c712
6 files changed, 2007 insertions, 0 deletions
diff --git a/wilink_6_1/TWD/Data_Service/Export_Inc/RxQueue_api.h b/wilink_6_1/TWD/Data_Service/Export_Inc/RxQueue_api.h
new file mode 100644
index 0000000..4695d41
--- /dev/null
+++ b/wilink_6_1/TWD/Data_Service/Export_Inc/RxQueue_api.h
@@ -0,0 +1,59 @@
+/*
+ * RxQueue_api.h
+ *
+ * Copyright(c) 1998 - 2009 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.
+ */
+
+
+
+/** \file RxQueue_api.h
+ * \brief RxQueue module header file.
+ *
+ * \see RxQueue_api.c
+ */
+
+#ifndef _RX_QUEUE_H_
+#define _RX_QUEUE_H_
+
+/*
+ * External Functions Prototypes
+ * =============================
+ */
+TI_HANDLE RxQueue_Create (TI_HANDLE hOs);
+TI_STATUS RxQueue_Destroy (TI_HANDLE hRxQueue);
+TI_STATUS RxQueue_Init (TI_HANDLE hRxQueue, TI_HANDLE hReport);
+void RxQueue_CloseBaSession(TI_HANDLE hRxQueue, TI_UINT8 uFrameTid);
+void RxQueue_ReceivePacket (TI_HANDLE hRxQueue, const void *aFrame);
+void RxQueue_Register_CB (TI_HANDLE hRxQueue, TI_UINT32 CallBackID, void *CBFunc, TI_HANDLE CBObj);
+
+
+#endif /* _STA_CAP_H_ */
+
+
diff --git a/wilink_6_1/TWD/Data_Service/Export_Inc/txCtrlBlk_api.h b/wilink_6_1/TWD/Data_Service/Export_Inc/txCtrlBlk_api.h
new file mode 100644
index 0000000..a324816
--- /dev/null
+++ b/wilink_6_1/TWD/Data_Service/Export_Inc/txCtrlBlk_api.h
@@ -0,0 +1,61 @@
+/*
+ * txCtrlBlk_api.h
+ *
+ * Copyright(c) 1998 - 2009 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: txCtrlBlk_api.h */
+/* PURPOSE: Tx control block module API. */
+/* */
+/***************************************************************************/
+#ifndef _TX_CTRL_BLK_API_H_
+#define _TX_CTRL_BLK_API_H_
+
+
+#include "TWDriver.h"
+
+/* Public Function Definitions */
+TI_HANDLE txCtrlBlk_Create (TI_HANDLE hOs);
+TI_STATUS txCtrlBlk_Destroy (TI_HANDLE hTxCtrlBlk);
+TI_STATUS txCtrlBlk_Init (TI_HANDLE hTxCtrlBlk, TI_HANDLE hReport, TI_HANDLE hContext);
+TTxCtrlBlk *txCtrlBlk_Alloc (TI_HANDLE hTxCtrlBlk);
+void txCtrlBlk_Free (TI_HANDLE hTxCtrlBlk, TTxCtrlBlk *pCurrentEntry);
+TTxCtrlBlk *txCtrlBlk_GetPointer(TI_HANDLE hTxCtrlBlk, TI_UINT8 descId);
+#ifdef TI_DBG
+void txCtrlBlk_PrintTable(TI_HANDLE hTxCtrlBlk);
+#endif /* TI_DBG */
+
+
+#endif /* _TX_CTRL_BLK_API_H_ */
+
+
diff --git a/wilink_6_1/TWD/Data_Service/Export_Inc/txHwQueue_api.h b/wilink_6_1/TWD/Data_Service/Export_Inc/txHwQueue_api.h
new file mode 100644
index 0000000..92e3bd2
--- /dev/null
+++ b/wilink_6_1/TWD/Data_Service/Export_Inc/txHwQueue_api.h
@@ -0,0 +1,71 @@
+/*
+ * txHwQueue_api.h
+ *
+ * Copyright(c) 1998 - 2009 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: txHwQueue_api.h
+ *
+ * PURPOSE: HW Tx Queue module API.
+ *
+ ****************************************************************************/
+
+#ifndef _TX_HW_QUEUE_API_H
+#define _TX_HW_QUEUE_API_H
+
+
+#include "TWDriver.h"
+#include "TWDriverInternal.h"
+
+
+/* Public Function Definitions */
+
+TI_HANDLE txHwQueue_Create (TI_HANDLE hOs);
+TI_STATUS txHwQueue_Destroy (TI_HANDLE hTxHwQueue);
+TI_STATUS txHwQueue_Init (TI_HANDLE hTxHwQueue, TI_HANDLE hReport);
+TI_STATUS txHwQueue_Config (TI_HANDLE hTxHwQueue, TTwdInitParams *pInitParams);
+TI_STATUS txHwQueue_SetHwInfo (TI_HANDLE hTxHwQueue, TDmaParams *pDmaParams);
+TI_STATUS txHwQueue_Restart (TI_HANDLE hTxHwQueue);
+ETxHwQueStatus txHwQueue_AllocResources (TI_HANDLE hTxHwQueue, TTxCtrlBlk *pTxCtrlBlk);
+void txHwQueue_UpdateFreeResources (TI_HANDLE hTxHwQueue, FwStatus_t *pFwStatus);
+void txHwQueue_RegisterCb (TI_HANDLE hTxHwQueue, TI_UINT32 uCallBackId, void *fCbFunc, TI_HANDLE hCbHndl);
+#ifdef TI_DBG
+void txHwQueue_PrintInfo (TI_HANDLE hTxHwQueue);
+#endif /* TI_DBG */
+
+
+#endif /* _TX_HW_QUEUE_API_H */
+
+
+
+
diff --git a/wilink_6_1/TWD/Data_Service/RxQueue.c b/wilink_6_1/TWD/Data_Service/RxQueue.c
new file mode 100644
index 0000000..7f627be
--- /dev/null
+++ b/wilink_6_1/TWD/Data_Service/RxQueue.c
@@ -0,0 +1,823 @@
+/*
+ * RxQueue.c
+ *
+ * Copyright(c) 1998 - 2009 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.
+ */
+
+
+/** \file RxQueue.c
+ * \brief RX Queue module that responsible to support re-ordering of received packets to upper layers.
+ *
+ * \see RxQueue.h
+ */
+#define __FILE_ID__ FILE_ID_98
+#include "tidef.h"
+#include "osApi.h"
+#include "report.h"
+#include "RxBuf.h"
+#include "TWDriver.h"
+#include "public_descriptors.h"
+
+/************************ static definition declaration *****************************/
+#define RX_QUEUE_ARRAY_SIZE 8
+#define RX_QUEUE_ARRAY_SIZE_BIT_MASK 0x7 /* RX_QUEUE_ARRAY_SIZE -1 */
+#define RX_QUEUE_WIN_SIZE RX_QUEUE_ARRAY_SIZE
+
+#define BA_SESSION_IS_A_BIGGER_THAN_B(A,B) (((((A)-(B)) & 0xFFF) < 0x7FF) && ((A)!=(B)))
+#define BA_SESSION_IS_A_BIGGER_EQUAL_THAN_B(A,B) (((((A)-(B)) & 0xFFF) < 0x7FF))
+#define SEQ_NUM_WRAP 0x1000
+#define SEQ_NUM_MASK 0xFFF
+
+
+/************************ static structures declaration *****************************/
+/* structure describe one entry of save packet information in the packet queue array */
+typedef struct
+{
+ void *pPacket; /* Packet address of the packet */
+ TI_STATUS tStatus; /* RxXfer status. */
+ TI_UINT16 uFrameSn;
+} TRxQueuePacketEntry;
+
+/* structure describe set of data that one Tid, also including the arras himself */
+typedef struct
+{
+ /* array packets Entries */
+ TRxQueuePacketEntry aPaketsQueue [RX_QUEUE_ARRAY_SIZE];
+ /* TID BA state */
+ TI_BOOL aTidBaEstablished;
+ /* index that winStar point on */
+ TI_UINT32 aWinStartArrayInex;
+ /* windows size */
+ TI_UINT32 aTidWinSize;
+ /* expected sequence number (ESN) */
+ TI_UINT16 aTidExpectedSn;
+} TRxQueueTidDataBase;
+
+/* structure describe set of data that assist of manage one SA RxQueue arrays */
+typedef struct
+{
+ TRxQueueTidDataBase tSa1ArrayMng [MAX_NUM_OF_802_1d_TAGS];
+} TRxQueueArraysMng;
+
+/* main RxQueue structure in order to management the packets disordered array. */
+typedef struct
+{
+ TI_HANDLE hOs; /* OS handler */
+ TI_HANDLE hReport; /* Report handler */
+ TRxQueueArraysMng tRxQueueArraysMng; /* manage each Source Address RxQueue arrays */
+ TPacketReceiveCb tReceivePacketCB; /* Receive packets CB address */
+ TI_HANDLE hReceivePacketCB_handle; /* Receive packets CB handler */
+
+} TRxQueue;
+
+/************************ static function declaration *****************************/
+static TI_STATUS RxQueue_PassPacket (TI_HANDLE hRxQueue, TI_STATUS tStatus, const void *pBuffer);
+
+/**
+ * \fn RxQueue_Create()
+ * \brief Create the RxQueue module.
+ *
+ * Allocate and clear the RxQueue module object.
+ *
+ * \param hOs - Handle to Os Abstraction Layer
+ * \return Handle of the allocated object
+ * \sa RxQueue_Destroy
+ */
+TI_HANDLE RxQueue_Create (TI_HANDLE hOs)
+{
+ TRxQueue *pRxQueue;
+
+ /* allocate module object */
+ pRxQueue = os_memoryAlloc (hOs, sizeof(TRxQueue));
+
+ if (!pRxQueue)
+ {
+ WLAN_OS_REPORT (("RxQueue_Create(): Allocation failed!!\n"));
+ return NULL;
+ }
+
+ os_memoryZero (hOs, pRxQueue, (sizeof(TRxQueue)));
+
+ pRxQueue->hOs = hOs;
+
+ return (pRxQueue);
+}
+
+
+/**
+ * \fn RxQueue_Destroy()
+ * \brief Destroy the module.
+ *
+ * Free the module's queues and object.
+ *
+ * \param hRxQueue - The module object
+ * \return TI_OK on success or TI_NOK on failure
+ * \sa RxQueue_Create
+ */
+TI_STATUS RxQueue_Destroy (TI_HANDLE hRxQueue)
+{
+ TRxQueue *pRxQueue = (TRxQueue *)hRxQueue;
+
+ /* free module object */
+ os_memoryFree (pRxQueue->hOs, pRxQueue, sizeof(TRxQueue));
+
+ return TI_OK;
+}
+
+
+/**
+ * \fn RxQueue_Init()
+ * \brief Init required handles
+ *
+ * Init required handles and module variables.
+ *
+ * \note
+ * \param hRxQueue - The module object
+ * \param hReport - Report module Handles
+ * \return TI_OK on success or TI_NOK on failure
+ * \sa
+ */
+TI_STATUS RxQueue_Init (TI_HANDLE hRxQueue, TI_HANDLE hReport)
+{
+ TRxQueue *pRxQueue = (TRxQueue *)hRxQueue;
+
+ pRxQueue->hReport = hReport;
+
+ return TI_OK;
+}
+
+
+/**
+ * \fn RxQueue_Register_CB()
+ * \brief Register the function to be called for received Rx.
+ *
+ * \note
+ * \param hRxQueue - The module object
+ * \param CallBackID - event ID
+ * \param CBFunc - function address.
+ * \param CBObj - function parameter.
+ * \return TI_OK on success or TI_NOK on failure
+ * \sa
+ */
+void RxQueue_Register_CB (TI_HANDLE hRxQueue, TI_UINT32 uCallBackID, void *CBFunc, TI_HANDLE CBObj)
+{
+ TRxQueue* pRxQueue = (TRxQueue *)hRxQueue;
+
+ TRACE1(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION , "RxQueue_Register_CB: CallBack ID = 0x%x\n", uCallBackID);
+
+ switch(uCallBackID)
+ {
+ case TWD_INT_RECEIVE_PACKET:
+ pRxQueue->tReceivePacketCB = (TPacketReceiveCb)CBFunc;
+ pRxQueue->hReceivePacketCB_handle = CBObj;
+ break;
+
+ default:
+ TRACE0(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_Register_CB: Illegal value\n");
+ break;
+ }
+}
+
+/**
+ * \fn RxQueue_CloseBaSession ()
+ * \brief Close BA session receiver and pass all packets in the TID queue to upper layer.
+ *
+ * \note
+ * \param hRxQueue - RxQueue handle.
+ * \param uFrameTid - TID session.
+ * \return None
+ * \sa
+ */
+void RxQueue_CloseBaSession(TI_HANDLE hRxQueue, TI_UINT8 uFrameTid)
+{
+ TRxQueue *pRxQueue = (TRxQueue *)hRxQueue;
+ TI_UINT32 i;
+ /*set the SA Tid pointer */
+ TRxQueueTidDataBase *pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]);
+
+ /* TID illegal value ? */
+ if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS)
+ {
+ TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_CloseBaSession: BA event - DELBA frame with TID value too big, TID = %d\n", uFrameTid);
+
+ return;
+ }
+
+ if(pTidDataBase->aTidBaEstablished == TI_TRUE)
+ {
+ /* clean BA session */
+ pTidDataBase->aTidBaEstablished = TI_FALSE;
+
+ /* pass all valid entries at the array */
+ for (i = 0; (i < RX_QUEUE_ARRAY_SIZE) && (i < RX_QUEUE_WIN_SIZE); i++)
+ {
+ if (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL)
+ {
+ RxQueue_PassPacket (pRxQueue,
+ pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus,
+ pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket);
+
+ pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL;
+ }
+
+ pTidDataBase->aWinStartArrayInex ++;
+
+ /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */
+ pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
+ }
+ }
+}
+
+
+/**
+ * \fn RxQueue_PassPacket()
+ * \brief Responsible on decode packet parameters and pass it to upper layer.
+ *
+ * \note
+ * \param hRxQueue - RxQueue handle.
+ * \param aStatus - RxXfer status that indicate if the upper layer should free the packet or use it.
+ * \param pFrame - paket address of the packet
+ * \param pRxParams - address to structure of the Rx Descriptor received by FW.
+ * \return TI_OK on success or TI_NOK on failure
+ * \sa
+ */
+static TI_STATUS RxQueue_PassPacket (TI_HANDLE hRxQueue, TI_STATUS tStatus, const void *pBuffer)
+{
+
+ TRxQueue *pRxQueue = (TRxQueue *)hRxQueue;
+
+ if (tStatus == TI_OK)
+ {
+ /* Get the mac header location in the packet Buffer */
+ dot11_header_t *pMacHdr = (dot11_header_t *)(TI_UINT8*)RX_BUF_DATA(pBuffer);
+
+ /* Handle endian for the frame control fields */
+ pMacHdr->fc = ENDIAN_HANDLE_WORD(pMacHdr->fc);
+ pMacHdr->duration = ENDIAN_HANDLE_WORD(pMacHdr->duration);
+ pMacHdr->seqCtrl = ENDIAN_HANDLE_WORD(pMacHdr->seqCtrl);
+ }
+ else
+ {
+ RxIfDescriptor_t *pRxParams = (RxIfDescriptor_t*)pBuffer;
+
+ pRxParams->status &= ~RX_DESC_STATUS_MASK;
+ pRxParams->status |= RX_DESC_STATUS_DRIVER_RX_Q_FAIL;
+ }
+
+ TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION , "RxQueue_PassPacket: call TWD_OWNER_RX_QUEUE CB. In std rxData_ReceivePacket()\n");
+
+ /* Set the packet to upper layer */
+ /* if the packet status not success it will be discarded */
+ pRxQueue->tReceivePacketCB (pRxQueue->hReceivePacketCB_handle, pBuffer);
+
+ return TI_OK;
+}
+
+
+/**
+ * \fn RxQueue_ReceivePacket()
+ * \brief Main function of the RxQueue module.
+ * Responsible on reorder of the packets from the RxXfer to the RX module.
+ * Call from RxXfer in order to pass packet to uppers layers.
+ * In order to save disordered packets the module use array of structures per TID
+ * that each entry describe a packet. The array elements is sorted in the way that
+ * the winStart array index represent always the winStar packet and the lowest SN.
+ * Each increment index represent index at the BA window. Array index winEnd always
+ * represent winEnd packet. The indexes of winStart and winEnd handled in cyclic manner.
+ * The function functionality devided to parts:
+ * Part 1:
+ * in case the modulo receive packet with SN equal to winStart:
+ * " pass it to upper layers
+ * " increases winStart and array index winStart
+ * " validate that all sequential queue packet are pass to the upper layers.
+ * Part 2:
+ * in case the modulo receive packet that SN between winStart to winEnd:
+ * " Save it sorted at the array at index: Save index = ((SN - winStart) + index array winStart) % arraySize.
+ * Part 3:
+ * in case the modulo receive packet that SN higher then winEnd:
+ * " Update winStart and WinEnd.
+ * " Save it sorted at the array in index winEnd index.
+ * " Pass to the upper layers all packets at the array indexes from old winStart index to the updated winStart index.
+ * Part 4 + 5:
+ * in case the modulo receive BA event packet:
+ * " Update winStart and WinEnd
+ * " Pass to the upper layers all packets at the array indexes from old winStart index to the updated winStart index.
+ * " Free BA event packet via pass it to upper layers with error status.
+ *
+ * \note
+ * \param hRxQueue - RxQueue handle.
+ * \param aStatus - RxXfer status that indicate if the upper layer should free the packet or use it.
+ * \param pBuffer - paket address of the packet
+ * \return None
+ * \sa
+ */
+void RxQueue_ReceivePacket (TI_HANDLE hRxQueue, const void * pBuffer)
+{
+ TRxQueue *pRxQueue = (TRxQueue *)hRxQueue;
+ RxIfDescriptor_t *pRxParams = (RxIfDescriptor_t*)pBuffer;
+ TI_UINT8 *pFrame = RX_BUF_DATA((TI_UINT8 *)pBuffer);
+ TI_STATUS tStatus = TI_OK;
+ dot11_header_t *pHdr = (dot11_header_t *)pFrame;
+ TI_UINT16 uQosControl;
+
+ COPY_WLAN_WORD(&uQosControl, &pHdr->qosControl); /* copy with endianess handling. */
+
+ /*
+ * Retrieving the TAG from the packet itself and not from the Rx Descriptor since by now it is not correct
+ * Note: in the DR TAG_CLASS_EAPOL packet handled as TAG_CLASS_QOS_DATA
+ */
+ if (IS_QOS_FRAME(*(TI_UINT16*)pFrame) && (pRxParams->packet_class_tag != TAG_CLASS_QOS_DATA) && (pRxParams->packet_class_tag != TAG_CLASS_AMSDU))
+ {
+ TRACE1(pRxQueue->hReport, REPORT_SEVERITY_WARNING, "RxQueue_ReceivePacket: BAD CLASS TAG =0x%x from FW.\n", pRxParams->packet_class_tag);
+
+ /* Get AMSDU bit from frame */
+ if( uQosControl & DOT11_QOS_CONTROL_FIELD_A_MSDU_BITS)
+ {
+ pRxParams->packet_class_tag = TAG_CLASS_AMSDU;
+ }
+ else
+ {
+ pRxParams->packet_class_tag = TAG_CLASS_QOS_DATA;
+ }
+ }
+
+ /*
+ * packet doesn't need reorder ?
+ */
+ if ((pRxParams->packet_class_tag != TAG_CLASS_QOS_DATA) && (pRxParams->packet_class_tag != TAG_CLASS_BA_EVENT) && (pRxParams->packet_class_tag != TAG_CLASS_AMSDU))
+ {
+ TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: pass packet without reorder.\n");
+
+ RxQueue_PassPacket (pRxQueue, tStatus, pBuffer);
+
+ return;
+ }
+
+
+ /*
+ * pRxParams->type == TAG_CLASS_QOS_DATA ?
+ */
+ if ((pRxParams->packet_class_tag == TAG_CLASS_QOS_DATA) || (pRxParams->packet_class_tag == TAG_CLASS_AMSDU))
+ {
+ TI_UINT8 uFrameTid;
+ TI_UINT16 uFrameSn;
+ TI_UINT16 uSequenceControl;
+ TRxQueueTidDataBase *pTidDataBase;
+
+ /* Get TID from frame */
+ uFrameTid = uQosControl & DOT11_QOS_CONTROL_FIELD_TID_BITS;
+
+ /* TID illegal value ? */
+ if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS)
+ {
+ TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR, "RxQueue_ReceivePacket: TID value too big, TID = %d. packet discarded!\n",uFrameTid);
+
+ RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
+
+ return;
+ }
+
+ /*set the SA Tid pointer */
+ pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]);
+
+ /* TID legal value */
+ /* packet TID BA not established ? */
+ if (pTidDataBase->aTidBaEstablished != TI_TRUE)
+ {
+ TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: pass packet without reorder.\n");
+
+ RxQueue_PassPacket (pRxQueue, tStatus, pBuffer);
+
+ return;
+ }
+
+ /* packet TID BA established */
+ /* Get Sequence Number from frame */
+ COPY_WLAN_WORD(&uSequenceControl, &pHdr->seqCtrl); /* copy with endianess handling. */
+ uFrameSn = (uSequenceControl & DOT11_SC_SEQ_NUM_MASK) >> 4;
+
+ /*
+ * note:
+ * the FW never send paket, in establish TID BA, that the SN less then ESN !!!
+ */
+
+ /* frame Sequence Number is the expected one ? */
+ if (uFrameSn == pTidDataBase->aTidExpectedSn)
+ {
+ TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: frame Sequence Number == expected one Sequence Number.\n");
+
+ /* pass the packet */
+ RxQueue_PassPacket (pRxQueue, tStatus, pBuffer);
+
+ pTidDataBase->aTidExpectedSn++;
+ pTidDataBase->aTidExpectedSn &= 0xfff;
+
+ /* increase the ArrayInex to the next */
+ pTidDataBase->aWinStartArrayInex++;
+
+ /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */
+ pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
+
+ /* pass all saved queue packets with SN higher then the expected one */
+ while (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL)
+ {
+ RxQueue_PassPacket (pRxQueue,
+ pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus,
+ pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket);
+
+ pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL;
+
+ pTidDataBase->aWinStartArrayInex++;
+
+ /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */
+ pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
+
+ pTidDataBase->aTidExpectedSn++;
+ pTidDataBase->aTidExpectedSn &= 0xfff;
+ }
+
+ return;
+ }
+
+ /* frame Sequence Number is lower then Expected sequence number (ISN) ? */
+ if (! BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn, pTidDataBase->aTidExpectedSn))
+ {
+ /* WLAN_OS_REPORT(("%s: ERROR - SN=%u is less than ESN=%u\n", __FUNCTION__, uFrameSn, pTidDataBase->aTidExpectedSn)); */
+
+ TRACE2(pRxQueue->hReport, REPORT_SEVERITY_ERROR,
+ "RxQueue_ReceivePacket: frame SN=%u is less than ESN=%u\n",uFrameSn,pTidDataBase->aTidExpectedSn);
+
+ RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
+
+ return;
+ }
+
+ /* frame Sequence Number between winStart and winEnd ? */
+ if ((BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn, pTidDataBase->aTidExpectedSn)) &&
+ /* mean: uFrameSn <= pTidDataBase->aTidExpectedSn + pTidDataBase->aTidWinSize) */
+ ( ! BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn,(pTidDataBase->aTidExpectedSn + pTidDataBase->aTidWinSize - 1))))
+ {
+ TI_UINT16 uSaveInex = pTidDataBase->aWinStartArrayInex + (TI_UINT16)((uFrameSn + SEQ_NUM_WRAP - pTidDataBase->aTidExpectedSn) & SEQ_NUM_MASK);
+ /* uSaveInex % RX_QUEUE_ARRAY_SIZE */
+ uSaveInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
+
+
+ if (pTidDataBase->aPaketsQueue[uSaveInex].pPacket == NULL)
+ {
+ /* save the packet in the queue */
+ pTidDataBase->aPaketsQueue[uSaveInex].tStatus = tStatus;
+ pTidDataBase->aPaketsQueue[uSaveInex].pPacket = (void *)pBuffer;
+ pTidDataBase->aPaketsQueue[uSaveInex].uFrameSn = uFrameSn;
+ }
+ else
+ {
+ TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR, "RxQueue_ReceivePacket: frame Sequence has allready saved. uFrameSn = %d\n",uFrameSn);
+ RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
+ return;
+ }
+ return;
+ }
+
+
+ /*
+ frame Sequence Number higher then winEnd ?
+ */
+ if ( BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn, (pTidDataBase->aTidExpectedSn + pTidDataBase->aTidWinSize - 1)) )
+ {
+ TI_UINT32 i;
+ TI_UINT16 uNewWinStartSn = (uFrameSn + SEQ_NUM_WRAP - pTidDataBase->aTidWinSize + 1) & SEQ_NUM_MASK;
+ TI_UINT16 uSaveInex;
+
+ TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: frame Sequence Number higher then winEnd.\n");
+
+ /* increase the ArrayInex to the next */
+ pTidDataBase->aWinStartArrayInex++;
+
+ /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */
+ pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
+
+ /* update the Expected SN since the current one is lost */
+ pTidDataBase->aTidExpectedSn++;
+ pTidDataBase->aTidExpectedSn &= 0xFFF;
+
+ /* pass all saved queue packets with SN lower then the new win start */
+ for (i = 0;
+ BA_SESSION_IS_A_BIGGER_THAN_B(uNewWinStartSn,pTidDataBase->aTidExpectedSn) &&
+ (i < RX_QUEUE_ARRAY_SIZE) &&
+ (i < pTidDataBase->aTidWinSize);
+ i++)
+ {
+ if (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL)
+ {
+ RxQueue_PassPacket (pRxQueue,
+ pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus,
+ pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket);
+
+ pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL;
+ }
+
+ pTidDataBase->aWinStartArrayInex++;
+
+ /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */
+ pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
+
+ pTidDataBase->aTidExpectedSn++;
+ pTidDataBase->aTidExpectedSn &= 0xFFF;
+
+ }
+
+ /* Calculate the new Expected SN */
+ if (i == pTidDataBase->aTidWinSize)
+ {
+ pTidDataBase->aTidExpectedSn = uNewWinStartSn;
+ }
+ else
+ {
+ /* Incase the uWinStartDelta lower than aTidWinSize check if ther are packets stored in Array */
+ while (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL) {
+ RxQueue_PassPacket (pRxQueue,
+ pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus,
+ pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket);
+
+ pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL;
+
+ pTidDataBase->aWinStartArrayInex++;
+
+ /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */
+ pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
+
+ pTidDataBase->aTidExpectedSn++;
+ pTidDataBase->aTidExpectedSn &= 0xFFF;
+ }
+ }
+
+ if(pTidDataBase->aTidExpectedSn == uFrameSn)
+ {
+ /* pass the packet */
+ RxQueue_PassPacket (pRxQueue, tStatus, pBuffer);
+ pTidDataBase->aTidExpectedSn++;
+ pTidDataBase->aTidExpectedSn &= 0xfff;
+ }
+ else
+ {
+ uSaveInex = pTidDataBase->aWinStartArrayInex + (TI_UINT16)((uFrameSn + SEQ_NUM_WRAP - pTidDataBase->aTidExpectedSn) & SEQ_NUM_MASK);
+
+ /* uSaveInex % RX_QUEUE_ARRAY_SIZE */
+ uSaveInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
+
+ /* save the packet in the last entry of the queue */
+ pTidDataBase->aPaketsQueue[uSaveInex].tStatus = tStatus;
+ pTidDataBase->aPaketsQueue[uSaveInex].pPacket = (void *)pBuffer;
+ pTidDataBase->aPaketsQueue[uSaveInex].pPacket = (void *)pBuffer;
+ }
+
+ return;
+ }
+ }
+
+
+ /*
+ * BA event ?
+ */
+ if (pRxParams->packet_class_tag == TAG_CLASS_BA_EVENT)
+ {
+ TRxQueueTidDataBase *pTidDataBase;
+ TI_UINT8 *pDataFrameBody;
+ TI_UINT16 ufc;
+ TI_UINT8 uFrameTid;
+ TI_UINT16 uStartingSequenceNumber;
+ TI_UINT16 uWinStartDelta;
+ TI_UINT16 uBarControlField;
+ TI_UINT16 uBaStartingSequenceControlField;
+ TI_UINT16 uBAParameterField;
+ TI_UINT32 i;
+
+ /* Get sub type from frame */
+ COPY_WLAN_WORD(&ufc, &pHdr->fc); /* copy with endianess handling. */
+
+ /* get the type to BA event */
+ switch ((dot11_Fc_Sub_Type_e)(ufc & DOT11_FC_SUB_MASK))
+ {
+ case DOT11_FC_SUB_BAR:
+ TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION , "RxQueue_ReceivePacket: BA event - BAR frame.\n");
+
+ /* get pointer to the frame body */
+ pDataFrameBody = pFrame + sizeof(dot11_BarFrameHeader_t);
+
+ /* Get TID from BAR frame */
+ COPY_WLAN_WORD (&uBarControlField, (TI_UINT16 *)pDataFrameBody); /* copy with endianess handling. */
+ uFrameTid = (uBarControlField & DOT11_BAR_CONTROL_FIELD_TID_BITS) >> 12;
+
+ /* TID illegal value ? */
+ if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS)
+ {
+ TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - BAR frame with TID value too big, TID = %d.\n",uFrameTid);
+
+ RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
+
+ return;
+ }
+
+ /* set the SA Tid pointer */
+ pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]);
+
+ /* TID legal value */
+ /* packet TID BA not established ? */
+ if (pTidDataBase->aTidBaEstablished != TI_TRUE)
+ {
+ TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - BAR frame for TID not established, TID = %d.\n",uFrameTid);
+
+ RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
+
+ return;
+ }
+
+ /* Get Starting Sequence number from BAR frame */
+ pDataFrameBody = pDataFrameBody + 2;
+ COPY_WLAN_WORD (&uBaStartingSequenceControlField, (TI_UINT16 *)pDataFrameBody); /* copy with endianess handling. */
+ uStartingSequenceNumber = (uBaStartingSequenceControlField & DOT11_SC_SEQ_NUM_MASK) >> 4;
+
+ /* Starting Sequence Number is higher then winStart ? */
+ if ( BA_SESSION_IS_A_BIGGER_THAN_B (uStartingSequenceNumber, pTidDataBase->aTidExpectedSn) )
+ {
+ uWinStartDelta = (uStartingSequenceNumber + SEQ_NUM_WRAP - pTidDataBase->aTidExpectedSn) & SEQ_NUM_MASK;
+
+ /* pass all saved queue packets with SN lower then the new win start */
+ for (i = 0;
+ ((i < uWinStartDelta) || (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL)) &&
+ (i < RX_QUEUE_ARRAY_SIZE) &&
+ (i < RX_QUEUE_WIN_SIZE);
+ i++)
+ {
+ if (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL)
+ {
+ RxQueue_PassPacket (pRxQueue,
+ pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus,
+ pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket);
+
+ pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL;
+ }
+
+ pTidDataBase->aWinStartArrayInex++;
+
+ /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */
+ pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
+ }
+
+ pTidDataBase->aTidExpectedSn = uStartingSequenceNumber;
+ }
+ break;
+
+
+ case DOT11_FC_SUB_ACTION:
+ /* get pointer to the frame body */
+ pDataFrameBody = pFrame + sizeof(dot11_mgmtHeader_t);
+
+ /* get Action field from BA action frame */
+ pDataFrameBody++;
+ switch(*pDataFrameBody)
+ {
+ case DOT11_BA_ACTION_ADDBA:
+
+ TRACE0( pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: BA event - ADDBA frame.\n");
+
+ /* get TID field and winSize from ADDBA action frame */
+ pDataFrameBody = pDataFrameBody + 2;
+ COPY_WLAN_WORD(&uBAParameterField, (TI_UINT16 *)pDataFrameBody); /* copy with endianess handling. */
+ uFrameTid = (uBAParameterField & DOT11_BA_PARAMETER_SET_FIELD_TID_BITS) >> 2;
+
+ /* TID illegal value ? */
+ if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS)
+ {
+ TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - ADDBA frame with TID value too big, TID = %d.\n",uFrameTid);
+
+ RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
+
+ return;
+ }
+
+ /*set the SA Tid pointer */
+ pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]);
+
+ /* TID legal value */
+ /* packet TID BA established ? */
+ if (pTidDataBase->aTidBaEstablished == TI_TRUE)
+ {
+ TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - ADDBA frame for TID already established, TID = %d.\n",uFrameTid);
+
+ RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
+
+ return;
+ }
+
+ /* get winSize from ADDBA action frame */
+ pTidDataBase->aTidWinSize = (uBAParameterField & DOT11_BA_PARAMETER_SET_FIELD_WINSIZE_BITS) >> 6;
+
+ /* winSize illegal value ? */
+ if (pTidDataBase->aTidWinSize > RX_QUEUE_WIN_SIZE)
+ {
+ /* In case the win Size is higher then 8 the driver and the FW set it to 8 and inform the AP in ADDBA respond */
+ pTidDataBase->aTidWinSize = RX_QUEUE_WIN_SIZE;
+ }
+
+ /* packet TID BA not yet established and winSize legal */
+ /* establishe BA TID */
+ pTidDataBase->aTidBaEstablished = TI_TRUE;
+
+ /* get initial sequence number (ISN) from ADDBA action frame */
+ pDataFrameBody = pDataFrameBody + 4;
+ COPY_WLAN_WORD (&uStartingSequenceNumber, (TI_UINT16 *)pDataFrameBody); /* copy with endianess handling. */
+ pTidDataBase->aTidExpectedSn = (uStartingSequenceNumber & DOT11_SC_SEQ_NUM_MASK) >> 4;
+ pTidDataBase->aWinStartArrayInex = 0;
+ os_memoryZero (pRxQueue->hOs, pTidDataBase->aPaketsQueue, sizeof (TRxQueuePacketEntry) * RX_QUEUE_ARRAY_SIZE);
+ break;
+
+ case DOT11_BA_ACTION_DELBA:
+
+ TRACE0( pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: BA event - DELBA frame.\n");
+
+ /* get TID field and winSize from ADDBA action frame */
+ pDataFrameBody = pDataFrameBody + 2;
+ COPY_WLAN_WORD(&uBAParameterField, (TI_UINT16 *)pDataFrameBody); /* copy with endianess handling. */
+ uFrameTid = (uBAParameterField & DOT11_DELBA_PARAMETER_FIELD_TID_BITS) >> 12;
+
+ /* TID illegal value ? */
+ if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS)
+ {
+ TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - DELBA frame with TID value too big, TID = %d.\n",uFrameTid);
+
+ RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
+
+ return;
+ }
+
+ /*set the SA Tid pointer */
+ pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]);
+
+ /* TID legal value */
+ /* packet TID BA not established ? */
+ if (pTidDataBase->aTidBaEstablished != TI_TRUE)
+ {
+ TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - DELBA frame for TID not established, TID = %d.\n",uFrameTid);
+
+ RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
+
+ return;
+ }
+
+ RxQueue_CloseBaSession(hRxQueue, uFrameTid);
+ break;
+
+ default:
+ TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event Action field from BA action frame illegal. action = 0x%x\n",*pDataFrameBody);
+
+ RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
+
+ return;
+ }
+ break;
+
+ default:
+ TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event with Subtype illegal. Subtype = 0x%x\n",((ufc & DOT11_FC_SUB_MASK) >> 4));
+
+ RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
+
+ return;
+ }
+
+ }
+
+ TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR, "RxQueue_ReceivePacket: unknow type tag. tag = %d\n", pRxParams->packet_class_tag);
+
+ RxQueue_PassPacket (pRxQueue, tStatus, pBuffer);
+
+ return;
+}
+
diff --git a/wilink_6_1/TWD/Data_Service/txCtrlBlk.c b/wilink_6_1/TWD/Data_Service/txCtrlBlk.c
new file mode 100644
index 0000000..1462e1b
--- /dev/null
+++ b/wilink_6_1/TWD/Data_Service/txCtrlBlk.c
@@ -0,0 +1,281 @@
+/*
+ * txCtrlBlk.c
+ *
+ * Copyright(c) 1998 - 2009 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: txCtrlBlk.c
+ *
+ * PURPOSE: Maintains active packets Tx attributes table (including descriptor).
+ *
+ * DESCRIPTION:
+ * ============
+ * This module allocates and frees table entry for each packet in the Tx
+ * process (from sendPkt by upper driver until Tx-complete).
+ *
+ ****************************************************************************/
+#define __FILE_ID__ FILE_ID_99
+#include "osApi.h"
+#include "tidef.h"
+#include "report.h"
+#include "context.h"
+#include "TWDriver.h"
+#include "txCtrlBlk_api.h"
+
+
+/* The TxCtrlBlk module object - contains the control-block table. */
+typedef struct
+{
+ TI_HANDLE hOs;
+ TI_HANDLE hReport;
+ TI_HANDLE hContext;
+
+ TTxCtrlBlk aTxCtrlBlkTbl[CTRL_BLK_ENTRIES_NUM]; /* The table of control-block entries. */
+
+#ifdef TI_DBG /* Just for debug. */
+ TI_UINT32 uNumUsedEntries;
+#endif
+
+} TTxCtrlBlkObj;
+
+
+/****************************************************************************
+ * txCtrlBlk_Create()
+ ****************************************************************************
+ * DESCRIPTION: Create the Tx control block table object
+ *
+ * INPUTS: hOs
+ *
+ * OUTPUT: None
+ *
+ * RETURNS: The Created object
+ ****************************************************************************/
+TI_HANDLE txCtrlBlk_Create (TI_HANDLE hOs)
+{
+ TTxCtrlBlkObj *pTxCtrlBlk;
+
+ pTxCtrlBlk = os_memoryAlloc (hOs, sizeof(TTxCtrlBlkObj));
+ if (pTxCtrlBlk == NULL)
+ return NULL;
+
+ os_memoryZero (hOs, pTxCtrlBlk, sizeof(TTxCtrlBlkObj));
+
+ pTxCtrlBlk->hOs = hOs;
+
+ return( (TI_HANDLE)pTxCtrlBlk );
+}
+
+
+/****************************************************************************
+ * txCtrlBlk_Destroy()
+ ****************************************************************************
+ * DESCRIPTION: Destroy the Tx control block table object
+ *
+ * INPUTS: hTxCtrlBlk - The object to free
+ *
+ * OUTPUT: None
+ *
+ * RETURNS: TI_OK or TI_NOK
+ ****************************************************************************/
+TI_STATUS txCtrlBlk_Destroy (TI_HANDLE hTxCtrlBlk)
+{
+ TTxCtrlBlkObj *pTxCtrlBlk = (TTxCtrlBlkObj *)hTxCtrlBlk;
+
+ if (pTxCtrlBlk)
+ os_memoryFree(pTxCtrlBlk->hOs, pTxCtrlBlk, sizeof(TTxCtrlBlkObj));
+
+ return TI_OK;
+}
+
+
+/****************************************************************************
+ * txCtrlBlk_Init()
+ ****************************************************************************
+ DESCRIPTION: Initialize the Tx control block module.
+ ****************************************************************************/
+TI_STATUS txCtrlBlk_Init (TI_HANDLE hTxCtrlBlk, TI_HANDLE hReport, TI_HANDLE hContext)
+{
+ TTxCtrlBlkObj *pTxCtrlBlk = (TTxCtrlBlkObj *)hTxCtrlBlk;
+ TI_UINT8 entry;
+
+ pTxCtrlBlk->hReport = hReport;
+ pTxCtrlBlk->hContext = hContext;
+
+ /* For all entries, write the entry index in the descriptor and the next entry address
+ in the next free entery pointer. Init also some other fields. */
+ for(entry = 0; entry < CTRL_BLK_ENTRIES_NUM; entry++)
+ {
+ pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.descID = entry;
+ pTxCtrlBlk->aTxCtrlBlkTbl[entry].pNextFreeEntry = &(pTxCtrlBlk->aTxCtrlBlkTbl[entry + 1]);
+ pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.aid = 1; /* The value for infrastructure BSS */
+ pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.reserved = 0;
+ }
+
+ /* Write null in the next-free index of the last entry. */
+ pTxCtrlBlk->aTxCtrlBlkTbl[CTRL_BLK_ENTRIES_NUM - 1].pNextFreeEntry = NULL;
+
+ #ifdef TI_DBG
+ pTxCtrlBlk->uNumUsedEntries = 0;
+ #endif
+
+ return TI_OK;
+}
+
+
+/****************************************************************************
+ * txCtrlBlk_Alloc()
+ ****************************************************************************
+ * DESCRIPTION:
+ Allocate a free control-block entry for the current Tx packet's parameters
+ (including the descriptor structure).
+ Note that entry 0 in the list is never allocated and points to the
+ first free entry.
+ ****************************************************************************/
+TTxCtrlBlk *txCtrlBlk_Alloc (TI_HANDLE hTxCtrlBlk)
+{
+ TTxCtrlBlkObj *pTxCtrlBlk = (TTxCtrlBlkObj *)hTxCtrlBlk;
+ TTxCtrlBlk *pCurrentEntry; /* The pointer of the new entry allocated for the packet. */
+ TTxCtrlBlk *pFirstFreeEntry; /* The first entry just points to the first free entry. */
+
+ pFirstFreeEntry = &(pTxCtrlBlk->aTxCtrlBlkTbl[0]);
+
+ /* Protect block allocation from preemption (may be called from external context) */
+ context_EnterCriticalSection (pTxCtrlBlk->hContext);
+
+ pCurrentEntry = pFirstFreeEntry->pNextFreeEntry; /* Get free entry. */
+
+#ifdef TI_DBG
+ /* If no free entries, print error (not expected to happen) and return NULL. */
+ if (pCurrentEntry->pNextFreeEntry == NULL)
+ {
+TRACE1(pTxCtrlBlk->hReport, REPORT_SEVERITY_ERROR, "txCtrlBlk_alloc(): No free entry, UsedEntries=%d\n", pTxCtrlBlk->uNumUsedEntries);
+ context_LeaveCriticalSection (pTxCtrlBlk->hContext);
+ return NULL;
+ }
+ pTxCtrlBlk->uNumUsedEntries++;
+#endif
+
+ /* Link the first entry to the next free entry. */
+ pFirstFreeEntry->pNextFreeEntry = pCurrentEntry->pNextFreeEntry;
+
+ context_LeaveCriticalSection (pTxCtrlBlk->hContext);
+
+ /* Clear the next-free-entry index just as an indication that our entry is not free. */
+ pCurrentEntry->pNextFreeEntry = 0;
+
+ pCurrentEntry->tTxPktParams.uFlags = 0;
+ pCurrentEntry->tTxPktParams.uHeadroomSize = 0;
+
+ return pCurrentEntry;
+}
+
+
+/****************************************************************************
+ * txCtrlBlk_Free()
+ ****************************************************************************
+ * DESCRIPTION:
+ Link the freed entry after entry 0, so now it is the first free entry to
+ be allocated.
+ ****************************************************************************/
+void txCtrlBlk_Free (TI_HANDLE hTxCtrlBlk, TTxCtrlBlk *pCurrentEntry)
+{
+ TTxCtrlBlkObj *pTxCtrlBlk = (TTxCtrlBlkObj *)hTxCtrlBlk;
+ TTxCtrlBlk *pFirstFreeEntry = &(pTxCtrlBlk->aTxCtrlBlkTbl[0]);
+
+#ifdef TI_DBG
+ /* If the pointed entry is already free, print error and exit (not expected to happen). */
+ if (pCurrentEntry->pNextFreeEntry != 0)
+ {
+TRACE2(pTxCtrlBlk->hReport, REPORT_SEVERITY_ERROR, "txCtrlBlk_free(): Entry %d alredy free, UsedEntries=%d\n", pCurrentEntry->tTxDescriptor.descID, pTxCtrlBlk->uNumUsedEntries);
+ return;
+ }
+ pTxCtrlBlk->uNumUsedEntries--;
+#endif
+
+ /* Protect block freeing from preemption (may be called from external context) */
+ context_EnterCriticalSection (pTxCtrlBlk->hContext);
+
+ /* Link the freed entry between entry 0 and the next free entry. */
+ pCurrentEntry->pNextFreeEntry = pFirstFreeEntry->pNextFreeEntry;
+ pFirstFreeEntry->pNextFreeEntry = pCurrentEntry;
+
+ context_LeaveCriticalSection (pTxCtrlBlk->hContext);
+}
+
+
+/****************************************************************************
+ * txCtrlBlk_GetPointer()
+ ****************************************************************************
+ * DESCRIPTION:
+ Return a pointer to the control block entry of the requested packet.
+ Used upon tx-complete to retrieve info after getting the descId from the FW.
+ ****************************************************************************/
+TTxCtrlBlk *txCtrlBlk_GetPointer (TI_HANDLE hTxCtrlBlk, TI_UINT8 descId)
+{
+ TTxCtrlBlkObj *pTxCtrlBlk = (TTxCtrlBlkObj *)hTxCtrlBlk;
+ return ( &(pTxCtrlBlk->aTxCtrlBlkTbl[descId]) );
+}
+
+
+/****************************************************************************
+ * txCtrlBlk_PrintTable()
+ ****************************************************************************
+ * DESCRIPTION: Print the txCtrlBlk table main fields.
+ ****************************************************************************/
+#ifdef TI_DBG
+void txCtrlBlk_PrintTable (TI_HANDLE hTxCtrlBlk)
+{
+#ifdef REPORT_LOG
+ TTxCtrlBlkObj *pTxCtrlBlk = (TTxCtrlBlkObj *)hTxCtrlBlk;
+ TI_UINT8 entry;
+
+ WLAN_OS_REPORT((" Tx-Control-Block Information, UsedEntries=%d\n", pTxCtrlBlk->uNumUsedEntries));
+ WLAN_OS_REPORT(("==============================================\n"));
+
+ for(entry = 0; entry < CTRL_BLK_ENTRIES_NUM; entry++)
+ {
+ WLAN_OS_REPORT(("Entry %d: DescID=%d, Next=0x%x, Len=%d, StartTime=%d, TID=%d, ExtraBlks=%d, TotalBlks=%d, Flags=0x%x\n",
+ entry,
+ pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.descID,
+ pTxCtrlBlk->aTxCtrlBlkTbl[entry].pNextFreeEntry,
+ ENDIAN_HANDLE_WORD(pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.length),
+ ENDIAN_HANDLE_LONG(pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.startTime),
+ pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.tid,
+ pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.extraMemBlks,
+ pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.totalMemBlks,
+ pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxPktParams.uFlags));
+ }
+#endif
+}
+#endif /* TI_DBG */
+
diff --git a/wilink_6_1/TWD/Data_Service/txHwQueue.c b/wilink_6_1/TWD/Data_Service/txHwQueue.c
new file mode 100644
index 0000000..19a0098
--- /dev/null
+++ b/wilink_6_1/TWD/Data_Service/txHwQueue.c
@@ -0,0 +1,712 @@
+/*
+ * txHwQueue.c
+ *
+ * Copyright(c) 1998 - 2009 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: txHwQueue.c
+ *
+ * PURPOSE: manage the wlan hardware Tx memory blocks allocation per queue.
+ *
+ * DESCRIPTION:
+ * ============
+ * This module is responsible for the HW Tx data-blocks and descriptors allocation.
+ * The HW Tx blocks are allocated in the driver by rough calculations without
+ * accessing the FW.
+ * They are freed according to FW counters that are provided by the FwEvent module
+ * on every FW interrupt.
+ ****************************************************************************/
+#define __FILE_ID__ FILE_ID_100
+#include "osApi.h"
+#include "report.h"
+#include "TWDriver.h"
+#include "txCtrlBlk_api.h"
+#include "txHwQueue_api.h"
+
+
+/* Translate input TID to AC */
+/* Note: This structure is shared with other modules */
+const EAcTrfcType WMEQosTagToACTable[MAX_NUM_OF_802_1d_TAGS] =
+ {QOS_AC_BE, QOS_AC_BK, QOS_AC_BK, QOS_AC_BE, QOS_AC_VI, QOS_AC_VI, QOS_AC_VO, QOS_AC_VO};
+
+/*
+ * Local definitions:
+ */
+
+/* Spare blocks written in extraMemBlks field in TxDescriptor for HW use */
+#define BLKS_HW_ALLOC_SPARE 2
+
+/* Set queue's backpressure bit (indicates queue state changed from ready to busy or inversely). */
+#define SET_QUEUE_BACKPRESSURE(pBackpressure, uQueueId) (*pBackpressure |= (1 << uQueueId))
+
+/* Callback function definition for UpdateBusyMap */
+typedef void (* tUpdateBusyMapCb)(TI_HANDLE hCbHndl, TI_UINT32 uBackpressure);
+
+/* Per Queue HW blocks accounting data: */
+typedef struct
+{
+ TI_UINT32 uNumBlksThresh; /* Minimum HW blocks that must be reserved for this Queue. */
+ TI_UINT32 uNumBlksUsed; /* Number of HW blocks that are currently allocated for this Queue. */
+ TI_UINT32 uNumBlksReserved; /* Number of HW blocks currently reserved for this Queue (to guarentee the low threshold). */
+ TI_UINT32 uAllocatedBlksCntr; /* Accumulates allocated blocks for FW freed-blocks counter coordination. */
+ TI_UINT32 uFwFreedBlksCntr; /* Accumulated freed blocks in FW. */
+ TI_UINT32 uNumBlksCausedBusy; /* Number of HW blocks that caused queue busy state. */
+ TI_BOOL bQueueBusy; /* If TI_TRUE, this queue is currently stopped. */
+ TI_UINT16 uPercentOfBlkLowThresh; /* Configured percentage of blocks to use as the queue's low allocation threshold */
+ TI_UINT16 uPercentOfBlkHighThresh; /* Configured percentage of blocks to use as the queue's high allocation threshold */
+
+} TTxHwQueueInfo;
+
+typedef struct
+{
+ TI_HANDLE hOs;
+ TI_HANDLE hReport;
+
+ tUpdateBusyMapCb fUpdateBusyMapCb; /* The upper layers UpdateBusyMap callback */
+ TI_HANDLE hUpdateBusyMapHndl;/* The handle for the fUpdateBusyMapCb */
+
+ TI_UINT32 uNumTotalBlks; /* The total number of Tx blocks */
+ TI_UINT32 uNumTotalBlksFree; /* Total number of free HW blocks */
+ TI_UINT32 uNumTotalBlksReserved; /* Total number of free but reserved HW blocks */
+ TI_UINT32 uNumUsedDescriptors; /* Total number of packets in the FW. */
+ TI_UINT8 uFwTxResultsCntr; /* Accumulated freed descriptors in FW. */
+ TI_UINT8 uDrvTxPacketsCntr; /* Accumulated allocated descriptors in driver. */
+
+ TTxHwQueueInfo aTxHwQueueInfo[MAX_NUM_OF_AC]; /* The per queue variables */
+
+} TTxHwQueue;
+
+
+static void txHwQueue_UpdateFreeBlocks (TTxHwQueue *pTxHwQueue, TI_UINT32 uQueueId, TI_UINT32 uFreeBlocks);
+static TI_UINT32 txHwQueue_CheckResources (TTxHwQueue *pTxHwQueue, TTxHwQueueInfo *pQueueInfo);
+
+
+
+/****************************************************************************
+ * txHwQueue_Create()
+ ****************************************************************************
+ * DESCRIPTION: Create the Tx buffers pool object
+ *
+ * INPUTS: None
+ *
+ * OUTPUT: None
+ *
+ * RETURNS: The Created object
+ ****************************************************************************/
+TI_HANDLE txHwQueue_Create (TI_HANDLE hOs)
+{
+ TTxHwQueue *pTxHwQueue;
+
+ pTxHwQueue = os_memoryAlloc(hOs, sizeof(TTxHwQueue));
+ if (pTxHwQueue == NULL)
+ {
+ return NULL;
+ }
+
+ os_memoryZero(hOs, pTxHwQueue, sizeof(TTxHwQueue));
+
+ pTxHwQueue->hOs = hOs;
+
+ return (TI_HANDLE)pTxHwQueue;
+}
+
+/****************************************************************************
+ * txHwQueue_Destroy()
+ ****************************************************************************
+ * DESCRIPTION: Destroy the Tx buffers pool object
+ *
+ * INPUTS: hTxHwQueue - The object to free
+ *
+ * OUTPUT: None
+ *
+ * RETURNS: TI_OK or TI_NOK
+ ****************************************************************************/
+TI_STATUS txHwQueue_Destroy (TI_HANDLE hTxHwQueue)
+{
+ TTxHwQueue *pTxHwQueue = (TTxHwQueue *)hTxHwQueue;
+
+ if (pTxHwQueue)
+ {
+ os_memoryFree(pTxHwQueue->hOs, pTxHwQueue, sizeof(TTxHwQueue));
+ }
+ return TI_OK;
+}
+
+
+
+
+/****************************************************************************
+ * txHwQueue_Init()
+ ****************************************************************************
+
+ DESCRIPTION: Initialize module handles.
+
+ ****************************************************************************/
+TI_STATUS txHwQueue_Init (TI_HANDLE hTxHwQueue, TI_HANDLE hReport)
+{
+ TTxHwQueue *pTxHwQueue = (TTxHwQueue *)hTxHwQueue;
+
+ pTxHwQueue->hReport = hReport;
+
+ return TI_OK;
+}
+
+
+/****************************************************************************
+ * txHwQueue_Config()
+ ****************************************************************************
+ * DESCRIPTION: Configure the Tx buffers pool object
+ *
+ * INPUTS: None
+ *
+ * OUTPUT: None
+ *
+ * RETURNS:
+ ****************************************************************************/
+TI_STATUS txHwQueue_Config (TI_HANDLE hTxHwQueue, TTwdInitParams *pInitParams)
+{
+ TTxHwQueue *pTxHwQueue = (TTxHwQueue *)hTxHwQueue;
+ TI_UINT32 TxQid;
+
+ /* Configure queue parameters to Tx-HW queue module */
+ for (TxQid = 0; TxQid < MAX_NUM_OF_AC; TxQid++)
+ {
+ pTxHwQueue->aTxHwQueueInfo[TxQid].uNumBlksThresh = pInitParams->tGeneral.TxBlocksThresholdPerAc[TxQid];
+ }
+
+ return TI_OK;
+}
+
+
+
+/****************************************************************************
+ * txHwQueue_SetHwInfo()
+ ****************************************************************************
+
+ DESCRIPTION:
+
+ Called after the HW configuration in the driver init or recovery process.
+ Configure Tx HW information, including Tx-HW-blocks number, and per queue
+ Tx-descriptors number. Than, restart the module variables.
+
+ Two thresholds are defined per queue:
+ a) TxBlocksLowPercentPerQueue[queue] - The lower threshold is the minimal number of
+ Tx blocks guaranteed for each queue.
+ The sum of all low thresholds should be less than 100%.
+ b) TxBlocksHighPercentPerQueue[queue] - The higher threshold is the maximal number of
+ Tx blocks that may be allocated to the queue.
+ The extra blocks above the low threshold can be allocated when needed only
+ if they are currently available and are not needed in order to guarantee
+ the other queues low threshold.
+ The sum of all high thresholds should be more than 100%.
+ ****************************************************************************/
+TI_STATUS txHwQueue_SetHwInfo (TI_HANDLE hTxHwQueue, TDmaParams *pDmaParams)
+{
+ TTxHwQueue *pTxHwQueue = (TTxHwQueue *)hTxHwQueue;
+
+ pTxHwQueue->uNumTotalBlks = pDmaParams->NumTxBlocks - 1; /* One block must be always free for FW use. */
+
+ /* Restart the module variables. */
+ txHwQueue_Restart (hTxHwQueue);
+
+ return TI_OK;
+}
+
+
+/****************************************************************************
+ * txHwQueue_Restart()
+ ****************************************************************************
+ DESCRIPTION:
+ ============
+ Called after the HW configuration in the driver init or recovery process.
+ Restarts the Tx-HW-Queue module.
+ ****************************************************************************/
+TI_STATUS txHwQueue_Restart (TI_HANDLE hTxHwQueue)
+{
+ TTxHwQueue *pTxHwQueue = (TTxHwQueue *)hTxHwQueue;
+ TTxHwQueueInfo *pQueueInfo;
+ TI_UINT32 TxQid;
+
+
+ /*
+ * All blocks are free at restart.
+ * Note that free means all blocks that are currently not in use, while reserved are
+ * a part of the free blocks that are the summary of all queues reserved blocks.
+ * Each queue may take from the reserved part only up to its own reservation (according to
+ * its low threshold).
+ */
+ pTxHwQueue->uNumTotalBlksFree = pTxHwQueue->uNumTotalBlks;
+ pTxHwQueue->uNumTotalBlksReserved = 0;
+ pTxHwQueue->uNumUsedDescriptors = 0;
+ pTxHwQueue->uFwTxResultsCntr = 0;
+ pTxHwQueue->uDrvTxPacketsCntr = 0;
+
+ for (TxQid = 0; TxQid < MAX_NUM_OF_AC; TxQid++)
+ {
+ pQueueInfo = &pTxHwQueue->aTxHwQueueInfo[TxQid];
+
+ pQueueInfo->uNumBlksUsed = 0;
+ pQueueInfo->uAllocatedBlksCntr = 0;
+ pQueueInfo->uFwFreedBlksCntr = 0;
+ pQueueInfo->uNumBlksCausedBusy = 0;
+ pQueueInfo->bQueueBusy = TI_FALSE;
+
+ /* Since no blocks are used yet, reserved blocks number equals to the low threshold. */
+ pQueueInfo->uNumBlksReserved = pQueueInfo->uNumBlksThresh;
+
+ /* Accumulate total reserved blocks. */
+ pTxHwQueue->uNumTotalBlksReserved += pQueueInfo->uNumBlksReserved;
+ }
+
+ return TI_OK;
+}
+
+
+/****************************************************************************
+ * txHwQueue_AllocResources()
+ ****************************************************************************
+ * DESCRIPTION:
+ ============
+ 1. Estimate required HW-blocks number.
+ 2. If the required blocks are not available or no free descriptor,
+ return STOP_CURRENT (to stop current queue and requeue the packet).
+ 3. Resources are available so update allocated blocks and descriptors counters.
+ 4. If no resources for another similar packet, return STOP_NEXT (to stop current queue).
+ Else, return SUCCESS
+ ****************************************************************************/
+ETxHwQueStatus txHwQueue_AllocResources (TI_HANDLE hTxHwQueue, TTxCtrlBlk *pTxCtrlBlk)
+{
+ TTxHwQueue *pTxHwQueue = (TTxHwQueue *)hTxHwQueue;
+ TI_UINT32 uNumBlksToAlloc; /* The number of blocks required for the current packet. */
+ TI_UINT32 uExcludedLength; /* The data length not included in the rough blocks calculation */
+ TI_UINT32 uAvailableBlks; /* Max blocks that are currently available for this queue. */
+ TI_UINT32 uReservedBlks; /* How many blocks are reserved for this queue before this allocation. */
+ TI_UINT32 uQueueId = WMEQosTagToACTable[pTxCtrlBlk->tTxDescriptor.tid];
+ TTxHwQueueInfo *pQueueInfo = &(pTxHwQueue->aTxHwQueueInfo[uQueueId]);
+
+
+ /***********************************************************************/
+ /* Calculate packet required HW blocks. */
+ /***********************************************************************/
+
+ /* Divide length by 256 instead of 252 (block size) to save CPU */
+ uNumBlksToAlloc = ( pTxCtrlBlk->tTxDescriptor.length + 20 ) >> 8;
+
+ /* The length not yet included in the uNumBlksToAlloc is the sum of:
+ 1) 4 bytes per block as a result of using 256 instead of 252 block size.
+ 2) The remainder of the division by 256.
+ 3) Overhead due to header translation, security and LLC header (subtracting ethernet header).
+ */
+ uExcludedLength = (uNumBlksToAlloc << 2) + ((pTxCtrlBlk->tTxDescriptor.length + 20) & 0xFF) + MAX_HEADER_SIZE - 14;
+
+ /* Add 1 or 2 blocks for the excluded length, according to its size */
+ uNumBlksToAlloc += (uExcludedLength > 252) ? 2 : 1;
+
+ /* Add extra blocks needed in case of fragmentation */
+ uNumBlksToAlloc += BLKS_HW_ALLOC_SPARE;
+
+ /***********************************************************************/
+ /* Check if the required resources are available */
+ /***********************************************************************/
+
+ /* Find max available blocks for this queue (0 could indicate no descriptors). */
+ uAvailableBlks = txHwQueue_CheckResources (pTxHwQueue, pQueueInfo);
+
+ /* If we need more blocks than available, return STOP_CURRENT (stop current queue and requeue packet). */
+ if (uNumBlksToAlloc > uAvailableBlks)
+ {
+ TRACE6(pTxHwQueue->hReport, REPORT_SEVERITY_INFORMATION, ": No resources, Queue=%d, ReqBlks=%d, FreeBlks=%d, UsedBlks=%d, AvailBlks=%d, UsedPkts=%d\n", uQueueId, uNumBlksToAlloc, pTxHwQueue->uNumTotalBlksFree, pQueueInfo->uNumBlksUsed, uAvailableBlks, pTxHwQueue->uNumUsedDescriptors);
+ pQueueInfo->uNumBlksCausedBusy = uNumBlksToAlloc;
+ pQueueInfo->bQueueBusy = TI_TRUE;
+
+ return TX_HW_QUE_STATUS_STOP_CURRENT; /**** Exit! (we should stop queue and requeue packet) ****/
+ }
+
+ /***********************************************************************/
+ /* Allocate required resources */
+ /***********************************************************************/
+
+ /* Update blocks numbers in Tx descriptor */
+ pTxCtrlBlk->tTxDescriptor.extraMemBlks = BLKS_HW_ALLOC_SPARE;
+ pTxCtrlBlk->tTxDescriptor.totalMemBlks = uNumBlksToAlloc;
+
+ /* Update packet allocation info: */
+ pTxHwQueue->uNumUsedDescriptors++; /* Update number of packets in FW (for descriptors allocation check). */
+ pTxHwQueue->uDrvTxPacketsCntr++;
+ pQueueInfo->uAllocatedBlksCntr += uNumBlksToAlloc; /* For FW counter coordination. */
+ uReservedBlks = pQueueInfo->uNumBlksReserved;
+
+ /* If we are currently using less than the low threshold (i.e. we have some reserved blocks),
+ blocks allocation should reduce the reserved blocks number as follows:
+ */
+ if (uReservedBlks)
+ {
+
+ /* If adding the allocated blocks to the used blocks will pass the low-threshold,
+ only the part up to the low-threshold is subtracted from the reserved blocks.
+ This is because blocks are reserved for the Queue only up to its low-threshold.
+
+ 0 old used low new used high
+ |######| | | |
+ |######| | | |
+ <------------ allocated ----------->
+ <----- old reserved ---->
+ new reserved = 0 (we passed the low threshold)
+ */
+ if (uNumBlksToAlloc > uReservedBlks)
+ {
+ pQueueInfo->uNumBlksReserved = 0;
+ pTxHwQueue->uNumTotalBlksReserved -= uReservedBlks; /* reduce change from total reserved.*/
+ }
+
+
+ /* Else, if allocating less than reserved,
+ the allocated blocks are subtracted from the reserved blocks:
+
+ 0 old used new used low high
+ |######| | | |
+ |######| | | |
+ <- allocated ->
+ <--------- old reserved ---------->
+ <-- new reserved -->
+ */
+ else
+ {
+ pQueueInfo->uNumBlksReserved -= uNumBlksToAlloc;
+ pTxHwQueue->uNumTotalBlksReserved -= uNumBlksToAlloc; /* reduce change from total reserved.*/
+ }
+ }
+
+
+ /* Update total free blocks and Queue used blocks with the allocated blocks number. */
+ pTxHwQueue->uNumTotalBlksFree -= uNumBlksToAlloc;
+ pQueueInfo->uNumBlksUsed += uNumBlksToAlloc;
+
+ TRACE6(pTxHwQueue->hReport, REPORT_SEVERITY_INFORMATION, ": SUCCESS, Queue=%d, Req-blks=%d , Free=%d, Used=%d, Reserved=%d, Accumulated=%d\n", uQueueId, uNumBlksToAlloc, pTxHwQueue->uNumTotalBlksFree, pQueueInfo->uNumBlksUsed, pQueueInfo->uNumBlksReserved, pQueueInfo->uAllocatedBlksCntr);
+
+ /* If no resources for another similar packet, return STOP_NEXT (to stop current queue). */
+ /* Note: Current packet transmission is continued */
+ if ( (uNumBlksToAlloc << 1) > uAvailableBlks )
+ {
+ TRACE6(pTxHwQueue->hReport, REPORT_SEVERITY_INFORMATION, ": No resources for next pkt, Queue=%d, ReqBlks=%d, FreeBlks=%d, UsedBlks=%d, AvailBlks=%d, UsedPkts=%d\n", uQueueId, uNumBlksToAlloc, pTxHwQueue->uNumTotalBlksFree, pQueueInfo->uNumBlksUsed, uAvailableBlks, pTxHwQueue->uNumUsedDescriptors);
+ pQueueInfo->uNumBlksCausedBusy = uNumBlksToAlloc;
+ pQueueInfo->bQueueBusy = TI_TRUE;
+ return TX_HW_QUE_STATUS_STOP_NEXT;
+ }
+
+ /* Return SUCCESS (resources are available). */
+ return TX_HW_QUE_STATUS_SUCCESS;
+}
+
+
+/****************************************************************************
+ * txHwQueue_UpdateFreeBlocks()
+ ****************************************************************************
+ * DESCRIPTION:
+ ===========
+ This function is called per queue after reading the freed blocks counters from the FwStatus.
+ It updates the queue's blocks status according to the freed blocks.
+ ****************************************************************************/
+static void txHwQueue_UpdateFreeBlocks (TTxHwQueue *pTxHwQueue, TI_UINT32 uQueueId, TI_UINT32 uFreeBlocks)
+{
+ TTxHwQueueInfo *pQueueInfo = &(pTxHwQueue->aTxHwQueueInfo[uQueueId]);
+ TI_UINT32 lowThreshold; /* Minimum blocks that are guaranteed for this Queue. */
+ TI_UINT32 newUsedBlks; /* Blocks that are used by this Queue after updating free blocks. */
+ TI_UINT32 newReserved; /* How many blocks are reserved to this Queue after freeing. */
+ TI_UINT32 numBlksToFree; /* The number of blocks freed in the current queue. */
+
+ /* If the FW free blocks counter didn't change, exit */
+ uFreeBlocks = ENDIAN_HANDLE_LONG(uFreeBlocks);
+ if (uFreeBlocks == pQueueInfo->uFwFreedBlksCntr)
+ {
+ return;
+ }
+
+ pQueueInfo->uFwFreedBlksCntr = uFreeBlocks;
+
+ /* The uFreeBlocks is the accumulated number of blocks freed by the FW for the uQueueId.
+ * Subtracting it from the accumulated number of blocks allocated by the driver should
+ * give the current number of used blocks in this queue.
+ * Since the difference is always a small positive number, a simple subtraction should work
+ * also for wrap around.
+ */
+ newUsedBlks = pQueueInfo->uAllocatedBlksCntr - uFreeBlocks;
+
+ numBlksToFree = pQueueInfo->uNumBlksUsed - newUsedBlks;
+
+#ifdef TI_DBG /* Sanity check: make sure we don't free more than is allocated. */
+ if (numBlksToFree > pQueueInfo->uNumBlksUsed)
+ {
+ TRACE5(pTxHwQueue->hReport, REPORT_SEVERITY_ERROR, ": Try to free more blks than used: Queue %d, ToFree %d, Used %d, HostAlloc=0x%x, FwFree=0x%x\n", uQueueId, numBlksToFree, pQueueInfo->uNumBlksUsed, pQueueInfo->uAllocatedBlksCntr, uFreeBlocks);
+ }
+#endif
+
+ /* Update total free blocks and Queue used blocks with the freed blocks number. */
+ pTxHwQueue->uNumTotalBlksFree += numBlksToFree;
+ pQueueInfo->uNumBlksUsed = newUsedBlks;
+
+ lowThreshold = pQueueInfo->uNumBlksThresh;
+
+ /* If after freeing the blocks we are using less than the low threshold,
+ update total reserved blocks number as follows:
+ (note: if we are above the low threshold after freeing the blocks we still have no reservation.)
+ */
+ if (newUsedBlks < lowThreshold)
+ {
+ newReserved = lowThreshold - newUsedBlks;
+ pQueueInfo->uNumBlksReserved = newReserved;
+
+
+ /* If freeing the blocks reduces the used blocks from above to below the low-threshold,
+ only the part from the low-threshold to the new used number is added to the
+ reserved blocks (because blocks are reserved for the Queue only up to its low-threshold):
+
+ 0 new used low old used high
+ |###########|####################|################| |
+ |###########|####################|################| |
+ <-------------- freed -------------->
+ <-- new reserved -->
+ old reserved = 0
+ */
+ if (numBlksToFree > newReserved)
+ pTxHwQueue->uNumTotalBlksReserved += newReserved; /* Add change to total reserved.*/
+
+
+ /* Else, if we were under the low-threshold before freeing these blocks,
+ all freed blocks are added to the reserved blocks:
+
+ 0 new used old used low high
+ |################|#################| | |
+ |################|#################| | |
+ <---- freed ---->
+ <- old reserved ->
+ <---------- new reserved ---------->
+ */
+ else
+ pTxHwQueue->uNumTotalBlksReserved += numBlksToFree; /* Add change to total reserved.*/
+ }
+
+ TRACE5(pTxHwQueue->hReport, REPORT_SEVERITY_INFORMATION, ": Queue %d, ToFree %d, Used %d, HostAlloc=0x%x, FwFree=0x%x\n", uQueueId, numBlksToFree, pQueueInfo->uNumBlksUsed, pQueueInfo->uAllocatedBlksCntr, uFreeBlocks);
+}
+
+
+/****************************************************************************
+ * txHwQueue_UpdateFreeResources()
+ ****************************************************************************
+ * DESCRIPTION:
+ ===========
+ Called by FwEvent upon Data interrupt to update freed HW-Queue resources as follows:
+ 1) For all queues, update blocks and descriptors numbers according to FwStatus information.
+ 2) For each busy queue, if now available indicate it in the backpressure bitmap.
+ ****************************************************************************/
+void txHwQueue_UpdateFreeResources (TI_HANDLE hTxHwQueue, FwStatus_t *pFwStatus)
+{
+ TTxHwQueue *pTxHwQueue = (TTxHwQueue *)hTxHwQueue;
+ TTxHwQueueInfo *pQueueInfo;
+ TI_UINT32 uQueueId;
+ TI_UINT32 uAvailableBlks; /* Max blocks available for current queue. */
+ TI_UINT32 uNewNumUsedDescriptors;
+ TI_UINT32 uBackpressure = 0;
+ TI_UINT32 *pFreeBlocks = (TI_UINT32 *)pFwStatus->txReleasedBlks;
+ TI_UINT32 uTempFwCounters;
+ FwStatCntrs_t *pFwStatusCounters;
+
+ /*
+ * If TxResults counter changed in FwStatus, update descriptors number according to information
+ */
+ uTempFwCounters = (ENDIAN_HANDLE_LONG(pFwStatus->counters));
+ pFwStatusCounters = (FwStatCntrs_t *)&uTempFwCounters;
+ if (pFwStatusCounters->txResultsCntr != pTxHwQueue->uFwTxResultsCntr)
+ {
+ pTxHwQueue->uFwTxResultsCntr = pFwStatusCounters->txResultsCntr;
+
+ /* Calculate new number of used descriptors (the else is for wrap around case) */
+ if (pTxHwQueue->uFwTxResultsCntr <= pTxHwQueue->uDrvTxPacketsCntr)
+ {
+ uNewNumUsedDescriptors = (TI_UINT32)(pTxHwQueue->uDrvTxPacketsCntr - pTxHwQueue->uFwTxResultsCntr);
+ }
+ else
+ {
+ uNewNumUsedDescriptors = 0x100 - (TI_UINT32)(pTxHwQueue->uFwTxResultsCntr - pTxHwQueue->uDrvTxPacketsCntr);
+ }
+
+#ifdef TI_DBG /* Sanity check: make sure we don't free more descriptors than allocated. */
+ if (uNewNumUsedDescriptors >= pTxHwQueue->uNumUsedDescriptors)
+ {
+ TRACE2(pTxHwQueue->hReport, REPORT_SEVERITY_ERROR, ": Used descriptors number should decrease: UsedDesc %d, NewUsedDesc %d\n", pTxHwQueue->uNumUsedDescriptors, uNewNumUsedDescriptors);
+ }
+#endif
+
+ /* Update number of packets left in FW (for descriptors allocation check). */
+ pTxHwQueue->uNumUsedDescriptors = uNewNumUsedDescriptors;
+ }
+
+ /*
+ * For all queues, update blocks numbers according to FwStatus information
+ */
+ for (uQueueId = 0; uQueueId < MAX_NUM_OF_AC; uQueueId++)
+ {
+ pQueueInfo = &(pTxHwQueue->aTxHwQueueInfo[uQueueId]);
+
+ /* Update per queue number of used, free and reserved blocks. */
+ txHwQueue_UpdateFreeBlocks (pTxHwQueue, uQueueId, pFreeBlocks[uQueueId]);
+ }
+
+ /*
+ * For each busy queue, if now available indicate it in the backpressure bitmap
+ */
+ for (uQueueId = 0; uQueueId < MAX_NUM_OF_AC; uQueueId++)
+ {
+ pQueueInfo = &(pTxHwQueue->aTxHwQueueInfo[uQueueId]);
+
+ /* If the queue was stopped */
+ if (pQueueInfo->bQueueBusy)
+ {
+ /* Find max available blocks for this queue (0 could indicate no descriptors). */
+ uAvailableBlks = txHwQueue_CheckResources (pTxHwQueue, pQueueInfo);
+
+ /* If the required blocks and a descriptor are available,
+ set the queue's backpressure bit to indicate NOT-busy! */
+ if (pQueueInfo->uNumBlksCausedBusy <= uAvailableBlks)
+ {
+ TRACE6(pTxHwQueue->hReport, REPORT_SEVERITY_INFORMATION, ": Queue Available, Queue=%d, ReqBlks=%d, FreeBlks=%d, UsedBlks=%d, AvailBlks=%d, UsedPkts=%d\n", uQueueId, pQueueInfo->uNumBlksCausedBusy, pTxHwQueue->uNumTotalBlksFree, pQueueInfo->uNumBlksUsed, uAvailableBlks, pTxHwQueue->uNumUsedDescriptors);
+ SET_QUEUE_BACKPRESSURE(&uBackpressure, uQueueId); /* Start queue. */
+ pQueueInfo->bQueueBusy = TI_FALSE;
+ }
+ }
+ }
+
+ /* If released queues map is not 0, send it to the upper layers (if CB available) */
+ if ((uBackpressure > 0) && (pTxHwQueue->fUpdateBusyMapCb != NULL))
+ {
+ pTxHwQueue->fUpdateBusyMapCb (pTxHwQueue->hUpdateBusyMapHndl, uBackpressure);
+ }
+}
+
+
+/****************************************************************************
+ * txHwQueue_CheckResources()
+ ****************************************************************************
+ * DESCRIPTION:
+ ============
+ Return the given queue's available blocks.
+ If no descriptors available, return 0.
+ ****************************************************************************/
+static TI_UINT32 txHwQueue_CheckResources (TTxHwQueue *pTxHwQueue, TTxHwQueueInfo *pQueueInfo)
+{
+ /* If descriptors are available: */
+ if (pTxHwQueue->uNumUsedDescriptors < NUM_TX_DESCRIPTORS)
+ {
+ /* Calculate how many buffers are available for this Queue: the total free buffers minus the buffers
+ that are reserved for other Queues (all reserved minus this Queue's reserved). */
+ return (pTxHwQueue->uNumTotalBlksFree - (pTxHwQueue->uNumTotalBlksReserved - pQueueInfo->uNumBlksReserved));
+ }
+
+ /* If no descriptors are available, return 0 (can't transmit anything). */
+ else
+ {
+ return 0;
+ }
+}
+
+
+/****************************************************************************
+ * txHwQueue_RegisterCb()
+ ****************************************************************************
+ * DESCRIPTION: Register the upper driver TxHwQueue callback functions.
+ ****************************************************************************/
+void txHwQueue_RegisterCb (TI_HANDLE hTxHwQueue, TI_UINT32 uCallBackId, void *fCbFunc, TI_HANDLE hCbHndl)
+{
+ TTxHwQueue *pTxHwQueue = (TTxHwQueue *)hTxHwQueue;
+
+ switch (uCallBackId)
+ {
+ case TWD_INT_UPDATE_BUSY_MAP:
+ pTxHwQueue->fUpdateBusyMapCb = (tUpdateBusyMapCb)fCbFunc;
+ pTxHwQueue->hUpdateBusyMapHndl = hCbHndl;
+ break;
+
+ default:
+ TRACE1(pTxHwQueue->hReport, REPORT_SEVERITY_ERROR, " - Illegal parameter = %d\n", uCallBackId);
+ return;
+ }
+}
+
+
+/****************************************************************************
+ * txHwQueue_PrintInfo()
+ ****************************************************************************
+ * DESCRIPTION: Print the Hw Queue module current information
+ ****************************************************************************/
+#ifdef TI_DBG
+void txHwQueue_PrintInfo (TI_HANDLE hTxHwQueue)
+{
+#ifdef REPORT_LOG
+ TTxHwQueue *pTxHwQueue = (TTxHwQueue *)hTxHwQueue;
+ TI_INT32 TxQid;
+
+ /* Print the Tx-HW-Queue information: */
+ WLAN_OS_REPORT(("Hw-Queues Information:\n"));
+ WLAN_OS_REPORT(("======================\n"));
+ WLAN_OS_REPORT(("Total Blocks: %d\n", pTxHwQueue->uNumTotalBlks));
+ WLAN_OS_REPORT(("Total Free Blocks: %d\n", pTxHwQueue->uNumTotalBlksFree));
+ WLAN_OS_REPORT(("Total Reserved Blocks: %d\n", pTxHwQueue->uNumTotalBlksReserved));
+ WLAN_OS_REPORT(("Total Used Descriptors: %d\n", pTxHwQueue->uNumUsedDescriptors));
+ WLAN_OS_REPORT(("FwTxResultsCntr: %d\n", pTxHwQueue->uFwTxResultsCntr));
+ WLAN_OS_REPORT(("DrvTxPacketsCntr: %d\n", pTxHwQueue->uDrvTxPacketsCntr));
+
+ for(TxQid = 0; TxQid < MAX_NUM_OF_AC; TxQid++)
+ {
+ WLAN_OS_REPORT(("Q=%d: Used=%d, Reserve=%d, Threshold=%d\n",
+ TxQid,
+ pTxHwQueue->aTxHwQueueInfo[TxQid].uNumBlksUsed,
+ pTxHwQueue->aTxHwQueueInfo[TxQid].uNumBlksReserved,
+ pTxHwQueue->aTxHwQueueInfo[TxQid].uNumBlksThresh));
+ }
+
+ WLAN_OS_REPORT(("\n"));
+
+ for(TxQid = 0; TxQid < MAX_NUM_OF_AC; TxQid++)
+ {
+ WLAN_OS_REPORT(("Queue=%d: HostAllocCount=0x%x, FwFreeCount=0x%x, BusyBlks=%d, Busy=%d\n",
+ TxQid,
+ pTxHwQueue->aTxHwQueueInfo[TxQid].uAllocatedBlksCntr,
+ pTxHwQueue->aTxHwQueueInfo[TxQid].uFwFreedBlksCntr,
+ pTxHwQueue->aTxHwQueueInfo[TxQid].uNumBlksCausedBusy,
+ pTxHwQueue->aTxHwQueueInfo[TxQid].bQueueBusy));
+ }
+#endif
+}
+
+#endif /* TI_DBG */
+