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"
43 BUILD_TIMER_FUNCTION(MlmePeriodicExec
);
44 /*BUILD_TIMER_FUNCTION(MlmeRssiReportExec); */
45 BUILD_TIMER_FUNCTION(AsicRxAntEvalTimeout
);
46 BUILD_TIMER_FUNCTION(APSDPeriodicExec
);
47 BUILD_TIMER_FUNCTION(AsicRfTuningExec
);
49 BUILD_TIMER_FUNCTION(BeaconUpdateExec
);
50 #endif /* RTMP_MAC_USB // */
52 BUILD_TIMER_FUNCTION(BeaconTimeout
);
53 BUILD_TIMER_FUNCTION(ScanTimeout
);
54 BUILD_TIMER_FUNCTION(AuthTimeout
);
55 BUILD_TIMER_FUNCTION(AssocTimeout
);
56 BUILD_TIMER_FUNCTION(ReassocTimeout
);
57 BUILD_TIMER_FUNCTION(DisassocTimeout
);
58 BUILD_TIMER_FUNCTION(LinkDownExec
);
59 BUILD_TIMER_FUNCTION(StaQuickResponeForRateUpExec
);
60 BUILD_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc
);
62 BUILD_TIMER_FUNCTION(PsPollWakeExec
);
63 BUILD_TIMER_FUNCTION(RadioOnExec
);
64 #endif /* RTMP_MAC_PCI // */
66 BUILD_TIMER_FUNCTION(RtmpUsbStaAsicForceWakeupTimeout
);
67 #endif /* RTMP_MAC_USB // */
69 #if defined(AP_LED) || defined(STA_LED)
70 extern void LedCtrlMain(void *SystemSpecific1
,
71 void *FunctionContext
,
72 void *SystemSpecific2
, void *SystemSpecific3
);
73 BUILD_TIMER_FUNCTION(LedCtrlMain
);
76 #ifdef RTMP_TIMER_TASK_SUPPORT
77 static void RtmpTimerQHandle(struct rt_rtmp_adapter
*pAd
)
79 #ifndef KTHREAD_SUPPORT
82 struct rt_ralink_timer
*pTimer
;
83 struct rt_rtmp_timer_task_entry
*pEntry
;
84 unsigned long irqFlag
;
85 struct rt_rtmp_os_task
*pTask
;
87 pTask
= &pAd
->timerTask
;
88 while (!pTask
->task_killed
) {
91 #ifdef KTHREAD_SUPPORT
92 RTMP_WAIT_EVENT_INTERRUPTIBLE(pAd
, pTask
);
94 RTMP_SEM_EVENT_WAIT(&(pTask
->taskSema
), status
);
97 if (pAd
->TimerQ
.status
== RTMP_TASK_STAT_STOPED
)
100 /* event happened. */
101 while (pAd
->TimerQ
.pQHead
) {
102 RTMP_INT_LOCK(&pAd
->TimerQLock
, irqFlag
);
103 pEntry
= pAd
->TimerQ
.pQHead
;
105 pTimer
= pEntry
->pRaTimer
;
108 pAd
->TimerQ
.pQHead
= pEntry
->pNext
;
109 if (pEntry
== pAd
->TimerQ
.pQTail
)
110 pAd
->TimerQ
.pQTail
= NULL
;
112 /* return this queue entry to timerQFreeList. */
113 pEntry
->pNext
= pAd
->TimerQ
.pQPollFreeList
;
114 pAd
->TimerQ
.pQPollFreeList
= pEntry
;
116 RTMP_INT_UNLOCK(&pAd
->TimerQLock
, irqFlag
);
119 if ((pTimer
->handle
!= NULL
)
120 && (!pAd
->PM_FlgSuspend
))
122 (void *)pTimer
->cookie
,
125 && (pTimer
->State
== FALSE
))
126 RTMP_OS_Add_Timer(&pTimer
->TimerObj
,
131 #ifndef KTHREAD_SUPPORT
133 pAd
->TimerQ
.status
= RTMP_TASK_STAT_STOPED
;
134 RTMP_SET_FLAG(pAd
, fRTMP_ADAPTER_HALT_IN_PROGRESS
);
141 int RtmpTimerQThread(IN
void *Context
)
143 struct rt_rtmp_os_task
*pTask
;
144 struct rt_rtmp_adapter
*pAd
;
149 RtmpOSTaskCustomize(pTask
);
151 RtmpTimerQHandle(pAd
);
153 DBGPRINT(RT_DEBUG_TRACE
, ("<---%s\n", __func__
));
154 #ifndef KTHREAD_SUPPORT
155 pTask
->taskPID
= THREAD_PID_INIT_VALUE
;
157 /* notify the exit routine that we're actually exiting now
159 * complete()/wait_for_completion() is similar to up()/down(),
160 * except that complete() is safe in the case where the structure
161 * is getting deleted in a parallel mode of execution (i.e. just
162 * after the down() -- that's necessary for the thread-shutdown
165 * complete_and_exit() goes even further than this -- it is safe in
166 * the case that the thread of the caller is going away (not just
167 * the structure) -- this is necessary for the module-remove case.
168 * This is important in preemption kernels, which transfer the flow
169 * of execution immediately upon a complete().
171 RtmpOSTaskNotifyToExit(pTask
);
177 struct rt_rtmp_timer_task_entry
*RtmpTimerQInsert(struct rt_rtmp_adapter
*pAd
,
178 struct rt_ralink_timer
*pTimer
)
180 struct rt_rtmp_timer_task_entry
*pQNode
= NULL
, *pQTail
;
181 unsigned long irqFlags
;
182 struct rt_rtmp_os_task
*pTask
= &pAd
->timerTask
;
184 RTMP_INT_LOCK(&pAd
->TimerQLock
, irqFlags
);
185 if (pAd
->TimerQ
.status
& RTMP_TASK_CAN_DO_INSERT
) {
186 if (pAd
->TimerQ
.pQPollFreeList
) {
187 pQNode
= pAd
->TimerQ
.pQPollFreeList
;
188 pAd
->TimerQ
.pQPollFreeList
= pQNode
->pNext
;
190 pQNode
->pRaTimer
= pTimer
;
191 pQNode
->pNext
= NULL
;
193 pQTail
= pAd
->TimerQ
.pQTail
;
194 if (pAd
->TimerQ
.pQTail
!= NULL
)
195 pQTail
->pNext
= pQNode
;
196 pAd
->TimerQ
.pQTail
= pQNode
;
197 if (pAd
->TimerQ
.pQHead
== NULL
)
198 pAd
->TimerQ
.pQHead
= pQNode
;
201 RTMP_INT_UNLOCK(&pAd
->TimerQLock
, irqFlags
);
204 #ifdef KTHREAD_SUPPORT
207 RTMP_SEM_EVENT_UP(&pTask
->taskSema
);
214 BOOLEAN
RtmpTimerQRemove(struct rt_rtmp_adapter
*pAd
, struct rt_ralink_timer
*pTimer
)
216 struct rt_rtmp_timer_task_entry
*pNode
, *pPrev
= NULL
;
217 unsigned long irqFlags
;
219 RTMP_INT_LOCK(&pAd
->TimerQLock
, irqFlags
);
220 if (pAd
->TimerQ
.status
>= RTMP_TASK_STAT_INITED
) {
221 pNode
= pAd
->TimerQ
.pQHead
;
223 if (pNode
->pRaTimer
== pTimer
)
226 pNode
= pNode
->pNext
;
229 /* Now move it to freeList queue. */
231 if (pNode
== pAd
->TimerQ
.pQHead
)
232 pAd
->TimerQ
.pQHead
= pNode
->pNext
;
233 if (pNode
== pAd
->TimerQ
.pQTail
)
234 pAd
->TimerQ
.pQTail
= pPrev
;
236 pPrev
->pNext
= pNode
->pNext
;
238 /* return this queue entry to timerQFreeList. */
239 pNode
->pNext
= pAd
->TimerQ
.pQPollFreeList
;
240 pAd
->TimerQ
.pQPollFreeList
= pNode
;
243 RTMP_INT_UNLOCK(&pAd
->TimerQLock
, irqFlags
);
248 void RtmpTimerQExit(struct rt_rtmp_adapter
*pAd
)
250 struct rt_rtmp_timer_task_entry
*pTimerQ
;
251 unsigned long irqFlags
;
253 RTMP_INT_LOCK(&pAd
->TimerQLock
, irqFlags
);
254 while (pAd
->TimerQ
.pQHead
) {
255 pTimerQ
= pAd
->TimerQ
.pQHead
;
256 pAd
->TimerQ
.pQHead
= pTimerQ
->pNext
;
257 /* remove the timeQ */
259 pAd
->TimerQ
.pQPollFreeList
= NULL
;
260 os_free_mem(pAd
, pAd
->TimerQ
.pTimerQPoll
);
261 pAd
->TimerQ
.pQTail
= NULL
;
262 pAd
->TimerQ
.pQHead
= NULL
;
263 #ifndef KTHREAD_SUPPORT
264 pAd
->TimerQ
.status
= RTMP_TASK_STAT_STOPED
;
266 RTMP_INT_UNLOCK(&pAd
->TimerQLock
, irqFlags
);
270 void RtmpTimerQInit(struct rt_rtmp_adapter
*pAd
)
273 struct rt_rtmp_timer_task_entry
*pQNode
, *pEntry
;
274 unsigned long irqFlags
;
276 NdisAllocateSpinLock(&pAd
->TimerQLock
);
278 NdisZeroMemory(&pAd
->TimerQ
, sizeof(pAd
->TimerQ
));
280 os_alloc_mem(pAd
, &pAd
->TimerQ
.pTimerQPoll
,
281 sizeof(struct rt_rtmp_timer_task_entry
) * TIMER_QUEUE_SIZE_MAX
);
282 if (pAd
->TimerQ
.pTimerQPoll
) {
284 pQNode
= (struct rt_rtmp_timer_task_entry
*)pAd
->TimerQ
.pTimerQPoll
;
285 NdisZeroMemory(pAd
->TimerQ
.pTimerQPoll
,
286 sizeof(struct rt_rtmp_timer_task_entry
) *
287 TIMER_QUEUE_SIZE_MAX
);
289 RTMP_INT_LOCK(&pAd
->TimerQLock
, irqFlags
);
290 for (i
= 0; i
< TIMER_QUEUE_SIZE_MAX
; i
++) {
291 pQNode
->pNext
= pEntry
;
295 pAd
->TimerQ
.pQPollFreeList
= pEntry
;
296 pAd
->TimerQ
.pQHead
= NULL
;
297 pAd
->TimerQ
.pQTail
= NULL
;
298 pAd
->TimerQ
.status
= RTMP_TASK_STAT_INITED
;
299 RTMP_INT_UNLOCK(&pAd
->TimerQLock
, irqFlags
);
302 #endif /* RTMP_TIMER_TASK_SUPPORT // */