blob: d5523c23a37100eb85d8fcbda75cfabf41086feb [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_dxe.c
25
26 @brief
27
28 This file contains the external API exposed by the wlan data transfer abstraction layer module.
29 Copyright (c) 2010-2011 QUALCOMM Incorporated.
30 All Rights Reserved.
31 Qualcomm Confidential and Proprietary
32========================================================================*/
33
34/*===========================================================================
35
36 EDIT HISTORY FOR FILE
37
38
39 This section contains comments describing changes made to the module.
40 Notice that changes are listed in reverse chronological order.
41
42
43 $Header:$ $DateTime: $ $Author: $
44
45
46when who what, where, why
47-------- --- ----------------------------------------------------------
4808/03/10 schang Created module.
49
50===========================================================================*/
51
52/*===========================================================================
53
54 INCLUDE FILES FOR MODULE
55
56===========================================================================*/
57
58/*----------------------------------------------------------------------------
59 * Include Files
60 * -------------------------------------------------------------------------*/
61#include "wlan_qct_dxe.h"
62#include "wlan_qct_dxe_i.h"
63#include "wlan_qct_pal_device.h"
64#ifdef FEATURE_R33D
65#include "wlan_qct_pal_bus.h"
66#endif /* FEATURE_R33D */
67
68/*----------------------------------------------------------------------------
69 * Local Definitions
70 * -------------------------------------------------------------------------*/
71//#define WLANDXE_DEBUG_CH_INFO_DUMP
72
73/* Temporary configuration defines
74 * Have to find out permanent solution */
75#define T_WLANDXE_MAX_DESCRIPTOR_COUNT 40
76#define T_WLANDXE_MAX_FRAME_SIZE 2000
77#define T_WLANDXE_TX_INT_ENABLE_FCOUNT 1
78#define T_WLANDXE_MEMDUMP_BYTE_PER_LINE 16
79#define T_WLANDXE_MAX_RX_PACKET_WAIT 6000
Jeff Johnsone7245742012-09-05 17:12:55 -070080#define WLANDXE_MAX_REAPED_RX_FRAMES 512
Jeff Johnson295189b2012-06-20 16:38:30 -070081
82/* This is temporary fot the compile
83 * WDI will release official version
84 * This must be removed */
85#define WDI_GET_PAL_CTX() NULL
86
87/*-------------------------------------------------------------------------
88 * Local Varables
89 *-------------------------------------------------------------------------*/
90/* This is temp, someone have to allocate for me, and must be part of global context */
91static WLANDXE_CtrlBlkType *tempDxeCtrlBlk = NULL;
92static char *channelType[WDTS_CHANNEL_MAX] =
93 {
94 "TX_LOW_PRI",
95 "TX_HIGH_PRI",
96 "RX_LOW_PRI",
97#ifndef WLANDXE_TEST_CHANNEL_ENABLE
98 "RX_HIGH_PRI",
99#else
100 "H2H_TEST_TX",
101 "H2H_TEST_RX"
102#endif /* WLANDXE_TEST_CHANNEL_ENABLE */
103 };
Jeff Johnsone7245742012-09-05 17:12:55 -0700104static wpt_packet *rx_reaped_buf[WLANDXE_MAX_REAPED_RX_FRAMES];
Jeff Johnson295189b2012-06-20 16:38:30 -0700105
106/*-------------------------------------------------------------------------
107 * External Function Proto Type
108 *-------------------------------------------------------------------------*/
109
110/*-------------------------------------------------------------------------
111 * Local Function Proto Type
112 *-------------------------------------------------------------------------*/
113static wpt_status dxeRXFrameSingleBufferAlloc
114(
115 WLANDXE_CtrlBlkType *dxeCtxt,
116 WLANDXE_ChannelCBType *channelEntry,
117 WLANDXE_DescCtrlBlkType *currentCtrlBlock
118);
119
120/*-------------------------------------------------------------------------
121 * Local Function
122 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700123/*==========================================================================
124 @ Function Name
125 dxeChannelMonitor
126
127 @ Description
128
129 @ Parameters
130 WLANDXE_ChannelCBType *channelEntry
131 Channel specific control block
132
133 @ Return
134 wpt_status
135
136===========================================================================*/
137static wpt_status dxeChannelMonitor
138(
139 char *monitorDescription,
140 WLANDXE_ChannelCBType *channelEntry
141)
142{
143 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
144
Jeff Johnsone7245742012-09-05 17:12:55 -0700145 if((NULL == monitorDescription) || (NULL == channelEntry))
146 {
147 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
148 "INVALID Input ARG");
149 return eWLAN_PAL_STATUS_E_INVAL;
150 }
151
152 if(channelEntry->channelType > WDTS_CHANNEL_RX_HIGH_PRI)
153 {
154 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
155 "INVALID Channel type");
156 return eWLAN_PAL_STATUS_E_INVAL;
157 }
158
159 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700160 "=== %s Channel Number %d, Channel Type %s",
161 monitorDescription, channelEntry->assignedDMAChannel, channelType[channelEntry->channelType]);
Jeff Johnsone7245742012-09-05 17:12:55 -0700162 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700163 "numDesc %d, numFreeDesc %d, numResvDesc %d",
164 channelEntry->numDesc, channelEntry->numFreeDesc, channelEntry->numRsvdDesc);
Jeff Johnsone7245742012-09-05 17:12:55 -0700165 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700166 "headCB 0x%x, next 0x%x, DESC 0x%x",
167 channelEntry->headCtrlBlk, channelEntry->headCtrlBlk->nextCtrlBlk, channelEntry->headCtrlBlk->linkedDescPhyAddr);
Jeff Johnsone7245742012-09-05 17:12:55 -0700168 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700169 "tailCB 0x%x, next 0x%x, DESC 0x%x",
170 channelEntry->tailCtrlBlk, channelEntry->tailCtrlBlk->nextCtrlBlk, channelEntry->tailCtrlBlk->linkedDescPhyAddr);
Jeff Johnsone7245742012-09-05 17:12:55 -0700171 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700172 "headCB Order %d, tailCB Order %d",
173 channelEntry->headCtrlBlk->ctrlBlkOrder, channelEntry->tailCtrlBlk->ctrlBlkOrder);
Jeff Johnsone7245742012-09-05 17:12:55 -0700174 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700175 "numFragmentCurrentChain %d, numTotalFrame %d ===",
176 channelEntry->numFragmentCurrentChain, channelEntry->numTotalFrame);
177
178 return status;
179}
180
Jeff Johnsone7245742012-09-05 17:12:55 -0700181#ifdef WLANDXE_DEBUG_MEMORY_DUMP
Jeff Johnson295189b2012-06-20 16:38:30 -0700182/*==========================================================================
183 @ Function Name
184 dxeMemoryDump
185
186 @ Description
187
188 @ Parameters
189 WLANDXE_ChannelCBType *channelEntry
190 Channel specific control block
191
192 @ Return
193 wpt_status
194
195===========================================================================*/
196static wpt_status dxeMemoryDump
197(
198 wpt_uint8 *dumpPointer,
199 wpt_uint32 dumpSize,
200 char *dumpTarget
201)
202{
203 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
204 wpt_uint32 numBytes = 0;
205 wpt_uint32 idx;
206
Jeff Johnsone7245742012-09-05 17:12:55 -0700207 if((NULL == dumpPointer) ||
208 (NULL == dumpTarget))
209 {
210 return status;
211 }
212
Jeff Johnson295189b2012-06-20 16:38:30 -0700213 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
214 "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
215 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
216 "%s Location 0x%x, Size %d", dumpTarget, dumpPointer, dumpSize);
217
218 numBytes = dumpSize % T_WLANDXE_MEMDUMP_BYTE_PER_LINE;
219 for(idx = 0; idx < dumpSize; idx++)
220 {
221 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
222 "0x%2x ", dumpPointer[idx]);
223 if(0 == ((idx + 1) % T_WLANDXE_MEMDUMP_BYTE_PER_LINE))
224 {
225 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW, "\n");
226 }
227 }
228 if(0 != numBytes)
229 {
230 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW, "\n");
231 }
232 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
233 "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
234
235 return status;
236}
Jeff Johnsone7245742012-09-05 17:12:55 -0700237#endif /* WLANDXE_DEBUG_MEMORY_DUMP */
Jeff Johnson295189b2012-06-20 16:38:30 -0700238
239/*==========================================================================
240 @ Function Name
241 dxeDescriptorDump
242
243 @ Description
244
245 @ Parameters
246 WLANDXE_ChannelCBType *channelEntry
247 Channel specific control block
248
249 @ Return
250 wpt_status
251
252===========================================================================*/
253wpt_status dxeDescriptorDump
254(
255 WLANDXE_ChannelCBType *channelEntry,
256 WLANDXE_DescType *targetDesc,
257 wpt_uint32 fragmentOrder
258)
259{
260 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
261
262
Jeff Johnsone7245742012-09-05 17:12:55 -0700263 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700264 "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
Jeff Johnsone7245742012-09-05 17:12:55 -0700265 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
266 "Descriptor Dump for channel %s, order %d",
Jeff Johnson295189b2012-06-20 16:38:30 -0700267 channelType[channelEntry->channelType],
Jeff Johnsone7245742012-09-05 17:12:55 -0700268 fragmentOrder);
Jeff Johnson295189b2012-06-20 16:38:30 -0700269
Jeff Johnsone7245742012-09-05 17:12:55 -0700270 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700271 "CTRL WORD 0x%x, TransferSize %d",
272 WLANDXE_U32_SWAP_ENDIAN(targetDesc->descCtrl.ctrl),
273 WLANDXE_U32_SWAP_ENDIAN(targetDesc->xfrSize));
Jeff Johnsone7245742012-09-05 17:12:55 -0700274 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700275 "SRC ADD 0x%x, DST ADD 0x%x, NEXT DESC 0x%x",
276 WLANDXE_U32_SWAP_ENDIAN(targetDesc->dxedesc.dxe_short_desc.srcMemAddrL),
277 WLANDXE_U32_SWAP_ENDIAN(targetDesc->dxedesc.dxe_short_desc.dstMemAddrL),
278 WLANDXE_U32_SWAP_ENDIAN(targetDesc->dxedesc.dxe_short_desc.phyNextL));
Jeff Johnsone7245742012-09-05 17:12:55 -0700279 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700280 "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
281
282 return status;
283}
284
285/*==========================================================================
286 @ Function Name
287 dxeChannelRegisterDump
288
289 @ Description
290
291 @ Parameters
292 WLANDXE_ChannelCBType *channelEntry
293 Channel specific control block
294
295 @ Return
296 wpt_status
297
298===========================================================================*/
299wpt_status dxeChannelRegisterDump
300(
301 WLANDXE_ChannelCBType *channelEntry,
302 char *dumpTarget
303)
304{
305 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
306 wpt_uint32 regValue = 0;
307
Jeff Johnsone7245742012-09-05 17:12:55 -0700308 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700309 "%s Channel register dump for %s, base address 0x%x",
310 channelType[channelEntry->channelType],
311 dumpTarget,
312 channelEntry->channelRegister.chDXEBaseAddr);
313 regValue = 0;
314 wpalReadRegister(channelEntry->channelRegister.chDXECtrlRegAddr, &regValue);
Jeff Johnsone7245742012-09-05 17:12:55 -0700315 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700316 "Control Register 0x%x", regValue);
317
318 regValue = 0;
319 wpalReadRegister(channelEntry->channelRegister.chDXEStatusRegAddr, &regValue);
Jeff Johnsone7245742012-09-05 17:12:55 -0700320 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700321 "Status Register 0x%x", regValue);
322 regValue = 0;
323
324 wpalReadRegister(channelEntry->channelRegister.chDXESadrlRegAddr, &regValue);
Jeff Johnsone7245742012-09-05 17:12:55 -0700325 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700326 "Source Address Register 0x%x", regValue);
327 regValue = 0;
328
329 wpalReadRegister(channelEntry->channelRegister.chDXEDadrlRegAddr, &regValue);
Jeff Johnsone7245742012-09-05 17:12:55 -0700330 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700331 "Destination Address Register 0x%x", regValue);
332 regValue = 0;
333
334 wpalReadRegister(channelEntry->channelRegister.chDXELstDesclRegAddr, &regValue);
Jeff Johnsone7245742012-09-05 17:12:55 -0700335 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700336 "Descriptor Address Register 0x%x", regValue);
337
338 return status;
339}
Jeff Johnsone7245742012-09-05 17:12:55 -0700340
341/*==========================================================================
342 @ Function Name
343 dxeChannelAllDescDump
344
345 @ Description
346 Dump all DXE descriptors within assigned channe;
347
348 @ Parameters
349 WLANDXE_ChannelCBType *channelEntry
350
351 @ Return
352 NONE
353
354===========================================================================*/
355void dxeChannelAllDescDump
356(
357 WLANDXE_ChannelCBType *channelEntry
358)
359{
360 wpt_uint32 channelLoop;
361 WLANDXE_DescCtrlBlkType *targetCtrlBlk;
362
363 targetCtrlBlk = channelEntry->headCtrlBlk;
364
365 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
366 "%s %d descriptor chains",
367 channelType[channelEntry->channelType], (int)channelEntry->numDesc);
368 for(channelLoop = 0; channelLoop < channelEntry->numDesc; channelLoop++)
369 {
370 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
371 "%5d : 0x%x", (int)targetCtrlBlk->ctrlBlkOrder,
372 (unsigned int)targetCtrlBlk->linkedDesc->descCtrl.ctrl);
373 targetCtrlBlk = (WLANDXE_DescCtrlBlkType *)targetCtrlBlk->nextCtrlBlk;
374 }
375
376 return;
377}
Jeff Johnson295189b2012-06-20 16:38:30 -0700378
379/*==========================================================================
380 @ Function Name
381 dxeCtrlBlkAlloc
382
383 @ Description
384 Allocate DXE Control block
385 DXE control block will used by Host DXE driver only, internal structure
386 Will make ring linked list
387
388 @ Parameters
389 WLANDXE_CtrlBlkType *dxeCtrlBlk,
390 DXE host driver main control block
391 WLANDXE_ChannelCBType *channelEntry
392 Channel specific control block
393
394 @ Return
395 wpt_status
396
397===========================================================================*/
398static wpt_status dxeCtrlBlkAlloc
399(
400 WLANDXE_CtrlBlkType *dxeCtrlBlk,
401 WLANDXE_ChannelCBType *channelEntry
402)
403{
404 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
405 unsigned int idx, fIdx;
406 WLANDXE_DescCtrlBlkType *currentCtrlBlk = NULL;
407 WLANDXE_DescCtrlBlkType *freeCtrlBlk = NULL;
408 WLANDXE_DescCtrlBlkType *prevCtrlBlk = NULL;
409 WLANDXE_DescCtrlBlkType *nextCtrlBlk = NULL;
410
411 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
412 "%s Enter", __FUNCTION__);
413
414 /* Sanity check */
415 if((NULL == dxeCtrlBlk) || (NULL == channelEntry))
416 {
417 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
418 "dxeCtrlBlkAlloc Channel Entry is not valid");
419 return eWLAN_PAL_STATUS_E_INVAL;
420 }
421
422 /* Allocate pre asigned number of control blocks */
423 for(idx = 0; idx < channelEntry->numDesc; idx++)
424 {
425 currentCtrlBlk = (WLANDXE_DescCtrlBlkType *)wpalMemoryAllocate(sizeof(WLANDXE_DescCtrlBlkType));
426 if(NULL == currentCtrlBlk)
427 {
428 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
429 "dxeCtrlBlkOpen MemAlloc Fail for channel %d",
430 channelEntry->channelType);
431 freeCtrlBlk = channelEntry->headCtrlBlk;
432 for(fIdx = 0; fIdx < idx; fIdx++)
433 {
434 if(NULL == freeCtrlBlk)
435 {
436 break;
437 }
438
439 nextCtrlBlk = freeCtrlBlk->nextCtrlBlk;
440 wpalMemoryFree((void *)freeCtrlBlk);
441 freeCtrlBlk = nextCtrlBlk;
442 }
443 return eWLAN_PAL_STATUS_E_FAULT;
444 }
445
446 memset((wpt_uint8 *)currentCtrlBlk, 0, sizeof(WLANDXE_DescCtrlBlkType));
447 /* Initialize common elements first */
448 currentCtrlBlk->xfrFrame = NULL;
449 currentCtrlBlk->linkedDesc = NULL;
450 currentCtrlBlk->linkedDescPhyAddr = 0;
451 currentCtrlBlk->ctrlBlkOrder = idx;
452
453 /* This is the first control block allocated
454 * Next Control block is not allocated yet
455 * head and tail must be first control block */
456 if(0 == idx)
457 {
458 currentCtrlBlk->nextCtrlBlk = NULL;
459 channelEntry->headCtrlBlk = currentCtrlBlk;
460 channelEntry->tailCtrlBlk = currentCtrlBlk;
461 }
462 /* This is not first, not last control block
463 * previous control block may has next linked block */
464 else if((0 < idx) && (idx < (channelEntry->numDesc - 1)))
465 {
466 prevCtrlBlk->nextCtrlBlk = currentCtrlBlk;
467 }
468 /* This is last control blocl
469 * next control block for the last control block is head, first control block
470 * then whole linked list made RING */
471 else if((channelEntry->numDesc - 1) == idx)
472 {
473 prevCtrlBlk->nextCtrlBlk = currentCtrlBlk;
474 currentCtrlBlk->nextCtrlBlk = channelEntry->headCtrlBlk;
475 }
476 else
477 {
478 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
479 "dxeCtrlBlkOpen Invalid Ctrl Blk location %d",
480 channelEntry->channelType);
481 wpalMemoryFree(currentCtrlBlk);
482 return eWLAN_PAL_STATUS_E_FAULT;
483 }
484
485 prevCtrlBlk = currentCtrlBlk;
486 channelEntry->numFreeDesc++;
487 }
488
489 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,"%s Exit", __FUNCTION__);
490 return status;
491}
492
493/*==========================================================================
494 @ Function Name
495 dxeDescLinkAlloc
496
497 @ Description
498 Allocate DXE descriptor
499 DXE descriptor will be shared by DXE host driver and RIVA DXE engine
500 Will make RING linked list
501 Will be linked with Descriptor control block one by one
502
503 @ Parameters
504 WLANDXE_CtrlBlkType *dxeCtrlBlk,
505 DXE host driver main control block
506 WLANDXE_ChannelCBType *channelEntry
507 Channel specific control block
508 @ Return
509 wpt_status
510
511===========================================================================*/
512static wpt_status dxeDescAllocAndLink
513(
514 WLANDXE_CtrlBlkType *dxeCtrlBlk,
515 WLANDXE_ChannelCBType *channelEntry
516)
517{
518 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
519 WLANDXE_DescType *currentDesc = NULL;
520 WLANDXE_DescType *prevDesc = NULL;
521 WLANDXE_DescCtrlBlkType *currentCtrlBlk = NULL;
522 unsigned int idx;
523 void *physAddress = NULL;
524#ifdef WLANDXE_TEST_CHANNEL_ENABLE
525 WLANDXE_ChannelCBType *testTXChannelCB = &dxeCtrlBlk->dxeChannel[WDTS_CHANNEL_H2H_TEST_TX];
526 WLANDXE_DescCtrlBlkType *currDescCtrlBlk = testTXChannelCB->headCtrlBlk;
527#endif /* WLANDXE_TEST_CHANNEL_ENABLE*/
528
529 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
530 "%s Enter", __FUNCTION__);
531
532 /* Sanity Check */
533 if((NULL == dxeCtrlBlk) || (NULL == channelEntry))
534 {
535 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
536 "dxeDescLinkAlloc Channel Entry is not valid");
537 return eWLAN_PAL_STATUS_E_INVAL;
538 }
539
540 currentCtrlBlk = channelEntry->headCtrlBlk;
541
542#if !(defined(FEATURE_R33D) || defined(WLANDXE_TEST_CHANNEL_ENABLE))
543 /* allocate all DXE descriptors for this channel in one chunk */
544 channelEntry->descriptorAllocation = (WLANDXE_DescType *)
545 wpalDmaMemoryAllocate(sizeof(WLANDXE_DescType)*channelEntry->numDesc,
546 &physAddress);
547 if(NULL == channelEntry->descriptorAllocation)
548 {
549 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
550 "dxeDescLinkAlloc Descriptor Alloc Fail");
551 return eWLAN_PAL_STATUS_E_RESOURCES;
552 }
553 currentDesc = channelEntry->descriptorAllocation;
554#endif
555
556 /* Allocate pre asigned number of descriptor */
557 for(idx = 0; idx < channelEntry->numDesc; idx++)
558 {
559#ifndef FEATURE_R33D
560#ifndef WLANDXE_TEST_CHANNEL_ENABLE
561 // descriptors were allocated in a chunk -- use the current one
562 memset((wpt_uint8 *)currentDesc, 0, sizeof(WLANDXE_DescType));
563 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
564 "Allocated Descriptor VA 0x%x, PA 0x%x", currentDesc, physAddress);
565#else
566 if(WDTS_CHANNEL_H2H_TEST_RX != channelEntry->channelType)
567 {
568 // allocate a descriptor
569 currentDesc = (WLANDXE_DescType *)wpalDmaMemoryAllocate(sizeof(WLANDXE_DescType),
570 &physAddress);
571 memset((wpt_uint8 *)currentDesc, 0, sizeof(WLANDXE_DescType));
572 }
573 else
574 {
575 currentDesc = currDescCtrlBlk->linkedDesc;
576 physAddress = (void *)currDescCtrlBlk->linkedDescPhyAddr;
577 currDescCtrlBlk = (WLANDXE_DescCtrlBlkType *)currDescCtrlBlk->nextCtrlBlk;
578 }
579#endif /* WLANDXE_TEST_CHANNEL_ENABLE */
580#else
581#ifndef WLANDXE_TEST_CHANNEL_ENABLE
582 currentDesc = (WLANDXE_DescType *)wpalAcpuDdrDxeDescMemoryAllocate(&physAddress);
583 memset((wpt_uint8 *)currentDesc, 0, sizeof(WLANDXE_DescType));
584 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
585 "Allocated Descriptor VA 0x%x, PA 0x%x", currentDesc, physAddress);
586#else
587 if(WDTS_CHANNEL_H2H_TEST_RX != channelEntry->channelType)
588 {
589 currentDesc = (WLANDXE_DescType *)wpalAcpuDdrDxeDescMemoryAllocate(&physAddress);
590 memset((wpt_uint8 *)currentDesc, 0, sizeof(WLANDXE_DescType));
591 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
592 "Allocated Descriptor VA 0x%x, PA 0x%x", currentDesc, physAddress);
593 }
594 else
595 {
596 currentDesc = currDescCtrlBlk->linkedDesc;
597 physAddress = (void *)currDescCtrlBlk->linkedDescPhyAddr;
598 currDescCtrlBlk = (WLANDXE_DescCtrlBlkType *)currDescCtrlBlk->nextCtrlBlk;
599 }
600#endif /* WLANDXE_TEST_CHANNEL_ENABLE */
601#endif /* FEATURE_R33D */
602 if(NULL == currentDesc)
603 {
604 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
605 "dxeDescLinkAlloc MemAlloc Fail for channel %d",
606 channelEntry->channelType);
607 return eWLAN_PAL_STATUS_E_FAULT;
608 }
609
610 if((WDTS_CHANNEL_TX_LOW_PRI == channelEntry->channelType) ||
611 (WDTS_CHANNEL_TX_HIGH_PRI == channelEntry->channelType))
612 {
613 currentDesc->descCtrl.ctrl = channelEntry->extraConfig.cw_ctrl_write;
614 currentDesc->dxedesc.dxe_short_desc.dstMemAddrL = channelEntry->extraConfig.refWQ_swapped;
615 }
616 else if((WDTS_CHANNEL_RX_LOW_PRI == channelEntry->channelType) ||
617 (WDTS_CHANNEL_RX_HIGH_PRI == channelEntry->channelType))
618 {
619 currentDesc->descCtrl.ctrl = channelEntry->extraConfig.cw_ctrl_read;
620 currentDesc->dxedesc.dxe_short_desc.srcMemAddrL = channelEntry->extraConfig.refWQ_swapped;
621 }
622 else
623 {
624 /* Just in case. H2H Test RX channel, do nothing
625 * By Definition this must not happen */
626 }
627
628 currentCtrlBlk->linkedDesc = currentDesc;
629 currentCtrlBlk->linkedDescPhyAddr = (unsigned int)physAddress;
630 /* First descriptor, next none
631 * descriptor bottom location is first descriptor address */
632 if(0 == idx)
633 {
634 currentDesc->dxedesc.dxe_short_desc.phyNextL = 0;
635 channelEntry->DescBottomLoc = currentDesc;
636 channelEntry->descBottomLocPhyAddr = (unsigned int)physAddress;
637 }
638 /* Not first, not last descriptor
639 * may make link for previous descriptor with current descriptor
640 * ENDIAN SWAP needed ????? */
641 else if((0 < idx) && (idx < (channelEntry->numDesc - 1)))
642 {
643 prevDesc->dxedesc.dxe_short_desc.phyNextL =
644 WLANDXE_U32_SWAP_ENDIAN((wpt_uint32)physAddress);
645 }
646 /* Last descriptor
647 * make a ring by asign next pointer as first descriptor
648 * ENDIAN SWAP NEEDED ??? */
649 else if((channelEntry->numDesc - 1) == idx)
650 {
651 prevDesc->dxedesc.dxe_short_desc.phyNextL =
652 WLANDXE_U32_SWAP_ENDIAN((wpt_uint32)physAddress);
653 currentDesc->dxedesc.dxe_short_desc.phyNextL =
654 WLANDXE_U32_SWAP_ENDIAN((wpt_uint32)channelEntry->headCtrlBlk->linkedDescPhyAddr);
655 }
656
657 /* If Current Channel is RX channel PAL Packet and OS packet buffer should be
658 * Pre allocated and physical address must be assigned into
659 * Corresponding DXE Descriptor */
660#ifdef WLANDXE_TEST_CHANNEL_ENABLE
661 if((WDTS_CHANNEL_RX_LOW_PRI == channelEntry->channelType) ||
662 (WDTS_CHANNEL_RX_HIGH_PRI == channelEntry->channelType) ||
663 (WDTS_CHANNEL_H2H_TEST_RX == channelEntry->channelType))
664#else
665 if((WDTS_CHANNEL_RX_LOW_PRI == channelEntry->channelType) ||
666 (WDTS_CHANNEL_RX_HIGH_PRI == channelEntry->channelType))
667#endif /* WLANDXE_TEST_CHANNEL_ENABLE */
668 {
669 status = dxeRXFrameSingleBufferAlloc(dxeCtrlBlk,
670 channelEntry,
671 currentCtrlBlk);
672 if( !WLAN_PAL_IS_STATUS_SUCCESS(status) )
673 {
674 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
675 "dxeDescLinkAlloc RX Buffer Alloc Fail for channel %d",
676 channelEntry->channelType);
677 return status;
678 }
679 --channelEntry->numFreeDesc;
680 }
681
682 currentCtrlBlk = currentCtrlBlk->nextCtrlBlk;
683 prevDesc = currentDesc;
684
685#ifndef FEATURE_R33D
686#ifndef WLANDXE_TEST_CHANNEL_ENABLE
687 // advance to the next pre-allocated descriptor in the chunk
688 currentDesc++;
689 physAddress = ((wpt_int8 *)physAddress) + sizeof(WLANDXE_DescType);
690#endif
691#endif
692 }
693
694 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
695 "%s Exit", __FUNCTION__);
696 return status;
697}
698
699/*==========================================================================
700 @ Function Name
701
702 @ Description
703
704 @ Parameters
705
706 @ Return
707 wpt_status
708
709===========================================================================*/
710static wpt_status dxeSetInterruptPath
711(
712 WLANDXE_CtrlBlkType *dxeCtrlBlk
713)
714{
715 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
716 wpt_uint32 interruptPath = 0;
717 wpt_uint32 idx;
718 WLANDXE_ChannelCBType *channelEntry = NULL;
719
720 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
721 "%s Enter", __FUNCTION__);
722
723 for(idx = 0; idx < WDTS_CHANNEL_MAX; idx++)
724 {
725 channelEntry = &dxeCtrlBlk->dxeChannel[idx];
726#ifdef WLANDXE_TEST_CHANNEL_ENABLE
727 if((WDTS_CHANNEL_TX_LOW_PRI == channelEntry->channelType) ||
728 (WDTS_CHANNEL_TX_HIGH_PRI == channelEntry->channelType) ||
729 (WDTS_CHANNEL_H2H_TEST_TX == channelEntry->channelType))
730#else
731 if((WDTS_CHANNEL_TX_LOW_PRI == channelEntry->channelType) ||
732 (WDTS_CHANNEL_TX_HIGH_PRI == channelEntry->channelType))
733#endif /* WLANDXE_TEST_CHANNEL_ENABLE */
734 {
735 interruptPath |= (1 << channelEntry->assignedDMAChannel);
736 }
737 else if((WDTS_CHANNEL_RX_LOW_PRI == channelEntry->channelType) ||
738 (WDTS_CHANNEL_RX_HIGH_PRI == channelEntry->channelType))
739 {
740 interruptPath |= (1 << (channelEntry->assignedDMAChannel + 16));
741 }
742 else
743 {
744 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
745 "H2H TEST RX???? %d", channelEntry->channelType);
746 }
747 }
748 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN,
749 "Interrupt Path Must be 0x%x", interruptPath);
750 dxeCtrlBlk->interruptPath = interruptPath;
751 wpalWriteRegister(WLANDXE_CCU_DXE_INT_SELECT, interruptPath);
752
753 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
754 "%s Exit", __FUNCTION__);
755 return status;
756}
757
758/*==========================================================================
759 @ Function Name
760 dxeEngineCoreStart
761
762 @ Description
763 Trigger to start RIVA DXE Hardware
764
765 @ Parameters
766 WLANDXE_CtrlBlkType *dxeCtrlBlk,
767 DXE host driver main control block
768
769 @ Return
770 wpt_status
771
772===========================================================================*/
773static wpt_status dxeEngineCoreStart
774(
775 WLANDXE_CtrlBlkType *dxeCtrlBlk
776)
777{
778 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
779 wpt_uint32 registerData = 0;
780
781 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
782 "%s Enter", __FUNCTION__);
783
784 /* START This core init is not needed for the integrated system */
785 /* Reset First */
786 registerData = WLANDXE_DMA_CSR_RESET_MASK;
787 wpalWriteRegister(WALNDEX_DMA_CSR_ADDRESS,
788 registerData);
789
790 registerData = WLANDXE_DMA_CSR_EN_MASK;
791 registerData |= WLANDXE_DMA_CSR_ECTR_EN_MASK;
792 registerData |= WLANDXE_DMA_CSR_TSTMP_EN_MASK;
793 registerData |= WLANDXE_DMA_CSR_H2H_SYNC_EN_MASK;
794
795 registerData = 0x00005c89;
796 wpalWriteRegister(WALNDEX_DMA_CSR_ADDRESS,
797 registerData);
798
799 /* Is This needed?
800 * Not sure, revisit with integrated system */
801 /* END This core init is not needed for the integrated system */
802
803 dxeSetInterruptPath(dxeCtrlBlk);
804 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
805 "%s Exit", __FUNCTION__);
806 return status;
807}
808
809/*==========================================================================
810 @ Function Name
811 dxeChannelInitProgram
812
813 @ Description
814 Program RIVA DXE engine register with initial value
815 What must be programmed
816 - Source Address (SADRL, chDXESadrlRegAddr)
817 - Destination address (DADRL, chDXEDadrlRegAddr)
818 - Next Descriptor address (DESCL, chDXEDesclRegAddr)
819 - current descriptor address (LST_DESCL, chDXELstDesclRegAddr)
820
821 Not need to program now
822 - Channel Control register (CH_CTRL, chDXECtrlRegAddr)
823 TX : Have to program to trigger send out frame
824 RX : programmed by DXE engine
825
826 @ Parameters
827 WLANDXE_CtrlBlkType *dxeCtrlBlk,
828 DXE host driver main control block
829 WLANDXE_ChannelCBType *channelEntry
830 Channel specific control block
831 @ Return
832 wpt_status
833
834===========================================================================*/
835static wpt_status dxeChannelInitProgram
836(
837 WLANDXE_CtrlBlkType *dxeCtrlBlk,
838 WLANDXE_ChannelCBType *channelEntry
839)
840{
841 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
842 wpt_uint32 idx;
843 WLANDXE_DescType *currentDesc = NULL;
844 WLANDXE_DescCtrlBlkType *currentCtrlBlk = NULL;
845
846 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
847 "%s Enter", __FUNCTION__);
848
849 /* Sanity Check */
850 if((NULL == dxeCtrlBlk) || (NULL == channelEntry))
851 {
852 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
853 "dxeChannelInitProgram Channel Entry is not valid");
854 return eWLAN_PAL_STATUS_E_INVAL;
855 }
856
857 /* Program Source address and destination adderss */
858 if(!channelEntry->channelConfig.useShortDescFmt)
859 {
860 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
861 "dxeChannelInitProgram Long Descriptor not support yet");
862 return eWLAN_PAL_STATUS_E_FAILURE;
863 }
864
865 /* Common register area */
866 /* Next linked list Descriptor pointer */
867 status = wpalWriteRegister(channelEntry->channelRegister.chDXEDesclRegAddr,
868 channelEntry->headCtrlBlk->linkedDescPhyAddr);
869 if(eWLAN_PAL_STATUS_SUCCESS != status)
870 {
871 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
872 "dxeChannelInitProgram Write DESC Address register fail");
873 return status;
874 }
875
876 if((WDTS_CHANNEL_TX_LOW_PRI == channelEntry->channelType) ||
877 (WDTS_CHANNEL_TX_HIGH_PRI == channelEntry->channelType))
878 {
879 /* Program default registers */
880 /* TX DMA channel, DMA destination address is work Q */
881 status = wpalWriteRegister(channelEntry->channelRegister.chDXEDadrlRegAddr,
882 channelEntry->channelConfig.refWQ);
883 if(eWLAN_PAL_STATUS_SUCCESS != status)
884 {
885 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
886 "dxeChannelInitProgram Write TX DAddress register fail");
887 return status;
888 }
889 }
890 else if((WDTS_CHANNEL_RX_LOW_PRI == channelEntry->channelType) ||
891 (WDTS_CHANNEL_RX_HIGH_PRI == channelEntry->channelType))
892 {
893 /* Initialize Descriptor control Word First */
894 currentCtrlBlk = channelEntry->headCtrlBlk;
895 for(idx = 0; idx < channelEntry->channelConfig.nDescs; idx++)
896 {
897 currentDesc = currentCtrlBlk->linkedDesc;
898 currentCtrlBlk = currentCtrlBlk->nextCtrlBlk;
899 }
900
901 /* RX DMA channel, DMA source address is work Q */
902 status = wpalWriteRegister(channelEntry->channelRegister.chDXESadrlRegAddr,
903 channelEntry->channelConfig.refWQ);
904 if(eWLAN_PAL_STATUS_SUCCESS != status)
905 {
906 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
907 "dxeChannelInitProgram Write RX SAddress WQ register fail");
908 return status;
909 }
910
911 /* RX DMA channel, Program pre allocated destination Address */
912 status = wpalWriteRegister(channelEntry->channelRegister.chDXEDadrlRegAddr,
913 WLANDXE_U32_SWAP_ENDIAN(channelEntry->DescBottomLoc->dxedesc.dxe_short_desc.phyNextL));
914 if(eWLAN_PAL_STATUS_SUCCESS != status)
915 {
916 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
917 "dxeChannelInitProgram Write RX DAddress register fail");
918 return status;
919 }
920
921 /* RX Channels, default Control registers MUST BE ENABLED */
922 wpalWriteRegister(channelEntry->channelRegister.chDXECtrlRegAddr,
923 channelEntry->extraConfig.chan_mask);
924 if(eWLAN_PAL_STATUS_SUCCESS != status)
925 {
926 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
927 "dxeChannelInitProgram Write RX Control register fail");
928 return status;
929 }
930 }
931 else
932 {
933 /* H2H test channel, not use work Q */
934 /* Program pre allocated destination Address */
935 status = wpalWriteRegister(channelEntry->channelRegister.chDXEDadrlRegAddr,
936 WLANDXE_U32_SWAP_ENDIAN(channelEntry->DescBottomLoc->dxedesc.dxe_short_desc.phyNextL));
937 if(eWLAN_PAL_STATUS_SUCCESS != status)
938 {
939 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
940 "dxeChannelInitProgram Write RX DAddress register fail");
941 return status;
942 }
943 }
944
945 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
946 "%s Exit", __FUNCTION__);
947 return status;
948}
949
950
951/*==========================================================================
952 @ Function Name
953 dxeChannelStart
954
955 @ Description
956 Start Specific Channel
957
958 @ Parameters
959 WLANDXE_CtrlBlkType *dxeCtrlBlk,
960 DXE host driver main control block
961 WLANDXE_ChannelCBType *channelEntry
962 Channel specific control block
963
964 @ Return
965 wpt_status
966
967===========================================================================*/
968static wpt_status dxeChannelStart
969(
970 WLANDXE_CtrlBlkType *dxeCtrlBlk,
971 WLANDXE_ChannelCBType *channelEntry
972)
973{
974 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
975 wpt_uint32 regValue = 0;
976 wpt_uint32 intMaskVal = 0;
977
978 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
979 "%s Enter", __FUNCTION__);
980
981 channelEntry->extraConfig.chEnabled = eWLAN_PAL_TRUE;
982 channelEntry->extraConfig.chConfigured = eWLAN_PAL_TRUE;
983
984 /* Enable individual channel
985 * not to break current channel setup, first read register */
986 status = wpalReadRegister(WALNDEX_DMA_CH_EN_ADDRESS,
987 &regValue);
988 if(eWLAN_PAL_STATUS_SUCCESS != status)
989 {
990 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
991 "dxeChannelStart Read Channel Enable register fail");
992 return status;
993 }
994
995 /* Enable Channel specific Interrupt */
996 status = wpalReadRegister(WLANDXE_INT_MASK_REG_ADDRESS,
997 &intMaskVal);
998 if(eWLAN_PAL_STATUS_SUCCESS != status)
999 {
1000 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1001 "dxeChannelStart Read INT_MASK register fail");
1002 return status;
1003 }
1004 intMaskVal |= channelEntry->extraConfig.intMask;
1005 status = wpalWriteRegister(WLANDXE_INT_MASK_REG_ADDRESS,
1006 intMaskVal);
1007 if(eWLAN_PAL_STATUS_SUCCESS != status)
1008 {
1009 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1010 "dxeChannelStart Write INT_MASK register fail");
1011 return status;
1012 }
1013
1014 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
1015 "%s Exit", __FUNCTION__);
1016 return status;
1017}
1018
1019/*==========================================================================
1020 @ Function Name
1021 dxeChannelStop
1022
1023 @ Description
1024 Stop Specific Channel
1025
1026 @ Parameters
1027 WLANDXE_CtrlBlkType *dxeCtrlBlk,
1028 DXE host driver main control block
1029 WLANDXE_ChannelCBType *channelEntry
1030 Channel specific control block
1031
1032 @ Return
1033 wpt_status
1034
1035===========================================================================*/
1036static wpt_status dxeChannelStop
1037(
1038 WLANDXE_CtrlBlkType *dxeCtrlBlk,
1039 WLANDXE_ChannelCBType *channelEntry
1040)
1041{
1042 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
1043 wpt_uint32 intMaskVal = 0;
1044
1045 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
1046 "%s Enter", __FUNCTION__);
1047
1048 /* Sanity */
1049 if((NULL == dxeCtrlBlk) || (NULL == channelEntry))
1050 {
1051 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1052 "dxeChannelStop Invalid arg input");
1053 return eWLAN_PAL_STATUS_E_INVAL;
1054 }
1055
1056 /* Maskout interrupt */
1057 status = wpalReadRegister(WLANDXE_INT_MASK_REG_ADDRESS,
1058 &intMaskVal);
1059 if(eWLAN_PAL_STATUS_SUCCESS != status)
1060 {
1061 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1062 "dxeChannelStop Read INT_MASK register fail");
1063 return status;
1064 }
1065 intMaskVal ^= channelEntry->extraConfig.intMask;
1066 status = wpalWriteRegister(WLANDXE_INT_MASK_REG_ADDRESS,
1067 intMaskVal);
1068 if(eWLAN_PAL_STATUS_SUCCESS != status)
1069 {
1070 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1071 "dxeChannelStop Write INT_MASK register fail");
1072 return status;
1073 }
1074
1075 channelEntry->extraConfig.chEnabled = eWLAN_PAL_FALSE;
1076
1077 /* Stop Channel ??? */
1078 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
1079 "%s Exit", __FUNCTION__);
1080 return status;
1081}
1082
1083/*==========================================================================
1084 @ Function Name
1085 dxeChannelClose
1086
1087 @ Description
1088 Close Specific Channel
1089 Free pre allocated RX frame buffer if RX channel
1090 Free DXE descriptor for each channel
1091 Free Descriptor control block for each channel
1092
1093 @ Parameters
1094 WLANDXE_CtrlBlkType *dxeCtrlBlk,
1095 DXE host driver main control block
1096 WLANDXE_ChannelCBType *channelEntry
1097 Channel specific control block
1098
1099 @ Return
1100 wpt_status
1101
1102===========================================================================*/
1103static wpt_status dxeChannelClose
1104(
1105 WLANDXE_CtrlBlkType *dxeCtrlBlk,
1106 WLANDXE_ChannelCBType *channelEntry
1107)
1108{
1109 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
1110 wpt_uint32 idx;
1111 WLANDXE_DescCtrlBlkType *currentCtrlBlk = NULL;
1112 WLANDXE_DescCtrlBlkType *nextCtrlBlk = NULL;
1113 WLANDXE_DescType *currentDescriptor = NULL;
1114 WLANDXE_DescType *nextDescriptor = NULL;
1115
1116 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
1117 "%s Enter", __FUNCTION__);
1118
1119 /* Sanity */
1120 if((NULL == dxeCtrlBlk) || (NULL == channelEntry))
1121 {
1122 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1123 "dxeChannelStop Invalid arg input");
1124 return eWLAN_PAL_STATUS_E_INVAL;
1125 }
1126
1127 currentCtrlBlk = channelEntry->headCtrlBlk;
1128 if(NULL != currentCtrlBlk)
1129 {
1130 currentDescriptor = currentCtrlBlk->linkedDesc;
1131 for(idx = 0; idx < channelEntry->numDesc; idx++)
1132 {
1133 if (idx + 1 != channelEntry->numDesc)
1134 {
1135 nextCtrlBlk = currentCtrlBlk->nextCtrlBlk;
1136 nextDescriptor = nextCtrlBlk->linkedDesc;
1137 }
1138 else
1139 {
1140 nextCtrlBlk = NULL;
1141 nextDescriptor = NULL;
1142 }
1143 if((WDTS_CHANNEL_RX_LOW_PRI == channelEntry->channelType) ||
1144 (WDTS_CHANNEL_RX_HIGH_PRI == channelEntry->channelType))
1145 {
1146 if (NULL != currentCtrlBlk->xfrFrame)
1147 {
1148 wpalUnlockPacket(currentCtrlBlk->xfrFrame);
1149 wpalPacketFree(currentCtrlBlk->xfrFrame);
1150 }
1151 }
1152 /*
1153 * It is the responsibility of DXE to walk through the
1154 * descriptor chain and unlock any pending packets (if
1155 * locked).
1156 */
1157 if((WDTS_CHANNEL_TX_LOW_PRI == channelEntry->channelType) ||
1158 (WDTS_CHANNEL_TX_HIGH_PRI == channelEntry->channelType))
1159 {
1160 if((NULL != currentCtrlBlk->xfrFrame) &&
1161 (eWLAN_PAL_STATUS_SUCCESS == wpalIsPacketLocked(currentCtrlBlk->xfrFrame)))
1162 {
1163 wpalUnlockPacket(currentCtrlBlk->xfrFrame);
1164 wpalPacketFree(currentCtrlBlk->xfrFrame);
1165 }
1166 }
1167#if (defined(FEATURE_R33D) || defined(WLANDXE_TEST_CHANNEL_ENABLE))
1168 // descriptors allocated individually so free them individually
1169 wpalDmaMemoryFree(currentDescriptor);
1170#endif
1171 wpalMemoryFree(currentCtrlBlk);
1172
1173 currentCtrlBlk = nextCtrlBlk;
1174 currentDescriptor = nextDescriptor;
1175 }
1176 }
1177
1178#if !(defined(FEATURE_R33D) || defined(WLANDXE_TEST_CHANNEL_ENABLE))
1179 // descriptors were allocated as a single chunk so free the chunk
1180 if(NULL != channelEntry->descriptorAllocation)
1181 {
1182 wpalDmaMemoryFree(channelEntry->descriptorAllocation);
1183 }
1184#endif
1185
1186 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
1187 "%s Exit", __FUNCTION__);
1188 return status;
1189}
1190
1191/*==========================================================================
1192 @ Function Name
1193 dxeChannelCleanInt
1194
1195 @ Description
1196 Clean up interrupt from RIVA HW
1197 After Host finish to handle interrupt, interrupt signal must be cleaned up
1198 Otherwise next interrupt will not be generated
1199
1200 @ Parameters
1201 WLANDXE_ChannelCBType *channelEntry
1202 Channel specific control block
1203 wpt_uint32 *chStat
1204 Channel Status register value
1205
1206 @ Return
1207 wpt_status
1208
1209===========================================================================*/
1210static wpt_status dxeChannelCleanInt
1211(
1212 WLANDXE_ChannelCBType *channelEntry,
1213 wpt_uint32 *chStat
1214)
1215{
1216 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
1217
1218 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
1219 "%s Enter", __FUNCTION__);
1220
1221 /* Read Channel Status Register to know why INT Happen */
1222 status = wpalReadRegister(channelEntry->channelRegister.chDXEStatusRegAddr,
1223 chStat);
1224 if(eWLAN_PAL_STATUS_SUCCESS != status)
1225 {
1226 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1227 "dxeChannelCleanInt Read CH STAT register fail");
1228 return eWLAN_PAL_STATUS_E_FAULT;
1229 }
1230 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
1231 "%s Channel INT Clean, Status 0x%x",
1232 channelType[channelEntry->channelType], *chStat);
1233
1234 /* Clean up all the INT within this channel */
1235 status = wpalWriteRegister(WLANDXE_INT_CLR_ADDRESS,
1236 (1 << channelEntry->assignedDMAChannel));
1237 if(eWLAN_PAL_STATUS_SUCCESS != status)
1238 {
1239 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1240 "dxeChannelCleanInt Write CH Clean register fail");
1241 return eWLAN_PAL_STATUS_E_FAULT;
1242 }
1243
Jeff Johnsone7245742012-09-05 17:12:55 -07001244 /* Clean up Error INT Bit */
1245 if(WLANDXE_CH_STAT_INT_ERR_MASK & *chStat)
1246 {
1247 status = wpalWriteRegister(WLANDXE_INT_ERR_CLR_ADDRESS,
1248 (1 << channelEntry->assignedDMAChannel));
1249 if(eWLAN_PAL_STATUS_SUCCESS != status)
1250 {
1251 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1252 "dxeChannelCleanInt Read CH STAT register fail");
1253 return eWLAN_PAL_STATUS_E_FAULT;
1254 }
1255 }
1256
1257 /* Clean up DONE INT Bit */
1258 if(WLANDXE_CH_STAT_INT_DONE_MASK & *chStat)
1259 {
1260 status = wpalWriteRegister(WLANDXE_INT_DONE_CLR_ADDRESS,
1261 (1 << channelEntry->assignedDMAChannel));
1262 if(eWLAN_PAL_STATUS_SUCCESS != status)
1263 {
1264 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1265 "dxeChannelCleanInt Read CH STAT register fail");
1266 return eWLAN_PAL_STATUS_E_FAULT;
1267 }
1268 }
1269
1270 /* Clean up ED INT Bit */
1271 if(WLANDXE_CH_STAT_INT_ED_MASK & *chStat)
1272 {
1273 status = wpalWriteRegister(WLANDXE_INT_ED_CLR_ADDRESS,
1274 (1 << channelEntry->assignedDMAChannel));
1275 if(eWLAN_PAL_STATUS_SUCCESS != status)
1276 {
1277 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1278 "dxeChannelCleanInt Read CH STAT register fail");
1279 return eWLAN_PAL_STATUS_E_FAULT;
1280 }
1281 }
1282
Jeff Johnson295189b2012-06-20 16:38:30 -07001283 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
1284 "%s Exit", __FUNCTION__);
1285 return status;
1286}
1287
1288/*==========================================================================
1289 @ Function Name
1290 dxeRXPacketAvailableCB
1291
1292 @ Description
1293 If RX frame handler encounts RX buffer pool empty condition,
1294 DXE RX handle loop will be blocked till get available RX buffer pool.
1295 When new RX buffer pool available, Packet available CB function will
1296 be called.
1297
1298 @ Parameters
1299 wpt_packet *freePacket
1300 Newly allocated RX buffer
1301 v_VOID_t *usrData
1302 DXE context
1303
1304 @ Return
1305 NONE
1306
1307===========================================================================*/
1308void dxeRXPacketAvailableCB
1309(
1310 wpt_packet *freePacket,
1311 v_VOID_t *usrData
1312)
1313{
1314 WLANDXE_CtrlBlkType *dxeCtxt = NULL;
1315 wpt_status status;
1316
1317 /* Simple Sanity */
1318 if((NULL == freePacket) || (NULL == usrData))
1319 {
1320 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
1321 "Get Free RX Buffer fail, Critical Error");
1322 HDXE_ASSERT(0);
1323 return;
1324 }
1325
1326 dxeCtxt = (WLANDXE_CtrlBlkType *)usrData;
1327
1328 if(WLANDXE_CTXT_COOKIE != dxeCtxt->dxeCookie)
1329 {
1330 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
1331 "DXE Context data corrupted, Critical Error");
1332 HDXE_ASSERT(0);
1333 return;
1334 }
1335
1336 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO,
1337 "DXE RX packet available, post MSG to RX Thread");
1338
1339 dxeCtxt->freeRXPacket = freePacket;
1340
1341 /* Serialize RX Packet Available message upon RX thread */
1342 HDXE_ASSERT(NULL != dxeCtxt->rxPktAvailMsg);
1343
1344 status = wpalPostRxMsg(WDI_GET_PAL_CTX(),
1345 dxeCtxt->rxPktAvailMsg);
1346 if(eWLAN_PAL_STATUS_SUCCESS != status)
1347 {
1348 HDXE_ASSERT(eWLAN_PAL_STATUS_SUCCESS == status);
1349 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
1350 "dxeRXPacketAvailableCB serialize fail");
1351 }
1352
1353 return;
1354}
1355
1356/*==========================================================================
1357 @ Function Name
1358 dxeRXFrameSingleBufferAlloc
1359
1360 @ Description
1361 Allocate Platform packet buffer to prepare RX frame
1362 RX frame memory space must be pre allocted and must be asigned to
1363 descriptor
1364 then whenever DMA engine want to tranfer frame from BMU,
1365 buffer must be ready
1366
1367 @ Parameters
1368 WLANDXE_CtrlBlkType *dxeCtrlBlk,
1369 DXE host driver main control block
1370 WLANDXE_ChannelCBType *channelEntry
1371 Channel specific control block
1372 WLANDXE_DescCtrlBlkType currentCtrlBlock
1373 current control block which have to be asigned
1374 frame buffer
1375
1376 @ Return
1377 wpt_status
1378
1379===========================================================================*/
1380static wpt_status dxeRXFrameSingleBufferAlloc
1381(
1382 WLANDXE_CtrlBlkType *dxeCtxt,
1383 WLANDXE_ChannelCBType *channelEntry,
1384 WLANDXE_DescCtrlBlkType *currentCtrlBlock
1385)
1386{
1387 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
1388 wpt_packet *currentPalPacketBuffer = NULL;
1389 WLANDXE_DescType *currentDesc = NULL;
1390#ifdef FEATURE_R33D
1391 wpt_uint32 virtualAddressPCIe;
1392 wpt_uint32 physicalAddressPCIe;
1393#else
1394 wpt_iterator iterator;
1395 wpt_uint32 allocatedSize = 0;
1396 void *physAddress = NULL;
1397#endif /* FEATURE_R33D */
1398
Jeff Johnson295189b2012-06-20 16:38:30 -07001399
1400 currentDesc = currentCtrlBlock->linkedDesc;
1401
1402 /* First check if a packet pointer has already been provided by a previously
1403 invoked Rx packet available callback. If so use that packet. */
1404 if(dxeCtxt->rxPalPacketUnavailable && (NULL != dxeCtxt->freeRXPacket))
1405 {
1406 currentPalPacketBuffer = dxeCtxt->freeRXPacket;
1407 dxeCtxt->rxPalPacketUnavailable = eWLAN_PAL_FALSE;
1408 dxeCtxt->freeRXPacket = NULL;
1409 }
1410 else if(!dxeCtxt->rxPalPacketUnavailable)
1411 {
1412 /* Allocate platform Packet buffer and OS Frame Buffer at here */
1413 currentPalPacketBuffer = wpalPacketAlloc(eWLAN_PAL_PKT_TYPE_RX_RAW,
1414 WLANDXE_DEFAULT_RX_OS_BUFFER_SIZE,
1415 dxeRXPacketAvailableCB,
1416 (void *)dxeCtxt);
1417
1418 if(NULL == currentPalPacketBuffer)
1419 {
1420 dxeCtxt->rxPalPacketUnavailable = eWLAN_PAL_TRUE;
1421 }
1422 }
1423
1424 if(NULL == currentPalPacketBuffer)
1425 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001426 return eWLAN_PAL_STATUS_E_RESOURCES;
1427 }
1428
1429 currentCtrlBlock->xfrFrame = currentPalPacketBuffer;
1430 currentPalPacketBuffer->pktType = eWLAN_PAL_PKT_TYPE_RX_RAW;
1431 currentPalPacketBuffer->pBD = NULL;
1432 currentPalPacketBuffer->pBDPhys = NULL;
1433 currentPalPacketBuffer->BDLength = 0;
1434#ifdef FEATURE_R33D
1435 status = wpalAllocateShadowRxFrame(currentPalPacketBuffer,
1436 &physicalAddressPCIe,
1437 &virtualAddressPCIe);
1438 HDXE_ASSERT(0 != physicalAddressPCIe);
1439 HDXE_ASSERT(0 != virtualAddressPCIe);
1440 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_MED,
1441 "RX Shadow Memory Va 0x%x, Pa 0x%x",
1442 virtualAddressPCIe, physicalAddressPCIe);
1443 if(eWLAN_PAL_STATUS_SUCCESS != status)
1444 {
1445 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1446 "dxeRXFrameBufferAlloc Shadow Mem Alloc fail");
1447 return status;
1448 }
1449 currentCtrlBlock->shadowBufferVa = virtualAddressPCIe;
1450 currentPalPacketBuffer->pBDPhys = (void *)physicalAddressPCIe;
1451 memset((wpt_uint8 *)currentCtrlBlock->shadowBufferVa, 0, WLANDXE_DEFAULT_RX_OS_BUFFER_SIZE);
1452#else
1453 status = wpalLockPacketForTransfer(currentPalPacketBuffer);
1454 if(eWLAN_PAL_STATUS_SUCCESS != status)
1455 {
1456 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1457 "dxeRXFrameBufferAlloc unable to lock packet");
1458 return status;
1459 }
1460
1461 /* Init iterator to get physical os buffer address */
1462 status = wpalIteratorInit(&iterator, currentPalPacketBuffer);
1463 if(eWLAN_PAL_STATUS_SUCCESS != status)
1464 {
1465 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1466 "dxeRXFrameBufferAlloc iterator init fail");
1467 return status;
1468 }
1469 status = wpalIteratorNext(&iterator,
1470 currentPalPacketBuffer,
1471 &physAddress,
1472 &allocatedSize);
1473 if(eWLAN_PAL_STATUS_SUCCESS != status)
1474 {
1475 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1476 "dxeRXFrameBufferAlloc iterator Get Next pointer fail");
1477 return status;
1478 }
1479 currentPalPacketBuffer->pBDPhys = physAddress;
1480#endif /* FEATURE_R33D */
1481
1482 /* DXE descriptor must have SWAPPED addres in it's structure
1483 * !!! SWAPPED !!! */
1484 currentDesc->dxedesc.dxe_short_desc.dstMemAddrL =
1485 WLANDXE_U32_SWAP_ENDIAN((wpt_uint32)currentPalPacketBuffer->pBDPhys);
1486
Jeff Johnson295189b2012-06-20 16:38:30 -07001487 return status;
1488}
1489
1490/*==========================================================================
1491 @ Function Name
1492 dxeRXFrameRefillRing
1493
1494 @ Description
1495 Allocate Platform packet buffers to try to fill up the DXE Rx ring
1496
1497 @ Parameters
1498 WLANDXE_CtrlBlkType *dxeCtrlBlk,
1499 DXE host driver main control block
1500 WLANDXE_ChannelCBType *channelEntry
1501 Channel specific control block
1502
1503 @ Return
1504 wpt_status
1505
1506===========================================================================*/
1507static wpt_status dxeRXFrameRefillRing
1508(
1509 WLANDXE_CtrlBlkType *dxeCtxt,
1510 WLANDXE_ChannelCBType *channelEntry
1511)
1512{
1513 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
1514 WLANDXE_DescCtrlBlkType *currentCtrlBlk = channelEntry->tailCtrlBlk;
1515 WLANDXE_DescType *currentDesc = NULL;
1516
1517 while(channelEntry->numFreeDesc > 0)
1518 {
1519 /* Current Control block is free
1520 * and associated frame buffer is not linked with control block anymore
1521 * allocate new frame buffer for current control block */
1522 status = dxeRXFrameSingleBufferAlloc(dxeCtxt,
1523 channelEntry,
1524 currentCtrlBlk);
1525
1526 if(eWLAN_PAL_STATUS_SUCCESS != status)
1527 {
1528 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN,
1529 "dxeRXFrameRefillRing, out of RX buffer pool, break here");
1530 break;
1531 }
1532
1533 currentDesc = currentCtrlBlk->linkedDesc;
1534 currentDesc->descCtrl.ctrl = channelEntry->extraConfig.cw_ctrl_read;
1535
1536 /* Issue a dummy read from the DXE descriptor DDR location to ensure
1537 that any posted writes are reflected in memory before DXE looks at
1538 the descriptor. */
1539 if(channelEntry->extraConfig.cw_ctrl_read != currentDesc->descCtrl.ctrl)
1540 {
1541 //HDXE_ASSERT(0);
1542 }
1543
1544 /* Kick off the DXE ring, if not in any power save mode */
1545 if((WLANDXE_POWER_STATE_IMPS != dxeCtxt->hostPowerState) &&
1546 (WLANDXE_POWER_STATE_DOWN != dxeCtxt->hostPowerState))
1547 {
1548 wpalWriteRegister(WALNDEX_DMA_ENCH_ADDRESS,
1549 1 << channelEntry->assignedDMAChannel);
1550 }
1551 currentCtrlBlk = currentCtrlBlk->nextCtrlBlk;
1552 --channelEntry->numFreeDesc;
1553 }
1554
1555 channelEntry->tailCtrlBlk = currentCtrlBlk;
1556
1557 return status;
1558}
1559
1560/*==========================================================================
Jeff Johnsone7245742012-09-05 17:12:55 -07001561 @ Function Name
1562 dxeRXFrameRouteUpperLayer
1563
1564 @ Description
1565 Test DXE descriptors and if any RX frame pending within RING,
1566 Route to upper layer
1567
1568 @ Parameters
1569 WLANDXE_CtrlBlkType *dxeCtrlBlk,
1570 DXE host driver main control block
1571 WLANDXE_ChannelCBType *channelEntry
1572 Channel specific control block
1573 @ Return
1574 -1 Any error happen
1575 0 No frame pulled from RX RING
1576 int number of RX frames pulled from RX ring
1577
1578===========================================================================*/
1579static wpt_int32 dxeRXFrameRouteUpperLayer
1580(
1581 WLANDXE_CtrlBlkType *dxeCtxt,
1582 WLANDXE_ChannelCBType *channelEntry
1583)
1584{
1585 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
1586 WLANDXE_DescCtrlBlkType *currentCtrlBlk = NULL;
1587 WLANDXE_DescType *currentDesc = NULL;
1588 wpt_uint32 descCtrl, frameCount = 0, i;
1589
1590 currentCtrlBlk = channelEntry->headCtrlBlk;
1591 currentDesc = currentCtrlBlk->linkedDesc;
1592
1593 /* Descriptoe should be SWAPPED ???? */
1594 descCtrl = currentDesc->descCtrl.ctrl;
1595
1596 /* Get frames while VALID bit is not set (DMA complete) and a data
1597 * associated with it */
1598 while(!(WLANDXE_U32_SWAP_ENDIAN(descCtrl) & WLANDXE_DESC_CTRL_VALID) &&
1599 (eWLAN_PAL_STATUS_SUCCESS == wpalIsPacketLocked(currentCtrlBlk->xfrFrame)) &&
1600 (currentCtrlBlk->xfrFrame->pInternalData != NULL) &&
1601 (frameCount < WLANDXE_MAX_REAPED_RX_FRAMES) )
1602 {
1603 channelEntry->numTotalFrame++;
1604 channelEntry->numFreeDesc++;
1605#ifdef FEATURE_R33D
1606 /* Transfer Size should be */
1607 currentDesc->xfrSize = WLANDXE_U32_SWAP_ENDIAN(WLANDXE_DEFAULT_RX_OS_BUFFER_SIZE);
1608 status = wpalPrepareRxFrame(&currentCtrlBlk->xfrFrame,
1609 (wpt_uint32)currentCtrlBlk->xfrFrame->pBDPhys,
1610 currentCtrlBlk->shadowBufferVa,
1611 WLANDXE_DEFAULT_RX_OS_BUFFER_SIZE);
1612 if(eWLAN_PAL_STATUS_SUCCESS != status)
1613 {
1614 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1615 "dxeRXFrameReady Prepare RX Frame fail");
1616 return -1;
1617 }
1618 status = wpalFreeRxFrame(currentCtrlBlk->shadowBufferVa);
1619 if(eWLAN_PAL_STATUS_SUCCESS != status)
1620 {
1621 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1622 "dxeRXFrameReady Free Shadow RX Frame fail");
1623 return -1;
1624 }
1625
1626#else /* FEATURE_R33D */
1627 status = wpalUnlockPacket(currentCtrlBlk->xfrFrame);
1628 if (eWLAN_PAL_STATUS_SUCCESS != status)
1629 {
1630 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1631 "dxeRXFrameReady unable to unlock packet");
1632 return -1;
1633 }
1634#endif /* FEATURE_R33D */
1635 /* This Descriptor is valid, so linked Control block is also valid
1636 * Linked Control block has pre allocated packet buffer
1637 * So, just let upper layer knows preallocated frame pointer will be OK */
1638 /* Reap Rx frames */
1639 rx_reaped_buf[frameCount] = currentCtrlBlk->xfrFrame;
1640 frameCount++;
1641
1642 /* Now try to refill the ring with empty Rx buffers to keep DXE busy */
1643 dxeRXFrameRefillRing(dxeCtxt,channelEntry);
1644
1645 /* Test next contorl block
1646 * if valid, this control block also has new RX frame must be handled */
1647 currentCtrlBlk = (WLANDXE_DescCtrlBlkType *)currentCtrlBlk->nextCtrlBlk;
1648 currentDesc = currentCtrlBlk->linkedDesc;
1649 descCtrl = currentDesc->descCtrl.ctrl;
1650 }
1651
1652 /* Update head control block
1653 * current control block's valid bit was 0
1654 * next trial first control block must be current control block */
1655 channelEntry->headCtrlBlk = currentCtrlBlk;
1656
1657 /* Deliver all the reaped RX frames to upper layers */
1658 i = 0;
1659 while(i < frameCount) {
1660 dxeCtxt->rxReadyCB(dxeCtxt->clientCtxt, rx_reaped_buf[i], channelEntry->channelType);
1661 i++;
1662 }
1663
1664 return frameCount;
1665}
1666
1667/*==========================================================================
Jeff Johnson295189b2012-06-20 16:38:30 -07001668 @ Function Name
1669 dxeRXFrameReady
1670
1671 @ Description
1672 Pop frame from descriptor and route frame to upper transport layer
1673 Assign new platform packet buffer into used descriptor
1674 Actual frame pop and resource realloc
1675
1676 @ Parameters
1677 WLANDXE_CtrlBlkType *dxeCtrlBlk,
1678 DXE host driver main control block
1679 WLANDXE_ChannelCBType *channelEntry
1680 Channel specific control block
1681
1682 @ Return
1683 wpt_status
1684
1685===========================================================================*/
1686static wpt_status dxeRXFrameReady
1687(
1688 WLANDXE_CtrlBlkType *dxeCtxt,
1689 WLANDXE_ChannelCBType *channelEntry
1690)
1691{
1692 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
1693 WLANDXE_DescCtrlBlkType *currentCtrlBlk = NULL;
1694 WLANDXE_DescType *currentDesc = NULL;
1695 wpt_uint32 descCtrl;
Jeff Johnsone7245742012-09-05 17:12:55 -07001696 wpt_int32 frameCount = 0;
1697
1698 wpt_uint32 descLoop;
1699 wpt_uint32 invalidatedFound = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001700
1701 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
1702 "%s Enter", __FUNCTION__);
1703
1704 /* Sanity Check */
1705 if((NULL == dxeCtxt) || (NULL == channelEntry))
1706 {
1707 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1708 "dxeRXFrameReady Channel Entry is not valid");
1709 return eWLAN_PAL_STATUS_E_INVAL;
1710 }
1711
Jeff Johnsone7245742012-09-05 17:12:55 -07001712 frameCount = dxeRXFrameRouteUpperLayer(dxeCtxt, channelEntry);
Jeff Johnson295189b2012-06-20 16:38:30 -07001713
Jeff Johnsone7245742012-09-05 17:12:55 -07001714 if(0 > frameCount)
Jeff Johnson295189b2012-06-20 16:38:30 -07001715 {
1716 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
Jeff Johnsone7245742012-09-05 17:12:55 -07001717 "dxeRXFrameReady RX frame route fail");
Jeff Johnson295189b2012-06-20 16:38:30 -07001718 return eWLAN_PAL_STATUS_E_INVAL;
1719 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001720
Jeff Johnsone7245742012-09-05 17:12:55 -07001721 if((0 == frameCount) &&
1722 ((WLANDXE_POWER_STATE_BMPS == dxeCtxt->hostPowerState) ||
1723 (WLANDXE_POWER_STATE_FULL == dxeCtxt->hostPowerState)))
1724 {
1725 currentCtrlBlk = channelEntry->headCtrlBlk;
Jeff Johnson295189b2012-06-20 16:38:30 -07001726 currentDesc = currentCtrlBlk->linkedDesc;
1727 descCtrl = currentDesc->descCtrl.ctrl;
Jeff Johnsone7245742012-09-05 17:12:55 -07001728
1729 if(WLANDXE_POWER_STATE_BMPS != dxeCtxt->hostPowerState)
1730 {
1731 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
1732 "RX ISR called but no frame handled PWS %d, channel %s",
1733 (int)dxeCtxt->hostPowerState,
1734 channelType[channelEntry->channelType]);
1735 }
1736
1737 /* Current interupt empty and previous interrupt also empty
1738 * detected successive empty interrupt
1739 * or first interrupt empty, this should not happen */
1740 if(0 == channelEntry->numFragmentCurrentChain)
1741 {
1742 dxeChannelMonitor("RX Ready", channelEntry);
1743 dxeDescriptorDump(channelEntry, channelEntry->headCtrlBlk->linkedDesc, 0);
1744 dxeChannelRegisterDump(channelEntry, "RX successive empty interrupt");
1745 dxeChannelAllDescDump(channelEntry);
1746
1747 /* Abnormal interrupt detected, try to find not validated descriptor */
1748 for(descLoop = 0; descLoop < channelEntry->numDesc; descLoop++)
1749 {
1750 if(!(WLANDXE_U32_SWAP_ENDIAN(descCtrl) & WLANDXE_DESC_CTRL_VALID))
1751 {
1752 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1753 "Found Invalidated Descriptor %d", (int)descLoop);
1754 if(eWLAN_PAL_STATUS_SUCCESS == wpalIsPacketLocked(currentCtrlBlk->xfrFrame))
1755 {
1756 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1757 "Packet locked, Resync Host and HW");
1758 channelEntry->headCtrlBlk = currentCtrlBlk;
1759 invalidatedFound = 1;
1760 break;
1761 }
1762 else
1763 {
1764 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1765 "Packet Not Locked, cannot transfer frame");
1766 }
1767 }
1768 currentCtrlBlk = (WLANDXE_DescCtrlBlkType *)currentCtrlBlk->nextCtrlBlk;
1769 currentDesc = currentCtrlBlk->linkedDesc;
1770 descCtrl = currentDesc->descCtrl.ctrl;
1771 }
1772
Jeff Johnson32d95a32012-09-10 13:15:23 -07001773 /* Invalidated descriptor found, and that is not head descriptor
1774 * This means HW/SW descriptor miss match happen, and we may recover with just resync
1775 * Try re-sync here */
1776 if((invalidatedFound) && (0 != descLoop))
Jeff Johnsone7245742012-09-05 17:12:55 -07001777 {
1778 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1779 "Found New Sync location with HW, handle frames from there");
1780 frameCount = dxeRXFrameRouteUpperLayer(dxeCtxt, channelEntry);
1781 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1782 "re-sync routed %d frames to upper layer", (int)frameCount);
1783 frameCount = 0;
1784 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001785 /* Successive Empty interrupt
1786 * But this case, first descriptor also invalidated, then it means head descriptor
1787 * is linked with already handled RX frame, then could not unlock RX frame
1788 * This is just Out of RX buffer pool, not need to anything here */
1789 else if((invalidatedFound) && (0 == descLoop))
1790 {
1791 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1792 "Out of RX Low resource, and INT came in, do nothing till get RX resource");
1793 }
1794 /* Critical error, reload driver */
Jeff Johnsone7245742012-09-05 17:12:55 -07001795 else
1796 {
1797 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1798 "Could not found invalidated descriptor");
1799 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1800 "RX successive empty interrupt, Could not find invalidated DESC reload driver");
1801 dxeCtxt->driverReloadInProcessing = eWLAN_PAL_TRUE;
1802 wpalWlanReload();
1803 }
1804 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001805 }
1806
1807 channelEntry->numFragmentCurrentChain = frameCount;
Jeff Johnson295189b2012-06-20 16:38:30 -07001808 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
1809 "%s Exit", __FUNCTION__);
1810 return status;
1811}
1812
1813/*==========================================================================
1814 @ Function Name
1815 dxeNotifySmsm
1816
1817 @ Description: Notify SMSM to start DXE engine and/or condition of Tx ring
1818 buffer
1819
1820 @ Parameters
1821
1822 @ Return
1823 wpt_status
1824
1825===========================================================================*/
1826static wpt_status dxeNotifySmsm
1827(
1828 wpt_boolean kickDxe,
1829 wpt_boolean ringEmpty
1830)
1831{
1832 wpt_uint32 clrSt = 0;
1833 wpt_uint32 setSt = 0;
1834
1835 if(kickDxe)
1836 {
1837 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_MED, "Kick off DXE");
1838
1839 if(tempDxeCtrlBlk->lastKickOffDxe == 0)
1840 {
1841 setSt |= WPAL_SMSM_WLAN_TX_ENABLE;
1842 tempDxeCtrlBlk->lastKickOffDxe = 1;
1843 }
1844 else if(tempDxeCtrlBlk->lastKickOffDxe == 1)
1845 {
1846 clrSt |= WPAL_SMSM_WLAN_TX_ENABLE;
1847 tempDxeCtrlBlk->lastKickOffDxe = 0;
1848 }
1849 else
1850 {
1851 HDXE_ASSERT(0);
1852 }
1853 }
1854 else
1855 {
1856 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_MED, "no need to kick off DXE");
1857 }
1858
1859 if(ringEmpty)
1860 {
1861 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_MED, "SMSM Tx Ring Empty");
1862 clrSt |= WPAL_SMSM_WLAN_TX_RINGS_EMPTY;
1863 }
1864 else
1865 {
1866 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_MED, "SMSM Tx Ring Not Empty");
1867 setSt |= WPAL_SMSM_WLAN_TX_RINGS_EMPTY;
1868 }
1869
1870 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_HIGH, "C%x S%x", clrSt, setSt);
1871
1872 wpalNotifySmsm(clrSt, setSt);
1873
1874 return eWLAN_PAL_STATUS_SUCCESS;
1875}
1876
1877/*==========================================================================
1878 @ Function Name
1879 dxePsComplete
1880
1881 @ Description: Utility function to check the resv desc to deside if we can
1882 get into Power Save mode now
1883
1884 @ Parameters
1885
1886 @ Return
1887 None
1888
1889===========================================================================*/
1890static void dxePsComplete(WLANDXE_CtrlBlkType *dxeCtxt, wpt_boolean intr_based)
1891{
1892 if( dxeCtxt->hostPowerState == WLANDXE_POWER_STATE_FULL )
1893 {
1894 return;
1895 }
1896
1897 //if both HIGH & LOW Tx channels don't have anything on resv desc,all Tx pkts
1898 //must have been consumed by RIVA, OK to get into BMPS
1899 if((0 == dxeCtxt->dxeChannel[WDTS_CHANNEL_TX_LOW_PRI].numRsvdDesc) &&
1900 (0 == dxeCtxt->dxeChannel[WDTS_CHANNEL_TX_HIGH_PRI].numRsvdDesc))
1901 {
1902 tempDxeCtrlBlk->ringNotEmpty = eWLAN_PAL_FALSE;
1903 //if host is in BMPS & no pkt to Tx, RIVA can go to power save
1904 if(WLANDXE_POWER_STATE_BMPS == dxeCtxt->hostPowerState)
1905 {
1906 dxeCtxt->rivaPowerState = WLANDXE_RIVA_POWER_STATE_BMPS_UNKNOWN;
1907 dxeNotifySmsm(eWLAN_PAL_FALSE, eWLAN_PAL_TRUE);
1908 }
1909 }
1910 else //still more pkts to be served by RIVA
1911 {
1912 tempDxeCtrlBlk->ringNotEmpty = eWLAN_PAL_TRUE;
1913
1914 switch(dxeCtxt->rivaPowerState)
1915 {
1916 case WLANDXE_RIVA_POWER_STATE_ACTIVE:
1917 //NOP
1918 break;
1919 case WLANDXE_RIVA_POWER_STATE_BMPS_UNKNOWN:
1920 if(intr_based)
1921 {
1922 dxeCtxt->rivaPowerState = WLANDXE_RIVA_POWER_STATE_ACTIVE;
1923 dxeNotifySmsm(eWLAN_PAL_TRUE, eWLAN_PAL_FALSE);
1924 }
1925 break;
1926 default:
1927 //assert
1928 break;
1929 }
1930 }
1931}
1932
1933/*==========================================================================
1934 @ Function Name
1935 dxeRXEventHandler
1936
1937 @ Description
1938 Handle serailized RX frame ready event
1939 First disable interrupt then pick up frame from pre allocated buffer
1940 Since frame handle is doen, clear interrupt bit to ready next interrupt
1941 Finally re enable interrupt
1942
1943 @ Parameters
1944 wpt_msg *rxReadyMsg
1945 RX frame ready MSG pointer
1946 include DXE control context
1947
1948 @ Return
1949 NONE
1950
1951===========================================================================*/
1952void dxeRXEventHandler
1953(
1954 wpt_msg *rxReadyMsg
1955)
1956{
1957 wpt_msg *msgContent = (wpt_msg *)rxReadyMsg;
1958 WLANDXE_CtrlBlkType *dxeCtxt = NULL;
1959 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
1960 wpt_uint32 intSrc = 0;
1961 WLANDXE_ChannelCBType *channelCb = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07001962 wpt_uint32 chHighStat = 0;
1963 wpt_uint32 chLowStat = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001964
Jeff Johnsone7245742012-09-05 17:12:55 -07001965 dxeCtxt = (WLANDXE_CtrlBlkType *)(msgContent->pContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07001966
Jeff Johnsone7245742012-09-05 17:12:55 -07001967 if(eWLAN_PAL_TRUE == dxeCtxt->driverReloadInProcessing)
Jeff Johnson295189b2012-06-20 16:38:30 -07001968 {
1969 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
Jeff Johnsone7245742012-09-05 17:12:55 -07001970 "RX Ready WLAN Driver re-loading in progress");
Jeff Johnson32d95a32012-09-10 13:15:23 -07001971 return;
Jeff Johnson295189b2012-06-20 16:38:30 -07001972 }
1973
Jeff Johnsone7245742012-09-05 17:12:55 -07001974 /* Now try to refill the ring with empty Rx buffers to keep DXE busy */
1975 dxeRXFrameRefillRing(dxeCtxt, &dxeCtxt->dxeChannel[WDTS_CHANNEL_RX_LOW_PRI]);
1976 dxeRXFrameRefillRing(dxeCtxt, &dxeCtxt->dxeChannel[WDTS_CHANNEL_RX_HIGH_PRI]);
1977
Jeff Johnson295189b2012-06-20 16:38:30 -07001978 dxeCtxt = (WLANDXE_CtrlBlkType *)(msgContent->pContext);
1979
1980 if((!dxeCtxt->dxeChannel[WDTS_CHANNEL_RX_HIGH_PRI].extraConfig.chEnabled) ||
1981 (!dxeCtxt->dxeChannel[WDTS_CHANNEL_RX_LOW_PRI].extraConfig.chEnabled))
1982 {
1983 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
1984 "DXE already stopped in RX event handler. Just return");
1985 return;
1986 }
1987
1988 if((WLANDXE_POWER_STATE_IMPS == dxeCtxt->hostPowerState) ||
1989 (WLANDXE_POWER_STATE_DOWN == dxeCtxt->hostPowerState))
1990 {
1991 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN,
1992 "%s Riva is in %d, Just Pull frames without any register touch ",
1993 __FUNCTION__, dxeCtxt->hostPowerState);
1994
1995 /* Not to touch any register, just pull frame directly from chain ring
1996 * First high priority */
1997 channelCb = &dxeCtxt->dxeChannel[WDTS_CHANNEL_RX_HIGH_PRI];
1998 status = dxeRXFrameReady(dxeCtxt,
1999 channelCb);
2000 if(eWLAN_PAL_STATUS_SUCCESS != status)
2001 {
2002 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2003 "dxeRXEventHandler Pull from RX high channel fail");
2004 }
2005
2006 /* Second low priority */
2007 channelCb = &dxeCtxt->dxeChannel[WDTS_CHANNEL_RX_LOW_PRI];
2008 status = dxeRXFrameReady(dxeCtxt,
2009 channelCb);
2010 if(eWLAN_PAL_STATUS_SUCCESS != status)
2011 {
2012 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2013 "dxeRXEventHandler Pull from RX low channel fail");
2014 }
2015
2016 /* Interrupt will not enabled at here, it will be enabled at PS mode change */
2017 tempDxeCtrlBlk->rxIntDisabledByIMPS = eWLAN_PAL_TRUE;
2018
2019 return;
2020 }
2021
2022 /* Disable device interrupt */
2023 /* Read whole interrupt mask register and exclusive only this channel int */
2024 status = wpalReadRegister(WLANDXE_INT_SRC_RAW_ADDRESS,
2025 &intSrc);
2026 if(eWLAN_PAL_STATUS_SUCCESS != status)
2027 {
2028 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2029 "dxeRXEventHandler Read INT_SRC register fail");
2030 return;
2031 }
2032 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_MED,
2033 "RX Event Handler INT Source 0x%x", intSrc);
2034
2035#ifndef WLANDXE_TEST_CHANNEL_ENABLE
2036 /* Test High Priority Channel interrupt is enabled or not */
2037 channelCb = &dxeCtxt->dxeChannel[WDTS_CHANNEL_RX_HIGH_PRI];
2038 if(intSrc & (1 << channelCb->assignedDMAChannel))
2039 {
2040 status = dxeChannelCleanInt(channelCb, &chHighStat);
2041 if(eWLAN_PAL_STATUS_SUCCESS != status)
2042 {
2043 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2044 "dxeRXEventHandler INT Clean up fail");
2045 return;
2046 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002047 if(WLANDXE_CH_STAT_INT_ERR_MASK & chHighStat)
2048 {
2049 /* Error Happen during transaction, Handle it */
2050 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07002051 else if((WLANDXE_CH_STAT_INT_DONE_MASK & chHighStat) ||
2052 (WLANDXE_CH_STAT_INT_ED_MASK & chHighStat))
Jeff Johnson295189b2012-06-20 16:38:30 -07002053 {
2054 /* Handle RX Ready for high priority channel */
2055 status = dxeRXFrameReady(dxeCtxt,
2056 channelCb);
2057 }
2058 else if(WLANDXE_CH_STAT_MASKED_MASK & chHighStat)
2059 {
2060 status = dxeRXFrameReady(dxeCtxt,
2061 channelCb);
2062 }
2063 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO,
2064 "RX HIGH CH EVNT STAT 0x%x, %d frames handled", chHighStat, channelCb->numFragmentCurrentChain);
Jeff Johnsone7245742012-09-05 17:12:55 -07002065 /* Update the Rx DONE histogram */
2066 channelCb->rxDoneHistogram = (channelCb->rxDoneHistogram << 1);
2067 if(WLANDXE_CH_STAT_INT_DONE_MASK & chHighStat)
2068 {
2069 channelCb->rxDoneHistogram |= 1;
2070 }
2071 else
2072 {
2073 channelCb->rxDoneHistogram &= ~1;
2074 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002075 }
2076#else
2077 /* Test H2H Test interrupt is enabled or not */
2078 channelCb = &dxeCtxt->dxeChannel[WDTS_CHANNEL_H2H_TEST_RX];
2079 if(intSrc & (1 << channelCb->assignedDMAChannel))
2080 {
2081 status = dxeChannelCleanInt(channelCb, &chStat);
2082 if(eWLAN_PAL_STATUS_SUCCESS != status)
2083 {
2084 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2085 "dxeRXEventHandler INT Clean up fail");
2086 return;
2087 }
2088
2089 if(WLANDXE_CH_STAT_INT_ERR_MASK & chStat)
2090 {
2091 /* Error Happen during transaction, Handle it */
2092 }
2093 else if(WLANDXE_CH_STAT_INT_ED_MASK & chStat)
2094 {
2095 /* Handle RX Ready for high priority channel */
2096 status = dxeRXFrameReady(dxeCtxt,
2097 channelCb);
2098 }
2099 /* Update the Rx DONE histogram */
2100 channelCb->rxDoneHistogram = (channelCb->rxDoneHistogram << 1);
2101 if(WLANDXE_CH_STAT_INT_DONE_MASK & chStat)
2102 {
2103 channelCb->rxDoneHistogram |= 1;
2104 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN,
2105 "DXE Channel Number %d, Rx DONE Histogram 0x%016llx",
2106 channelCb->assignedDMAChannel, channelCb->rxDoneHistogram);
2107 }
2108 else
2109 {
2110 channelCb->rxDoneHistogram &= ~1;
2111 }
2112 }
2113#endif /* WLANDXE_TEST_CHANNEL_ENABLE */
2114
2115 /* Test Low Priority Channel interrupt is enabled or not */
Jeff Johnsone7245742012-09-05 17:12:55 -07002116 channelCb = &dxeCtxt->dxeChannel[WDTS_CHANNEL_RX_LOW_PRI];
Jeff Johnson295189b2012-06-20 16:38:30 -07002117 if(intSrc & (1 << channelCb->assignedDMAChannel))
2118 {
2119 status = dxeChannelCleanInt(channelCb, &chLowStat);
2120 if(eWLAN_PAL_STATUS_SUCCESS != status)
2121 {
2122 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2123 "dxeRXEventHandler INT Clean up fail");
2124 return;
2125 }
2126
2127 if(WLANDXE_CH_STAT_INT_ERR_MASK & chLowStat)
2128 {
2129 /* Error Happen during transaction, Handle it */
2130 }
2131 else if(WLANDXE_CH_STAT_INT_ED_MASK & chLowStat)
2132 {
2133 /* Handle RX Ready for low priority channel */
2134 status = dxeRXFrameReady(dxeCtxt,
2135 channelCb);
Jeff Johnsone7245742012-09-05 17:12:55 -07002136 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002137
2138 /* Update the Rx DONE histogram */
2139 channelCb->rxDoneHistogram = (channelCb->rxDoneHistogram << 1);
2140 if(WLANDXE_CH_STAT_INT_DONE_MASK & chLowStat)
2141 {
2142 channelCb->rxDoneHistogram |= 1;
Jeff Johnson295189b2012-06-20 16:38:30 -07002143 }
2144 else
2145 {
2146 channelCb->rxDoneHistogram &= ~1;
2147 }
2148 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO,
2149 "RX LOW CH EVNT STAT 0x%x, %d frames handled", chLowStat, channelCb->numFragmentCurrentChain);
2150 }
2151 if(eWLAN_PAL_STATUS_SUCCESS != status)
2152 {
2153 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2154 "dxeRXEventHandler Handle Frame Ready Fail");
2155 return;
2156 }
2157
2158 /* Enable system level ISR */
2159 /* Enable RX ready Interrupt at here */
2160 status = wpalEnableInterrupt(DXE_INTERRUPT_RX_READY);
2161 if(eWLAN_PAL_STATUS_SUCCESS != status)
2162 {
2163 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2164 "dxeRXEventHandler Enable RX Ready interrupt fail");
2165 return;
2166 }
2167
2168 /* Prepare Control Register EN Channel */
2169 if(!(dxeCtxt->dxeChannel[WDTS_CHANNEL_RX_HIGH_PRI].extraConfig.chan_mask & WLANDXE_CH_CTRL_EN_MASK))
2170 {
2171 HDXE_ASSERT(0);
2172 }
2173 if(!(WLANDXE_CH_STAT_INT_ED_MASK & chHighStat))
2174 {
2175 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_MED,
2176 "dxeRXEventHandler RX High, Not yet ED, re-enable CH");
2177 wpalWriteRegister(dxeCtxt->dxeChannel[WDTS_CHANNEL_RX_HIGH_PRI].channelRegister.chDXECtrlRegAddr,
2178 dxeCtxt->dxeChannel[WDTS_CHANNEL_RX_HIGH_PRI].extraConfig.chan_mask);
2179 }
2180 else
2181 {
2182 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_MED,
2183 "dxeRXEventHandler RX High, CH STAT = ED_MASK, will RIVA PC");
2184 }
2185
2186 /* Prepare Control Register EN Channel */
2187 if(!(dxeCtxt->dxeChannel[WDTS_CHANNEL_RX_LOW_PRI].extraConfig.chan_mask & WLANDXE_CH_CTRL_EN_MASK))
2188 {
2189 HDXE_ASSERT(0);
2190 }
2191 if(!(WLANDXE_CH_STAT_INT_ED_MASK & chLowStat))
2192 {
2193 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_MED,
2194 "dxeRXEventHandler RX Low, Not yet ED, re-enable CH");
2195 wpalWriteRegister(dxeCtxt->dxeChannel[WDTS_CHANNEL_RX_LOW_PRI].channelRegister.chDXECtrlRegAddr,
2196 dxeCtxt->dxeChannel[WDTS_CHANNEL_RX_LOW_PRI].extraConfig.chan_mask);
2197 }
2198 else
2199 {
2200 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_MED,
2201 "dxeRXEventHandler RX Low, CH STAT = ED_MASK, will RIVA PC");
2202 }
2203
2204 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
2205 "%s Exit", __FUNCTION__);
2206 return;
2207}
2208
2209/*==========================================================================
2210 @ Function Name
2211 dxeRXPacketAvailableEventHandler
2212
2213 @ Description
2214 Handle serialized RX Packet Available event when the corresponding callback
2215 is invoked by WPAL.
2216 Try to fill up any completed DXE descriptors with available Rx packet buffer
2217 pointers.
2218
2219 @ Parameters
2220 wpt_msg *rxPktAvailMsg
2221 RX frame ready MSG pointer
2222 include DXE control context
2223
2224 @ Return
2225 NONE
2226
2227===========================================================================*/
2228void dxeRXPacketAvailableEventHandler
2229(
2230 wpt_msg *rxPktAvailMsg
2231)
2232{
2233 WLANDXE_CtrlBlkType *dxeCtxt = NULL;
2234 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
2235 WLANDXE_ChannelCBType *channelCb = NULL;
2236
2237 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
2238 "%s Enter", __FUNCTION__);
2239
2240 /* Sanity Check */
2241 if(NULL == rxPktAvailMsg)
2242 {
2243 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2244 "dxeRXPacketAvailableEventHandler Context is not valid");
2245 return;
2246 }
2247
2248 dxeCtxt = (WLANDXE_CtrlBlkType *)(rxPktAvailMsg->pContext);
2249
2250 do
2251 {
2252 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN,
2253 "dxeRXPacketAvailableEventHandler, start refilling ring");
2254
2255 channelCb = &dxeCtxt->dxeChannel[WDTS_CHANNEL_RX_HIGH_PRI];
2256 status = dxeRXFrameRefillRing(dxeCtxt,channelCb);
2257
2258 // Wait for another callback to indicate when Rx resources are available
2259 // again.
2260 if(eWLAN_PAL_STATUS_SUCCESS != status)
2261 {
2262 break;
2263 }
2264
2265 channelCb = &dxeCtxt->dxeChannel[WDTS_CHANNEL_RX_LOW_PRI];
2266 status = dxeRXFrameRefillRing(dxeCtxt,channelCb);
2267 if(eWLAN_PAL_STATUS_SUCCESS != status)
2268 {
2269 break;
2270 }
2271 } while(0);
2272
2273 if((WLANDXE_POWER_STATE_IMPS == dxeCtxt->hostPowerState) ||
2274 (WLANDXE_POWER_STATE_DOWN == dxeCtxt->hostPowerState))
2275 {
2276 /* Interrupt will not enabled at here, it will be enabled at PS mode change */
2277 tempDxeCtrlBlk->rxIntDisabledByIMPS = eWLAN_PAL_TRUE;
2278 }
2279}
2280
2281/*==========================================================================
2282 @ Function Name
2283 dxeRXISR
2284
2285 @ Description
2286 RX frame ready interrupt service routine
2287 interrupt entry function, this function called based on ISR context
2288 Must be serialized
2289
2290 @ Parameters
2291 void *hostCtxt
2292 DXE host driver control context,
2293 pre registerd during interrupt registration
2294
2295 @ Return
2296 NONE
2297
2298===========================================================================*/
2299static void dxeRXISR
2300(
2301 void *hostCtxt
2302)
2303{
2304 WLANDXE_CtrlBlkType *dxeCtxt = (WLANDXE_CtrlBlkType *)hostCtxt;
2305 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
2306#ifdef FEATURE_R33D
2307 wpt_uint32 regValue;
2308#endif /* FEATURE_R33D */
2309
Jeff Johnson295189b2012-06-20 16:38:30 -07002310
2311#ifdef FEATURE_R33D
2312 status = wpalReadRegister(WLANDXE_INT_SRC_RAW_ADDRESS,
2313 &regValue);
2314 if(eWLAN_PAL_STATUS_SUCCESS != status)
2315 {
2316 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2317 "dxeTXCompISR Read INT_SRC_RAW fail");
2318 return;
2319 }
2320 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN,
2321 "INT_SRC_RAW 0x%x", regValue);
2322 if(0 == regValue)
2323 {
2324 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN,
2325 "This is not DXE Interrupt, Reject it 0x%x", regValue);
2326 return;
2327 }
2328#endif /* FEATURE_R33D */
2329
2330 /* Disable interrupt at here
2331 * Disable RX Ready system level Interrupt at here
2332 * Otherwise infinite loop might happen */
2333 status = wpalDisableInterrupt(DXE_INTERRUPT_RX_READY);
2334 if(eWLAN_PAL_STATUS_SUCCESS != status)
2335 {
2336 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2337 "dxeRXFrameReadyISR Disable RX ready interrupt fail");
2338 return;
2339 }
2340
2341 /* Serialize RX Ready interrupt upon RX thread */
2342 HDXE_ASSERT(NULL != dxeCtxt->rxIsrMsg);
2343 status = wpalPostRxMsg(WDI_GET_PAL_CTX(),
2344 dxeCtxt->rxIsrMsg);
2345 if(eWLAN_PAL_STATUS_SUCCESS != status)
2346 {
2347 HDXE_ASSERT(eWLAN_PAL_STATUS_SUCCESS == status);
2348 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
2349 "dxeRXFrameReadyISR interrupt serialize fail");
2350 }
2351
Jeff Johnson295189b2012-06-20 16:38:30 -07002352 return;
2353}
2354
2355/*==========================================================================
2356 @ Function Name
2357 dxeTXPushFrame
2358
2359 @ Description
2360 Push TX frame into DXE descriptor and DXE register
2361 Send notification to DXE register that TX frame is ready to transfer
2362
2363 @ Parameters
2364 WLANDXE_ChannelCBType *channelEntry
2365 Channel specific control block
2366 wpt_packet *palPacket
2367 Packet pointer ready to transfer
2368
2369 @ Return
2370 PAL_STATUS_T
2371===========================================================================*/
2372static wpt_status dxeTXPushFrame
2373(
2374 WLANDXE_ChannelCBType *channelEntry,
2375 wpt_packet *palPacket
2376)
2377{
2378 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
2379 WLANDXE_DescCtrlBlkType *currentCtrlBlk = NULL;
2380 WLANDXE_DescType *currentDesc = NULL;
2381 WLANDXE_DescType *firstDesc = NULL;
2382 WLANDXE_DescType *LastDesc = NULL;
2383 void *sourcePhysicalAddress = NULL;
2384 wpt_uint32 xferSize = 0;
2385#ifdef FEATURE_R33D
2386 tx_frm_pcie_vector_t frameVector;
2387 wpt_uint32 Va;
2388 wpt_uint32 fragCount = 0;
2389#else
2390 wpt_iterator iterator;
2391#endif /* FEATURE_R33D */
Jeff Johnsone7245742012-09-05 17:12:55 -07002392
2393 wpt_uint32 isEmpty = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07002394
2395 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
2396 "%s Enter", __FUNCTION__);
2397
Jeff Johnsone7245742012-09-05 17:12:55 -07002398 if((0 == tempDxeCtrlBlk->dxeChannel[WDTS_CHANNEL_TX_LOW_PRI].numRsvdDesc) &&
2399 (0 == tempDxeCtrlBlk->dxeChannel[WDTS_CHANNEL_TX_HIGH_PRI].numRsvdDesc))
Jeff Johnson295189b2012-06-20 16:38:30 -07002400 {
Jeff Johnsone7245742012-09-05 17:12:55 -07002401 isEmpty = 1;
Jeff Johnson295189b2012-06-20 16:38:30 -07002402 }
2403
2404 channelEntry->numFragmentCurrentChain = 0;
2405 currentCtrlBlk = channelEntry->headCtrlBlk;
2406
2407 /* Initialize interator, TX is fragmented */
2408#ifdef FEATURE_R33D
2409 memset(&frameVector, 0, sizeof(tx_frm_pcie_vector_t));
2410 status = wpalPrepareTxFrame(palPacket,
2411 &frameVector,
2412 &Va);
2413#else
2414 status = wpalLockPacketForTransfer(palPacket);
2415 if(eWLAN_PAL_STATUS_SUCCESS != status)
2416 {
2417 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2418 "dxeTXPushFrame unable to lock packet");
2419 return status;
2420 }
2421
2422 status = wpalIteratorInit(&iterator, palPacket);
2423#endif /* FEATURE_R33D */
2424 if(eWLAN_PAL_STATUS_SUCCESS != status)
2425 {
2426 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2427 "dxeTXPushFrame iterator init fail");
2428 return status;
2429 }
2430
2431 /* !!!! Revisit break condition !!!!!!! */
2432 while(1)
2433 {
2434 /* Get current descriptor pointer from current control block */
2435 currentDesc = currentCtrlBlk->linkedDesc;
2436 if(NULL == firstDesc)
2437 {
2438 firstDesc = currentCtrlBlk->linkedDesc;
2439 }
2440 /* All control block will have same palPacket Pointer
2441 * to make logic simpler */
2442 currentCtrlBlk->xfrFrame = palPacket;
2443
2444 /* Get next fragment physical address and fragment size
2445 * if this is the first trial, will get first physical address
2446 * if no more fragment, Descriptor src address will be set as NULL, OK??? */
2447#ifdef FEATURE_R33D
2448 if(fragCount == frameVector.num_frg)
2449 {
2450 break;
2451 }
2452 currentCtrlBlk->shadowBufferVa = frameVector.frg[0].va;
2453 sourcePhysicalAddress = (void *)frameVector.frg[fragCount].pa;
2454 xferSize = frameVector.frg[fragCount].size;
2455 fragCount++;
2456 HDXE_ASSERT(0 != xferSize);
2457 HDXE_ASSERT(NULL != sourcePhysicalAddress);
2458#else
2459 status = wpalIteratorNext(&iterator,
2460 palPacket,
2461 &sourcePhysicalAddress,
2462 &xferSize);
2463 if((NULL == sourcePhysicalAddress) ||
2464 (0 == xferSize))
2465 {
2466 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
2467 "dxeTXPushFrame end of current frame");
2468 break;
2469 }
2470 if(eWLAN_PAL_STATUS_SUCCESS != status)
2471 {
2472 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2473 "dxeTXPushFrame Get next frame fail");
2474 return status;
2475 }
2476#endif /* FEATURE_R33D */
2477
2478 /* This is the LAST descriptor valid for this transaction */
2479 LastDesc = currentCtrlBlk->linkedDesc;
2480
2481 /* Program DXE descriptor */
2482 currentDesc->dxedesc.dxe_short_desc.srcMemAddrL =
2483 WLANDXE_U32_SWAP_ENDIAN((wpt_uint32)sourcePhysicalAddress);
2484
2485 /* Just normal data transfer from aCPU Flat Memory to BMU Q */
2486 if((WDTS_CHANNEL_TX_LOW_PRI == channelEntry->channelType) ||
2487 (WDTS_CHANNEL_TX_HIGH_PRI == channelEntry->channelType))
2488 {
2489 currentDesc->dxedesc.dxe_short_desc.dstMemAddrL =
2490 WLANDXE_U32_SWAP_ENDIAN(channelEntry->channelConfig.refWQ);
2491 }
2492 else
2493 {
2494 /* Test specific H2H transfer, destination address already set
2495 * Do Nothing */
2496 }
2497 currentDesc->xfrSize = WLANDXE_U32_SWAP_ENDIAN(xferSize);
2498
2499 /* Program channel control register */
2500 /* First frame not set VAL bit, why ??? */
2501 if(0 == channelEntry->numFragmentCurrentChain)
2502 {
2503 currentDesc->descCtrl.ctrl = channelEntry->extraConfig.cw_ctrl_write;
2504 }
2505 else
2506 {
2507 currentDesc->descCtrl.ctrl = channelEntry->extraConfig.cw_ctrl_write_valid;
2508 }
2509
2510 /* Update statistics */
2511 channelEntry->numFragmentCurrentChain++;
2512 channelEntry->numFreeDesc--;
2513 channelEntry->numRsvdDesc++;
2514
2515 /* Get next control block */
2516 currentCtrlBlk = currentCtrlBlk->nextCtrlBlk;
2517 }
2518 channelEntry->numTotalFrame++;
2519 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
2520 "NUM TX FRAG %d, Total Frame %d",
2521 channelEntry->numFragmentCurrentChain, channelEntry->numTotalFrame);
2522
2523 /* Program Channel control register
2524 * Set as end of packet
2525 * Enable interrupt also for first code lock down
2526 * performace optimization, this will be revisited */
2527 if(NULL == LastDesc)
2528 {
2529 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2530 "dxeTXPushFrame NULL Last Descriptor, broken chain");
2531 return eWLAN_PAL_STATUS_E_FAULT;
2532 }
2533 LastDesc->descCtrl.ctrl = channelEntry->extraConfig.cw_ctrl_write_eop_int;
2534 /* Now First one also Valid ????
2535 * this procedure will prevent over handle descriptor from previous
2536 * TX trigger */
2537 firstDesc->descCtrl.ctrl = channelEntry->extraConfig.cw_ctrl_write_valid;
2538
2539 /* If in BMPS mode no need to notify the DXE Engine, notify SMSM instead */
2540 if(WLANDXE_RIVA_POWER_STATE_BMPS_UNKNOWN == tempDxeCtrlBlk->rivaPowerState)
2541 {
2542 /* Update channel head as next avaliable linked slot */
2543 channelEntry->headCtrlBlk = currentCtrlBlk;
Jeff Johnsone7245742012-09-05 17:12:55 -07002544
2545 if( isEmpty )
2546 {
2547 tempDxeCtrlBlk->ringNotEmpty = eWLAN_PAL_TRUE;
2548 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW, "SMSM_ret LO=%d HI=%d", tempDxeCtrlBlk->dxeChannel[WDTS_CHANNEL_TX_LOW_PRI].numRsvdDesc,
2549 tempDxeCtrlBlk->dxeChannel[WDTS_CHANNEL_TX_HIGH_PRI].numRsvdDesc );
2550 dxeNotifySmsm(eWLAN_PAL_TRUE, eWLAN_PAL_FALSE);
2551 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002552 return status;
2553 }
2554
2555 /* If DXE use external descriptor, registers are not needed to be programmed
2556 * Just after finish to program descriptor, tirigger to send */
2557 if(channelEntry->extraConfig.chan_mask & WLANDXE_CH_CTRL_EDEN_MASK)
2558 {
2559 /* Issue a dummy read from the DXE descriptor DDR location to
2560 ensure that any previously posted write to the descriptor
2561 completes. */
2562 if(channelEntry->extraConfig.cw_ctrl_write_valid != firstDesc->descCtrl.ctrl)
2563 {
2564 //HDXE_ASSERT(0);
2565 }
2566
2567 /* Everything is ready
2568 * Trigger to start DMA */
2569 status = wpalWriteRegister(channelEntry->channelRegister.chDXECtrlRegAddr,
2570 channelEntry->extraConfig.chan_mask);
2571 if(eWLAN_PAL_STATUS_SUCCESS != status)
2572 {
2573 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2574 "dxeTXPushFrame Write Channel Ctrl Register fail");
2575 return status;
2576 }
2577
2578 /* Update channel head as next avaliable linked slot */
2579 channelEntry->headCtrlBlk = currentCtrlBlk;
2580
2581 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
2582 "%s Exit", __FUNCTION__);
2583 return status;
2584 }
2585
2586 /* If DXE not use external descriptor, program each registers */
2587 /* Circular buffer handle not need to program DESC register???
2588 * GEN5 code not programed RING buffer case
2589 * REVISIT THIS !!!!!! */
2590 if((WDTS_CHANNEL_TX_LOW_PRI == channelEntry->channelType) ||
2591 (WDTS_CHANNEL_TX_HIGH_PRI == channelEntry->channelType))
2592 {
2593 /* Destination address, assigned Work Q */
2594 status = wpalWriteRegister(channelEntry->channelRegister.chDXEDadrlRegAddr,
2595 channelEntry->channelConfig.refWQ);
2596 if(eWLAN_PAL_STATUS_SUCCESS != status)
2597 {
2598 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2599 "dxeTXPushFrame Program dest address register fail");
2600 return status;
2601 }
2602 /* If descriptor format is SHORT */
2603 if(channelEntry->channelConfig.useShortDescFmt)
2604 {
2605 status = wpalWriteRegister(channelEntry->channelRegister.chDXEDadrhRegAddr,
2606 0);
2607 if(eWLAN_PAL_STATUS_SUCCESS != status)
2608 {
2609 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2610 "dxeTXPushFrame Program dest address register fail");
2611 return status;
2612 }
2613 }
2614 else
2615 {
2616 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2617 "dxeTXPushFrame LONG Descriptor Format!!!");
2618 }
2619 }
2620#ifdef WLANDXE_TEST_CHANNEL_ENABLE
2621 else if(WDTS_CHANNEL_H2H_TEST_TX == channelEntry->channelType)
2622 {
2623 /* Destination address, Physical memory address */
2624 status = wpalWriteRegister(channelEntry->channelRegister.chDXEDadrlRegAddr,
2625 WLANDXE_U32_SWAP_ENDIAN(firstDesc->dxedesc.dxe_short_desc.dstMemAddrL));
2626 if(eWLAN_PAL_STATUS_SUCCESS != status)
2627 {
2628 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2629 "dxeTXPushFrame Program dest address register fail");
2630 return status;
2631 }
2632 /* If descriptor format is SHORT */
2633 if(channelEntry->channelConfig.useShortDescFmt)
2634 {
2635 status = wpalWriteRegister(channelEntry->channelRegister.chDXEDadrhRegAddr,
2636 0);
2637 if(eWLAN_PAL_STATUS_SUCCESS != status)
2638 {
2639 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2640 "dxeTXPushFrame Program dest address register fail");
2641 return status;
2642 }
2643 }
2644 else
2645 {
2646 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2647 "dxeTXPushFrame LONG Descriptor Format!!!");
2648 }
2649 }
2650#endif /* WLANDXE_TEST_CHANNEL_ENABLE */
2651
2652 /* Program Source address register
2653 * This address is already programmed into DXE Descriptor
2654 * But register also upadte */
2655 status = wpalWriteRegister(channelEntry->channelRegister.chDXESadrlRegAddr,
2656 WLANDXE_U32_SWAP_ENDIAN(firstDesc->dxedesc.dxe_short_desc.srcMemAddrL));
2657 if(eWLAN_PAL_STATUS_SUCCESS != status)
2658 {
2659 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2660 "dxeTXPushFrame Program src address register fail");
2661 return status;
2662 }
2663 /* If descriptor format is SHORT */
2664 if(channelEntry->channelConfig.useShortDescFmt)
2665 {
2666 status = wpalWriteRegister(channelEntry->channelRegister.chDXESadrhRegAddr,
2667 0);
2668 if(eWLAN_PAL_STATUS_SUCCESS != status)
2669 {
2670 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2671 "dxeTXPushFrame Program dest address register fail");
2672 return status;
2673 }
2674 }
2675 else
2676 {
2677 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2678 "dxeTXPushFrame LONG Descriptor Format!!!");
2679 }
2680
2681 /* Linked list Descriptor pointer */
2682 status = wpalWriteRegister(channelEntry->channelRegister.chDXEDesclRegAddr,
2683 channelEntry->headCtrlBlk->linkedDescPhyAddr);
2684 if(eWLAN_PAL_STATUS_SUCCESS != status)
2685 {
2686 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2687 "dxeTXPushFrame Write DESC Address register fail");
2688 return status;
2689 }
2690 /* If descriptor format is SHORT */
2691 if(channelEntry->channelConfig.useShortDescFmt)
2692 {
2693 status = wpalWriteRegister(channelEntry->channelRegister.chDXEDeschRegAddr,
2694 0);
2695 if(eWLAN_PAL_STATUS_SUCCESS != status)
2696 {
2697 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2698 "dxeTXPushFrame Program dest address register fail");
2699 return status;
2700 }
2701 }
2702 else
2703 {
2704 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2705 "dxeTXPushFrame LONG Descriptor Format!!!");
2706 }
2707
2708 /* Transfer Size */
2709 xferSize = WLANDXE_U32_SWAP_ENDIAN(firstDesc->xfrSize);
2710 status = wpalWriteRegister(channelEntry->channelRegister.chDXESzRegAddr,
2711 xferSize);
2712 if(eWLAN_PAL_STATUS_SUCCESS != status)
2713 {
2714 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2715 "dxeTXPushFrame Write DESC Address register fail");
2716 return status;
2717 }
2718
2719 /* Everything is ready
2720 * Trigger to start DMA */
2721 status = wpalWriteRegister(channelEntry->channelRegister.chDXECtrlRegAddr,
2722 channelEntry->extraConfig.chan_mask);
2723 if(eWLAN_PAL_STATUS_SUCCESS != status)
2724 {
2725 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2726 "dxeTXPushFrame Write Channel Ctrl Register fail");
2727 return status;
2728 }
2729
2730 /* Update channel head as next avaliable linked slot */
2731 channelEntry->headCtrlBlk = currentCtrlBlk;
2732
2733 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
2734 "%s Exit", __FUNCTION__);
2735 return status;
2736}
2737
2738/*==========================================================================
2739 @ Function Name
2740 dxeTXCompFrame
2741
2742 @ Description
2743 TX Frame transfer complete event handler
2744
2745 @ Parameters
2746 WLANDXE_CtrlBlkType *dxeCtrlBlk,
2747 DXE host driver main control block
2748 WLANDXE_ChannelCBType *channelEntry
2749 Channel specific control block
2750
2751 @ Return
2752 PAL_STATUS_T
2753===========================================================================*/
2754static wpt_status dxeTXCompFrame
2755(
2756 WLANDXE_CtrlBlkType *hostCtxt,
2757 WLANDXE_ChannelCBType *channelEntry
2758)
2759{
2760 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
2761 WLANDXE_DescCtrlBlkType *currentCtrlBlk = NULL;
2762 WLANDXE_DescType *currentDesc = NULL;
2763 wpt_uint32 descCtrlValue = 0;
2764 unsigned int *lowThreshold = NULL;
2765
2766 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
2767 "%s Enter", __FUNCTION__);
2768
2769 /* Sanity */
2770 if((NULL == hostCtxt) || (NULL == channelEntry))
2771 {
2772 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2773 "dxeTXCompFrame Invalid ARG");
2774 return eWLAN_PAL_STATUS_E_INVAL;
2775 }
2776
2777 if(NULL == hostCtxt->txCompCB)
2778 {
2779 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2780 "dxeTXCompFrame TXCompCB is not registered");
Jeff Johnsone7245742012-09-05 17:12:55 -07002781 return eWLAN_PAL_STATUS_SUCCESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07002782 }
2783
2784 wpalMutexAcquire(&channelEntry->dxeChannelLock);
2785
2786 currentCtrlBlk = channelEntry->tailCtrlBlk;
2787 currentDesc = currentCtrlBlk->linkedDesc;
2788
2789 if( currentCtrlBlk == channelEntry->headCtrlBlk )
2790 {
2791 wpalMutexRelease(&channelEntry->dxeChannelLock);
Jeff Johnsone7245742012-09-05 17:12:55 -07002792 return eWLAN_PAL_STATUS_SUCCESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07002793 }
2794
2795 /* */
2796 while(1)
2797 {
2798// HDXE_ASSERT(WLAN_PAL_IS_STATUS_SUCCESS(WLAN_RivaValidateDesc(currentDesc)));
2799 descCtrlValue = currentDesc->descCtrl.ctrl;
2800 if((descCtrlValue & WLANDXE_DESC_CTRL_VALID))
2801 {
2802 /* caught up with head, bail out */
2803 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_MED,
2804 "dxeTXCompFrame caught up with head - next DESC has VALID set");
2805 break;
2806 }
2807
2808 HDXE_ASSERT(currentCtrlBlk->xfrFrame != NULL);
2809 channelEntry->numFreeDesc++;
2810 channelEntry->numRsvdDesc--;
2811
2812 /* Send Frame TX Complete notification with frame start fragment location */
2813 if(WLANDXE_U32_SWAP_ENDIAN(descCtrlValue) & WLANDXE_DESC_CTRL_EOP)
2814 {
2815 hostCtxt->txCompletedFrames--;
2816#ifdef FEATURE_R33D
2817 wpalFreeTxFrame(currentCtrlBlk->shadowBufferVa);
2818#else
2819 status = wpalUnlockPacket(currentCtrlBlk->xfrFrame);
2820 if (eWLAN_PAL_STATUS_SUCCESS != status)
2821 {
2822 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2823 "dxeRXFrameReady unable to unlock packet");
2824 wpalMutexRelease(&channelEntry->dxeChannelLock);
2825 return status;
2826 }
2827#endif /* FEATURE_R33D */
2828 hostCtxt->txCompCB(hostCtxt->clientCtxt,
2829 currentCtrlBlk->xfrFrame,
2830 eWLAN_PAL_STATUS_SUCCESS);
2831 channelEntry->numFragmentCurrentChain = 0;
2832 }
2833 currentCtrlBlk = currentCtrlBlk->nextCtrlBlk;
2834 currentDesc = currentCtrlBlk->linkedDesc;
2835
2836 /* Break condition
2837 * Head control block is the control block must be programed for the next TX
2838 * so, head control block is not programmed control block yet
2839 * if loop encounte head control block, stop to complete
2840 * in theory, COMP CB must be called already ??? */
2841 if(currentCtrlBlk == channelEntry->headCtrlBlk)
2842 {
2843 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_MED,
2844 "dxeTXCompFrame caught up with head ptr");
2845 break;
2846 }
2847 /* VALID Bit check ???? */
2848 }
2849
2850 /* Tail and Head Control block must be same */
2851 channelEntry->tailCtrlBlk = currentCtrlBlk;
2852
2853 lowThreshold = channelEntry->channelType == WDTS_CHANNEL_TX_LOW_PRI?
2854 &(hostCtxt->txCompInt.txLowResourceThreshold_LoPriCh):
2855 &(hostCtxt->txCompInt.txLowResourceThreshold_HiPriCh);
2856
2857 /* If specific channel hit low resource condition send notification to upper layer */
2858 if((eWLAN_PAL_TRUE == channelEntry->hitLowResource) &&
2859 (channelEntry->numFreeDesc > *lowThreshold))
2860 {
2861 /* Change it back if we raised it for fetching a remaining packet from TL */
2862 if(WLANDXE_TX_LOW_RES_THRESHOLD > *lowThreshold)
2863 {
2864 *lowThreshold = WLANDXE_TX_LOW_RES_THRESHOLD;
2865 }
2866
2867 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN,
2868 "DXE TX %d channel recovered from low resource", channelEntry->channelType);
2869 hostCtxt->lowResourceCB(hostCtxt->clientCtxt,
2870 channelEntry->channelType,
2871 eWLAN_PAL_TRUE);
2872 channelEntry->hitLowResource = eWLAN_PAL_FALSE;
2873 }
2874
2875 wpalMutexRelease(&channelEntry->dxeChannelLock);
2876
2877 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
2878 "%s Exit", __FUNCTION__);
2879 return status;
2880}
2881
2882/*==========================================================================
2883 @ Function Name
2884 dxeTXEventHandler
2885
2886 @ Description
2887 If DXE HW sends TX related interrupt, this event handler will be called
2888 Handle higher priority channel first
2889 Figureout why interrupt happen and call appropriate final even handler
2890 TX complete or error happen
2891
2892 @ Parameters
2893 void *msgPtr
2894 Even MSG
2895
2896 @ Return
2897 PAL_STATUS_T
2898===========================================================================*/
2899void dxeTXEventHandler
2900(
2901 wpt_msg *msgPtr
2902)
2903{
2904 wpt_msg *msgContent = (wpt_msg *)msgPtr;
2905 WLANDXE_CtrlBlkType *dxeCtxt = NULL;
2906 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
2907 wpt_uint32 intSrc = 0;
2908 wpt_uint32 chStat = 0;
2909 WLANDXE_ChannelCBType *channelCb = NULL;
2910
2911 wpt_uint8 bEnableISR = 0;
2912
2913 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
2914 "%s Enter", __FUNCTION__);
2915
2916 dxeCtxt = (WLANDXE_CtrlBlkType *)(msgContent->pContext);
Jeff Johnsone7245742012-09-05 17:12:55 -07002917 dxeCtxt->ucTxMsgCnt = 0;
2918
2919 if(eWLAN_PAL_TRUE == dxeCtxt->driverReloadInProcessing)
2920 {
2921 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2922 "wlan: TX COMP WLAN Driver re-loading in progress");
2923 return;
2924 }
2925
Jeff Johnson295189b2012-06-20 16:38:30 -07002926 /* Return from here if the RIVA is in IMPS, to avoid register access */
2927 if(WLANDXE_POWER_STATE_IMPS == dxeCtxt->hostPowerState)
2928 {
Jeff Johnsone7245742012-09-05 17:12:55 -07002929 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2930 "dxeTXEventHandler TX COMP INT");
2931 status = dxeTXCompFrame(dxeCtxt, &dxeCtxt->dxeChannel[WDTS_CHANNEL_TX_HIGH_PRI]);
2932 if(eWLAN_PAL_STATUS_SUCCESS != status)
2933 {
2934 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2935 "dxeTXEventHandler IMPS COMP interrupt fail");
2936 }
2937 if((dxeCtxt->txCompletedFrames) &&
2938 (eWLAN_PAL_FALSE == dxeCtxt->txIntEnable))
2939 {
2940 dxeCtxt->txIntEnable = eWLAN_PAL_TRUE;
2941 wpalEnableInterrupt(DXE_INTERRUPT_TX_COMPLE);
2942 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN,
2943 "TX COMP INT Enabled, remain TX frame count on ring %d",
2944 dxeCtxt->txCompletedFrames);
2945 /*Kicking the DXE after the TX Complete interrupt was enabled - to avoid
2946 the posibility of a race*/
2947 dxePsComplete(dxeCtxt, eWLAN_PAL_TRUE);
2948 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002949 return;
2950 }
2951
2952 if((!dxeCtxt->dxeChannel[WDTS_CHANNEL_TX_HIGH_PRI].extraConfig.chEnabled) ||
2953 (!dxeCtxt->dxeChannel[WDTS_CHANNEL_TX_LOW_PRI].extraConfig.chEnabled))
2954 {
2955 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2956 "DXE already stopped in TX event handler. Just return");
2957 return;
2958 }
2959
Jeff Johnson295189b2012-06-20 16:38:30 -07002960 /* Disable device interrupt */
2961 /* Read whole interrupt mask register and exclusive only this channel int */
2962 status = wpalReadRegister(WLANDXE_INT_SRC_RAW_ADDRESS,
2963 &intSrc);
2964 if(eWLAN_PAL_STATUS_SUCCESS != status)
2965 {
2966 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2967 "dxeTXCompleteEventHandler Read INT_DONE_SRC register fail");
2968 return;
2969 }
2970 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_MED,
2971 "TX Event Handler INT Source 0x%x", intSrc);
2972
2973 /* Test High Priority Channel is the INT source or not */
2974 channelCb = &dxeCtxt->dxeChannel[WDTS_CHANNEL_TX_HIGH_PRI];
2975 if(intSrc & (1 << channelCb->assignedDMAChannel))
2976 {
2977 status = dxeChannelCleanInt(channelCb, &chStat);
2978 if(eWLAN_PAL_STATUS_SUCCESS != status)
2979 {
2980 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
2981 "dxeTXEventHandler INT Clean up fail");
2982 return;
2983 }
2984
2985 if(WLANDXE_CH_STAT_INT_ERR_MASK & chStat)
2986 {
2987 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
2988 "dxeTXEventHandler TX HI status=%x", chStat);
2989 HDXE_ASSERT(0);
2990 }
2991 else if(WLANDXE_CH_STAT_INT_DONE_MASK & chStat)
2992 {
2993 /* Handle TX complete for high priority channel */
2994 status = dxeTXCompFrame(dxeCtxt,
2995 channelCb);
Jeff Johnsone7245742012-09-05 17:12:55 -07002996 bEnableISR = 1;
Jeff Johnson295189b2012-06-20 16:38:30 -07002997 }
2998 else if(WLANDXE_CH_STAT_INT_ED_MASK & chStat)
2999 {
3000 /* Handle TX complete for high priority channel */
3001 status = dxeTXCompFrame(dxeCtxt,
3002 channelCb);
Jeff Johnsone7245742012-09-05 17:12:55 -07003003 bEnableISR = 1;
Jeff Johnson295189b2012-06-20 16:38:30 -07003004 }
3005 else
3006 {
3007 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3008 "dxeTXEventHandler TX HI status=%x", chStat);
3009 }
3010
3011 if(WLANDXE_CH_STAT_MASKED_MASK & chStat)
3012 {
3013 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_HIGH,
3014 "dxeTXEventHandler TX HIGH Channel Masked Unmask it!!!!");
3015 }
3016
3017 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_HIGH,
3018 "TX HIGH STAT 0x%x RESRVD %d", chStat, channelCb->numRsvdDesc);
3019 }
3020
3021 /* Test Low Priority Channel interrupt is enabled or not */
3022 channelCb = &dxeCtxt->dxeChannel[WDTS_CHANNEL_TX_LOW_PRI];
3023 if(intSrc & (1 << channelCb->assignedDMAChannel))
3024 {
3025 status = dxeChannelCleanInt(channelCb, &chStat);
3026 if(eWLAN_PAL_STATUS_SUCCESS != status)
3027 {
3028 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3029 "dxeTXEventHandler INT Clean up fail");
3030 return;
3031 }
3032
3033 if(WLANDXE_CH_STAT_INT_ERR_MASK & chStat)
3034 {
3035 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
3036 "dxeTXEventHandler TX LO status=%x", chStat);
3037 HDXE_ASSERT(0);
3038 }
3039 else if(WLANDXE_CH_STAT_INT_DONE_MASK & chStat)
3040 {
3041 /* Handle TX complete for low priority channel */
3042 status = dxeTXCompFrame(dxeCtxt,
3043 channelCb);
Jeff Johnsone7245742012-09-05 17:12:55 -07003044 bEnableISR = 1;
Jeff Johnson295189b2012-06-20 16:38:30 -07003045 }
3046 else if(WLANDXE_CH_STAT_INT_ED_MASK & chStat)
3047 {
3048 /* Handle TX complete for low priority channel */
3049 status = dxeTXCompFrame(dxeCtxt,
3050 channelCb);
Jeff Johnsone7245742012-09-05 17:12:55 -07003051 bEnableISR = 1;
Jeff Johnson295189b2012-06-20 16:38:30 -07003052 }
3053 else
3054 {
3055 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3056 "dxeTXEventHandler TX LO status=%x", chStat);
3057 }
3058
3059 if(WLANDXE_CH_STAT_MASKED_MASK & chStat)
3060 {
3061 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_HIGH,
3062 "dxeTXEventHandler TX Low Channel Masked Unmask it!!!!");
3063 }
3064 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO,
3065 "TX LOW STAT 0x%x RESRVD %d", chStat, channelCb->numRsvdDesc);
3066 }
3067
3068
3069#ifdef WLANDXE_TEST_CHANNEL_ENABLE
3070 /* Test H2H TX Channel interrupt is enabled or not */
3071 channelCb = &dxeCtxt->dxeChannel[WDTS_CHANNEL_H2H_TEST_TX];
3072 if(intSrc & (1 << channelCb->assignedDMAChannel))
3073 {
3074 status = wpalReadRegister(channelCb->channelRegister.chDXEStatusRegAddr,
3075 &chStat);
3076 if(eWLAN_PAL_STATUS_SUCCESS != status)
3077 {
3078 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3079 "dxeChannelCleanInt Read CH STAT register fail");
3080 return;
3081 }
3082
3083 if(WLANDXE_CH_STAT_INT_ERR_MASK & chStat)
3084 {
3085 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
3086 "WLANDXE_CH_STAT_INT_ERR_MASK occurred");
3087 HDXE_ASSERT(0);
3088 }
3089 else if(WLANDXE_CH_STAT_INT_DONE_MASK & chStat)
3090 {
3091 /* Handle TX complete for high priority channel */
3092 status = dxeTXCompFrame(dxeCtxt,
3093 channelCb);
3094 if(eWLAN_PAL_STATUS_SUCCESS != status)
3095 {
3096 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3097 "dxeTXEventHandler INT Clean up fail");
3098 return;
3099 }
3100 }
3101 else
3102 {
3103 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3104 "unexpected channel state %d", chStat);
3105 }
3106 }
3107#endif /* WLANDXE_TEST_CHANNEL_ENABLE */
3108
3109 if((bEnableISR || (dxeCtxt->txCompletedFrames)) &&
3110 (eWLAN_PAL_FALSE == dxeCtxt->txIntEnable))
3111 {
3112 dxeCtxt->txIntEnable = eWLAN_PAL_TRUE;
3113 wpalEnableInterrupt(DXE_INTERRUPT_TX_COMPLE);
3114 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN,
3115 "TX COMP INT Enabled, remain TX frame count on ring %d",
3116 dxeCtxt->txCompletedFrames);
3117 }
3118
3119 /*Kicking the DXE after the TX Complete interrupt was enabled - to avoid
3120 the posibility of a race*/
3121 dxePsComplete(dxeCtxt, eWLAN_PAL_TRUE);
3122
3123 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
3124 "%s Exit", __FUNCTION__);
3125 return;
3126}
3127
3128
3129/*==========================================================================
3130 @ Function Name
3131 dxeTXCompleteProcessing
3132
3133 @ Description
3134 If DXE HW sends TX related interrupt, this event handler will be called
3135 Handle higher priority channel first
3136 Figureout why interrupt happen and call appropriate final even handler
3137 TX complete or error happen
3138
3139 @ Parameters
3140 dxeCtxt DXE context
3141
3142 @ Return
3143 PAL_STATUS_T
3144===========================================================================*/
3145void dxeTXCompleteProcessing
3146(
3147 WLANDXE_CtrlBlkType *dxeCtxt
3148)
3149{
3150 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
3151 WLANDXE_ChannelCBType *channelCb = NULL;
3152
3153 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
3154 "%s Enter", __FUNCTION__);
3155
3156 /* Test High Priority Channel is the INT source or not */
3157 channelCb = &dxeCtxt->dxeChannel[WDTS_CHANNEL_TX_HIGH_PRI];
3158
3159 /* Handle TX complete for high priority channel */
3160 status = dxeTXCompFrame(dxeCtxt, channelCb);
3161
3162 /* Test Low Priority Channel interrupt is enabled or not */
3163 channelCb = &dxeCtxt->dxeChannel[WDTS_CHANNEL_TX_LOW_PRI];
3164
3165 /* Handle TX complete for low priority channel */
3166 status = dxeTXCompFrame(dxeCtxt, channelCb);
3167
3168 if((eWLAN_PAL_FALSE == dxeCtxt->txIntEnable) &&
3169 ((dxeCtxt->txCompletedFrames > 0) ||
3170 (WLANDXE_POWER_STATE_FULL == dxeCtxt->hostPowerState)))
3171 {
3172 dxeCtxt->txIntEnable = eWLAN_PAL_TRUE;
3173 wpalEnableInterrupt(DXE_INTERRUPT_TX_COMPLE);
3174 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN,
3175 "%s %s : %d, %s : %d", __FUNCTION__,
3176 channelType[dxeCtxt->dxeChannel[WDTS_CHANNEL_TX_HIGH_PRI].channelType],
3177 dxeCtxt->dxeChannel[WDTS_CHANNEL_TX_HIGH_PRI].numRsvdDesc,
3178 channelType[dxeCtxt->dxeChannel[WDTS_CHANNEL_TX_LOW_PRI].channelType],
3179 dxeCtxt->dxeChannel[WDTS_CHANNEL_TX_LOW_PRI].numRsvdDesc);
3180 }
3181
3182 /*Kicking the DXE after the TX Complete interrupt was enabled - to avoid
3183 the posibility of a race*/
3184 dxePsComplete(dxeCtxt, eWLAN_PAL_FALSE);
3185
3186 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
3187 "%s Exit", __FUNCTION__);
3188 return;
3189}
3190/*==========================================================================
3191 @ Function Name
3192 dxeTXISR
3193
3194 @ Description
3195 TX interrupt ISR
3196 Platform will call this function if INT is happen
3197 This function must be registered into platform interrupt module
3198
3199 @ Parameters
3200 void *hostCtxt
3201 DXE host driver control context,
3202 pre registerd during interrupt registration
3203
3204 @ Return
3205 PAL_STATUS_T
3206===========================================================================*/
3207static void dxeTXISR
3208(
3209 void *hostCtxt
3210)
3211{
3212 WLANDXE_CtrlBlkType *dxeCtxt = (WLANDXE_CtrlBlkType *)hostCtxt;
3213 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
3214#ifdef FEATURE_R33D
3215 wpt_uint32 regValue;
3216#endif /* FEATURE_R33D */
3217
3218 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
3219 "%s Enter", __FUNCTION__);
3220
3221 /* Return from here if the RIVA is in IMPS, to avoid register access */
Jeff Johnsone7245742012-09-05 17:12:55 -07003222 if(WLANDXE_POWER_STATE_DOWN == dxeCtxt->hostPowerState)
Jeff Johnson295189b2012-06-20 16:38:30 -07003223 {
Jeff Johnsone7245742012-09-05 17:12:55 -07003224 dxeCtxt->txIntEnable = eWLAN_PAL_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003225 /* Disable interrupt at here,
3226 IMPS or IMPS Pending state should not access RIVA register */
3227 status = wpalDisableInterrupt(DXE_INTERRUPT_TX_COMPLE);
3228 if(eWLAN_PAL_STATUS_SUCCESS != status)
3229 {
3230 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3231 "dxeRXFrameReadyISR Disable RX ready interrupt fail");
3232 return;
3233 }
3234 dxeCtxt->txIntDisabledByIMPS = eWLAN_PAL_TRUE;
3235 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
3236 "%s Riva is in %d, return from here ", __FUNCTION__, dxeCtxt->hostPowerState);
3237 return;
3238 }
3239
3240#ifdef FEATURE_R33D
3241 status = wpalReadRegister(WLANDXE_INT_SRC_RAW_ADDRESS,
3242 &regValue);
3243 if(eWLAN_PAL_STATUS_SUCCESS != status)
3244 {
3245 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3246 "dxeTXCompISR Read INT_SRC_RAW fail");
3247 return;
3248 }
3249 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
3250 "INT_SRC_RAW 0x%x", regValue);
3251 if(0 == regValue)
3252 {
3253 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN,
3254 "This is not DXE Interrupt, Reject it");
3255 return;
3256 }
3257#endif /* FEATURE_R33D */
3258
3259 /* Disable TX Complete Interrupt at here */
3260 status = wpalDisableInterrupt(DXE_INTERRUPT_TX_COMPLE);
3261 if(eWLAN_PAL_STATUS_SUCCESS != status)
3262 {
3263 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3264 "dxeTXCompISR Disable TX complete interrupt fail");
3265 return;
3266 }
3267 dxeCtxt->txIntEnable = eWLAN_PAL_FALSE;
3268
3269
3270 if( dxeCtxt->ucTxMsgCnt )
3271 {
3272 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO,
3273 "Avoiding serializing TX Complete event");
3274 return;
3275 }
3276
3277 dxeCtxt->ucTxMsgCnt = 1;
3278
3279 /* Serialize TX complete interrupt upon TX thread */
3280 HDXE_ASSERT(NULL != dxeCtxt->txIsrMsg);
3281 status = wpalPostTxMsg(WDI_GET_PAL_CTX(),
3282 dxeCtxt->txIsrMsg);
3283 if(eWLAN_PAL_STATUS_SUCCESS != status)
3284 {
3285 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL,
3286 "dxeTXCompISR interrupt serialize fail status=%d", status);
3287 }
3288
3289 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
3290 "%s Exit", __FUNCTION__);
3291 return;
3292}
3293
3294/*-------------------------------------------------------------------------
3295 * Global Function
3296 *-------------------------------------------------------------------------*/
3297/*==========================================================================
3298 @ Function Name
3299 WLANDXE_Open
3300
3301 @ Description
3302 Open host DXE driver, allocate DXE resources
3303 Allocate, DXE local control block, DXE descriptor pool, DXE descriptor control block pool
3304
3305 @ Parameters
3306 pVoid pAdaptor : Driver global control block pointer
3307
3308 @ Return
3309 pVoid DXE local module control block pointer
3310===========================================================================*/
3311void *WLANDXE_Open
3312(
3313 void
3314)
3315{
3316 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
3317 unsigned int idx;
3318 WLANDXE_ChannelCBType *currentChannel = NULL;
3319 int smsmInitState;
3320#ifdef WLANDXE_TEST_CHANNEL_ENABLE
3321 wpt_uint32 sIdx;
3322 WLANDXE_ChannelCBType *channel = NULL;
3323 WLANDXE_DescCtrlBlkType *crntDescCB = NULL;
3324 WLANDXE_DescCtrlBlkType *nextDescCB = NULL;
3325#endif /* WLANDXE_TEST_CHANNEL_ENABLE */
3326
3327 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
3328 "%s Enter", __FUNCTION__);
3329
3330 /* This is temporary allocation */
3331 tempDxeCtrlBlk = (WLANDXE_CtrlBlkType *)wpalMemoryAllocate(sizeof(WLANDXE_CtrlBlkType));
3332 if(NULL == tempDxeCtrlBlk)
3333 {
3334 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3335 "WLANDXE_Open Control Block Alloc Fail");
3336 return NULL;
3337 }
3338 wpalMemoryZero(tempDxeCtrlBlk, sizeof(WLANDXE_CtrlBlkType));
3339
3340 status = dxeCommonDefaultConfig(tempDxeCtrlBlk);
3341 if(eWLAN_PAL_STATUS_SUCCESS != status)
3342 {
3343 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3344 "WLANDXE_Open Common Configuration Fail");
3345 WLANDXE_Close(tempDxeCtrlBlk);
3346 return NULL;
3347 }
3348
3349 for(idx = 0; idx < WDTS_CHANNEL_MAX; idx++)
3350 {
3351 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN,
3352 "WLANDXE_Open Channel %s Open Start", channelType[idx]);
3353 currentChannel = &tempDxeCtrlBlk->dxeChannel[idx];
3354 if(idx == WDTS_CHANNEL_TX_LOW_PRI)
3355 {
3356 currentChannel->channelType = WDTS_CHANNEL_TX_LOW_PRI;
3357 }
3358 else if(idx == WDTS_CHANNEL_TX_HIGH_PRI)
3359 {
3360 currentChannel->channelType = WDTS_CHANNEL_TX_HIGH_PRI;
3361 }
3362 else if(idx == WDTS_CHANNEL_RX_LOW_PRI)
3363 {
3364 currentChannel->channelType = WDTS_CHANNEL_RX_LOW_PRI;
3365 }
3366 else if(idx == WDTS_CHANNEL_RX_HIGH_PRI)
3367 {
3368 currentChannel->channelType = WDTS_CHANNEL_RX_HIGH_PRI;
3369 }
3370#ifdef WLANDXE_TEST_CHANNEL_ENABLE
3371 else if(idx == WDTS_CHANNEL_H2H_TEST_TX)
3372 {
3373 currentChannel->channelType = WDTS_CHANNEL_H2H_TEST_TX;
3374 }
3375 else if(idx == WDTS_CHANNEL_H2H_TEST_RX)
3376 {
3377 currentChannel->channelType = WDTS_CHANNEL_H2H_TEST_RX;
3378 }
3379#endif /* WLANDXE_TEST_CHANNEL_ENABLE */
3380
3381 /* Config individual channels from channel default setup table */
3382 status = dxeChannelDefaultConfig(tempDxeCtrlBlk,
3383 currentChannel);
3384 if(eWLAN_PAL_STATUS_SUCCESS != status)
3385 {
3386 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3387 "WLANDXE_Open Channel Basic Configuration Fail for channel %d", idx);
3388 WLANDXE_Close(tempDxeCtrlBlk);
3389 return NULL;
3390 }
3391
3392 /* Allocate DXE Control Block will be used by host DXE driver */
3393 status = dxeCtrlBlkAlloc(tempDxeCtrlBlk, currentChannel);
3394 if(eWLAN_PAL_STATUS_SUCCESS != status)
3395 {
3396 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3397 "WLANDXE_Open Alloc DXE Control Block Fail for channel %d", idx);
3398
3399 WLANDXE_Close(tempDxeCtrlBlk);
3400 return NULL;
3401 }
3402 status = wpalMutexInit(&currentChannel->dxeChannelLock);
3403 if(eWLAN_PAL_STATUS_SUCCESS != status)
3404 {
3405 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN,
3406 "WLANDXE_Open Lock Init Fail for channel %d", idx);
3407 WLANDXE_Close(tempDxeCtrlBlk);
3408 return NULL;
3409 }
3410
3411 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN,
3412 "WLANDXE_Open Channel %s Open Success", channelType[idx]);
3413 }
3414
3415 /* Allocate and Init RX READY ISR Serialize Buffer */
3416 tempDxeCtrlBlk->rxIsrMsg = (wpt_msg *)wpalMemoryAllocate(sizeof(wpt_msg));
3417 if(NULL == tempDxeCtrlBlk->rxIsrMsg)
3418 {
3419 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3420 "WLANDXE_Open Alloc RX ISR Fail");
3421 WLANDXE_Close(tempDxeCtrlBlk);
3422 return NULL;
3423 }
3424 wpalMemoryZero(tempDxeCtrlBlk->rxIsrMsg, sizeof(wpt_msg));
3425 tempDxeCtrlBlk->rxIsrMsg->callback = dxeRXEventHandler;
3426 tempDxeCtrlBlk->rxIsrMsg->pContext = (void *)tempDxeCtrlBlk;
3427
3428 /* Allocate and Init TX COMP ISR Serialize Buffer */
3429 tempDxeCtrlBlk->txIsrMsg = (wpt_msg *)wpalMemoryAllocate(sizeof(wpt_msg));
3430 if(NULL == tempDxeCtrlBlk->txIsrMsg)
3431 {
3432 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3433 "WLANDXE_Open Alloc TX ISR Fail");
3434 WLANDXE_Close(tempDxeCtrlBlk);
3435 return NULL;
3436 }
3437 wpalMemoryZero(tempDxeCtrlBlk->txIsrMsg, sizeof(wpt_msg));
3438 tempDxeCtrlBlk->txIsrMsg->callback = dxeTXEventHandler;
3439 tempDxeCtrlBlk->txIsrMsg->pContext = (void *)tempDxeCtrlBlk;
3440
3441 /* Allocate and Init RX Packet Available Serialize Message Buffer */
3442 tempDxeCtrlBlk->rxPktAvailMsg = (wpt_msg *)wpalMemoryAllocate(sizeof(wpt_msg));
3443 if(NULL == tempDxeCtrlBlk->rxPktAvailMsg)
3444 {
3445 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3446 "WLANDXE_Open Alloc RX Packet Available Message Fail");
3447 WLANDXE_Close(tempDxeCtrlBlk);
3448 return NULL;
3449 }
3450 wpalMemoryZero(tempDxeCtrlBlk->rxPktAvailMsg, sizeof(wpt_msg));
3451 tempDxeCtrlBlk->rxPktAvailMsg->callback = dxeRXPacketAvailableEventHandler;
3452 tempDxeCtrlBlk->rxPktAvailMsg->pContext = (void *)tempDxeCtrlBlk;
3453
3454 tempDxeCtrlBlk->freeRXPacket = NULL;
3455 tempDxeCtrlBlk->dxeCookie = WLANDXE_CTXT_COOKIE;
3456 tempDxeCtrlBlk->rxIntDisabledByIMPS = eWLAN_PAL_FALSE;
3457 tempDxeCtrlBlk->txIntDisabledByIMPS = eWLAN_PAL_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07003458 tempDxeCtrlBlk->driverReloadInProcessing = eWLAN_PAL_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003459
3460 /* Initialize SMSM state
3461 * Init State is
3462 * Clear TX Enable
3463 * RING EMPTY STATE */
3464 smsmInitState = wpalNotifySmsm(WPAL_SMSM_WLAN_TX_ENABLE,
3465 WPAL_SMSM_WLAN_TX_RINGS_EMPTY);
3466 if(0 != smsmInitState)
3467 {
3468 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3469 "SMSM Channel init fail %d", smsmInitState);
3470 for(idx = 0; idx < WDTS_CHANNEL_MAX; idx++)
3471 {
3472 dxeChannelClose(tempDxeCtrlBlk, &tempDxeCtrlBlk->dxeChannel[idx]);
3473 }
3474 wpalMemoryFree((void *)&tempDxeCtrlBlk->rxIsrMsg);
3475 wpalMemoryFree((void *)&tempDxeCtrlBlk->txIsrMsg);
3476 wpalMemoryFree(tempDxeCtrlBlk);
3477 return NULL;
3478 }
3479
3480 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN,
3481 "WLANDXE_Open Success");
3482 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
3483 "%s Exit", __FUNCTION__);
3484 return (void *)tempDxeCtrlBlk;
3485}
3486
3487/*==========================================================================
3488 @ Function Name
3489 WLANDXE_ClientRegistration
3490
3491 @ Description
3492 Make callback functions registration into DXE driver from DXE driver client
3493
3494 @ Parameters
3495 pVoid pDXEContext : DXE module control block
3496 WDTS_RxFrameReadyCbType rxFrameReadyCB : RX Frame ready CB function pointer
3497 WDTS_TxCompleteCbType txCompleteCB : TX complete CB function pointer
3498 WDTS_LowResourceCbType lowResourceCB : Low DXE resource notification CB function pointer
3499 void *userContext : DXE Cliennt control block
3500
3501 @ Return
3502 wpt_status
3503===========================================================================*/
3504wpt_status WLANDXE_ClientRegistration
3505(
3506 void *pDXEContext,
3507 WLANDXE_RxFrameReadyCbType rxFrameReadyCB,
3508 WLANDXE_TxCompleteCbType txCompleteCB,
3509 WLANDXE_LowResourceCbType lowResourceCB,
3510 void *userContext
3511)
3512{
3513 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
3514 WLANDXE_CtrlBlkType *dxeCtxt;
3515
3516 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
3517 "%s Enter", __FUNCTION__);
3518
3519 /* Sanity */
3520 if(NULL == pDXEContext)
3521 {
3522 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3523 "WLANDXE_ClientRegistration Invalid DXE CB");
3524 return eWLAN_PAL_STATUS_E_INVAL;
3525 }
3526
3527 if(NULL == rxFrameReadyCB)
3528 {
3529 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3530 "WLANDXE_ClientRegistration Invalid RX READY CB");
3531 return eWLAN_PAL_STATUS_E_INVAL;
3532 }
3533
3534 if(NULL == txCompleteCB)
3535 {
3536 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3537 "WLANDXE_ClientRegistration Invalid txCompleteCB");
3538 return eWLAN_PAL_STATUS_E_INVAL;
3539 }
3540
3541 if(NULL == lowResourceCB)
3542 {
3543 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3544 "WLANDXE_ClientRegistration Invalid lowResourceCB");
3545 return eWLAN_PAL_STATUS_E_INVAL;
3546 }
3547
3548 if(NULL == userContext)
3549 {
3550 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3551 "WLANDXE_ClientRegistration Invalid userContext");
3552 return eWLAN_PAL_STATUS_E_INVAL;
3553 }
3554
3555 dxeCtxt = (WLANDXE_CtrlBlkType *)pDXEContext;
3556
3557 /* Assign */
3558 dxeCtxt->rxReadyCB = rxFrameReadyCB;
3559 dxeCtxt->txCompCB = txCompleteCB;
3560 dxeCtxt->lowResourceCB = lowResourceCB;
3561 dxeCtxt->clientCtxt = userContext;
3562
3563 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
3564 "%s Exit", __FUNCTION__);
3565 return status;
3566}
3567
3568/*==========================================================================
3569 @ Function Name
3570 WLANDXE_Start
3571
3572 @ Description
3573 Start Host DXE driver
3574 Initialize DXE channels and start channel
3575
3576 @ Parameters
3577 pVoid pDXEContext : DXE module control block
3578
3579 @ Return
3580 wpt_status
3581===========================================================================*/
3582wpt_status WLANDXE_Start
3583(
3584 void *pDXEContext
3585)
3586{
3587 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
3588 wpt_uint32 idx;
3589 WLANDXE_CtrlBlkType *dxeCtxt = NULL;
3590
3591 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
3592 "%s Enter", __FUNCTION__);
3593
3594 /* Sanity */
3595 if(NULL == pDXEContext)
3596 {
3597 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3598 "WLANDXE_Start Invalid DXE CB");
3599 return eWLAN_PAL_STATUS_E_INVAL;
3600 }
3601 dxeCtxt = (WLANDXE_CtrlBlkType *)pDXEContext;
3602
3603 /* WLANDXE_Start called means DXE engine already initiates
3604 * And DXE HW is reset and init finished
3605 * But here to make sure HW is initialized, reset again */
3606 status = dxeEngineCoreStart(dxeCtxt);
3607 if(eWLAN_PAL_STATUS_SUCCESS != status)
3608 {
3609 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3610 "WLANDXE_Start DXE HW init Fail");
3611 return status;
3612 }
3613
3614 /* Individual Channel Start */
3615 for(idx = 0; idx < WDTS_CHANNEL_MAX; idx++)
3616 {
3617 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN,
3618 "WLANDXE_Start Channel %s Start", channelType[idx]);
3619
3620 /* Allocate DXE descriptor will be shared by Host driver and DXE engine */
3621 /* Make connection between DXE descriptor and DXE control block */
3622 status = dxeDescAllocAndLink(tempDxeCtrlBlk, &dxeCtxt->dxeChannel[idx]);
3623 if(eWLAN_PAL_STATUS_SUCCESS != status)
3624 {
3625 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3626 "WLANDXE_Start Alloc DXE Descriptor Fail for channel %d", idx);
3627 return status;
3628 }
3629
3630 /* Program each channel register with configuration arguments */
3631 status = dxeChannelInitProgram(dxeCtxt,
3632 &dxeCtxt->dxeChannel[idx]);
3633 if(eWLAN_PAL_STATUS_SUCCESS != status)
3634 {
3635 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3636 "WLANDXE_Start %d Program DMA channel Fail", idx);
3637 return status;
3638 }
3639
3640 /* ??? Trigger to start DMA channel
3641 * This must be seperated from ??? */
3642 status = dxeChannelStart(dxeCtxt,
3643 &dxeCtxt->dxeChannel[idx]);
3644 if(eWLAN_PAL_STATUS_SUCCESS != status)
3645 {
3646 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3647 "WLANDXE_Start %d Channel Start Fail", idx);
3648 return status;
3649 }
3650 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN,
3651 "WLANDXE_Start Channel %s Start Success", channelType[idx]);
3652 }
3653
3654 /* Register ISR to OS */
3655 /* Register TX complete interrupt into platform */
3656 status = wpalRegisterInterrupt(DXE_INTERRUPT_TX_COMPLE,
3657 dxeTXISR,
3658 dxeCtxt);
3659 if(eWLAN_PAL_STATUS_SUCCESS != status)
3660 {
3661 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3662 "WLANDXE_Start TX comp interrupt registration Fail");
3663 return status;
3664 }
3665
3666 /* Register RX ready interrupt into platform */
3667 status = wpalRegisterInterrupt(DXE_INTERRUPT_RX_READY,
3668 dxeRXISR,
3669 dxeCtxt);
3670 if(eWLAN_PAL_STATUS_SUCCESS != status)
3671 {
3672 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3673 "WLANDXE_Start RX Ready interrupt registration Fail");
3674 return status;
3675 }
3676
3677 /* Enable system level ISR */
3678 /* Enable RX ready Interrupt at here */
3679 status = wpalEnableInterrupt(DXE_INTERRUPT_RX_READY);
3680 if(eWLAN_PAL_STATUS_SUCCESS != status)
3681 {
3682 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3683 "dxeTXCompleteEventHandler Enable TX complete interrupt fail");
3684 return status;
3685 }
3686
3687 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
3688 "%s Exit", __FUNCTION__);
3689 return status;
3690}
3691
3692/*==========================================================================
3693 @ Function Name
3694 WLANDXE_TXFrame
3695
3696 @ Description
3697 Trigger frame transmit from host to RIVA
3698
3699 @ Parameters
3700 pVoid pDXEContext : DXE Control Block
3701 wpt_packet pPacket : transmit packet structure
3702 WDTS_ChannelType channel : TX channel
3703
3704 @ Return
3705 wpt_status
3706===========================================================================*/
3707wpt_status WLANDXE_TxFrame
3708(
3709 void *pDXEContext,
3710 wpt_packet *pPacket,
3711 WDTS_ChannelType channel
3712)
3713{
3714 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
3715 WLANDXE_ChannelCBType *currentChannel = NULL;
3716 WLANDXE_CtrlBlkType *dxeCtxt = NULL;
3717 unsigned int *lowThreshold = NULL;
3718
3719 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
3720 "%s Enter", __FUNCTION__);
3721
3722 /* Sanity */
3723 if(NULL == pDXEContext)
3724 {
3725 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3726 "WLANDXE_Start Invalid DXE CB");
3727 return eWLAN_PAL_STATUS_E_INVAL;
3728 }
3729
3730 if(NULL == pPacket)
3731 {
3732 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3733 "WLANDXE_Start Invalid pPacket");
3734 return eWLAN_PAL_STATUS_E_INVAL;
3735 }
3736
3737 if((WDTS_CHANNEL_MAX < channel) || (WDTS_CHANNEL_MAX == channel))
3738 {
3739 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3740 "WLANDXE_Start Invalid channel");
3741 return eWLAN_PAL_STATUS_E_INVAL;
3742 }
3743
3744 dxeCtxt = (WLANDXE_CtrlBlkType *)pDXEContext;
3745
3746 currentChannel = &dxeCtxt->dxeChannel[channel];
3747
3748
3749 wpalMutexAcquire(&currentChannel->dxeChannelLock);
3750
3751 lowThreshold = currentChannel->channelType == WDTS_CHANNEL_TX_LOW_PRI?
3752 &(dxeCtxt->txCompInt.txLowResourceThreshold_LoPriCh):
3753 &(dxeCtxt->txCompInt.txLowResourceThreshold_HiPriCh);
3754
3755 /* Decide have to activate TX complete event or not */
3756 switch(dxeCtxt->txCompInt.txIntEnable)
3757 {
3758 /* TX complete interrupt will be activated when low DXE resource */
3759 case WLANDXE_TX_COMP_INT_LR_THRESHOLD:
3760 if((currentChannel->numFreeDesc <= *lowThreshold) &&
3761 (eWLAN_PAL_FALSE == dxeCtxt->txIntEnable))
3762 {
3763 dxeCtxt->txIntEnable = eWLAN_PAL_TRUE;
3764 dxeCtxt->lowResourceCB(dxeCtxt->clientCtxt,
3765 channel,
3766 eWLAN_PAL_FALSE);
3767 }
3768 break;
3769
3770 /* TX complete interrupt will be activated n number of frames transfered */
3771 case WLANDXE_TX_COMP_INT_PER_K_FRAMES:
3772 if(channel == WDTS_CHANNEL_TX_LOW_PRI)
3773 {
3774 currentChannel->numFrameBeforeInt++;
3775 }
3776 break;
3777
3778 /* TX complete interrupt will be activated periodically */
3779 case WLANDXE_TX_COMP_INT_TIMER:
3780 break;
3781 }
3782
3783 dxeCtxt->txCompletedFrames++;
3784
3785 /* Update DXE descriptor, this is frame based
3786 * if a frame consist of N fragments, N Descriptor will be programed */
3787 status = dxeTXPushFrame(currentChannel, pPacket);
3788 if(eWLAN_PAL_STATUS_SUCCESS != status)
3789 {
3790 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3791 "WLANDXE_TxFrame TX Push Frame fail");
3792 wpalMutexRelease(&currentChannel->dxeChannelLock);
3793 return status;
3794 }
3795
3796 /* If specific channel hit low resource condition, send notification to upper layer */
3797 if(currentChannel->numFreeDesc <= *lowThreshold)
3798 {
3799 dxeCtxt->lowResourceCB(dxeCtxt->clientCtxt,
3800 channel,
3801 eWLAN_PAL_FALSE);
3802 currentChannel->hitLowResource = eWLAN_PAL_TRUE;
3803 }
3804 wpalMutexRelease(&currentChannel->dxeChannelLock);
3805
3806 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
3807 "%s Exit", __FUNCTION__);
3808 return status;
3809}
3810
3811/*==========================================================================
3812 @ Function Name
3813 WLANDXE_CompleteTX
3814
3815 @ Description
3816 Informs DXE that the current series of Tx packets is complete
3817
3818 @ Parameters
3819 pContext pDXEContext : DXE Control Block
3820 ucTxResReq TX resource number required by TL/WDI
3821
3822 @ Return
3823 wpt_status
3824===========================================================================*/
3825wpt_status
3826WLANDXE_CompleteTX
3827(
3828 void* pContext,
3829 wpt_uint32 ucTxResReq
3830)
3831{
3832 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
3833 WLANDXE_CtrlBlkType *dxeCtxt = (WLANDXE_CtrlBlkType *)(pContext);
3834 WLANDXE_ChannelCBType *channelCb = NULL;
3835 wpt_boolean inLowRes;
3836
3837 /* Sanity Check */
3838 if( NULL == pContext )
3839 {
3840 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3841 "WLANDXE_CompleteTX invalid param");
3842 return eWLAN_PAL_STATUS_E_INVAL;
3843 }
3844
3845 channelCb = &dxeCtxt->dxeChannel[WDTS_CHANNEL_TX_LOW_PRI];
3846 inLowRes = channelCb->hitLowResource;
3847
3848 if(WLANDXE_TX_LOW_RES_THRESHOLD < ucTxResReq)
3849 {
3850 /* Raise threshold temporarily if necessary */
3851 dxeCtxt->txCompInt.txLowResourceThreshold_LoPriCh = ucTxResReq;
3852
3853 if(eWLAN_PAL_FALSE == inLowRes)
3854 {
3855 /* Put the channel to low resource condition */
3856 dxeCtxt->lowResourceCB(dxeCtxt->clientCtxt,
3857 WDTS_CHANNEL_TX_LOW_PRI,
3858 eWLAN_PAL_FALSE);
3859 inLowRes = channelCb->hitLowResource = eWLAN_PAL_TRUE;
3860 }
3861 }
3862
3863 /*Try to reclaim resources*/
3864 dxeTXCompleteProcessing(dxeCtxt);
3865
3866 /* In previous WLANTL_GetFrames call, TL didn't fetch a packet
3867 because its fragment size is larger than DXE free resource. */
3868 if(0 < ucTxResReq)
3869 {
3870 /* DXE successfully claimed enough free DXE resouces for next fetch. */
3871 if(WLANDXE_GetFreeTxDataResNumber(dxeCtxt) >= ucTxResReq)
3872 {
3873 /* DXE has not been in low resource condition. DXE forces to kick off
3874 TX tranmit */
3875 if((eWLAN_PAL_FALSE == inLowRes) &&
3876 (eWLAN_PAL_FALSE == channelCb->hitLowResource))
3877 {
3878 dxeCtxt->lowResourceCB(dxeCtxt->clientCtxt,
3879 WDTS_CHANNEL_TX_LOW_PRI,
3880 eWLAN_PAL_FALSE);
3881 dxeCtxt->lowResourceCB(dxeCtxt->clientCtxt,
3882 WDTS_CHANNEL_TX_LOW_PRI,
3883 eWLAN_PAL_TRUE);
3884 channelCb->hitLowResource = eWLAN_PAL_FALSE;
3885 }
3886 }
3887 else
3888 {
3889 /* DXE doesn't have enough free DXE resources. Put the channel
3890 to low resource condition. */
3891 if(eWLAN_PAL_FALSE == channelCb->hitLowResource)
3892 {
3893 /* Put the channel to low resource condition */
3894 dxeCtxt->lowResourceCB(dxeCtxt->clientCtxt,
3895 WDTS_CHANNEL_TX_LOW_PRI,
3896 eWLAN_PAL_FALSE);
3897 channelCb->hitLowResource = eWLAN_PAL_TRUE;
3898 }
3899 }
3900 }
3901
3902 return status;
3903}
3904
3905/*==========================================================================
3906 @ Function Name
3907 WLANDXE_Stop
3908
3909 @ Description
3910 Stop DXE channels and DXE engine operations
3911 Disable all channel interrupt
3912 Stop all channel operation
3913
3914 @ Parameters
3915 pVoid pDXEContext : DXE Control Block
3916
3917 @ Return
3918 wpt_status
3919===========================================================================*/
3920wpt_status WLANDXE_Stop
3921(
3922 void *pDXEContext
3923)
3924{
3925 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
3926 wpt_uint32 idx;
3927 WLANDXE_CtrlBlkType *dxeCtxt = NULL;
3928
3929 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
3930 "%s Enter", __FUNCTION__);
3931
3932 /* Sanity */
3933 if(NULL == pDXEContext)
3934 {
3935 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3936 "WLANDXE_Stop Invalid DXE CB");
3937 return eWLAN_PAL_STATUS_E_INVAL;
3938 }
3939
3940 dxeCtxt = (WLANDXE_CtrlBlkType *)pDXEContext;
3941 for(idx = 0; idx < WDTS_CHANNEL_MAX; idx++)
3942 {
3943 status = dxeChannelStop(dxeCtxt, &dxeCtxt->dxeChannel[idx]);
3944 if(eWLAN_PAL_STATUS_SUCCESS != status)
3945 {
3946 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
3947 "WLANDXE_Stop Channel %d Stop Fail", idx);
3948 return status;
3949 }
3950 }
3951
3952 /* During Stop unregister interrupt */
3953 wpalUnRegisterInterrupt(DXE_INTERRUPT_TX_COMPLE);
3954 wpalUnRegisterInterrupt(DXE_INTERRUPT_RX_READY);
3955
3956 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
3957 "%s Exit", __FUNCTION__);
3958 return status;
3959}
3960
3961/*==========================================================================
3962 @ Function Name
3963 WLANDXE_Close
3964
3965 @ Description
3966 Close DXE channels
3967 Free DXE related resources
3968 DXE descriptor free
3969 Descriptor control block free
3970 Pre allocated RX buffer free
3971
3972 @ Parameters
3973 pVoid pDXEContext : DXE Control Block
3974
3975 @ Return
3976 wpt_status
3977===========================================================================*/
3978wpt_status WLANDXE_Close
3979(
3980 void *pDXEContext
3981)
3982{
3983 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
3984 wpt_uint32 idx;
3985 WLANDXE_CtrlBlkType *dxeCtxt = NULL;
3986#ifdef WLANDXE_TEST_CHANNEL_ENABLE
3987 wpt_uint32 sIdx;
3988 WLANDXE_ChannelCBType *channel = NULL;
3989 WLANDXE_DescCtrlBlkType *crntDescCB = NULL;
3990 WLANDXE_DescCtrlBlkType *nextDescCB = NULL;
3991#endif /* WLANDXE_TEST_CHANNEL_ENABLE */
3992
3993 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
3994 "%s Enter", __FUNCTION__);
3995
3996 /* Sanity */
3997 if(NULL == pDXEContext)
3998 {
3999 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
4000 "WLANDXE_Stop Invalid DXE CB");
4001 return eWLAN_PAL_STATUS_E_INVAL;
4002 }
4003
4004 dxeCtxt = (WLANDXE_CtrlBlkType *)pDXEContext;
4005 for(idx = 0; idx < WDTS_CHANNEL_MAX; idx++)
4006 {
4007 wpalMutexDelete(&dxeCtxt->dxeChannel[idx].dxeChannelLock);
4008 dxeChannelClose(dxeCtxt, &dxeCtxt->dxeChannel[idx]);
4009#ifdef WLANDXE_TEST_CHANNEL_ENABLE
4010 channel = &dxeCtxt->dxeChannel[idx];
4011 crntDescCB = channel->headCtrlBlk;
4012 for(sIdx = 0; sIdx < channel->numDesc; sIdx++)
4013 {
4014 nextDescCB = (WLANDXE_DescCtrlBlkType *)crntDescCB->nextCtrlBlk;
4015 wpalMemoryFree((void *)crntDescCB);
4016 crntDescCB = nextDescCB;
4017 if(NULL == crntDescCB)
4018 {
4019 break;
4020 }
4021 }
4022#endif /* WLANDXE_TEST_CHANNEL_ENABLE */
4023 }
4024
4025 if(NULL != dxeCtxt->rxIsrMsg)
4026 {
4027 wpalMemoryFree(dxeCtxt->rxIsrMsg);
4028 }
4029 if(NULL != dxeCtxt->txIsrMsg)
4030 {
4031 wpalMemoryFree(dxeCtxt->txIsrMsg);
4032 }
4033 if(NULL != dxeCtxt->rxPktAvailMsg)
4034 {
4035 wpalMemoryFree(dxeCtxt->rxPktAvailMsg);
4036 }
4037
4038 wpalMemoryFree(pDXEContext);
4039
4040 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
4041 "%s Exit", __FUNCTION__);
4042 return status;
4043}
4044
4045/*==========================================================================
4046 @ Function Name
4047 WLANDXE_TriggerTX
4048
4049 @ Description
4050 TBD
4051
4052 @ Parameters
4053 pVoid pDXEContext : DXE Control Block
4054
4055 @ Return
4056 wpt_status
4057===========================================================================*/
4058wpt_status WLANDXE_TriggerTX
4059(
4060 void *pDXEContext
4061)
4062{
4063 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
4064
4065 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
4066 "%s Enter", __FUNCTION__);
4067
4068 /* TBD */
4069
4070 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
4071 "%s Exit", __FUNCTION__);
4072 return status;
4073}
4074
4075/*==========================================================================
4076 @ Function Name
4077 dxeTxThreadSetPowerStateEventHandler
4078
4079 @ Description
4080 If WDI sends set power state req, this event handler will be called in Tx
4081 thread context
4082
4083 @ Parameters
4084 void *msgPtr
4085 Event MSG
4086
4087 @ Return
4088 None
4089===========================================================================*/
4090void dxeTxThreadSetPowerStateEventHandler
4091(
4092 wpt_msg *msgPtr
4093)
4094{
4095 wpt_msg *msgContent = (wpt_msg *)msgPtr;
4096 WLANDXE_CtrlBlkType *dxeCtxt;
4097 wpt_status status = eWLAN_PAL_STATUS_E_FAILURE;
4098 WLANDXE_PowerStateType reqPowerState;
4099
4100 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
4101 "%s Enter", __FUNCTION__);
4102
4103
4104 dxeCtxt = (WLANDXE_CtrlBlkType *)(msgContent->pContext);
4105 reqPowerState = (WLANDXE_PowerStateType)msgContent->val;
4106 dxeCtxt->setPowerStateCb = (WLANDXE_SetPowerStateCbType)msgContent->ptr;
4107
4108 switch(reqPowerState)
4109 {
4110 case WLANDXE_POWER_STATE_BMPS:
4111 if(WLANDXE_RIVA_POWER_STATE_ACTIVE == dxeCtxt->rivaPowerState)
4112 {
4113 //don't block MC waiting for num_rsvd to become 0 since it may take a while
4114 //based on amount of TX and RX activity - during this time any received
4115 // management frames will remain un-processed consuming RX buffers
4116 dxeCtxt->rivaPowerState = WLANDXE_RIVA_POWER_STATE_BMPS_UNKNOWN;
4117 dxeCtxt->hostPowerState = reqPowerState;
4118 }
4119 else
4120 {
4121 status = eWLAN_PAL_STATUS_E_INVAL;
4122 }
4123 break;
4124 case WLANDXE_POWER_STATE_IMPS:
4125 if(WLANDXE_RIVA_POWER_STATE_ACTIVE == dxeCtxt->rivaPowerState)
4126 {
4127 dxeCtxt->rivaPowerState = WLANDXE_RIVA_POWER_STATE_IMPS_UNKNOWN;
4128 }
4129 else
4130 {
4131 status = eWLAN_PAL_STATUS_E_INVAL;
4132 }
4133 break;
4134 case WLANDXE_POWER_STATE_FULL:
4135 if(WLANDXE_RIVA_POWER_STATE_BMPS_UNKNOWN == dxeCtxt->rivaPowerState)
4136 {
4137 dxeCtxt->rivaPowerState = WLANDXE_RIVA_POWER_STATE_ACTIVE;
4138 }
4139 dxeCtxt->hostPowerState = reqPowerState;
4140 dxeNotifySmsm(eWLAN_PAL_FALSE, eWLAN_PAL_TRUE);
4141 break;
4142 case WLANDXE_POWER_STATE_DOWN:
4143 WLANDXE_Stop((void *)dxeCtxt);
4144 break;
4145 default:
4146 //assert
4147 break;
4148 }
4149
4150 if(WLANDXE_POWER_STATE_BMPS_PENDING != dxeCtxt->hostPowerState)
4151 {
4152 dxeCtxt->setPowerStateCb(status,
4153 dxeCtxt->dxeChannel[WDTS_CHANNEL_TX_LOW_PRI].descBottomLocPhyAddr);
4154 }
4155 /* Free MSG buffer */
4156 wpalMemoryFree(msgPtr);
4157 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
4158 "%s Exit", __FUNCTION__);
4159 return;
4160}
4161
4162
4163/*==========================================================================
4164 @ Function Name
4165 dxeRxThreadSetPowerStateEventHandler
4166
4167 @ Description
4168 If WDI sends set power state req, this event handler will be called in Rx
4169 thread context
4170
4171 @ Parameters
4172 void *msgPtr
4173 Event MSG
4174
4175 @ Return
4176 None
4177===========================================================================*/
4178void dxeRxThreadSetPowerStateEventHandler
4179(
4180 wpt_msg *msgPtr
4181)
4182{
4183 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
4184
4185 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
4186 "%s Enter", __FUNCTION__);
4187
4188 /* Now serialise the message through Tx thread also to make sure
4189 * no register access when RIVA is in powersave */
4190 /*Use the same message pointer just change the call back function */
4191 msgPtr->callback = dxeTxThreadSetPowerStateEventHandler;
4192 status = wpalPostTxMsg(WDI_GET_PAL_CTX(),
4193 msgPtr);
4194 if ( eWLAN_PAL_STATUS_SUCCESS != status )
4195 {
4196 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
4197 "Tx thread Set power state req serialize fail status=%d",
4198 status, 0, 0);
4199 }
4200
4201 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
4202 "%s Exit", __FUNCTION__);
4203}
4204
4205/*==========================================================================
4206 @ Function Name
4207 WLANDXE_SetPowerState
4208
4209 @ Description
4210 From Client let DXE knows what is the WLAN HW(RIVA) power state
4211
4212 @ Parameters
4213 pVoid pDXEContext : DXE Control Block
4214 WLANDXE_PowerStateType powerState
4215
4216 @ Return
4217 wpt_status
4218===========================================================================*/
4219wpt_status WLANDXE_SetPowerState
4220(
4221 void *pDXEContext,
4222 WDTS_PowerStateType powerState,
4223 WDTS_SetPSCbType cBack
4224)
4225{
4226 wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
4227 WLANDXE_CtrlBlkType *pDxeCtrlBlk;
4228 WLANDXE_PowerStateType hostPowerState;
4229 wpt_msg *rxCompMsg;
4230
4231 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
4232 "%s Enter", __FUNCTION__);
4233 if(NULL == pDXEContext)
4234 {
4235 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
4236 "NULL pDXEContext passed by caller", 0, 0, 0);
4237 return eWLAN_PAL_STATUS_E_FAILURE;
4238 }
4239 pDxeCtrlBlk = (WLANDXE_CtrlBlkType *)pDXEContext;
4240
Jeff Johnson295189b2012-06-20 16:38:30 -07004241 switch(powerState)
4242 {
4243 case WDTS_POWER_STATE_FULL:
4244 hostPowerState = WLANDXE_POWER_STATE_FULL;
4245 break;
4246 case WDTS_POWER_STATE_BMPS:
4247 pDxeCtrlBlk->hostPowerState = WLANDXE_POWER_STATE_BMPS;
4248 hostPowerState = WLANDXE_POWER_STATE_BMPS;
4249 break;
4250 case WDTS_POWER_STATE_IMPS:
4251 pDxeCtrlBlk->hostPowerState = WLANDXE_POWER_STATE_IMPS;
4252 hostPowerState = WLANDXE_POWER_STATE_IMPS;
4253 break;
4254 case WDTS_POWER_STATE_DOWN:
4255 pDxeCtrlBlk->hostPowerState = WLANDXE_POWER_STATE_DOWN;
4256 hostPowerState = WLANDXE_POWER_STATE_DOWN;
4257 break;
4258 default:
4259 hostPowerState = WLANDXE_POWER_STATE_MAX;
4260 }
4261
4262 // A callback i.e. ACK back is needed only when we want to enable BMPS
4263 // and the data/management path is active because we want to ensure
4264 // DXE registers are not accessed when RIVA may be power-collapsed. So
4265 // we need a callback in enter_bmps_req (the request to RIVA is sent
4266 // only after ACK back from TX thread). A callback is not needed in
4267 // finish_scan_req during BMPS since data-path is resumed only in
4268 // finish_scan_rsp and no management frames are sent in between. No
4269 // callback is needed when going from BMPS enabled to BMPS suspended/
4270 // disabled when it is known that RIVA is awake and cannot enter power
4271 // collapse autonomously so no callback is needed in exit_bmps_rsp or
4272 // init_scan_rsp
4273 if ( cBack )
4274 {
4275 //serialize through Rx thread
4276 rxCompMsg = (wpt_msg *)wpalMemoryAllocate(sizeof(wpt_msg));
4277 if(NULL == rxCompMsg)
4278 {
4279 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
4280 "WLANDXE_SetPowerState, MSG MEM alloc Fail");
4281 return eWLAN_PAL_STATUS_E_RESOURCES;
4282 }
4283
4284 /* Event type, where it must be defined???? */
4285 /* THIS MUST BE CLEARED ASAP
4286 txCompMsg->type = TX_COMPLETE; */
4287 rxCompMsg->callback = dxeRxThreadSetPowerStateEventHandler;
4288 rxCompMsg->pContext = pDxeCtrlBlk;
4289 rxCompMsg->val = hostPowerState;
4290 rxCompMsg->ptr = cBack;
4291 status = wpalPostRxMsg(WDI_GET_PAL_CTX(),
4292 rxCompMsg);
4293 if ( eWLAN_PAL_STATUS_SUCCESS != status )
4294 {
4295 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
4296 "Rx thread Set power state req serialize fail status=%d",
4297 status, 0, 0);
4298 }
4299 }
4300 else
4301 {
4302 if ( WLANDXE_POWER_STATE_FULL == hostPowerState )
4303 {
4304 if( WLANDXE_POWER_STATE_BMPS == pDxeCtrlBlk->hostPowerState )
4305 {
4306 dxeNotifySmsm(eWLAN_PAL_FALSE, eWLAN_PAL_TRUE);
4307 }
4308 else if( WLANDXE_POWER_STATE_IMPS == pDxeCtrlBlk->hostPowerState )
4309 {
4310 /* Requested Full power from exit IMPS, reenable the interrupts*/
4311 if(eWLAN_PAL_TRUE == pDxeCtrlBlk->rxIntDisabledByIMPS)
4312 {
4313 pDxeCtrlBlk->rxIntDisabledByIMPS = eWLAN_PAL_FALSE;
4314 /* Enable RX interrupt at here, if new PS is not IMPS */
4315 status = wpalEnableInterrupt(DXE_INTERRUPT_RX_READY);
4316 if(eWLAN_PAL_STATUS_SUCCESS != status)
4317 {
4318 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
4319 "%s Enable RX ready interrupt fail", __FUNCTION__);
4320 return status;
4321 }
4322 }
4323 if(eWLAN_PAL_TRUE == pDxeCtrlBlk->txIntDisabledByIMPS)
4324 {
4325 pDxeCtrlBlk->txIntDisabledByIMPS = eWLAN_PAL_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07004326 pDxeCtrlBlk->txIntEnable = eWLAN_PAL_TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004327 /* Enable RX interrupt at here, if new PS is not IMPS */
4328 status = wpalEnableInterrupt(DXE_INTERRUPT_TX_COMPLE);
4329 if(eWLAN_PAL_STATUS_SUCCESS != status)
4330 {
4331 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
4332 "%s Enable TX comp interrupt fail", __FUNCTION__);
4333 return status;
4334 }
4335 }
4336 }
4337 pDxeCtrlBlk->hostPowerState = hostPowerState;
4338 pDxeCtrlBlk->rivaPowerState = WLANDXE_RIVA_POWER_STATE_ACTIVE;
4339 }
4340 else if ( hostPowerState == WLANDXE_POWER_STATE_BMPS )
4341 {
4342 pDxeCtrlBlk->hostPowerState = hostPowerState;
4343 pDxeCtrlBlk->rivaPowerState = WLANDXE_RIVA_POWER_STATE_BMPS_UNKNOWN;
4344 }
4345 else
4346 {
4347 HDXE_ASSERT(0);
4348 }
4349 }
4350
4351 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
4352 "%s Exit", __FUNCTION__);
4353
4354 return status;
4355}
4356
4357/*==========================================================================
4358 @ Function Name
4359 WLANDXE_GetFreeTxDataResNumber
4360
4361 @ Description
4362 Returns free descriptor numbers for TX data channel (TX high priority)
4363
4364 @ Parameters
4365 pVoid pDXEContext : DXE Control Block
4366
4367 @ Return
4368 wpt_uint32 Free descriptor number of TX high pri ch
4369===========================================================================*/
4370wpt_uint32 WLANDXE_GetFreeTxDataResNumber
4371(
4372 void *pDXEContext
4373)
4374{
4375 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW,
4376 "%s Enter", __FUNCTION__);
4377
4378 if(NULL == pDXEContext)
4379 {
4380 HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
4381 "NULL parameter passed by caller", 0, 0, 0);
4382 return (0);
4383 }
4384
4385 return
4386 ((WLANDXE_CtrlBlkType *)pDXEContext)->dxeChannel[WDTS_CHANNEL_TX_LOW_PRI].numFreeDesc;
4387}