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