xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_peer_obj.c (revision 87a8e4458319c60b618522e263ed900e36aab528)
1 /*
2  * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18  /**
19  * DOC: Public APIs to perform operations on Peer object
20  */
21 #include <wlan_objmgr_cmn.h>
22 #include <wlan_objmgr_global_obj.h>
23 #include <wlan_objmgr_psoc_obj.h>
24 #include <wlan_objmgr_pdev_obj.h>
25 #include <wlan_objmgr_vdev_obj.h>
26 #include <wlan_objmgr_peer_obj.h>
27 #include <qdf_mem.h>
28 #include <qdf_module.h>
29 #include "wlan_objmgr_global_obj_i.h"
30 #include "wlan_objmgr_psoc_obj_i.h"
31 #include "wlan_objmgr_pdev_obj_i.h"
32 #include "wlan_objmgr_vdev_obj_i.h"
33 
34 
35 /**
36  ** APIs to Create/Delete Peer object APIs
37  */
38 static QDF_STATUS wlan_objmgr_peer_object_status(
39 		struct wlan_objmgr_peer *peer)
40 {
41 	uint8_t id;
42 	QDF_STATUS status = QDF_STATUS_SUCCESS;
43 
44 	wlan_peer_obj_lock(peer);
45 	/* Iterate through all components to derive the object status */
46 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
47 		/* If component disabled, Ignore */
48 		if (peer->obj_status[id] == QDF_STATUS_COMP_DISABLED)
49 			continue;
50 		/* If component operates in Async, status is Partially created,
51 			break */
52 		else if (peer->obj_status[id] == QDF_STATUS_COMP_ASYNC) {
53 			if (peer->peer_comp_priv_obj[id] == NULL) {
54 				status = QDF_STATUS_COMP_ASYNC;
55 				break;
56 			}
57 		/* If component failed to allocate its object, treat it as
58 			failure, complete object need to be cleaned up */
59 		} else if ((peer->obj_status[id] == QDF_STATUS_E_NOMEM) ||
60 			(peer->obj_status[id] == QDF_STATUS_E_FAILURE)) {
61 			obj_mgr_err("Peer comp object(id:%d) alloc fail", id);
62 			status = QDF_STATUS_E_FAILURE;
63 			break;
64 		}
65 	}
66 	wlan_peer_obj_unlock(peer);
67 	return status;
68 }
69 
70 static QDF_STATUS wlan_objmgr_peer_obj_free(struct wlan_objmgr_peer *peer)
71 {
72 	struct wlan_objmgr_psoc *psoc;
73 	struct wlan_objmgr_vdev *vdev;
74 	uint8_t *macaddr;
75 	uint8_t vdev_id;
76 
77 	if (peer == NULL) {
78 		obj_mgr_err("PEER is NULL");
79 		return QDF_STATUS_E_FAILURE;
80 	}
81 
82 	macaddr = wlan_peer_get_macaddr(peer);
83 
84 	vdev = wlan_peer_get_vdev(peer);
85 	if (vdev == NULL) {
86 		obj_mgr_err(
87 			"VDEV is NULL for peer(%02x:%02x:%02x:%02x:%02x:%02x)",
88 				macaddr[0], macaddr[1], macaddr[2],
89 				macaddr[3], macaddr[4], macaddr[5]);
90 		return QDF_STATUS_E_FAILURE;
91 	}
92 
93 	vdev_id = wlan_vdev_get_id(vdev);
94 
95 	/* get PSOC from VDEV, if it is NULL, return */
96 	psoc = wlan_vdev_get_psoc(vdev);
97 	if (psoc == NULL) {
98 		obj_mgr_err(
99 			"PSOC is NULL for peer(%02x:%02x:%02x:%02x:%02x:%02x)",
100 				macaddr[0], macaddr[1], macaddr[2],
101 				macaddr[3], macaddr[4], macaddr[5]);
102 		return QDF_STATUS_E_FAILURE;
103 	}
104 
105 	/* Decrement ref count for BSS peer, so that BSS peer deletes last*/
106 	if ((wlan_peer_get_peer_type(peer) == WLAN_PEER_STA) ||
107 	    (wlan_peer_get_peer_type(peer) == WLAN_PEER_STA_TEMP) ||
108 	    (wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_CLI))
109 		wlan_objmgr_peer_release_ref(wlan_vdev_get_bsspeer(vdev),
110 					     WLAN_OBJMGR_ID);
111 
112 	/* Detach peer from VDEV's peer list */
113 	if (wlan_objmgr_vdev_peer_detach(vdev, peer) == QDF_STATUS_E_FAILURE) {
114 		obj_mgr_err(
115 		"Peer(%02x:%02x:%02x:%02x:%02x:%02x) VDEV detach fail, vdev id: %d",
116 			macaddr[0], macaddr[1], macaddr[2],
117 			macaddr[3], macaddr[4], macaddr[5], vdev_id);
118 		return QDF_STATUS_E_FAILURE;
119 	}
120 	/* Detach peer from PSOC's peer list */
121 	if (wlan_objmgr_psoc_peer_detach(psoc, peer) == QDF_STATUS_E_FAILURE) {
122 		obj_mgr_err(
123 		"Peer(%02x:%02x:%02x:%02x:%02x:%02x) PSOC detach failure",
124 			macaddr[0], macaddr[1], macaddr[2],
125 			macaddr[3], macaddr[4], macaddr[5]);
126 		return QDF_STATUS_E_FAILURE;
127 	}
128 	qdf_spinlock_destroy(&peer->peer_lock);
129 	qdf_mem_free(peer);
130 
131 	return QDF_STATUS_SUCCESS;
132 
133 }
134 
135 #ifdef WLAN_OBJMGR_REF_ID_DEBUG
136 static void
137 wlan_objmgr_peer_init_ref_id_debug(struct wlan_objmgr_peer *peer)
138 {
139 	uint8_t id;
140 
141 	for (id = 0; id < WLAN_REF_ID_MAX; id++)
142 		qdf_atomic_init(&peer->peer_objmgr.ref_id_dbg[id]);
143 }
144 #else
145 static inline void
146 wlan_objmgr_peer_init_ref_id_debug(struct wlan_objmgr_peer *peer) {}
147 #endif
148 
149 struct wlan_objmgr_peer *wlan_objmgr_peer_obj_create(
150 			struct wlan_objmgr_vdev *vdev,
151 			enum wlan_peer_type type,
152 			uint8_t *macaddr)
153 {
154 	struct wlan_objmgr_peer *peer;
155 	struct wlan_objmgr_psoc *psoc;
156 	wlan_objmgr_peer_create_handler handler;
157 	wlan_objmgr_peer_status_handler stat_handler;
158 	void *arg;
159 	QDF_STATUS obj_status;
160 	uint8_t id;
161 
162 	if (vdev == NULL) {
163 		obj_mgr_err(
164 			"VDEV is NULL for peer (%02x:%02x:%02x:%02x:%02x:%02x)",
165 				macaddr[0], macaddr[1], macaddr[2],
166 				macaddr[3], macaddr[4], macaddr[5]);
167 		return NULL;
168 	}
169 	/* Get psoc, if psoc is NULL, return */
170 	psoc = wlan_vdev_get_psoc(vdev);
171 	if (psoc == NULL) {
172 		obj_mgr_err(
173 			"PSOC is NULL for peer (%02x:%02x:%02x:%02x:%02x:%02x)",
174 				macaddr[0], macaddr[1], macaddr[2],
175 				macaddr[3], macaddr[4], macaddr[5]);
176 		return NULL;
177 	}
178 	/* Allocate memory for peer object */
179 	peer = qdf_mem_malloc(sizeof(*peer));
180 	if (peer == NULL) {
181 		obj_mgr_err(
182 		"Peer(%02x:%02x:%02x:%02x:%02x:%02x) allocation failure",
183 				macaddr[0], macaddr[1], macaddr[2],
184 				macaddr[3], macaddr[4], macaddr[5]);
185 		return NULL;
186 	}
187 	peer->obj_state = WLAN_OBJ_STATE_ALLOCATED;
188 	qdf_atomic_init(&peer->peer_objmgr.ref_cnt);
189 	wlan_objmgr_peer_init_ref_id_debug(peer);
190 	wlan_objmgr_peer_get_ref(peer, WLAN_OBJMGR_ID);
191 	/* set vdev to peer */
192 	wlan_peer_set_vdev(peer, vdev);
193 	/* set peer type */
194 	wlan_peer_set_peer_type(peer, type);
195 	/* set mac address of peer */
196 	wlan_peer_set_macaddr(peer, macaddr);
197 	/* initialize peer state */
198 	wlan_peer_mlme_set_state(peer, WLAN_INIT_STATE);
199 	wlan_peer_mlme_reset_seq_num(peer);
200 	peer->peer_objmgr.print_cnt = 0;
201 
202 	qdf_spinlock_create(&peer->peer_lock);
203 	/* Attach peer to psoc, psoc maintains the node table for the device */
204 	if (wlan_objmgr_psoc_peer_attach(psoc, peer) !=
205 					QDF_STATUS_SUCCESS) {
206 		obj_mgr_warn(
207 		"Peer(%02x:%02x:%02x:%02x:%02x:%02x) PSOC attach failure",
208 				macaddr[0], macaddr[1], macaddr[2],
209 				macaddr[3], macaddr[4], macaddr[5]);
210 		qdf_spinlock_destroy(&peer->peer_lock);
211 		qdf_mem_free(peer);
212 		return NULL;
213 	}
214 	/* Attach peer to vdev peer table */
215 	if (wlan_objmgr_vdev_peer_attach(vdev, peer) !=
216 					QDF_STATUS_SUCCESS) {
217 		obj_mgr_warn(
218 		"Peer(%02x:%02x:%02x:%02x:%02x:%02x) VDEV attach failure",
219 				macaddr[0], macaddr[1], macaddr[2],
220 				macaddr[3], macaddr[4], macaddr[5]);
221 		/* if attach fails, detach from psoc table before free */
222 		wlan_objmgr_psoc_peer_detach(psoc, peer);
223 		qdf_spinlock_destroy(&peer->peer_lock);
224 		qdf_mem_free(peer);
225 		return NULL;
226 	}
227 	wlan_peer_set_pdev_id(peer, wlan_objmgr_pdev_get_pdev_id(
228 			wlan_vdev_get_pdev(vdev)));
229 	/* Increment ref count for BSS peer, so that BSS peer deletes last*/
230 	if ((type == WLAN_PEER_STA) || (type == WLAN_PEER_STA_TEMP)
231 				    || (type == WLAN_PEER_P2P_CLI))
232 		wlan_objmgr_peer_get_ref(wlan_vdev_get_bsspeer(vdev),
233 					 WLAN_OBJMGR_ID);
234 	/* TODO init other parameters */
235 	/* Invoke registered create handlers */
236 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
237 		handler = g_umac_glb_obj->peer_create_handler[id];
238 		arg = g_umac_glb_obj->peer_create_handler_arg[id];
239 		if (handler != NULL)
240 			peer->obj_status[id] = handler(peer, arg);
241 		else
242 			peer->obj_status[id] = QDF_STATUS_COMP_DISABLED;
243 	}
244 	/* derive the object status */
245 	obj_status = wlan_objmgr_peer_object_status(peer);
246 	/* If SUCCESS, Object is created */
247 	if (obj_status == QDF_STATUS_SUCCESS) {
248 		peer->obj_state = WLAN_OBJ_STATE_CREATED;
249 		for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
250 			stat_handler = g_umac_glb_obj->peer_status_handler[id];
251 			arg = g_umac_glb_obj->peer_status_handler_arg[id];
252 			if (stat_handler != NULL)
253 				stat_handler(peer, arg,
254 					     QDF_STATUS_SUCCESS);
255 		}
256 	} else if (obj_status == QDF_STATUS_COMP_ASYNC) {
257 		/* If any component operates in different context, update it
258 		as partially created */
259 		peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED;
260 	} else if (obj_status == QDF_STATUS_E_FAILURE) {
261 		/* Clean up the peer */
262 		obj_mgr_err(
263 		"Peer(%02x:%02x:%02x:%02x:%02x:%02x) comp object alloc fail",
264 				macaddr[0], macaddr[1], macaddr[2],
265 				macaddr[3], macaddr[4], macaddr[5]);
266 		wlan_objmgr_peer_obj_delete(peer);
267 		return NULL;
268 	}
269 
270 	obj_mgr_debug("Created peer " QDF_MAC_ADDR_STR,
271 		      QDF_MAC_ADDR_ARRAY(macaddr));
272 
273 	return peer;
274 }
275 
276 static QDF_STATUS wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer *peer)
277 {
278 	uint8_t id;
279 	wlan_objmgr_peer_destroy_handler handler;
280 	QDF_STATUS obj_status;
281 	void *arg;
282 	uint8_t *macaddr;
283 
284 	if (peer == NULL) {
285 		obj_mgr_err("PEER is NULL");
286 		return QDF_STATUS_E_FAILURE;
287 	}
288 	wlan_objmgr_notify_destroy(peer, WLAN_PEER_OP);
289 
290 	macaddr = wlan_peer_get_macaddr(peer);
291 
292 	obj_mgr_debug("Physically deleting peer " QDF_MAC_ADDR_STR,
293 		      QDF_MAC_ADDR_ARRAY(macaddr));
294 
295 	if (peer->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) {
296 		obj_mgr_err("PEER object del is not invoked obj_state:%d peer "
297 			    QDF_MAC_ADDR_STR, peer->obj_state,
298 			    QDF_MAC_ADDR_ARRAY(macaddr));
299 		WLAN_OBJMGR_BUG(0);
300 	}
301 
302 	/* Invoke registered destroy handlers */
303 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
304 		handler = g_umac_glb_obj->peer_destroy_handler[id];
305 		arg = g_umac_glb_obj->peer_destroy_handler_arg[id];
306 		if (handler != NULL)
307 			peer->obj_status[id] = handler(peer, arg);
308 		else
309 			peer->obj_status[id] = QDF_STATUS_COMP_DISABLED;
310 	}
311 	/* Derive the object status */
312 	obj_status = wlan_objmgr_peer_object_status(peer);
313 	if (obj_status == QDF_STATUS_E_FAILURE) {
314 		/* If it status is failure, memory will not be freed */
315 		QDF_BUG(0);
316 		return QDF_STATUS_E_FAILURE;
317 	}
318 	/* few components deletion is in progress */
319 	if (obj_status == QDF_STATUS_COMP_ASYNC) {
320 		peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED;
321 		return QDF_STATUS_COMP_ASYNC;
322 	}
323 
324 	/* Free the peer object */
325 	return wlan_objmgr_peer_obj_free(peer);
326 }
327 
328 QDF_STATUS wlan_objmgr_peer_obj_delete(struct wlan_objmgr_peer *peer)
329 {
330 	uint8_t print_idx;
331 	uint8_t *macaddr;
332 
333 	if (peer == NULL) {
334 		obj_mgr_err("PEER is NULL");
335 		return QDF_STATUS_E_FAILURE;
336 	}
337 
338 	wlan_peer_obj_lock(peer);
339 	macaddr = wlan_peer_get_macaddr(peer);
340 	wlan_peer_obj_unlock(peer);
341 
342 	obj_mgr_debug("Logically deleting peer " QDF_MAC_ADDR_STR,
343 		      QDF_MAC_ADDR_ARRAY(macaddr));
344 
345 	print_idx = qdf_get_pidx();
346 	wlan_objmgr_print_peer_ref_ids(peer, QDF_TRACE_LEVEL_DEBUG);
347 	/**
348 	 * Update VDEV object state to LOGICALLY DELETED
349 	 * It prevents further access of this object
350 	 */
351 	wlan_peer_obj_lock(peer);
352 	peer->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED;
353 	wlan_peer_obj_unlock(peer);
354 	wlan_objmgr_notify_log_delete(peer, WLAN_PEER_OP);
355 	wlan_objmgr_peer_release_ref(peer, WLAN_OBJMGR_ID);
356 
357 	return QDF_STATUS_SUCCESS;
358 }
359 qdf_export_symbol(wlan_objmgr_peer_obj_delete);
360 /**
361  ** APIs to attach/detach component objects
362  */
363 QDF_STATUS wlan_objmgr_peer_component_obj_attach(
364 		struct wlan_objmgr_peer *peer,
365 		enum wlan_umac_comp_id id,
366 		void *comp_priv_obj,
367 		QDF_STATUS status)
368 {
369 	wlan_objmgr_peer_status_handler s_hler;
370 	void *arg;
371 	uint8_t i;
372 	QDF_STATUS obj_status;
373 
374 	/* component id is invalid */
375 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
376 		return QDF_STATUS_MAXCOMP_FAIL;
377 
378 	wlan_peer_obj_lock(peer);
379 	/* If there is a valid entry, return failure,
380 	valid object needs to be freed first */
381 	if (peer->peer_comp_priv_obj[id] != NULL) {
382 		wlan_peer_obj_unlock(peer);
383 		return QDF_STATUS_E_FAILURE;
384 	}
385 	/* Assign component object private pointer(can be NULL also), status */
386 	peer->peer_comp_priv_obj[id] = comp_priv_obj;
387 	peer->obj_status[id] = status;
388 	wlan_peer_obj_unlock(peer);
389 
390 	if (peer->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED)
391 		return QDF_STATUS_SUCCESS;
392 
393 	/* If PEER object status is partially created means, this API is
394 	invoked with differnt context. this block should be executed for async
395 	components only */
396 	/* Derive status */
397 	obj_status = wlan_objmgr_peer_object_status(peer);
398 	/* STATUS_SUCCESS means, object is CREATED */
399 	if (obj_status == QDF_STATUS_SUCCESS)
400 		peer->obj_state = WLAN_OBJ_STATE_CREATED;
401 	/* update state as CREATION failed, caller has to delete the
402 	PEER object */
403 	else if (obj_status == QDF_STATUS_E_FAILURE)
404 		peer->obj_state = WLAN_OBJ_STATE_CREATION_FAILED;
405 	/* Notify components about the CREATION success/failure */
406 	if ((obj_status == QDF_STATUS_SUCCESS) ||
407 	    (obj_status == QDF_STATUS_E_FAILURE)) {
408 		/* nofity object status */
409 		for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) {
410 			s_hler = g_umac_glb_obj->peer_status_handler[i];
411 			arg = g_umac_glb_obj->peer_status_handler_arg[i];
412 			if (s_hler != NULL)
413 				s_hler(peer, arg, obj_status);
414 		}
415 	}
416 	return QDF_STATUS_SUCCESS;
417 }
418 
419 QDF_STATUS wlan_objmgr_peer_component_obj_detach(
420 		struct wlan_objmgr_peer *peer,
421 		enum wlan_umac_comp_id id,
422 		void *comp_priv_obj)
423 {
424 	QDF_STATUS obj_status;
425 
426 	/* component id is invalid */
427 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
428 		return QDF_STATUS_MAXCOMP_FAIL;
429 
430 	wlan_peer_obj_lock(peer);
431 	/* If there is a invalid entry, return failure */
432 	if (peer->peer_comp_priv_obj[id] != comp_priv_obj) {
433 		peer->obj_status[id] = QDF_STATUS_E_FAILURE;
434 		wlan_peer_obj_unlock(peer);
435 		return QDF_STATUS_E_FAILURE;
436 	}
437 	/* Reset the pointer to NULL */
438 	peer->peer_comp_priv_obj[id] = NULL;
439 	peer->obj_status[id] = QDF_STATUS_SUCCESS;
440 	wlan_peer_obj_unlock(peer);
441 
442 	/* If PEER object status is partially destroyed means, this API is
443 	invoked with differnt context, this block should be executed for async
444 	components only */
445 	if ((peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) ||
446 	    (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) {
447 		/* Derive object status */
448 		obj_status = wlan_objmgr_peer_object_status(peer);
449 		if (obj_status == QDF_STATUS_SUCCESS) {
450 			/*Update the status as Deleted, if full object
451 				deletion is in progress */
452 			if (peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED)
453 				peer->obj_state = WLAN_OBJ_STATE_DELETED;
454 			/* Move to creation state, since this component
455 			deletion alone requested */
456 			if (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
457 				peer->obj_state = WLAN_OBJ_STATE_CREATED;
458 		/* Object status is failure */
459 		} else if (obj_status == QDF_STATUS_E_FAILURE) {
460 			/*Update the status as Deletion failed, if full object
461 				deletion is in progress */
462 			if (peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED)
463 				peer->obj_state =
464 					WLAN_OBJ_STATE_DELETION_FAILED;
465 			/* Move to creation state, since this component
466 			deletion alone requested (do not block other
467 			components) */
468 			if (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
469 				peer->obj_state = WLAN_OBJ_STATE_CREATED;
470 		}
471 
472 			/* Delete peer object */
473 		if ((obj_status == QDF_STATUS_SUCCESS)  &&
474 		    (peer->obj_state == WLAN_OBJ_STATE_DELETED)) {
475 			/* Free the peer object */
476 			return wlan_objmgr_peer_obj_free(peer);
477 		}
478 	}
479 
480 	return QDF_STATUS_SUCCESS;
481 }
482 
483 
484 QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_creation(
485 		struct wlan_objmgr_peer *peer,
486 		enum wlan_umac_comp_id id)
487 {
488 	wlan_objmgr_peer_create_handler handler;
489 	void *arg;
490 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
491 
492 	/* Component id is invalid */
493 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
494 		return QDF_STATUS_MAXCOMP_FAIL;
495 
496 	wlan_peer_obj_lock(peer);
497 	/* If component object is already created, delete old
498 		component object, then invoke creation */
499 	if (peer->peer_comp_priv_obj[id] != NULL) {
500 		wlan_peer_obj_unlock(peer);
501 		return QDF_STATUS_E_FAILURE;
502 	}
503 	wlan_peer_obj_unlock(peer);
504 
505 	/* Invoke registered create handlers */
506 	handler = g_umac_glb_obj->peer_create_handler[id];
507 	arg = g_umac_glb_obj->peer_create_handler_arg[id];
508 	if (handler != NULL)
509 		peer->obj_status[id] = handler(peer, arg);
510 	else
511 		return QDF_STATUS_E_FAILURE;
512 
513 	/* If object status is created, then only handle this object status */
514 	if (peer->obj_state == WLAN_OBJ_STATE_CREATED) {
515 		/* Derive object status */
516 		obj_status = wlan_objmgr_peer_object_status(peer);
517 		/* Move PDEV object state to Partially created state */
518 		if (obj_status == QDF_STATUS_COMP_ASYNC) {
519 			/*TODO atomic */
520 			peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED;
521 		}
522 	}
523 
524 	return obj_status;
525 }
526 
527 
528 QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_deletion(
529 		struct wlan_objmgr_peer *peer,
530 		enum wlan_umac_comp_id id)
531 {
532 	wlan_objmgr_peer_destroy_handler handler;
533 	void *arg;
534 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
535 
536 	/* component id is invalid */
537 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
538 		return QDF_STATUS_MAXCOMP_FAIL;
539 
540 	wlan_peer_obj_lock(peer);
541 	/* Component object was never created, invalid operation */
542 	if (peer->peer_comp_priv_obj[id] == NULL) {
543 		wlan_peer_obj_unlock(peer);
544 		return QDF_STATUS_E_FAILURE;
545 	}
546 
547 	wlan_peer_obj_unlock(peer);
548 
549 	/* Invoke registered destroy handlers */
550 	handler = g_umac_glb_obj->peer_destroy_handler[id];
551 	arg = g_umac_glb_obj->peer_destroy_handler_arg[id];
552 	if (handler != NULL)
553 		peer->obj_status[id] = handler(peer, arg);
554 	else
555 		return QDF_STATUS_E_FAILURE;
556 
557 	/* If object status is created, then only handle this object status */
558 	if (peer->obj_state == WLAN_OBJ_STATE_CREATED) {
559 		obj_status = wlan_objmgr_peer_object_status(peer);
560 			/* move object state to DEL progress */
561 		if (obj_status == QDF_STATUS_COMP_ASYNC)
562 			peer->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS;
563 	}
564 	return obj_status;
565 }
566 
567 void *wlan_objmgr_peer_get_comp_private_obj(
568 		struct wlan_objmgr_peer *peer,
569 		enum wlan_umac_comp_id id)
570 {
571 	void *comp_priv_obj;
572 
573 	/* component id is invalid */
574 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
575 		QDF_BUG(0);
576 		return NULL;
577 	}
578 
579 	if (peer == NULL) {
580 		QDF_BUG(0);
581 		return NULL;
582 	}
583 
584 	comp_priv_obj = peer->peer_comp_priv_obj[id];
585 	return comp_priv_obj;
586 }
587 qdf_export_symbol(wlan_objmgr_peer_get_comp_private_obj);
588 
589 #ifdef WLAN_OBJMGR_REF_ID_DEBUG
590 static inline void
591 wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer *peer,
592 				  wlan_objmgr_ref_dbgid id)
593 {
594 	qdf_atomic_inc(&peer->peer_objmgr.ref_id_dbg[id]);
595 }
596 #else
597 static inline void
598 wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer *peer,
599 				  wlan_objmgr_ref_dbgid id) {}
600 #endif
601 
602 void wlan_objmgr_peer_get_ref(struct wlan_objmgr_peer *peer,
603 			      wlan_objmgr_ref_dbgid id)
604 {
605 	if (peer == NULL) {
606 		obj_mgr_err("peer obj is NULL for %d", id);
607 		QDF_ASSERT(0);
608 		return;
609 	}
610 	/* Increment ref count */
611 	qdf_atomic_inc(&peer->peer_objmgr.ref_cnt);
612 	wlan_objmgr_peer_get_debug_id_ref(peer, id);
613 
614 	return;
615 }
616 qdf_export_symbol(wlan_objmgr_peer_get_ref);
617 
618 QDF_STATUS wlan_objmgr_peer_try_get_ref(struct wlan_objmgr_peer *peer,
619 						 wlan_objmgr_ref_dbgid id)
620 {
621 
622 	uint8_t *macaddr;
623 
624 	if (peer == NULL) {
625 		obj_mgr_err("peer obj is NULL for %d", id);
626 		QDF_ASSERT(0);
627 		return QDF_STATUS_E_FAILURE;
628 	}
629 
630 	wlan_peer_obj_lock(peer);
631 	macaddr = wlan_peer_get_macaddr(peer);
632 	if (peer->obj_state != WLAN_OBJ_STATE_CREATED) {
633 		wlan_peer_obj_unlock(peer);
634 		if (peer->peer_objmgr.print_cnt++ <=
635 				WLAN_OBJMGR_RATELIMIT_THRESH)
636 			obj_mgr_warn(
637 			"peer(" QDF_MAC_ADDR_STR ") not in Created st(%d)",
638 			QDF_MAC_ADDR_ARRAY(macaddr),
639 				peer->obj_state);
640 		return QDF_STATUS_E_RESOURCES;
641 	}
642 
643 	wlan_objmgr_peer_get_ref(peer, id);
644 	wlan_peer_obj_unlock(peer);
645 
646 	return QDF_STATUS_SUCCESS;
647 }
648 qdf_export_symbol(wlan_objmgr_peer_try_get_ref);
649 
650 #ifdef WLAN_OBJMGR_REF_ID_DEBUG
651 static void
652 wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer *peer,
653 				      wlan_objmgr_ref_dbgid id)
654 {
655 	uint8_t *macaddr;
656 
657 	macaddr = wlan_peer_get_macaddr(peer);
658 	if (!qdf_atomic_read(&peer->peer_objmgr.ref_id_dbg[id])) {
659 		obj_mgr_err(
660 		"peer(%02x:%02x:%02x:%02x:%02x:%02x) ref was not taken by %d",
661 			macaddr[0], macaddr[1], macaddr[2],
662 			macaddr[3], macaddr[4], macaddr[5], id);
663 		wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg,
664 					  QDF_TRACE_LEVEL_FATAL);
665 		WLAN_OBJMGR_BUG(0);
666 	}
667 
668 	qdf_atomic_dec(&peer->peer_objmgr.ref_id_dbg[id]);
669 }
670 #else
671 static inline void
672 wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer *peer,
673 				      wlan_objmgr_ref_dbgid id) {}
674 #endif
675 
676 void wlan_objmgr_peer_release_ref(struct wlan_objmgr_peer *peer,
677 				  wlan_objmgr_ref_dbgid id)
678 {
679 	uint8_t *macaddr;
680 
681 	if (!peer) {
682 		obj_mgr_err("peer obj is NULL for %d", id);
683 		QDF_ASSERT(0);
684 		return;
685 	}
686 
687 	macaddr = wlan_peer_get_macaddr(peer);
688 
689 	if (!qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) {
690 		obj_mgr_err("peer(%02x:%02x:%02x:%02x:%02x:%02x) ref cnt is 0",
691 				macaddr[0], macaddr[1], macaddr[2],
692 				macaddr[3], macaddr[4], macaddr[5]);
693 		WLAN_OBJMGR_BUG(0);
694 		return;
695 	}
696 	wlan_objmgr_peer_release_debug_id_ref(peer, id);
697 
698 	/* Provide synchronization from the access to add peer
699 	 * to logically deleted peer list.
700 	 */
701 	wlan_peer_obj_lock(peer);
702 	/* Decrement ref count, free peer object, if ref count == 0 */
703 	if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt)) {
704 		wlan_peer_obj_unlock(peer);
705 		wlan_objmgr_peer_obj_destroy(peer);
706 	} else {
707 		wlan_peer_obj_unlock(peer);
708 	}
709 
710 	return;
711 }
712 qdf_export_symbol(wlan_objmgr_peer_release_ref);
713 
714 struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_active_head(
715 				struct wlan_objmgr_vdev *vdev,
716 				qdf_list_t *peer_list,
717 				wlan_objmgr_ref_dbgid dbg_id)
718 {
719 	struct wlan_objmgr_peer *peer;
720 	qdf_list_node_t *vdev_node = NULL;
721 	qdf_list_node_t *prev_vdev_node = NULL;
722 
723 	wlan_vdev_obj_lock(vdev);
724 
725 	if (qdf_list_peek_front(peer_list, &vdev_node) != QDF_STATUS_SUCCESS) {
726 		wlan_vdev_obj_unlock(vdev);
727 		return NULL;
728 	}
729 
730 	do {
731 		peer = qdf_container_of(vdev_node, struct wlan_objmgr_peer,
732 						vdev_peer);
733 
734 		if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) ==
735 				QDF_STATUS_SUCCESS) {
736 			wlan_vdev_obj_unlock(vdev);
737 			return peer;
738 		}
739 
740 		prev_vdev_node = vdev_node;
741 	} while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) ==
742 							QDF_STATUS_SUCCESS);
743 
744 	wlan_vdev_obj_unlock(vdev);
745 
746 	return NULL;
747 }
748 
749 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_vdev(
750 					struct wlan_objmgr_vdev *vdev,
751 					qdf_list_t *peer_list,
752 					struct wlan_objmgr_peer *peer,
753 					wlan_objmgr_ref_dbgid dbg_id)
754 {
755 	struct wlan_objmgr_peer *peer_next;
756 	qdf_list_node_t *vdev_node = NULL;
757 	qdf_list_node_t *prev_vdev_node = NULL;
758 
759 	if (peer == NULL)
760 		return NULL;
761 
762 	wlan_vdev_obj_lock(vdev);
763 
764 	prev_vdev_node = &peer->vdev_peer;
765 	while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) ==
766 						QDF_STATUS_SUCCESS) {
767 		peer_next = qdf_container_of(vdev_node, struct wlan_objmgr_peer,
768 					vdev_peer);
769 
770 		if (wlan_objmgr_peer_try_get_ref(peer_next, dbg_id) ==
771 				QDF_STATUS_SUCCESS) {
772 			wlan_vdev_obj_unlock(vdev);
773 			return peer_next;
774 		}
775 
776 		prev_vdev_node = vdev_node;
777 	}
778 
779 	wlan_vdev_obj_unlock(vdev);
780 
781 	return NULL;
782 }
783 
784 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_psoc(
785 					struct wlan_peer_list *peer_list,
786 					uint8_t hash_index,
787 					struct wlan_objmgr_peer *peer,
788 					wlan_objmgr_ref_dbgid dbg_id)
789 {
790 	struct wlan_objmgr_peer *peer_next = NULL;
791 	qdf_list_node_t *psoc_node = NULL;
792 	qdf_list_node_t *prev_psoc_node = NULL;
793 	qdf_list_t *obj_list;
794 
795 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
796 	obj_list = &peer_list->peer_hash[hash_index];
797 
798 	prev_psoc_node = &peer->psoc_peer;
799 	while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) ==
800 						QDF_STATUS_SUCCESS) {
801 		peer_next = qdf_container_of(psoc_node, struct wlan_objmgr_peer,
802 						psoc_peer);
803 
804 		if (wlan_objmgr_peer_try_get_ref(peer_next, dbg_id) ==
805 				QDF_STATUS_SUCCESS) {
806 			qdf_spin_unlock_bh(&peer_list->peer_list_lock);
807 			return peer_next;
808 		}
809 
810 		prev_psoc_node = psoc_node;
811 	}
812 
813 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
814 
815 	return NULL;
816 }
817 
818 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_active_head(
819 					struct wlan_peer_list *peer_list,
820 					uint8_t hash_index,
821 					wlan_objmgr_ref_dbgid dbg_id)
822 {
823 	struct wlan_objmgr_peer *peer;
824 	qdf_list_node_t *psoc_node = NULL;
825 	qdf_list_node_t *prev_psoc_node = NULL;
826 	qdf_list_t *obj_list;
827 
828 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
829 	obj_list = &peer_list->peer_hash[hash_index];
830 
831 	if (qdf_list_peek_front(obj_list, &psoc_node) != QDF_STATUS_SUCCESS) {
832 		qdf_spin_unlock_bh(&peer_list->peer_list_lock);
833 		return NULL;
834 	}
835 
836 	do {
837 		peer = qdf_container_of(psoc_node, struct wlan_objmgr_peer,
838 						psoc_peer);
839 		if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) ==
840 				QDF_STATUS_SUCCESS) {
841 			qdf_spin_unlock_bh(&peer_list->peer_list_lock);
842 			return peer;
843 		}
844 
845 		prev_psoc_node = psoc_node;
846 	} while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) ==
847 						QDF_STATUS_SUCCESS);
848 
849 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
850 	return NULL;
851 }
852 
853 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head_ref(
854 					struct wlan_peer_list *peer_list,
855 					uint8_t hash_index,
856 					wlan_objmgr_ref_dbgid dbg_id)
857 {
858 	struct wlan_objmgr_peer *peer;
859 	qdf_list_t *obj_list;
860 
861 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
862 	obj_list = &peer_list->peer_hash[hash_index];
863 
864 	peer = wlan_psoc_peer_list_peek_head(obj_list);
865 
866 	/**
867 	 * This API is invoked by caller, only when caller need to access the
868 	 * peer object, though object is not in active state, this API should be
869 	 * used carefully, where multiple object frees are not triggered
870 	 */
871 	if (peer)
872 		wlan_objmgr_peer_get_ref(peer, dbg_id);
873 
874 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
875 
876 	return peer;
877 }
878 
879 struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc_ref(
880 			struct wlan_peer_list *peer_list, uint8_t hash_index,
881 			struct wlan_objmgr_peer *peer,
882 			wlan_objmgr_ref_dbgid dbg_id)
883 {
884 	qdf_list_t *obj_list;
885 	struct wlan_objmgr_peer *peer_next;
886 
887 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
888 	obj_list = &peer_list->peer_hash[hash_index];
889 
890 	peer_next = wlan_peer_get_next_peer_of_psoc(obj_list, peer);
891 	/**
892 	 * This API is invoked by caller, only when caller need to access the
893 	 * peer object, though object is not in active state, this API should be
894 	 * used carefully, where multiple free on object are not triggered
895 	 */
896 	if (peer_next)
897 		wlan_objmgr_peer_get_ref(peer_next, dbg_id);
898 
899 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
900 
901 	return peer_next;
902 }
903 
904 #ifdef WLAN_OBJMGR_REF_ID_DEBUG
905 void
906 wlan_objmgr_print_peer_ref_ids(struct wlan_objmgr_peer *peer,
907 			       QDF_TRACE_LEVEL log_level)
908 {
909 	wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg, log_level);
910 }
911 
912 uint32_t
913 wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer *peer,
914 				  enum wlan_umac_comp_id id)
915 {
916 	return qdf_atomic_read(&peer->peer_objmgr.ref_id_dbg[id]);
917 }
918 #else
919 void
920 wlan_objmgr_print_peer_ref_ids(struct wlan_objmgr_peer *peer,
921 			       QDF_TRACE_LEVEL log_level)
922 {
923 	uint32_t pending_ref;
924 
925 	pending_ref = qdf_atomic_read(&peer->peer_objmgr.ref_cnt);
926 	obj_mgr_log_level(log_level, "Pending refs -- %d", pending_ref);
927 }
928 
929 uint32_t
930 wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer *peer,
931 				  enum wlan_umac_comp_id id)
932 {
933 	return 0;
934 }
935 #endif
936