xref: /wlan-driver/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_debug.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  *
3*5113495bSYour Name  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
4*5113495bSYour Name  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
5*5113495bSYour Name  *
6*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
7*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
8*5113495bSYour Name  * above copyright notice and this permission notice appear in all
9*5113495bSYour Name  * copies.
10*5113495bSYour Name  *
11*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
12*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
14*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
15*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
16*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
17*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
18*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
19*5113495bSYour Name  */
20*5113495bSYour Name /*
21*5113495bSYour Name  * DOC: Public APIs to perform debug operations on object manager
22*5113495bSYour Name  */
23*5113495bSYour Name 
24*5113495bSYour Name #include <wlan_objmgr_psoc_obj.h>
25*5113495bSYour Name #include <wlan_objmgr_pdev_obj.h>
26*5113495bSYour Name #include <wlan_objmgr_vdev_obj.h>
27*5113495bSYour Name #include <wlan_objmgr_peer_obj.h>
28*5113495bSYour Name #include <wlan_objmgr_debug.h>
29*5113495bSYour Name #include "wlan_objmgr_global_obj_i.h"
30*5113495bSYour Name #include <qdf_mem.h>
31*5113495bSYour Name #include <qdf_platform.h>
32*5113495bSYour Name #include <qdf_str.h>
33*5113495bSYour Name 
34*5113495bSYour Name /*
35*5113495bSYour Name  * Default TTL (of FW) for mgmt frames is 5 sec, by considering all the other
36*5113495bSYour Name  * delays, arrived with this value
37*5113495bSYour Name  */
38*5113495bSYour Name #ifndef LOG_DEL_OBJ_TIMEOUT_VALUE_MSEC
39*5113495bSYour Name #define LOG_DEL_OBJ_TIMEOUT_VALUE_MSEC   8000
40*5113495bSYour Name #endif
41*5113495bSYour Name #ifndef LOG_DEL_OBJ_DESTROY_DURATION_SEC
42*5113495bSYour Name #define LOG_DEL_OBJ_DESTROY_DURATION_SEC 8
43*5113495bSYour Name #endif
44*5113495bSYour Name 
45*5113495bSYour Name /*
46*5113495bSYour Name  * The max duration for which a obj can be allowed to remain in L-state
47*5113495bSYour Name  * The duration  should be higher than the psoc idle timeout.
48*5113495bSYour Name  */
49*5113495bSYour Name #define LOG_DEL_OBJ_DESTROY_ASSERT_DURATION_SEC 32
50*5113495bSYour Name #define LOG_DEL_OBJ_LIST_MAX_COUNT       (3 + 5 + 48 + 4096)
51*5113495bSYour Name 
52*5113495bSYour Name union wlan_objmgr_del_obj {
53*5113495bSYour Name 	struct wlan_objmgr_psoc *obj_psoc;
54*5113495bSYour Name 	struct wlan_objmgr_pdev *obj_pdev;
55*5113495bSYour Name 	struct wlan_objmgr_vdev *obj_vdev;
56*5113495bSYour Name 	struct wlan_objmgr_peer *obj_peer;
57*5113495bSYour Name };
58*5113495bSYour Name 
59*5113495bSYour Name /**
60*5113495bSYour Name  * struct log_del_obj    - Logically deleted Object
61*5113495bSYour Name  * @obj:            Represents peer/vdev/pdev/psoc
62*5113495bSYour Name  * @node:           List node from Logically deleted list
63*5113495bSYour Name  * @obj_type:       Object type for peer/vdev/pdev/psoc
64*5113495bSYour Name  * @tstamp:         Timestamp when node entered logically
65*5113495bSYour Name  *                  deleted state
66*5113495bSYour Name  */
67*5113495bSYour Name struct log_del_obj {
68*5113495bSYour Name 	union wlan_objmgr_del_obj obj;
69*5113495bSYour Name 	qdf_list_node_t node;
70*5113495bSYour Name 	enum wlan_objmgr_obj_type obj_type;
71*5113495bSYour Name 	qdf_time_t tstamp;
72*5113495bSYour Name };
73*5113495bSYour Name 
74*5113495bSYour Name /**
75*5113495bSYour Name  * struct wlan_objmgr_debug_info     - Objmgr debug info
76*5113495bSYour Name  * for Logically deleted object
77*5113495bSYour Name  * @obj_timer:          Timer object
78*5113495bSYour Name  * @obj_list:           list object having linking logically
79*5113495bSYour Name  *                       deleted nodes
80*5113495bSYour Name  * @list_lock:          lock to protect list
81*5113495bSYour Name  */
82*5113495bSYour Name struct wlan_objmgr_debug_info {
83*5113495bSYour Name 	qdf_timer_t obj_timer;
84*5113495bSYour Name 	qdf_list_t obj_list;
85*5113495bSYour Name 	qdf_spinlock_t list_lock;
86*5113495bSYour Name };
87*5113495bSYour Name 
88*5113495bSYour Name static const char *
wlan_obj_type_get_obj_name(enum wlan_objmgr_obj_type obj_type)89*5113495bSYour Name wlan_obj_type_get_obj_name(enum wlan_objmgr_obj_type obj_type)
90*5113495bSYour Name {
91*5113495bSYour Name 	static const struct wlan_obj_type_to_name {
92*5113495bSYour Name 		enum wlan_objmgr_obj_type obj_type;
93*5113495bSYour Name 		const char *name;
94*5113495bSYour Name 	} obj_type_name[WLAN_OBJ_TYPE_MAX] = {
95*5113495bSYour Name 		{WLAN_PSOC_OP, "psoc"},
96*5113495bSYour Name 		{WLAN_PDEV_OP, "pdev"},
97*5113495bSYour Name 		{WLAN_VDEV_OP, "vdev"},
98*5113495bSYour Name 		{WLAN_PEER_OP, "peer"}
99*5113495bSYour Name 	};
100*5113495bSYour Name 	uint8_t idx;
101*5113495bSYour Name 
102*5113495bSYour Name 	for (idx = 0; idx < WLAN_OBJ_TYPE_MAX; idx++) {
103*5113495bSYour Name 		if (obj_type == obj_type_name[idx].obj_type)
104*5113495bSYour Name 			return obj_type_name[idx].name;
105*5113495bSYour Name 	}
106*5113495bSYour Name 
107*5113495bSYour Name 	return NULL;
108*5113495bSYour Name }
109*5113495bSYour Name 
110*5113495bSYour Name static uint8_t*
wlan_objmgr_debug_get_macaddr(union wlan_objmgr_del_obj * obj,enum wlan_objmgr_obj_type obj_type)111*5113495bSYour Name wlan_objmgr_debug_get_macaddr(union wlan_objmgr_del_obj *obj,
112*5113495bSYour Name 			      enum wlan_objmgr_obj_type obj_type)
113*5113495bSYour Name {
114*5113495bSYour Name 	switch (obj_type) {
115*5113495bSYour Name 	case WLAN_PSOC_OP:
116*5113495bSYour Name 		return wlan_psoc_get_hw_macaddr(obj->obj_psoc);
117*5113495bSYour Name 	case WLAN_PDEV_OP:
118*5113495bSYour Name 		return wlan_pdev_get_hw_macaddr(obj->obj_pdev);
119*5113495bSYour Name 	case WLAN_VDEV_OP:
120*5113495bSYour Name 		return wlan_vdev_mlme_get_macaddr(obj->obj_vdev);
121*5113495bSYour Name 	case WLAN_PEER_OP:
122*5113495bSYour Name 		return wlan_peer_get_macaddr(obj->obj_peer);
123*5113495bSYour Name 	default:
124*5113495bSYour Name 		obj_mgr_err("invalid obj_type");
125*5113495bSYour Name 		return NULL;
126*5113495bSYour Name 	}
127*5113495bSYour Name }
128*5113495bSYour Name 
129*5113495bSYour Name static void
wlan_objmgr_insert_ld_obj_to_list(struct wlan_objmgr_debug_info * debug_info,qdf_list_node_t * node)130*5113495bSYour Name wlan_objmgr_insert_ld_obj_to_list(struct wlan_objmgr_debug_info *debug_info,
131*5113495bSYour Name 				  qdf_list_node_t *node)
132*5113495bSYour Name {
133*5113495bSYour Name 	/* Insert object to list with lock being held*/
134*5113495bSYour Name 	qdf_spin_lock_bh(&debug_info->list_lock);
135*5113495bSYour Name 
136*5113495bSYour Name 	/* Start timer only when list is empty */
137*5113495bSYour Name 	if (qdf_list_empty(&debug_info->obj_list))
138*5113495bSYour Name 		qdf_timer_start(&debug_info->obj_timer,
139*5113495bSYour Name 				LOG_DEL_OBJ_TIMEOUT_VALUE_MSEC);
140*5113495bSYour Name 
141*5113495bSYour Name 	qdf_list_insert_back(&debug_info->obj_list, node);
142*5113495bSYour Name 	qdf_spin_unlock_bh(&debug_info->list_lock);
143*5113495bSYour Name }
144*5113495bSYour Name 
wlan_obj_type_get_obj(union wlan_objmgr_del_obj * obj,union wlan_objmgr_del_obj * del_obj,enum wlan_objmgr_obj_type obj_type)145*5113495bSYour Name static void wlan_obj_type_get_obj(union wlan_objmgr_del_obj *obj,
146*5113495bSYour Name 				  union wlan_objmgr_del_obj *del_obj,
147*5113495bSYour Name 				  enum wlan_objmgr_obj_type obj_type)
148*5113495bSYour Name {
149*5113495bSYour Name 	switch (obj_type) {
150*5113495bSYour Name 	case WLAN_PSOC_OP:
151*5113495bSYour Name 		del_obj->obj_psoc = obj->obj_psoc;
152*5113495bSYour Name 		return;
153*5113495bSYour Name 	case WLAN_PDEV_OP:
154*5113495bSYour Name 		del_obj->obj_pdev = obj->obj_pdev;
155*5113495bSYour Name 		return;
156*5113495bSYour Name 	case WLAN_VDEV_OP:
157*5113495bSYour Name 		del_obj->obj_vdev = obj->obj_vdev;
158*5113495bSYour Name 		return;
159*5113495bSYour Name 	case WLAN_PEER_OP:
160*5113495bSYour Name 		del_obj->obj_peer = obj->obj_peer;
161*5113495bSYour Name 		return;
162*5113495bSYour Name 	default:
163*5113495bSYour Name 		obj_mgr_err("invalid obj_type");
164*5113495bSYour Name 		return;
165*5113495bSYour Name 	}
166*5113495bSYour Name }
167*5113495bSYour Name 
wlan_objmgr_notify_log_delete(void * obj,enum wlan_objmgr_obj_type obj_type)168*5113495bSYour Name void wlan_objmgr_notify_log_delete(void *obj,
169*5113495bSYour Name 				   enum wlan_objmgr_obj_type obj_type)
170*5113495bSYour Name {
171*5113495bSYour Name 	struct wlan_objmgr_debug_info *debug_info;
172*5113495bSYour Name 	const char *obj_name;
173*5113495bSYour Name 	uint8_t *macaddr;
174*5113495bSYour Name 	qdf_time_t tstamp;
175*5113495bSYour Name 	struct log_del_obj *node;
176*5113495bSYour Name 	union wlan_objmgr_del_obj *del_obj = (union wlan_objmgr_del_obj *)&obj;
177*5113495bSYour Name 
178*5113495bSYour Name 	if (!obj) {
179*5113495bSYour Name 		obj_mgr_err("object is null");
180*5113495bSYour Name 		return;
181*5113495bSYour Name 	}
182*5113495bSYour Name 
183*5113495bSYour Name 	debug_info = g_umac_glb_obj->debug_info;
184*5113495bSYour Name 
185*5113495bSYour Name 	if (!debug_info) {
186*5113495bSYour Name 		obj_mgr_err("debug_info is null");
187*5113495bSYour Name 		return;
188*5113495bSYour Name 	}
189*5113495bSYour Name 
190*5113495bSYour Name 	macaddr = wlan_objmgr_debug_get_macaddr(del_obj, obj_type);
191*5113495bSYour Name 	if (!macaddr) {
192*5113495bSYour Name 		obj_mgr_err("macaddr is null");
193*5113495bSYour Name 		return;
194*5113495bSYour Name 	}
195*5113495bSYour Name 
196*5113495bSYour Name 	obj_name = wlan_obj_type_get_obj_name(obj_type);
197*5113495bSYour Name 	if (!obj_name) {
198*5113495bSYour Name 		obj_mgr_err("obj_name is null");
199*5113495bSYour Name 		return;
200*5113495bSYour Name 	}
201*5113495bSYour Name 
202*5113495bSYour Name 	tstamp = qdf_system_ticks_to_msecs(qdf_system_ticks()) / 1000;
203*5113495bSYour Name 	node = qdf_mem_malloc(sizeof(*node));
204*5113495bSYour Name 	if (!node)
205*5113495bSYour Name 		return;
206*5113495bSYour Name 
207*5113495bSYour Name 	wlan_obj_type_get_obj(del_obj, &node->obj, obj_type);
208*5113495bSYour Name 	node->obj_type = obj_type;
209*5113495bSYour Name 	node->tstamp = tstamp;
210*5113495bSYour Name 	obj_mgr_debug("#%s : mac_addr: "QDF_MAC_ADDR_FMT" entered L-state",
211*5113495bSYour Name 		      obj_name, QDF_MAC_ADDR_REF(macaddr));
212*5113495bSYour Name 	wlan_objmgr_insert_ld_obj_to_list(debug_info, &node->node);
213*5113495bSYour Name }
214*5113495bSYour Name 
wlan_objmgr_del_obj_match(union wlan_objmgr_del_obj * obj,union wlan_objmgr_del_obj * del_obj,enum wlan_objmgr_obj_type obj_type)215*5113495bSYour Name static bool wlan_objmgr_del_obj_match(union wlan_objmgr_del_obj *obj,
216*5113495bSYour Name 				      union wlan_objmgr_del_obj *del_obj,
217*5113495bSYour Name 				      enum wlan_objmgr_obj_type obj_type)
218*5113495bSYour Name {
219*5113495bSYour Name 	switch (obj_type) {
220*5113495bSYour Name 	case WLAN_PSOC_OP:
221*5113495bSYour Name 		return (del_obj->obj_psoc == obj->obj_psoc);
222*5113495bSYour Name 	case WLAN_PDEV_OP:
223*5113495bSYour Name 		return (del_obj->obj_pdev == obj->obj_pdev);
224*5113495bSYour Name 	case WLAN_VDEV_OP:
225*5113495bSYour Name 		return (del_obj->obj_vdev == obj->obj_vdev);
226*5113495bSYour Name 	case WLAN_PEER_OP:
227*5113495bSYour Name 		return (del_obj->obj_peer == obj->obj_peer);
228*5113495bSYour Name 	default:
229*5113495bSYour Name 		return false;
230*5113495bSYour Name 	}
231*5113495bSYour Name }
232*5113495bSYour Name 
233*5113495bSYour Name static void
wlan_objmgr_rem_ld_obj_from_list(union wlan_objmgr_del_obj * obj,struct wlan_objmgr_debug_info * debug_info,enum wlan_objmgr_obj_type obj_type)234*5113495bSYour Name wlan_objmgr_rem_ld_obj_from_list(union wlan_objmgr_del_obj *obj,
235*5113495bSYour Name 				 struct wlan_objmgr_debug_info *debug_info,
236*5113495bSYour Name 				 enum wlan_objmgr_obj_type obj_type)
237*5113495bSYour Name {
238*5113495bSYour Name 	qdf_list_node_t *node = NULL;
239*5113495bSYour Name 	struct log_del_obj *obj_to_remove = NULL;
240*5113495bSYour Name 	qdf_list_t *list;
241*5113495bSYour Name 	QDF_STATUS status;
242*5113495bSYour Name 
243*5113495bSYour Name 	list = &debug_info->obj_list;
244*5113495bSYour Name 	qdf_spin_lock_bh(&debug_info->list_lock);
245*5113495bSYour Name 	status = qdf_list_peek_front(list, &node);
246*5113495bSYour Name 
247*5113495bSYour Name 	while (QDF_IS_STATUS_SUCCESS(status)) {
248*5113495bSYour Name 		obj_to_remove = qdf_container_of(node,
249*5113495bSYour Name 						 struct log_del_obj, node);
250*5113495bSYour Name 		if (wlan_objmgr_del_obj_match(obj, &obj_to_remove->obj,
251*5113495bSYour Name 					      obj_type) &&
252*5113495bSYour Name 		    obj_to_remove->obj_type == obj_type) {
253*5113495bSYour Name 			status = qdf_list_remove_node(list,
254*5113495bSYour Name 						      &obj_to_remove->node);
255*5113495bSYour Name 			/* Stop timer if list is empty */
256*5113495bSYour Name 			if (QDF_IS_STATUS_SUCCESS(status)) {
257*5113495bSYour Name 				if (qdf_list_empty(&debug_info->obj_list))
258*5113495bSYour Name 					qdf_timer_stop(&debug_info->obj_timer);
259*5113495bSYour Name 				qdf_mem_free(obj_to_remove);
260*5113495bSYour Name 			}
261*5113495bSYour Name 			break;
262*5113495bSYour Name 		}
263*5113495bSYour Name 		status = qdf_list_peek_next(list, node, &node);
264*5113495bSYour Name 	};
265*5113495bSYour Name 	qdf_spin_unlock_bh(&debug_info->list_lock);
266*5113495bSYour Name }
267*5113495bSYour Name 
wlan_objmgr_notify_destroy(void * obj,enum wlan_objmgr_obj_type obj_type)268*5113495bSYour Name void wlan_objmgr_notify_destroy(void *obj,
269*5113495bSYour Name 				enum wlan_objmgr_obj_type obj_type)
270*5113495bSYour Name {
271*5113495bSYour Name 	struct wlan_objmgr_debug_info *debug_info;
272*5113495bSYour Name 	uint8_t *macaddr;
273*5113495bSYour Name 	const char *obj_name;
274*5113495bSYour Name 	union wlan_objmgr_del_obj *del_obj = (union wlan_objmgr_del_obj *)&obj;
275*5113495bSYour Name 
276*5113495bSYour Name 	debug_info = g_umac_glb_obj->debug_info;
277*5113495bSYour Name 
278*5113495bSYour Name 	if (!debug_info) {
279*5113495bSYour Name 		obj_mgr_err("debug_info is null");
280*5113495bSYour Name 		return;
281*5113495bSYour Name 	}
282*5113495bSYour Name 	macaddr = wlan_objmgr_debug_get_macaddr(del_obj, obj_type);
283*5113495bSYour Name 	if (!macaddr) {
284*5113495bSYour Name 		obj_mgr_err("macaddr is null");
285*5113495bSYour Name 		return;
286*5113495bSYour Name 	}
287*5113495bSYour Name 	obj_name = wlan_obj_type_get_obj_name(obj_type);
288*5113495bSYour Name 	if (!obj_name) {
289*5113495bSYour Name 		obj_mgr_err("obj_name is null");
290*5113495bSYour Name 		return;
291*5113495bSYour Name 	}
292*5113495bSYour Name 	obj_mgr_debug("#%s : macaddr: "QDF_MAC_ADDR_FMT" exited L-state",
293*5113495bSYour Name 		      obj_name, QDF_MAC_ADDR_REF(macaddr));
294*5113495bSYour Name 
295*5113495bSYour Name 	wlan_objmgr_rem_ld_obj_from_list(del_obj,
296*5113495bSYour Name 					 debug_info, obj_type);
297*5113495bSYour Name }
298*5113495bSYour Name 
299*5113495bSYour Name /**
300*5113495bSYour Name  * wlan_objmgr_debug_obj_destroyed_panic() - Panic in case obj is in L-state
301*5113495bSYour Name  * for long
302*5113495bSYour Name  * @obj_name: The name of the module ID
303*5113495bSYour Name  *
304*5113495bSYour Name  * This will invoke panic in the case that the obj is in logically destroyed
305*5113495bSYour Name  * state for a long time. The panic is invoked only in case feature flag
306*5113495bSYour Name  * WLAN_OBJMGR_PANIC_ON_BUG is enabled
307*5113495bSYour Name  *
308*5113495bSYour Name  * Return: None
309*5113495bSYour Name  */
310*5113495bSYour Name #ifdef CONFIG_LEAK_DETECTION
wlan_objmgr_debug_obj_destroyed_panic(const char * obj_name)311*5113495bSYour Name static inline void wlan_objmgr_debug_obj_destroyed_panic(const char *obj_name)
312*5113495bSYour Name {
313*5113495bSYour Name 	obj_mgr_alert("#%s in L-state for too long!", obj_name);
314*5113495bSYour Name 	QDF_BUG(0);
315*5113495bSYour Name }
316*5113495bSYour Name #else
wlan_objmgr_debug_obj_destroyed_panic(const char * obj_name)317*5113495bSYour Name static inline void wlan_objmgr_debug_obj_destroyed_panic(const char *obj_name)
318*5113495bSYour Name {
319*5113495bSYour Name }
320*5113495bSYour Name #endif
321*5113495bSYour Name 
322*5113495bSYour Name /*
323*5113495bSYour Name  * wlan_objmgr_print_pending_refs() - Print pending refs according to the obj
324*5113495bSYour Name  * @obj:	Represents peer/vdev/pdev/psoc
325*5113495bSYour Name  * @obj_type:	Object type for peer/vdev/pdev/psoc
326*5113495bSYour Name  *
327*5113495bSYour Name  * Return: None
328*5113495bSYour Name  */
wlan_objmgr_print_pending_refs(union wlan_objmgr_del_obj * obj,enum wlan_objmgr_obj_type obj_type)329*5113495bSYour Name static void wlan_objmgr_print_pending_refs(union wlan_objmgr_del_obj *obj,
330*5113495bSYour Name 					   enum wlan_objmgr_obj_type obj_type)
331*5113495bSYour Name {
332*5113495bSYour Name 	switch (obj_type) {
333*5113495bSYour Name 	case WLAN_PSOC_OP:
334*5113495bSYour Name 		wlan_objmgr_print_ref_ids(obj->obj_psoc->soc_objmgr.ref_id_dbg,
335*5113495bSYour Name 					  QDF_TRACE_LEVEL_DEBUG);
336*5113495bSYour Name 		break;
337*5113495bSYour Name 	case WLAN_PDEV_OP:
338*5113495bSYour Name 		wlan_objmgr_print_ref_ids(obj->obj_pdev->pdev_objmgr.ref_id_dbg,
339*5113495bSYour Name 					  QDF_TRACE_LEVEL_DEBUG);
340*5113495bSYour Name 		break;
341*5113495bSYour Name 	case WLAN_VDEV_OP:
342*5113495bSYour Name 		wlan_objmgr_print_ref_ids(obj->obj_vdev->vdev_objmgr.ref_id_dbg,
343*5113495bSYour Name 					  QDF_TRACE_LEVEL_DEBUG);
344*5113495bSYour Name 		break;
345*5113495bSYour Name 	case WLAN_PEER_OP:
346*5113495bSYour Name 		wlan_objmgr_print_ref_ids(obj->obj_peer->peer_objmgr.ref_id_dbg,
347*5113495bSYour Name 					  QDF_TRACE_LEVEL_DEBUG);
348*5113495bSYour Name 		break;
349*5113495bSYour Name 	default:
350*5113495bSYour Name 		obj_mgr_debug("invalid obj_type");
351*5113495bSYour Name 	}
352*5113495bSYour Name }
353*5113495bSYour Name 
354*5113495bSYour Name #ifdef WLAN_OBJMGR_REF_ID_TRACE
355*5113495bSYour Name static void
wlan_objmgr_print_ref_func_line(struct wlan_objmgr_trace_func * func_head,uint32_t id)356*5113495bSYour Name wlan_objmgr_print_ref_func_line(struct wlan_objmgr_trace_func *func_head,
357*5113495bSYour Name 				uint32_t id)
358*5113495bSYour Name {
359*5113495bSYour Name 	uint32_t ref_cnt;
360*5113495bSYour Name 	struct wlan_objmgr_line_ref_node *tmp_ln_node;
361*5113495bSYour Name 
362*5113495bSYour Name 	obj_mgr_debug("ID: %s(%d)", string_from_dbgid(id), id);
363*5113495bSYour Name 	while (func_head) {
364*5113495bSYour Name 		obj_mgr_debug("Func: %s", func_head->func);
365*5113495bSYour Name 		tmp_ln_node = func_head->line_head;
366*5113495bSYour Name 		while (tmp_ln_node) {
367*5113495bSYour Name 			ref_cnt = qdf_atomic_read(&tmp_ln_node->line_ref.cnt);
368*5113495bSYour Name 			obj_mgr_debug("line: %d cnt: %d",
369*5113495bSYour Name 				      tmp_ln_node->line_ref.line,
370*5113495bSYour Name 				      ref_cnt);
371*5113495bSYour Name 			tmp_ln_node = tmp_ln_node->next;
372*5113495bSYour Name 		}
373*5113495bSYour Name 		func_head = func_head->next;
374*5113495bSYour Name 	}
375*5113495bSYour Name }
376*5113495bSYour Name 
377*5113495bSYour Name static void
wlan_objmgr_trace_print_ref(union wlan_objmgr_del_obj * obj,enum wlan_objmgr_obj_type obj_type)378*5113495bSYour Name wlan_objmgr_trace_print_ref(union wlan_objmgr_del_obj *obj,
379*5113495bSYour Name 			    enum wlan_objmgr_obj_type obj_type)
380*5113495bSYour Name {
381*5113495bSYour Name 	uint32_t id;
382*5113495bSYour Name 	struct wlan_objmgr_trace_func *func_head;
383*5113495bSYour Name 	struct wlan_objmgr_trace *trace;
384*5113495bSYour Name 	struct wlan_objmgr_vdev_objmgr *vdev_obj;
385*5113495bSYour Name 	struct wlan_objmgr_peer_objmgr *peer_obj;
386*5113495bSYour Name 
387*5113495bSYour Name 	switch (obj_type) {
388*5113495bSYour Name 	case WLAN_VDEV_OP:
389*5113495bSYour Name 		vdev_obj = &obj->obj_vdev->vdev_objmgr;
390*5113495bSYour Name 		trace = &vdev_obj->trace;
391*5113495bSYour Name 		for (id = 0; id < WLAN_REF_ID_MAX; id++) {
392*5113495bSYour Name 			if (qdf_atomic_read(&vdev_obj->ref_id_dbg[id])) {
393*5113495bSYour Name 				obj_mgr_debug("Reference:");
394*5113495bSYour Name 
395*5113495bSYour Name 				func_head = trace->references[id].head;
396*5113495bSYour Name 				wlan_objmgr_print_ref_func_line(func_head, id);
397*5113495bSYour Name 
398*5113495bSYour Name 				obj_mgr_debug("Dereference:");
399*5113495bSYour Name 				func_head = trace->dereferences[id].head;
400*5113495bSYour Name 				wlan_objmgr_print_ref_func_line(func_head, id);
401*5113495bSYour Name 			}
402*5113495bSYour Name 		}
403*5113495bSYour Name 		break;
404*5113495bSYour Name 	case WLAN_PEER_OP:
405*5113495bSYour Name 		peer_obj = &obj->obj_peer->peer_objmgr;
406*5113495bSYour Name 		trace = &peer_obj->trace;
407*5113495bSYour Name 		for (id = 0; id < WLAN_REF_ID_MAX; id++) {
408*5113495bSYour Name 			if (qdf_atomic_read(&peer_obj->ref_id_dbg[id])) {
409*5113495bSYour Name 				obj_mgr_debug("Reference:");
410*5113495bSYour Name 
411*5113495bSYour Name 				func_head = trace->references[id].head;
412*5113495bSYour Name 				wlan_objmgr_print_ref_func_line(func_head, id);
413*5113495bSYour Name 
414*5113495bSYour Name 				obj_mgr_debug("Dereference:");
415*5113495bSYour Name 				func_head = trace->dereferences[id].head;
416*5113495bSYour Name 				wlan_objmgr_print_ref_func_line(func_head, id);
417*5113495bSYour Name 			}
418*5113495bSYour Name 		}
419*5113495bSYour Name 		break;
420*5113495bSYour Name 	default:
421*5113495bSYour Name 		break;
422*5113495bSYour Name 	}
423*5113495bSYour Name }
424*5113495bSYour Name #else
425*5113495bSYour Name static void
wlan_objmgr_trace_print_ref(union wlan_objmgr_del_obj * obj,enum wlan_objmgr_obj_type obj_type)426*5113495bSYour Name wlan_objmgr_trace_print_ref(union wlan_objmgr_del_obj *obj,
427*5113495bSYour Name 			    enum wlan_objmgr_obj_type obj_type)
428*5113495bSYour Name {
429*5113495bSYour Name }
430*5113495bSYour Name #endif
431*5113495bSYour Name 
432*5113495bSYour Name /* timeout handler for iterating logically deleted object */
433*5113495bSYour Name 
wlan_objmgr_iterate_log_del_obj_handler(void * timer_arg)434*5113495bSYour Name static void wlan_objmgr_iterate_log_del_obj_handler(void *timer_arg)
435*5113495bSYour Name {
436*5113495bSYour Name 	enum wlan_objmgr_obj_type obj_type;
437*5113495bSYour Name 	uint8_t *macaddr;
438*5113495bSYour Name 	const char *obj_name;
439*5113495bSYour Name 	struct wlan_objmgr_debug_info *debug_info;
440*5113495bSYour Name 	qdf_list_node_t *node;
441*5113495bSYour Name 	qdf_list_t *log_del_obj_list = NULL;
442*5113495bSYour Name 	struct log_del_obj *del_obj = NULL;
443*5113495bSYour Name 	qdf_time_t cur_tstamp;
444*5113495bSYour Name 	QDF_STATUS status;
445*5113495bSYour Name 
446*5113495bSYour Name 	debug_info = g_umac_glb_obj->debug_info;
447*5113495bSYour Name 
448*5113495bSYour Name 	if (!debug_info) {
449*5113495bSYour Name 		obj_mgr_err("debug_info is not initialized");
450*5113495bSYour Name 		return;
451*5113495bSYour Name 	}
452*5113495bSYour Name 
453*5113495bSYour Name 	log_del_obj_list = &debug_info->obj_list;
454*5113495bSYour Name 	qdf_spin_lock_bh(&debug_info->list_lock);
455*5113495bSYour Name 
456*5113495bSYour Name 	status = qdf_list_peek_front(log_del_obj_list, &node);
457*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
458*5113495bSYour Name 		qdf_spin_unlock_bh(&debug_info->list_lock);
459*5113495bSYour Name 		return;
460*5113495bSYour Name 	}
461*5113495bSYour Name 
462*5113495bSYour Name 	/* compute the current timestamp in seconds
463*5113495bSYour Name 	 * need to compare with destroy duration of object
464*5113495bSYour Name 	 */
465*5113495bSYour Name 	cur_tstamp = (qdf_system_ticks_to_msecs(qdf_system_ticks()) / 1000);
466*5113495bSYour Name 
467*5113495bSYour Name 	do {
468*5113495bSYour Name 		del_obj = qdf_container_of(node, struct log_del_obj, node);
469*5113495bSYour Name 		obj_type = del_obj->obj_type;
470*5113495bSYour Name 		macaddr = wlan_objmgr_debug_get_macaddr(&del_obj->obj,
471*5113495bSYour Name 							obj_type);
472*5113495bSYour Name 		obj_name = wlan_obj_type_get_obj_name(obj_type);
473*5113495bSYour Name 
474*5113495bSYour Name 		/* If object is in logically deleted state for time more than
475*5113495bSYour Name 		 * destroy duration, print the object type and MAC
476*5113495bSYour Name 		 */
477*5113495bSYour Name 		if (cur_tstamp  < (del_obj->tstamp +
478*5113495bSYour Name 					LOG_DEL_OBJ_DESTROY_DURATION_SEC)) {
479*5113495bSYour Name 			break;
480*5113495bSYour Name 		}
481*5113495bSYour Name 		if (!macaddr) {
482*5113495bSYour Name 			obj_mgr_err("macaddr is null");
483*5113495bSYour Name 			QDF_BUG(0);
484*5113495bSYour Name 			break;
485*5113495bSYour Name 		}
486*5113495bSYour Name 		if (!obj_name) {
487*5113495bSYour Name 			obj_mgr_err("obj_name is null");
488*5113495bSYour Name 			QDF_BUG(0);
489*5113495bSYour Name 			break;
490*5113495bSYour Name 		}
491*5113495bSYour Name 
492*5113495bSYour Name 		obj_mgr_alert("#%s in L-state,MAC: " QDF_MAC_ADDR_FMT,
493*5113495bSYour Name 			      obj_name, QDF_MAC_ADDR_REF(macaddr));
494*5113495bSYour Name 		wlan_objmgr_print_pending_refs(&del_obj->obj, obj_type);
495*5113495bSYour Name 
496*5113495bSYour Name 		wlan_objmgr_trace_print_ref(&del_obj->obj, obj_type);
497*5113495bSYour Name 		if (cur_tstamp > del_obj->tstamp +
498*5113495bSYour Name 		    LOG_DEL_OBJ_DESTROY_ASSERT_DURATION_SEC) {
499*5113495bSYour Name 			if (!qdf_is_recovering() && !qdf_is_fw_down())
500*5113495bSYour Name 				wlan_objmgr_debug_obj_destroyed_panic(obj_name);
501*5113495bSYour Name 		}
502*5113495bSYour Name 
503*5113495bSYour Name 		status = qdf_list_peek_next(log_del_obj_list, node, &node);
504*5113495bSYour Name 
505*5113495bSYour Name 	} while (QDF_IS_STATUS_SUCCESS(status));
506*5113495bSYour Name 
507*5113495bSYour Name 	qdf_timer_mod(&debug_info->obj_timer, LOG_DEL_OBJ_TIMEOUT_VALUE_MSEC);
508*5113495bSYour Name 	qdf_spin_unlock_bh(&debug_info->list_lock);
509*5113495bSYour Name }
510*5113495bSYour Name 
wlan_objmgr_debug_info_deinit(void)511*5113495bSYour Name void wlan_objmgr_debug_info_deinit(void)
512*5113495bSYour Name {
513*5113495bSYour Name 	struct log_del_obj *obj_to_remove;
514*5113495bSYour Name 	struct wlan_objmgr_debug_info *debug_info;
515*5113495bSYour Name 	qdf_list_node_t *node = NULL;
516*5113495bSYour Name 	qdf_list_t *list;
517*5113495bSYour Name 	bool is_child_alive = false;
518*5113495bSYour Name 
519*5113495bSYour Name 	debug_info = g_umac_glb_obj->debug_info;
520*5113495bSYour Name 
521*5113495bSYour Name 	if (!debug_info) {
522*5113495bSYour Name 		obj_mgr_err("debug_info is not initialized");
523*5113495bSYour Name 		return;
524*5113495bSYour Name 	}
525*5113495bSYour Name 	list = &debug_info->obj_list;
526*5113495bSYour Name 
527*5113495bSYour Name 	qdf_spin_lock_bh(&debug_info->list_lock);
528*5113495bSYour Name 
529*5113495bSYour Name 	/* Check if any child of global object is in L-state and remove it,
530*5113495bSYour Name 	 * ideally it shouldn't be
531*5113495bSYour Name 	 */
532*5113495bSYour Name 	while (qdf_list_remove_front(list, &node) == QDF_STATUS_SUCCESS) {
533*5113495bSYour Name 		is_child_alive = true;
534*5113495bSYour Name 		obj_to_remove = qdf_container_of(node,
535*5113495bSYour Name 						 struct log_del_obj, node);
536*5113495bSYour Name 		if (qdf_list_empty(&debug_info->obj_list))
537*5113495bSYour Name 			qdf_timer_stop(&debug_info->obj_timer);
538*5113495bSYour Name 		/* free the object */
539*5113495bSYour Name 		qdf_mem_free(obj_to_remove);
540*5113495bSYour Name 	}
541*5113495bSYour Name 	qdf_spin_unlock_bh(&debug_info->list_lock);
542*5113495bSYour Name 
543*5113495bSYour Name 	if (is_child_alive) {
544*5113495bSYour Name 		obj_mgr_alert("This shouldn't happen!!, No child of global"
545*5113495bSYour Name 			       "object should be in L-state, as global obj"
546*5113495bSYour Name 				"is going to destroy");
547*5113495bSYour Name 		QDF_BUG(0);
548*5113495bSYour Name 	}
549*5113495bSYour Name 
550*5113495bSYour Name 	/* free timer, destroy spinlock, list and debug_info object as
551*5113495bSYour Name 	 * global object is going to free
552*5113495bSYour Name 	 */
553*5113495bSYour Name 	qdf_list_destroy(list);
554*5113495bSYour Name 	qdf_timer_free(&debug_info->obj_timer);
555*5113495bSYour Name 	qdf_spinlock_destroy(&debug_info->list_lock);
556*5113495bSYour Name 	qdf_mem_free(debug_info);
557*5113495bSYour Name 
558*5113495bSYour Name 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
559*5113495bSYour Name 	g_umac_glb_obj->debug_info = NULL;
560*5113495bSYour Name 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
561*5113495bSYour Name }
562*5113495bSYour Name 
wlan_objmgr_debug_info_init(void)563*5113495bSYour Name void wlan_objmgr_debug_info_init(void)
564*5113495bSYour Name {
565*5113495bSYour Name 	struct wlan_objmgr_debug_info *debug_info;
566*5113495bSYour Name 
567*5113495bSYour Name 	debug_info = qdf_mem_malloc(sizeof(*debug_info));
568*5113495bSYour Name 	if (!debug_info) {
569*5113495bSYour Name 		g_umac_glb_obj->debug_info = NULL;
570*5113495bSYour Name 		return;
571*5113495bSYour Name 	}
572*5113495bSYour Name 
573*5113495bSYour Name 	/* Initialize timer with timeout handler */
574*5113495bSYour Name 	qdf_timer_init(NULL, &debug_info->obj_timer,
575*5113495bSYour Name 		       wlan_objmgr_iterate_log_del_obj_handler,
576*5113495bSYour Name 		       NULL, QDF_TIMER_TYPE_WAKE_APPS);
577*5113495bSYour Name 
578*5113495bSYour Name 	/* Initialize the node_count to 0 and create list*/
579*5113495bSYour Name 	qdf_list_create(&debug_info->obj_list,
580*5113495bSYour Name 			LOG_DEL_OBJ_LIST_MAX_COUNT);
581*5113495bSYour Name 
582*5113495bSYour Name 	/* Initialize the spin_lock to protect list */
583*5113495bSYour Name 	qdf_spinlock_create(&debug_info->list_lock);
584*5113495bSYour Name 
585*5113495bSYour Name 	/* attach debug_info object to global object */
586*5113495bSYour Name 	g_umac_glb_obj->debug_info = debug_info;
587*5113495bSYour Name }
588*5113495bSYour Name 
589*5113495bSYour Name #ifdef WLAN_OBJMGR_REF_ID_TRACE
590*5113495bSYour Name void
wlan_objmgr_trace_init_lock(struct wlan_objmgr_trace * trace)591*5113495bSYour Name wlan_objmgr_trace_init_lock(struct wlan_objmgr_trace *trace)
592*5113495bSYour Name {
593*5113495bSYour Name 	qdf_spinlock_create(&trace->trace_lock);
594*5113495bSYour Name }
595*5113495bSYour Name 
596*5113495bSYour Name void
wlan_objmgr_trace_deinit_lock(struct wlan_objmgr_trace * trace)597*5113495bSYour Name wlan_objmgr_trace_deinit_lock(struct wlan_objmgr_trace *trace)
598*5113495bSYour Name {
599*5113495bSYour Name 	qdf_spinlock_destroy(&trace->trace_lock);
600*5113495bSYour Name }
601*5113495bSYour Name #endif
602*5113495bSYour Name 
603*5113495bSYour Name #ifdef WLAN_OBJMGR_REF_ID_TRACE
604*5113495bSYour Name static inline struct wlan_objmgr_line_ref_node*
wlan_objmgr_trace_line_node_alloc(int line)605*5113495bSYour Name wlan_objmgr_trace_line_node_alloc(int line)
606*5113495bSYour Name {
607*5113495bSYour Name 	struct wlan_objmgr_line_ref_node *line_node;
608*5113495bSYour Name 
609*5113495bSYour Name 	line_node = qdf_mem_malloc_atomic(sizeof(*line_node));
610*5113495bSYour Name 	if (!line_node)
611*5113495bSYour Name 		return NULL;
612*5113495bSYour Name 
613*5113495bSYour Name 	line_node->line_ref.line = line;
614*5113495bSYour Name 	qdf_atomic_set(&line_node->line_ref.cnt, 1);
615*5113495bSYour Name 	line_node->next = NULL;
616*5113495bSYour Name 
617*5113495bSYour Name 	return line_node;
618*5113495bSYour Name }
619*5113495bSYour Name 
620*5113495bSYour Name static inline struct wlan_objmgr_trace_func*
wlan_objmgr_trace_ref_node_alloc(const char * func,int line)621*5113495bSYour Name wlan_objmgr_trace_ref_node_alloc(const char *func, int line)
622*5113495bSYour Name {
623*5113495bSYour Name 	struct wlan_objmgr_trace_func *func_node;
624*5113495bSYour Name 	struct wlan_objmgr_line_ref_node *line_node;
625*5113495bSYour Name 
626*5113495bSYour Name 	func_node = qdf_mem_malloc_atomic(sizeof(*func_node));
627*5113495bSYour Name 	if (!func_node)
628*5113495bSYour Name 		return NULL;
629*5113495bSYour Name 
630*5113495bSYour Name 	line_node = wlan_objmgr_trace_line_node_alloc(line);
631*5113495bSYour Name 	if (!line_node) {
632*5113495bSYour Name 		qdf_mem_free(func_node);
633*5113495bSYour Name 		return NULL;
634*5113495bSYour Name 	}
635*5113495bSYour Name 
636*5113495bSYour Name 	func_node->line_head = line_node;
637*5113495bSYour Name 	qdf_str_lcopy(func_node->func, func, WLAN_OBJMGR_TRACE_FUNC_SIZE);
638*5113495bSYour Name 	func_node->next = NULL;
639*5113495bSYour Name 
640*5113495bSYour Name 	return func_node;
641*5113495bSYour Name }
642*5113495bSYour Name 
643*5113495bSYour Name static inline void
wlan_objmgr_trace_check_line(struct wlan_objmgr_trace_func * tmp_func_node,struct wlan_objmgr_trace * trace,int line)644*5113495bSYour Name wlan_objmgr_trace_check_line(struct wlan_objmgr_trace_func *tmp_func_node,
645*5113495bSYour Name 			     struct wlan_objmgr_trace *trace, int line)
646*5113495bSYour Name {
647*5113495bSYour Name 	struct wlan_objmgr_line_ref_node *tmp_ln_node;
648*5113495bSYour Name 
649*5113495bSYour Name 	tmp_ln_node = tmp_func_node->line_head;
650*5113495bSYour Name 	while (tmp_ln_node) {
651*5113495bSYour Name 		if (tmp_ln_node->line_ref.line == line) {
652*5113495bSYour Name 			qdf_atomic_inc(&tmp_ln_node->line_ref.cnt);
653*5113495bSYour Name 			break;
654*5113495bSYour Name 		}
655*5113495bSYour Name 		tmp_ln_node = tmp_ln_node->next;
656*5113495bSYour Name 	}
657*5113495bSYour Name 	if (!tmp_ln_node) {
658*5113495bSYour Name 		tmp_ln_node = wlan_objmgr_trace_line_node_alloc(line);
659*5113495bSYour Name 		if (tmp_ln_node) {
660*5113495bSYour Name 			tmp_ln_node->next = tmp_func_node->line_head;
661*5113495bSYour Name 			tmp_func_node->line_head = tmp_ln_node;
662*5113495bSYour Name 		}
663*5113495bSYour Name 	}
664*5113495bSYour Name }
665*5113495bSYour Name 
666*5113495bSYour Name void
wlan_objmgr_trace_ref(struct wlan_objmgr_trace_func ** func_head,struct wlan_objmgr_trace * trace,const char * func,int line)667*5113495bSYour Name wlan_objmgr_trace_ref(struct wlan_objmgr_trace_func **func_head,
668*5113495bSYour Name 		      struct wlan_objmgr_trace *trace,
669*5113495bSYour Name 		      const char *func, int line)
670*5113495bSYour Name {
671*5113495bSYour Name 	struct wlan_objmgr_trace_func *tmp_func_node;
672*5113495bSYour Name 	struct wlan_objmgr_trace_func *func_node;
673*5113495bSYour Name 
674*5113495bSYour Name 	qdf_spin_lock_bh(&trace->trace_lock);
675*5113495bSYour Name 	if (!*func_head) {
676*5113495bSYour Name 		tmp_func_node = wlan_objmgr_trace_ref_node_alloc(func, line);
677*5113495bSYour Name 		if (tmp_func_node)
678*5113495bSYour Name 			*func_head = tmp_func_node;
679*5113495bSYour Name 	} else {
680*5113495bSYour Name 		tmp_func_node = *func_head;
681*5113495bSYour Name 		while (tmp_func_node) {
682*5113495bSYour Name 			func_node = tmp_func_node;
683*5113495bSYour Name 			if (!qdf_str_ncmp(tmp_func_node->func, func,
684*5113495bSYour Name 					  WLAN_OBJMGR_TRACE_FUNC_SIZE - 1)) {
685*5113495bSYour Name 				wlan_objmgr_trace_check_line(tmp_func_node,
686*5113495bSYour Name 							     trace, line);
687*5113495bSYour Name 				break;
688*5113495bSYour Name 			}
689*5113495bSYour Name 			tmp_func_node = tmp_func_node->next;
690*5113495bSYour Name 		}
691*5113495bSYour Name 
692*5113495bSYour Name 		if (!tmp_func_node) {
693*5113495bSYour Name 			tmp_func_node = wlan_objmgr_trace_ref_node_alloc(func,
694*5113495bSYour Name 									 line);
695*5113495bSYour Name 			if (tmp_func_node)
696*5113495bSYour Name 				func_node->next = tmp_func_node;
697*5113495bSYour Name 		}
698*5113495bSYour Name 	}
699*5113495bSYour Name 	qdf_spin_unlock_bh(&trace->trace_lock);
700*5113495bSYour Name }
701*5113495bSYour Name 
702*5113495bSYour Name static void
wlan_objmgr_trace_del_line(struct wlan_objmgr_line_ref_node ** line_head)703*5113495bSYour Name wlan_objmgr_trace_del_line(struct wlan_objmgr_line_ref_node **line_head)
704*5113495bSYour Name {
705*5113495bSYour Name 	struct wlan_objmgr_line_ref_node *del_tmp_node;
706*5113495bSYour Name 	struct wlan_objmgr_line_ref_node *line_node;
707*5113495bSYour Name 
708*5113495bSYour Name 	line_node = *line_head;
709*5113495bSYour Name 	while (line_node) {
710*5113495bSYour Name 		del_tmp_node = line_node;
711*5113495bSYour Name 		line_node = line_node->next;
712*5113495bSYour Name 		qdf_mem_free(del_tmp_node);
713*5113495bSYour Name 	}
714*5113495bSYour Name 	*line_head = NULL;
715*5113495bSYour Name }
716*5113495bSYour Name 
717*5113495bSYour Name void
wlan_objmgr_trace_del_ref_list(struct wlan_objmgr_trace * trace)718*5113495bSYour Name wlan_objmgr_trace_del_ref_list(struct wlan_objmgr_trace *trace)
719*5113495bSYour Name {
720*5113495bSYour Name 	struct wlan_objmgr_trace_func *func_node;
721*5113495bSYour Name 	struct wlan_objmgr_trace_func *del_tmp_node;
722*5113495bSYour Name 	uint32_t id;
723*5113495bSYour Name 
724*5113495bSYour Name 	qdf_spin_lock_bh(&trace->trace_lock);
725*5113495bSYour Name 	for (id = 0; id < WLAN_REF_ID_MAX; id++) {
726*5113495bSYour Name 		func_node = trace->references[id].head;
727*5113495bSYour Name 		while (func_node) {
728*5113495bSYour Name 			del_tmp_node = func_node;
729*5113495bSYour Name 			wlan_objmgr_trace_del_line(&del_tmp_node->line_head);
730*5113495bSYour Name 			func_node = func_node->next;
731*5113495bSYour Name 			qdf_mem_free(del_tmp_node);
732*5113495bSYour Name 		}
733*5113495bSYour Name 		trace->references[id].head = NULL;
734*5113495bSYour Name 	}
735*5113495bSYour Name 	for (id = 0; id < WLAN_REF_ID_MAX; id++) {
736*5113495bSYour Name 		func_node = trace->dereferences[id].head;
737*5113495bSYour Name 		while (func_node) {
738*5113495bSYour Name 			del_tmp_node = func_node;
739*5113495bSYour Name 			wlan_objmgr_trace_del_line(&del_tmp_node->line_head);
740*5113495bSYour Name 			func_node = func_node->next;
741*5113495bSYour Name 			qdf_mem_free(del_tmp_node);
742*5113495bSYour Name 		}
743*5113495bSYour Name 		trace->dereferences[id].head = NULL;
744*5113495bSYour Name 	}
745*5113495bSYour Name 	qdf_spin_unlock_bh(&trace->trace_lock);
746*5113495bSYour Name }
747*5113495bSYour Name #endif
748