qdf_lock.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
  1. /*
  2. * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
  3. * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for
  6. * any purpose with or without fee is hereby granted, provided that the
  7. * above copyright notice and this permission notice appear in all
  8. * copies.
  9. *
  10. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
  11. * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  12. * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
  13. * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  14. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  15. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  16. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  17. * PERFORMANCE OF THIS SOFTWARE.
  18. */
  19. #include <linux/module.h>
  20. #include <qdf_lock.h>
  21. #include <qdf_trace.h>
  22. #include <qdf_module.h>
  23. #include <qdf_types.h>
  24. #include <i_host_diag_core_event.h>
  25. #ifdef FEATURE_RUNTIME_PM
  26. #include <cds_api.h>
  27. #include <hif.h>
  28. #endif
  29. #include <i_qdf_lock.h>
  30. #include <linux/suspend.h>
  31. /**
  32. * qdf_mutex_create() - Initialize a mutex
  33. * @m: mutex to initialize
  34. *
  35. * Returns: QDF_STATUS
  36. * =0 success
  37. * else fail status
  38. */
  39. #undef qdf_mutex_create
  40. QDF_STATUS qdf_mutex_create(qdf_mutex_t *lock, const char *func, int line)
  41. {
  42. /* check for invalid pointer */
  43. if (!lock) {
  44. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  45. "%s: NULL pointer passed in", __func__);
  46. return QDF_STATUS_E_FAULT;
  47. }
  48. /* check for 'already initialized' lock */
  49. if (LINUX_LOCK_COOKIE == lock->cookie) {
  50. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  51. "%s: already initialized lock", __func__);
  52. return QDF_STATUS_E_BUSY;
  53. }
  54. if (in_interrupt()) {
  55. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  56. "%s cannot be called from interrupt context!!!",
  57. __func__);
  58. return QDF_STATUS_E_FAULT;
  59. }
  60. qdf_lock_stats_create(&lock->stats, func, line);
  61. /* initialize new lock */
  62. mutex_init(&lock->m_lock);
  63. lock->cookie = LINUX_LOCK_COOKIE;
  64. lock->state = LOCK_RELEASED;
  65. lock->process_id = 0;
  66. lock->refcount = 0;
  67. return QDF_STATUS_SUCCESS;
  68. }
  69. qdf_export_symbol(qdf_mutex_create);
  70. /**
  71. * qdf_mutex_acquire() - acquire a QDF lock
  72. * @lock: Pointer to the opaque lock object to acquire
  73. *
  74. * A lock object is acquired by calling qdf_mutex_acquire(). If the lock
  75. * is already locked, the calling thread shall block until the lock becomes
  76. * available. This operation shall return with the lock object referenced by
  77. * lock in the locked state with the calling thread as its owner.
  78. *
  79. * Return:
  80. * QDF_STATUS_SUCCESS: lock was successfully initialized
  81. * QDF failure reason codes: lock is not initialized and can't be used
  82. */
  83. QDF_STATUS qdf_mutex_acquire(qdf_mutex_t *lock)
  84. {
  85. int rc;
  86. /* check for invalid pointer */
  87. if (!lock) {
  88. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  89. "%s: NULL pointer passed in", __func__);
  90. QDF_ASSERT(0);
  91. return QDF_STATUS_E_FAULT;
  92. }
  93. /* check if lock refers to an initialized object */
  94. if (LINUX_LOCK_COOKIE != lock->cookie) {
  95. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  96. "%s: uninitialized lock", __func__);
  97. QDF_ASSERT(0);
  98. return QDF_STATUS_E_INVAL;
  99. }
  100. if (in_interrupt()) {
  101. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  102. "%s cannot be called from interrupt context!!!",
  103. __func__);
  104. QDF_ASSERT(0);
  105. return QDF_STATUS_E_FAULT;
  106. }
  107. if ((lock->process_id == current->pid) &&
  108. (lock->state == LOCK_ACQUIRED)) {
  109. lock->refcount++;
  110. #ifdef QDF_NESTED_LOCK_DEBUG
  111. pe_err("%s: %x %d %d", __func__, lock, current->pid,
  112. lock->refcount);
  113. #endif
  114. return QDF_STATUS_SUCCESS;
  115. }
  116. BEFORE_LOCK(lock, mutex_is_locked(&lock->m_lock));
  117. /* acquire a Lock */
  118. mutex_lock(&lock->m_lock);
  119. AFTER_LOCK(lock, __func__);
  120. rc = mutex_is_locked(&lock->m_lock);
  121. if (rc == 0) {
  122. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  123. "%s: unable to lock mutex (rc = %d)", __func__, rc);
  124. QDF_ASSERT(0);
  125. return QDF_STATUS_E_FAILURE;
  126. }
  127. #ifdef QDF_NESTED_LOCK_DEBUG
  128. pe_err("%s: %x %d", __func__, lock, current->pid);
  129. #endif
  130. if (LOCK_DESTROYED != lock->state) {
  131. lock->process_id = current->pid;
  132. lock->refcount++;
  133. lock->state = LOCK_ACQUIRED;
  134. return QDF_STATUS_SUCCESS;
  135. }
  136. /* lock is already destroyed */
  137. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  138. "%s: Lock is already destroyed", __func__);
  139. mutex_unlock(&lock->m_lock);
  140. QDF_ASSERT(0);
  141. return QDF_STATUS_E_FAILURE;
  142. }
  143. qdf_export_symbol(qdf_mutex_acquire);
  144. /**
  145. * qdf_mutex_release() - release a QDF lock
  146. * @lock: Pointer to the opaque lock object to be released
  147. *
  148. * qdf_mutex_release() function shall release the lock object
  149. * referenced by 'lock'.
  150. *
  151. * If a thread attempts to release a lock that it unlocked or is not
  152. * initialized, an error is returned.
  153. *
  154. * Return:
  155. * QDF_STATUS_SUCCESS: lock was successfully initialized
  156. * QDF failure reason codes: lock is not initialized and can't be used
  157. */
  158. QDF_STATUS qdf_mutex_release(qdf_mutex_t *lock)
  159. {
  160. /* check for invalid pointer */
  161. if (!lock) {
  162. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  163. "%s: NULL pointer passed in", __func__);
  164. QDF_ASSERT(0);
  165. return QDF_STATUS_E_FAULT;
  166. }
  167. /* check if lock refers to an uninitialized object */
  168. if (LINUX_LOCK_COOKIE != lock->cookie) {
  169. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  170. "%s: uninitialized lock", __func__);
  171. QDF_ASSERT(0);
  172. return QDF_STATUS_E_INVAL;
  173. }
  174. if (in_interrupt()) {
  175. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  176. "%s cannot be called from interrupt context!!!",
  177. __func__);
  178. QDF_ASSERT(0);
  179. return QDF_STATUS_E_FAULT;
  180. }
  181. /* current_thread = get_current_thread_id();
  182. * Check thread ID of caller against thread ID
  183. * of the thread which acquire the lock
  184. */
  185. if (lock->process_id != current->pid) {
  186. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  187. "%s: current task pid does not match original task pid!!",
  188. __func__);
  189. #ifdef QDF_NESTED_LOCK_DEBUG
  190. pe_err("%s: Lock held by=%d being released by=%d",
  191. __func__, lock->process_id, current->pid);
  192. #endif
  193. QDF_ASSERT(0);
  194. return QDF_STATUS_E_PERM;
  195. }
  196. if ((lock->process_id == current->pid) &&
  197. (lock->state == LOCK_ACQUIRED)) {
  198. if (lock->refcount > 0)
  199. lock->refcount--;
  200. }
  201. #ifdef QDF_NESTED_LOCK_DEBUG
  202. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, "%s: %x %d %d", __func__, lock, lock->process_id,
  203. lock->refcount);
  204. #endif
  205. if (lock->refcount)
  206. return QDF_STATUS_SUCCESS;
  207. lock->process_id = 0;
  208. lock->refcount = 0;
  209. lock->state = LOCK_RELEASED;
  210. /* release a Lock */
  211. BEFORE_UNLOCK(lock, 0);
  212. mutex_unlock(&lock->m_lock);
  213. #ifdef QDF_NESTED_LOCK_DEBUG
  214. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, "%s: Freeing lock %x %d %d", lock, lock->process_id,
  215. lock->refcount);
  216. #endif
  217. return QDF_STATUS_SUCCESS;
  218. }
  219. qdf_export_symbol(qdf_mutex_release);
  220. #ifdef WLAN_WAKE_LOCK_DEBUG
  221. #include "qdf_tracker.h"
  222. #define qdf_wake_lock_tracker_bits 2 /* 4 buckets */
  223. static qdf_tracker_declare(qdf_wake_lock_tracker, qdf_wake_lock_tracker_bits,
  224. "wake lock leaks", "wake lock create",
  225. "wake lock destroy");
  226. void qdf_wake_lock_feature_init(void)
  227. {
  228. qdf_tracker_init(&qdf_wake_lock_tracker);
  229. }
  230. void qdf_wake_lock_feature_deinit(void)
  231. {
  232. qdf_tracker_deinit(&qdf_wake_lock_tracker);
  233. }
  234. void qdf_wake_lock_check_for_leaks(void)
  235. {
  236. qdf_tracker_check_for_leaks(&qdf_wake_lock_tracker);
  237. }
  238. static inline QDF_STATUS qdf_wake_lock_dbg_track(qdf_wake_lock_t *lock,
  239. const char *func,
  240. uint32_t line)
  241. {
  242. return qdf_tracker_track(&qdf_wake_lock_tracker, lock, func, line);
  243. }
  244. static inline void qdf_wake_lock_dbg_untrack(qdf_wake_lock_t *lock,
  245. const char *func, uint32_t line)
  246. {
  247. qdf_tracker_untrack(&qdf_wake_lock_tracker, lock, func, line);
  248. }
  249. #else
  250. static inline QDF_STATUS qdf_wake_lock_dbg_track(qdf_wake_lock_t *lock,
  251. const char *func,
  252. uint32_t line)
  253. {
  254. return QDF_STATUS_SUCCESS;
  255. }
  256. static inline void qdf_wake_lock_dbg_untrack(qdf_wake_lock_t *lock,
  257. const char *func, uint32_t line)
  258. { }
  259. #endif /* WLAN_WAKE_LOCK_DEBUG */
  260. /**
  261. * qdf_wake_lock_name() - This function returns the name of the wakelock
  262. * @lock: Pointer to the wakelock
  263. *
  264. * This function returns the name of the wakelock
  265. *
  266. * Return: Pointer to the name if it is valid or a default string
  267. */
  268. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
  269. const char *qdf_wake_lock_name(qdf_wake_lock_t *lock)
  270. {
  271. if (lock)
  272. return lock->lock.name;
  273. return "UNNAMED_WAKELOCK";
  274. }
  275. #else
  276. const char *qdf_wake_lock_name(qdf_wake_lock_t *lock)
  277. {
  278. return "NO_WAKELOCK_SUPPORT";
  279. }
  280. #endif
  281. qdf_export_symbol(qdf_wake_lock_name);
  282. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 110)) || \
  283. defined(WAKEUP_SOURCE_DEV)
  284. QDF_STATUS __qdf_wake_lock_create(qdf_wake_lock_t *lock, const char *name,
  285. const char *func, uint32_t line)
  286. {
  287. QDF_STATUS status;
  288. status = qdf_wake_lock_dbg_track(lock, func, line);
  289. if (QDF_IS_STATUS_ERROR(status))
  290. return status;
  291. qdf_mem_zero(lock, sizeof(*lock));
  292. lock->priv = wakeup_source_register(lock->lock.dev, name);
  293. if (!(lock->priv)) {
  294. QDF_BUG(0);
  295. return QDF_STATUS_E_FAILURE;
  296. }
  297. lock->lock = *(lock->priv);
  298. return QDF_STATUS_SUCCESS;
  299. }
  300. #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
  301. QDF_STATUS __qdf_wake_lock_create(qdf_wake_lock_t *lock, const char *name,
  302. const char *func, uint32_t line)
  303. {
  304. QDF_STATUS status;
  305. status = qdf_wake_lock_dbg_track(lock, func, line);
  306. if (QDF_IS_STATUS_ERROR(status))
  307. return status;
  308. wakeup_source_init(&(lock->lock), name);
  309. lock->priv = &(lock->lock);
  310. return QDF_STATUS_SUCCESS;
  311. }
  312. #else
  313. QDF_STATUS __qdf_wake_lock_create(qdf_wake_lock_t *lock, const char *name,
  314. const char *func, uint32_t line)
  315. {
  316. return QDF_STATUS_SUCCESS;
  317. }
  318. #endif
  319. qdf_export_symbol(__qdf_wake_lock_create);
  320. /**
  321. * qdf_wake_lock_acquire() - acquires a wake lock
  322. * @lock: The wake lock to acquire
  323. * @reason: Reason for wakelock
  324. *
  325. * Return:
  326. * QDF status success: if wake lock is acquired
  327. * QDF status failure: if wake lock was not acquired
  328. */
  329. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
  330. QDF_STATUS qdf_wake_lock_acquire(qdf_wake_lock_t *lock, uint32_t reason)
  331. {
  332. host_diag_log_wlock(reason, qdf_wake_lock_name(lock),
  333. WIFI_POWER_EVENT_DEFAULT_WAKELOCK_TIMEOUT,
  334. WIFI_POWER_EVENT_WAKELOCK_TAKEN);
  335. __pm_stay_awake(lock->priv);
  336. return QDF_STATUS_SUCCESS;
  337. }
  338. #else
  339. QDF_STATUS qdf_wake_lock_acquire(qdf_wake_lock_t *lock, uint32_t reason)
  340. {
  341. return QDF_STATUS_SUCCESS;
  342. }
  343. #endif
  344. qdf_export_symbol(qdf_wake_lock_acquire);
  345. /**
  346. * qdf_wake_lock_timeout_acquire() - acquires a wake lock with a timeout
  347. * @lock: The wake lock to acquire
  348. * @reason: Reason for wakelock
  349. *
  350. * Return:
  351. * QDF status success: if wake lock is acquired
  352. * QDF status failure: if wake lock was not acquired
  353. */
  354. #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
  355. QDF_STATUS qdf_wake_lock_timeout_acquire(qdf_wake_lock_t *lock, uint32_t msec)
  356. {
  357. pm_wakeup_ws_event(lock->priv, msec, true);
  358. return QDF_STATUS_SUCCESS;
  359. }
  360. #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
  361. QDF_STATUS qdf_wake_lock_timeout_acquire(qdf_wake_lock_t *lock, uint32_t msec)
  362. {
  363. /* Wakelock for Rx is frequent.
  364. * It is reported only during active debug
  365. */
  366. __pm_wakeup_event(&(lock->lock), msec);
  367. return QDF_STATUS_SUCCESS;
  368. }
  369. #else /* LINUX_VERSION_CODE */
  370. QDF_STATUS qdf_wake_lock_timeout_acquire(qdf_wake_lock_t *lock, uint32_t msec)
  371. {
  372. return QDF_STATUS_SUCCESS;
  373. }
  374. #endif /* LINUX_VERSION_CODE */
  375. qdf_export_symbol(qdf_wake_lock_timeout_acquire);
  376. /**
  377. * qdf_wake_lock_release() - releases a wake lock
  378. * @lock: the wake lock to release
  379. * @reason: Reason for wakelock
  380. *
  381. * Return:
  382. * QDF status success: if wake lock is acquired
  383. * QDF status failure: if wake lock was not acquired
  384. */
  385. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
  386. QDF_STATUS qdf_wake_lock_release(qdf_wake_lock_t *lock, uint32_t reason)
  387. {
  388. host_diag_log_wlock(reason, qdf_wake_lock_name(lock),
  389. WIFI_POWER_EVENT_DEFAULT_WAKELOCK_TIMEOUT,
  390. WIFI_POWER_EVENT_WAKELOCK_RELEASED);
  391. __pm_relax(lock->priv);
  392. return QDF_STATUS_SUCCESS;
  393. }
  394. #else
  395. QDF_STATUS qdf_wake_lock_release(qdf_wake_lock_t *lock, uint32_t reason)
  396. {
  397. return QDF_STATUS_SUCCESS;
  398. }
  399. #endif
  400. qdf_export_symbol(qdf_wake_lock_release);
  401. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 110)) || \
  402. defined(WAKEUP_SOURCE_DEV)
  403. void __qdf_wake_lock_destroy(qdf_wake_lock_t *lock,
  404. const char *func, uint32_t line)
  405. {
  406. wakeup_source_unregister(lock->priv);
  407. qdf_wake_lock_dbg_untrack(lock, func, line);
  408. }
  409. #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
  410. void __qdf_wake_lock_destroy(qdf_wake_lock_t *lock,
  411. const char *func, uint32_t line)
  412. {
  413. wakeup_source_trash(&(lock->lock));
  414. qdf_wake_lock_dbg_untrack(lock, func, line);
  415. }
  416. #else
  417. void __qdf_wake_lock_destroy(qdf_wake_lock_t *lock,
  418. const char *func, uint32_t line)
  419. {
  420. }
  421. #endif
  422. qdf_export_symbol(__qdf_wake_lock_destroy);
  423. /**
  424. * qdf_pm_system_wakeup() - wakeup system
  425. *
  426. * Return: None
  427. */
  428. void qdf_pm_system_wakeup(void)
  429. {
  430. pm_system_wakeup();
  431. }
  432. qdf_export_symbol(qdf_pm_system_wakeup);
  433. #ifdef FEATURE_RUNTIME_PM
  434. /**
  435. * qdf_to_hif_convert_trpm_id() - Convert QDF Runtime PM ID to HIF RTPM ID
  436. * @id: Client id
  437. *
  438. * Return: HIF Runtime pm ID of client
  439. */
  440. static uint32_t qdf_to_hif_convert_rtpm_id(uint32_t id)
  441. {
  442. switch (id) {
  443. case QDF_RTPM_ID_RESERVED:
  444. return HIF_RTPM_ID_RESERVED;
  445. case QDF_RTPM_ID_PM_QOS_NOTIFY:
  446. return HIF_RTPM_ID_PM_QOS_NOTIFY;
  447. case QDF_RTPM_ID_WIPHY_SUSPEND:
  448. return HIF_RTPM_ID_WIPHY_SUSPEND;
  449. default:
  450. return HIF_RTPM_ID_MAX;
  451. }
  452. }
  453. /**
  454. * qdf_to_hif_convert_rtpm_type() - Convert QDF Runtime PM call type to HIF
  455. * call type
  456. * @type: call type
  457. *
  458. * Return: HIF runtime PM call type
  459. */
  460. static uint8_t qdf_to_hif_convert_rtpm_type(uint8_t type)
  461. {
  462. switch (type) {
  463. case QDF_RTPM_GET:
  464. return HIF_RTPM_GET_ASYNC;
  465. case QDF_RTPM_GET_FORCE:
  466. return HIF_RTPM_GET_FORCE;
  467. case QDF_RTPM_GET_SYNC:
  468. return HIF_RTPM_GET_SYNC;
  469. case QDF_RTPM_GET_NORESUME:
  470. return HIF_RTPM_GET_NORESUME;
  471. case QDF_RTPM_PUT:
  472. return HIF_RTPM_PUT_ASYNC;
  473. case QDF_RTPM_PUT_SYNC_SUSPEND:
  474. return HIF_RTPM_PUT_SYNC_SUSPEND;
  475. case QDF_RTPM_PUT_NOIDLE:
  476. return HIF_RTPM_PUT_NOIDLE;
  477. default:
  478. return QDF_STATUS_E_NOSUPPORT;
  479. }
  480. }
  481. QDF_STATUS qdf_rtpm_register(uint32_t id, void (*hif_rpm_cbk)(void))
  482. {
  483. return hif_rtpm_register(qdf_to_hif_convert_rtpm_id(id), hif_rpm_cbk);
  484. }
  485. qdf_export_symbol(qdf_rtpm_register);
  486. QDF_STATUS qdf_rtpm_deregister(uint32_t id)
  487. {
  488. return hif_rtpm_deregister(qdf_to_hif_convert_rtpm_id(id));
  489. }
  490. qdf_export_symbol(qdf_rtpm_deregister);
  491. QDF_STATUS __qdf_runtime_lock_init(qdf_runtime_lock_t *lock, const char *name)
  492. {
  493. return hif_runtime_lock_init(lock, name);
  494. }
  495. qdf_export_symbol(__qdf_runtime_lock_init);
  496. void qdf_runtime_lock_deinit(qdf_runtime_lock_t *lock)
  497. {
  498. hif_runtime_lock_deinit(lock->lock);
  499. }
  500. qdf_export_symbol(qdf_runtime_lock_deinit);
  501. QDF_STATUS qdf_rtpm_get(uint8_t type, uint32_t id)
  502. {
  503. return hif_rtpm_get(qdf_to_hif_convert_rtpm_type(type),
  504. qdf_to_hif_convert_rtpm_id(id));
  505. }
  506. qdf_export_symbol(qdf_rtpm_get);
  507. QDF_STATUS qdf_rtpm_put(uint8_t type, uint32_t id)
  508. {
  509. return hif_rtpm_put(qdf_to_hif_convert_rtpm_type(type),
  510. qdf_to_hif_convert_rtpm_id(id));
  511. }
  512. qdf_export_symbol(qdf_rtpm_put);
  513. QDF_STATUS qdf_runtime_pm_prevent_suspend(qdf_runtime_lock_t *lock)
  514. {
  515. return hif_pm_runtime_prevent_suspend(lock->lock);
  516. }
  517. qdf_export_symbol(qdf_runtime_pm_prevent_suspend);
  518. QDF_STATUS qdf_runtime_pm_allow_suspend(qdf_runtime_lock_t *lock)
  519. {
  520. return hif_pm_runtime_allow_suspend(lock->lock);
  521. }
  522. qdf_export_symbol(qdf_runtime_pm_allow_suspend);
  523. QDF_STATUS qdf_rtpm_sync_resume(void)
  524. {
  525. return hif_rtpm_sync_resume();
  526. }
  527. #endif
  528. /**
  529. * qdf_spinlock_acquire() - acquires a spin lock
  530. * @lock: Spin lock to acquire
  531. *
  532. * Return:
  533. * QDF status success: if wake lock is acquired
  534. */
  535. QDF_STATUS qdf_spinlock_acquire(qdf_spinlock_t *lock)
  536. {
  537. spin_lock(&lock->lock.spinlock);
  538. return QDF_STATUS_SUCCESS;
  539. }
  540. qdf_export_symbol(qdf_spinlock_acquire);
  541. /**
  542. * qdf_spinlock_release() - release a spin lock
  543. * @lock: Spin lock to release
  544. *
  545. * Return:
  546. * QDF status success : if wake lock is acquired
  547. */
  548. QDF_STATUS qdf_spinlock_release(qdf_spinlock_t *lock)
  549. {
  550. spin_unlock(&lock->lock.spinlock);
  551. return QDF_STATUS_SUCCESS;
  552. }
  553. qdf_export_symbol(qdf_spinlock_release);
  554. /**
  555. * qdf_mutex_destroy() - destroy a QDF lock
  556. * @lock: Pointer to the opaque lock object to be destroyed
  557. *
  558. * function shall destroy the lock object referenced by lock. After a
  559. * successful return from qdf_mutex_destroy()
  560. * the lock object becomes, in effect, uninitialized.
  561. *
  562. * A destroyed lock object can be reinitialized using qdf_mutex_create();
  563. * the results of otherwise referencing the object after it has been destroyed
  564. * are undefined. Calls to QDF lock functions to manipulate the lock such
  565. * as qdf_mutex_acquire() will fail if the lock is destroyed. Therefore,
  566. * don't use the lock after it has been destroyed until it has
  567. * been re-initialized.
  568. *
  569. * Return:
  570. * QDF_STATUS_SUCCESS: lock was successfully initialized
  571. * QDF failure reason codes: lock is not initialized and can't be used
  572. */
  573. QDF_STATUS qdf_mutex_destroy(qdf_mutex_t *lock)
  574. {
  575. /* check for invalid pointer */
  576. if (!lock) {
  577. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  578. "%s: NULL pointer passed in", __func__);
  579. return QDF_STATUS_E_FAULT;
  580. }
  581. if (LINUX_LOCK_COOKIE != lock->cookie) {
  582. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  583. "%s: uninitialized lock", __func__);
  584. return QDF_STATUS_E_INVAL;
  585. }
  586. if (in_interrupt()) {
  587. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  588. "%s cannot be called from interrupt context!!!",
  589. __func__);
  590. return QDF_STATUS_E_FAULT;
  591. }
  592. /* check if lock is released */
  593. if (!mutex_trylock(&lock->m_lock)) {
  594. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  595. "%s: lock is not released", __func__);
  596. return QDF_STATUS_E_BUSY;
  597. }
  598. lock->cookie = 0;
  599. lock->state = LOCK_DESTROYED;
  600. lock->process_id = 0;
  601. lock->refcount = 0;
  602. qdf_lock_stats_destroy(&lock->stats);
  603. mutex_unlock(&lock->m_lock);
  604. return QDF_STATUS_SUCCESS;
  605. }
  606. qdf_export_symbol(qdf_mutex_destroy);
  607. #if QDF_LOCK_STATS_LIST
  608. struct qdf_lock_cookie {
  609. union {
  610. struct {
  611. struct lock_stats *stats;
  612. const char *func;
  613. int line;
  614. } cookie;
  615. struct {
  616. struct qdf_lock_cookie *next;
  617. } empty_node;
  618. } u;
  619. };
  620. #ifndef QDF_LOCK_STATS_LIST_SIZE
  621. #define QDF_LOCK_STATS_LIST_SIZE 256
  622. #endif
  623. static qdf_spinlock_t qdf_lock_list_spinlock;
  624. static struct qdf_lock_cookie lock_cookies[QDF_LOCK_STATS_LIST_SIZE];
  625. static struct qdf_lock_cookie *lock_cookie_freelist;
  626. static qdf_atomic_t lock_cookie_get_failures;
  627. static qdf_atomic_t lock_cookie_untracked_num;
  628. /* dummy value */
  629. #define DUMMY_LOCK_COOKIE 0xc00c1e
  630. /**
  631. * qdf_is_lock_cookie - check if memory is a valid lock cookie
  632. *
  633. * return true if the memory is within the range of the lock cookie
  634. * memory.
  635. */
  636. static bool qdf_is_lock_cookie(struct qdf_lock_cookie *lock_cookie)
  637. {
  638. return lock_cookie >= &lock_cookies[0] &&
  639. lock_cookie <= &lock_cookies[QDF_LOCK_STATS_LIST_SIZE-1];
  640. }
  641. /**
  642. * qdf_is_lock_cookie_free() - check if the lock cookie is on the freelist
  643. * @lock_cookie: lock cookie to check
  644. *
  645. * Check that the next field of the lock cookie points to a lock cookie.
  646. * currently this is only true if the cookie is on the freelist.
  647. *
  648. * Checking for the function and line being NULL and 0 should also have worked.
  649. */
  650. static bool qdf_is_lock_cookie_free(struct qdf_lock_cookie *lock_cookie)
  651. {
  652. struct qdf_lock_cookie *tmp = lock_cookie->u.empty_node.next;
  653. return qdf_is_lock_cookie(tmp) || (!tmp);
  654. }
  655. static struct qdf_lock_cookie *qdf_get_lock_cookie(void)
  656. {
  657. struct qdf_lock_cookie *lock_cookie;
  658. qdf_spin_lock_bh(&qdf_lock_list_spinlock);
  659. lock_cookie = lock_cookie_freelist;
  660. if (lock_cookie_freelist)
  661. lock_cookie_freelist = lock_cookie_freelist->u.empty_node.next;
  662. qdf_spin_unlock_bh(&qdf_lock_list_spinlock);
  663. return lock_cookie;
  664. }
  665. static void __qdf_put_lock_cookie(struct qdf_lock_cookie *lock_cookie)
  666. {
  667. if (!qdf_is_lock_cookie(lock_cookie))
  668. QDF_BUG(0);
  669. lock_cookie->u.empty_node.next = lock_cookie_freelist;
  670. lock_cookie_freelist = lock_cookie;
  671. }
  672. static void qdf_put_lock_cookie(struct qdf_lock_cookie *lock_cookie)
  673. {
  674. qdf_spin_lock_bh(&qdf_lock_list_spinlock);
  675. __qdf_put_lock_cookie(lock_cookie);
  676. qdf_spin_unlock_bh(&qdf_lock_list_spinlock);
  677. }
  678. void qdf_lock_stats_init(void)
  679. {
  680. int i;
  681. for (i = 0; i < QDF_LOCK_STATS_LIST_SIZE; i++)
  682. __qdf_put_lock_cookie(&lock_cookies[i]);
  683. /* stats must be allocated for the spinlock before the cookie,
  684. * otherwise this qdf_lock_list_spinlock wouldnt get initialized
  685. * properly
  686. */
  687. qdf_spinlock_create(&qdf_lock_list_spinlock);
  688. qdf_atomic_init(&lock_cookie_get_failures);
  689. qdf_atomic_init(&lock_cookie_untracked_num);
  690. }
  691. void qdf_lock_stats_deinit(void)
  692. {
  693. int i;
  694. qdf_spinlock_destroy(&qdf_lock_list_spinlock);
  695. for (i = 0; i < QDF_LOCK_STATS_LIST_SIZE; i++) {
  696. if (!qdf_is_lock_cookie_free(&lock_cookies[i]))
  697. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG,
  698. "%s: lock_not_destroyed, fun: %s, line %d",
  699. __func__, lock_cookies[i].u.cookie.func,
  700. lock_cookies[i].u.cookie.line);
  701. }
  702. lock_cookie_freelist = NULL;
  703. }
  704. /* allocated separate memory in case the lock memory is freed without
  705. * running the deinitialization code. The cookie list will not be
  706. * corrupted.
  707. */
  708. void qdf_lock_stats_cookie_create(struct lock_stats *stats,
  709. const char *func, int line)
  710. {
  711. struct qdf_lock_cookie *cookie = qdf_get_lock_cookie();
  712. if (!cookie) {
  713. int count;
  714. qdf_atomic_inc(&lock_cookie_get_failures);
  715. count = qdf_atomic_inc_return(&lock_cookie_untracked_num);
  716. stats->cookie = (void *) DUMMY_LOCK_COOKIE;
  717. return;
  718. }
  719. stats->cookie = cookie;
  720. stats->cookie->u.cookie.stats = stats;
  721. stats->cookie->u.cookie.func = func;
  722. stats->cookie->u.cookie.line = line;
  723. }
  724. qdf_export_symbol(qdf_lock_stats_cookie_create);
  725. void qdf_lock_stats_cookie_destroy(struct lock_stats *stats)
  726. {
  727. struct qdf_lock_cookie *cookie = stats->cookie;
  728. if (!cookie) {
  729. QDF_DEBUG_PANIC("Lock destroyed twice or never created");
  730. return;
  731. }
  732. stats->cookie = NULL;
  733. if (cookie == (void *)DUMMY_LOCK_COOKIE) {
  734. qdf_atomic_dec(&lock_cookie_untracked_num);
  735. return;
  736. }
  737. cookie->u.cookie.stats = NULL;
  738. cookie->u.cookie.func = NULL;
  739. cookie->u.cookie.line = 0;
  740. qdf_put_lock_cookie(cookie);
  741. }
  742. qdf_export_symbol(qdf_lock_stats_cookie_destroy);
  743. #endif