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