linux/drivers/staging/rt3090/common/rtmp_timer.c
<<
>>
Prefs
   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
  44BUILD_TIMER_FUNCTION(MlmePeriodicExec);
  45//BUILD_TIMER_FUNCTION(MlmeRssiReportExec);
  46BUILD_TIMER_FUNCTION(AsicRxAntEvalTimeout);
  47BUILD_TIMER_FUNCTION(APSDPeriodicExec);
  48BUILD_TIMER_FUNCTION(AsicRfTuningExec);
  49
  50
  51#ifdef CONFIG_STA_SUPPORT
  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 QOS_DLS_SUPPORT
  66BUILD_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)
  75extern void LedCtrlMain(
  76        IN PVOID SystemSpecific1,
  77        IN PVOID FunctionContext,
  78        IN PVOID SystemSpecific2,
  79        IN PVOID SystemSpecific3);
  80BUILD_TIMER_FUNCTION(LedCtrlMain);
  81#endif
  82
  83
  84#ifdef RTMP_TIMER_TASK_SUPPORT
  85static 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
 151INT 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
 190RTMP_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
 232BOOLEAN 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
 272void 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
 296void 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 //
 328
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.