blob: 05b557abbb552c9094b608c0ff46846a6d0bde79 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/**=========================================================================
43
44 \file vos_timer.c
45
46 \brief virtual Operating System Servies (vOS)
47
48 Definitions for vOSS Timer services
49
50 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
51
52 Qualcomm Confidential and Proprietary.
53
54 ========================================================================*/
55
56/* $Header$ */
57
58/*--------------------------------------------------------------------------
59 Include Files
60 ------------------------------------------------------------------------*/
61#include <vos_timer.h>
62#include <vos_lock.h>
63#include <vos_api.h>
64#include "wlan_qct_sys.h"
65#include "vos_sched.h"
66
67/*--------------------------------------------------------------------------
68 Preprocessor definitions and constants
69 ------------------------------------------------------------------------*/
70
71#define LINUX_TIMER_COOKIE 0x12341234
72#define LINUX_INVALID_TIMER_COOKIE 0xfeedface
73#define TMR_INVALID_ID ( 0 )
74
75/*--------------------------------------------------------------------------
76 Type declarations
77 ------------------------------------------------------------------------*/
78
79/*----------------------------------------------------------------------------
80 * Static Variable Definitions
81 * -------------------------------------------------------------------------*/
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -070082static unsigned int persistentTimerCount;
Jeff Johnson295189b2012-06-20 16:38:30 -070083static vos_lock_t persistentTimerCountLock;
84// static sleep_okts_handle sleepClientHandle;
85
86/*-------------------------------------------------------------------------
87 Function declarations and documenation
88 ------------------------------------------------------------------------*/
89// TBD: Need to add code for deferred timers implementation
90
91// clean up timer states after it has been deactivated
92// check and try to allow sleep after a timer has been stopped or expired
93static void tryAllowingSleep( VOS_TIMER_TYPE type )
94{
95 if ( VOS_TIMER_TYPE_WAKE_APPS == type )
96 {
97 // vos_lock_acquire( &persistentTimerCountLock );
98 persistentTimerCount--;
99 if ( 0 == persistentTimerCount )
100 {
101 // since the number of persistent timers has decreased from 1 to 0,
102 // the timer should allow sleep
103 //sleep_assert_okts( sleepClientHandle );
104 }
105 //vos_lock_release( &persistentTimerCountLock );
106 }
107}
108
109
110/*----------------------------------------------------------------------------
111
112 \brief vos_linux_timer_callback() - internal vos entry point which is
113 called when the timer interval expires
114
115 This function in turn calls the vOS client callback and changes the
116 state of the timer from running (ACTIVE) to expired (INIT).
117
118
119 \param uTimerID - return value of the timeSetEvent() from the
120 vos_timer_start() API which
121
122 \param dwUser - this is supplied by the fourth parameter of the timeSetEvent()
123 which is the timer structure being passed as the userData
124
125 \param uMsg - Reserved / Not Used
126
127 \param dw1 - Reserved / Not Used
128
129 \param dw2 - Reserved / Not Used
130
131 \return nothing
132 --------------------------------------------------------------------------*/
133
134static void vos_linux_timer_callback ( v_U32_t data )
135{
136 vos_timer_t *timer = ( vos_timer_t *)data;
137 vos_msg_t msg;
138 VOS_STATUS vStatus;
139 unsigned long flags;
140
141 vos_timer_callback_t callback=NULL;
142 v_PVOID_t userData=NULL;
143 int threadId;
144 VOS_TIMER_TYPE type=VOS_TIMER_TYPE_SW;
145
146 VOS_ASSERT(timer);
147
148 if (timer == NULL)
149 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700150 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s Null pointer passed in!",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700151 return;
152 }
153
154 threadId = timer->platformInfo.threadID;
155 spin_lock_irqsave( &timer->platformInfo.spinlock,flags );
156
157 switch ( timer->state )
158 {
159 case VOS_TIMER_STATE_STARTING:
160 // we are in this state because someone just started the timer, MM timer
161 // got started and expired, but the time content have not bee updated
162 // this is a rare race condition!
163 timer->state = VOS_TIMER_STATE_STOPPED;
164 vStatus = VOS_STATUS_E_ALREADY;
165 break;
166 case VOS_TIMER_STATE_STOPPED:
167 vStatus = VOS_STATUS_E_ALREADY;
168 break;
169 case VOS_TIMER_STATE_UNUSED:
170 vStatus = VOS_STATUS_E_EXISTS;
171 break;
172 case VOS_TIMER_STATE_RUNNING:
173 // need to go to stop state here because the call-back function may restart
174 // timer (to emulate periodic timer)
175 timer->state = VOS_TIMER_STATE_STOPPED;
176 // copy the relevant timer information to local variables;
177 // once we exist from this critical section, the timer content may be modified
178 // by other tasks
179 callback = timer->callback;
180 userData = timer->userData;
181 threadId = timer->platformInfo.threadID;
182 type = timer->type;
183 vStatus = VOS_STATUS_SUCCESS;
184 break;
185 default:
186 VOS_ASSERT(0);
187 vStatus = VOS_STATUS_E_FAULT;
188 break;
189 }
190
191 spin_unlock_irqrestore( &timer->platformInfo.spinlock,flags );
192
193 if ( VOS_STATUS_SUCCESS != vStatus )
194 {
195 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
196 "TIMER callback called in a wrong state=%d", timer->state);
197 return;
198 }
199
200 tryAllowingSleep( type );
201
202 VOS_ASSERT( callback );
203
204 // If timer has expired then call vos_client specific callback
205 if ( vos_sched_is_tx_thread( threadId ) )
206 {
207 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
208 "TIMER callback: running on TX thread");
209
210 //Serialize to the Tx thread
211 sysBuildMessageHeader( SYS_MSG_ID_TX_TIMER, &msg );
212 msg.bodyptr = callback;
213 msg.bodyval = (v_U32_t)userData;
214
215 if(vos_tx_mq_serialize( VOS_MQ_ID_SYS, &msg ) == VOS_STATUS_SUCCESS)
216 return;
217 }
218#ifdef FEATURE_WLAN_INTEGRATED_SOC
219 else if ( vos_sched_is_rx_thread( threadId ) )
220 {
221 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
222 "TIMER callback: running on RX thread");
223
224 //Serialize to the Rx thread
225 sysBuildMessageHeader( SYS_MSG_ID_RX_TIMER, &msg );
226 msg.bodyptr = callback;
227 msg.bodyval = (v_U32_t)userData;
228
229 if(vos_rx_mq_serialize( VOS_MQ_ID_SYS, &msg ) == VOS_STATUS_SUCCESS)
230 return;
231 }
232#endif
233 else
234 {
235 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
236 "TIMER callback: running on MC thread");
237
238 // Serialize to the MC thread
239 sysBuildMessageHeader( SYS_MSG_ID_MC_TIMER, &msg );
240 msg.bodyptr = callback;
241 msg.bodyval = (v_U32_t)userData;
242
243 if(vos_mq_post_message( VOS_MQ_ID_SYS, &msg ) == VOS_STATUS_SUCCESS)
244 return;
245 }
246
247 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
248 "%s: Could not enqueue timer to any queue", __func__);
249 VOS_ASSERT(0);
250}
251
252/*---------------------------------------------------------------------------
253
254 \brief vos_timer_getCurrentState() - Get the current state of the timer
255
256 \param pTimer - the timer object
257
258 \return timer state
259
260 \sa
261
262---------------------------------------------------------------------------*/
263VOS_TIMER_STATE vos_timer_getCurrentState( vos_timer_t *pTimer )
264{
265 if ( NULL == pTimer )
266 {
267 VOS_ASSERT(0);
268 return VOS_TIMER_STATE_UNUSED;
269 }
270
271 switch ( pTimer->state )
272 {
273 case VOS_TIMER_STATE_STOPPED:
274 case VOS_TIMER_STATE_STARTING:
275 case VOS_TIMER_STATE_RUNNING:
276 case VOS_TIMER_STATE_UNUSED:
277 return pTimer->state;
278 default:
279 VOS_ASSERT(0);
280 return VOS_TIMER_STATE_UNUSED;
281 }
282}
283
284/*----------------------------------------------------------------------------
285
286 \brief vos_timer_module_init() - Initializes a vOSS timer module.
287
288 This API initializes the VOSS timer module. This needs to be called
289 exactly once prior to using any VOSS timers.
290
291 \sa
292
293 --------------------------------------------------------------------------*/
294
295void vos_timer_module_init( void )
296{
297 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
298 "Initializing the VOSS timer module");
299 vos_lock_init( &persistentTimerCountLock );
300}
301
302#ifdef TIMER_MANAGER
303#include "wlan_hdd_dp_utils.h"
304
305hdd_list_t vosTimerList;
306
307static void vos_timer_clean(void);
308
309void vos_timer_manager_init()
310{
311 /* Initalizing the list with maximum size of 60000 */
312 hdd_list_init(&vosTimerList, 1000);
313 return;
314}
315
316static void vos_timer_clean()
317{
318 v_SIZE_t listSize;
319 unsigned long flags;
320
321 hdd_list_size(&vosTimerList, &listSize);
322
323 if (listSize)
324 {
325 hdd_list_node_t* pNode;
326 VOS_STATUS vosStatus;
327
328 timer_node_t *ptimerNode;
329 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
330 "%s: List is not Empty. listSize %d ",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700331 __func__, (int)listSize);
Jeff Johnson295189b2012-06-20 16:38:30 -0700332
333 do
334 {
335 spin_lock_irqsave(&vosTimerList.lock, flags);
336 vosStatus = hdd_list_remove_front(&vosTimerList, &pNode);
337 spin_unlock_irqrestore(&vosTimerList.lock, flags);
338 if (VOS_STATUS_SUCCESS == vosStatus)
339 {
340 ptimerNode = (timer_node_t*)pNode;
341 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
342 "Timer Leak@ File %s, @Line %d",
343 ptimerNode->fileName, (int)ptimerNode->lineNum);
344
345 vos_mem_free(ptimerNode);
346 }
347 } while (vosStatus == VOS_STATUS_SUCCESS);
348 }
349}
350
351void vos_timer_exit()
352{
353 vos_timer_clean();
354 hdd_list_destroy(&vosTimerList);
355}
356#endif
357
358/*--------------------------------------------------------------------------
359
360 \brief vos_timer_init() - Initialize a vOSS timer.
361
362 This API initializes a vOS Timer object.
363
364 The \a vos_timer_init() initializes a vOS Timer object. A timer must be
365 initialized by calling vos_timer_initialize() before it may be used in
366 any other timer functions.
367
368 Attempting to initialize timer that is already initialized results in
369 a failure. A destroyed timer object can be re-initialized with a call to
370 \a vos_timer_init(). The results of otherwise referencing the object
371 after it has been destroyed are undefined.
372
373 Calls to vOSS timer functions to manipulate the timer such
374 as vos_timer_set() will fail if the timer is not initialized or has
375 been destroyed. Therefore, don't use the timer after it has been
376 destroyed until it has been re-initialized.
377
378 All callback will be executed within the VOS main thread unless it is
379 initialized from the Tx thread flow, in which case it will be executed
380 within the tx thread flow.
381
382 \param timer - pointer to the opaque timer object to initialize
383
384 \param timerType - specifies the type of timer. We have two different
385 timer types.
386 <ol>
387 <li> VOS_TIMER_TYPE_SW - Pure software timer. The Apps processor
388 may not be awoken when this timer expires.
389 <li> VOS_TIMER_TYPE_WAKE_APPS - The Apps processor will be awoken
390 from power collapse when this type of timer expires.
391 </ol>
392
393 \param callback - the callback function to be called when the timer
394 expires.
395
396 \param userData - a user data (or context) that is returned to the
397 callback function as a parameter when the timer expires.
398
399 \return VOS_STATUS_SUCCESS - timer was successfully initialized and
400 is ready to be used.
401
402 VOS_STATUS_E_RESOURCES - System resources (other than memory)
403 are unavailable to initialize the timer
404
405 VOS_STATUS_E_NOMEM - insufficient memory exists to initialize
406 the timer
407
408 VOS_STATUS_E_BUSY - The implementation has detected an attempt
409 to initialize the object referenced by timer, a previously
410 initialized but not yet destroyed timer.
411
412 VOS_STATUS_E_FAULT - timer is an invalid pointer.
413 \sa
414
415---------------------------------------------------------------------------*/
416#ifdef TIMER_MANAGER
417VOS_STATUS vos_timer_init_debug( vos_timer_t *timer, VOS_TIMER_TYPE timerType,
418 vos_timer_callback_t callback, v_PVOID_t userData,
419 char* fileName, v_U32_t lineNum )
420{
421 VOS_STATUS vosStatus;
422 unsigned long flags;
423 // Check for invalid pointer
424 if ((timer == NULL) || (callback == NULL))
425 {
426 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700427 "%s: Null params being passed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700428 VOS_ASSERT(0);
429 return VOS_STATUS_E_FAULT;
430 }
431
432 timer->ptimerNode = vos_mem_malloc(sizeof(timer_node_t));
433
434 if(timer->ptimerNode == NULL)
435 {
436 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700437 "%s: Not able to allocate memory for timeNode",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700438 VOS_ASSERT(0);
439 return VOS_STATUS_E_FAULT;
440 }
441
442 vos_mem_set(timer->ptimerNode, sizeof(timer_node_t), 0);
443
444 timer->ptimerNode->fileName = fileName;
445 timer->ptimerNode->lineNum = lineNum;
446 timer->ptimerNode->vosTimer = timer;
447
448 spin_lock_irqsave(&vosTimerList.lock, flags);
449 vosStatus = hdd_list_insert_front(&vosTimerList, &timer->ptimerNode->pNode);
450 spin_unlock_irqrestore(&vosTimerList.lock, flags);
451 if(VOS_STATUS_SUCCESS != vosStatus)
452 {
453 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700454 "%s: Unable to insert node into List vosStatus %d\n", __func__, vosStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -0700455 }
456
457 // set the various members of the timer structure
458 // with arguments passed or with default values
459 spin_lock_init(&timer->platformInfo.spinlock);
460 init_timer(&(timer->platformInfo.Timer));
461 timer->platformInfo.Timer.function = vos_linux_timer_callback;
462 timer->platformInfo.Timer.data = (unsigned long)timer;
463 timer->callback = callback;
464 timer->userData = userData;
465 timer->type = timerType;
466 timer->platformInfo.cookie = LINUX_TIMER_COOKIE;
467 timer->platformInfo.threadID = 0;
468 timer->state = VOS_TIMER_STATE_STOPPED;
469
470 return VOS_STATUS_SUCCESS;
471}
472#else
473VOS_STATUS vos_timer_init( vos_timer_t *timer, VOS_TIMER_TYPE timerType,
474 vos_timer_callback_t callback, v_PVOID_t userData )
475{
476 // Check for invalid pointer
477 if ((timer == NULL) || (callback == NULL))
478 {
479 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700480 "%s: Null params being passed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700481 VOS_ASSERT(0);
482 return VOS_STATUS_E_FAULT;
483 }
484
485 // set the various members of the timer structure
486 // with arguments passed or with default values
487 spin_lock_init(&timer->platformInfo.spinlock);
488 init_timer(&(timer->platformInfo.Timer));
489 timer->platformInfo.Timer.function = vos_linux_timer_callback;
490 timer->platformInfo.Timer.data = (unsigned long)timer;
491 timer->callback = callback;
492 timer->userData = userData;
493 timer->type = timerType;
494 timer->platformInfo.cookie = LINUX_TIMER_COOKIE;
495 timer->platformInfo.threadID = 0;
496 timer->state = VOS_TIMER_STATE_STOPPED;
497
498 return VOS_STATUS_SUCCESS;
499}
500#endif
501
502
503/*---------------------------------------------------------------------------
504
505 \brief vos_timer_destroy() - Destroy a vOSS Timer object
506
507 The \a vos_timer_destroy() function shall destroy the timer object.
508 After a successful return from \a vos_timer_destroy() the timer
509 object becomes, in effect, uninitialized.
510
511 A destroyed timer object can be re-initialized by calling
512 vos_timer_init(). The results of otherwise referencing the object
513 after it has been destroyed are undefined.
514
515 Calls to vOSS timer functions to manipulate the timer, such
516 as vos_timer_set() will fail if the lock is destroyed. Therefore,
517 don't use the timer after it has been destroyed until it has
518 been re-initialized.
519
520 \param timer - the timer object to be destroyed.
521
522 \return VOS_STATUS_SUCCESS - timer was successfully destroyed.
523
524 VOS_STATUS_E_BUSY - The implementation has detected an attempt
525 to destroy the object referenced by timer while it is still
526 still referenced. The timer must be stopped before it can be
527 destroyed.
528
529 VOS_STATUS_E_INVAL - The value specified by timer is invalid.
530
531 VOS_STATUS_E_FAULT - timer is an invalid pointer.
532 \sa
533
534---------------------------------------------------------------------------*/
535#ifdef TIMER_MANAGER
536VOS_STATUS vos_timer_destroy ( vos_timer_t *timer )
537{
538 VOS_STATUS vStatus=VOS_STATUS_SUCCESS;
539 unsigned long flags;
540
541 // Check for invalid pointer
542 if ( NULL == timer )
543 {
544 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700545 "%s: Null timer pointer being passed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700546 VOS_ASSERT(0);
547 return VOS_STATUS_E_FAULT;
548 }
549
550 // Check if timer refers to an uninitialized object
551 if ( LINUX_TIMER_COOKIE != timer->platformInfo.cookie )
552 {
553 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700554 "%s: Cannot destroy uninitialized timer",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700555 return VOS_STATUS_E_INVAL;
556 }
557
558 spin_lock_irqsave(&vosTimerList.lock, flags);
559 vStatus = hdd_list_remove_node(&vosTimerList, &timer->ptimerNode->pNode);
560 spin_unlock_irqrestore(&vosTimerList.lock, flags);
561 if(vStatus != VOS_STATUS_SUCCESS)
562 {
563 VOS_ASSERT(0);
564 return VOS_STATUS_E_INVAL;
565 }
566 vos_mem_free(timer->ptimerNode);
567
568
569 spin_lock_irqsave( &timer->platformInfo.spinlock,flags );
570
571 switch ( timer->state )
572 {
573 case VOS_TIMER_STATE_STARTING:
574 vStatus = VOS_STATUS_E_BUSY;
575 break;
576 case VOS_TIMER_STATE_RUNNING:
577 /* Stop the timer first */
578 del_timer(&(timer->platformInfo.Timer));
579 vStatus = VOS_STATUS_SUCCESS;
580 break;
581 case VOS_TIMER_STATE_STOPPED:
582 vStatus = VOS_STATUS_SUCCESS;
583 break;
584 case VOS_TIMER_STATE_UNUSED:
585 vStatus = VOS_STATUS_E_ALREADY;
586 break;
587 default:
588 vStatus = VOS_STATUS_E_FAULT;
589 break;
590 }
591
592 if ( VOS_STATUS_SUCCESS == vStatus )
593 {
594 timer->platformInfo.cookie = LINUX_INVALID_TIMER_COOKIE;
595 timer->state = VOS_TIMER_STATE_UNUSED;
596 spin_unlock_irqrestore( &timer->platformInfo.spinlock,flags );
597 return vStatus;
598 }
599
600 spin_unlock_irqrestore( &timer->platformInfo.spinlock,flags );
601
602
603 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
604 "%s: Cannot destroy timer in state = %d",__func__, timer->state);
605 VOS_ASSERT(0);
606
607 return vStatus;
608}
609
610#else
611VOS_STATUS vos_timer_destroy ( vos_timer_t *timer )
612{
613 VOS_STATUS vStatus=VOS_STATUS_SUCCESS;
614 unsigned long flags;
615
616 // Check for invalid pointer
617 if ( NULL == timer )
618 {
619 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700620 "%s: Null timer pointer being passed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700621 VOS_ASSERT(0);
622 return VOS_STATUS_E_FAULT;
623 }
624
625 // Check if timer refers to an uninitialized object
626 if ( LINUX_TIMER_COOKIE != timer->platformInfo.cookie )
627 {
628 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700629 "%s: Cannot destroy uninitialized timer",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700630 return VOS_STATUS_E_INVAL;
631 }
632 spin_lock_irqsave( &timer->platformInfo.spinlock,flags );
633
634 switch ( timer->state )
635 {
636 case VOS_TIMER_STATE_STARTING:
637 vStatus = VOS_STATUS_E_BUSY;
638 break;
639 case VOS_TIMER_STATE_RUNNING:
640 /* Stop the timer first */
641 del_timer(&(timer->platformInfo.Timer));
642 vStatus = VOS_STATUS_SUCCESS;
643 break;
644 case VOS_TIMER_STATE_STOPPED:
645 vStatus = VOS_STATUS_SUCCESS;
646 break;
647 case VOS_TIMER_STATE_UNUSED:
648 vStatus = VOS_STATUS_E_ALREADY;
649 break;
650 default:
651 vStatus = VOS_STATUS_E_FAULT;
652 break;
653 }
654
655 if ( VOS_STATUS_SUCCESS == vStatus )
656 {
657 timer->platformInfo.cookie = LINUX_INVALID_TIMER_COOKIE;
658 timer->state = VOS_TIMER_STATE_UNUSED;
659 spin_unlock_irqrestore( &timer->platformInfo.spinlock,flags );
660 return vStatus;
661 }
662
663 spin_unlock_irqrestore( &timer->platformInfo.spinlock,flags );
664
665 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
666 "%s: Cannot destroy timer in state = %d",__func__, timer->state);
667 VOS_ASSERT(0);
668
669 return vStatus;
670}
671#endif
672
673/*--------------------------------------------------------------------------
674
675 \brief vos_timer_start() - Start a vOSS Timer object
676
677 The \a vos_timer_start() function starts a timer to expire after the
678 specified interval, thus running the timer callback function when
679 the interval expires.
680
681 A timer only runs once (a one-shot timer). To re-start the
682 timer, vos_timer_start() has to be called after the timer runs
683 or has been cancelled.
684
685 \param timer - the timer object to be started
686
687 \param expirationTime - expiration time for the timer (in milliseconds)
688
689 \return VOS_STATUS_SUCCESS - timer was successfully started.
690
691 VOS_STATUS_E_ALREADY - The implementation has detected an attempt
692 to start a timer while it is already started. The timer must
693 be stopped or expire before it can be started again.
694
695 VOS_STATUS_E_INVAL - The value specified by timer is invalid.
696
697 VOS_STATUS_E_FAULT - timer is an invalid pointer.
698 \sa
699
700 -------------------------------------------------------------------------*/
701VOS_STATUS vos_timer_start( vos_timer_t *timer, v_U32_t expirationTime )
702{
703 unsigned long flags;
704
705 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH,
706 "Timer Addr inside voss_start : 0x%p ", timer );
707
708 // Check for invalid pointer
709 if ( NULL == timer )
710 {
711 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
712 "%s Null timer pointer being passed", __func__);
713 VOS_ASSERT(0);
714 return VOS_STATUS_E_INVAL;
715 }
716
717 // Check if timer refers to an uninitialized object
718 if ( LINUX_TIMER_COOKIE != timer->platformInfo.cookie )
719 {
720 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700721 "%s: Cannot start uninitialized timer",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700722 VOS_ASSERT(0);
723 return VOS_STATUS_E_INVAL;
724 }
725
726 // Check if timer has expiration time less than 10 ms
727 if ( expirationTime < 10 )
728 {
729 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
730 "%s: Cannot start a "
731 "timer with expiration less than 10 ms", __func__);
732 VOS_ASSERT(0);
733 return VOS_STATUS_E_INVAL;
734 }
735
736 // make sure the remainer of the logic isn't interrupted
737 spin_lock_irqsave( &timer->platformInfo.spinlock,flags );
738
739 // Ensure if the timer can be started
740 if ( VOS_TIMER_STATE_STOPPED != timer->state )
741 {
742 spin_unlock_irqrestore( &timer->platformInfo.spinlock,flags );
Mohit Khanna23863762012-09-11 17:40:09 -0700743 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH,
Jeff Johnson295189b2012-06-20 16:38:30 -0700744 "%s: Cannot start timer in state = %d ",__func__, timer->state);
745 return VOS_STATUS_E_ALREADY;
746 }
747
748 // Start the timer
749 mod_timer( &(timer->platformInfo.Timer),
750 jiffies + msecs_to_jiffies(expirationTime));
751
752 timer->state = VOS_TIMER_STATE_RUNNING;
753
754 // Get the thread ID on which the timer is being started
755 timer->platformInfo.threadID = current->pid;
756
757 if ( VOS_TIMER_TYPE_WAKE_APPS == timer->type )
758 {
759 persistentTimerCount++;
760 if ( 1 == persistentTimerCount )
761 {
762 // Since we now have one persistent timer, we need to disallow sleep
763 // sleep_negate_okts( sleepClientHandle );
764 }
765 }
766
767 spin_unlock_irqrestore( &timer->platformInfo.spinlock,flags );
768
769 return VOS_STATUS_SUCCESS;
770}
771
772
773/*--------------------------------------------------------------------------
774
775 \brief vos_timer_stop() - Stop a vOSS Timer
776
777 The \a vos_timer_stop() function stops a timer that has been started but
778 has not expired, essentially cancelling the 'start' request.
779
780 After a timer is stopped, it goes back to the state it was in after it
781 was created and can be started again via a call to vos_timer_start().
782
783 \param timer - the timer object to be stopped
784
785 \return VOS_STATUS_SUCCESS - timer was successfully stopped.
786
787 VOS_STATUS_E_EMPTY - The implementation has detected an attempt
788 to stop a timer that has not been started or has already
789 expired.
790
791 VOS_STATUS_E_INVAL - The value specified by timer is invalid.
792
793 VOS_STATUS_E_FAULT - timer is an invalid pointer.
794 \sa
795
796 ------------------------------------------------------------------------*/
797VOS_STATUS vos_timer_stop ( vos_timer_t *timer )
798{
799 unsigned long flags;
800
801 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH,
802 "%s: Timer Addr inside voss_stop : 0x%p",__func__,timer );
803
804 // Check for invalid pointer
805 if ( NULL == timer )
806 {
807 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
808 "%s Null timer pointer being passed", __func__);
809 VOS_ASSERT(0);
810 return VOS_STATUS_E_INVAL;
811 }
812
813 // Check if timer refers to an uninitialized object
814 if ( LINUX_TIMER_COOKIE != timer->platformInfo.cookie )
815 {
816 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700817 "%s: Cannot stop uninitialized timer",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700818 VOS_ASSERT(0);
819 return VOS_STATUS_E_INVAL;
820 }
821
822 // Ensure the timer state is correct
823 spin_lock_irqsave( &timer->platformInfo.spinlock,flags );
824
825 if ( VOS_TIMER_STATE_RUNNING != timer->state )
826 {
827 spin_unlock_irqrestore( &timer->platformInfo.spinlock,flags );
Mohit Khanna23863762012-09-11 17:40:09 -0700828 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH,
Jeff Johnson295189b2012-06-20 16:38:30 -0700829 "%s: Cannot stop timer in state = %d",
830 __func__, timer->state);
831 return VOS_STATUS_E_FAULT;
832 }
833
834 timer->state = VOS_TIMER_STATE_STOPPED;
835
836 del_timer(&(timer->platformInfo.Timer));
837
838 spin_unlock_irqrestore( &timer->platformInfo.spinlock,flags );
839
840 tryAllowingSleep( timer->type );
841
842 return VOS_STATUS_SUCCESS;
843}
844
845
846/*--------------------------------------------------------------------------
847
848 \brief vos_timer_get_system_ticks() - Get the system time in 10ms ticks
849
850 The \a vos_timer_get_system_ticks() function returns the current number
851 of timer ticks in 10msec intervals. This function is suitable timestamping
852 and calculating time intervals by calculating the difference between two
853 timestamps.
854
855 \returns - The current system tick count (in 10msec intervals). This
856 function cannot fail.
857
858 \sa
859
860 ------------------------------------------------------------------------*/
861v_TIME_t vos_timer_get_system_ticks( v_VOID_t )
862{
863 return( jiffies_to_msecs(jiffies) / 10 );
864}
865
866
867/*--------------------------------------------------------------------------
868
869 \brief vos_timer_get_system_time() - Get the system time in milliseconds
870
871 The \a vos_timer_get_system_time() function returns the number of milliseconds
872 that have elapsed since the system was started
873
874 \returns - The current system time in milliseconds.
875
876 \sa
877
878 ------------------------------------------------------------------------*/
879v_TIME_t vos_timer_get_system_time( v_VOID_t )
880{
881 struct timeval tv;
882 do_gettimeofday(&tv);
883 return tv.tv_sec*1000 + tv.tv_usec/1000;
884}