• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/drivers/staging/rt2860/common/
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
43BUILD_TIMER_FUNCTION(MlmePeriodicExec);
44/*BUILD_TIMER_FUNCTION(MlmeRssiReportExec); */
45BUILD_TIMER_FUNCTION(AsicRxAntEvalTimeout);
46BUILD_TIMER_FUNCTION(APSDPeriodicExec);
47BUILD_TIMER_FUNCTION(AsicRfTuningExec);
48#ifdef RTMP_MAC_USB
49BUILD_TIMER_FUNCTION(BeaconUpdateExec);
50#endif /* RTMP_MAC_USB // */
51
52BUILD_TIMER_FUNCTION(BeaconTimeout);
53BUILD_TIMER_FUNCTION(ScanTimeout);
54BUILD_TIMER_FUNCTION(AuthTimeout);
55BUILD_TIMER_FUNCTION(AssocTimeout);
56BUILD_TIMER_FUNCTION(ReassocTimeout);
57BUILD_TIMER_FUNCTION(DisassocTimeout);
58BUILD_TIMER_FUNCTION(LinkDownExec);
59BUILD_TIMER_FUNCTION(StaQuickResponeForRateUpExec);
60BUILD_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc);
61#ifdef RTMP_MAC_PCI
62BUILD_TIMER_FUNCTION(PsPollWakeExec);
63BUILD_TIMER_FUNCTION(RadioOnExec);
64#endif /* RTMP_MAC_PCI // */
65#ifdef RTMP_MAC_USB
66BUILD_TIMER_FUNCTION(RtmpUsbStaAsicForceWakeupTimeout);
67#endif /* RTMP_MAC_USB // */
68
69#if defined(AP_LED) || defined(STA_LED)
70extern void LedCtrlMain(void *SystemSpecific1,
71			void *FunctionContext,
72			void *SystemSpecific2, void *SystemSpecific3);
73BUILD_TIMER_FUNCTION(LedCtrlMain);
74#endif
75
76#ifdef RTMP_TIMER_TASK_SUPPORT
77static void RtmpTimerQHandle(struct rt_rtmp_adapter *pAd)
78{
79#ifndef KTHREAD_SUPPORT
80	int status;
81#endif
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;
86
87	pTask = &pAd->timerTask;
88	while (!pTask->task_killed) {
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
100		/* event happened. */
101		while (pAd->TimerQ.pQHead) {
102			RTMP_INT_LOCK(&pAd->TimerQLock, irqFlag);
103			pEntry = pAd->TimerQ.pQHead;
104			if (pEntry) {
105				pTimer = pEntry->pRaTimer;
106
107				/* update pQHead */
108				pAd->TimerQ.pQHead = pEntry->pNext;
109				if (pEntry == pAd->TimerQ.pQTail)
110					pAd->TimerQ.pQTail = NULL;
111
112				/* return this queue entry to timerQFreeList. */
113				pEntry->pNext = pAd->TimerQ.pQPollFreeList;
114				pAd->TimerQ.pQPollFreeList = pEntry;
115			}
116			RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlag);
117
118			if (pTimer) {
119				if ((pTimer->handle != NULL)
120				    && (!pAd->PM_FlgSuspend))
121					pTimer->handle(NULL,
122						       (void *)pTimer->cookie,
123						       NULL, pTimer);
124				if ((pTimer->Repeat)
125				    && (pTimer->State == FALSE))
126					RTMP_OS_Add_Timer(&pTimer->TimerObj,
127							  pTimer->TimerValue);
128			}
129		}
130
131#ifndef KTHREAD_SUPPORT
132		if (status != 0) {
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
141int RtmpTimerQThread(IN void *Context)
142{
143	struct rt_rtmp_os_task *pTask;
144	struct rt_rtmp_adapter *pAd;
145
146	pTask = Context;
147	pAd = pTask->priv;
148
149	RtmpOSTaskCustomize(pTask);
150
151	RtmpTimerQHandle(pAd);
152
153	DBGPRINT(RT_DEBUG_TRACE, ("<---%s\n", __func__));
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
177struct rt_rtmp_timer_task_entry *RtmpTimerQInsert(struct rt_rtmp_adapter *pAd,
178					struct rt_ralink_timer *pTimer)
179{
180	struct rt_rtmp_timer_task_entry *pQNode = NULL, *pQTail;
181	unsigned long irqFlags;
182	struct rt_rtmp_os_task *pTask = &pAd->timerTask;
183
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;
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
203	if (pQNode) {
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
214BOOLEAN RtmpTimerQRemove(struct rt_rtmp_adapter *pAd, struct rt_ralink_timer *pTimer)
215{
216	struct rt_rtmp_timer_task_entry *pNode, *pPrev = NULL;
217	unsigned long irqFlags;
218
219	RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags);
220	if (pAd->TimerQ.status >= RTMP_TASK_STAT_INITED) {
221		pNode = pAd->TimerQ.pQHead;
222		while (pNode) {
223			if (pNode->pRaTimer == pTimer)
224				break;
225			pPrev = pNode;
226			pNode = pNode->pNext;
227		}
228
229		/* Now move it to freeList queue. */
230		if (pNode) {
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
238			/* return this queue entry to timerQFreeList. */
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
248void RtmpTimerQExit(struct rt_rtmp_adapter *pAd)
249{
250	struct rt_rtmp_timer_task_entry *pTimerQ;
251	unsigned long irqFlags;
252
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 */
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
270void RtmpTimerQInit(struct rt_rtmp_adapter *pAd)
271{
272	int i;
273	struct rt_rtmp_timer_task_entry *pQNode, *pEntry;
274	unsigned long irqFlags;
275
276	NdisAllocateSpinLock(&pAd->TimerQLock);
277
278	NdisZeroMemory(&pAd->TimerQ, sizeof(pAd->TimerQ));
279
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) {
283		pEntry = NULL;
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);
288
289		RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags);
290		for (i = 0; i < TIMER_QUEUE_SIZE_MAX; i++) {
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}
302#endif /* RTMP_TIMER_TASK_SUPPORT // */
303