fa77f5d26c73c53f5f4774b7245793517f57c694
[firefly-linux-kernel-4.4.55.git] / drivers / staging / rt2860 / common / rtmp_timer.c
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 #ifdef RTMP_MAC_USB
50 BUILD_TIMER_FUNCTION(BeaconUpdateExec);
51 #endif // RTMP_MAC_USB //
52
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);
62 #ifdef RTMP_MAC_PCI
63 BUILD_TIMER_FUNCTION(PsPollWakeExec);
64 BUILD_TIMER_FUNCTION(RadioOnExec);
65 #endif // RTMP_MAC_PCI //
66 #ifdef RTMP_MAC_USB
67 BUILD_TIMER_FUNCTION(RtmpUsbStaAsicForceWakeupTimeout);
68 #endif // RTMP_MAC_USB //
69
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);
77 #endif
78
79
80 #ifdef RTMP_TIMER_TASK_SUPPORT
81 static void RtmpTimerQHandle(RTMP_ADAPTER *pAd)
82 {
83 #ifndef KTHREAD_SUPPORT
84         int status;
85 #endif
86         RALINK_TIMER_STRUCT     *pTimer;
87         RTMP_TIMER_TASK_ENTRY   *pEntry;
88         unsigned long   irqFlag;
89         RTMP_OS_TASK *pTask;
90
91
92         pTask = &pAd->timerTask;
93         while(!pTask->task_killed)
94         {
95                 pTimer = NULL;
96
97 #ifdef KTHREAD_SUPPORT
98                 RTMP_WAIT_EVENT_INTERRUPTIBLE(pAd, pTask);
99 #else
100                 RTMP_SEM_EVENT_WAIT(&(pTask->taskSema), status);
101 #endif
102
103                 if (pAd->TimerQ.status == RTMP_TASK_STAT_STOPED)
104                         break;
105
106                 // event happened.
107                 while(pAd->TimerQ.pQHead)
108                 {
109                         RTMP_INT_LOCK(&pAd->TimerQLock, irqFlag);
110                         pEntry = pAd->TimerQ.pQHead;
111                         if (pEntry)
112                         {
113                                 pTimer = pEntry->pRaTimer;
114
115                                 // update pQHead
116                                 pAd->TimerQ.pQHead = pEntry->pNext;
117                                 if (pEntry == pAd->TimerQ.pQTail)
118                                         pAd->TimerQ.pQTail = NULL;
119
120                                 // return this queue entry to timerQFreeList.
121                                 pEntry->pNext = pAd->TimerQ.pQPollFreeList;
122                                 pAd->TimerQ.pQPollFreeList = pEntry;
123                         }
124                         RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlag);
125
126                         if (pTimer)
127                         {
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);
132                         }
133                 }
134
135 #ifndef KTHREAD_SUPPORT
136                 if (status != 0)
137                 {
138                         pAd->TimerQ.status = RTMP_TASK_STAT_STOPED;
139                         RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
140                         break;
141                 }
142 #endif
143         }
144 }
145
146
147 INT RtmpTimerQThread(
148         IN OUT PVOID Context)
149 {
150         RTMP_OS_TASK    *pTask;
151         PRTMP_ADAPTER   pAd;
152
153
154         pTask = (RTMP_OS_TASK *)Context;
155         pAd = (PRTMP_ADAPTER)pTask->priv;
156
157         RtmpOSTaskCustomize(pTask);
158
159         RtmpTimerQHandle(pAd);
160
161         DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__func__));
162 #ifndef KTHREAD_SUPPORT
163         pTask->taskPID = THREAD_PID_INIT_VALUE;
164 #endif
165         /* notify the exit routine that we're actually exiting now
166          *
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
171          * case.
172          *
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().
178          */
179         RtmpOSTaskNotifyToExit(pTask);
180
181         return 0;
182
183 }
184
185
186 RTMP_TIMER_TASK_ENTRY *RtmpTimerQInsert(
187         IN RTMP_ADAPTER *pAd,
188         IN RALINK_TIMER_STRUCT *pTimer)
189 {
190         RTMP_TIMER_TASK_ENTRY *pQNode = NULL, *pQTail;
191         unsigned long irqFlags;
192         RTMP_OS_TASK    *pTask = &pAd->timerTask;
193
194         RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags);
195         if (pAd->TimerQ.status & RTMP_TASK_CAN_DO_INSERT)
196         {
197                 if(pAd->TimerQ.pQPollFreeList)
198                 {
199                         pQNode = pAd->TimerQ.pQPollFreeList;
200                         pAd->TimerQ.pQPollFreeList = pQNode->pNext;
201
202                         pQNode->pRaTimer = pTimer;
203                         pQNode->pNext = NULL;
204
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;
211                 }
212         }
213         RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags);
214
215         if (pQNode)
216         {
217 #ifdef KTHREAD_SUPPORT
218                 WAKE_UP(pTask);
219 #else
220                 RTMP_SEM_EVENT_UP(&pTask->taskSema);
221 #endif
222         }
223
224         return pQNode;
225 }
226
227
228 BOOLEAN RtmpTimerQRemove(
229         IN RTMP_ADAPTER *pAd,
230         IN RALINK_TIMER_STRUCT *pTimer)
231 {
232         RTMP_TIMER_TASK_ENTRY *pNode, *pPrev = NULL;
233         unsigned long irqFlags;
234
235         RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags);
236         if (pAd->TimerQ.status >= RTMP_TASK_STAT_INITED)
237         {
238                 pNode = pAd->TimerQ.pQHead;
239                 while (pNode)
240                 {
241                         if (pNode->pRaTimer == pTimer)
242                                 break;
243                         pPrev = pNode;
244                         pNode = pNode->pNext;
245                 }
246
247                 // Now move it to freeList queue.
248                 if (pNode)
249                 {
250                         if (pNode == pAd->TimerQ.pQHead)
251                                 pAd->TimerQ.pQHead = pNode->pNext;
252                         if (pNode == pAd->TimerQ.pQTail)
253                                 pAd->TimerQ.pQTail = pPrev;
254                         if (pPrev != NULL)
255                                 pPrev->pNext = pNode->pNext;
256
257                         // return this queue entry to timerQFreeList.
258                         pNode->pNext = pAd->TimerQ.pQPollFreeList;
259                         pAd->TimerQ.pQPollFreeList = pNode;
260                 }
261         }
262         RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags);
263
264         return TRUE;
265 }
266
267
268 void RtmpTimerQExit(RTMP_ADAPTER *pAd)
269 {
270         RTMP_TIMER_TASK_ENTRY *pTimerQ;
271         unsigned long irqFlags;
272
273         RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags);
274         while (pAd->TimerQ.pQHead)
275         {
276                 pTimerQ = pAd->TimerQ.pQHead;
277                 pAd->TimerQ.pQHead = pTimerQ->pNext;
278                 // remove the timeQ
279         }
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;
286 #endif
287         RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags);
288
289 }
290
291
292 void RtmpTimerQInit(RTMP_ADAPTER *pAd)
293 {
294         int     i;
295         RTMP_TIMER_TASK_ENTRY *pQNode, *pEntry;
296         unsigned long irqFlags;
297
298         NdisAllocateSpinLock(&pAd->TimerQLock);
299
300         NdisZeroMemory(&pAd->TimerQ, sizeof(pAd->TimerQ));
301
302         os_alloc_mem(pAd, &pAd->TimerQ.pTimerQPoll, sizeof(RTMP_TIMER_TASK_ENTRY) * TIMER_QUEUE_SIZE_MAX);
303         if (pAd->TimerQ.pTimerQPoll)
304         {
305                 pEntry = NULL;
306                 pQNode = (RTMP_TIMER_TASK_ENTRY *)pAd->TimerQ.pTimerQPoll;
307                 NdisZeroMemory(pAd->TimerQ.pTimerQPoll, sizeof(RTMP_TIMER_TASK_ENTRY) * TIMER_QUEUE_SIZE_MAX);
308
309                 RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags);
310                 for (i = 0 ;i <TIMER_QUEUE_SIZE_MAX; i++)
311                 {
312                         pQNode->pNext = pEntry;
313                         pEntry = pQNode;
314                         pQNode++;
315                 }
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);
321         }
322 }
323 #endif // RTMP_TIMER_TASK_SUPPORT //