1 /*
2  * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 /**
20  * DOC: Public APIs to perform operations on Peer object
21  */
22 #include <wlan_objmgr_cmn.h>
23 #include <wlan_objmgr_global_obj.h>
24 #include <wlan_objmgr_psoc_obj.h>
25 #include <wlan_objmgr_pdev_obj.h>
26 #include <wlan_objmgr_vdev_obj.h>
27 #include <wlan_objmgr_peer_obj.h>
28 #include <wlan_objmgr_debug.h>
29 #include <qdf_mem.h>
30 #include <qdf_module.h>
31 #include "wlan_objmgr_global_obj_i.h"
32 #include "wlan_objmgr_psoc_obj_i.h"
33 #include "wlan_objmgr_pdev_obj_i.h"
34 #include "wlan_objmgr_vdev_obj_i.h"
35 
36 
37 /*
38  * APIs to Create/Delete Peer object APIs
39  */
wlan_objmgr_peer_object_status(struct wlan_objmgr_peer * peer)40 static QDF_STATUS wlan_objmgr_peer_object_status(
41 		struct wlan_objmgr_peer *peer)
42 {
43 	uint8_t id;
44 	QDF_STATUS status = QDF_STATUS_SUCCESS;
45 
46 	wlan_peer_obj_lock(peer);
47 	/* Iterate through all components to derive the object status */
48 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
49 		/* If component disabled, Ignore */
50 		if (peer->obj_status[id] == QDF_STATUS_COMP_DISABLED)
51 			continue;
52 		/* If component operates in Async, status is Partially created,
53 			break */
54 		else if (peer->obj_status[id] == QDF_STATUS_COMP_ASYNC) {
55 			if (!peer->peer_comp_priv_obj[id]) {
56 				status = QDF_STATUS_COMP_ASYNC;
57 				break;
58 			}
59 		/* If component failed to allocate its object, treat it as
60 			failure, complete object need to be cleaned up */
61 		} else if ((peer->obj_status[id] == QDF_STATUS_E_NOMEM) ||
62 			(peer->obj_status[id] == QDF_STATUS_E_FAILURE)) {
63 			obj_mgr_err("Peer comp object(id:%d) alloc fail", id);
64 			status = QDF_STATUS_E_FAILURE;
65 			break;
66 		}
67 	}
68 	wlan_peer_obj_unlock(peer);
69 	return status;
70 }
71 
wlan_objmgr_peer_obj_free(struct wlan_objmgr_peer * peer)72 static QDF_STATUS wlan_objmgr_peer_obj_free(struct wlan_objmgr_peer *peer)
73 {
74 	struct wlan_objmgr_psoc *psoc;
75 	struct wlan_objmgr_vdev *vdev;
76 	uint8_t *macaddr;
77 	uint8_t vdev_id;
78 	bool peer_free_notify = true;
79 
80 	if (!peer) {
81 		obj_mgr_err("PEER is NULL");
82 		return QDF_STATUS_E_FAILURE;
83 	}
84 
85 	macaddr = wlan_peer_get_macaddr(peer);
86 
87 	vdev = wlan_peer_get_vdev(peer);
88 	if (!vdev) {
89 		obj_mgr_err(
90 			"VDEV is NULL for peer("QDF_MAC_ADDR_FMT")",
91 				QDF_MAC_ADDR_REF(macaddr));
92 		return QDF_STATUS_E_FAILURE;
93 	}
94 
95 	/* Notify peer free only for non self peer*/
96 	if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer),
97 			 wlan_vdev_mlme_get_macaddr(vdev)) ==
98 				QDF_STATUS_SUCCESS)
99 		peer_free_notify = false;
100 
101 	vdev_id = wlan_vdev_get_id(vdev);
102 
103 	/* get PSOC from VDEV, if it is NULL, return */
104 	psoc = wlan_vdev_get_psoc(vdev);
105 	if (!psoc) {
106 		obj_mgr_err(
107 			"PSOC is NULL for peer("QDF_MAC_ADDR_FMT")",
108 				QDF_MAC_ADDR_REF(macaddr));
109 		return QDF_STATUS_E_FAILURE;
110 	}
111 
112 	/* Decrement ref count for BSS peer, so that BSS peer deletes last*/
113 	if ((wlan_peer_get_peer_type(peer) == WLAN_PEER_STA) ||
114 	    (wlan_peer_get_peer_type(peer) == WLAN_PEER_STA_TEMP) ||
115 	    (wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_CLI))
116 		wlan_objmgr_peer_release_ref(wlan_vdev_get_bsspeer(vdev),
117 					     WLAN_OBJMGR_ID);
118 
119 	wlan_objmgr_vdev_get_ref(vdev, WLAN_OBJMGR_ID);
120 
121 	/* Detach peer from VDEV's peer list */
122 	if (wlan_objmgr_vdev_peer_detach(vdev, peer) == QDF_STATUS_E_FAILURE) {
123 		obj_mgr_err(
124 		"Peer("QDF_MAC_ADDR_FMT") VDEV detach fail, vdev id: %d",
125 			QDF_MAC_ADDR_REF(macaddr), vdev_id);
126 		wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID);
127 		return QDF_STATUS_E_FAILURE;
128 	}
129 	/* Detach peer from PSOC's peer list */
130 	if (wlan_objmgr_psoc_peer_detach(psoc, peer) == QDF_STATUS_E_FAILURE) {
131 		obj_mgr_err(
132 		"Peer("QDF_MAC_ADDR_FMT") PSOC detach failure",
133 			QDF_MAC_ADDR_REF(macaddr));
134 		wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID);
135 		return QDF_STATUS_E_FAILURE;
136 	}
137 	wlan_objmgr_peer_trace_del_ref_list(peer);
138 	wlan_objmgr_peer_trace_deinit_lock(peer);
139 	qdf_spinlock_destroy(&peer->peer_lock);
140 	qdf_mem_free(peer);
141 	peer = NULL;
142 
143 	if (peer_free_notify)
144 		wlan_objmgr_vdev_peer_freed_notify(vdev);
145 
146 	wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID);
147 
148 	return QDF_STATUS_SUCCESS;
149 
150 }
151 
152 #ifdef WLAN_OBJMGR_REF_ID_DEBUG
153 static void
wlan_objmgr_peer_init_ref_id_debug(struct wlan_objmgr_peer * peer)154 wlan_objmgr_peer_init_ref_id_debug(struct wlan_objmgr_peer *peer)
155 {
156 	uint8_t id;
157 
158 	for (id = 0; id < WLAN_REF_ID_MAX; id++)
159 		qdf_atomic_init(&peer->peer_objmgr.ref_id_dbg[id]);
160 }
161 #else
162 static inline void
wlan_objmgr_peer_init_ref_id_debug(struct wlan_objmgr_peer * peer)163 wlan_objmgr_peer_init_ref_id_debug(struct wlan_objmgr_peer *peer) {}
164 #endif
165 
wlan_objmgr_peer_obj_create(struct wlan_objmgr_vdev * vdev,enum wlan_peer_type type,uint8_t * macaddr)166 struct wlan_objmgr_peer *wlan_objmgr_peer_obj_create(
167 			struct wlan_objmgr_vdev *vdev,
168 			enum wlan_peer_type type,
169 			uint8_t *macaddr)
170 {
171 	struct wlan_objmgr_peer *peer;
172 	struct wlan_objmgr_psoc *psoc;
173 	wlan_objmgr_peer_create_handler handler;
174 	wlan_objmgr_peer_status_handler stat_handler;
175 	void *arg;
176 	QDF_STATUS obj_status;
177 	uint8_t id;
178 
179 	if (!vdev) {
180 		obj_mgr_err(
181 			"VDEV is NULL for peer ("QDF_MAC_ADDR_FMT")",
182 				QDF_MAC_ADDR_REF(macaddr));
183 		return NULL;
184 	}
185 	/* Get psoc, if psoc is NULL, return */
186 	psoc = wlan_vdev_get_psoc(vdev);
187 	if (!psoc) {
188 		obj_mgr_err(
189 			"PSOC is NULL for peer ("QDF_MAC_ADDR_FMT")",
190 				QDF_MAC_ADDR_REF(macaddr));
191 		return NULL;
192 	}
193 	/* Allocate memory for peer object */
194 	peer = qdf_mem_malloc(sizeof(*peer));
195 	if (!peer)
196 		return NULL;
197 
198 	peer->obj_state = WLAN_OBJ_STATE_ALLOCATED;
199 	qdf_atomic_init(&peer->peer_objmgr.ref_cnt);
200 	wlan_objmgr_peer_init_ref_id_debug(peer);
201 	wlan_objmgr_peer_trace_init_lock(peer);
202 	wlan_objmgr_peer_get_ref(peer, WLAN_OBJMGR_ID);
203 	/* set vdev to peer */
204 	wlan_peer_set_vdev(peer, vdev);
205 	/* set peer type */
206 	wlan_peer_set_peer_type(peer, type);
207 	/* set mac address of peer */
208 	wlan_peer_set_macaddr(peer, macaddr);
209 	/* initialize peer state */
210 	wlan_peer_mlme_set_state(peer, WLAN_INIT_STATE);
211 	wlan_peer_mlme_reset_seq_num(peer);
212 	peer->peer_objmgr.print_cnt = 0;
213 
214 	qdf_spinlock_create(&peer->peer_lock);
215 	/* Attach peer to psoc, psoc maintains the node table for the device */
216 	if (wlan_objmgr_psoc_peer_attach(psoc, peer) !=
217 					QDF_STATUS_SUCCESS) {
218 		obj_mgr_warn(
219 		"Peer("QDF_MAC_ADDR_FMT") PSOC attach failure",
220 				QDF_MAC_ADDR_REF(macaddr));
221 		qdf_spinlock_destroy(&peer->peer_lock);
222 		wlan_objmgr_peer_trace_deinit_lock(peer);
223 		qdf_mem_free(peer);
224 		return NULL;
225 	}
226 	/* Attach peer to vdev peer table */
227 	if (wlan_objmgr_vdev_peer_attach(vdev, peer) !=
228 					QDF_STATUS_SUCCESS) {
229 		obj_mgr_warn(
230 		"Peer("QDF_MAC_ADDR_FMT") VDEV attach failure",
231 				QDF_MAC_ADDR_REF(macaddr));
232 		/* if attach fails, detach from psoc table before free */
233 		wlan_objmgr_psoc_peer_detach(psoc, peer);
234 		qdf_spinlock_destroy(&peer->peer_lock);
235 		wlan_objmgr_peer_trace_deinit_lock(peer);
236 		qdf_mem_free(peer);
237 		return NULL;
238 	}
239 	wlan_peer_set_pdev_id(peer, wlan_objmgr_pdev_get_pdev_id(
240 			wlan_vdev_get_pdev(vdev)));
241 	/* Increment ref count for BSS peer, so that BSS peer deletes last*/
242 	if ((type == WLAN_PEER_STA) || (type == WLAN_PEER_STA_TEMP)
243 				    || (type == WLAN_PEER_P2P_CLI))
244 		wlan_objmgr_peer_get_ref(wlan_vdev_get_bsspeer(vdev),
245 					 WLAN_OBJMGR_ID);
246 	/* TODO init other parameters */
247 	/* Invoke registered create handlers */
248 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
249 		handler = g_umac_glb_obj->peer_create_handler[id];
250 		arg = g_umac_glb_obj->peer_create_handler_arg[id];
251 		if (handler)
252 			peer->obj_status[id] = handler(peer, arg);
253 		else
254 			peer->obj_status[id] = QDF_STATUS_COMP_DISABLED;
255 	}
256 	/* derive the object status */
257 	obj_status = wlan_objmgr_peer_object_status(peer);
258 	/* If SUCCESS, Object is created */
259 	if (obj_status == QDF_STATUS_SUCCESS) {
260 		peer->obj_state = WLAN_OBJ_STATE_CREATED;
261 		for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
262 			stat_handler = g_umac_glb_obj->peer_status_handler[id];
263 			arg = g_umac_glb_obj->peer_status_handler_arg[id];
264 			if (stat_handler)
265 				stat_handler(peer, arg,
266 					     QDF_STATUS_SUCCESS);
267 		}
268 	} else if (obj_status == QDF_STATUS_COMP_ASYNC) {
269 		/* If any component operates in different context, update it
270 		as partially created */
271 		peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED;
272 	} else if (obj_status == QDF_STATUS_E_FAILURE) {
273 		/* Clean up the peer */
274 		obj_mgr_err(
275 		"Peer("QDF_MAC_ADDR_FMT") comp object alloc fail",
276 				QDF_MAC_ADDR_REF(macaddr));
277 		wlan_objmgr_peer_obj_delete(peer);
278 		return NULL;
279 	}
280 
281 	obj_mgr_debug("Created peer " QDF_MAC_ADDR_FMT " type %d",
282 		      QDF_MAC_ADDR_REF(macaddr), type);
283 
284 	return peer;
285 }
286 
287 static QDF_STATUS
__wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer * peer)288 __wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer *peer)
289 {
290 	uint8_t id;
291 	wlan_objmgr_peer_destroy_handler handler;
292 	QDF_STATUS obj_status;
293 	void *arg;
294 	uint8_t *macaddr;
295 
296 	if (!peer) {
297 		obj_mgr_err("PEER is NULL");
298 		return QDF_STATUS_E_FAILURE;
299 	}
300 	wlan_objmgr_notify_destroy(peer, WLAN_PEER_OP);
301 
302 	macaddr = wlan_peer_get_macaddr(peer);
303 
304 	obj_mgr_debug("Physically deleting peer " QDF_MAC_ADDR_FMT,
305 		      QDF_MAC_ADDR_REF(macaddr));
306 
307 	if (peer->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) {
308 		obj_mgr_err("PEER object del is not invoked obj_state:%d peer "
309 			    QDF_MAC_ADDR_FMT, peer->obj_state,
310 			    QDF_MAC_ADDR_REF(macaddr));
311 		WLAN_OBJMGR_BUG(0);
312 	}
313 
314 	/* Invoke registered destroy handlers */
315 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
316 		handler = g_umac_glb_obj->peer_destroy_handler[id];
317 		arg = g_umac_glb_obj->peer_destroy_handler_arg[id];
318 		if (handler &&
319 		    (peer->obj_status[id] == QDF_STATUS_SUCCESS ||
320 		     peer->obj_status[id] == QDF_STATUS_COMP_ASYNC))
321 			peer->obj_status[id] = handler(peer, arg);
322 		else
323 			peer->obj_status[id] = QDF_STATUS_COMP_DISABLED;
324 	}
325 	/* Derive the object status */
326 	obj_status = wlan_objmgr_peer_object_status(peer);
327 	if (obj_status == QDF_STATUS_E_FAILURE) {
328 		/* If it status is failure, memory will not be freed */
329 		QDF_BUG(0);
330 		return QDF_STATUS_E_FAILURE;
331 	}
332 	/* few components deletion is in progress */
333 	if (obj_status == QDF_STATUS_COMP_ASYNC) {
334 		peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED;
335 		return QDF_STATUS_COMP_ASYNC;
336 	}
337 
338 	/* Free the peer object */
339 	return wlan_objmgr_peer_obj_free(peer);
340 }
341 
342 #ifdef FEATURE_DELAYED_PEER_OBJ_DESTROY
343 /*
344  * Length of the list used to hold delayed peer obj free.
345  * Must be a multiple of 2.
346  */
347 #define MAX_DELAYED_FREE_PEERS 64
348 
349 /**
350  * wlan_objmgr_peer_obj_free_work() - Peer obj freed in the delayed work
351  * @data: PDEV object
352  *
353  * Peer obj freed in the delayed work
354  *
355  * Return: None
356  */
wlan_objmgr_peer_obj_free_work(void * data)357 static void wlan_objmgr_peer_obj_free_work(void *data)
358 {
359 	struct wlan_objmgr_pdev *pdev = data;
360 	struct wlan_objmgr_peer *peer;
361 	qdf_list_node_t *node;
362 	uint8_t *macaddr;
363 
364 	if (!pdev) {
365 		obj_mgr_err("pdev is NULL");
366 		return;
367 	}
368 
369 	qdf_spin_lock_bh(&pdev->peer_free_lock);
370 	while (!(qdf_list_empty(&pdev->peer_free_list))) {
371 		qdf_list_remove_front(&pdev->peer_free_list, &node);
372 		qdf_spin_unlock_bh(&pdev->peer_free_lock);
373 
374 		peer = qdf_container_of(node,
375 					struct wlan_objmgr_peer,
376 					free_node);
377 
378 		macaddr = wlan_peer_get_macaddr(peer);
379 		obj_mgr_debug("active_work_cnt %u list size %u peer 0x%pK("
380 			      QDF_MAC_ADDR_FMT ")",
381 			      pdev->active_work_cnt,
382 			      qdf_list_size(&pdev->peer_free_list),
383 			      peer,
384 			      QDF_MAC_ADDR_REF(macaddr));
385 
386 		__wlan_objmgr_peer_obj_destroy(peer);
387 
388 		qdf_spin_lock_bh(&pdev->peer_free_lock);
389 	}
390 
391 	pdev->active_work_cnt--;
392 
393 	qdf_spin_unlock_bh(&pdev->peer_free_lock);
394 }
395 
396 /**
397  * wlan_peer_obj_free_enqueue() - enqueue freed peer into kworker
398  * @peer: PEER object
399  *
400  * Enqueue freed peer into kworker
401  *
402  * Return: None
403  */
404 static QDF_STATUS
wlan_peer_obj_free_enqueue(struct wlan_objmgr_peer * peer)405 wlan_peer_obj_free_enqueue(struct wlan_objmgr_peer *peer)
406 {
407 	struct wlan_objmgr_vdev *vdev;
408 	struct wlan_objmgr_pdev *pdev;
409 	uint8_t *macaddr;
410 
411 	if (!peer) {
412 		obj_mgr_err("peer is NULL");
413 		return QDF_STATUS_E_FAILURE;
414 	}
415 
416 	macaddr = wlan_peer_get_macaddr(peer);
417 
418 	vdev = wlan_peer_get_vdev(peer);
419 	if (!vdev) {
420 		obj_mgr_err("VDEV is NULL for peer(" QDF_MAC_ADDR_FMT ")",
421 			    QDF_MAC_ADDR_REF(macaddr));
422 		return QDF_STATUS_E_FAILURE;
423 	}
424 	/* get PDEV from VDEV, if it is NULL, return */
425 	pdev = wlan_vdev_get_pdev(vdev);
426 	if (!pdev) {
427 		obj_mgr_err("PDEV is NULL for peer(" QDF_MAC_ADDR_FMT ")",
428 			    QDF_MAC_ADDR_REF(macaddr));
429 		return QDF_STATUS_E_FAILURE;
430 	}
431 
432 	qdf_spin_lock_bh(&pdev->peer_free_lock);
433 	qdf_list_insert_back(&pdev->peer_free_list, &peer->free_node);
434 	pdev->active_work_cnt++;
435 	qdf_spin_unlock_bh(&pdev->peer_free_lock);
436 
437 	obj_mgr_debug("active_work_cnt %u list size %u peer 0x%pK("
438 		      QDF_MAC_ADDR_FMT ")",
439 		      pdev->active_work_cnt,
440 		      qdf_list_size(&pdev->peer_free_list),
441 		      peer,
442 		      QDF_MAC_ADDR_REF(macaddr));
443 
444 	qdf_sched_work(0, &pdev->peer_obj_free_work);
445 
446 	return QDF_STATUS_SUCCESS;
447 }
448 
449 static QDF_STATUS
wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer * peer)450 wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer *peer)
451 {
452 	QDF_STATUS status;
453 
454 	if (qdf_in_atomic()) {
455 		status = wlan_peer_obj_free_enqueue(peer);
456 		if (status == QDF_STATUS_SUCCESS)
457 			return status;
458 
459 		obj_mgr_err("enqueue failure, call free obj directly");
460 	}
461 
462 	status = __wlan_objmgr_peer_obj_destroy(peer);
463 
464 	return status;
465 }
466 
467 /**
468  * wlan_delayed_peer_obj_free_init() - Init for delayed peer obj freed queue
469  * @data: PDEV object
470  *
471  * Initialize main data structures to process peer obj destroy in a delayed
472  * workqueue.
473  *
474  * Return: QDF_STATUS_SUCCESS on success else a QDF error.
475  */
wlan_delayed_peer_obj_free_init(void * data)476 QDF_STATUS wlan_delayed_peer_obj_free_init(void *data)
477 {
478 	struct wlan_objmgr_pdev *pdev = data;
479 
480 	if (!pdev) {
481 		obj_mgr_err("pdev is NULL");
482 		return QDF_STATUS_E_FAILURE;
483 	}
484 
485 	qdf_spinlock_create(&pdev->peer_free_lock);
486 	qdf_create_work(0, &pdev->peer_obj_free_work,
487 			wlan_objmgr_peer_obj_free_work,
488 			(void *)pdev);
489 	pdev->active_work_cnt = 0;
490 
491 	/* Initialize PDEV's peer free list, assign default values */
492 	qdf_list_create(&pdev->peer_free_list, MAX_DELAYED_FREE_PEERS);
493 
494 	obj_mgr_debug("Delayed peer obj free init successfully");
495 
496 	return QDF_STATUS_SUCCESS;
497 }
498 
499 /**
500  * wlan_delayed_peer_obj_free_deinit() - De-Init delayed peer freed processing
501  * @data: PDEV object
502  *
503  * De-initialize main data structures to process peer obj freed in a delayed
504  * workqueue.
505  *
506  * Return: QDF_STATUS_SUCCESS on success else a QDF error.
507  */
wlan_delayed_peer_obj_free_deinit(void * data)508 QDF_STATUS wlan_delayed_peer_obj_free_deinit(void *data)
509 {
510 	struct wlan_objmgr_pdev *pdev = data;
511 
512 	if (!pdev) {
513 		obj_mgr_err("pdev is NULL");
514 		return QDF_STATUS_E_FAILURE;
515 	}
516 
517 	qdf_destroy_work(0, &pdev->peer_obj_free_work);
518 	qdf_spinlock_destroy(&pdev->peer_free_lock);
519 
520 	obj_mgr_debug("Deinit successfully, active_work_cnt=%u",
521 		      pdev->active_work_cnt);
522 
523 	return QDF_STATUS_SUCCESS;
524 }
525 #else
526 static QDF_STATUS
wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer * peer)527 wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer *peer)
528 {
529 	return __wlan_objmgr_peer_obj_destroy(peer);
530 }
531 #endif
532 
wlan_objmgr_peer_obj_delete(struct wlan_objmgr_peer * peer)533 QDF_STATUS wlan_objmgr_peer_obj_delete(struct wlan_objmgr_peer *peer)
534 {
535 	uint8_t print_idx;
536 	uint8_t *macaddr;
537 
538 	if (!peer) {
539 		obj_mgr_err("PEER is NULL");
540 		return QDF_STATUS_E_FAILURE;
541 	}
542 
543 	wlan_peer_obj_lock(peer);
544 	macaddr = wlan_peer_get_macaddr(peer);
545 	wlan_peer_obj_unlock(peer);
546 
547 	obj_mgr_debug("Logically deleting peer " QDF_MAC_ADDR_FMT,
548 		      QDF_MAC_ADDR_REF(macaddr));
549 
550 	print_idx = qdf_get_pidx();
551 	wlan_objmgr_print_peer_ref_ids(peer, QDF_TRACE_LEVEL_DEBUG);
552 	/*
553 	 * Update VDEV object state to LOGICALLY DELETED
554 	 * It prevents further access of this object
555 	 */
556 	wlan_peer_obj_lock(peer);
557 	peer->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED;
558 	wlan_peer_obj_unlock(peer);
559 	wlan_objmgr_notify_log_delete(peer, WLAN_PEER_OP);
560 	wlan_objmgr_peer_release_ref(peer, WLAN_OBJMGR_ID);
561 
562 	return QDF_STATUS_SUCCESS;
563 }
564 qdf_export_symbol(wlan_objmgr_peer_obj_delete);
565 /*
566  * APIs to attach/detach component objects
567  */
wlan_objmgr_peer_component_obj_attach(struct wlan_objmgr_peer * peer,enum wlan_umac_comp_id id,void * comp_priv_obj,QDF_STATUS status)568 QDF_STATUS wlan_objmgr_peer_component_obj_attach(
569 		struct wlan_objmgr_peer *peer,
570 		enum wlan_umac_comp_id id,
571 		void *comp_priv_obj,
572 		QDF_STATUS status)
573 {
574 	wlan_objmgr_peer_status_handler s_hler;
575 	void *arg;
576 	uint8_t i;
577 	QDF_STATUS obj_status;
578 
579 	/* component id is invalid */
580 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
581 		return QDF_STATUS_MAXCOMP_FAIL;
582 
583 	wlan_peer_obj_lock(peer);
584 	/* If there is a valid entry, return failure,
585 	valid object needs to be freed first */
586 	if (peer->peer_comp_priv_obj[id]) {
587 		wlan_peer_obj_unlock(peer);
588 		return QDF_STATUS_E_FAILURE;
589 	}
590 	/* Assign component object private pointer(can be NULL also), status */
591 	peer->peer_comp_priv_obj[id] = comp_priv_obj;
592 	peer->obj_status[id] = status;
593 	wlan_peer_obj_unlock(peer);
594 
595 	if (peer->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED)
596 		return QDF_STATUS_SUCCESS;
597 
598 	/* If PEER object status is partially created means, this API is
599 	invoked with different context. this block should be executed for async
600 	components only */
601 	/* Derive status */
602 	obj_status = wlan_objmgr_peer_object_status(peer);
603 	/* STATUS_SUCCESS means, object is CREATED */
604 	if (obj_status == QDF_STATUS_SUCCESS)
605 		peer->obj_state = WLAN_OBJ_STATE_CREATED;
606 	/* update state as CREATION failed, caller has to delete the
607 	PEER object */
608 	else if (obj_status == QDF_STATUS_E_FAILURE)
609 		peer->obj_state = WLAN_OBJ_STATE_CREATION_FAILED;
610 	/* Notify components about the CREATION success/failure */
611 	if ((obj_status == QDF_STATUS_SUCCESS) ||
612 	    (obj_status == QDF_STATUS_E_FAILURE)) {
613 		/* notify object status */
614 		for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) {
615 			s_hler = g_umac_glb_obj->peer_status_handler[i];
616 			arg = g_umac_glb_obj->peer_status_handler_arg[i];
617 			if (s_hler)
618 				s_hler(peer, arg, obj_status);
619 		}
620 	}
621 	return QDF_STATUS_SUCCESS;
622 }
623 
624 qdf_export_symbol(wlan_objmgr_peer_component_obj_attach);
625 
wlan_objmgr_peer_component_obj_detach(struct wlan_objmgr_peer * peer,enum wlan_umac_comp_id id,void * comp_priv_obj)626 QDF_STATUS wlan_objmgr_peer_component_obj_detach(
627 		struct wlan_objmgr_peer *peer,
628 		enum wlan_umac_comp_id id,
629 		void *comp_priv_obj)
630 {
631 	QDF_STATUS obj_status;
632 
633 	/* component id is invalid */
634 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
635 		return QDF_STATUS_MAXCOMP_FAIL;
636 
637 	wlan_peer_obj_lock(peer);
638 	/* If there is a invalid entry, return failure */
639 	if (peer->peer_comp_priv_obj[id] != comp_priv_obj) {
640 		peer->obj_status[id] = QDF_STATUS_E_FAILURE;
641 		wlan_peer_obj_unlock(peer);
642 		return QDF_STATUS_E_FAILURE;
643 	}
644 	/* Reset the pointer to NULL */
645 	peer->peer_comp_priv_obj[id] = NULL;
646 	peer->obj_status[id] = QDF_STATUS_SUCCESS;
647 	wlan_peer_obj_unlock(peer);
648 
649 	/* If PEER object status is partially destroyed means, this API is
650 	invoked with different context, this block should be executed for async
651 	components only */
652 	if ((peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) ||
653 	    (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) {
654 		/* Derive object status */
655 		obj_status = wlan_objmgr_peer_object_status(peer);
656 		if (obj_status == QDF_STATUS_SUCCESS) {
657 			/*Update the status as Deleted, if full object
658 				deletion is in progress */
659 			if (peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED)
660 				peer->obj_state = WLAN_OBJ_STATE_DELETED;
661 			/* Move to creation state, since this component
662 			deletion alone requested */
663 			if (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
664 				peer->obj_state = WLAN_OBJ_STATE_CREATED;
665 		/* Object status is failure */
666 		} else if (obj_status == QDF_STATUS_E_FAILURE) {
667 			/*Update the status as Deletion failed, if full object
668 				deletion is in progress */
669 			if (peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED)
670 				peer->obj_state =
671 					WLAN_OBJ_STATE_DELETION_FAILED;
672 			/* Move to creation state, since this component
673 			deletion alone requested (do not block other
674 			components) */
675 			if (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
676 				peer->obj_state = WLAN_OBJ_STATE_CREATED;
677 		}
678 
679 			/* Delete peer object */
680 		if ((obj_status == QDF_STATUS_SUCCESS)  &&
681 		    (peer->obj_state == WLAN_OBJ_STATE_DELETED)) {
682 			/* Free the peer object */
683 			return wlan_objmgr_peer_obj_free(peer);
684 		}
685 	}
686 
687 	return QDF_STATUS_SUCCESS;
688 }
689 
690 qdf_export_symbol(wlan_objmgr_peer_component_obj_detach);
691 
wlan_objmgr_trigger_peer_comp_priv_object_creation(struct wlan_objmgr_peer * peer,enum wlan_umac_comp_id id)692 QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_creation(
693 		struct wlan_objmgr_peer *peer,
694 		enum wlan_umac_comp_id id)
695 {
696 	wlan_objmgr_peer_create_handler handler;
697 	void *arg;
698 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
699 
700 	/* Component id is invalid */
701 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
702 		return QDF_STATUS_MAXCOMP_FAIL;
703 
704 	wlan_peer_obj_lock(peer);
705 	/* If component object is already created, delete old
706 		component object, then invoke creation */
707 	if (peer->peer_comp_priv_obj[id]) {
708 		wlan_peer_obj_unlock(peer);
709 		return QDF_STATUS_E_FAILURE;
710 	}
711 	wlan_peer_obj_unlock(peer);
712 
713 	/* Invoke registered create handlers */
714 	handler = g_umac_glb_obj->peer_create_handler[id];
715 	arg = g_umac_glb_obj->peer_create_handler_arg[id];
716 	if (handler)
717 		peer->obj_status[id] = handler(peer, arg);
718 	else
719 		return QDF_STATUS_E_FAILURE;
720 
721 	/* If object status is created, then only handle this object status */
722 	if (peer->obj_state == WLAN_OBJ_STATE_CREATED) {
723 		/* Derive object status */
724 		obj_status = wlan_objmgr_peer_object_status(peer);
725 		/* Move PDEV object state to Partially created state */
726 		if (obj_status == QDF_STATUS_COMP_ASYNC) {
727 			/*TODO atomic */
728 			peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED;
729 		}
730 	}
731 
732 	return obj_status;
733 }
734 
735 
wlan_objmgr_trigger_peer_comp_priv_object_deletion(struct wlan_objmgr_peer * peer,enum wlan_umac_comp_id id)736 QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_deletion(
737 		struct wlan_objmgr_peer *peer,
738 		enum wlan_umac_comp_id id)
739 {
740 	wlan_objmgr_peer_destroy_handler handler;
741 	void *arg;
742 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
743 
744 	/* component id is invalid */
745 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
746 		return QDF_STATUS_MAXCOMP_FAIL;
747 
748 	wlan_peer_obj_lock(peer);
749 	/* Component object was never created, invalid operation */
750 	if (!peer->peer_comp_priv_obj[id]) {
751 		wlan_peer_obj_unlock(peer);
752 		return QDF_STATUS_E_FAILURE;
753 	}
754 
755 	wlan_peer_obj_unlock(peer);
756 
757 	/* Invoke registered destroy handlers */
758 	handler = g_umac_glb_obj->peer_destroy_handler[id];
759 	arg = g_umac_glb_obj->peer_destroy_handler_arg[id];
760 	if (handler)
761 		peer->obj_status[id] = handler(peer, arg);
762 	else
763 		return QDF_STATUS_E_FAILURE;
764 
765 	/* If object status is created, then only handle this object status */
766 	if (peer->obj_state == WLAN_OBJ_STATE_CREATED) {
767 		obj_status = wlan_objmgr_peer_object_status(peer);
768 			/* move object state to DEL progress */
769 		if (obj_status == QDF_STATUS_COMP_ASYNC)
770 			peer->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS;
771 	}
772 	return obj_status;
773 }
774 
wlan_objmgr_peer_get_comp_private_obj(struct wlan_objmgr_peer * peer,enum wlan_umac_comp_id id)775 void *wlan_objmgr_peer_get_comp_private_obj(
776 		struct wlan_objmgr_peer *peer,
777 		enum wlan_umac_comp_id id)
778 {
779 	void *comp_priv_obj;
780 
781 	/* component id is invalid */
782 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
783 		QDF_BUG(0);
784 		return NULL;
785 	}
786 
787 	if (!peer) {
788 		QDF_BUG(0);
789 		return NULL;
790 	}
791 
792 	comp_priv_obj = peer->peer_comp_priv_obj[id];
793 	return comp_priv_obj;
794 }
795 qdf_export_symbol(wlan_objmgr_peer_get_comp_private_obj);
796 
797 #ifdef WLAN_OBJMGR_REF_ID_DEBUG
798 static inline void
wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id)799 wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer *peer,
800 				  wlan_objmgr_ref_dbgid id)
801 {
802 	qdf_atomic_inc(&peer->peer_objmgr.ref_id_dbg[id]);
803 }
804 #else
805 static inline void
wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id)806 wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer *peer,
807 				  wlan_objmgr_ref_dbgid id) {}
808 #endif
809 
810 #ifdef WLAN_OBJMGR_REF_ID_DEBUG
811 static QDF_STATUS
wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id)812 wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer *peer,
813 				      wlan_objmgr_ref_dbgid id)
814 {
815 	if (!qdf_atomic_read(&peer->peer_objmgr.ref_id_dbg[id])) {
816 		uint8_t *macaddr;
817 
818 		macaddr = wlan_peer_get_macaddr(peer);
819 		obj_mgr_err(
820 		"peer("QDF_MAC_ADDR_FMT") ref was not taken by %d",
821 			QDF_MAC_ADDR_REF(macaddr), id);
822 		wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg,
823 					  QDF_TRACE_LEVEL_FATAL);
824 		WLAN_OBJMGR_BUG(0);
825 		return QDF_STATUS_E_FAILURE;
826 	}
827 
828 	qdf_atomic_dec(&peer->peer_objmgr.ref_id_dbg[id]);
829 	return QDF_STATUS_SUCCESS;
830 }
831 #else
832 static QDF_STATUS
wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id)833 wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer *peer,
834 				      wlan_objmgr_ref_dbgid id)
835 {
836 	return QDF_STATUS_SUCCESS;
837 }
838 #endif
839 
840 #ifdef WLAN_OBJMGR_REF_ID_TRACE
841 static inline void
wlan_objmgr_peer_ref_trace(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id,const char * func,int line)842 wlan_objmgr_peer_ref_trace(struct wlan_objmgr_peer *peer,
843 			   wlan_objmgr_ref_dbgid id,
844 			   const char *func, int line)
845 {
846 	struct wlan_objmgr_trace *trace;
847 
848 	trace = &peer->peer_objmgr.trace;
849 
850 	if (func)
851 		wlan_objmgr_trace_ref(&trace->references[id].head,
852 				      trace, func, line);
853 }
854 
855 static inline void
wlan_objmgr_peer_deref_trace(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id,const char * func,int line)856 wlan_objmgr_peer_deref_trace(struct wlan_objmgr_peer *peer,
857 			     wlan_objmgr_ref_dbgid id,
858 			     const char *func, int line)
859 {
860 	struct wlan_objmgr_trace *trace;
861 
862 	trace = &peer->peer_objmgr.trace;
863 	if (func)
864 		wlan_objmgr_trace_ref(&trace->dereferences[id].head,
865 				      trace, func, line);
866 }
867 #endif
868 
869 #ifdef WLAN_OBJMGR_REF_ID_TRACE
wlan_objmgr_peer_get_ref_debug(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id,const char * func,int line)870 void wlan_objmgr_peer_get_ref_debug(struct wlan_objmgr_peer *peer,
871 				    wlan_objmgr_ref_dbgid id,
872 				    const char *func, int line)
873 {
874 	if (!peer) {
875 		obj_mgr_err("peer obj is NULL for %d", id);
876 		QDF_ASSERT(0);
877 		return;
878 	}
879 	/* Increment ref count */
880 	qdf_atomic_inc(&peer->peer_objmgr.ref_cnt);
881 	wlan_objmgr_peer_get_debug_id_ref(peer, id);
882 
883 	wlan_objmgr_peer_ref_trace(peer, id, func, line);
884 	return;
885 }
886 
887 qdf_export_symbol(wlan_objmgr_peer_get_ref_debug);
888 #else
wlan_objmgr_peer_get_ref(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id)889 void wlan_objmgr_peer_get_ref(struct wlan_objmgr_peer *peer,
890 			      wlan_objmgr_ref_dbgid id)
891 {
892 	if (!peer) {
893 		obj_mgr_err("peer obj is NULL for %d", id);
894 		QDF_ASSERT(0);
895 		return;
896 	}
897 	/* Increment ref count */
898 	qdf_atomic_inc(&peer->peer_objmgr.ref_cnt);
899 	wlan_objmgr_peer_get_debug_id_ref(peer, id);
900 }
901 
902 qdf_export_symbol(wlan_objmgr_peer_get_ref);
903 #endif
904 
905 #ifdef WLAN_OBJMGR_REF_ID_TRACE
wlan_objmgr_peer_try_get_ref_debug(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id,const char * func,int line)906 QDF_STATUS wlan_objmgr_peer_try_get_ref_debug(struct wlan_objmgr_peer *peer,
907 					      wlan_objmgr_ref_dbgid id,
908 					      const char *func, int line)
909 {
910 	if (!peer) {
911 		obj_mgr_err("peer obj is NULL for %d", id);
912 		QDF_ASSERT(0);
913 		return QDF_STATUS_E_FAILURE;
914 	}
915 
916 	wlan_peer_obj_lock(peer);
917 	if (peer->obj_state != WLAN_OBJ_STATE_CREATED) {
918 		wlan_peer_obj_unlock(peer);
919 		if (peer->peer_objmgr.print_cnt++ <=
920 				WLAN_OBJMGR_RATELIMIT_THRESH) {
921 			uint8_t *macaddr;
922 
923 			macaddr = wlan_peer_get_macaddr(peer);
924 			obj_mgr_debug(
925 			"peer(" QDF_MAC_ADDR_FMT ") not in Created st(%d)",
926 			QDF_MAC_ADDR_REF(macaddr),
927 			peer->obj_state);
928 		}
929 		return QDF_STATUS_E_RESOURCES;
930 	}
931 
932 	wlan_objmgr_peer_get_ref_debug(peer, id, func, line);
933 	wlan_peer_obj_unlock(peer);
934 
935 	return QDF_STATUS_SUCCESS;
936 }
937 
938 qdf_export_symbol(wlan_objmgr_peer_try_get_ref_debug);
939 #else
wlan_objmgr_peer_try_get_ref(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id)940 QDF_STATUS wlan_objmgr_peer_try_get_ref(struct wlan_objmgr_peer *peer,
941 					wlan_objmgr_ref_dbgid id)
942 {
943 	if (!peer) {
944 		obj_mgr_err("peer obj is NULL for %d", id);
945 		QDF_ASSERT(0);
946 		return QDF_STATUS_E_FAILURE;
947 	}
948 
949 	wlan_peer_obj_lock(peer);
950 	if (peer->obj_state != WLAN_OBJ_STATE_CREATED) {
951 		wlan_peer_obj_unlock(peer);
952 		if (peer->peer_objmgr.print_cnt++ <=
953 				WLAN_OBJMGR_RATELIMIT_THRESH) {
954 			uint8_t *macaddr;
955 
956 			macaddr = wlan_peer_get_macaddr(peer);
957 			obj_mgr_debug(
958 			"peer(" QDF_MAC_ADDR_FMT ") not in Created st(%d)",
959 			QDF_MAC_ADDR_REF(macaddr),
960 			peer->obj_state);
961 		}
962 		return QDF_STATUS_E_RESOURCES;
963 	}
964 
965 	wlan_objmgr_peer_get_ref(peer, id);
966 	wlan_peer_obj_unlock(peer);
967 
968 	return QDF_STATUS_SUCCESS;
969 }
970 
971 qdf_export_symbol(wlan_objmgr_peer_try_get_ref);
972 #endif
973 
974 #ifdef WLAN_OBJMGR_REF_ID_TRACE
wlan_peer_get_next_active_peer_of_psoc_debug(struct wlan_peer_list * peer_list,uint8_t hash_index,struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid dbg_id,const char * func,int line)975 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_psoc_debug(
976 					struct wlan_peer_list *peer_list,
977 					uint8_t hash_index,
978 					struct wlan_objmgr_peer *peer,
979 					wlan_objmgr_ref_dbgid dbg_id,
980 					const char *func, int line)
981 {
982 	struct wlan_objmgr_peer *peer_next = NULL;
983 	qdf_list_node_t *psoc_node = NULL;
984 	qdf_list_node_t *prev_psoc_node = NULL;
985 	qdf_list_t *obj_list;
986 
987 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
988 	obj_list = &peer_list->peer_hash[hash_index];
989 
990 	prev_psoc_node = &peer->psoc_peer;
991 	while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) ==
992 						QDF_STATUS_SUCCESS) {
993 		peer_next = qdf_container_of(psoc_node, struct wlan_objmgr_peer,
994 					     psoc_peer);
995 
996 		if (wlan_objmgr_peer_try_get_ref_debug(peer_next, dbg_id,
997 						       func, line) ==
998 				QDF_STATUS_SUCCESS) {
999 			qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1000 			return peer_next;
1001 		}
1002 
1003 		prev_psoc_node = psoc_node;
1004 	}
1005 
1006 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1007 
1008 	return NULL;
1009 }
1010 #else
wlan_peer_get_next_active_peer_of_psoc(struct wlan_peer_list * peer_list,uint8_t hash_index,struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid dbg_id)1011 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_psoc(
1012 					struct wlan_peer_list *peer_list,
1013 					uint8_t hash_index,
1014 					struct wlan_objmgr_peer *peer,
1015 					wlan_objmgr_ref_dbgid dbg_id)
1016 {
1017 	struct wlan_objmgr_peer *peer_next = NULL;
1018 	qdf_list_node_t *psoc_node = NULL;
1019 	qdf_list_node_t *prev_psoc_node = NULL;
1020 	qdf_list_t *obj_list;
1021 
1022 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
1023 	obj_list = &peer_list->peer_hash[hash_index];
1024 
1025 	prev_psoc_node = &peer->psoc_peer;
1026 	while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) ==
1027 						QDF_STATUS_SUCCESS) {
1028 		peer_next = qdf_container_of(psoc_node, struct wlan_objmgr_peer,
1029 					     psoc_peer);
1030 
1031 		if (wlan_objmgr_peer_try_get_ref(peer_next, dbg_id) ==
1032 				QDF_STATUS_SUCCESS) {
1033 			qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1034 			return peer_next;
1035 		}
1036 
1037 		prev_psoc_node = psoc_node;
1038 	}
1039 
1040 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1041 
1042 	return NULL;
1043 }
1044 #endif
1045 
1046 #ifdef WLAN_OBJMGR_REF_ID_TRACE
wlan_vdev_peer_list_peek_active_head_debug(struct wlan_objmgr_vdev * vdev,qdf_list_t * peer_list,wlan_objmgr_ref_dbgid dbg_id,const char * func,int line)1047 struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_active_head_debug(
1048 				struct wlan_objmgr_vdev *vdev,
1049 				qdf_list_t *peer_list,
1050 				wlan_objmgr_ref_dbgid dbg_id,
1051 				const char *func, int line)
1052 {
1053 	struct wlan_objmgr_peer *peer;
1054 	qdf_list_node_t *vdev_node = NULL;
1055 	qdf_list_node_t *prev_vdev_node = NULL;
1056 
1057 	wlan_vdev_obj_lock(vdev);
1058 
1059 	if (qdf_list_peek_front(peer_list, &vdev_node) != QDF_STATUS_SUCCESS) {
1060 		wlan_vdev_obj_unlock(vdev);
1061 		return NULL;
1062 	}
1063 
1064 	do {
1065 		peer = qdf_container_of(vdev_node, struct wlan_objmgr_peer,
1066 					vdev_peer);
1067 
1068 		if (wlan_objmgr_peer_try_get_ref_debug(peer, dbg_id,
1069 						       func, line) ==
1070 				QDF_STATUS_SUCCESS) {
1071 			wlan_vdev_obj_unlock(vdev);
1072 			return peer;
1073 		}
1074 
1075 		prev_vdev_node = vdev_node;
1076 	} while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) ==
1077 							QDF_STATUS_SUCCESS);
1078 
1079 	wlan_vdev_obj_unlock(vdev);
1080 
1081 	return NULL;
1082 }
1083 #else
wlan_vdev_peer_list_peek_active_head(struct wlan_objmgr_vdev * vdev,qdf_list_t * peer_list,wlan_objmgr_ref_dbgid dbg_id)1084 struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_active_head(
1085 				struct wlan_objmgr_vdev *vdev,
1086 				qdf_list_t *peer_list,
1087 				wlan_objmgr_ref_dbgid dbg_id)
1088 {
1089 	struct wlan_objmgr_peer *peer;
1090 	qdf_list_node_t *vdev_node = NULL;
1091 	qdf_list_node_t *prev_vdev_node = NULL;
1092 
1093 	wlan_vdev_obj_lock(vdev);
1094 
1095 	if (qdf_list_peek_front(peer_list, &vdev_node) != QDF_STATUS_SUCCESS) {
1096 		wlan_vdev_obj_unlock(vdev);
1097 		return NULL;
1098 	}
1099 
1100 	do {
1101 		peer = qdf_container_of(vdev_node, struct wlan_objmgr_peer,
1102 						vdev_peer);
1103 
1104 		if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) ==
1105 				QDF_STATUS_SUCCESS) {
1106 			wlan_vdev_obj_unlock(vdev);
1107 			return peer;
1108 		}
1109 
1110 		prev_vdev_node = vdev_node;
1111 	} while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) ==
1112 							QDF_STATUS_SUCCESS);
1113 
1114 	wlan_vdev_obj_unlock(vdev);
1115 
1116 	return NULL;
1117 }
1118 #endif
1119 
1120 #ifdef WLAN_OBJMGR_REF_ID_TRACE
wlan_peer_get_next_active_peer_of_vdev_debug(struct wlan_objmgr_vdev * vdev,qdf_list_t * peer_list,struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid dbg_id,const char * func,int line)1121 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_vdev_debug(
1122 					struct wlan_objmgr_vdev *vdev,
1123 					qdf_list_t *peer_list,
1124 					struct wlan_objmgr_peer *peer,
1125 					wlan_objmgr_ref_dbgid dbg_id,
1126 					const char *func, int line)
1127 {
1128 	struct wlan_objmgr_peer *peer_next;
1129 	qdf_list_node_t *vdev_node = NULL;
1130 	qdf_list_node_t *prev_vdev_node = NULL;
1131 
1132 	if (!peer)
1133 		return NULL;
1134 
1135 	wlan_vdev_obj_lock(vdev);
1136 
1137 	prev_vdev_node = &peer->vdev_peer;
1138 	while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) ==
1139 						QDF_STATUS_SUCCESS) {
1140 		peer_next = qdf_container_of(vdev_node, struct wlan_objmgr_peer,
1141 					     vdev_peer);
1142 
1143 		if (wlan_objmgr_peer_try_get_ref_debug(peer_next, dbg_id,
1144 						       func, line) ==
1145 				QDF_STATUS_SUCCESS) {
1146 			wlan_vdev_obj_unlock(vdev);
1147 			return peer_next;
1148 		}
1149 
1150 		prev_vdev_node = vdev_node;
1151 	}
1152 
1153 	wlan_vdev_obj_unlock(vdev);
1154 
1155 	return NULL;
1156 }
1157 #else
wlan_peer_get_next_active_peer_of_vdev(struct wlan_objmgr_vdev * vdev,qdf_list_t * peer_list,struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid dbg_id)1158 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_vdev(
1159 					struct wlan_objmgr_vdev *vdev,
1160 					qdf_list_t *peer_list,
1161 					struct wlan_objmgr_peer *peer,
1162 					wlan_objmgr_ref_dbgid dbg_id)
1163 {
1164 	struct wlan_objmgr_peer *peer_next;
1165 	qdf_list_node_t *vdev_node = NULL;
1166 	qdf_list_node_t *prev_vdev_node = NULL;
1167 
1168 	if (!peer)
1169 		return NULL;
1170 
1171 	wlan_vdev_obj_lock(vdev);
1172 
1173 	prev_vdev_node = &peer->vdev_peer;
1174 	while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) ==
1175 						QDF_STATUS_SUCCESS) {
1176 		peer_next = qdf_container_of(vdev_node, struct wlan_objmgr_peer,
1177 					vdev_peer);
1178 
1179 		if (wlan_objmgr_peer_try_get_ref(peer_next, dbg_id) ==
1180 				QDF_STATUS_SUCCESS) {
1181 			wlan_vdev_obj_unlock(vdev);
1182 			return peer_next;
1183 		}
1184 
1185 		prev_vdev_node = vdev_node;
1186 	}
1187 
1188 	wlan_vdev_obj_unlock(vdev);
1189 
1190 	return NULL;
1191 }
1192 #endif
1193 
1194 #ifdef WLAN_OBJMGR_REF_ID_TRACE
wlan_psoc_peer_list_peek_active_head_debug(struct wlan_peer_list * peer_list,uint8_t hash_index,wlan_objmgr_ref_dbgid dbg_id,const char * func,int line)1195 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_active_head_debug(
1196 					struct wlan_peer_list *peer_list,
1197 					uint8_t hash_index,
1198 					wlan_objmgr_ref_dbgid dbg_id,
1199 					const char *func, int line)
1200 {
1201 	struct wlan_objmgr_peer *peer;
1202 	qdf_list_node_t *psoc_node = NULL;
1203 	qdf_list_node_t *prev_psoc_node = NULL;
1204 	qdf_list_t *obj_list;
1205 
1206 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
1207 	obj_list = &peer_list->peer_hash[hash_index];
1208 
1209 	if (qdf_list_peek_front(obj_list, &psoc_node) != QDF_STATUS_SUCCESS) {
1210 		qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1211 		return NULL;
1212 	}
1213 
1214 	do {
1215 		peer = qdf_container_of(psoc_node, struct wlan_objmgr_peer,
1216 					psoc_peer);
1217 		if (wlan_objmgr_peer_try_get_ref_debug(peer, dbg_id,
1218 						       func, line) ==
1219 				QDF_STATUS_SUCCESS) {
1220 			qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1221 			return peer;
1222 		}
1223 
1224 		prev_psoc_node = psoc_node;
1225 	} while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) ==
1226 						QDF_STATUS_SUCCESS);
1227 
1228 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1229 	return NULL;
1230 }
1231 #else
wlan_psoc_peer_list_peek_active_head(struct wlan_peer_list * peer_list,uint8_t hash_index,wlan_objmgr_ref_dbgid dbg_id)1232 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_active_head(
1233 					struct wlan_peer_list *peer_list,
1234 					uint8_t hash_index,
1235 					wlan_objmgr_ref_dbgid dbg_id)
1236 {
1237 	struct wlan_objmgr_peer *peer;
1238 	qdf_list_node_t *psoc_node = NULL;
1239 	qdf_list_node_t *prev_psoc_node = NULL;
1240 	qdf_list_t *obj_list;
1241 
1242 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
1243 	obj_list = &peer_list->peer_hash[hash_index];
1244 
1245 	if (qdf_list_peek_front(obj_list, &psoc_node) != QDF_STATUS_SUCCESS) {
1246 		qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1247 		return NULL;
1248 	}
1249 
1250 	do {
1251 		peer = qdf_container_of(psoc_node, struct wlan_objmgr_peer,
1252 						psoc_peer);
1253 		if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) ==
1254 				QDF_STATUS_SUCCESS) {
1255 			qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1256 			return peer;
1257 		}
1258 
1259 		prev_psoc_node = psoc_node;
1260 	} while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) ==
1261 						QDF_STATUS_SUCCESS);
1262 
1263 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1264 	return NULL;
1265 }
1266 #endif
1267 
1268 #ifdef WLAN_OBJMGR_REF_ID_TRACE
wlan_psoc_peer_list_peek_head_ref_debug(struct wlan_peer_list * peer_list,uint8_t hash_index,wlan_objmgr_ref_dbgid dbg_id,const char * func,int line)1269 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head_ref_debug(
1270 					struct wlan_peer_list *peer_list,
1271 					uint8_t hash_index,
1272 					wlan_objmgr_ref_dbgid dbg_id,
1273 					const char *func, int line)
1274 {
1275 	struct wlan_objmgr_peer *peer;
1276 	qdf_list_t *obj_list;
1277 
1278 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
1279 	obj_list = &peer_list->peer_hash[hash_index];
1280 
1281 	peer = wlan_psoc_peer_list_peek_head(obj_list);
1282 
1283 	/* This API is invoked by caller, only when caller need to access the
1284 	 * peer object, though object is not in active state, this API should be
1285 	 * used carefully, where multiple object frees are not triggered
1286 	 */
1287 	if (peer)
1288 		wlan_objmgr_peer_get_ref_debug(peer, dbg_id, func, line);
1289 
1290 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1291 
1292 	return peer;
1293 }
1294 #else
wlan_psoc_peer_list_peek_head_ref(struct wlan_peer_list * peer_list,uint8_t hash_index,wlan_objmgr_ref_dbgid dbg_id)1295 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head_ref(
1296 					struct wlan_peer_list *peer_list,
1297 					uint8_t hash_index,
1298 					wlan_objmgr_ref_dbgid dbg_id)
1299 {
1300 	struct wlan_objmgr_peer *peer;
1301 	qdf_list_t *obj_list;
1302 
1303 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
1304 	obj_list = &peer_list->peer_hash[hash_index];
1305 
1306 	peer = wlan_psoc_peer_list_peek_head(obj_list);
1307 
1308 	/* This API is invoked by caller, only when caller need to access the
1309 	 * peer object, though object is not in active state, this API should be
1310 	 * used carefully, where multiple object frees are not triggered
1311 	 */
1312 	if (peer)
1313 		wlan_objmgr_peer_get_ref(peer, dbg_id);
1314 
1315 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1316 
1317 	return peer;
1318 }
1319 #endif
1320 
1321 #ifdef WLAN_OBJMGR_REF_ID_TRACE
wlan_peer_get_next_peer_of_psoc_ref_debug(struct wlan_peer_list * peer_list,uint8_t hash_index,struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid dbg_id,const char * func,int line)1322 struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc_ref_debug(
1323 			struct wlan_peer_list *peer_list, uint8_t hash_index,
1324 			struct wlan_objmgr_peer *peer,
1325 			wlan_objmgr_ref_dbgid dbg_id,
1326 			const char *func, int line)
1327 {
1328 	qdf_list_t *obj_list;
1329 	struct wlan_objmgr_peer *peer_next;
1330 
1331 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
1332 	obj_list = &peer_list->peer_hash[hash_index];
1333 
1334 	peer_next = wlan_peer_get_next_peer_of_psoc(obj_list, peer);
1335 	/* This API is invoked by caller, only when caller need to access the
1336 	 * peer object, though object is not in active state, this API should be
1337 	 * used carefully, where multiple free on object are not triggered
1338 	 */
1339 	if (peer_next)
1340 		wlan_objmgr_peer_get_ref_debug(peer_next, dbg_id, func, line);
1341 
1342 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1343 
1344 	return peer_next;
1345 }
1346 #else
wlan_peer_get_next_peer_of_psoc_ref(struct wlan_peer_list * peer_list,uint8_t hash_index,struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid dbg_id)1347 struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc_ref(
1348 			struct wlan_peer_list *peer_list, uint8_t hash_index,
1349 			struct wlan_objmgr_peer *peer,
1350 			wlan_objmgr_ref_dbgid dbg_id)
1351 {
1352 	qdf_list_t *obj_list;
1353 	struct wlan_objmgr_peer *peer_next;
1354 
1355 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
1356 	obj_list = &peer_list->peer_hash[hash_index];
1357 
1358 	peer_next = wlan_peer_get_next_peer_of_psoc(obj_list, peer);
1359 	/* This API is invoked by caller, only when caller need to access the
1360 	 * peer object, though object is not in active state, this API should be
1361 	 * used carefully, where multiple free on object are not triggered
1362 	 */
1363 	if (peer_next)
1364 		wlan_objmgr_peer_get_ref(peer_next, dbg_id);
1365 
1366 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1367 
1368 	return peer_next;
1369 }
1370 #endif
1371 
1372 #ifdef WLAN_OBJMGR_REF_ID_TRACE
wlan_objmgr_peer_release_ref_debug(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id,const char * func,int line)1373 void wlan_objmgr_peer_release_ref_debug(struct wlan_objmgr_peer *peer,
1374 					wlan_objmgr_ref_dbgid id,
1375 					const char *func, int line)
1376 {
1377 	QDF_STATUS status;
1378 
1379 	if (!peer) {
1380 		obj_mgr_err("peer obj is NULL for %d", id);
1381 		QDF_ASSERT(0);
1382 		return;
1383 	}
1384 
1385 	if (!qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) {
1386 		uint8_t *macaddr;
1387 
1388 		macaddr = wlan_peer_get_macaddr(peer);
1389 		obj_mgr_err("peer("QDF_MAC_ADDR_FMT") ref cnt is 0",
1390 				QDF_MAC_ADDR_REF(macaddr));
1391 		WLAN_OBJMGR_BUG(0);
1392 		return;
1393 	}
1394 
1395 	status = wlan_objmgr_peer_release_debug_id_ref(peer, id);
1396 	if (QDF_IS_STATUS_ERROR(status))
1397 		return;
1398 
1399 	wlan_objmgr_peer_deref_trace(peer, id, func, line);
1400 	/* Provide synchronization from the access to add peer
1401 	 * to logically deleted peer list.
1402 	 */
1403 	wlan_peer_obj_lock(peer);
1404 	/* Decrement ref count, free peer object, if ref count == 0 */
1405 	if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt)) {
1406 		wlan_peer_obj_unlock(peer);
1407 		wlan_objmgr_peer_obj_destroy(peer);
1408 	} else {
1409 		wlan_peer_obj_unlock(peer);
1410 	}
1411 
1412 	return;
1413 }
1414 
1415 qdf_export_symbol(wlan_objmgr_peer_release_ref_debug);
1416 #else
wlan_objmgr_peer_release_ref(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id)1417 void wlan_objmgr_peer_release_ref(struct wlan_objmgr_peer *peer,
1418 				  wlan_objmgr_ref_dbgid id)
1419 {
1420 	QDF_STATUS status;
1421 
1422 	if (!peer) {
1423 		obj_mgr_err("peer obj is NULL for %d", id);
1424 		QDF_ASSERT(0);
1425 		return;
1426 	}
1427 
1428 	if (!qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) {
1429 		uint8_t *macaddr;
1430 
1431 		macaddr = wlan_peer_get_macaddr(peer);
1432 		obj_mgr_err("peer("QDF_MAC_ADDR_FMT") ref cnt is 0",
1433 			    QDF_MAC_ADDR_REF(macaddr));
1434 		WLAN_OBJMGR_BUG(0);
1435 		return;
1436 	}
1437 
1438 	status = wlan_objmgr_peer_release_debug_id_ref(peer, id);
1439 	if (QDF_IS_STATUS_ERROR(status))
1440 		return;
1441 
1442 	/* Provide synchronization from the access to add peer
1443 	 * to logically deleted peer list.
1444 	 */
1445 	wlan_peer_obj_lock(peer);
1446 	/* Decrement ref count, free peer object, if ref count == 0 */
1447 	if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt)) {
1448 		wlan_peer_obj_unlock(peer);
1449 		wlan_objmgr_peer_obj_destroy(peer);
1450 	} else {
1451 		wlan_peer_obj_unlock(peer);
1452 	}
1453 }
1454 
1455 qdf_export_symbol(wlan_objmgr_peer_release_ref);
1456 #endif
1457 
1458 #ifdef WLAN_OBJMGR_REF_ID_DEBUG
1459 void
wlan_objmgr_print_peer_ref_ids(struct wlan_objmgr_peer * peer,QDF_TRACE_LEVEL log_level)1460 wlan_objmgr_print_peer_ref_ids(struct wlan_objmgr_peer *peer,
1461 			       QDF_TRACE_LEVEL log_level)
1462 {
1463 	wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg, log_level);
1464 }
1465 
1466 uint32_t
wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer * peer,enum wlan_umac_comp_id id)1467 wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer *peer,
1468 				  enum wlan_umac_comp_id id)
1469 {
1470 	return qdf_atomic_read(&peer->peer_objmgr.ref_id_dbg[id]);
1471 }
1472 #else
1473 void
wlan_objmgr_print_peer_ref_ids(struct wlan_objmgr_peer * peer,QDF_TRACE_LEVEL log_level)1474 wlan_objmgr_print_peer_ref_ids(struct wlan_objmgr_peer *peer,
1475 			       QDF_TRACE_LEVEL log_level)
1476 {
1477 	uint32_t pending_ref;
1478 
1479 	pending_ref = qdf_atomic_read(&peer->peer_objmgr.ref_cnt);
1480 	obj_mgr_log_level(log_level, "Pending refs -- %d", pending_ref);
1481 }
1482 
1483 uint32_t
wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer * peer,enum wlan_umac_comp_id id)1484 wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer *peer,
1485 				  enum wlan_umac_comp_id id)
1486 {
1487 	return 0;
1488 }
1489 #endif
1490 
1491 #ifdef WLAN_FEATURE_DYNAMIC_MAC_ADDR_UPDATE
wlan_peer_update_macaddr(struct wlan_objmgr_peer * peer,uint8_t * new_macaddr)1492 QDF_STATUS wlan_peer_update_macaddr(struct wlan_objmgr_peer *peer,
1493 				    uint8_t *new_macaddr)
1494 {
1495 	struct wlan_objmgr_psoc *psoc;
1496 	struct wlan_objmgr_vdev *vdev;
1497 	uint8_t *macaddr;
1498 	QDF_STATUS status;
1499 
1500 	if (!peer) {
1501 		obj_mgr_err("PEER is NULL");
1502 		return QDF_STATUS_E_FAILURE;
1503 	}
1504 
1505 	macaddr = wlan_peer_get_macaddr(peer);
1506 
1507 	vdev = wlan_peer_get_vdev(peer);
1508 	if (!vdev) {
1509 		obj_mgr_err("VDEV is NULL for peer(" QDF_MAC_ADDR_FMT ")",
1510 			    QDF_MAC_ADDR_REF(macaddr));
1511 		return QDF_STATUS_E_FAILURE;
1512 	}
1513 
1514 	/* get PSOC from VDEV, if it is NULL, return */
1515 	psoc = wlan_vdev_get_psoc(vdev);
1516 	if (!psoc) {
1517 		obj_mgr_err("PSOC is NULL for peer(" QDF_MAC_ADDR_FMT ")",
1518 			    QDF_MAC_ADDR_REF(macaddr));
1519 		return QDF_STATUS_E_FAILURE;
1520 	}
1521 
1522 	status = wlan_objmgr_psoc_peer_detach(psoc, peer);
1523 	if (QDF_IS_STATUS_ERROR(status)) {
1524 		obj_mgr_err("Failed to detach peer(" QDF_MAC_ADDR_FMT ")",
1525 			    QDF_MAC_ADDR_REF(macaddr));
1526 		return status;
1527 	}
1528 
1529 	wlan_peer_set_macaddr(peer, new_macaddr);
1530 
1531 	status = wlan_objmgr_psoc_peer_attach(psoc, peer);
1532 	if (QDF_IS_STATUS_ERROR(status)) {
1533 		obj_mgr_err("Failed to attach peer(" QDF_MAC_ADDR_FMT ")",
1534 			    QDF_MAC_ADDR_REF(new_macaddr));
1535 		return status;
1536 	}
1537 	return QDF_STATUS_SUCCESS;
1538 }
1539 #endif
1540