blob: e10c5c8ed8eb143fa2245aec23937390689e381d [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_wdi_ds.c
45 *
46 * \brief define Dataservice API
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
58#include "wlan_qct_wdi.h"
59#include "wlan_qct_wdi_i.h"
60#include "wlan_qct_wdi_ds.h"
61#include "wlan_qct_wdi_ds_i.h"
62#include "wlan_qct_wdi_dts.h"
63#include "wlan_qct_wdi_dp.h"
64#include "wlan_qct_wdi_sta.h"
65
66
67
68
69/* DAL registration function.
70 * Parameters:
71 * pContext:Cookie that should be passed back to the caller along
72 * with the callback.
73 * pfnTxCompleteCallback:Callback function that is to be invoked to return
74 * packets which have been transmitted.
75 * pfnRxPacketCallback:Callback function that is to be invoked to deliver
76 * packets which have been received
77 * pfnTxFlowControlCallback:Callback function that is to be invoked to
78 * indicate/clear congestion.
79 *
80 * Return Value: SUCCESS Completed successfully.
81 * FAILURE_XXX Request was rejected due XXX Reason.
82 *
83 */
84WDI_Status WDI_DS_Register( void *pContext,
85 WDI_DS_TxCompleteCallback pfnTxCompleteCallback,
86 WDI_DS_RxPacketCallback pfnRxPacketCallback,
87 WDI_DS_TxFlowControlCallback pfnTxFlowControlCallback,
88 void *pCallbackContext)
89{
90 WDI_DS_ClientDataType *pClientData;
91 wpt_uint8 bssLoop;
92
93 // Do Sanity checks
94 if (NULL == pContext ||
95 NULL == pCallbackContext ||
96 NULL == pfnTxCompleteCallback ||
97 NULL == pfnRxPacketCallback ||
98 NULL == pfnTxFlowControlCallback) {
99 return WDI_STATUS_E_FAILURE;
100 }
101
102 pClientData = (WDI_DS_ClientDataType *)WDI_DS_GetDatapathContext(pContext);
103 if (NULL == pClientData)
104 {
105 return WDI_STATUS_MEM_FAILURE;
106 }
107
108 // Store callbacks in client structure
109 pClientData->pcontext = pContext;
110 pClientData->receiveFrameCB = pfnRxPacketCallback;
111 pClientData->txCompleteCB = pfnTxCompleteCallback;
112 pClientData->txResourceCB = pfnTxFlowControlCallback;
113 pClientData->pCallbackContext = pCallbackContext;
114
115 for(bssLoop = 0; bssLoop < WDI_DS_MAX_SUPPORTED_BSS; bssLoop++)
116 {
117 pClientData->staIdxPerBssIdxTable[bssLoop].isUsed = 0;
118 pClientData->staIdxPerBssIdxTable[bssLoop].bssIdx = WDI_DS_INDEX_INVALID;
119 pClientData->staIdxPerBssIdxTable[bssLoop].staIdx = WDI_DS_INDEX_INVALID;
120 }
121 return WDI_STATUS_SUCCESS;
122}
123
124
125
126/* DAL Transmit function.
127 * Parameters:
128 * pContext:Cookie that should be passed back to the caller along with the callback.
129 * pFrame:Refernce to PAL frame.
130 * more: Does the invokee have more than one packet pending?
131 * Return Value: SUCCESS Completed successfully.
132 * FAILURE_XXX Request was rejected due XXX Reason.
133 *
134 */
135
136
137WDI_Status WDI_DS_TxPacket(void *pContext,
138 wpt_packet *pFrame,
139 wpt_boolean more)
140{
141 WDI_DS_ClientDataType *pClientData;
142 wpt_uint8 ucSwFrameTXXlation;
143 wpt_uint8 ucUP;
144 wpt_uint8 ucTypeSubtype;
145 wpt_uint8 alignment;
146 wpt_uint8 ucTxFlag;
147 wpt_uint8* pSTAMACAddress;
148 wpt_uint8* pAddr2MACAddress;
149 WDI_DS_TxMetaInfoType *pTxMetadata;
150 void *physBDHeader, *pvBDHeader;
151 wpt_uint8 ucType;
152 WDI_DS_BdMemPoolType *pMemPool;
153 wpt_uint8 ucBdPoolType;
154 wpt_uint8 staId;
155
156 // Do Sanity checks
157 if (NULL == pContext)
158 {
159 return WDI_STATUS_E_FAILURE;
160 }
161
162 pClientData = (WDI_DS_ClientDataType *) WDI_DS_GetDatapathContext(pContext);
163 if (NULL == pClientData || pClientData->suspend)
164 {
165 return WDI_STATUS_E_FAILURE;
166 }
167
168 // extract metadata from PAL packet
169 pTxMetadata = WDI_DS_ExtractTxMetaData(pFrame);
170 ucSwFrameTXXlation = pTxMetadata->fdisableFrmXlt;
171 ucTypeSubtype = pTxMetadata->typeSubtype;
172 ucUP = pTxMetadata->fUP;
173 ucTxFlag = pTxMetadata->txFlags;
174 pSTAMACAddress = &(pTxMetadata->fSTAMACAddress[0]);
175 pAddr2MACAddress = &(pTxMetadata->addr2MACAddress[0]);
176
177 /*------------------------------------------------------------------------
178 Get type and subtype of the frame first
179 ------------------------------------------------------------------------*/
180 ucType = (ucTypeSubtype & WDI_FRAME_TYPE_MASK) >> WDI_FRAME_TYPE_OFFSET;
181 switch(ucType)
182 {
183 case WDI_MAC_DATA_FRAME:
Madan Mohan Koyyalamudi1541a5b2012-10-29 16:18:21 -0700184 if(!pTxMetadata->isEapol)
185 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700186 pMemPool = &(pClientData->dataMemPool);
187 ucBdPoolType = WDI_DATA_POOL_ID;
Madan Mohan Koyyalamudi1541a5b2012-10-29 16:18:21 -0700188 break;
189 }
190 // intentional fall-through to handle eapol packet as mgmt
Jeff Johnson295189b2012-06-20 16:38:30 -0700191 case WDI_MAC_MGMT_FRAME:
192 pMemPool = &(pClientData->mgmtMemPool);
193 ucBdPoolType = WDI_MGMT_POOL_ID;
194 break;
195 default:
Madan Mohan Koyyalamudi4e31b132012-11-02 13:13:52 -0700196 return WDI_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700197 }
198
199 // Allocate BD header from pool
200 pvBDHeader = WDI_DS_MemPoolAlloc(pMemPool, &physBDHeader, ucBdPoolType);
201 if(NULL == pvBDHeader)
202 return WDI_STATUS_E_FAILURE;
203
204 WDI_SetBDPointers(pFrame, pvBDHeader, physBDHeader);
205
206 alignment = 0;
207 WDI_DS_PrepareBDHeader(pFrame, ucSwFrameTXXlation, alignment);
208
209 if(WDI_STATUS_SUCCESS !=
210 WDI_FillTxBd( pContext, ucTypeSubtype, pSTAMACAddress, pAddr2MACAddress,
211 &ucUP, 1, pvBDHeader, ucTxFlag /* No ACK */, 0, &staId)){
212 WDI_DS_MemPoolFree(pMemPool, pvBDHeader, physBDHeader);
213 return WDI_STATUS_E_FAILURE;
214 }
215 // Send packet to transport layer.
216 if(eWLAN_PAL_STATUS_SUCCESS !=WDTS_TxPacket(pContext, pFrame)){
217 WDI_DS_MemPoolFree(pMemPool, pvBDHeader, physBDHeader);
218 return WDI_STATUS_E_FAILURE;
219 }
220
221 /* resource count only for data packet */
Madan Mohan Koyyalamudi1541a5b2012-10-29 16:18:21 -0700222 // EAPOL packet doesn't use data mem pool if being treated as higher priority
223 if(WDI_MAC_DATA_FRAME == ucType && (!pTxMetadata->isEapol))
Jeff Johnson295189b2012-06-20 16:38:30 -0700224 {
225 WDI_DS_MemPoolIncreaseReserveCount(pMemPool, staId);
226 }
227 return WDI_STATUS_SUCCESS;
228}
229
230
231/* DAL Transmit Complete function.
232 * Parameters:
233 * pContext:Cookie that should be passed back to the caller along with the callback.
234 * ucTxResReq:TX resource number required by TL
235 * Return Value: SUCCESS Completed successfully.
236 * FAILURE_XXX Request was rejected due XXX Reason.
237 *
238 */
239
240
241WDI_Status WDI_DS_TxComplete(void *pContext, wpt_uint32 ucTxResReq)
242{
243 // Do Sanity checks
244 if(NULL == pContext)
245 return WDI_STATUS_E_FAILURE;
246
247 // Send notification to transport layer.
248 if(eWLAN_PAL_STATUS_SUCCESS !=WDTS_CompleteTx(pContext, ucTxResReq))
249 {
250 return WDI_STATUS_E_FAILURE;
251 }
252
253 return WDI_STATUS_SUCCESS;
254}
255
256/* DAL Suspend Transmit function.
257 * Parameters:
258 * pContext:Cookie that should be passed back to the caller along with the callback.
259 * Return Value: SUCCESS Completed successfully.
260 * FAILURE_XXX Request was rejected due XXX Reason.
261 *
262 */
263
264
265WDI_Status WDI_DS_TxSuspend(void *pContext)
266{
267 WDI_DS_ClientDataType *pClientData =
268 (WDI_DS_ClientDataType *) WDI_DS_GetDatapathContext(pContext);
269 pClientData->suspend = 1;
270
271 return WDI_STATUS_SUCCESS;
272
273}
274
275
276/* DAL Resume Transmit function.
277 * Parameters:
278 * pContext:Cookie that should be passed back to the caller along with the callback.
279 * Return Value: SUCCESS Completed successfully.
280 * FAILURE_XXX Request was rejected due XXX Reason.
281 *
282 */
283
284
285WDI_Status WDI_DS_TxResume(void *pContext)
286{
287 WDI_DS_ClientDataType *pClientData =
288 (WDI_DS_ClientDataType *) WDI_DS_GetDatapathContext(pContext);
289
290 pClientData->suspend = 0;
291
292 return WDI_STATUS_SUCCESS;
293}
294
295/* DAL Get Available Resource Count.
296 * This is the number of free descririptor in DXE
297 * Parameters:
298 * pContext:Cookie that should be passed back to the caller along with the callback.
299 * wdiResPool: - identifier of resource pool
300 * Return Value: number of resources available
301 * This is the number of free descririptor in DXE
302 *
303 */
304
305wpt_uint32 WDI_GetAvailableResCount(void *pContext,WDI_ResPoolType wdiResPool)
306{
307 WDI_DS_ClientDataType *pClientData =
308 (WDI_DS_ClientDataType *) WDI_DS_GetDatapathContext(pContext);
309
310 switch(wdiResPool)
311 {
312 case WDI_MGMT_POOL_ID:
313 return (WDI_DS_HI_PRI_RES_NUM - 2*WDI_DS_GetAvailableResCount(&pClientData->mgmtMemPool));
314 case WDI_DATA_POOL_ID:
315 return WDTS_GetFreeTxDataResNumber(pContext);
316 default:
317 return 0;
318 }
319}
320
321/* DAL Get resrved Resource Count per STA.
322 * Parameters:
323 * pContext:Cookie that should be passed back to the caller along with the callback.
324 * wdiResPool: - identifier of resource pool
325 * staId: STA ID
326 * Return Value: number of resources reserved per STA
327 *
328 */
329wpt_uint32 WDI_DS_GetReservedResCountPerSTA(void *pContext,WDI_ResPoolType wdiResPool, wpt_uint8 staId)
330{
331 WDI_DS_ClientDataType *pClientData =
332 (WDI_DS_ClientDataType *) WDI_DS_GetDatapathContext(pContext);
333 switch(wdiResPool)
334 {
335 case WDI_MGMT_POOL_ID:
336 return WDI_DS_MemPoolGetRsvdResCountPerSTA(&pClientData->mgmtMemPool, staId);
337 case WDI_DATA_POOL_ID:
338 return WDI_DS_MemPoolGetRsvdResCountPerSTA(&pClientData->dataMemPool, staId);
339 default:
340 return 0;
341 }
342}
343
344/* DAL STA info add into memPool.
345 * Parameters:
346 * pContext:Cookie that should be passed back to the caller along with the callback.
347 * staId: STA ID
348 * Return Value: number of resources reserved per STA
349 *
350 */
351WDI_Status WDI_DS_AddSTAMemPool(void *pContext, wpt_uint8 staIndex)
352{
353 WDI_Status status = WDI_STATUS_SUCCESS;
354 WDI_DS_ClientDataType *pClientData =
355 (WDI_DS_ClientDataType *) WDI_DS_GetDatapathContext(pContext);
356
357 status = WDI_DS_MemPoolAddSTA(&pClientData->mgmtMemPool, staIndex);
358 if(WDI_STATUS_SUCCESS != status)
359 {
360 /* Add STA into MGMT memPool Fail */
361 return status;
362 }
363
364 status = WDI_DS_MemPoolAddSTA(&pClientData->dataMemPool, staIndex);
365 if(WDI_STATUS_SUCCESS != status)
366 {
367 /* Add STA into DATA memPool Fail */
368 return status;
369 }
370
371 return WDI_STATUS_SUCCESS;
372}
373
374/* DAL STA info del from memPool.
375 * Parameters:
376 * pContext:Cookie that should be passed back to the caller along with the callback.
377 * staId: STA ID
378 * Return Value: number of resources reserved per STA
379 *
380 */
381WDI_Status WDI_DS_DelSTAMemPool(void *pContext, wpt_uint8 staIndex)
382{
383 WDI_Status status = WDI_STATUS_SUCCESS;
384 WDI_DS_ClientDataType *pClientData =
385 (WDI_DS_ClientDataType *) WDI_DS_GetDatapathContext(pContext);
386
387 status = WDI_DS_MemPoolDelSTA(&pClientData->mgmtMemPool, staIndex);
388 if(WDI_STATUS_SUCCESS != status)
389 {
390 /* Del STA from MGMT memPool Fail */
391 return status;
392 }
393 status = WDI_DS_MemPoolDelSTA(&pClientData->dataMemPool, staIndex);
394 if(WDI_STATUS_SUCCESS != status)
395 {
396 /* Del STA from DATA memPool Fail */
397 return status;
398 }
399 return WDI_STATUS_SUCCESS;
400}
401
402/* DAL Set STA index associated with BSS index.
403 * Parameters:
404 * pContext:Cookie that should be passed back to the caller along with the callback.
405 * bssIdx: BSS index
406 * staId: STA index associated with BSS index
407 * Return Status: Found empty slot
408 *
409 */
410WDI_Status WDI_DS_SetStaIdxPerBssIdx(void *pContext, wpt_uint8 bssIdx, wpt_uint8 staIdx)
411{
412 WDI_DS_ClientDataType *pClientData;
413 wpt_uint8 bssLoop;
414
415 pClientData = (WDI_DS_ClientDataType *)WDI_DS_GetDatapathContext(pContext);
416 for (bssLoop = 0; bssLoop < WDI_DS_MAX_SUPPORTED_BSS; bssLoop++)
417 {
418 if ((pClientData->staIdxPerBssIdxTable[bssLoop].isUsed) &&
419 (bssIdx == pClientData->staIdxPerBssIdxTable[bssLoop].bssIdx) &&
420 (staIdx == pClientData->staIdxPerBssIdxTable[bssLoop].staIdx))
421 {
422 return WDI_STATUS_SUCCESS;
423 }
424
425 if (0 == pClientData->staIdxPerBssIdxTable[bssLoop].isUsed)
426 {
427 pClientData->staIdxPerBssIdxTable[bssLoop].bssIdx = bssIdx;
428 pClientData->staIdxPerBssIdxTable[bssLoop].staIdx = staIdx;
429 pClientData->staIdxPerBssIdxTable[bssLoop].isUsed = 1;
430 return WDI_STATUS_SUCCESS;
431 }
432 }
433
434 /* Could not find empty slot */
435 return WDI_STATUS_E_FAILURE;
436}
437
438/* DAL Get STA index associated with BSS index.
439 * Parameters:
440 * pContext:Cookie that should be passed back to the caller along with the callback.
441 * bssIdx: BSS index
442 * staId: STA index associated with BSS index
443 * Return Status: Found empty slot
444 *
445 */
446WDI_Status WDI_DS_GetStaIdxFromBssIdx(void *pContext, wpt_uint8 bssIdx, wpt_uint8 *staIdx)
447{
448 WDI_DS_ClientDataType *pClientData;
449 wpt_uint8 bssLoop;
450
451 pClientData = (WDI_DS_ClientDataType *)WDI_DS_GetDatapathContext(pContext);
452 for(bssLoop = 0; bssLoop < WDI_DS_MAX_SUPPORTED_BSS; bssLoop++)
453 {
454 if(bssIdx == pClientData->staIdxPerBssIdxTable[bssLoop].bssIdx)
455 {
456 /* Found BSS index from slot */
457 *staIdx = pClientData->staIdxPerBssIdxTable[bssLoop].staIdx;
458 return WDI_STATUS_SUCCESS;
459 }
460 }
461
462 /* Could not find associated STA index with BSS index */
463 return WDI_STATUS_E_FAILURE;
464}
465
466/* DAL Clear STA index associated with BSS index.
467 * Parameters:
468 * pContext:Cookie that should be passed back to the caller along with the callback.
469 * bssIdx: BSS index
470 * staId: STA index associated with BSS index
471 * Return Status: Found empty slot
472 *
473 */
474WDI_Status WDI_DS_ClearStaIdxPerBssIdx(void *pContext, wpt_uint8 bssIdx, wpt_uint8 staIdx)
475{
476 WDI_DS_ClientDataType *pClientData;
477 wpt_uint8 bssLoop;
478
479 pClientData = (WDI_DS_ClientDataType *)WDI_DS_GetDatapathContext(pContext);
480 for(bssLoop = 0; bssLoop < WDI_DS_MAX_SUPPORTED_BSS; bssLoop++)
481 {
482 if((bssIdx == pClientData->staIdxPerBssIdxTable[bssLoop].bssIdx) &&
483 (staIdx == pClientData->staIdxPerBssIdxTable[bssLoop].staIdx))
484 {
485 pClientData->staIdxPerBssIdxTable[bssLoop].bssIdx = WDI_DS_INDEX_INVALID;
486 pClientData->staIdxPerBssIdxTable[bssLoop].staIdx = WDI_DS_INDEX_INVALID;
487 pClientData->staIdxPerBssIdxTable[bssLoop].isUsed = 0;
488 return WDI_STATUS_SUCCESS;
489 }
490 }
491
492 /* Could not find associated STA index with BSS index */
493 return WDI_STATUS_E_FAILURE;
494}