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