]>
Commit | Line | Data |
---|---|---|
36c7928c 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 | ||
43 | ||
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); | |
49 | ||
50 | ||
51 | #ifdef CONFIG_STA_SUPPORT | |
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); | |
61 | #ifdef RTMP_MAC_PCI | |
62 | BUILD_TIMER_FUNCTION(PsPollWakeExec); | |
63 | BUILD_TIMER_FUNCTION(RadioOnExec); | |
64 | #endif // RTMP_MAC_PCI // | |
65 | #ifdef QOS_DLS_SUPPORT | |
66 | BUILD_TIMER_FUNCTION(DlsTimeoutAction); | |
67 | #endif // QOS_DLS_SUPPORT // | |
68 | ||
69 | ||
70 | #endif // CONFIG_STA_SUPPORT // | |
71 | ||
72 | ||
73 | ||
74 | #if defined(AP_LED) || defined(STA_LED) | |
75 | extern void LedCtrlMain( | |
76 | IN PVOID SystemSpecific1, | |
77 | IN PVOID FunctionContext, | |
78 | IN PVOID SystemSpecific2, | |
79 | IN PVOID SystemSpecific3); | |
80 | BUILD_TIMER_FUNCTION(LedCtrlMain); | |
81 | #endif | |
82 | ||
83 | ||
84 | #ifdef RTMP_TIMER_TASK_SUPPORT | |
85 | static void RtmpTimerQHandle(RTMP_ADAPTER *pAd) | |
86 | { | |
87 | #ifndef KTHREAD_SUPPORT | |
88 | int status; | |
89 | #endif | |
90 | RALINK_TIMER_STRUCT *pTimer; | |
91 | RTMP_TIMER_TASK_ENTRY *pEntry; | |
92 | unsigned long irqFlag; | |
93 | RTMP_OS_TASK *pTask; | |
94 | ||
95 | ||
96 | pTask = &pAd->timerTask; | |
97 | while(!pTask->task_killed) | |
98 | { | |
99 | pTimer = NULL; | |
100 | ||
101 | #ifdef KTHREAD_SUPPORT | |
102 | RTMP_WAIT_EVENT_INTERRUPTIBLE(pAd, pTask); | |
103 | #else | |
104 | RTMP_SEM_EVENT_WAIT(&(pTask->taskSema), status); | |
105 | #endif | |
106 | ||
107 | if (pAd->TimerQ.status == RTMP_TASK_STAT_STOPED) | |
108 | break; | |
109 | ||
110 | // event happened. | |
111 | while(pAd->TimerQ.pQHead) | |
112 | { | |
113 | RTMP_INT_LOCK(&pAd->TimerQLock, irqFlag); | |
114 | pEntry = pAd->TimerQ.pQHead; | |
115 | if (pEntry) | |
116 | { | |
117 | pTimer = pEntry->pRaTimer; | |
118 | ||
119 | // update pQHead | |
120 | pAd->TimerQ.pQHead = pEntry->pNext; | |
121 | if (pEntry == pAd->TimerQ.pQTail) | |
122 | pAd->TimerQ.pQTail = NULL; | |
123 | ||
124 | // return this queue entry to timerQFreeList. | |
125 | pEntry->pNext = pAd->TimerQ.pQPollFreeList; | |
126 | pAd->TimerQ.pQPollFreeList = pEntry; | |
127 | } | |
128 | RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlag); | |
129 | ||
130 | if (pTimer) | |
131 | { | |
132 | if ((pTimer->handle != NULL) && (!pAd->PM_FlgSuspend)) | |
133 | pTimer->handle(NULL, (PVOID) pTimer->cookie, NULL, pTimer); | |
134 | if ((pTimer->Repeat) && (pTimer->State == FALSE)) | |
135 | RTMP_OS_Add_Timer(&pTimer->TimerObj, pTimer->TimerValue); | |
136 | } | |
137 | } | |
138 | ||
139 | #ifndef KTHREAD_SUPPORT | |
140 | if (status != 0) | |
141 | { | |
142 | pAd->TimerQ.status = RTMP_TASK_STAT_STOPED; | |
143 | RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); | |
144 | break; | |
145 | } | |
146 | #endif | |
147 | } | |
148 | } | |
149 | ||
150 | ||
151 | INT RtmpTimerQThread( | |
152 | IN OUT PVOID Context) | |
153 | { | |
154 | RTMP_OS_TASK *pTask; | |
155 | PRTMP_ADAPTER pAd; | |
156 | ||
157 | ||
158 | pTask = (RTMP_OS_TASK *)Context; | |
159 | pAd = (PRTMP_ADAPTER)pTask->priv; | |
160 | ||
161 | RtmpOSTaskCustomize(pTask); | |
162 | ||
163 | RtmpTimerQHandle(pAd); | |
164 | ||
165 | DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__FUNCTION__)); | |
166 | #ifndef KTHREAD_SUPPORT | |
167 | pTask->taskPID = THREAD_PID_INIT_VALUE; | |
168 | #endif | |
169 | /* notify the exit routine that we're actually exiting now | |
170 | * | |
171 | * complete()/wait_for_completion() is similar to up()/down(), | |
172 | * except that complete() is safe in the case where the structure | |
173 | * is getting deleted in a parallel mode of execution (i.e. just | |
174 | * after the down() -- that's necessary for the thread-shutdown | |
175 | * case. | |
176 | * | |
177 | * complete_and_exit() goes even further than this -- it is safe in | |
178 | * the case that the thread of the caller is going away (not just | |
179 | * the structure) -- this is necessary for the module-remove case. | |
180 | * This is important in preemption kernels, which transfer the flow | |
181 | * of execution immediately upon a complete(). | |
182 | */ | |
183 | RtmpOSTaskNotifyToExit(pTask); | |
184 | ||
185 | return 0; | |
186 | ||
187 | } | |
188 | ||
189 | ||
190 | RTMP_TIMER_TASK_ENTRY *RtmpTimerQInsert( | |
191 | IN RTMP_ADAPTER *pAd, | |
192 | IN RALINK_TIMER_STRUCT *pTimer) | |
193 | { | |
194 | RTMP_TIMER_TASK_ENTRY *pQNode = NULL, *pQTail; | |
195 | unsigned long irqFlags; | |
196 | RTMP_OS_TASK *pTask = &pAd->timerTask; | |
197 | ||
198 | RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags); | |
199 | if (pAd->TimerQ.status & RTMP_TASK_CAN_DO_INSERT) | |
200 | { | |
201 | if(pAd->TimerQ.pQPollFreeList) | |
202 | { | |
203 | pQNode = pAd->TimerQ.pQPollFreeList; | |
204 | pAd->TimerQ.pQPollFreeList = pQNode->pNext; | |
205 | ||
206 | pQNode->pRaTimer = pTimer; | |
207 | pQNode->pNext = NULL; | |
208 | ||
209 | pQTail = pAd->TimerQ.pQTail; | |
210 | if (pAd->TimerQ.pQTail != NULL) | |
211 | pQTail->pNext = pQNode; | |
212 | pAd->TimerQ.pQTail = pQNode; | |
213 | if (pAd->TimerQ.pQHead == NULL) | |
214 | pAd->TimerQ.pQHead = pQNode; | |
215 | } | |
216 | } | |
217 | RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags); | |
218 | ||
219 | if (pQNode) | |
220 | { | |
221 | #ifdef KTHREAD_SUPPORT | |
222 | WAKE_UP(pTask); | |
223 | #else | |
224 | RTMP_SEM_EVENT_UP(&pTask->taskSema); | |
225 | #endif | |
226 | } | |
227 | ||
228 | return pQNode; | |
229 | } | |
230 | ||
231 | ||
232 | BOOLEAN RtmpTimerQRemove( | |
233 | IN RTMP_ADAPTER *pAd, | |
234 | IN RALINK_TIMER_STRUCT *pTimer) | |
235 | { | |
236 | RTMP_TIMER_TASK_ENTRY *pNode, *pPrev = NULL; | |
237 | unsigned long irqFlags; | |
238 | ||
239 | RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags); | |
240 | if (pAd->TimerQ.status >= RTMP_TASK_STAT_INITED) | |
241 | { | |
242 | pNode = pAd->TimerQ.pQHead; | |
243 | while (pNode) | |
244 | { | |
245 | if (pNode->pRaTimer == pTimer) | |
246 | break; | |
247 | pPrev = pNode; | |
248 | pNode = pNode->pNext; | |
249 | } | |
250 | ||
251 | // Now move it to freeList queue. | |
252 | if (pNode) | |
253 | { | |
254 | if (pNode == pAd->TimerQ.pQHead) | |
255 | pAd->TimerQ.pQHead = pNode->pNext; | |
256 | if (pNode == pAd->TimerQ.pQTail) | |
257 | pAd->TimerQ.pQTail = pPrev; | |
258 | if (pPrev != NULL) | |
259 | pPrev->pNext = pNode->pNext; | |
260 | ||
261 | // return this queue entry to timerQFreeList. | |
262 | pNode->pNext = pAd->TimerQ.pQPollFreeList; | |
263 | pAd->TimerQ.pQPollFreeList = pNode; | |
264 | } | |
265 | } | |
266 | RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags); | |
267 | ||
268 | return TRUE; | |
269 | } | |
270 | ||
271 | ||
272 | void RtmpTimerQExit(RTMP_ADAPTER *pAd) | |
273 | { | |
274 | RTMP_TIMER_TASK_ENTRY *pTimerQ; | |
275 | unsigned long irqFlags; | |
276 | ||
277 | RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags); | |
278 | while (pAd->TimerQ.pQHead) | |
279 | { | |
280 | pTimerQ = pAd->TimerQ.pQHead; | |
281 | pAd->TimerQ.pQHead = pTimerQ->pNext; | |
282 | // remove the timeQ | |
283 | } | |
284 | pAd->TimerQ.pQPollFreeList = NULL; | |
285 | os_free_mem(pAd, pAd->TimerQ.pTimerQPoll); | |
286 | pAd->TimerQ.pQTail = NULL; | |
287 | pAd->TimerQ.pQHead = NULL; | |
288 | #ifndef KTHREAD_SUPPORT | |
289 | pAd->TimerQ.status = RTMP_TASK_STAT_STOPED; | |
290 | #endif | |
291 | RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags); | |
292 | ||
293 | } | |
294 | ||
295 | ||
296 | void RtmpTimerQInit(RTMP_ADAPTER *pAd) | |
297 | { | |
298 | int i; | |
299 | RTMP_TIMER_TASK_ENTRY *pQNode, *pEntry; | |
300 | unsigned long irqFlags; | |
301 | ||
302 | NdisAllocateSpinLock(&pAd->TimerQLock); | |
303 | ||
304 | NdisZeroMemory(&pAd->TimerQ, sizeof(pAd->TimerQ)); | |
305 | ||
306 | os_alloc_mem(pAd, &pAd->TimerQ.pTimerQPoll, sizeof(RTMP_TIMER_TASK_ENTRY) * TIMER_QUEUE_SIZE_MAX); | |
307 | if (pAd->TimerQ.pTimerQPoll) | |
308 | { | |
309 | pEntry = NULL; | |
310 | pQNode = (RTMP_TIMER_TASK_ENTRY *)pAd->TimerQ.pTimerQPoll; | |
311 | NdisZeroMemory(pAd->TimerQ.pTimerQPoll, sizeof(RTMP_TIMER_TASK_ENTRY) * TIMER_QUEUE_SIZE_MAX); | |
312 | ||
313 | RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags); | |
314 | for (i = 0 ;i <TIMER_QUEUE_SIZE_MAX; i++) | |
315 | { | |
316 | pQNode->pNext = pEntry; | |
317 | pEntry = pQNode; | |
318 | pQNode++; | |
319 | } | |
320 | pAd->TimerQ.pQPollFreeList = pEntry; | |
321 | pAd->TimerQ.pQHead = NULL; | |
322 | pAd->TimerQ.pQTail = NULL; | |
323 | pAd->TimerQ.status = RTMP_TASK_STAT_INITED; | |
324 | RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags); | |
325 | } | |
326 | } | |
327 | #endif // RTMP_TIMER_TASK_SUPPORT // |