qdf_lock.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. /*
  2. * Copyright (c) 2014-2017 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. * @file qdf_lock.h
  28. * This file abstracts locking operations.
  29. */
  30. #ifndef _QDF_LOCK_H
  31. #define _QDF_LOCK_H
  32. #include <qdf_types.h>
  33. #include <qdf_mem.h>
  34. #include <qdf_time.h>
  35. #include <i_qdf_trace.h>
  36. #define QDF_LOCK_STATS 0
  37. #define QDF_LOCK_STATS_DESTROY_PRINT 0
  38. #define QDF_LOCK_STATS_BUG_ON 0
  39. #define QDF_MAX_HOLD_TIME_ALOWED_SPINLOCK_IRQ 1000
  40. #define QDF_MAX_HOLD_TIME_ALOWED_SPINLOCK_BH 5000
  41. #define QDF_MAX_HOLD_TIME_ALOWED_SPINLOCK 5000
  42. #if !QDF_LOCK_STATS
  43. struct lock_stats {};
  44. #define BEFORE_LOCK(x...) do {} while (0)
  45. #define AFTER_LOCK(x...) do {} while (0)
  46. #define BEFORE_UNLOCK(x...) do {} while (0)
  47. #define qdf_lock_stats_create(x...) do {} while (0)
  48. #define qdf_lock_stats_destroy(x...) do {} while (0)
  49. #else
  50. struct lock_stats {
  51. const char *initialization_fn;
  52. int line;
  53. int acquired;
  54. int contended;
  55. uint64_t contention_time;
  56. uint64_t non_contention_time;
  57. uint64_t held_time;
  58. uint64_t last_acquired;
  59. uint64_t max_contention_wait;
  60. uint64_t max_held_time;
  61. int num_large_contentions;
  62. int num_large_holds;
  63. };
  64. #define LARGE_CONTENTION QDF_LOG_TIMESTAMP_CYCLES_PER_10_US
  65. #define BEFORE_LOCK(lock, was_locked) \
  66. { \
  67. uint64_t BEFORE_LOCK_time; \
  68. uint64_t AFTER_LOCK_time; \
  69. bool BEFORE_LOCK_is_locked = was_locked; \
  70. BEFORE_LOCK_time = qdf_get_log_timestamp(); \
  71. do {} while (0)
  72. #define AFTER_LOCK(lock) \
  73. AFTER_LOCK_time = qdf_get_log_timestamp(); \
  74. lock->stats.acquired++; \
  75. lock->stats.last_acquired = AFTER_LOCK_time; \
  76. if (BEFORE_LOCK_is_locked) { \
  77. lock->stats.contended++; \
  78. lock->stats.contention_time += \
  79. (AFTER_LOCK_time - BEFORE_LOCK_time); \
  80. } else { \
  81. lock->stats.non_contention_time += \
  82. (AFTER_LOCK_time - BEFORE_LOCK_time); \
  83. } \
  84. \
  85. if (AFTER_LOCK_time - BEFORE_LOCK_time > LARGE_CONTENTION) \
  86. lock->stats.num_large_contentions++; \
  87. \
  88. if (AFTER_LOCK_time - BEFORE_LOCK_time > \
  89. lock->stats.max_contention_wait) \
  90. lock->stats.max_contention_wait = \
  91. AFTER_LOCK_time - BEFORE_LOCK_time; \
  92. }
  93. /* max_hold_time in US */
  94. #define BEFORE_UNLOCK(lock, max_hold_time) \
  95. do {\
  96. uint64_t held_time = qdf_get_log_timestamp() - \
  97. lock->stats.last_acquired; \
  98. lock->stats.held_time += held_time; \
  99. \
  100. if (held_time > lock->stats.max_held_time) \
  101. lock->stats.max_held_time = held_time; \
  102. \
  103. if (held_time > LARGE_CONTENTION) \
  104. lock->stats.num_large_holds++; \
  105. if (QDF_LOCK_STATS_BUG_ON && max_hold_time && \
  106. held_time > qdf_usecs_to_log_timestamp(max_hold_time)) { \
  107. qdf_print("BEFORE_UNLOCK: lock held too long (%lluus)\n", \
  108. qdf_log_timestamp_to_usecs(held_time)); \
  109. QDF_BUG(0); \
  110. } \
  111. } while (0)
  112. static inline void qdf_lock_stats_destroy(struct lock_stats *stats)
  113. {
  114. if (QDF_LOCK_STATS_DESTROY_PRINT) {
  115. qdf_print("%s: lock: %s %d \t"
  116. "acquired:\t%d\tcontended:\t%d\t"
  117. "contention_time\t%llu\tmax_contention_wait:\t%llu\t"
  118. "non_contention_time\t%llu\t"
  119. "held_time\t%llu\tmax_held:\t%llu\t\n"
  120. , __func__, stats->initialization_fn, stats->line,
  121. stats->acquired, stats->contended,
  122. qdf_log_timestamp_to_usecs(stats->contention_time),
  123. qdf_log_timestamp_to_usecs(stats->max_contention_wait),
  124. qdf_log_timestamp_to_usecs(stats->non_contention_time),
  125. qdf_log_timestamp_to_usecs(stats->held_time),
  126. qdf_log_timestamp_to_usecs(stats->max_held_time));
  127. }
  128. }
  129. static inline void qdf_lock_stats_create(struct lock_stats *stats,
  130. const char *func, int line)
  131. {
  132. qdf_mem_zero(stats, sizeof(*stats));
  133. stats->initialization_fn = func;
  134. stats->line = line;
  135. }
  136. #endif
  137. #include <i_qdf_lock.h>
  138. #define WIFI_POWER_EVENT_DEFAULT_WAKELOCK_TIMEOUT 0
  139. #define WIFI_POWER_EVENT_WAKELOCK_TAKEN 0
  140. #define WIFI_POWER_EVENT_WAKELOCK_RELEASED 1
  141. /**
  142. * qdf_semaphore_acquire_timeout() - Take the semaphore before timeout
  143. * @m: semaphore to take
  144. * @timeout: maximum time to try to take the semaphore
  145. * Return: int
  146. */
  147. static inline int qdf_semaphore_acquire_timeout(struct semaphore *m,
  148. unsigned long timeout)
  149. {
  150. return __qdf_semaphore_acquire_timeout(m, timeout);
  151. }
  152. struct qdf_spinlock {
  153. __qdf_spinlock_t lock;
  154. struct lock_stats stats;
  155. };
  156. /**
  157. * @brief Platform spinlock object
  158. */
  159. typedef struct qdf_spinlock qdf_spinlock_t;
  160. /**
  161. * @brief Platform mutex object
  162. */
  163. typedef __qdf_semaphore_t qdf_semaphore_t;
  164. typedef __qdf_mutex_t qdf_mutex_t;
  165. /* function Declaration */
  166. QDF_STATUS qdf_mutex_create(qdf_mutex_t *m, const char *func, int line);
  167. #define qdf_mutex_create(m) qdf_mutex_create(m, __func__, __LINE__)
  168. QDF_STATUS qdf_mutex_acquire(qdf_mutex_t *m);
  169. QDF_STATUS qdf_mutex_release(qdf_mutex_t *m);
  170. QDF_STATUS qdf_mutex_destroy(qdf_mutex_t *lock);
  171. /**
  172. * qdf_spinlock_create - Initialize a spinlock
  173. * @lock: spinlock object pointer
  174. * Return: none
  175. */
  176. static inline void qdf_spinlock_create(qdf_spinlock_t *lock, const char *func,
  177. int line)
  178. {
  179. __qdf_spinlock_create(&lock->lock);
  180. qdf_lock_stats_create(&lock->stats, func, line);
  181. }
  182. #define qdf_spinlock_create(x) qdf_spinlock_create(x, __func__, __LINE__)
  183. /**
  184. * qdf_spinlock_destroy - Delete a spinlock
  185. * @lock: spinlock object pointer
  186. * Return: none
  187. */
  188. static inline void qdf_spinlock_destroy(qdf_spinlock_t *lock)
  189. {
  190. qdf_lock_stats_destroy(&lock->stats);
  191. __qdf_spinlock_destroy(&lock->lock);
  192. }
  193. /**
  194. * qdf_spin_is_locked() - check if the spinlock is locked
  195. * @lock: spinlock object
  196. *
  197. * Return: nonzero if lock is held.
  198. */
  199. static inline int qdf_spin_is_locked(qdf_spinlock_t *lock)
  200. {
  201. return __qdf_spin_is_locked(&lock->lock);
  202. }
  203. /**
  204. * qdf_spin_trylock_bh() - spin trylock bottomhalf
  205. * @lock: spinlock object
  206. *
  207. * Return: nonzero if lock is acquired
  208. */
  209. static inline int qdf_spin_trylock_bh(qdf_spinlock_t *lock)
  210. {
  211. return __qdf_spin_trylock_bh(&lock->lock);
  212. }
  213. int qdf_spin_trylock_bh_outline(qdf_spinlock_t *lock);
  214. /**
  215. * qdf_spin_lock_bh() - locks the spinlock mutex in soft irq context
  216. * @lock: spinlock object pointer
  217. * Return: none
  218. */
  219. static inline void qdf_spin_lock_bh(qdf_spinlock_t *lock)
  220. {
  221. BEFORE_LOCK(lock, qdf_spin_is_locked(lock));
  222. __qdf_spin_lock_bh(&lock->lock);
  223. AFTER_LOCK(lock);
  224. }
  225. void qdf_spin_lock_bh_outline(qdf_spinlock_t *lock);
  226. /**
  227. * qdf_spin_unlock_bh() - unlocks the spinlock mutex in soft irq context
  228. * @lock: spinlock object pointer
  229. * Return: none
  230. */
  231. static inline void qdf_spin_unlock_bh(qdf_spinlock_t *lock)
  232. {
  233. BEFORE_UNLOCK(lock, QDF_MAX_HOLD_TIME_ALOWED_SPINLOCK_BH);
  234. __qdf_spin_unlock_bh(&lock->lock);
  235. }
  236. void qdf_spin_unlock_bh_outline(qdf_spinlock_t *lock);
  237. /**
  238. * qdf_spinlock_irq_exec - Execute the input function with spinlock held
  239. * and interrupt disabled.
  240. * @hdl: OS handle
  241. * @lock: spinlock to be held for the critical region
  242. * @func: critical region function that to be executed
  243. * @context: context of the critical region function
  244. * Return: Boolean status returned by the critical region function
  245. */
  246. static inline bool qdf_spinlock_irq_exec(qdf_handle_t hdl,
  247. qdf_spinlock_t *lock,
  248. qdf_irqlocked_func_t func, void *arg)
  249. {
  250. return __qdf_spinlock_irq_exec(hdl, &lock->lock, func, arg);
  251. }
  252. /**
  253. * qdf_spin_lock() - Acquire a Spinlock(SMP) & disable Preemption (Preemptive)
  254. * @lock: Lock object
  255. *
  256. * Return: none
  257. */
  258. static inline void qdf_spin_lock(qdf_spinlock_t *lock)
  259. {
  260. BEFORE_LOCK(lock, qdf_spin_is_locked(lock));
  261. __qdf_spin_lock(&lock->lock);
  262. AFTER_LOCK(lock);
  263. }
  264. /**
  265. * qdf_spin_unlock() - Unlock the spinlock and enables the Preemption
  266. * @lock: Lock object
  267. *
  268. * Return: none
  269. */
  270. static inline void qdf_spin_unlock(qdf_spinlock_t *lock)
  271. {
  272. BEFORE_UNLOCK(lock, QDF_MAX_HOLD_TIME_ALOWED_SPINLOCK);
  273. __qdf_spin_unlock(&lock->lock);
  274. }
  275. /**
  276. * qdf_spin_lock_irq() - Acquire a Spinlock(SMP) & save the irq state
  277. * @lock: Lock object
  278. * @flags: flags
  279. *
  280. * Return: none
  281. */
  282. static inline void qdf_spin_lock_irq(qdf_spinlock_t *lock, unsigned long flags)
  283. {
  284. BEFORE_LOCK(lock, qdf_spin_is_locked(lock));
  285. __qdf_spin_lock_irq(&lock->lock.spinlock, flags);
  286. AFTER_LOCK(lock);
  287. }
  288. /**
  289. * qdf_spin_lock_irqsave() - Acquire a Spinlock (SMP) & disable Preemption
  290. * (Preemptive) and disable IRQs
  291. * @lock: Lock object
  292. *
  293. * Return: none
  294. */
  295. static inline void qdf_spin_lock_irqsave(qdf_spinlock_t *lock)
  296. {
  297. BEFORE_LOCK(lock, qdf_spin_is_locked(lock));
  298. __qdf_spin_lock_irqsave(&lock->lock);
  299. AFTER_LOCK(lock);
  300. }
  301. /**
  302. * qdf_spin_unlock_irqrestore() - Unlock the spinlock and enables the
  303. * Preemption and enable IRQ
  304. * @lock: Lock object
  305. *
  306. * Return: none
  307. */
  308. static inline void qdf_spin_unlock_irqrestore(qdf_spinlock_t *lock)
  309. {
  310. BEFORE_UNLOCK(lock, QDF_MAX_HOLD_TIME_ALOWED_SPINLOCK_IRQ);
  311. __qdf_spin_unlock_irqrestore(&lock->lock);
  312. }
  313. /**
  314. * qdf_spin_unlock_irq() - Unlock a Spinlock(SMP) & save the restore state
  315. * @lock: Lock object
  316. * @flags: flags
  317. *
  318. * Return: none
  319. */
  320. static inline void qdf_spin_unlock_irq(qdf_spinlock_t *lock,
  321. unsigned long flags)
  322. {
  323. BEFORE_UNLOCK(lock, QDF_MAX_HOLD_TIME_ALOWED_SPINLOCK_IRQ);
  324. __qdf_spin_unlock_irq(&lock->lock.spinlock, flags);
  325. }
  326. /**
  327. * qdf_semaphore_init() - initialize a semaphore
  328. * @m: Semaphore to initialize
  329. * Return: None
  330. */
  331. static inline void qdf_semaphore_init(qdf_semaphore_t *m)
  332. {
  333. __qdf_semaphore_init(m);
  334. }
  335. /**
  336. * qdf_semaphore_acquire() - take the semaphore
  337. * @m: Semaphore to take
  338. * Return: int
  339. */
  340. static inline int qdf_semaphore_acquire(qdf_semaphore_t *m)
  341. {
  342. return __qdf_semaphore_acquire(m);
  343. }
  344. /**
  345. * qdf_semaphore_release() - give the semaphore
  346. * @m: Semaphore to give
  347. * Return: None
  348. */
  349. static inline void qdf_semaphore_release(qdf_semaphore_t *m)
  350. {
  351. __qdf_semaphore_release(m);
  352. }
  353. /**
  354. * qdf_semaphore_acquire_intr - Take the semaphore, interruptible version
  355. * @osdev: OS Device
  356. * @m: mutex to take
  357. * Return: int
  358. */
  359. static inline int qdf_semaphore_acquire_intr(qdf_semaphore_t *m)
  360. {
  361. return __qdf_semaphore_acquire_intr(m);
  362. }
  363. QDF_STATUS qdf_wake_lock_create(qdf_wake_lock_t *lock, const char *name);
  364. QDF_STATUS qdf_wake_lock_acquire(qdf_wake_lock_t *lock, uint32_t reason);
  365. const char *qdf_wake_lock_name(qdf_wake_lock_t *lock);
  366. QDF_STATUS qdf_wake_lock_timeout_acquire(qdf_wake_lock_t *lock,
  367. uint32_t msec);
  368. QDF_STATUS qdf_wake_lock_release(qdf_wake_lock_t *lock, uint32_t reason);
  369. QDF_STATUS qdf_wake_lock_destroy(qdf_wake_lock_t *lock);
  370. struct hif_pm_runtime_lock;
  371. typedef struct hif_pm_runtime_lock *qdf_runtime_lock_t;
  372. QDF_STATUS qdf_runtime_pm_get(void);
  373. QDF_STATUS qdf_runtime_pm_put(void);
  374. QDF_STATUS qdf_runtime_pm_prevent_suspend(qdf_runtime_lock_t lock);
  375. QDF_STATUS qdf_runtime_pm_allow_suspend(qdf_runtime_lock_t lock);
  376. qdf_runtime_lock_t qdf_runtime_lock_init(const char *name);
  377. void qdf_runtime_lock_deinit(qdf_runtime_lock_t lock);
  378. QDF_STATUS qdf_spinlock_acquire(qdf_spinlock_t *lock);
  379. QDF_STATUS qdf_spinlock_release(qdf_spinlock_t *lock);
  380. #endif /* _QDF_LOCK_H */