xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_peer_obj.c (revision 1f55ed1a9f5050d8da228aa8dd3fff7c0242aa71)
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 &&
307 		    (peer->obj_status[id] == QDF_STATUS_SUCCESS ||
308 		     peer->obj_status[id] == QDF_STATUS_COMP_ASYNC))
309 			peer->obj_status[id] = handler(peer, arg);
310 		else
311 			peer->obj_status[id] = QDF_STATUS_COMP_DISABLED;
312 	}
313 	/* Derive the object status */
314 	obj_status = wlan_objmgr_peer_object_status(peer);
315 	if (obj_status == QDF_STATUS_E_FAILURE) {
316 		/* If it status is failure, memory will not be freed */
317 		QDF_BUG(0);
318 		return QDF_STATUS_E_FAILURE;
319 	}
320 	/* few components deletion is in progress */
321 	if (obj_status == QDF_STATUS_COMP_ASYNC) {
322 		peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED;
323 		return QDF_STATUS_COMP_ASYNC;
324 	}
325 
326 	/* Free the peer object */
327 	return wlan_objmgr_peer_obj_free(peer);
328 }
329 
330 QDF_STATUS wlan_objmgr_peer_obj_delete(struct wlan_objmgr_peer *peer)
331 {
332 	uint8_t print_idx;
333 	uint8_t *macaddr;
334 
335 	if (peer == NULL) {
336 		obj_mgr_err("PEER is NULL");
337 		return QDF_STATUS_E_FAILURE;
338 	}
339 
340 	wlan_peer_obj_lock(peer);
341 	macaddr = wlan_peer_get_macaddr(peer);
342 	wlan_peer_obj_unlock(peer);
343 
344 	obj_mgr_debug("Logically deleting peer " QDF_MAC_ADDR_STR,
345 		      QDF_MAC_ADDR_ARRAY(macaddr));
346 
347 	print_idx = qdf_get_pidx();
348 	wlan_objmgr_print_peer_ref_ids(peer, QDF_TRACE_LEVEL_DEBUG);
349 	/**
350 	 * Update VDEV object state to LOGICALLY DELETED
351 	 * It prevents further access of this object
352 	 */
353 	wlan_peer_obj_lock(peer);
354 	peer->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED;
355 	wlan_peer_obj_unlock(peer);
356 	wlan_objmgr_notify_log_delete(peer, WLAN_PEER_OP);
357 	wlan_objmgr_peer_release_ref(peer, WLAN_OBJMGR_ID);
358 
359 	return QDF_STATUS_SUCCESS;
360 }
361 qdf_export_symbol(wlan_objmgr_peer_obj_delete);
362 /**
363  ** APIs to attach/detach component objects
364  */
365 QDF_STATUS wlan_objmgr_peer_component_obj_attach(
366 		struct wlan_objmgr_peer *peer,
367 		enum wlan_umac_comp_id id,
368 		void *comp_priv_obj,
369 		QDF_STATUS status)
370 {
371 	wlan_objmgr_peer_status_handler s_hler;
372 	void *arg;
373 	uint8_t i;
374 	QDF_STATUS obj_status;
375 
376 	/* component id is invalid */
377 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
378 		return QDF_STATUS_MAXCOMP_FAIL;
379 
380 	wlan_peer_obj_lock(peer);
381 	/* If there is a valid entry, return failure,
382 	valid object needs to be freed first */
383 	if (peer->peer_comp_priv_obj[id] != NULL) {
384 		wlan_peer_obj_unlock(peer);
385 		return QDF_STATUS_E_FAILURE;
386 	}
387 	/* Assign component object private pointer(can be NULL also), status */
388 	peer->peer_comp_priv_obj[id] = comp_priv_obj;
389 	peer->obj_status[id] = status;
390 	wlan_peer_obj_unlock(peer);
391 
392 	if (peer->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED)
393 		return QDF_STATUS_SUCCESS;
394 
395 	/* If PEER object status is partially created means, this API is
396 	invoked with differnt context. this block should be executed for async
397 	components only */
398 	/* Derive status */
399 	obj_status = wlan_objmgr_peer_object_status(peer);
400 	/* STATUS_SUCCESS means, object is CREATED */
401 	if (obj_status == QDF_STATUS_SUCCESS)
402 		peer->obj_state = WLAN_OBJ_STATE_CREATED;
403 	/* update state as CREATION failed, caller has to delete the
404 	PEER object */
405 	else if (obj_status == QDF_STATUS_E_FAILURE)
406 		peer->obj_state = WLAN_OBJ_STATE_CREATION_FAILED;
407 	/* Notify components about the CREATION success/failure */
408 	if ((obj_status == QDF_STATUS_SUCCESS) ||
409 	    (obj_status == QDF_STATUS_E_FAILURE)) {
410 		/* nofity object status */
411 		for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) {
412 			s_hler = g_umac_glb_obj->peer_status_handler[i];
413 			arg = g_umac_glb_obj->peer_status_handler_arg[i];
414 			if (s_hler != NULL)
415 				s_hler(peer, arg, obj_status);
416 		}
417 	}
418 	return QDF_STATUS_SUCCESS;
419 }
420 
421 QDF_STATUS wlan_objmgr_peer_component_obj_detach(
422 		struct wlan_objmgr_peer *peer,
423 		enum wlan_umac_comp_id id,
424 		void *comp_priv_obj)
425 {
426 	QDF_STATUS obj_status;
427 
428 	/* component id is invalid */
429 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
430 		return QDF_STATUS_MAXCOMP_FAIL;
431 
432 	wlan_peer_obj_lock(peer);
433 	/* If there is a invalid entry, return failure */
434 	if (peer->peer_comp_priv_obj[id] != comp_priv_obj) {
435 		peer->obj_status[id] = QDF_STATUS_E_FAILURE;
436 		wlan_peer_obj_unlock(peer);
437 		return QDF_STATUS_E_FAILURE;
438 	}
439 	/* Reset the pointer to NULL */
440 	peer->peer_comp_priv_obj[id] = NULL;
441 	peer->obj_status[id] = QDF_STATUS_SUCCESS;
442 	wlan_peer_obj_unlock(peer);
443 
444 	/* If PEER object status is partially destroyed means, this API is
445 	invoked with differnt context, this block should be executed for async
446 	components only */
447 	if ((peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) ||
448 	    (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) {
449 		/* Derive object status */
450 		obj_status = wlan_objmgr_peer_object_status(peer);
451 		if (obj_status == QDF_STATUS_SUCCESS) {
452 			/*Update the status as Deleted, if full object
453 				deletion is in progress */
454 			if (peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED)
455 				peer->obj_state = WLAN_OBJ_STATE_DELETED;
456 			/* Move to creation state, since this component
457 			deletion alone requested */
458 			if (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
459 				peer->obj_state = WLAN_OBJ_STATE_CREATED;
460 		/* Object status is failure */
461 		} else if (obj_status == QDF_STATUS_E_FAILURE) {
462 			/*Update the status as Deletion failed, if full object
463 				deletion is in progress */
464 			if (peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED)
465 				peer->obj_state =
466 					WLAN_OBJ_STATE_DELETION_FAILED;
467 			/* Move to creation state, since this component
468 			deletion alone requested (do not block other
469 			components) */
470 			if (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
471 				peer->obj_state = WLAN_OBJ_STATE_CREATED;
472 		}
473 
474 			/* Delete peer object */
475 		if ((obj_status == QDF_STATUS_SUCCESS)  &&
476 		    (peer->obj_state == WLAN_OBJ_STATE_DELETED)) {
477 			/* Free the peer object */
478 			return wlan_objmgr_peer_obj_free(peer);
479 		}
480 	}
481 
482 	return QDF_STATUS_SUCCESS;
483 }
484 
485 
486 QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_creation(
487 		struct wlan_objmgr_peer *peer,
488 		enum wlan_umac_comp_id id)
489 {
490 	wlan_objmgr_peer_create_handler handler;
491 	void *arg;
492 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
493 
494 	/* Component id is invalid */
495 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
496 		return QDF_STATUS_MAXCOMP_FAIL;
497 
498 	wlan_peer_obj_lock(peer);
499 	/* If component object is already created, delete old
500 		component object, then invoke creation */
501 	if (peer->peer_comp_priv_obj[id] != NULL) {
502 		wlan_peer_obj_unlock(peer);
503 		return QDF_STATUS_E_FAILURE;
504 	}
505 	wlan_peer_obj_unlock(peer);
506 
507 	/* Invoke registered create handlers */
508 	handler = g_umac_glb_obj->peer_create_handler[id];
509 	arg = g_umac_glb_obj->peer_create_handler_arg[id];
510 	if (handler != NULL)
511 		peer->obj_status[id] = handler(peer, arg);
512 	else
513 		return QDF_STATUS_E_FAILURE;
514 
515 	/* If object status is created, then only handle this object status */
516 	if (peer->obj_state == WLAN_OBJ_STATE_CREATED) {
517 		/* Derive object status */
518 		obj_status = wlan_objmgr_peer_object_status(peer);
519 		/* Move PDEV object state to Partially created state */
520 		if (obj_status == QDF_STATUS_COMP_ASYNC) {
521 			/*TODO atomic */
522 			peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED;
523 		}
524 	}
525 
526 	return obj_status;
527 }
528 
529 
530 QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_deletion(
531 		struct wlan_objmgr_peer *peer,
532 		enum wlan_umac_comp_id id)
533 {
534 	wlan_objmgr_peer_destroy_handler handler;
535 	void *arg;
536 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
537 
538 	/* component id is invalid */
539 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
540 		return QDF_STATUS_MAXCOMP_FAIL;
541 
542 	wlan_peer_obj_lock(peer);
543 	/* Component object was never created, invalid operation */
544 	if (peer->peer_comp_priv_obj[id] == NULL) {
545 		wlan_peer_obj_unlock(peer);
546 		return QDF_STATUS_E_FAILURE;
547 	}
548 
549 	wlan_peer_obj_unlock(peer);
550 
551 	/* Invoke registered destroy handlers */
552 	handler = g_umac_glb_obj->peer_destroy_handler[id];
553 	arg = g_umac_glb_obj->peer_destroy_handler_arg[id];
554 	if (handler != NULL)
555 		peer->obj_status[id] = handler(peer, arg);
556 	else
557 		return QDF_STATUS_E_FAILURE;
558 
559 	/* If object status is created, then only handle this object status */
560 	if (peer->obj_state == WLAN_OBJ_STATE_CREATED) {
561 		obj_status = wlan_objmgr_peer_object_status(peer);
562 			/* move object state to DEL progress */
563 		if (obj_status == QDF_STATUS_COMP_ASYNC)
564 			peer->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS;
565 	}
566 	return obj_status;
567 }
568 
569 void *wlan_objmgr_peer_get_comp_private_obj(
570 		struct wlan_objmgr_peer *peer,
571 		enum wlan_umac_comp_id id)
572 {
573 	void *comp_priv_obj;
574 
575 	/* component id is invalid */
576 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
577 		QDF_BUG(0);
578 		return NULL;
579 	}
580 
581 	if (peer == NULL) {
582 		QDF_BUG(0);
583 		return NULL;
584 	}
585 
586 	comp_priv_obj = peer->peer_comp_priv_obj[id];
587 	return comp_priv_obj;
588 }
589 qdf_export_symbol(wlan_objmgr_peer_get_comp_private_obj);
590 
591 #ifdef WLAN_OBJMGR_REF_ID_DEBUG
592 static inline void
593 wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer *peer,
594 				  wlan_objmgr_ref_dbgid id)
595 {
596 	qdf_atomic_inc(&peer->peer_objmgr.ref_id_dbg[id]);
597 }
598 #else
599 static inline void
600 wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer *peer,
601 				  wlan_objmgr_ref_dbgid id) {}
602 #endif
603 
604 void wlan_objmgr_peer_get_ref(struct wlan_objmgr_peer *peer,
605 			      wlan_objmgr_ref_dbgid id)
606 {
607 	if (peer == NULL) {
608 		obj_mgr_err("peer obj is NULL for %d", id);
609 		QDF_ASSERT(0);
610 		return;
611 	}
612 	/* Increment ref count */
613 	qdf_atomic_inc(&peer->peer_objmgr.ref_cnt);
614 	wlan_objmgr_peer_get_debug_id_ref(peer, id);
615 
616 	return;
617 }
618 qdf_export_symbol(wlan_objmgr_peer_get_ref);
619 
620 QDF_STATUS wlan_objmgr_peer_try_get_ref(struct wlan_objmgr_peer *peer,
621 						 wlan_objmgr_ref_dbgid id)
622 {
623 
624 	uint8_t *macaddr;
625 
626 	if (peer == NULL) {
627 		obj_mgr_err("peer obj is NULL for %d", id);
628 		QDF_ASSERT(0);
629 		return QDF_STATUS_E_FAILURE;
630 	}
631 
632 	wlan_peer_obj_lock(peer);
633 	macaddr = wlan_peer_get_macaddr(peer);
634 	if (peer->obj_state != WLAN_OBJ_STATE_CREATED) {
635 		wlan_peer_obj_unlock(peer);
636 		if (peer->peer_objmgr.print_cnt++ <=
637 				WLAN_OBJMGR_RATELIMIT_THRESH)
638 			obj_mgr_warn(
639 			"peer(" QDF_MAC_ADDR_STR ") not in Created st(%d)",
640 			QDF_MAC_ADDR_ARRAY(macaddr),
641 				peer->obj_state);
642 		return QDF_STATUS_E_RESOURCES;
643 	}
644 
645 	wlan_objmgr_peer_get_ref(peer, id);
646 	wlan_peer_obj_unlock(peer);
647 
648 	return QDF_STATUS_SUCCESS;
649 }
650 qdf_export_symbol(wlan_objmgr_peer_try_get_ref);
651 
652 #ifdef WLAN_OBJMGR_REF_ID_DEBUG
653 static void
654 wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer *peer,
655 				      wlan_objmgr_ref_dbgid id)
656 {
657 	uint8_t *macaddr;
658 
659 	macaddr = wlan_peer_get_macaddr(peer);
660 	if (!qdf_atomic_read(&peer->peer_objmgr.ref_id_dbg[id])) {
661 		obj_mgr_err(
662 		"peer(%02x:%02x:%02x:%02x:%02x:%02x) ref was not taken by %d",
663 			macaddr[0], macaddr[1], macaddr[2],
664 			macaddr[3], macaddr[4], macaddr[5], id);
665 		wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg,
666 					  QDF_TRACE_LEVEL_FATAL);
667 		WLAN_OBJMGR_BUG(0);
668 	}
669 
670 	qdf_atomic_dec(&peer->peer_objmgr.ref_id_dbg[id]);
671 }
672 #else
673 static inline void
674 wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer *peer,
675 				      wlan_objmgr_ref_dbgid id) {}
676 #endif
677 
678 void wlan_objmgr_peer_release_ref(struct wlan_objmgr_peer *peer,
679 				  wlan_objmgr_ref_dbgid id)
680 {
681 	uint8_t *macaddr;
682 
683 	if (!peer) {
684 		obj_mgr_err("peer obj is NULL for %d", id);
685 		QDF_ASSERT(0);
686 		return;
687 	}
688 
689 	macaddr = wlan_peer_get_macaddr(peer);
690 
691 	if (!qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) {
692 		obj_mgr_err("peer(%02x:%02x:%02x:%02x:%02x:%02x) ref cnt is 0",
693 				macaddr[0], macaddr[1], macaddr[2],
694 				macaddr[3], macaddr[4], macaddr[5]);
695 		WLAN_OBJMGR_BUG(0);
696 		return;
697 	}
698 	wlan_objmgr_peer_release_debug_id_ref(peer, id);
699 
700 	/* Provide synchronization from the access to add peer
701 	 * to logically deleted peer list.
702 	 */
703 	wlan_peer_obj_lock(peer);
704 	/* Decrement ref count, free peer object, if ref count == 0 */
705 	if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt)) {
706 		wlan_peer_obj_unlock(peer);
707 		wlan_objmgr_peer_obj_destroy(peer);
708 	} else {
709 		wlan_peer_obj_unlock(peer);
710 	}
711 
712 	return;
713 }
714 qdf_export_symbol(wlan_objmgr_peer_release_ref);
715 
716 struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_active_head(
717 				struct wlan_objmgr_vdev *vdev,
718 				qdf_list_t *peer_list,
719 				wlan_objmgr_ref_dbgid dbg_id)
720 {
721 	struct wlan_objmgr_peer *peer;
722 	qdf_list_node_t *vdev_node = NULL;
723 	qdf_list_node_t *prev_vdev_node = NULL;
724 
725 	wlan_vdev_obj_lock(vdev);
726 
727 	if (qdf_list_peek_front(peer_list, &vdev_node) != QDF_STATUS_SUCCESS) {
728 		wlan_vdev_obj_unlock(vdev);
729 		return NULL;
730 	}
731 
732 	do {
733 		peer = qdf_container_of(vdev_node, struct wlan_objmgr_peer,
734 						vdev_peer);
735 
736 		if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) ==
737 				QDF_STATUS_SUCCESS) {
738 			wlan_vdev_obj_unlock(vdev);
739 			return peer;
740 		}
741 
742 		prev_vdev_node = vdev_node;
743 	} while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) ==
744 							QDF_STATUS_SUCCESS);
745 
746 	wlan_vdev_obj_unlock(vdev);
747 
748 	return NULL;
749 }
750 
751 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_vdev(
752 					struct wlan_objmgr_vdev *vdev,
753 					qdf_list_t *peer_list,
754 					struct wlan_objmgr_peer *peer,
755 					wlan_objmgr_ref_dbgid dbg_id)
756 {
757 	struct wlan_objmgr_peer *peer_next;
758 	qdf_list_node_t *vdev_node = NULL;
759 	qdf_list_node_t *prev_vdev_node = NULL;
760 
761 	if (peer == NULL)
762 		return NULL;
763 
764 	wlan_vdev_obj_lock(vdev);
765 
766 	prev_vdev_node = &peer->vdev_peer;
767 	while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) ==
768 						QDF_STATUS_SUCCESS) {
769 		peer_next = qdf_container_of(vdev_node, struct wlan_objmgr_peer,
770 					vdev_peer);
771 
772 		if (wlan_objmgr_peer_try_get_ref(peer_next, dbg_id) ==
773 				QDF_STATUS_SUCCESS) {
774 			wlan_vdev_obj_unlock(vdev);
775 			return peer_next;
776 		}
777 
778 		prev_vdev_node = vdev_node;
779 	}
780 
781 	wlan_vdev_obj_unlock(vdev);
782 
783 	return NULL;
784 }
785 
786 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_psoc(
787 					struct wlan_peer_list *peer_list,
788 					uint8_t hash_index,
789 					struct wlan_objmgr_peer *peer,
790 					wlan_objmgr_ref_dbgid dbg_id)
791 {
792 	struct wlan_objmgr_peer *peer_next = NULL;
793 	qdf_list_node_t *psoc_node = NULL;
794 	qdf_list_node_t *prev_psoc_node = NULL;
795 	qdf_list_t *obj_list;
796 
797 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
798 	obj_list = &peer_list->peer_hash[hash_index];
799 
800 	prev_psoc_node = &peer->psoc_peer;
801 	while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) ==
802 						QDF_STATUS_SUCCESS) {
803 		peer_next = qdf_container_of(psoc_node, struct wlan_objmgr_peer,
804 						psoc_peer);
805 
806 		if (wlan_objmgr_peer_try_get_ref(peer_next, dbg_id) ==
807 				QDF_STATUS_SUCCESS) {
808 			qdf_spin_unlock_bh(&peer_list->peer_list_lock);
809 			return peer_next;
810 		}
811 
812 		prev_psoc_node = psoc_node;
813 	}
814 
815 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
816 
817 	return NULL;
818 }
819 
820 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_active_head(
821 					struct wlan_peer_list *peer_list,
822 					uint8_t hash_index,
823 					wlan_objmgr_ref_dbgid dbg_id)
824 {
825 	struct wlan_objmgr_peer *peer;
826 	qdf_list_node_t *psoc_node = NULL;
827 	qdf_list_node_t *prev_psoc_node = NULL;
828 	qdf_list_t *obj_list;
829 
830 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
831 	obj_list = &peer_list->peer_hash[hash_index];
832 
833 	if (qdf_list_peek_front(obj_list, &psoc_node) != QDF_STATUS_SUCCESS) {
834 		qdf_spin_unlock_bh(&peer_list->peer_list_lock);
835 		return NULL;
836 	}
837 
838 	do {
839 		peer = qdf_container_of(psoc_node, struct wlan_objmgr_peer,
840 						psoc_peer);
841 		if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) ==
842 				QDF_STATUS_SUCCESS) {
843 			qdf_spin_unlock_bh(&peer_list->peer_list_lock);
844 			return peer;
845 		}
846 
847 		prev_psoc_node = psoc_node;
848 	} while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) ==
849 						QDF_STATUS_SUCCESS);
850 
851 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
852 	return NULL;
853 }
854 
855 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head_ref(
856 					struct wlan_peer_list *peer_list,
857 					uint8_t hash_index,
858 					wlan_objmgr_ref_dbgid dbg_id)
859 {
860 	struct wlan_objmgr_peer *peer;
861 	qdf_list_t *obj_list;
862 
863 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
864 	obj_list = &peer_list->peer_hash[hash_index];
865 
866 	peer = wlan_psoc_peer_list_peek_head(obj_list);
867 
868 	/**
869 	 * This API is invoked by caller, only when caller need to access the
870 	 * peer object, though object is not in active state, this API should be
871 	 * used carefully, where multiple object frees are not triggered
872 	 */
873 	if (peer)
874 		wlan_objmgr_peer_get_ref(peer, dbg_id);
875 
876 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
877 
878 	return peer;
879 }
880 
881 struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc_ref(
882 			struct wlan_peer_list *peer_list, uint8_t hash_index,
883 			struct wlan_objmgr_peer *peer,
884 			wlan_objmgr_ref_dbgid dbg_id)
885 {
886 	qdf_list_t *obj_list;
887 	struct wlan_objmgr_peer *peer_next;
888 
889 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
890 	obj_list = &peer_list->peer_hash[hash_index];
891 
892 	peer_next = wlan_peer_get_next_peer_of_psoc(obj_list, peer);
893 	/**
894 	 * This API is invoked by caller, only when caller need to access the
895 	 * peer object, though object is not in active state, this API should be
896 	 * used carefully, where multiple free on object are not triggered
897 	 */
898 	if (peer_next)
899 		wlan_objmgr_peer_get_ref(peer_next, dbg_id);
900 
901 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
902 
903 	return peer_next;
904 }
905 
906 #ifdef WLAN_OBJMGR_REF_ID_DEBUG
907 void
908 wlan_objmgr_print_peer_ref_ids(struct wlan_objmgr_peer *peer,
909 			       QDF_TRACE_LEVEL log_level)
910 {
911 	wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg, log_level);
912 }
913 
914 uint32_t
915 wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer *peer,
916 				  enum wlan_umac_comp_id id)
917 {
918 	return qdf_atomic_read(&peer->peer_objmgr.ref_id_dbg[id]);
919 }
920 #else
921 void
922 wlan_objmgr_print_peer_ref_ids(struct wlan_objmgr_peer *peer,
923 			       QDF_TRACE_LEVEL log_level)
924 {
925 	uint32_t pending_ref;
926 
927 	pending_ref = qdf_atomic_read(&peer->peer_objmgr.ref_cnt);
928 	obj_mgr_log_level(log_level, "Pending refs -- %d", pending_ref);
929 }
930 
931 uint32_t
932 wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer *peer,
933 				  enum wlan_umac_comp_id id)
934 {
935 	return 0;
936 }
937 #endif
938