xref: /wlan-dirver/qca-wifi-host-cmn/qdf/linux/src/qdf_lock.c (revision d94f0fb619d3da5ae22f9943f88d4634e2d28581)
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 
20 #include <linux/module.h>
21 #include <qdf_lock.h>
22 #include <qdf_trace.h>
23 #include <qdf_module.h>
24 
25 #include <qdf_types.h>
26 #include <i_host_diag_core_event.h>
27 #ifdef FEATURE_RUNTIME_PM
28 #include <cds_api.h>
29 #include <hif.h>
30 #endif
31 #include <i_qdf_lock.h>
32 #include <linux/suspend.h>
33 
34 /**
35  * qdf_mutex_create() - Initialize a mutex
36  * @m: mutex to initialize
37  *
38  * Returns: QDF_STATUS
39  * =0 success
40  * else fail status
41  */
42 #undef qdf_mutex_create
43 QDF_STATUS qdf_mutex_create(qdf_mutex_t *lock, const char *func, int line)
44 {
45 	/* check for invalid pointer */
46 	if (!lock) {
47 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
48 			  "%s: NULL pointer passed in", __func__);
49 		return QDF_STATUS_E_FAULT;
50 	}
51 	/* check for 'already initialized' lock */
52 	if (LINUX_LOCK_COOKIE == lock->cookie) {
53 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
54 			  "%s: already initialized lock", __func__);
55 		return QDF_STATUS_E_BUSY;
56 	}
57 
58 	if (in_interrupt()) {
59 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
60 			  "%s cannot be called from interrupt context!!!",
61 			  __func__);
62 		return QDF_STATUS_E_FAULT;
63 	}
64 
65 	qdf_lock_stats_create(&lock->stats, func, line);
66 
67 	/* initialize new lock */
68 	mutex_init(&lock->m_lock);
69 	lock->cookie = LINUX_LOCK_COOKIE;
70 	lock->state = LOCK_RELEASED;
71 	lock->process_id = 0;
72 	lock->refcount = 0;
73 
74 	return QDF_STATUS_SUCCESS;
75 }
76 qdf_export_symbol(qdf_mutex_create);
77 
78 /**
79  * qdf_mutex_acquire() - acquire a QDF lock
80  * @lock: Pointer to the opaque lock object to acquire
81  *
82  * A lock object is acquired by calling qdf_mutex_acquire().  If the lock
83  * is already locked, the calling thread shall block until the lock becomes
84  * available. This operation shall return with the lock object referenced by
85  * lock in the locked state with the calling thread as its owner.
86  *
87  * Return:
88  * QDF_STATUS_SUCCESS: lock was successfully initialized
89  * QDF failure reason codes: lock is not initialized and can't be used
90  */
91 QDF_STATUS qdf_mutex_acquire(qdf_mutex_t *lock)
92 {
93 	int rc;
94 	/* check for invalid pointer */
95 	if (!lock) {
96 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
97 			  "%s: NULL pointer passed in", __func__);
98 		QDF_ASSERT(0);
99 		return QDF_STATUS_E_FAULT;
100 	}
101 	/* check if lock refers to an initialized object */
102 	if (LINUX_LOCK_COOKIE != lock->cookie) {
103 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
104 			  "%s: uninitialized lock", __func__);
105 		QDF_ASSERT(0);
106 		return QDF_STATUS_E_INVAL;
107 	}
108 
109 	if (in_interrupt()) {
110 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
111 			  "%s cannot be called from interrupt context!!!",
112 			  __func__);
113 		QDF_ASSERT(0);
114 		return QDF_STATUS_E_FAULT;
115 	}
116 	if ((lock->process_id == current->pid) &&
117 		(lock->state == LOCK_ACQUIRED)) {
118 		lock->refcount++;
119 #ifdef QDF_NESTED_LOCK_DEBUG
120 			pe_err("%s: %x %d %d", __func__, lock, current->pid,
121 			  lock->refcount);
122 #endif
123 		return QDF_STATUS_SUCCESS;
124 	}
125 
126 	BEFORE_LOCK(lock, mutex_is_locked(&lock->m_lock));
127 	/* acquire a Lock */
128 	mutex_lock(&lock->m_lock);
129 	AFTER_LOCK(lock, __func__);
130 	rc = mutex_is_locked(&lock->m_lock);
131 	if (rc == 0) {
132 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
133 			  "%s: unable to lock mutex (rc = %d)", __func__, rc);
134 		QDF_ASSERT(0);
135 		return QDF_STATUS_E_FAILURE;
136 	}
137 #ifdef QDF_NESTED_LOCK_DEBUG
138 		pe_err("%s: %x %d", __func__, lock, current->pid);
139 #endif
140 	if (LOCK_DESTROYED != lock->state) {
141 		lock->process_id = current->pid;
142 		lock->refcount++;
143 		lock->state = LOCK_ACQUIRED;
144 		return QDF_STATUS_SUCCESS;
145 	}
146 
147 	/* lock is already destroyed */
148 	QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
149 		  "%s: Lock is already destroyed", __func__);
150 	mutex_unlock(&lock->m_lock);
151 	QDF_ASSERT(0);
152 	return QDF_STATUS_E_FAILURE;
153 }
154 qdf_export_symbol(qdf_mutex_acquire);
155 
156 /**
157  * qdf_mutex_release() - release a QDF lock
158  * @lock: Pointer to the opaque lock object to be released
159  *
160  * qdf_mutex_release() function shall release the lock object
161  * referenced by 'lock'.
162  *
163  * If a thread attempts to release a lock that it unlocked or is not
164  * initialized, an error is returned.
165  *
166  * Return:
167  * QDF_STATUS_SUCCESS: lock was successfully initialized
168  * QDF failure reason codes: lock is not initialized and can't be used
169  */
170 QDF_STATUS qdf_mutex_release(qdf_mutex_t *lock)
171 {
172 	/* check for invalid pointer */
173 	if (!lock) {
174 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
175 			  "%s: NULL pointer passed in", __func__);
176 		QDF_ASSERT(0);
177 		return QDF_STATUS_E_FAULT;
178 	}
179 
180 	/* check if lock refers to an uninitialized object */
181 	if (LINUX_LOCK_COOKIE != lock->cookie) {
182 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
183 			  "%s: uninitialized lock", __func__);
184 		QDF_ASSERT(0);
185 		return QDF_STATUS_E_INVAL;
186 	}
187 
188 	if (in_interrupt()) {
189 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
190 			  "%s cannot be called from interrupt context!!!",
191 			  __func__);
192 		QDF_ASSERT(0);
193 		return QDF_STATUS_E_FAULT;
194 	}
195 
196 	/* current_thread = get_current_thread_id();
197 	 * Check thread ID of caller against thread ID
198 	 * of the thread which acquire the lock
199 	 */
200 	if (lock->process_id != current->pid) {
201 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
202 			  "%s: current task pid does not match original task pid!!",
203 			  __func__);
204 #ifdef QDF_NESTED_LOCK_DEBUG
205 		pe_err("%s: Lock held by=%d being released by=%d",
206 			  __func__, lock->process_id, current->pid);
207 #endif
208 		QDF_ASSERT(0);
209 		return QDF_STATUS_E_PERM;
210 	}
211 	if ((lock->process_id == current->pid) &&
212 		(lock->state == LOCK_ACQUIRED)) {
213 		if (lock->refcount > 0)
214 			lock->refcount--;
215 	}
216 #ifdef QDF_NESTED_LOCK_DEBUG
217 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, "%s: %x %d %d", __func__, lock, lock->process_id,
218 		  lock->refcount);
219 #endif
220 	if (lock->refcount)
221 		return QDF_STATUS_SUCCESS;
222 
223 	lock->process_id = 0;
224 	lock->refcount = 0;
225 	lock->state = LOCK_RELEASED;
226 	/* release a Lock */
227 	BEFORE_UNLOCK(lock, 0);
228 	mutex_unlock(&lock->m_lock);
229 #ifdef QDF_NESTED_LOCK_DEBUG
230 	QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, "%s: Freeing lock %x %d %d", lock, lock->process_id,
231 		  lock->refcount);
232 #endif
233 	return QDF_STATUS_SUCCESS;
234 }
235 qdf_export_symbol(qdf_mutex_release);
236 
237 #ifdef WLAN_WAKE_LOCK_DEBUG
238 #include "qdf_tracker.h"
239 
240 #define qdf_wake_lock_tracker_bits 2 /* 4 buckets */
241 static qdf_tracker_declare(qdf_wake_lock_tracker, qdf_wake_lock_tracker_bits,
242 			   "wake lock leaks", "wake lock create",
243 			   "wake lock destroy");
244 
245 void qdf_wake_lock_feature_init(void)
246 {
247 	qdf_tracker_init(&qdf_wake_lock_tracker);
248 }
249 
250 void qdf_wake_lock_feature_deinit(void)
251 {
252 	qdf_tracker_deinit(&qdf_wake_lock_tracker);
253 }
254 
255 void qdf_wake_lock_check_for_leaks(void)
256 {
257 	qdf_tracker_check_for_leaks(&qdf_wake_lock_tracker);
258 }
259 
260 static inline QDF_STATUS qdf_wake_lock_dbg_track(qdf_wake_lock_t *lock,
261 						 const char *func,
262 						 uint32_t line)
263 {
264 	return qdf_tracker_track(&qdf_wake_lock_tracker, lock, func, line);
265 }
266 
267 static inline void qdf_wake_lock_dbg_untrack(qdf_wake_lock_t *lock,
268 					     const char *func, uint32_t line)
269 {
270 	qdf_tracker_untrack(&qdf_wake_lock_tracker, lock, func, line);
271 }
272 #else
273 static inline QDF_STATUS qdf_wake_lock_dbg_track(qdf_wake_lock_t *lock,
274 						 const char *func,
275 						 uint32_t line)
276 {
277 	return QDF_STATUS_SUCCESS;
278 }
279 
280 static inline void qdf_wake_lock_dbg_untrack(qdf_wake_lock_t *lock,
281 					     const char *func, uint32_t line)
282 { }
283 #endif /* WLAN_WAKE_LOCK_DEBUG */
284 
285 /**
286  * qdf_wake_lock_name() - This function returns the name of the wakelock
287  * @lock: Pointer to the wakelock
288  *
289  * This function returns the name of the wakelock
290  *
291  * Return: Pointer to the name if it is valid or a default string
292  */
293 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
294 const char *qdf_wake_lock_name(qdf_wake_lock_t *lock)
295 {
296 	if (lock)
297 		return lock->lock.name;
298 	return "UNNAMED_WAKELOCK";
299 }
300 #else
301 const char *qdf_wake_lock_name(qdf_wake_lock_t *lock)
302 {
303 	return "NO_WAKELOCK_SUPPORT";
304 }
305 #endif
306 qdf_export_symbol(qdf_wake_lock_name);
307 
308 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 110)) || \
309 	defined(WAKEUP_SOURCE_DEV)
310 QDF_STATUS __qdf_wake_lock_create(qdf_wake_lock_t *lock, const char *name,
311 				  const char *func, uint32_t line)
312 {
313 	QDF_STATUS status;
314 
315 	status = qdf_wake_lock_dbg_track(lock, func, line);
316 	if (QDF_IS_STATUS_ERROR(status))
317 		return status;
318 
319 	qdf_mem_zero(lock, sizeof(*lock));
320 	lock->priv = wakeup_source_register(lock->lock.dev, name);
321 	if (!(lock->priv)) {
322 		QDF_BUG(0);
323 		return QDF_STATUS_E_FAILURE;
324 	}
325 
326 	lock->lock = *(lock->priv);
327 
328 	return QDF_STATUS_SUCCESS;
329 }
330 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
331 QDF_STATUS __qdf_wake_lock_create(qdf_wake_lock_t *lock, const char *name,
332 				  const char *func, uint32_t line)
333 {
334 	QDF_STATUS status;
335 
336 	status = qdf_wake_lock_dbg_track(lock, func, line);
337 	if (QDF_IS_STATUS_ERROR(status))
338 		return status;
339 
340 	wakeup_source_init(&(lock->lock), name);
341 	lock->priv = &(lock->lock);
342 
343 	return QDF_STATUS_SUCCESS;
344 }
345 #else
346 QDF_STATUS __qdf_wake_lock_create(qdf_wake_lock_t *lock, const char *name,
347 				  const char *func, uint32_t line)
348 {
349 	return QDF_STATUS_SUCCESS;
350 }
351 #endif
352 qdf_export_symbol(__qdf_wake_lock_create);
353 
354 /**
355  * qdf_wake_lock_acquire() - acquires a wake lock
356  * @lock: The wake lock to acquire
357  * @reason: Reason for wakelock
358  *
359  * Return:
360  * QDF status success: if wake lock is acquired
361  * QDF status failure: if wake lock was not acquired
362  */
363 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
364 QDF_STATUS qdf_wake_lock_acquire(qdf_wake_lock_t *lock, uint32_t reason)
365 {
366 	host_diag_log_wlock(reason, qdf_wake_lock_name(lock),
367 			    WIFI_POWER_EVENT_DEFAULT_WAKELOCK_TIMEOUT,
368 			    WIFI_POWER_EVENT_WAKELOCK_TAKEN);
369 	__pm_stay_awake(lock->priv);
370 
371 	return QDF_STATUS_SUCCESS;
372 }
373 #else
374 QDF_STATUS qdf_wake_lock_acquire(qdf_wake_lock_t *lock, uint32_t reason)
375 {
376 	return QDF_STATUS_SUCCESS;
377 }
378 #endif
379 qdf_export_symbol(qdf_wake_lock_acquire);
380 
381 /**
382  * qdf_wake_lock_timeout_acquire() - acquires a wake lock with a timeout
383  * @lock: The wake lock to acquire
384  * @reason: Reason for wakelock
385  *
386  * Return:
387  * QDF status success: if wake lock is acquired
388  * QDF status failure: if wake lock was not acquired
389  */
390 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
391 QDF_STATUS qdf_wake_lock_timeout_acquire(qdf_wake_lock_t *lock, uint32_t msec)
392 {
393 	pm_wakeup_ws_event(lock->priv, msec, true);
394 	return QDF_STATUS_SUCCESS;
395 }
396 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
397 QDF_STATUS qdf_wake_lock_timeout_acquire(qdf_wake_lock_t *lock, uint32_t msec)
398 {
399 	/* Wakelock for Rx is frequent.
400 	 * It is reported only during active debug
401 	 */
402 	__pm_wakeup_event(&(lock->lock), msec);
403 	return QDF_STATUS_SUCCESS;
404 }
405 #else /* LINUX_VERSION_CODE */
406 QDF_STATUS qdf_wake_lock_timeout_acquire(qdf_wake_lock_t *lock, uint32_t msec)
407 {
408 	return QDF_STATUS_SUCCESS;
409 }
410 #endif /* LINUX_VERSION_CODE */
411 qdf_export_symbol(qdf_wake_lock_timeout_acquire);
412 
413 /**
414  * qdf_wake_lock_release() - releases a wake lock
415  * @lock: the wake lock to release
416  * @reason: Reason for wakelock
417  *
418  * Return:
419  * QDF status success: if wake lock is acquired
420  * QDF status failure: if wake lock was not acquired
421  */
422 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
423 QDF_STATUS qdf_wake_lock_release(qdf_wake_lock_t *lock, uint32_t reason)
424 {
425 	host_diag_log_wlock(reason, qdf_wake_lock_name(lock),
426 			    WIFI_POWER_EVENT_DEFAULT_WAKELOCK_TIMEOUT,
427 			    WIFI_POWER_EVENT_WAKELOCK_RELEASED);
428 	__pm_relax(lock->priv);
429 
430 	return QDF_STATUS_SUCCESS;
431 }
432 #else
433 QDF_STATUS qdf_wake_lock_release(qdf_wake_lock_t *lock, uint32_t reason)
434 {
435 	return QDF_STATUS_SUCCESS;
436 }
437 #endif
438 qdf_export_symbol(qdf_wake_lock_release);
439 
440 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 110)) || \
441 	defined(WAKEUP_SOURCE_DEV)
442 void __qdf_wake_lock_destroy(qdf_wake_lock_t *lock,
443 			     const char *func, uint32_t line)
444 {
445 	wakeup_source_unregister(lock->priv);
446 	qdf_wake_lock_dbg_untrack(lock, func, line);
447 }
448 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
449 void __qdf_wake_lock_destroy(qdf_wake_lock_t *lock,
450 			     const char *func, uint32_t line)
451 {
452 	wakeup_source_trash(&(lock->lock));
453 	qdf_wake_lock_dbg_untrack(lock, func, line);
454 }
455 #else
456 void __qdf_wake_lock_destroy(qdf_wake_lock_t *lock,
457 			     const char *func, uint32_t line)
458 {
459 }
460 #endif
461 qdf_export_symbol(__qdf_wake_lock_destroy);
462 
463 /**
464  * qdf_pm_system_wakeup() - wakeup system
465  *
466  * Return: None
467  */
468 void qdf_pm_system_wakeup(void)
469 {
470 	pm_system_wakeup();
471 }
472 
473 qdf_export_symbol(qdf_pm_system_wakeup);
474 
475 #ifdef FEATURE_RUNTIME_PM
476 /**
477  * qdf_runtime_pm_get() - do a get opperation on the device
478  *
479  * A get opperation will prevent a runtime suspend until a
480  * corresponding put is done.  This api should be used when sending
481  * data.
482  *
483  * CONTRARY TO THE REGULAR RUNTIME PM, WHEN THE BUS IS SUSPENDED,
484  * THIS API WILL ONLY REQUEST THE RESUME AND NOT TO A GET!!!
485  *
486  * return: success if the bus is up and a get has been issued
487  *   otherwise an error code.
488  */
489 QDF_STATUS qdf_runtime_pm_get(void)
490 {
491 	void *ol_sc;
492 	int ret;
493 
494 	ol_sc = cds_get_context(QDF_MODULE_ID_HIF);
495 
496 	if (!ol_sc) {
497 		QDF_ASSERT(0);
498 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
499 			  "%s: HIF context is null!", __func__);
500 		return QDF_STATUS_E_INVAL;
501 	}
502 
503 	ret = hif_pm_runtime_get(ol_sc, RTPM_ID_RESVERD, false);
504 
505 	if (ret)
506 		return QDF_STATUS_E_FAILURE;
507 	return QDF_STATUS_SUCCESS;
508 }
509 qdf_export_symbol(qdf_runtime_pm_get);
510 
511 /**
512  * qdf_runtime_pm_put() - do a put opperation on the device
513  *
514  * A put opperation will allow a runtime suspend after a corresponding
515  * get was done.  This api should be used when sending data.
516  *
517  * This api will return a failure if the hif module hasn't been
518  * initialized
519  *
520  * return: QDF_STATUS_SUCCESS if the put is performed
521  */
522 QDF_STATUS qdf_runtime_pm_put(void)
523 {
524 	void *ol_sc;
525 	int ret;
526 
527 	ol_sc = cds_get_context(QDF_MODULE_ID_HIF);
528 
529 	if (!ol_sc) {
530 		QDF_ASSERT(0);
531 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
532 			  "%s: HIF context is null!", __func__);
533 		return QDF_STATUS_E_INVAL;
534 	}
535 
536 	ret = hif_pm_runtime_put(ol_sc, RTPM_ID_RESVERD);
537 
538 	if (ret)
539 		return QDF_STATUS_E_FAILURE;
540 	return QDF_STATUS_SUCCESS;
541 }
542 qdf_export_symbol(qdf_runtime_pm_put);
543 
544 /**
545  * qdf_runtime_pm_prevent_suspend() - prevent a runtime bus suspend
546  * @lock: an opaque context for tracking
547  *
548  * The lock can only be acquired once per lock context and is tracked.
549  *
550  * return: QDF_STATUS_SUCCESS or failure code.
551  */
552 QDF_STATUS qdf_runtime_pm_prevent_suspend(qdf_runtime_lock_t *lock)
553 {
554 	void *ol_sc;
555 	int ret;
556 
557 	ol_sc = cds_get_context(QDF_MODULE_ID_HIF);
558 
559 	if (!ol_sc) {
560 		QDF_ASSERT(0);
561 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
562 			  "%s: HIF context is null!", __func__);
563 		return QDF_STATUS_E_INVAL;
564 	}
565 
566 	ret = hif_pm_runtime_prevent_suspend(ol_sc, lock->lock);
567 
568 	if (ret)
569 		return QDF_STATUS_E_FAILURE;
570 	return QDF_STATUS_SUCCESS;
571 }
572 qdf_export_symbol(qdf_runtime_pm_prevent_suspend);
573 
574 /**
575  * qdf_runtime_pm_allow_suspend() - prevent a runtime bus suspend
576  * @lock: an opaque context for tracking
577  *
578  * The lock can only be acquired once per lock context and is tracked.
579  *
580  * return: QDF_STATUS_SUCCESS or failure code.
581  */
582 QDF_STATUS qdf_runtime_pm_allow_suspend(qdf_runtime_lock_t *lock)
583 {
584 	void *ol_sc;
585 	int ret;
586 
587 	ol_sc = cds_get_context(QDF_MODULE_ID_HIF);
588 	if (!ol_sc) {
589 		QDF_ASSERT(0);
590 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
591 		"%s: HIF context is null!", __func__);
592 		return QDF_STATUS_E_INVAL;
593 	}
594 
595 	ret = hif_pm_runtime_allow_suspend(ol_sc, lock->lock);
596 	if (ret)
597 		return QDF_STATUS_E_FAILURE;
598 
599 	return QDF_STATUS_SUCCESS;
600 }
601 qdf_export_symbol(qdf_runtime_pm_allow_suspend);
602 
603 /**
604  * qdf_runtime_lock_init() - initialize runtime lock
605  * @name: name of the runtime lock
606  *
607  * Initialize a runtime pm lock.  This lock can be used
608  * to prevent the runtime pm system from putting the bus
609  * to sleep.
610  *
611  * Return: runtime_pm_lock_t
612  */
613 QDF_STATUS __qdf_runtime_lock_init(qdf_runtime_lock_t *lock, const char *name)
614 {
615 	int ret = hif_runtime_lock_init(lock, name);
616 
617 	if (ret)
618 		return QDF_STATUS_E_NOMEM;
619 
620 	return QDF_STATUS_SUCCESS;
621 }
622 qdf_export_symbol(__qdf_runtime_lock_init);
623 
624 /**
625  * qdf_runtime_lock_deinit() - deinitialize runtime pm lock
626  * @lock: the lock to deinitialize
627  *
628  * Ensures the lock is released. Frees the runtime lock.
629  *
630  * Return: void
631  */
632 void qdf_runtime_lock_deinit(qdf_runtime_lock_t *lock)
633 {
634 	void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
635 
636 	if (!hif_ctx)
637 		return;
638 
639 	if (!lock)
640 		return;
641 
642 	hif_runtime_lock_deinit(hif_ctx, lock->lock);
643 }
644 qdf_export_symbol(qdf_runtime_lock_deinit);
645 
646 #else
647 
648 QDF_STATUS qdf_runtime_pm_get(void)
649 {
650 	return QDF_STATUS_SUCCESS;
651 }
652 qdf_export_symbol(qdf_runtime_pm_get);
653 
654 QDF_STATUS qdf_runtime_pm_put(void)
655 {
656 	return QDF_STATUS_SUCCESS;
657 }
658 qdf_export_symbol(qdf_runtime_pm_put);
659 
660 QDF_STATUS qdf_runtime_pm_prevent_suspend(qdf_runtime_lock_t *lock)
661 {
662 	return QDF_STATUS_SUCCESS;
663 }
664 qdf_export_symbol(qdf_runtime_pm_prevent_suspend);
665 
666 QDF_STATUS qdf_runtime_pm_allow_suspend(qdf_runtime_lock_t *lock)
667 {
668 	return QDF_STATUS_SUCCESS;
669 }
670 qdf_export_symbol(qdf_runtime_pm_allow_suspend);
671 
672 QDF_STATUS __qdf_runtime_lock_init(qdf_runtime_lock_t *lock, const char *name)
673 {
674 	return QDF_STATUS_SUCCESS;
675 }
676 qdf_export_symbol(__qdf_runtime_lock_init);
677 
678 void qdf_runtime_lock_deinit(qdf_runtime_lock_t *lock)
679 {
680 }
681 qdf_export_symbol(qdf_runtime_lock_deinit);
682 
683 #endif /* FEATURE_RUNTIME_PM */
684 
685 /**
686  * qdf_spinlock_acquire() - acquires a spin lock
687  * @lock: Spin lock to acquire
688  *
689  * Return:
690  * QDF status success: if wake lock is acquired
691  */
692 QDF_STATUS qdf_spinlock_acquire(qdf_spinlock_t *lock)
693 {
694 	spin_lock(&lock->lock.spinlock);
695 	return QDF_STATUS_SUCCESS;
696 }
697 qdf_export_symbol(qdf_spinlock_acquire);
698 
699 
700 /**
701  * qdf_spinlock_release() - release a spin lock
702  * @lock: Spin lock to release
703  *
704  * Return:
705  * QDF status success : if wake lock is acquired
706  */
707 QDF_STATUS qdf_spinlock_release(qdf_spinlock_t *lock)
708 {
709 	spin_unlock(&lock->lock.spinlock);
710 	return QDF_STATUS_SUCCESS;
711 }
712 qdf_export_symbol(qdf_spinlock_release);
713 
714 /**
715  * qdf_mutex_destroy() - destroy a QDF lock
716  * @lock: Pointer to the opaque lock object to be destroyed
717  *
718  * function shall destroy the lock object referenced by lock. After a
719  * successful return from qdf_mutex_destroy()
720  * the lock object becomes, in effect, uninitialized.
721  *
722  * A destroyed lock object can be reinitialized using qdf_mutex_create();
723  * the results of otherwise referencing the object after it has been destroyed
724  * are undefined.  Calls to QDF lock functions to manipulate the lock such
725  * as qdf_mutex_acquire() will fail if the lock is destroyed.  Therefore,
726  * don't use the lock after it has been destroyed until it has
727  * been re-initialized.
728  *
729  * Return:
730  * QDF_STATUS_SUCCESS: lock was successfully initialized
731  * QDF failure reason codes: lock is not initialized and can't be used
732  */
733 QDF_STATUS qdf_mutex_destroy(qdf_mutex_t *lock)
734 {
735 	/* check for invalid pointer */
736 	if (!lock) {
737 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
738 			  "%s: NULL pointer passed in", __func__);
739 		return QDF_STATUS_E_FAULT;
740 	}
741 
742 	if (LINUX_LOCK_COOKIE != lock->cookie) {
743 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
744 			  "%s: uninitialized lock", __func__);
745 		return QDF_STATUS_E_INVAL;
746 	}
747 
748 	if (in_interrupt()) {
749 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
750 			  "%s cannot be called from interrupt context!!!",
751 			  __func__);
752 		return QDF_STATUS_E_FAULT;
753 	}
754 
755 	/* check if lock is released */
756 	if (!mutex_trylock(&lock->m_lock)) {
757 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
758 			  "%s: lock is not released", __func__);
759 		return QDF_STATUS_E_BUSY;
760 	}
761 	lock->cookie = 0;
762 	lock->state = LOCK_DESTROYED;
763 	lock->process_id = 0;
764 	lock->refcount = 0;
765 
766 	qdf_lock_stats_destroy(&lock->stats);
767 	mutex_unlock(&lock->m_lock);
768 
769 	return QDF_STATUS_SUCCESS;
770 }
771 qdf_export_symbol(qdf_mutex_destroy);
772 
773 #if QDF_LOCK_STATS_LIST
774 struct qdf_lock_cookie {
775 	union {
776 		struct {
777 			struct lock_stats *stats;
778 			const char *func;
779 			int line;
780 		} cookie;
781 		struct {
782 			struct qdf_lock_cookie *next;
783 		} empty_node;
784 	} u;
785 };
786 
787 #ifndef QDF_LOCK_STATS_LIST_SIZE
788 #define QDF_LOCK_STATS_LIST_SIZE 256
789 #endif
790 
791 static qdf_spinlock_t qdf_lock_list_spinlock;
792 static struct qdf_lock_cookie lock_cookies[QDF_LOCK_STATS_LIST_SIZE];
793 static struct qdf_lock_cookie *lock_cookie_freelist;
794 static qdf_atomic_t lock_cookie_get_failures;
795 static qdf_atomic_t lock_cookie_untracked_num;
796 /* dummy value */
797 #define DUMMY_LOCK_COOKIE 0xc00c1e
798 
799 /**
800  * qdf_is_lock_cookie - check if memory is a valid lock cookie
801  *
802  * return true if the memory is within the range of the lock cookie
803  * memory.
804  */
805 static bool qdf_is_lock_cookie(struct qdf_lock_cookie *lock_cookie)
806 {
807 	return lock_cookie >= &lock_cookies[0] &&
808 		lock_cookie <= &lock_cookies[QDF_LOCK_STATS_LIST_SIZE-1];
809 }
810 
811 /**
812  * qdf_is_lock_cookie_free() -  check if the lock cookie is on the freelist
813  * @lock_cookie: lock cookie to check
814  *
815  * Check that the next field of the lock cookie points to a lock cookie.
816  * currently this is only true if the cookie is on the freelist.
817  *
818  * Checking for the function and line being NULL and 0 should also have worked.
819  */
820 static bool qdf_is_lock_cookie_free(struct qdf_lock_cookie *lock_cookie)
821 {
822 	struct qdf_lock_cookie *tmp = lock_cookie->u.empty_node.next;
823 
824 	return qdf_is_lock_cookie(tmp) || (!tmp);
825 }
826 
827 static struct qdf_lock_cookie *qdf_get_lock_cookie(void)
828 {
829 	struct qdf_lock_cookie *lock_cookie;
830 
831 	qdf_spin_lock_bh(&qdf_lock_list_spinlock);
832 	lock_cookie = lock_cookie_freelist;
833 	if (lock_cookie_freelist)
834 		lock_cookie_freelist = lock_cookie_freelist->u.empty_node.next;
835 	qdf_spin_unlock_bh(&qdf_lock_list_spinlock);
836 	return lock_cookie;
837 }
838 
839 static void __qdf_put_lock_cookie(struct qdf_lock_cookie *lock_cookie)
840 {
841 	if (!qdf_is_lock_cookie(lock_cookie))
842 		QDF_BUG(0);
843 
844 	lock_cookie->u.empty_node.next = lock_cookie_freelist;
845 	lock_cookie_freelist = lock_cookie;
846 }
847 
848 static void qdf_put_lock_cookie(struct qdf_lock_cookie *lock_cookie)
849 {
850 	qdf_spin_lock_bh(&qdf_lock_list_spinlock);
851 	__qdf_put_lock_cookie(lock_cookie);
852 	qdf_spin_unlock_bh(&qdf_lock_list_spinlock);
853 }
854 
855 void qdf_lock_stats_init(void)
856 {
857 	int i;
858 
859 	for (i = 0; i < QDF_LOCK_STATS_LIST_SIZE; i++)
860 		__qdf_put_lock_cookie(&lock_cookies[i]);
861 
862 	/* stats must be allocated for the spinlock before the cookie,
863 	 * otherwise this qdf_lock_list_spinlock wouldnt get initialized
864 	 * properly
865 	 */
866 	qdf_spinlock_create(&qdf_lock_list_spinlock);
867 	qdf_atomic_init(&lock_cookie_get_failures);
868 	qdf_atomic_init(&lock_cookie_untracked_num);
869 }
870 
871 void qdf_lock_stats_deinit(void)
872 {
873 	int i;
874 
875 	qdf_spinlock_destroy(&qdf_lock_list_spinlock);
876 	for (i = 0; i < QDF_LOCK_STATS_LIST_SIZE; i++) {
877 		if (!qdf_is_lock_cookie_free(&lock_cookies[i]))
878 			QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG,
879 				  "%s: lock_not_destroyed, fun: %s, line %d",
880 				  __func__, lock_cookies[i].u.cookie.func,
881 				  lock_cookies[i].u.cookie.line);
882 	}
883 	lock_cookie_freelist = NULL;
884 }
885 
886 /* allocated separate memory in case the lock memory is freed without
887  * running the deinitialization code.  The cookie list will not be
888  * corrupted.
889  */
890 void qdf_lock_stats_cookie_create(struct lock_stats *stats,
891 				  const char *func, int line)
892 {
893 	struct qdf_lock_cookie *cookie = qdf_get_lock_cookie();
894 
895 	if (!cookie) {
896 		int count;
897 
898 		qdf_atomic_inc(&lock_cookie_get_failures);
899 		count = qdf_atomic_inc_return(&lock_cookie_untracked_num);
900 		stats->cookie = (void *) DUMMY_LOCK_COOKIE;
901 		return;
902 	}
903 
904 	stats->cookie = cookie;
905 	stats->cookie->u.cookie.stats = stats;
906 	stats->cookie->u.cookie.func = func;
907 	stats->cookie->u.cookie.line = line;
908 }
909 
910 qdf_export_symbol(qdf_lock_stats_cookie_create);
911 
912 void qdf_lock_stats_cookie_destroy(struct lock_stats *stats)
913 {
914 	struct qdf_lock_cookie *cookie = stats->cookie;
915 
916 	if (!cookie) {
917 		QDF_DEBUG_PANIC("Lock destroyed twice or never created");
918 		return;
919 	}
920 
921 	stats->cookie = NULL;
922 	if (cookie == (void *)DUMMY_LOCK_COOKIE) {
923 		qdf_atomic_dec(&lock_cookie_untracked_num);
924 		return;
925 	}
926 
927 	cookie->u.cookie.stats = NULL;
928 	cookie->u.cookie.func = NULL;
929 	cookie->u.cookie.line = 0;
930 
931 	qdf_put_lock_cookie(cookie);
932 }
933 
934 qdf_export_symbol(qdf_lock_stats_cookie_destroy);
935 #endif
936