1 /*
2 * txCtrlBlk.c
3 *
4 * Copyright(c) 1998 - 2009 Texas Instruments. All rights reserved.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name Texas Instruments nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34
35 /****************************************************************************
36 *
37 * MODULE: txCtrlBlk.c
38 *
39 * PURPOSE: Maintains active packets Tx attributes table (including descriptor).
40 *
41 * DESCRIPTION:
42 * ============
43 * This module allocates and frees table entry for each packet in the Tx
44 * process (from sendPkt by upper driver until Tx-complete).
45 *
46 ****************************************************************************/
47 #define __FILE_ID__ FILE_ID_99
48 #include "osApi.h"
49 #include "tidef.h"
50 #include "report.h"
51 #include "context.h"
52 #include "TWDriver.h"
53 #include "txCtrlBlk_api.h"
54
55
56 /* The TxCtrlBlk module object - contains the control-block table. */
57 typedef struct
58 {
59 TI_HANDLE hOs;
60 TI_HANDLE hReport;
61 TI_HANDLE hContext;
62
63 TTxCtrlBlk aTxCtrlBlkTbl[CTRL_BLK_ENTRIES_NUM]; /* The table of control-block entries. */
64
65 #ifdef TI_DBG /* Just for debug. */
66 TI_UINT32 uNumUsedEntries;
67 #endif
68
69 } TTxCtrlBlkObj;
70
71
72 /****************************************************************************
73 * txCtrlBlk_Create()
74 ****************************************************************************
75 * DESCRIPTION: Create the Tx control block table object
76 *
77 * INPUTS: hOs
78 *
79 * OUTPUT: None
80 *
81 * RETURNS: The Created object
82 ****************************************************************************/
txCtrlBlk_Create(TI_HANDLE hOs)83 TI_HANDLE txCtrlBlk_Create (TI_HANDLE hOs)
84 {
85 TTxCtrlBlkObj *pTxCtrlBlk;
86
87 pTxCtrlBlk = os_memoryAlloc (hOs, sizeof(TTxCtrlBlkObj));
88 if (pTxCtrlBlk == NULL)
89 return NULL;
90
91 os_memoryZero (hOs, pTxCtrlBlk, sizeof(TTxCtrlBlkObj));
92
93 pTxCtrlBlk->hOs = hOs;
94
95 return( (TI_HANDLE)pTxCtrlBlk );
96 }
97
98
99 /****************************************************************************
100 * txCtrlBlk_Destroy()
101 ****************************************************************************
102 * DESCRIPTION: Destroy the Tx control block table object
103 *
104 * INPUTS: hTxCtrlBlk - The object to free
105 *
106 * OUTPUT: None
107 *
108 * RETURNS: TI_OK or TI_NOK
109 ****************************************************************************/
txCtrlBlk_Destroy(TI_HANDLE hTxCtrlBlk)110 TI_STATUS txCtrlBlk_Destroy (TI_HANDLE hTxCtrlBlk)
111 {
112 TTxCtrlBlkObj *pTxCtrlBlk = (TTxCtrlBlkObj *)hTxCtrlBlk;
113
114 if (pTxCtrlBlk)
115 os_memoryFree(pTxCtrlBlk->hOs, pTxCtrlBlk, sizeof(TTxCtrlBlkObj));
116
117 return TI_OK;
118 }
119
120
121 /****************************************************************************
122 * txCtrlBlk_Init()
123 ****************************************************************************
124 DESCRIPTION: Initialize the Tx control block module.
125 ****************************************************************************/
txCtrlBlk_Init(TI_HANDLE hTxCtrlBlk,TI_HANDLE hReport,TI_HANDLE hContext)126 TI_STATUS txCtrlBlk_Init (TI_HANDLE hTxCtrlBlk, TI_HANDLE hReport, TI_HANDLE hContext)
127 {
128 TTxCtrlBlkObj *pTxCtrlBlk = (TTxCtrlBlkObj *)hTxCtrlBlk;
129 TTxnStruct *pTxn;
130 TI_UINT8 entry;
131
132 pTxCtrlBlk->hReport = hReport;
133 pTxCtrlBlk->hContext = hContext;
134
135 /* For all entries, write the entry index in the descriptor and the next entry address
136 in the next free entery pointer. Init also some other fields. */
137 for(entry = 0; entry < CTRL_BLK_ENTRIES_NUM; entry++)
138 {
139 pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.descID = entry;
140 pTxCtrlBlk->aTxCtrlBlkTbl[entry].pNextFreeEntry = &(pTxCtrlBlk->aTxCtrlBlkTbl[entry + 1]);
141 pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.aid = 1; /* The value for infrastructure BSS */
142 pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.reserved = 0;
143
144 /* Prepare the Txn fields to the host-slave register (fixed address) */
145 pTxn = &(pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxnStruct);
146 TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_FIXED_ADDR)
147 }
148
149 /* Write null in the next-free index of the last entry. */
150 pTxCtrlBlk->aTxCtrlBlkTbl[CTRL_BLK_ENTRIES_NUM - 1].pNextFreeEntry = NULL;
151
152 #ifdef TI_DBG
153 pTxCtrlBlk->uNumUsedEntries = 0;
154 #endif
155
156 return TI_OK;
157 }
158
159
160 /****************************************************************************
161 * txCtrlBlk_Alloc()
162 ****************************************************************************
163 * DESCRIPTION:
164 Allocate a free control-block entry for the current Tx packet's parameters
165 (including the descriptor structure).
166 Note that entry 0 in the list is never allocated and points to the
167 first free entry.
168 ****************************************************************************/
txCtrlBlk_Alloc(TI_HANDLE hTxCtrlBlk)169 TTxCtrlBlk *txCtrlBlk_Alloc (TI_HANDLE hTxCtrlBlk)
170 {
171 TTxCtrlBlkObj *pTxCtrlBlk = (TTxCtrlBlkObj *)hTxCtrlBlk;
172 TTxCtrlBlk *pCurrentEntry; /* The pointer of the new entry allocated for the packet. */
173 TTxCtrlBlk *pFirstFreeEntry; /* The first entry just points to the first free entry. */
174
175 pFirstFreeEntry = &(pTxCtrlBlk->aTxCtrlBlkTbl[0]);
176
177 /* Protect block allocation from preemption (may be called from external context) */
178 context_EnterCriticalSection (pTxCtrlBlk->hContext);
179
180 pCurrentEntry = pFirstFreeEntry->pNextFreeEntry; /* Get free entry. */
181
182 #ifdef TI_DBG
183 /* If no free entries, print error (not expected to happen) and return NULL. */
184 if (pCurrentEntry->pNextFreeEntry == NULL)
185 {
186 TRACE1(pTxCtrlBlk->hReport, REPORT_SEVERITY_ERROR, "txCtrlBlk_alloc(): No free entry, UsedEntries=%d\n", pTxCtrlBlk->uNumUsedEntries);
187 context_LeaveCriticalSection (pTxCtrlBlk->hContext);
188 return NULL;
189 }
190 pTxCtrlBlk->uNumUsedEntries++;
191 #endif
192
193 /* Link the first entry to the next free entry. */
194 pFirstFreeEntry->pNextFreeEntry = pCurrentEntry->pNextFreeEntry;
195
196 context_LeaveCriticalSection (pTxCtrlBlk->hContext);
197
198 /* Clear the next-free-entry index just as an indication that our entry is not free. */
199 pCurrentEntry->pNextFreeEntry = 0;
200
201 pCurrentEntry->tTxPktParams.uFlags = 0;
202 pCurrentEntry->tTxPktParams.uHeadroomSize = 0;
203
204 return pCurrentEntry;
205 }
206
207
208 /****************************************************************************
209 * txCtrlBlk_Free()
210 ****************************************************************************
211 * DESCRIPTION:
212 Link the freed entry after entry 0, so now it is the first free entry to
213 be allocated.
214 ****************************************************************************/
txCtrlBlk_Free(TI_HANDLE hTxCtrlBlk,TTxCtrlBlk * pCurrentEntry)215 void txCtrlBlk_Free (TI_HANDLE hTxCtrlBlk, TTxCtrlBlk *pCurrentEntry)
216 {
217 TTxCtrlBlkObj *pTxCtrlBlk = (TTxCtrlBlkObj *)hTxCtrlBlk;
218 TTxCtrlBlk *pFirstFreeEntry = &(pTxCtrlBlk->aTxCtrlBlkTbl[0]);
219
220 if (!pTxCtrlBlk)
221 {
222 return;
223 }
224
225 #ifdef TI_DBG
226 /* If the pointed entry is already free, print error and exit (not expected to happen). */
227 if (pCurrentEntry->pNextFreeEntry != 0)
228 {
229 TRACE2(pTxCtrlBlk->hReport, REPORT_SEVERITY_ERROR, "txCtrlBlk_free(): Entry %d alredy free, UsedEntries=%d\n", pCurrentEntry->tTxDescriptor.descID, pTxCtrlBlk->uNumUsedEntries);
230 return;
231 }
232 pTxCtrlBlk->uNumUsedEntries--;
233 #endif
234
235 /* Protect block freeing from preemption (may be called from external context) */
236 context_EnterCriticalSection (pTxCtrlBlk->hContext);
237
238 /* Link the freed entry between entry 0 and the next free entry. */
239 pCurrentEntry->pNextFreeEntry = pFirstFreeEntry->pNextFreeEntry;
240 pFirstFreeEntry->pNextFreeEntry = pCurrentEntry;
241
242 context_LeaveCriticalSection (pTxCtrlBlk->hContext);
243 }
244
245
246 /****************************************************************************
247 * txCtrlBlk_GetPointer()
248 ****************************************************************************
249 * DESCRIPTION:
250 Return a pointer to the control block entry of the requested packet.
251 Used upon tx-complete to retrieve info after getting the descId from the FW.
252 ****************************************************************************/
txCtrlBlk_GetPointer(TI_HANDLE hTxCtrlBlk,TI_UINT8 descId)253 TTxCtrlBlk *txCtrlBlk_GetPointer (TI_HANDLE hTxCtrlBlk, TI_UINT8 descId)
254 {
255 TTxCtrlBlkObj *pTxCtrlBlk = (TTxCtrlBlkObj *)hTxCtrlBlk;
256 return ( &(pTxCtrlBlk->aTxCtrlBlkTbl[descId]) );
257 }
258
259
260 /****************************************************************************
261 * txCtrlBlk_PrintTable()
262 ****************************************************************************
263 * DESCRIPTION: Print the txCtrlBlk table main fields.
264 ****************************************************************************/
265 #ifdef TI_DBG
txCtrlBlk_PrintTable(TI_HANDLE hTxCtrlBlk)266 void txCtrlBlk_PrintTable (TI_HANDLE hTxCtrlBlk)
267 {
268 #ifdef REPORT_LOG
269 TTxCtrlBlkObj *pTxCtrlBlk = (TTxCtrlBlkObj *)hTxCtrlBlk;
270 TI_UINT8 entry;
271
272 WLAN_OS_REPORT((" Tx-Control-Block Information, UsedEntries=%d\n", pTxCtrlBlk->uNumUsedEntries));
273 WLAN_OS_REPORT(("==============================================\n"));
274
275 for(entry = 0; entry < CTRL_BLK_ENTRIES_NUM; entry++)
276 {
277 WLAN_OS_REPORT(("Entry %d: DescID=%d, Next=0x%x, Len=%d, StartTime=%d, TID=%d, ExtraBlks=%d, TotalBlks=%d, Flags=0x%x\n",
278 entry,
279 pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.descID,
280 pTxCtrlBlk->aTxCtrlBlkTbl[entry].pNextFreeEntry,
281 ENDIAN_HANDLE_WORD(pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.length),
282 ENDIAN_HANDLE_LONG(pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.startTime),
283 pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.tid,
284 pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.extraMemBlks,
285 pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.totalMemBlks,
286 pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxPktParams.uFlags));
287 }
288 #endif
289 }
290 #endif /* TI_DBG */
291
292