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