blob: 13ff1dc2f46d740c3c2911ecbb55dff86437fd8d [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Jeff Johnson32d95a32012-09-10 13:15:23 -07002 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -07003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/**=========================================================================
23 *
24 * \file wlan_qct_dti_bd.c
25 *
26 * \brief Datapath utilities file.
27 *
28 * WLAN Device Abstraction layer External API for Dataservice
29 * DESCRIPTION
30 * This file contains the external API implemntation exposed by the
31 * wlan device abstarction layer module.
32 *
33 * Copyright (c) 2008 QUALCOMM Incorporated. All Rights Reserved.
34 * Qualcomm Confidential and Proprietary
35 */
36
37#include "wlan_qct_wdi.h"
38#include "wlan_qct_wdi_ds.h"
39#include "wlan_qct_wdi_ds_i.h"
40#include "wlan_qct_wdi_dts.h"
41#include "wlan_qct_wdi_dp.h"
42#include "wlan_qct_pal_type.h"
43#include "wlan_qct_pal_status.h"
44#include "wlan_qct_pal_api.h"
45#include "wlan_qct_pal_packet.h"
46
47
48
49/*==========================================================================
50 *
51 FUNCTION WDI_DS_PrepareBDHeader
52
53 DESCRIPTION
54 function for preparing BD header before HAL processing.
55
56 PARAMETERS
57
58 IN
59palPacket: PAL packet pointer
60
61
62RETURN VALUE
63No return.
64
65SIDE EFFECTS
66
67============================================================================*/
68void
69WDI_DS_PrepareBDHeader (wpt_packet* palPacket,
70 wpt_uint8 ucDisableHWFrmXtl, wpt_uint8 alignment)
71{
72 void* pvBDHeader;
73 wpt_uint8 ucHeaderOffset;
74 wpt_uint8 ucHeaderLen;
75 wpt_uint8 ucQosEnabled;
76 wpt_uint8 ucWDSEnabled;
77 wpt_uint32 ucMpduLen;
78 wpt_uint32 ucPktLen;
79 WDI_DS_TxMetaInfoType *pTxMetadata;
80
81
82 /* Extract reuqired information from Metadata */
83 pvBDHeader = WPAL_PACKET_GET_BD_POINTER(palPacket);
84 pTxMetadata = WDI_DS_ExtractTxMetaData(palPacket);
85 ucQosEnabled = pTxMetadata->qosEnabled;
86 ucWDSEnabled = pTxMetadata->fenableWDS;
87
88 WPAL_PACKET_SET_BD_LENGTH(palPacket, WDI_TX_BD_HEADER_SIZE);
89
90 /*---------------------------------------------------------------------
91 Fill MPDU info fields:
92 - MPDU data start offset
93 - MPDU header start offset
94 - MPDU header length
95 - MPDU length - this is a 16b field - needs swapping
96 --------------------------------------------------------------------*/
97
98 if ( ucDisableHWFrmXtl ) {
99 ucHeaderOffset = WDI_TX_BD_HEADER_SIZE;
100 ucHeaderLen = WDI_802_11_HEADER_LEN;
101 if ( 0 != ucQosEnabled ) {
102 ucHeaderLen += WDI_802_11_HEADER_QOS_CTL;
103 }
104 if ( 0 != ucWDSEnabled) {
105 ucHeaderLen += WDI_802_11_HEADER_ADDR4_LEN;
106 }
107 } else {
108 ucHeaderOffset = WDI_TX_BD_HEADER_SIZE+WDI_802_11_MAX_HEADER_LEN;
109 ucHeaderLen = WDI_802_3_HEADER_LEN;
110 }
111
112 WDI_TX_BD_SET_MPDU_HEADER_LEN( pvBDHeader, ucHeaderLen);
113 WDI_TX_BD_SET_MPDU_HEADER_OFFSET( pvBDHeader, ucHeaderOffset);
114 WDI_TX_BD_SET_MPDU_DATA_OFFSET( pvBDHeader,
115 ucHeaderOffset + ucHeaderLen + alignment);
116
117 // pkt length from PAL API. Need to change in case of HW FT used
118 ucPktLen = wpalPacketGetLength( palPacket ); // This includes BD length
119 /** This is the length (in number of bytes) of the entire MPDU
120 (header and data). Note that the length INCLUDES FCS field. */
121 ucMpduLen = ucPktLen - WPAL_PACKET_GET_BD_LENGTH( palPacket );
122 WDI_TX_BD_SET_MPDU_LEN( pvBDHeader, ucMpduLen );
123
124 DTI_TRACE( DTI_TRACE_LEVEL_INFO,
125 "WLAN DTI: VALUES ARE HLen=%x Hoff=%x doff=%x len=%x ex=%d",
126 ucHeaderLen, ucHeaderOffset,
127 (ucHeaderOffset + ucHeaderLen + alignment),
128 pTxMetadata->fPktlen, alignment);
129
130}/* WDI_DS_PrepareBDHeader */
131
132/*==========================================================================
133 *
134 FUNCTIONS WDI_DS_MemPoolXXX
135
136 DESCRIPTION
137 APIs for managing the BD header memory pool
138 PARAMETERS
139
140 IN
141WDI_DS_BdMemPoolType: Memory pool pointer
142
143
144
145============================================================================*/
146
147/*
148 * Create a memory pool which is DMA capabale
149 */
150WDI_Status WDI_DS_MemPoolCreate(WDI_DS_BdMemPoolType *memPool, wpt_uint8 chunkSize,
151 wpt_uint8 numChunks)
152{
153 wpt_uint8 staLoop;
154
155 //Allocate all the max size and align them to a double word boundary. The first 8 bytes are control bytes.
156 memPool->numChunks = 0;
157 memPool->chunkSize = chunkSize + 16 - (chunkSize%8);
158 memPool->pVirtBaseAddress = wpalDmaMemoryAllocate((numChunks * memPool->chunkSize),
159 &(memPool->pPhysBaseAddress));
160
161 if( memPool->pVirtBaseAddress == 0)
162 return WDI_STATUS_E_FAILURE;
163
164 memPool->AllocationBitmap = (wpt_uint32*)wpalMemoryAllocate( (numChunks/32 + 1) * sizeof(wpt_uint32));
165 if( NULL == memPool->AllocationBitmap)
166 return WDI_STATUS_E_FAILURE;
167 wpalMemoryZero(memPool->AllocationBitmap, (numChunks/32+1)*sizeof(wpt_uint32));
168
169 //Initialize resource infor per STA
170 for(staLoop = 0; staLoop < WDI_DS_MAX_STA_ID; staLoop++)
171 {
172 memPool->numChunkSTA[staLoop].STAIndex = 0xFF;
173 memPool->numChunkSTA[staLoop].numChunkReservedBySTA = 0;
174 memPool->numChunkSTA[staLoop].validIdx = 0;
175 }
176
177 return WDI_STATUS_SUCCESS;
178}
179
180/*
181 * Destroy the memory pool
182 */
183void WDI_DS_MemPoolDestroy(WDI_DS_BdMemPoolType *memPool)
184{
185 //Allocate all the max size.
186 wpalDmaMemoryFree(memPool->pVirtBaseAddress);
187 wpalMemoryFree(memPool->AllocationBitmap);
188 wpalMemoryZero(memPool, sizeof(*memPool));
189}
190/*
191 * Allocate chunk memory
192 */
193WPT_STATIC WPT_INLINE int find_leading_zero_and_setbit(wpt_uint32 *bitmap, wpt_uint32 maxNumPool)
194{
195 wpt_uint32 i,j, word;
196
197 for(i=0; i < (maxNumPool/32 + 1); i++){
198 j = 0;
199 word = bitmap[i];
200 for(j=0; j< 32; j++){
201 if((word & 1) == 0) {
202 bitmap[i] |= (1 << j);
203 return((i<<5) + j);
204 }
205 word >>= 1;
206 }
207 }
208 return -1;
209}
210
211void *WDI_DS_MemPoolAlloc(WDI_DS_BdMemPoolType *memPool, void **pPhysAddress,
212 WDI_ResPoolType wdiResPool)
213{
214 wpt_uint32 index;
215 void *pVirtAddress;
216 wpt_uint32 maxNumPool;
217 switch(wdiResPool)
218 {
219 case WDI_MGMT_POOL_ID:
220 maxNumPool = WDI_DS_HI_PRI_RES_NUM;
221 break;
222 case WDI_DATA_POOL_ID:
223 maxNumPool = WDI_DS_LO_PRI_RES_NUM;
224 break;
225 default:
226 return NULL;
227 }
228
229 if(maxNumPool == memPool->numChunks)
230 {
231 return NULL;
232 }
233 //Find the leading 0 in the allocation bitmap
234
235 if((index = find_leading_zero_and_setbit(memPool->AllocationBitmap, maxNumPool)) == -1)
236 {
237 //DbgBreakPoint();
238 DTI_TRACE( DTI_TRACE_LEVEL_INFO, "WDI_DS_MemPoolAlloc: index:%d(NULL), numChunks:%d",
239 index, memPool->numChunks );
240 return NULL;
241 }
242 memPool->numChunks++;
243 // The first 8 bytes are reserved for internal use for control bits and hash.
244 pVirtAddress = (wpt_uint8 *)memPool->pVirtBaseAddress + (memPool->chunkSize * index) + 8;
245 *pPhysAddress = (wpt_uint8 *)memPool->pPhysBaseAddress + (memPool->chunkSize * index) + 8;
246
247 DTI_TRACE( DTI_TRACE_LEVEL_INFO, "WDI_DS_MemPoolAlloc: index:%d, numChunks:%d", index, memPool->numChunks );
248
249 return pVirtAddress;
250
251}
252
253/*
254 * Free chunk memory
255 */
256void WDI_DS_MemPoolFree(WDI_DS_BdMemPoolType *memPool, void *pVirtAddress, void *pPhysAddress)
257{
258 wpt_uint32 index =
259 ((wpt_uint8 *)pVirtAddress - (wpt_uint8 *)memPool->pVirtBaseAddress - 8)/memPool->chunkSize;
260 wpt_uint32 word = memPool->AllocationBitmap[index/32];
261 word &= ~(1<<(index%32));
262 memPool->AllocationBitmap[index/32] = word;
263 memPool->numChunks--;
264
265 //DbgPrint( "WDI_DS_MemPoolFree: index:%d, numChunks:%d", index, memPool->numChunks );
266}
267
268
269/**
270 @brief Returns the available number of resources (BD headers)
271 available for TX
272
273 @param pMemPool: pointer to the BD memory pool
274
275 @see
276 @return Result of the function call
277*/
278wpt_uint32 WDI_DS_GetAvailableResCount(WDI_DS_BdMemPoolType *pMemPool)
279{
280 return pMemPool->numChunks;
281}
282
283/**
284 @brief WDI_DS_MemPoolAddSTA
285 Add NEW STA into mempool
286
287 @param pMemPool: pointer to the BD memory pool
288 @param staId STA ID
289
290 @see
291 @return Result of the function call
292*/
293WDI_Status WDI_DS_MemPoolAddSTA(WDI_DS_BdMemPoolType *memPool, wpt_uint8 staIndex)
294{
295 if(memPool->numChunkSTA[staIndex].STAIndex != 0xFF)
296 {
297 /* Already using this slot? Do nothing */
298 return WDI_STATUS_SUCCESS;
299 }
300
301 memPool->numChunkSTA[staIndex].STAIndex = staIndex;
302 memPool->numChunkSTA[staIndex].numChunkReservedBySTA = 0;
303 memPool->numChunkSTA[staIndex].validIdx = 1;
304 return WDI_STATUS_SUCCESS;
305}
306
307/**
308 @brief WDI_DS_MemPoolAddSTA
309 Remove STA from mempool
310
311 @param pMemPool: pointer to the BD memory pool
312 @param staId STA ID
313
314 @see
315 @return Result of the function call
316*/
317WDI_Status WDI_DS_MemPoolDelSTA(WDI_DS_BdMemPoolType *memPool, wpt_uint8 staIndex)
318{
319 if(memPool->numChunkSTA[staIndex].STAIndex == 0xFF)
320 {
321 /* Empty this slot? error, bad argument */
322 return WDI_STATUS_E_FAILURE;
323 }
324
325 memPool->numChunkSTA[staIndex].STAIndex = 0xFF;
326 memPool->numChunkSTA[staIndex].numChunkReservedBySTA = 0;
327 memPool->numChunkSTA[staIndex].validIdx = 0;
328 return WDI_STATUS_SUCCESS;
329}
330
331/**
332 @brief Returns the reserved number of resources (BD headers) per STA
333 available for TX
334
335 @param pMemPool: pointer to the BD memory pool
336 @param staId STA ID
337 @see
338 @return Result of the function call
339*/
340wpt_uint32 WDI_DS_MemPoolGetRsvdResCountPerSTA(WDI_DS_BdMemPoolType *pMemPool, wpt_uint8 staId)
341{
342 return pMemPool->numChunkSTA[staId].numChunkReservedBySTA;
343}
344
345/**
346 @brief Increase reserved TX resource count by specific STA
347
348 @param pMemPool: pointer to the BD memory pool
349 @param staId STA ID
350 @see
351 @return Result of the function call
352*/
353void WDI_DS_MemPoolIncreaseReserveCount(WDI_DS_BdMemPoolType *memPool, wpt_uint8 staId)
354{
355
356 if((memPool->numChunkSTA[staId].validIdx) && (staId < WDI_DS_MAX_STA_ID))
357 {
358 memPool->numChunkSTA[staId].numChunkReservedBySTA++;
359 }
360 return;
361}
362
363/**
364 @brief Decrease reserved TX resource count by specific STA
365
366 @param pMemPool: pointer to the BD memory pool
367 @param staId STA ID
368 @see
369 @return Result of the function call
370*/
371void WDI_DS_MemPoolDecreaseReserveCount(WDI_DS_BdMemPoolType *memPool, wpt_uint8 staId)
372{
373 if(0 == memPool->numChunkSTA[staId].numChunkReservedBySTA)
374 {
375 DTI_TRACE( DTI_TRACE_LEVEL_ERROR,
376 "SAT %d reserved resource count cannot be smaller than 0", staId );
377 return;
378 }
379
380 if((memPool->numChunkSTA[staId].validIdx) && (staId < WDI_DS_MAX_STA_ID))
381 {
382 memPool->numChunkSTA[staId].numChunkReservedBySTA--;
383 }
384 return;
385}