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