]>
Commit | Line | Data |
---|---|---|
ca97b838 BZ |
1 | /* |
2 | ************************************************************************* | |
3 | * Ralink Tech Inc. | |
4 | * 5F., No.36, Taiyuan St., Jhubei City, | |
5 | * Hsinchu County 302, | |
6 | * Taiwan, R.O.C. | |
7 | * | |
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | |
9 | * | |
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. * | |
14 | * * | |
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. * | |
19 | * * | |
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. * | |
24 | * * | |
25 | ************************************************************************* | |
26 | ||
27 | Module Name: | |
28 | rtmp_timer.c | |
29 | ||
30 | Abstract: | |
31 | task for timer handling | |
32 | ||
33 | Revision History: | |
34 | Who When What | |
35 | -------- ---------- ---------------------------------------------- | |
36 | Name Date Modification logs | |
37 | Shiang Tu 08-28-2008 init version | |
38 | ||
39 | */ | |
40 | ||
41 | #include "../rt_config.h" | |
42 | ||
ca97b838 | 43 | BUILD_TIMER_FUNCTION(MlmePeriodicExec); |
ec278fa2 | 44 | /*BUILD_TIMER_FUNCTION(MlmeRssiReportExec); */ |
ca97b838 BZ |
45 | BUILD_TIMER_FUNCTION(AsicRxAntEvalTimeout); |
46 | BUILD_TIMER_FUNCTION(APSDPeriodicExec); | |
47 | BUILD_TIMER_FUNCTION(AsicRfTuningExec); | |
48 | #ifdef RTMP_MAC_USB | |
49 | BUILD_TIMER_FUNCTION(BeaconUpdateExec); | |
ec278fa2 | 50 | #endif /* RTMP_MAC_USB // */ |
ca97b838 BZ |
51 | |
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); | |
e44fd1cf | 61 | #ifdef RTMP_MAC_PCI |
ca97b838 BZ |
62 | BUILD_TIMER_FUNCTION(PsPollWakeExec); |
63 | BUILD_TIMER_FUNCTION(RadioOnExec); | |
ec278fa2 | 64 | #endif /* RTMP_MAC_PCI // */ |
ca97b838 BZ |
65 | #ifdef RTMP_MAC_USB |
66 | BUILD_TIMER_FUNCTION(RtmpUsbStaAsicForceWakeupTimeout); | |
ec278fa2 | 67 | #endif /* RTMP_MAC_USB // */ |
ca97b838 BZ |
68 | |
69 | #if defined(AP_LED) || defined(STA_LED) | |
51126deb BZ |
70 | extern void LedCtrlMain(void *SystemSpecific1, |
71 | void *FunctionContext, | |
72 | void *SystemSpecific2, void *SystemSpecific3); | |
ca97b838 BZ |
73 | BUILD_TIMER_FUNCTION(LedCtrlMain); |
74 | #endif | |
75 | ||
ca97b838 | 76 | #ifdef RTMP_TIMER_TASK_SUPPORT |
96b3c83d | 77 | static void RtmpTimerQHandle(RTMP_ADAPTER * pAd) |
ca97b838 BZ |
78 | { |
79 | #ifndef KTHREAD_SUPPORT | |
80 | int status; | |
81 | #endif | |
96b3c83d BZ |
82 | RALINK_TIMER_STRUCT *pTimer; |
83 | RTMP_TIMER_TASK_ENTRY *pEntry; | |
84 | unsigned long irqFlag; | |
ca97b838 BZ |
85 | RTMP_OS_TASK *pTask; |
86 | ||
ca97b838 | 87 | pTask = &pAd->timerTask; |
96b3c83d | 88 | while (!pTask->task_killed) { |
ca97b838 BZ |
89 | pTimer = NULL; |
90 | ||
91 | #ifdef KTHREAD_SUPPORT | |
92 | RTMP_WAIT_EVENT_INTERRUPTIBLE(pAd, pTask); | |
93 | #else | |
94 | RTMP_SEM_EVENT_WAIT(&(pTask->taskSema), status); | |
95 | #endif | |
96 | ||
97 | if (pAd->TimerQ.status == RTMP_TASK_STAT_STOPED) | |
98 | break; | |
99 | ||
ec278fa2 | 100 | /* event happened. */ |
96b3c83d | 101 | while (pAd->TimerQ.pQHead) { |
ca97b838 BZ |
102 | RTMP_INT_LOCK(&pAd->TimerQLock, irqFlag); |
103 | pEntry = pAd->TimerQ.pQHead; | |
96b3c83d | 104 | if (pEntry) { |
ca97b838 BZ |
105 | pTimer = pEntry->pRaTimer; |
106 | ||
ec278fa2 | 107 | /* update pQHead */ |
ca97b838 BZ |
108 | pAd->TimerQ.pQHead = pEntry->pNext; |
109 | if (pEntry == pAd->TimerQ.pQTail) | |
110 | pAd->TimerQ.pQTail = NULL; | |
111 | ||
ec278fa2 | 112 | /* return this queue entry to timerQFreeList. */ |
ca97b838 BZ |
113 | pEntry->pNext = pAd->TimerQ.pQPollFreeList; |
114 | pAd->TimerQ.pQPollFreeList = pEntry; | |
115 | } | |
116 | RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlag); | |
117 | ||
96b3c83d BZ |
118 | if (pTimer) { |
119 | if ((pTimer->handle != NULL) | |
120 | && (!pAd->PM_FlgSuspend)) | |
121 | pTimer->handle(NULL, | |
51126deb | 122 | (void *)pTimer->cookie, |
96b3c83d BZ |
123 | NULL, pTimer); |
124 | if ((pTimer->Repeat) | |
125 | && (pTimer->State == FALSE)) | |
126 | RTMP_OS_Add_Timer(&pTimer->TimerObj, | |
127 | pTimer->TimerValue); | |
ca97b838 BZ |
128 | } |
129 | } | |
130 | ||
131 | #ifndef KTHREAD_SUPPORT | |
96b3c83d | 132 | if (status != 0) { |
ca97b838 BZ |
133 | pAd->TimerQ.status = RTMP_TASK_STAT_STOPED; |
134 | RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); | |
135 | break; | |
136 | } | |
137 | #endif | |
138 | } | |
139 | } | |
140 | ||
51126deb | 141 | int RtmpTimerQThread(IN void *Context) |
ca97b838 | 142 | { |
96b3c83d BZ |
143 | RTMP_OS_TASK *pTask; |
144 | PRTMP_ADAPTER pAd; | |
ca97b838 | 145 | |
96b3c83d BZ |
146 | pTask = (RTMP_OS_TASK *) Context; |
147 | pAd = (PRTMP_ADAPTER) pTask->priv; | |
ca97b838 BZ |
148 | |
149 | RtmpOSTaskCustomize(pTask); | |
150 | ||
151 | RtmpTimerQHandle(pAd); | |
152 | ||
96b3c83d | 153 | DBGPRINT(RT_DEBUG_TRACE, ("<---%s\n", __func__)); |
ca97b838 BZ |
154 | #ifndef KTHREAD_SUPPORT |
155 | pTask->taskPID = THREAD_PID_INIT_VALUE; | |
156 | #endif | |
157 | /* notify the exit routine that we're actually exiting now | |
158 | * | |
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 | |
163 | * case. | |
164 | * | |
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(). | |
170 | */ | |
171 | RtmpOSTaskNotifyToExit(pTask); | |
172 | ||
173 | return 0; | |
174 | ||
175 | } | |
176 | ||
96b3c83d BZ |
177 | RTMP_TIMER_TASK_ENTRY *RtmpTimerQInsert(IN RTMP_ADAPTER * pAd, |
178 | IN RALINK_TIMER_STRUCT * pTimer) | |
ca97b838 BZ |
179 | { |
180 | RTMP_TIMER_TASK_ENTRY *pQNode = NULL, *pQTail; | |
181 | unsigned long irqFlags; | |
96b3c83d | 182 | RTMP_OS_TASK *pTask = &pAd->timerTask; |
ca97b838 BZ |
183 | |
184 | RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags); | |
96b3c83d BZ |
185 | if (pAd->TimerQ.status & RTMP_TASK_CAN_DO_INSERT) { |
186 | if (pAd->TimerQ.pQPollFreeList) { | |
ca97b838 BZ |
187 | pQNode = pAd->TimerQ.pQPollFreeList; |
188 | pAd->TimerQ.pQPollFreeList = pQNode->pNext; | |
189 | ||
190 | pQNode->pRaTimer = pTimer; | |
191 | pQNode->pNext = NULL; | |
192 | ||
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; | |
199 | } | |
200 | } | |
201 | RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags); | |
202 | ||
96b3c83d | 203 | if (pQNode) { |
ca97b838 BZ |
204 | #ifdef KTHREAD_SUPPORT |
205 | WAKE_UP(pTask); | |
206 | #else | |
207 | RTMP_SEM_EVENT_UP(&pTask->taskSema); | |
208 | #endif | |
209 | } | |
210 | ||
211 | return pQNode; | |
212 | } | |
213 | ||
96b3c83d | 214 | BOOLEAN RtmpTimerQRemove(IN RTMP_ADAPTER * pAd, IN RALINK_TIMER_STRUCT * pTimer) |
ca97b838 BZ |
215 | { |
216 | RTMP_TIMER_TASK_ENTRY *pNode, *pPrev = NULL; | |
217 | unsigned long irqFlags; | |
218 | ||
219 | RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags); | |
96b3c83d | 220 | if (pAd->TimerQ.status >= RTMP_TASK_STAT_INITED) { |
ca97b838 | 221 | pNode = pAd->TimerQ.pQHead; |
96b3c83d | 222 | while (pNode) { |
ca97b838 BZ |
223 | if (pNode->pRaTimer == pTimer) |
224 | break; | |
225 | pPrev = pNode; | |
226 | pNode = pNode->pNext; | |
227 | } | |
228 | ||
ec278fa2 | 229 | /* Now move it to freeList queue. */ |
96b3c83d | 230 | if (pNode) { |
ca97b838 BZ |
231 | if (pNode == pAd->TimerQ.pQHead) |
232 | pAd->TimerQ.pQHead = pNode->pNext; | |
233 | if (pNode == pAd->TimerQ.pQTail) | |
234 | pAd->TimerQ.pQTail = pPrev; | |
235 | if (pPrev != NULL) | |
236 | pPrev->pNext = pNode->pNext; | |
237 | ||
ec278fa2 | 238 | /* return this queue entry to timerQFreeList. */ |
ca97b838 BZ |
239 | pNode->pNext = pAd->TimerQ.pQPollFreeList; |
240 | pAd->TimerQ.pQPollFreeList = pNode; | |
241 | } | |
242 | } | |
243 | RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags); | |
244 | ||
245 | return TRUE; | |
246 | } | |
247 | ||
96b3c83d | 248 | void RtmpTimerQExit(RTMP_ADAPTER * pAd) |
ca97b838 BZ |
249 | { |
250 | RTMP_TIMER_TASK_ENTRY *pTimerQ; | |
251 | unsigned long irqFlags; | |
252 | ||
253 | RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags); | |
96b3c83d | 254 | while (pAd->TimerQ.pQHead) { |
ca97b838 BZ |
255 | pTimerQ = pAd->TimerQ.pQHead; |
256 | pAd->TimerQ.pQHead = pTimerQ->pNext; | |
ec278fa2 | 257 | /* remove the timeQ */ |
ca97b838 BZ |
258 | } |
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; | |
265 | #endif | |
266 | RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags); | |
267 | ||
268 | } | |
269 | ||
96b3c83d | 270 | void RtmpTimerQInit(RTMP_ADAPTER * pAd) |
ca97b838 | 271 | { |
96b3c83d | 272 | int i; |
ca97b838 BZ |
273 | RTMP_TIMER_TASK_ENTRY *pQNode, *pEntry; |
274 | unsigned long irqFlags; | |
275 | ||
276 | NdisAllocateSpinLock(&pAd->TimerQLock); | |
277 | ||
278 | NdisZeroMemory(&pAd->TimerQ, sizeof(pAd->TimerQ)); | |
279 | ||
96b3c83d BZ |
280 | os_alloc_mem(pAd, &pAd->TimerQ.pTimerQPoll, |
281 | sizeof(RTMP_TIMER_TASK_ENTRY) * TIMER_QUEUE_SIZE_MAX); | |
282 | if (pAd->TimerQ.pTimerQPoll) { | |
ca97b838 | 283 | pEntry = NULL; |
96b3c83d BZ |
284 | pQNode = (RTMP_TIMER_TASK_ENTRY *) pAd->TimerQ.pTimerQPoll; |
285 | NdisZeroMemory(pAd->TimerQ.pTimerQPoll, | |
286 | sizeof(RTMP_TIMER_TASK_ENTRY) * | |
287 | TIMER_QUEUE_SIZE_MAX); | |
ca97b838 BZ |
288 | |
289 | RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags); | |
96b3c83d | 290 | for (i = 0; i < TIMER_QUEUE_SIZE_MAX; i++) { |
ca97b838 BZ |
291 | pQNode->pNext = pEntry; |
292 | pEntry = pQNode; | |
293 | pQNode++; | |
294 | } | |
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); | |
300 | } | |
301 | } | |
ec278fa2 | 302 | #endif /* RTMP_TIMER_TASK_SUPPORT // */ |