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