2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
31 task for timer handling
35 -------- ---------- ----------------------------------------------
36 Name Date Modification logs
37 Shiang Tu 08-28-2008 init version
41 #include "../rt_config.h"
44 BUILD_TIMER_FUNCTION(MlmePeriodicExec);
45 //BUILD_TIMER_FUNCTION(MlmeRssiReportExec);
46 BUILD_TIMER_FUNCTION(AsicRxAntEvalTimeout);
47 BUILD_TIMER_FUNCTION(APSDPeriodicExec);
48 BUILD_TIMER_FUNCTION(AsicRfTuningExec);
50 BUILD_TIMER_FUNCTION(BeaconUpdateExec);
51 #endif // RTMP_MAC_USB //
53 BUILD_TIMER_FUNCTION(BeaconTimeout);
54 BUILD_TIMER_FUNCTION(ScanTimeout);
55 BUILD_TIMER_FUNCTION(AuthTimeout);
56 BUILD_TIMER_FUNCTION(AssocTimeout);
57 BUILD_TIMER_FUNCTION(ReassocTimeout);
58 BUILD_TIMER_FUNCTION(DisassocTimeout);
59 BUILD_TIMER_FUNCTION(LinkDownExec);
60 BUILD_TIMER_FUNCTION(StaQuickResponeForRateUpExec);
61 BUILD_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc);
63 BUILD_TIMER_FUNCTION(PsPollWakeExec);
64 BUILD_TIMER_FUNCTION(RadioOnExec);
65 #endif // RTMP_MAC_PCI //
67 BUILD_TIMER_FUNCTION(RtmpUsbStaAsicForceWakeupTimeout);
68 #endif // RTMP_MAC_USB //
70 #if defined(AP_LED) || defined(STA_LED)
71 extern void LedCtrlMain(
72 IN PVOID SystemSpecific1,
73 IN PVOID FunctionContext,
74 IN PVOID SystemSpecific2,
75 IN PVOID SystemSpecific3);
76 BUILD_TIMER_FUNCTION(LedCtrlMain);
80 #ifdef RTMP_TIMER_TASK_SUPPORT
81 static void RtmpTimerQHandle(RTMP_ADAPTER *pAd)
83 #ifndef KTHREAD_SUPPORT
86 RALINK_TIMER_STRUCT *pTimer;
87 RTMP_TIMER_TASK_ENTRY *pEntry;
88 unsigned long irqFlag;
92 pTask = &pAd->timerTask;
93 while(!pTask->task_killed)
97 #ifdef KTHREAD_SUPPORT
98 RTMP_WAIT_EVENT_INTERRUPTIBLE(pAd, pTask);
100 RTMP_SEM_EVENT_WAIT(&(pTask->taskSema), status);
103 if (pAd->TimerQ.status == RTMP_TASK_STAT_STOPED)
107 while(pAd->TimerQ.pQHead)
109 RTMP_INT_LOCK(&pAd->TimerQLock, irqFlag);
110 pEntry = pAd->TimerQ.pQHead;
113 pTimer = pEntry->pRaTimer;
116 pAd->TimerQ.pQHead = pEntry->pNext;
117 if (pEntry == pAd->TimerQ.pQTail)
118 pAd->TimerQ.pQTail = NULL;
120 // return this queue entry to timerQFreeList.
121 pEntry->pNext = pAd->TimerQ.pQPollFreeList;
122 pAd->TimerQ.pQPollFreeList = pEntry;
124 RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlag);
128 if ((pTimer->handle != NULL) && (!pAd->PM_FlgSuspend))
129 pTimer->handle(NULL, (PVOID) pTimer->cookie, NULL, pTimer);
130 if ((pTimer->Repeat) && (pTimer->State == FALSE))
131 RTMP_OS_Add_Timer(&pTimer->TimerObj, pTimer->TimerValue);
135 #ifndef KTHREAD_SUPPORT
138 pAd->TimerQ.status = RTMP_TASK_STAT_STOPED;
139 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
147 INT RtmpTimerQThread(
148 IN OUT PVOID Context)
154 pTask = (RTMP_OS_TASK *)Context;
155 pAd = (PRTMP_ADAPTER)pTask->priv;
157 RtmpOSTaskCustomize(pTask);
159 RtmpTimerQHandle(pAd);
161 DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__func__));
162 #ifndef KTHREAD_SUPPORT
163 pTask->taskPID = THREAD_PID_INIT_VALUE;
165 /* notify the exit routine that we're actually exiting now
167 * complete()/wait_for_completion() is similar to up()/down(),
168 * except that complete() is safe in the case where the structure
169 * is getting deleted in a parallel mode of execution (i.e. just
170 * after the down() -- that's necessary for the thread-shutdown
173 * complete_and_exit() goes even further than this -- it is safe in
174 * the case that the thread of the caller is going away (not just
175 * the structure) -- this is necessary for the module-remove case.
176 * This is important in preemption kernels, which transfer the flow
177 * of execution immediately upon a complete().
179 RtmpOSTaskNotifyToExit(pTask);
186 RTMP_TIMER_TASK_ENTRY *RtmpTimerQInsert(
187 IN RTMP_ADAPTER *pAd,
188 IN RALINK_TIMER_STRUCT *pTimer)
190 RTMP_TIMER_TASK_ENTRY *pQNode = NULL, *pQTail;
191 unsigned long irqFlags;
192 RTMP_OS_TASK *pTask = &pAd->timerTask;
194 RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags);
195 if (pAd->TimerQ.status & RTMP_TASK_CAN_DO_INSERT)
197 if(pAd->TimerQ.pQPollFreeList)
199 pQNode = pAd->TimerQ.pQPollFreeList;
200 pAd->TimerQ.pQPollFreeList = pQNode->pNext;
202 pQNode->pRaTimer = pTimer;
203 pQNode->pNext = NULL;
205 pQTail = pAd->TimerQ.pQTail;
206 if (pAd->TimerQ.pQTail != NULL)
207 pQTail->pNext = pQNode;
208 pAd->TimerQ.pQTail = pQNode;
209 if (pAd->TimerQ.pQHead == NULL)
210 pAd->TimerQ.pQHead = pQNode;
213 RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags);
217 #ifdef KTHREAD_SUPPORT
220 RTMP_SEM_EVENT_UP(&pTask->taskSema);
228 BOOLEAN RtmpTimerQRemove(
229 IN RTMP_ADAPTER *pAd,
230 IN RALINK_TIMER_STRUCT *pTimer)
232 RTMP_TIMER_TASK_ENTRY *pNode, *pPrev = NULL;
233 unsigned long irqFlags;
235 RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags);
236 if (pAd->TimerQ.status >= RTMP_TASK_STAT_INITED)
238 pNode = pAd->TimerQ.pQHead;
241 if (pNode->pRaTimer == pTimer)
244 pNode = pNode->pNext;
247 // Now move it to freeList queue.
250 if (pNode == pAd->TimerQ.pQHead)
251 pAd->TimerQ.pQHead = pNode->pNext;
252 if (pNode == pAd->TimerQ.pQTail)
253 pAd->TimerQ.pQTail = pPrev;
255 pPrev->pNext = pNode->pNext;
257 // return this queue entry to timerQFreeList.
258 pNode->pNext = pAd->TimerQ.pQPollFreeList;
259 pAd->TimerQ.pQPollFreeList = pNode;
262 RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags);
268 void RtmpTimerQExit(RTMP_ADAPTER *pAd)
270 RTMP_TIMER_TASK_ENTRY *pTimerQ;
271 unsigned long irqFlags;
273 RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags);
274 while (pAd->TimerQ.pQHead)
276 pTimerQ = pAd->TimerQ.pQHead;
277 pAd->TimerQ.pQHead = pTimerQ->pNext;
280 pAd->TimerQ.pQPollFreeList = NULL;
281 os_free_mem(pAd, pAd->TimerQ.pTimerQPoll);
282 pAd->TimerQ.pQTail = NULL;
283 pAd->TimerQ.pQHead = NULL;
284 #ifndef KTHREAD_SUPPORT
285 pAd->TimerQ.status = RTMP_TASK_STAT_STOPED;
287 RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags);
292 void RtmpTimerQInit(RTMP_ADAPTER *pAd)
295 RTMP_TIMER_TASK_ENTRY *pQNode, *pEntry;
296 unsigned long irqFlags;
298 NdisAllocateSpinLock(&pAd->TimerQLock);
300 NdisZeroMemory(&pAd->TimerQ, sizeof(pAd->TimerQ));
302 os_alloc_mem(pAd, &pAd->TimerQ.pTimerQPoll, sizeof(RTMP_TIMER_TASK_ENTRY) * TIMER_QUEUE_SIZE_MAX);
303 if (pAd->TimerQ.pTimerQPoll)
306 pQNode = (RTMP_TIMER_TASK_ENTRY *)pAd->TimerQ.pTimerQPoll;
307 NdisZeroMemory(pAd->TimerQ.pTimerQPoll, sizeof(RTMP_TIMER_TASK_ENTRY) * TIMER_QUEUE_SIZE_MAX);
309 RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags);
310 for (i = 0 ;i <TIMER_QUEUE_SIZE_MAX; i++)
312 pQNode->pNext = pEntry;
316 pAd->TimerQ.pQPollFreeList = pEntry;
317 pAd->TimerQ.pQHead = NULL;
318 pAd->TimerQ.pQTail = NULL;
319 pAd->TimerQ.status = RTMP_TASK_STAT_INITED;
320 RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags);
323 #endif // RTMP_TIMER_TASK_SUPPORT //