qdf_mc_timer.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. /*
  2. * Copyright (c) 2014-2016 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. /*
  22. * This file was originally distributed by Qualcomm Atheros, Inc.
  23. * under proprietary terms before Copyright ownership was assigned
  24. * to the Linux Foundation.
  25. */
  26. /**
  27. * DOC: qdf_mc_timer
  28. * QCA driver framework timer APIs serialized to MC thread
  29. */
  30. /* Include Files */
  31. #include <qdf_mc_timer.h>
  32. #include <qdf_lock.h>
  33. #include "qdf_lock.h"
  34. #include "qdf_list.h"
  35. #include "qdf_mem.h"
  36. #include <linux/export.h>
  37. #ifndef NAPIER_CODE
  38. #ifdef CONFIG_MCL
  39. #include <cds_mc_timer.h>
  40. #endif
  41. #endif
  42. /* Preprocessor definitions and constants */
  43. #define LINUX_TIMER_COOKIE 0x12341234
  44. #define LINUX_INVALID_TIMER_COOKIE 0xfeedface
  45. #define TMR_INVALID_ID (0)
  46. /* Flag for napier emulation */
  47. #ifdef QCA_WIFI_NAPIER_EMULATION
  48. #define QDF_TIMER_MULTIPLIER 100
  49. #else
  50. #define QDF_TIMER_MULTIPLIER 1
  51. #endif
  52. /* Type declarations */
  53. /* Static Variable Definitions */
  54. static unsigned int persistent_timer_count;
  55. static qdf_mutex_t persistent_timer_count_lock;
  56. static void (*scheduler_timer_callback) (unsigned long data);
  57. void qdf_register_mc_timer_callback(void (*callback) (unsigned long data))
  58. {
  59. scheduler_timer_callback = callback;
  60. }
  61. EXPORT_SYMBOL(qdf_register_mc_timer_callback);
  62. /* Function declarations and documenation */
  63. /**
  64. * qdf_try_allowing_sleep() - clean up timer states after it has been deactivated
  65. * @type: timer type
  66. *
  67. * Clean up timer states after it has been deactivated check and try to allow
  68. * sleep after a timer has been stopped or expired.
  69. *
  70. * Return: none
  71. */
  72. void qdf_try_allowing_sleep(QDF_TIMER_TYPE type)
  73. {
  74. if (QDF_TIMER_TYPE_WAKE_APPS == type) {
  75. persistent_timer_count--;
  76. if (0 == persistent_timer_count) {
  77. /* since the number of persistent timers has
  78. decreased from 1 to 0, the timer should allow
  79. sleep
  80. */
  81. }
  82. }
  83. }
  84. EXPORT_SYMBOL(qdf_try_allowing_sleep);
  85. /**
  86. * qdf_mc_timer_get_current_state() - get the current state of the timer
  87. * @timer: Pointer to timer object
  88. *
  89. * Return:
  90. * QDF_TIMER_STATE - qdf timer state
  91. */
  92. QDF_TIMER_STATE qdf_mc_timer_get_current_state(qdf_mc_timer_t *timer)
  93. {
  94. if (NULL == timer) {
  95. QDF_ASSERT(0);
  96. return QDF_TIMER_STATE_UNUSED;
  97. }
  98. switch (timer->state) {
  99. case QDF_TIMER_STATE_STOPPED:
  100. case QDF_TIMER_STATE_STARTING:
  101. case QDF_TIMER_STATE_RUNNING:
  102. case QDF_TIMER_STATE_UNUSED:
  103. return timer->state;
  104. default:
  105. QDF_ASSERT(0);
  106. return QDF_TIMER_STATE_UNUSED;
  107. }
  108. }
  109. EXPORT_SYMBOL(qdf_mc_timer_get_current_state);
  110. /**
  111. * qdf_timer_module_init() - initializes a QDF timer module.
  112. *
  113. * This API initializes the QDF timer module. This needs to be called
  114. * exactly once prior to using any QDF timers.
  115. *
  116. * Return: none
  117. */
  118. void qdf_timer_module_init(void)
  119. {
  120. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH,
  121. "Initializing the QDF MC timer module");
  122. qdf_mutex_create(&persistent_timer_count_lock);
  123. }
  124. EXPORT_SYMBOL(qdf_timer_module_init);
  125. #ifdef TIMER_MANAGER
  126. qdf_list_t qdf_timer_list;
  127. qdf_spinlock_t qdf_timer_list_lock;
  128. static void qdf_timer_clean(void);
  129. /**
  130. * qdf_mc_timer_manager_init() - initialize QDF debug timer manager
  131. *
  132. * This API initializes QDF timer debug functionality.
  133. *
  134. * Return: none
  135. */
  136. void qdf_mc_timer_manager_init(void)
  137. {
  138. qdf_list_create(&qdf_timer_list, 1000);
  139. qdf_spinlock_create(&qdf_timer_list_lock);
  140. return;
  141. }
  142. EXPORT_SYMBOL(qdf_mc_timer_manager_init);
  143. /**
  144. * qdf_timer_clean() - clean up QDF timer debug functionality
  145. *
  146. * This API cleans up QDF timer debug functionality and prints which QDF timers
  147. * are leaked. This is called during driver unload.
  148. *
  149. * Return: none
  150. */
  151. static void qdf_timer_clean(void)
  152. {
  153. uint32_t list_size;
  154. qdf_list_node_t *node;
  155. QDF_STATUS qdf_status;
  156. qdf_mc_timer_node_t *timer_node;
  157. list_size = qdf_list_size(&qdf_timer_list);
  158. if (!list_size)
  159. return;
  160. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH,
  161. "%s: List is not Empty. list_size %d ",
  162. __func__, (int)list_size);
  163. do {
  164. qdf_spin_lock_irqsave(&qdf_timer_list_lock);
  165. qdf_status = qdf_list_remove_front(&qdf_timer_list, &node);
  166. qdf_spin_unlock_irqrestore(&qdf_timer_list_lock);
  167. if (QDF_STATUS_SUCCESS == qdf_status) {
  168. timer_node = (qdf_mc_timer_node_t *) node;
  169. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL,
  170. "timer Leak@ File %s, @Line %d",
  171. timer_node->file_name,
  172. (int)timer_node->line_num);
  173. qdf_mem_free(timer_node);
  174. }
  175. } while (qdf_status == QDF_STATUS_SUCCESS);
  176. }
  177. EXPORT_SYMBOL(qdf_timer_clean);
  178. /**
  179. * qdf_mc_timer_manager_exit() - exit QDF timer debug functionality
  180. *
  181. * This API exists QDF timer debug functionality
  182. *
  183. * Return: none
  184. */
  185. void qdf_mc_timer_manager_exit(void)
  186. {
  187. qdf_timer_clean();
  188. qdf_list_destroy(&qdf_timer_list);
  189. }
  190. EXPORT_SYMBOL(qdf_mc_timer_manager_exit);
  191. #endif
  192. /**
  193. * qdf_mc_timer_init() - initialize a QDF timer
  194. * @timer: Pointer to timer object
  195. * @timer_type: Type of timer
  196. * @callback: Callback to be called after timer expiry
  197. * @ser_data: User data which will be passed to callback function
  198. *
  199. * This API initializes a QDF timer object.
  200. *
  201. * qdf_mc_timer_init() initializes a QDF timer object. A timer must be
  202. * initialized by calling qdf_mc_timer_initialize() before it may be used in
  203. * any other timer functions.
  204. *
  205. * Attempting to initialize timer that is already initialized results in
  206. * a failure. A destroyed timer object can be re-initialized with a call to
  207. * qdf_mc_timer_init(). The results of otherwise referencing the object
  208. * after it has been destroyed are undefined.
  209. *
  210. * Calls to QDF timer functions to manipulate the timer such
  211. * as qdf_mc_timer_set() will fail if the timer is not initialized or has
  212. * been destroyed. Therefore, don't use the timer after it has been
  213. * destroyed until it has been re-initialized.
  214. *
  215. * All callback will be executed within the CDS main thread unless it is
  216. * initialized from the Tx thread flow, in which case it will be executed
  217. * within the tx thread flow.
  218. *
  219. * Return:
  220. * QDF_STATUS_SUCCESS: timer is initialized successfully
  221. * QDF failure status: timer initialization failed
  222. */
  223. #ifdef TIMER_MANAGER
  224. QDF_STATUS qdf_mc_timer_init_debug(qdf_mc_timer_t *timer,
  225. QDF_TIMER_TYPE timer_type,
  226. qdf_mc_timer_callback_t callback,
  227. void *user_data, char *file_name,
  228. uint32_t line_num)
  229. {
  230. QDF_STATUS qdf_status;
  231. /* check for invalid pointer */
  232. if ((timer == NULL) || (callback == NULL)) {
  233. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  234. "%s: Null params being passed", __func__);
  235. QDF_ASSERT(0);
  236. return QDF_STATUS_E_FAULT;
  237. }
  238. timer->timer_node = qdf_mem_malloc(sizeof(qdf_mc_timer_node_t));
  239. if (timer->timer_node == NULL) {
  240. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  241. "%s: Not able to allocate memory for time_node",
  242. __func__);
  243. QDF_ASSERT(0);
  244. return QDF_STATUS_E_NOMEM;
  245. }
  246. qdf_mem_set(timer->timer_node, sizeof(qdf_mc_timer_node_t), 0);
  247. timer->timer_node->file_name = file_name;
  248. timer->timer_node->line_num = line_num;
  249. timer->timer_node->qdf_timer = timer;
  250. qdf_spin_lock_irqsave(&qdf_timer_list_lock);
  251. qdf_status = qdf_list_insert_front(&qdf_timer_list,
  252. &timer->timer_node->node);
  253. qdf_spin_unlock_irqrestore(&qdf_timer_list_lock);
  254. if (QDF_STATUS_SUCCESS != qdf_status) {
  255. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  256. "%s: Unable to insert node into List qdf_status %d",
  257. __func__, qdf_status);
  258. }
  259. /* set the various members of the timer structure
  260. * with arguments passed or with default values
  261. */
  262. qdf_spinlock_create(&timer->platform_info.spinlock);
  263. if (QDF_TIMER_TYPE_SW == timer_type)
  264. init_timer_deferrable(&(timer->platform_info.timer));
  265. else
  266. init_timer(&(timer->platform_info.timer));
  267. #ifdef NAPIER_CODE
  268. timer->platform_info.timer.function = scheduler_timer_callback;
  269. #elif CONFIG_MCL
  270. timer->platform_info.timer.function = cds_linux_timer_callback;
  271. #else
  272. timer->platform_info.timer.function = NULL;
  273. #endif
  274. timer->platform_info.timer.data = (unsigned long)timer;
  275. timer->callback = callback;
  276. timer->user_data = user_data;
  277. timer->type = timer_type;
  278. timer->platform_info.cookie = LINUX_TIMER_COOKIE;
  279. timer->platform_info.thread_id = 0;
  280. timer->state = QDF_TIMER_STATE_STOPPED;
  281. return QDF_STATUS_SUCCESS;
  282. }
  283. #else
  284. QDF_STATUS qdf_mc_timer_init(qdf_mc_timer_t *timer, QDF_TIMER_TYPE timer_type,
  285. qdf_mc_timer_callback_t callback,
  286. void *user_data)
  287. {
  288. /* check for invalid pointer */
  289. if ((timer == NULL) || (callback == NULL)) {
  290. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  291. "%s: Null params being passed", __func__);
  292. QDF_ASSERT(0);
  293. return QDF_STATUS_E_FAULT;
  294. }
  295. /* set the various members of the timer structure
  296. * with arguments passed or with default values
  297. */
  298. qdf_spinlock_create(&timer->platform_info.spinlock);
  299. if (QDF_TIMER_TYPE_SW == timer_type)
  300. init_timer_deferrable(&(timer->platform_info.timer));
  301. else
  302. init_timer(&(timer->platform_info.timer));
  303. #ifdef NAPIER_CODE
  304. timer->platform_info.timer.function = scheduler_timer_callback;
  305. #elif CONFIG_MCL
  306. timer->platform_info.timer.function = cds_linux_timer_callback;
  307. #else
  308. timer->platform_info.timer.function = NULL;
  309. #endif
  310. timer->platform_info.timer.data = (unsigned long)timer;
  311. timer->callback = callback;
  312. timer->user_data = user_data;
  313. timer->type = timer_type;
  314. timer->platform_info.cookie = LINUX_TIMER_COOKIE;
  315. timer->platform_info.thread_id = 0;
  316. timer->state = QDF_TIMER_STATE_STOPPED;
  317. return QDF_STATUS_SUCCESS;
  318. }
  319. #endif
  320. /**
  321. * qdf_mc_timer_destroy() - destroy QDF timer
  322. * @timer: Pointer to timer object
  323. *
  324. * qdf_mc_timer_destroy() function shall destroy the timer object.
  325. * After a successful return from \a qdf_mc_timer_destroy() the timer
  326. * object becomes, in effect, uninitialized.
  327. *
  328. * A destroyed timer object can be re-initialized by calling
  329. * qdf_mc_timer_init(). The results of otherwise referencing the object
  330. * after it has been destroyed are undefined.
  331. *
  332. * Calls to QDF timer functions to manipulate the timer, such
  333. * as qdf_mc_timer_set() will fail if the lock is destroyed. Therefore,
  334. * don't use the timer after it has been destroyed until it has
  335. * been re-initialized.
  336. *
  337. * Return:
  338. * QDF_STATUS_SUCCESS - timer is initialized successfully
  339. * QDF failure status - timer initialization failed
  340. */
  341. #ifdef TIMER_MANAGER
  342. QDF_STATUS qdf_mc_timer_destroy(qdf_mc_timer_t *timer)
  343. {
  344. QDF_STATUS v_status = QDF_STATUS_SUCCESS;
  345. /* check for invalid pointer */
  346. if (NULL == timer) {
  347. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  348. "%s: Null timer pointer being passed", __func__);
  349. QDF_ASSERT(0);
  350. return QDF_STATUS_E_FAULT;
  351. }
  352. /* Check if timer refers to an uninitialized object */
  353. if (LINUX_TIMER_COOKIE != timer->platform_info.cookie) {
  354. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  355. "%s: Cannot destroy uninitialized timer", __func__);
  356. QDF_ASSERT(0);
  357. return QDF_STATUS_E_INVAL;
  358. }
  359. qdf_spin_lock_irqsave(&qdf_timer_list_lock);
  360. v_status = qdf_list_remove_node(&qdf_timer_list,
  361. &timer->timer_node->node);
  362. qdf_spin_unlock_irqrestore(&qdf_timer_list_lock);
  363. if (v_status != QDF_STATUS_SUCCESS) {
  364. QDF_ASSERT(0);
  365. return QDF_STATUS_E_INVAL;
  366. }
  367. qdf_mem_free(timer->timer_node);
  368. qdf_spin_lock_irqsave(&timer->platform_info.spinlock);
  369. switch (timer->state) {
  370. case QDF_TIMER_STATE_STARTING:
  371. v_status = QDF_STATUS_E_BUSY;
  372. break;
  373. case QDF_TIMER_STATE_RUNNING:
  374. /* Stop the timer first */
  375. del_timer(&(timer->platform_info.timer));
  376. v_status = QDF_STATUS_SUCCESS;
  377. break;
  378. case QDF_TIMER_STATE_STOPPED:
  379. v_status = QDF_STATUS_SUCCESS;
  380. break;
  381. case QDF_TIMER_STATE_UNUSED:
  382. v_status = QDF_STATUS_E_ALREADY;
  383. break;
  384. default:
  385. v_status = QDF_STATUS_E_FAULT;
  386. break;
  387. }
  388. if (QDF_STATUS_SUCCESS == v_status) {
  389. timer->platform_info.cookie = LINUX_INVALID_TIMER_COOKIE;
  390. timer->state = QDF_TIMER_STATE_UNUSED;
  391. qdf_spin_unlock_irqrestore(&timer->platform_info.spinlock);
  392. return v_status;
  393. }
  394. qdf_spin_unlock_irqrestore(&timer->platform_info.spinlock);
  395. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH,
  396. "%s: Cannot destroy timer in state = %d", __func__,
  397. timer->state);
  398. QDF_ASSERT(0);
  399. return v_status;
  400. }
  401. EXPORT_SYMBOL(qdf_mc_timer_destroy);
  402. #else
  403. /**
  404. * qdf_mc_timer_destroy() - destroy QDF timer
  405. * @timer: Pointer to timer object
  406. *
  407. * qdf_mc_timer_destroy() function shall destroy the timer object.
  408. * After a successful return from \a qdf_mc_timer_destroy() the timer
  409. * object becomes, in effect, uninitialized.
  410. *
  411. * A destroyed timer object can be re-initialized by calling
  412. * qdf_mc_timer_init(). The results of otherwise referencing the object
  413. * after it has been destroyed are undefined.
  414. *
  415. * Calls to QDF timer functions to manipulate the timer, such
  416. * as qdf_mc_timer_set() will fail if the lock is destroyed. Therefore,
  417. * don't use the timer after it has been destroyed until it has
  418. * been re-initialized.
  419. *
  420. * Return:
  421. * QDF_STATUS_SUCCESS - timer is initialized successfully
  422. * QDF failure status - timer initialization failed
  423. */
  424. QDF_STATUS qdf_mc_timer_destroy(qdf_mc_timer_t *timer)
  425. {
  426. QDF_STATUS v_status = QDF_STATUS_SUCCESS;
  427. /* check for invalid pointer */
  428. if (NULL == timer) {
  429. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  430. "%s: Null timer pointer being passed", __func__);
  431. QDF_ASSERT(0);
  432. return QDF_STATUS_E_FAULT;
  433. }
  434. /* check if timer refers to an uninitialized object */
  435. if (LINUX_TIMER_COOKIE != timer->platform_info.cookie) {
  436. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  437. "%s: Cannot destroy uninitialized timer", __func__);
  438. QDF_ASSERT(0);
  439. return QDF_STATUS_E_INVAL;
  440. }
  441. qdf_spin_lock_irqsave(&timer->platform_info.spinlock);
  442. switch (timer->state) {
  443. case QDF_TIMER_STATE_STARTING:
  444. v_status = QDF_STATUS_E_BUSY;
  445. break;
  446. case QDF_TIMER_STATE_RUNNING:
  447. /* Stop the timer first */
  448. del_timer(&(timer->platform_info.timer));
  449. v_status = QDF_STATUS_SUCCESS;
  450. break;
  451. case QDF_TIMER_STATE_STOPPED:
  452. v_status = QDF_STATUS_SUCCESS;
  453. break;
  454. case QDF_TIMER_STATE_UNUSED:
  455. v_status = QDF_STATUS_E_ALREADY;
  456. break;
  457. default:
  458. v_status = QDF_STATUS_E_FAULT;
  459. break;
  460. }
  461. if (QDF_STATUS_SUCCESS == v_status) {
  462. timer->platform_info.cookie = LINUX_INVALID_TIMER_COOKIE;
  463. timer->state = QDF_TIMER_STATE_UNUSED;
  464. qdf_spin_unlock_irqrestore(&timer->platform_info.spinlock);
  465. return v_status;
  466. }
  467. qdf_spin_unlock_irqrestore(&timer->platform_info.spinlock);
  468. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH,
  469. "%s: Cannot destroy timer in state = %d", __func__,
  470. timer->state);
  471. QDF_ASSERT(0);
  472. return v_status;
  473. }
  474. EXPORT_SYMBOL(qdf_mc_timer_destroy);
  475. #endif
  476. /**
  477. * qdf_mc_timer_start() - start a QDF timer object
  478. * @timer: Pointer to timer object
  479. * @expiration_time: Time to expire
  480. *
  481. * qdf_mc_timer_start() function starts a timer to expire after the
  482. * specified interval, thus running the timer callback function when
  483. * the interval expires.
  484. *
  485. * A timer only runs once (a one-shot timer). To re-start the
  486. * timer, qdf_mc_timer_start() has to be called after the timer runs
  487. * or has been cancelled.
  488. *
  489. * Return:
  490. * QDF_STATUS_SUCCESS: timer is initialized successfully
  491. * QDF failure status: timer initialization failed
  492. */
  493. QDF_STATUS qdf_mc_timer_start(qdf_mc_timer_t *timer, uint32_t expiration_time)
  494. {
  495. /* check for invalid pointer */
  496. if (NULL == timer) {
  497. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  498. "%s Null timer pointer being passed", __func__);
  499. QDF_ASSERT(0);
  500. return QDF_STATUS_E_INVAL;
  501. }
  502. /* check if timer refers to an uninitialized object */
  503. if (LINUX_TIMER_COOKIE != timer->platform_info.cookie) {
  504. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  505. "%s: Cannot start uninitialized timer", __func__);
  506. QDF_ASSERT(0);
  507. return QDF_STATUS_E_INVAL;
  508. }
  509. /* check if timer has expiration time less than 10 ms */
  510. if (expiration_time < 10) {
  511. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  512. "%s: Cannot start a timer with expiration less than 10 ms",
  513. __func__);
  514. QDF_ASSERT(0);
  515. return QDF_STATUS_E_INVAL;
  516. }
  517. /* update expiration time based on if emulation platform */
  518. expiration_time *= QDF_TIMER_MULTIPLIER;
  519. /* make sure the remainer of the logic isn't interrupted */
  520. qdf_spin_lock_irqsave(&timer->platform_info.spinlock);
  521. /* ensure if the timer can be started */
  522. if (QDF_TIMER_STATE_STOPPED != timer->state) {
  523. qdf_spin_unlock_irqrestore(&timer->platform_info.spinlock);
  524. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  525. "%s: Cannot start timer in state = %d ", __func__,
  526. timer->state);
  527. return QDF_STATUS_E_ALREADY;
  528. }
  529. /* start the timer */
  530. mod_timer(&(timer->platform_info.timer),
  531. jiffies + msecs_to_jiffies(expiration_time));
  532. timer->state = QDF_TIMER_STATE_RUNNING;
  533. /* get the thread ID on which the timer is being started */
  534. timer->platform_info.thread_id = current->pid;
  535. if (QDF_TIMER_TYPE_WAKE_APPS == timer->type) {
  536. persistent_timer_count++;
  537. if (1 == persistent_timer_count) {
  538. /* since we now have one persistent timer,
  539. * we need to disallow sleep
  540. * sleep_negate_okts(sleep_client_handle);
  541. */
  542. }
  543. }
  544. qdf_spin_unlock_irqrestore(&timer->platform_info.spinlock);
  545. return QDF_STATUS_SUCCESS;
  546. }
  547. EXPORT_SYMBOL(qdf_mc_timer_start);
  548. /**
  549. * qdf_mc_timer_stop() - stop a QDF timer
  550. * @timer: Pointer to timer object
  551. * qdf_mc_timer_stop() function stops a timer that has been started but
  552. * has not expired, essentially cancelling the 'start' request.
  553. *
  554. * After a timer is stopped, it goes back to the state it was in after it
  555. * was created and can be started again via a call to qdf_mc_timer_start().
  556. *
  557. * Return:
  558. * QDF_STATUS_SUCCESS: timer is initialized successfully
  559. * QDF failure status: timer initialization failed
  560. */
  561. QDF_STATUS qdf_mc_timer_stop(qdf_mc_timer_t *timer)
  562. {
  563. /* check for invalid pointer */
  564. if (NULL == timer) {
  565. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  566. "%s Null timer pointer being passed", __func__);
  567. QDF_ASSERT(0);
  568. return QDF_STATUS_E_INVAL;
  569. }
  570. /* check if timer refers to an uninitialized object */
  571. if (LINUX_TIMER_COOKIE != timer->platform_info.cookie) {
  572. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  573. "%s: Cannot stop uninitialized timer", __func__);
  574. QDF_ASSERT(0);
  575. return QDF_STATUS_E_INVAL;
  576. }
  577. /* ensure the timer state is correct */
  578. qdf_spin_lock_irqsave(&timer->platform_info.spinlock);
  579. if (QDF_TIMER_STATE_RUNNING != timer->state) {
  580. qdf_spin_unlock_irqrestore(&timer->platform_info.spinlock);
  581. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH,
  582. "%s: Cannot stop timer in state = %d",
  583. __func__, timer->state);
  584. return QDF_STATUS_SUCCESS;
  585. }
  586. timer->state = QDF_TIMER_STATE_STOPPED;
  587. del_timer(&(timer->platform_info.timer));
  588. qdf_spin_unlock_irqrestore(&timer->platform_info.spinlock);
  589. qdf_try_allowing_sleep(timer->type);
  590. return QDF_STATUS_SUCCESS;
  591. }
  592. EXPORT_SYMBOL(qdf_mc_timer_stop);
  593. /**
  594. * qdf_mc_timer_get_system_ticks() - get the system time in 10ms ticks
  595. * qdf_mc_timer_get_system_ticks() function returns the current number
  596. * of timer ticks in 10msec intervals. This function is suitable timestamping
  597. * and calculating time intervals by calculating the difference between two
  598. * timestamps.
  599. *
  600. * Return:
  601. * The current system tick count (in 10msec intervals). This
  602. * function cannot fail.
  603. */
  604. unsigned long qdf_mc_timer_get_system_ticks(void)
  605. {
  606. return jiffies_to_msecs(jiffies) / 10;
  607. }
  608. EXPORT_SYMBOL(qdf_mc_timer_get_system_ticks);
  609. /**
  610. * qdf_mc_timer_get_system_time() - Get the system time in milliseconds
  611. *
  612. * qdf_mc_timer_get_system_time() function returns the number of milliseconds
  613. * that have elapsed since the system was started
  614. *
  615. * Return:
  616. * The current system time in milliseconds
  617. */
  618. unsigned long qdf_mc_timer_get_system_time(void)
  619. {
  620. struct timeval tv;
  621. do_gettimeofday(&tv);
  622. return tv.tv_sec * 1000 + tv.tv_usec / 1000;
  623. }
  624. EXPORT_SYMBOL(qdf_mc_timer_get_system_time);
  625. /**
  626. * qdf_timer_module_deinit() - Deinitializes a QDF timer module.
  627. *
  628. * This API deinitializes the QDF timer module.
  629. * Return: none
  630. */
  631. void qdf_timer_module_deinit(void)
  632. {
  633. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH,
  634. "De-Initializing the QDF MC timer module");
  635. qdf_mutex_destroy(&persistent_timer_count_lock);
  636. }
  637. EXPORT_SYMBOL(qdf_timer_module_deinit);
  638. void qdf_get_time_of_the_day_in_hr_min_sec_usec(char *tbuf, int len)
  639. {
  640. struct timeval tv;
  641. struct rtc_time tm;
  642. unsigned long local_time;
  643. /* Format the Log time R#: [hr:min:sec.microsec] */
  644. do_gettimeofday(&tv);
  645. /* Convert rtc to local time */
  646. local_time = (u32)(tv.tv_sec - (sys_tz.tz_minuteswest * 60));
  647. rtc_time_to_tm(local_time, &tm);
  648. scnprintf(tbuf, len,
  649. "[%02d:%02d:%02d.%06lu]",
  650. tm.tm_hour, tm.tm_min, tm.tm_sec, tv.tv_usec);
  651. }
  652. EXPORT_SYMBOL(qdf_get_time_of_the_day_in_hr_min_sec_usec);