xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj.c (revision cd39549564686e1d60a410c477b7c6e9e19791fd)
1 /*
2  * Copyright (c) 2016 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 Global objects
20   */
21 
22 #include <wlan_objmgr_cmn.h>
23 #include <wlan_objmgr_global_obj.h>
24 #include <wlan_objmgr_global_obj_i.h>
25 #include <wlan_objmgr_psoc_obj.h>
26 #include <wlan_objmgr_pdev_obj.h>
27 #include <wlan_objmgr_vdev_obj.h>
28 #include <wlan_objmgr_peer_obj.h>
29 #include <wlan_objmgr_psoc_obj_i.h>
30 #include <wlan_objmgr_pdev_obj_i.h>
31 #include <qdf_mem.h>
32 
33 /**
34  ** APIs to Create/Delete Global object APIs
35  */
36 static QDF_STATUS wlan_objmgr_psoc_object_status(
37 			struct wlan_objmgr_psoc *psoc)
38 {
39 	uint8_t id;
40 	QDF_STATUS status = QDF_STATUS_SUCCESS;
41 
42 	wlan_psoc_obj_lock(psoc);
43 	/* Iterate through all components to derive the object status */
44 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
45 		/* If component disabled, Ignore */
46 		if (psoc->obj_status[id] == QDF_STATUS_COMP_DISABLED)
47 			continue;
48 		/* If component operates in Async, status is Partially created,
49 			break */
50 		else if (psoc->obj_status[id] == QDF_STATUS_COMP_ASYNC) {
51 			if (psoc->soc_comp_obj[id] == NULL) {
52 				status = QDF_STATUS_COMP_ASYNC;
53 				break;
54 			}
55 		/*
56 		 * If component failed to allocate its object, treat it as
57 		 * failure, complete object need to be cleaned up
58 		 */
59 		} else if ((psoc->obj_status[id] == QDF_STATUS_E_NOMEM) ||
60 			(psoc->obj_status[id] == QDF_STATUS_E_FAILURE)) {
61 			status = QDF_STATUS_E_FAILURE;
62 			break;
63 		}
64 	}
65 	wlan_psoc_obj_unlock(psoc);
66 	return status;
67 }
68 
69 static void wlan_objmgr_psoc_peer_list_init(struct wlan_peer_list *peer_list)
70 {
71 	uint8_t i;
72 
73 	qdf_spinlock_create(&peer_list->peer_list_lock);
74 	for (i = 0; i < WLAN_PEER_HASHSIZE; i++)
75 		qdf_list_create(&peer_list->peer_hash[i],
76 				WLAN_UMAC_PSOC_MAX_PEERS);
77 }
78 
79 static void wlan_objmgr_psoc_peer_list_deinit(struct wlan_peer_list *peer_list)
80 {
81 	uint8_t i;
82 
83 	/* deinit the lock */
84 	qdf_spinlock_destroy(&peer_list->peer_list_lock);
85 	for (i = 0; i < WLAN_PEER_HASHSIZE; i++)
86 		qdf_list_destroy(&peer_list->peer_hash[i]);
87 }
88 /*
89  * wlan_objmgr_psco_create_handler would return following status values
90  */
91 struct wlan_objmgr_psoc *wlan_objmgr_psoc_obj_create(uint32_t phy_version,
92 						WLAN_DEV_TYPE dev_type)
93 {
94 	uint8_t id;
95 	struct wlan_objmgr_psoc *psoc = NULL;
96 	wlan_objmgr_psoc_create_handler handler;
97 	wlan_objmgr_psoc_status_handler stat_handler;
98 	struct wlan_objmgr_psoc_objmgr *objmgr;
99 	QDF_STATUS obj_status;
100 	void *arg;
101 
102 	/* Allocate PSOC object's memory */
103 	psoc = qdf_mem_malloc(sizeof(*psoc));
104 	if (psoc == NULL) {
105 		qdf_print("%s: PSOC allocation failed\n", __func__);
106 		return NULL;
107 	}
108 	/* Init spinlock */
109 	qdf_spinlock_create(&psoc->psoc_lock);
110 	/* Initialize with default values */
111 	objmgr = &psoc->soc_objmgr;
112 	objmgr->wlan_pdev_count = 0;
113 	objmgr->wlan_vdev_count = 0;
114 	objmgr->max_vdev_count = WLAN_UMAC_PSOC_MAX_VDEVS;
115 	objmgr->wlan_peer_count = 0;
116 	/* set phy version, dev_type in psoc */
117 	wlan_psoc_set_nif_phy_version(psoc, phy_version);
118 	wlan_psoc_set_dev_type(psoc, dev_type);
119 	/* Initialize peer list */
120 	wlan_objmgr_psoc_peer_list_init(&objmgr->peer_list);
121 	/* Invoke registered create handlers */
122 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
123 		handler = g_umac_glb_obj->psoc_create_handler[id];
124 		arg = g_umac_glb_obj->psoc_create_handler_arg[id];
125 		if (handler != NULL)
126 			psoc->obj_status[id] = handler(psoc, arg);
127 		else
128 			psoc->obj_status[id] = QDF_STATUS_COMP_DISABLED;
129 	}
130 	/* Derive object status */
131 	obj_status = wlan_objmgr_psoc_object_status(psoc);
132 
133 	if (obj_status == QDF_STATUS_SUCCESS) {
134 		/* Object status is SUCCESS, Object is created */
135 		psoc->obj_state = WLAN_OBJ_STATE_CREATED;
136 		for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
137 			stat_handler = g_umac_glb_obj->psoc_status_handler[id];
138 			arg = g_umac_glb_obj->psoc_status_handler_arg[id];
139 			if (stat_handler != NULL)
140 				stat_handler(psoc, arg,
141 					     QDF_STATUS_SUCCESS);
142 		}
143 	/*
144 	 * Few components operates in Asynchrous communction, Object state
145 	 * partially created
146 	 */
147 	} else if (obj_status == QDF_STATUS_COMP_ASYNC) {
148 		psoc->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED;
149 	/* Component object failed to be created, clean up the object */
150 	} else if (obj_status == QDF_STATUS_E_FAILURE) {
151 		qdf_print("%s: PSOC component objects allocation failed\n",
152 			  __func__);
153 		/* Clean up the psoc */
154 		wlan_objmgr_psoc_obj_delete(psoc);
155 		return NULL;
156 	}
157 
158 	if (wlan_objmgr_psoc_object_attach(psoc) !=
159 				QDF_STATUS_SUCCESS) {
160 		qdf_print("%s: PSOC object attach failed\n", __func__);
161 		wlan_objmgr_psoc_obj_delete(psoc);
162 		return NULL;
163 	}
164 	return psoc;
165 }
166 EXPORT_SYMBOL(wlan_objmgr_psoc_obj_create);
167 
168 QDF_STATUS wlan_objmgr_psoc_obj_delete(struct wlan_objmgr_psoc *psoc)
169 {
170 	uint8_t id;
171 	wlan_objmgr_psoc_delete_handler handler;
172 	QDF_STATUS obj_status;
173 	void *arg;
174 
175 	/* if PSOC is NULL, return */
176 	if (psoc == NULL) {
177 		qdf_print("%s:psoc is NULL\n", __func__);
178 		return QDF_STATUS_E_FAILURE;
179 	}
180 
181 	/* Invoke registered create handlers */
182 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
183 		handler = g_umac_glb_obj->psoc_delete_handler[id];
184 		arg = g_umac_glb_obj->psoc_delete_handler_arg[id];
185 		if (handler != NULL)
186 			psoc->obj_status[id] = handler(psoc, arg);
187 		else
188 			psoc->obj_status[id] = QDF_STATUS_COMP_DISABLED;
189 	}
190 	/* Derive object status */
191 	obj_status = wlan_objmgr_psoc_object_status(psoc);
192 
193 	if (obj_status == QDF_STATUS_E_FAILURE) {
194 		qdf_print("%s: PSOC component object free failed\n", __func__);
195 		/* Ideally should not happen */
196 		/*This leads to memleak ??? how to handle */
197 		QDF_BUG(0);
198 		return QDF_STATUS_E_FAILURE;
199 	}
200 	/* Deletion is in progress */
201 	if (obj_status == QDF_STATUS_COMP_ASYNC) {
202 		psoc->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED;
203 		return QDF_STATUS_COMP_ASYNC;
204 	} else {
205 		/* Detach PSOC from global object's psoc list  */
206 		if (wlan_objmgr_psoc_object_detach(psoc) ==
207 					QDF_STATUS_E_FAILURE) {
208 			qdf_print("%s: PSOC object detach failed\n", __func__);
209 			return QDF_STATUS_E_FAILURE;
210 		}
211 		wlan_objmgr_psoc_peer_list_deinit(&psoc->soc_objmgr.peer_list);
212 		/* Destroy spinlock */
213 		qdf_spinlock_destroy(&psoc->psoc_lock);
214 		/* Free the memory */
215 		qdf_mem_free(psoc);
216 	}
217 	return QDF_STATUS_SUCCESS;
218 }
219 EXPORT_SYMBOL(wlan_objmgr_psoc_obj_delete);
220 
221 /**
222  ** APIs to attach/detach component objects
223  */
224 QDF_STATUS wlan_objmgr_psoc_component_obj_attach(
225 		struct wlan_objmgr_psoc *psoc,
226 		enum wlan_umac_comp_id id,
227 		void *comp_objptr,
228 		QDF_STATUS status)
229 {
230 	wlan_objmgr_psoc_status_handler stat_handler;
231 	void *arg = NULL;
232 	QDF_STATUS obj_status;
233 	uint8_t i;
234 
235 	/* component id is invalid */
236 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
237 		return QDF_STATUS_MAXCOMP_FAIL;
238 
239 	wlan_psoc_obj_lock(psoc);
240 	/* If there is a valid entry, return failure */
241 	if (psoc->soc_comp_obj[id] != NULL) {
242 		wlan_psoc_obj_unlock(psoc);
243 		return QDF_STATUS_E_FAILURE;
244 	}
245 	/* Save component's pointer and status */
246 	psoc->soc_comp_obj[id] = comp_objptr;
247 	psoc->obj_status[id] = status;
248 	wlan_psoc_obj_unlock(psoc);
249 
250 	if (psoc->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED)
251 		return QDF_STATUS_SUCCESS;
252 	/* If PSOC object status is partially created means, this API is
253 	 * invoked with differnt context, this block should be executed for
254 	 * async components only
255 	 */
256 	/* Derive status */
257 	obj_status = wlan_objmgr_psoc_object_status(psoc);
258 	/* STATUS_SUCCESS means, object is CREATED */
259 	if (obj_status == QDF_STATUS_SUCCESS)
260 		psoc->obj_state = WLAN_OBJ_STATE_CREATED;
261 	/* update state as CREATION failed, caller has to delete the
262 	 * PSOC object
263 	 */
264 	else if (obj_status == QDF_STATUS_E_FAILURE)
265 		psoc->obj_state = WLAN_OBJ_STATE_CREATION_FAILED;
266 
267 	/* Notify components about the CREATION success/failure */
268 	if ((obj_status == QDF_STATUS_SUCCESS) ||
269 	    (obj_status == QDF_STATUS_E_FAILURE)) {
270 		/* nofity object status */
271 		for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) {
272 			stat_handler = g_umac_glb_obj->psoc_status_handler[i];
273 			arg = g_umac_glb_obj->psoc_status_handler_arg[i];
274 			if (stat_handler != NULL)
275 				stat_handler(psoc, arg, obj_status);
276 		}
277 	}
278 	return QDF_STATUS_SUCCESS;
279 }
280 
281 QDF_STATUS wlan_objmgr_psoc_component_obj_detach(
282 		struct wlan_objmgr_psoc *psoc,
283 		enum wlan_umac_comp_id id,
284 		void *comp_objptr)
285 {
286 	QDF_STATUS obj_status;
287 
288 	/* component id is invalid */
289 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
290 		return QDF_STATUS_MAXCOMP_FAIL;
291 
292 	wlan_psoc_obj_lock(psoc);
293 	/* If there is a valid entry, return failure */
294 	if (psoc->soc_comp_obj[id] != comp_objptr) {
295 		psoc->obj_status[id] = QDF_STATUS_E_FAILURE;
296 		wlan_psoc_obj_unlock(psoc);
297 		return QDF_STATUS_E_FAILURE;
298 	}
299 	/* Reset pointers to NULL, update the status*/
300 	psoc->soc_comp_obj[id] = NULL;
301 	psoc->obj_status[id] = QDF_STATUS_SUCCESS;
302 	wlan_psoc_obj_unlock(psoc);
303 
304 	/* If PSOC object status is partially created means, this API is
305 	 * invoked with differnt context, this block should be executed for
306 	 * async components only
307 	 */
308 	if ((psoc->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) ||
309 	    (psoc->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) {
310 		/* Derive object status */
311 		obj_status = wlan_objmgr_psoc_object_status(psoc);
312 		if (obj_status == QDF_STATUS_SUCCESS) {
313 			/* Update the status as Deleted, if full object
314 			 * deletion is in progress
315 			 */
316 			if (psoc->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED)
317 				psoc->obj_state = WLAN_OBJ_STATE_DELETED;
318 
319 			/* Move to creation state, since this component
320 			 * deletion alone requested
321 			 */
322 			if (psoc->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
323 				psoc->obj_state = WLAN_OBJ_STATE_CREATED;
324 		/* Object status is failure */
325 		} else if (obj_status == QDF_STATUS_E_FAILURE) {
326 			/* Update the status as Deletion failed, if full object
327 			 * deletion is in progress
328 			 */
329 			if (psoc->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED)
330 				psoc->obj_state =
331 					WLAN_OBJ_STATE_DELETION_FAILED;
332 
333 			/* Move to creation state, since this component
334 			 * deletion alone requested (do not block other
335 			 * components)
336 			 */
337 			if (psoc->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
338 				psoc->obj_state = WLAN_OBJ_STATE_CREATED;
339 		}
340 
341 		/* Delete psoc object */
342 		if ((obj_status == QDF_STATUS_SUCCESS)  &&
343 		    (psoc->obj_state == WLAN_OBJ_STATE_DELETED)) {
344 			/* Detach PSOC from global object's psoc list */
345 			if (wlan_objmgr_psoc_object_detach(psoc) ==
346 						QDF_STATUS_E_FAILURE)
347 				return QDF_STATUS_E_FAILURE;
348 
349 			wlan_objmgr_psoc_peer_list_deinit(
350 				&psoc->soc_objmgr.peer_list);
351 			/* Destroy spinlock */
352 			qdf_spinlock_destroy(&psoc->psoc_lock);
353 			/* Free memory */
354 			qdf_mem_free(psoc);
355 		}
356 	}
357 	return QDF_STATUS_SUCCESS;
358 }
359 
360 /**
361  ** APIs to operations on psoc objects
362  */
363 
364 QDF_STATUS wlan_objmgr_iterate_obj_list(
365 		struct wlan_objmgr_psoc *psoc,
366 		enum wlan_objmgr_obj_type obj_type,
367 		wlan_objmgr_op_handler handler,
368 		void *arg, uint8_t lock_free_op)
369 {
370 	uint16_t obj_id;
371 	uint8_t i;
372 	struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr;
373 	struct wlan_peer_list *peer_list;
374 	qdf_list_t *obj_list;
375 	struct wlan_objmgr_peer *peer;
376 	struct wlan_objmgr_peer *peer_next;
377 
378 	/* If caller requests for lock free opeation, do not acquire,
379 	 * handler will handle the synchronization
380 	 */
381 	if (!lock_free_op)
382 		wlan_psoc_obj_lock(psoc);
383 
384 	switch (obj_type) {
385 	case WLAN_PDEV_OP:
386 		/* Iterate through PDEV list, invoke handler for each pdev */
387 		for (obj_id = 0; obj_id < WLAN_UMAC_MAX_PDEVS; obj_id++) {
388 			if (objmgr->wlan_pdev_list[obj_id] != NULL) {
389 				/* TODO increment ref count */
390 				handler(psoc,
391 					(void *)objmgr->wlan_pdev_list[obj_id],
392 					arg);
393 				/* TODO decrement ref count */
394 			}
395 		}
396 		break;
397 	case WLAN_VDEV_OP:
398 		/* Iterate through VDEV list, invoke handler for each vdev */
399 		for (obj_id = 0; obj_id < WLAN_UMAC_PSOC_MAX_VDEVS; obj_id++) {
400 			if (objmgr->wlan_vdev_list[obj_id] != NULL) {
401 				/* TODO increment ref count */
402 				handler(psoc,
403 					(void *)objmgr->wlan_vdev_list[obj_id],
404 					arg);
405 				/* TODO decrement ref count */
406 			}
407 		}
408 		break;
409 	case WLAN_PEER_OP:
410 		/* Iterate through PEER list, invoke handler for each peer */
411 		peer_list = &objmgr->peer_list;
412 		if (!lock_free_op)
413 			qdf_spin_lock_bh(&peer_list->peer_list_lock);
414 		/* Since peer list has sublist, iterate through sublists */
415 		for (i = 0; i < WLAN_PEER_HASHSIZE; i++) {
416 			obj_list = &peer_list->peer_hash[i];
417 			peer = wlan_psoc_peer_list_peek_head(obj_list);
418 			while (peer) {
419 				/* Increment ref count, to hold the
420 					peer pointer */
421 				wlan_objmgr_peer_ref_peer(peer);
422 				handler(psoc, (void *)peer, arg);
423 				/* Get next peer */
424 				peer_next = wlan_peer_get_next_peer_of_psoc(
425 								obj_list, peer);
426 				/* Decrement ref count, this can lead
427 					to peer deletion also */
428 				wlan_objmgr_peer_unref_peer(peer);
429 				peer = peer_next;
430 			}
431 		}
432 		if (!lock_free_op)
433 			qdf_spin_unlock_bh(&peer_list->peer_list_lock);
434 		break;
435 	default:
436 		break;
437 	}
438 	if (!lock_free_op)
439 		wlan_psoc_obj_unlock(psoc);
440 	return QDF_STATUS_SUCCESS;
441 }
442 
443 void wlan_objmgr_psoc_peer_delete(struct wlan_objmgr_psoc *psoc, void *obj,
444 						 void *args)
445 {
446 	struct wlan_objmgr_peer *peer = (struct wlan_objmgr_peer *)obj;
447 
448 	wlan_objmgr_peer_obj_delete(peer);
449 }
450 
451 void wlan_objmgr_psoc_vdev_delete(struct wlan_objmgr_psoc *psoc, void *obj,
452 							void *args)
453 {
454 	struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)obj;
455 
456 	wlan_objmgr_vdev_obj_delete(vdev);
457 }
458 
459 void wlan_objmgr_psoc_pdev_delete(struct wlan_objmgr_psoc *psoc, void *obj,
460 							void *args)
461 {
462 	struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)obj;
463 
464 	wlan_objmgr_pdev_obj_delete(pdev);
465 }
466 
467 QDF_STATUS wlan_objmgr_free_all_objects_per_psoc(
468 		struct wlan_objmgr_psoc *psoc)
469 {
470 	/* Free all peers */
471 	wlan_objmgr_iterate_obj_list(psoc, WLAN_PEER_OP,
472 				     wlan_objmgr_psoc_peer_delete, NULL, 1);
473 	/* Free all vdevs */
474 	wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
475 				     wlan_objmgr_psoc_vdev_delete, NULL, 1);
476 	/* Free all PDEVs */
477 	wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
478 				     wlan_objmgr_psoc_pdev_delete, NULL, 1);
479 	return QDF_STATUS_SUCCESS;
480 }
481 
482 QDF_STATUS wlan_objmgr_trigger_psoc_comp_object_creation(
483 		struct wlan_objmgr_psoc *psoc,
484 		enum wlan_umac_comp_id id)
485 {
486 	wlan_objmgr_psoc_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_psoc_obj_lock(psoc);
495 	/* If component object is already created, delete old
496 	 * component object, then invoke creation
497 	 */
498 	if (psoc->soc_comp_obj[id] != NULL) {
499 		wlan_psoc_obj_unlock(psoc);
500 		return QDF_STATUS_E_FAILURE;
501 	}
502 	wlan_psoc_obj_unlock(psoc);
503 	/* Invoke registered create handlers */
504 	handler = g_umac_glb_obj->psoc_create_handler[id];
505 	arg = g_umac_glb_obj->psoc_create_handler_arg[id];
506 	if (handler != NULL)
507 		psoc->obj_status[id] = handler(psoc, arg);
508 	else
509 		return QDF_STATUS_E_FAILURE;
510 
511 	/* If object status is created, then only handle this object status */
512 	if (psoc->obj_state == WLAN_OBJ_STATE_CREATED) {
513 		/* Derive object status */
514 		obj_status = wlan_objmgr_psoc_object_status(psoc);
515 		/* Move PSOC object state to Partially created state */
516 		if (obj_status == QDF_STATUS_COMP_ASYNC) {
517 			/*TODO atomic */
518 			psoc->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED;
519 		}
520 	}
521 	return obj_status;
522 }
523 
524 QDF_STATUS wlan_objmgr_trigger_psoc_comp_object_deletion(
525 		struct wlan_objmgr_psoc *psoc,
526 		enum wlan_umac_comp_id id)
527 {
528 	wlan_objmgr_psoc_delete_handler handler;
529 	void *arg;
530 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
531 
532 	/* component id is invalid */
533 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
534 		return QDF_STATUS_MAXCOMP_FAIL;
535 
536 	wlan_psoc_obj_lock(psoc);
537 	/* Component object was never created, invalid operation */
538 	if (psoc->soc_comp_obj[id] == NULL) {
539 		wlan_psoc_obj_unlock(psoc);
540 		return QDF_STATUS_E_FAILURE;
541 	}
542 	wlan_psoc_obj_unlock(psoc);
543 	/* Invoke registered create handlers */
544 	handler = g_umac_glb_obj->psoc_delete_handler[id];
545 	arg = g_umac_glb_obj->psoc_delete_handler_arg[id];
546 	if (handler != NULL)
547 		psoc->obj_status[id] = handler(psoc, arg);
548 	else
549 		return QDF_STATUS_E_FAILURE;
550 
551 	/* If object status is created, then only handle this object status */
552 	if (psoc->obj_state == WLAN_OBJ_STATE_CREATED) {
553 		obj_status = wlan_objmgr_psoc_object_status(psoc);
554 			/* move object state to DEL progress */
555 		if (obj_status == QDF_STATUS_COMP_ASYNC)
556 			psoc->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS;
557 	}
558 	return obj_status;
559 }
560 
561 /* Util APIs */
562 
563 QDF_STATUS wlan_objmgr_psoc_pdev_attach(struct wlan_objmgr_psoc *psoc,
564 					struct wlan_objmgr_pdev *pdev)
565 {
566 	struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr;
567 	uint8_t id = 0;
568 	QDF_STATUS status;
569 
570 	wlan_psoc_obj_lock(psoc);
571 	/*
572 	 * Derive pdev id from pdev map
573 	 * First free pdev id is assigned
574 	 */
575 	while ((id < WLAN_UMAC_MAX_PDEVS) &&
576 			(objmgr->wlan_pdev_id_map & (1<<id)))
577 		id++;
578 
579 	if (id == WLAN_UMAC_MAX_PDEVS) {
580 		status = QDF_STATUS_E_FAILURE;
581 	} else {
582 		/* Update the map for reserving the id */
583 		objmgr->wlan_pdev_id_map |= (1<<id);
584 		/* store pdev in pdev list */
585 		objmgr->wlan_pdev_list[id] = pdev;
586 		/* Increment pdev count */
587 		objmgr->wlan_pdev_count++;
588 		/* save pdev id */
589 		pdev->pdev_objmgr.wlan_pdev_id = id;
590 		status = QDF_STATUS_SUCCESS;
591 	}
592 	wlan_psoc_obj_unlock(psoc);
593 	return status;
594 }
595 
596 QDF_STATUS wlan_objmgr_psoc_pdev_detach(struct wlan_objmgr_psoc *psoc,
597 						struct wlan_objmgr_pdev *pdev)
598 {
599 	struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr;
600 	uint8_t id;
601 
602 	id = pdev->pdev_objmgr.wlan_pdev_id;
603 	/* If id is invalid, return */
604 	if (id >= WLAN_UMAC_MAX_PDEVS)
605 		return QDF_STATUS_E_FAILURE;
606 
607 	wlan_psoc_obj_lock(psoc);
608 	/* Free pdev id slot */
609 	objmgr->wlan_pdev_id_map &= ~(1<<id);
610 	objmgr->wlan_pdev_list[id] = NULL;
611 	objmgr->wlan_pdev_count--;
612 	pdev->pdev_objmgr.wlan_pdev_id = 0xff;
613 	wlan_psoc_obj_unlock(psoc);
614 
615 	return QDF_STATUS_E_FAILURE;
616 }
617 
618 struct wlan_objmgr_pdev *wlan_objmgr_find_pdev_by_id(
619 		struct wlan_objmgr_psoc *psoc, uint8_t id)
620 {
621 	struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr;
622 	struct wlan_objmgr_pdev *pdev = NULL;
623 
624 	wlan_psoc_obj_lock(psoc);
625 	/* get pdev from pdev list */
626 	pdev = objmgr->wlan_pdev_list[id];
627 	wlan_psoc_obj_unlock(psoc);
628 	return pdev;
629 }
630 
631 QDF_STATUS wlan_objmgr_psoc_vdev_attach(struct wlan_objmgr_psoc *psoc,
632 					struct wlan_objmgr_vdev *vdev)
633 {
634 	struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr;
635 	uint8_t id = 0;
636 	uint8_t map_index = 0;
637 	uint8_t map_entry_size = 32;
638 	uint8_t adjust_ix = 0;
639 	QDF_STATUS status;
640 
641 	wlan_psoc_obj_lock(psoc);
642 	/* Find first free vdev id */
643 	while ((id < objmgr->max_vdev_count) &&
644 		(objmgr->wlan_vdev_id_map[map_index] & (1<<(id - adjust_ix)))) {
645 		id++;
646 		/*
647 		 * The map is two DWORDS(32 bits), so, map_index
648 		 * adjust_ix derived based on the id value
649 		 */
650 		if (id == ((map_index+1)*map_entry_size)) {
651 			adjust_ix = map_index*map_entry_size;
652 			map_index++;
653 		}
654 	}
655 	/* If no free slot, return failure */
656 	if (id == objmgr->max_vdev_count) {
657 		status = QDF_STATUS_E_FAILURE;
658 	} else {
659 		/* set free vdev id index */
660 		objmgr->wlan_vdev_id_map[map_index] |= (1<<(id-adjust_ix));
661 		/* store vdev pointer in vdev list */
662 		objmgr->wlan_vdev_list[id] = vdev;
663 		/* increment vdev counter */
664 		objmgr->wlan_vdev_count++;
665 		/* save vdev id */
666 		vdev->vdev_objmgr.vdev_id = id;
667 		status = QDF_STATUS_SUCCESS;
668 	}
669 	wlan_psoc_obj_unlock(psoc);
670 	return status;
671 }
672 
673 QDF_STATUS wlan_objmgr_psoc_vdev_detach(struct wlan_objmgr_psoc *psoc,
674 					struct wlan_objmgr_vdev *vdev)
675 {
676 	struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr;
677 	uint8_t id = 0;
678 	uint8_t map_index = 0;
679 	uint8_t map_entry_size = 32;
680 	uint8_t adjust_ix = 0;
681 
682 	id = vdev->vdev_objmgr.vdev_id;
683 	/* Invalid vdev id */
684 	if (id >= WLAN_UMAC_PSOC_MAX_VDEVS)
685 		return QDF_STATUS_E_FAILURE;
686 	/*
687 	 * Derive map_index and adjust_ix to find actual DWORD
688 	 * the id map is present
689 	 */
690 	while ((id - adjust_ix) >= map_entry_size) {
691 		map_index++;
692 		adjust_ix = map_index * map_entry_size;
693 	}
694 	wlan_psoc_obj_lock(psoc);
695 	/* unset bit, to free the slot */
696 	objmgr->wlan_vdev_id_map[map_index] &= ~(1<<(id-adjust_ix));
697 	/* reset VDEV pointer to NULL in VDEV list array */
698 	objmgr->wlan_vdev_list[id] = NULL;
699 	/* decrement vdev count */
700 	objmgr->wlan_vdev_count--;
701 	vdev->vdev_objmgr.vdev_id = 0xff;
702 	wlan_psoc_obj_unlock(psoc);
703 	return QDF_STATUS_SUCCESS;
704 }
705 
706 
707 struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_id_from_psoc(
708 			struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
709 {
710 	struct wlan_objmgr_vdev *vdev;
711 
712 	/* if PSOC is NULL, return */
713 	if (psoc == NULL)
714 		return NULL;
715 	/* vdev id is invalid */
716 	if (vdev_id >= WLAN_UMAC_PSOC_MAX_VDEVS)
717 		return NULL;
718 
719 	wlan_psoc_obj_lock(psoc);
720 	/* retrieve vdev pointer from vdev list */
721 	vdev = psoc->soc_objmgr.wlan_vdev_list[vdev_id];
722 	wlan_psoc_obj_unlock(psoc);
723 	return vdev;
724 }
725 
726 struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_macaddr_from_psoc(
727 		struct wlan_objmgr_psoc *psoc, uint8_t *macaddr)
728 {
729 	struct wlan_objmgr_vdev *vdev;
730 	uint8_t id;
731 
732 	/* if PSOC is NULL, return */
733 	if (psoc == NULL)
734 		return NULL;
735 
736 	wlan_psoc_obj_lock(psoc);
737 	/* Iterate through PSOC's vdev list */
738 	for (id = 0; id < WLAN_UMAC_PSOC_MAX_VDEVS; id++) {
739 		vdev = psoc->soc_objmgr.wlan_vdev_list[id];
740 		if (vdev == NULL)
741 			continue;
742 		/* MAC address matches, break */
743 		if (WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), macaddr)
744 			== QDF_STATUS_SUCCESS) {
745 			wlan_psoc_obj_unlock(psoc);
746 			return vdev;
747 		}
748 	}
749 	wlan_psoc_obj_unlock(psoc);
750 	return NULL;
751 }
752 
753 static void wlan_obj_psoc_peerlist_add_tail(qdf_list_t *obj_list,
754 				struct wlan_objmgr_peer *obj)
755 {
756 	qdf_list_insert_back(obj_list, &obj->psoc_peer);
757 }
758 
759 static QDF_STATUS wlan_obj_psoc_peerlist_remove_peer(
760 				qdf_list_t *obj_list,
761 				struct wlan_objmgr_peer *peer)
762 {
763 	qdf_list_node_t *psoc_node = NULL;
764 
765 	if (peer == NULL)
766 		return QDF_STATUS_E_FAILURE;
767 	/* get vdev list node element */
768 	psoc_node = &peer->psoc_peer;
769 	/* list is empty, return failure */
770 	if (qdf_list_remove_node(obj_list, psoc_node) != QDF_STATUS_SUCCESS)
771 		return QDF_STATUS_E_FAILURE;
772 
773 	return QDF_STATUS_SUCCESS;
774 }
775 
776 struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer(
777 				qdf_list_t *obj_list,
778 				uint8_t *macaddr)
779 {
780 	struct wlan_objmgr_peer *peer;
781 	struct wlan_objmgr_peer *peer_temp;
782 
783 	/* Iterate through hash list to get the peer */
784 	peer = wlan_psoc_peer_list_peek_head(obj_list);
785 	while (peer != NULL) {
786 		/* For peer, macaddr is key */
787 		if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr)
788 			== QDF_STATUS_SUCCESS) {
789 			/* Increment ref count for access */
790 			wlan_objmgr_peer_ref_peer(peer);
791 			return peer;
792 		}
793 		/* Move to next peer */
794 		peer_temp = peer;
795 		peer = wlan_peer_get_next_peer_of_psoc(obj_list, peer_temp);
796 	}
797 	/* Not found, return NULL */
798 	return NULL;
799 }
800 
801 QDF_STATUS wlan_objmgr_psoc_peer_attach(struct wlan_objmgr_psoc *psoc,
802 					 struct wlan_objmgr_peer *peer)
803 {
804 	struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr;
805 	uint8_t hash_index;
806 
807 	wlan_psoc_obj_lock(psoc);
808 	/* Max peer limit is reached, return failure */
809 	if (objmgr->wlan_peer_count > WLAN_UMAC_PSOC_MAX_PEERS) {
810 		wlan_psoc_obj_unlock(psoc);
811 		return QDF_STATUS_E_FAILURE;
812 	}
813 	/* Derive hash index from mac address */
814 	hash_index = WLAN_PEER_HASH(peer->macaddr);
815 	/* add peer to hash peer list */
816 	wlan_obj_psoc_peerlist_add_tail(
817 			&objmgr->peer_list.peer_hash[hash_index],
818 							peer);
819 	/* Increment peer count */
820 	objmgr->wlan_peer_count++;
821 
822 	wlan_psoc_obj_unlock(psoc);
823 	return QDF_STATUS_SUCCESS;
824 }
825 
826 QDF_STATUS wlan_objmgr_psoc_peer_detach(struct wlan_objmgr_psoc *psoc,
827 						struct wlan_objmgr_peer *peer)
828 {
829 	struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr;
830 	uint8_t hash_index;
831 
832 	wlan_psoc_obj_lock(psoc);
833 	/* if list is empty, return */
834 	if (objmgr->wlan_peer_count == 0) {
835 		wlan_psoc_obj_unlock(psoc);
836 		return QDF_STATUS_E_FAILURE;
837 	}
838 	/* Get hash index, to locate the actual peer list */
839 	hash_index = WLAN_PEER_HASH(peer->macaddr);
840 	/* removes the peer from peer_list */
841 	if (wlan_obj_psoc_peerlist_remove_peer(
842 				&objmgr->peer_list.peer_hash[hash_index],
843 						peer) ==
844 				QDF_STATUS_E_FAILURE) {
845 		wlan_psoc_obj_unlock(psoc);
846 		qdf_print("%s: Failed to detach peer\n", __func__);
847 		return QDF_STATUS_E_FAILURE;
848 	}
849 	/* Decrement peer count */
850 	objmgr->wlan_peer_count--;
851 
852 	wlan_psoc_obj_unlock(psoc);
853 	return QDF_STATUS_SUCCESS;
854 }
855 
856 struct wlan_objmgr_peer *wlan_objmgr_find_peer(
857 			struct wlan_objmgr_psoc *psoc, uint8_t *macaddr)
858 {
859 	struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr;
860 	uint8_t hash_index;
861 	struct wlan_objmgr_peer *peer = NULL;
862 	struct wlan_peer_list *peer_list;
863 
864 	wlan_psoc_obj_lock(psoc);
865 	/* List is empty, return NULL */
866 	if (objmgr->wlan_peer_count == 0) {
867 		wlan_psoc_obj_unlock(psoc);
868 		return NULL;
869 	}
870 	/* reduce the search window, with hash key */
871 	hash_index = WLAN_PEER_HASH(macaddr);
872 	peer_list = &objmgr->peer_list;
873 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
874 	/* Iterate through peer list, get peer */
875 	peer = wlan_obj_psoc_peerlist_get_peer(
876 		&peer_list->peer_hash[hash_index], macaddr);
877 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
878 	wlan_psoc_obj_unlock(psoc);
879 	return peer;
880 }
881