xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_pdev_obj.c (revision e1d3d092f61a07549ab97f6f1f0c86554e0c642f)
1 /*
2  * Copyright (c) 2016-2017 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 #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 "wlan_objmgr_global_obj_i.h"
29 #include "wlan_objmgr_psoc_obj_i.h"
30 #include "wlan_objmgr_pdev_obj_i.h"
31 
32 
33 /**
34  ** APIs to Create/Delete Global object APIs
35  */
36 static QDF_STATUS wlan_objmgr_pdev_object_status(
37 		struct wlan_objmgr_pdev *pdev)
38 {
39 	uint8_t id;
40 	QDF_STATUS status = QDF_STATUS_SUCCESS;
41 
42 	wlan_pdev_obj_lock(pdev);
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 (pdev->obj_status[id] == QDF_STATUS_COMP_DISABLED) {
47 			continue;
48 		/* If component operates in Async, status is Partially created,
49 			break */
50 		} else if (pdev->obj_status[id] == QDF_STATUS_COMP_ASYNC) {
51 			if (pdev->pdev_comp_priv_obj[id] == NULL) {
52 				status = QDF_STATUS_COMP_ASYNC;
53 				break;
54 			}
55 		/* If component failed to allocate its object, treat it as
56 			failure, complete object need to be cleaned up */
57 		} else if ((pdev->obj_status[id] == QDF_STATUS_E_NOMEM) ||
58 			(pdev->obj_status[id] == QDF_STATUS_E_FAILURE)) {
59 			status = QDF_STATUS_E_FAILURE;
60 			break;
61 		}
62 	}
63 	wlan_pdev_obj_unlock(pdev);
64 	return status;
65 }
66 
67 static QDF_STATUS wlan_objmgr_pdev_obj_free(struct wlan_objmgr_pdev *pdev)
68 {
69 	/* Detach PDEV from PSOC PDEV's list */
70 	if (wlan_objmgr_psoc_pdev_detach(pdev->pdev_objmgr.wlan_psoc, pdev) ==
71 						QDF_STATUS_E_FAILURE) {
72 		qdf_print("%s: PSOC PDEV detach failed\n",  __func__);
73 		return QDF_STATUS_E_FAILURE;
74 	}
75 	qdf_spinlock_destroy(&pdev->pdev_lock);
76 	qdf_mem_free(pdev);
77 
78 	return QDF_STATUS_SUCCESS;
79 }
80 
81 struct wlan_objmgr_pdev *wlan_objmgr_pdev_obj_create(
82 			struct wlan_objmgr_psoc *psoc,
83 			struct pdev_osif_priv *osdev_priv)
84 {
85 	struct wlan_objmgr_pdev *pdev;
86 	uint8_t id;
87 	wlan_objmgr_pdev_create_handler handler;
88 	wlan_objmgr_pdev_status_handler s_handler;
89 	void *arg;
90 	QDF_STATUS obj_status;
91 
92 	if (psoc == NULL) {
93 		qdf_print("%s:psoc is NULL\n", __func__);
94 		return NULL;
95 	}
96 	/* Allocate PDEV object's memory */
97 	pdev = qdf_mem_malloc(sizeof(*pdev));
98 	if (pdev == NULL) {
99 		qdf_print("%s:pdev alloc failed\n", __func__);
100 		return NULL;
101 	}
102 	/* Attach PDEV with PSOC */
103 	if (wlan_objmgr_psoc_pdev_attach(psoc, pdev)
104 				!= QDF_STATUS_SUCCESS) {
105 		qdf_print("%s:pdev psoc attach failed\n", __func__);
106 		qdf_mem_free(pdev);
107 		return NULL;
108 	}
109 	/* Save PSOC object pointer in PDEV */
110 	wlan_pdev_set_psoc(pdev, psoc);
111 	/* Initialize PDEV spinlock */
112 	qdf_spinlock_create(&pdev->pdev_lock);
113 	/* Initialize PDEV's VDEV list, assign default values */
114 	qdf_list_create(&pdev->pdev_objmgr.wlan_vdev_list,
115 			WLAN_UMAC_PDEV_MAX_VDEVS);
116 	pdev->pdev_objmgr.wlan_vdev_count = 0;
117 	pdev->pdev_objmgr.max_vdev_count = WLAN_UMAC_PDEV_MAX_VDEVS;
118 	/* Save HDD/OSIF pointer */
119 	pdev->pdev_nif.pdev_ospriv = osdev_priv;
120 	qdf_atomic_init(&pdev->pdev_objmgr.ref_cnt);
121 	wlan_objmgr_pdev_get_ref(pdev, WLAN_OBJMGR_ID);
122 	/* Invoke registered create handlers */
123 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
124 		handler = g_umac_glb_obj->pdev_create_handler[id];
125 		arg = g_umac_glb_obj->pdev_create_handler_arg[id];
126 		if (handler != NULL)
127 			pdev->obj_status[id] = handler(pdev, arg);
128 		else
129 			pdev->obj_status[id] = QDF_STATUS_COMP_DISABLED;
130 	}
131 	/* Derive object status */
132 	obj_status = wlan_objmgr_pdev_object_status(pdev);
133 
134 	if (obj_status == QDF_STATUS_SUCCESS) {
135 		/* Object status is SUCCESS, Object is created */
136 		pdev->obj_state = WLAN_OBJ_STATE_CREATED;
137 		/* Invoke component registered status handlers */
138 		for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
139 			s_handler = g_umac_glb_obj->pdev_status_handler[id];
140 			arg = g_umac_glb_obj->pdev_status_handler_arg[id];
141 			if (s_handler != NULL) {
142 				s_handler(pdev, arg,
143 					  QDF_STATUS_SUCCESS);
144 			}
145 		}
146 	/* Few components operates in Asynchrous communction, Object state
147 	partially created */
148 	} else if (obj_status == QDF_STATUS_COMP_ASYNC) {
149 		pdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED;
150 	/* Component object failed to be created, clean up the object */
151 	} else if (obj_status == QDF_STATUS_E_FAILURE) {
152 		/* Clean up the psoc */
153 		qdf_print("%s: PDEV component objects allocation failed\n",
154 			  __func__);
155 		wlan_objmgr_pdev_obj_delete(pdev);
156 		return NULL;
157 	}
158 	return pdev;
159 }
160 EXPORT_SYMBOL(wlan_objmgr_pdev_obj_create);
161 
162 static QDF_STATUS wlan_objmgr_pdev_obj_destroy(struct wlan_objmgr_pdev *pdev)
163 {
164 	uint8_t id;
165 	wlan_objmgr_pdev_destroy_handler handler;
166 	QDF_STATUS obj_status;
167 	void *arg;
168 
169 	if (pdev == NULL) {
170 		qdf_print("%s:pdev is NULL\n", __func__);
171 		return QDF_STATUS_E_FAILURE;
172 	}
173 
174 	if (pdev->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) {
175 		qdf_print("%s:pdev object delete is not invoked\n", __func__);
176 		WLAN_OBJMGR_BUG(0);
177 	}
178 
179 	/* Invoke registered destroy handlers */
180 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
181 		handler = g_umac_glb_obj->pdev_destroy_handler[id];
182 		arg = g_umac_glb_obj->pdev_destroy_handler_arg[id];
183 		if (handler != NULL)
184 			pdev->obj_status[id] = handler(pdev, arg);
185 		else
186 			pdev->obj_status[id] = QDF_STATUS_COMP_DISABLED;
187 	}
188 	/* Derive object status */
189 	obj_status = wlan_objmgr_pdev_object_status(pdev);
190 
191 	if (obj_status == QDF_STATUS_E_FAILURE) {
192 		qdf_print("%s: PDEV component objects destroy failed\n",
193 			  __func__);
194 		/* Ideally should not happen */
195 		/* This leads to memleak ??? how to handle */
196 		QDF_BUG(0);
197 		return QDF_STATUS_E_FAILURE;
198 	}
199 	/* Deletion is in progress */
200 	if (obj_status == QDF_STATUS_COMP_ASYNC) {
201 		pdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED;
202 		return QDF_STATUS_COMP_ASYNC;
203 	}
204 
205 	/* Free PDEV object */
206 	return wlan_objmgr_pdev_obj_free(pdev);
207 }
208 
209 QDF_STATUS wlan_objmgr_pdev_obj_delete(struct wlan_objmgr_pdev *pdev)
210 {
211 	if (pdev == NULL) {
212 		qdf_print("%s:pdev is NULL\n", __func__);
213 		return QDF_STATUS_E_FAILURE;
214 	}
215 	/*
216 	 * Update PDEV object state to LOGICALLY DELETED
217 	 * It prevents further access of this object
218 	 */
219 	wlan_pdev_obj_lock(pdev);
220 	pdev->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED;
221 	wlan_pdev_obj_unlock(pdev);
222 	wlan_objmgr_pdev_release_ref(pdev, WLAN_OBJMGR_ID);
223 
224 	return QDF_STATUS_SUCCESS;
225 }
226 EXPORT_SYMBOL(wlan_objmgr_pdev_obj_delete);
227 
228 /**
229  ** APIs to attach/detach component objects
230  */
231 QDF_STATUS wlan_objmgr_pdev_component_obj_attach(
232 		struct wlan_objmgr_pdev *pdev,
233 		enum wlan_umac_comp_id id,
234 		void *comp_priv_obj,
235 		QDF_STATUS status)
236 {
237 	uint8_t i;
238 	wlan_objmgr_pdev_status_handler s_hlr;
239 	void *a;
240 	QDF_STATUS obj_status;
241 
242 	/* component id is invalid */
243 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
244 		qdf_print("%s: component-id %d is not supported\n",
245 			  __func__, id);
246 		return QDF_STATUS_MAXCOMP_FAIL;
247 	}
248 	wlan_pdev_obj_lock(pdev);
249 	/* If there is a valid entry, return failure */
250 	if (pdev->pdev_comp_priv_obj[id] != NULL) {
251 		qdf_print("%s: component-%d already have valid pointer\n",
252 			  __func__, id);
253 		wlan_pdev_obj_unlock(pdev);
254 		return QDF_STATUS_E_FAILURE;
255 	}
256 	/* Save component's pointer and status */
257 	pdev->pdev_comp_priv_obj[id] = comp_priv_obj;
258 	pdev->obj_status[id] = status;
259 
260 	wlan_pdev_obj_unlock(pdev);
261 
262 	if (pdev->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED)
263 		return QDF_STATUS_SUCCESS;
264 	/**
265 	 * If PDEV object status is partially created means, this API is
266 	 * invoked with differnt context, this block should be executed for
267 	 * async components only
268 	 */
269 	/* Derive status */
270 	obj_status = wlan_objmgr_pdev_object_status(pdev);
271 	/* STATUS_SUCCESS means, object is CREATED */
272 	if (obj_status == QDF_STATUS_SUCCESS)
273 		pdev->obj_state = WLAN_OBJ_STATE_CREATED;
274 	/* update state as CREATION failed, caller has to delete the
275 	PDEV object */
276 	else if (obj_status == QDF_STATUS_E_FAILURE)
277 		pdev->obj_state = WLAN_OBJ_STATE_CREATION_FAILED;
278 	/* Notify components about the CREATION success/failure */
279 	if ((obj_status == QDF_STATUS_SUCCESS) ||
280 	    (obj_status == QDF_STATUS_E_FAILURE)) {
281 		/* nofity object status */
282 		for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) {
283 			s_hlr = g_umac_glb_obj->pdev_status_handler[i];
284 			a = g_umac_glb_obj->pdev_status_handler_arg[i];
285 			if (s_hlr != NULL)
286 				s_hlr(pdev, a, obj_status);
287 		}
288 	}
289 	return QDF_STATUS_SUCCESS;
290 }
291 EXPORT_SYMBOL(wlan_objmgr_pdev_component_obj_attach);
292 
293 QDF_STATUS wlan_objmgr_pdev_component_obj_detach(
294 		struct wlan_objmgr_pdev *pdev,
295 		enum wlan_umac_comp_id id,
296 		void *comp_priv_obj)
297 {
298 	QDF_STATUS obj_status;
299 
300 	/* component id is invalid */
301 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
302 		return QDF_STATUS_MAXCOMP_FAIL;
303 
304 	wlan_pdev_obj_lock(pdev);
305 	/* If there is a invalid entry, return failure */
306 	if (pdev->pdev_comp_priv_obj[id] != comp_priv_obj) {
307 		pdev->obj_status[id] = QDF_STATUS_E_FAILURE;
308 		wlan_pdev_obj_unlock(pdev);
309 		return QDF_STATUS_E_FAILURE;
310 	}
311 	/* Reset pointers to NULL, update the status*/
312 	pdev->pdev_comp_priv_obj[id] = NULL;
313 	pdev->obj_status[id] = QDF_STATUS_SUCCESS;
314 	wlan_pdev_obj_unlock(pdev);
315 
316 	/* If PDEV object status is partially destroyed means, this API is
317 	invoked with differnt context, this block should be executed for async
318 	components only */
319 	if ((pdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) ||
320 	    (pdev->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) {
321 		/* Derive object status */
322 		obj_status = wlan_objmgr_pdev_object_status(pdev);
323 		if (obj_status == QDF_STATUS_SUCCESS) {
324 			/*Update the status as Deleted, if full object
325 				deletion is in progress */
326 			if (pdev->obj_state ==
327 				WLAN_OBJ_STATE_PARTIALLY_DELETED)
328 				pdev->obj_state = WLAN_OBJ_STATE_DELETED;
329 			/* Move to creation state, since this component
330 			deletion alone requested */
331 			if (pdev->obj_state ==
332 				WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
333 				pdev->obj_state = WLAN_OBJ_STATE_CREATED;
334 		/* Object status is failure */
335 		} else if (obj_status == QDF_STATUS_E_FAILURE) {
336 			/*Update the status as Deletion failed, if full object
337 				deletion is in progress */
338 			if (pdev->obj_state ==
339 					WLAN_OBJ_STATE_PARTIALLY_DELETED)
340 				pdev->obj_state =
341 					WLAN_OBJ_STATE_DELETION_FAILED;
342 			/* Move to creation state, since this component
343 			deletion alone requested (do not block other
344 			components)*/
345 			if (pdev->obj_state ==
346 					WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
347 				pdev->obj_state = WLAN_OBJ_STATE_CREATED;
348 		}
349 
350 		/* Delete pdev object */
351 		if ((obj_status == QDF_STATUS_SUCCESS) &&
352 		    (pdev->obj_state == WLAN_OBJ_STATE_DELETED)) {
353 			/* Free PDEV object */
354 			return wlan_objmgr_pdev_obj_free(pdev);
355 		}
356 	}
357 	return QDF_STATUS_SUCCESS;
358 }
359 EXPORT_SYMBOL(wlan_objmgr_pdev_component_obj_detach);
360 
361 /**
362  ** APIs to operations on pdev objects
363  */
364 static void wlan_objmgr_pdev_vdev_iterate_peers(struct wlan_objmgr_pdev *pdev,
365 				struct wlan_objmgr_vdev *vdev,
366 				wlan_objmgr_pdev_op_handler handler,
367 				void *arg, uint8_t lock_free_op,
368 				wlan_objmgr_ref_dbgid dbg_id)
369 {
370 	qdf_list_t *peer_list = NULL;
371 	struct wlan_objmgr_peer *peer = NULL;
372 	struct wlan_objmgr_peer *peer_next = NULL;
373 
374 	/* Iterating through vdev's peer list, so lock is
375 		needed */
376 	if (!lock_free_op)
377 		wlan_vdev_obj_lock(vdev);
378 	/* Get peer list of the vdev */
379 	peer_list = &vdev->vdev_objmgr.wlan_peer_list;
380 	if (peer_list != NULL) {
381 		peer = wlan_vdev_peer_list_peek_head(peer_list);
382 		while (peer != NULL) {
383 			/* Get next peer pointer */
384 			peer_next = wlan_peer_get_next_peer_of_vdev(peer_list,
385 								    peer);
386 			/* Increment ref count, to hold the
387 				peer pointer */
388 			if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) ==
389 					QDF_STATUS_SUCCESS) {
390 				/* Invoke the handler */
391 				handler(pdev, (void *)peer, arg);
392 				wlan_objmgr_peer_release_ref(peer, dbg_id);
393 			}
394 			peer = peer_next;
395 		}
396 	}
397 	if (!lock_free_op)
398 		wlan_vdev_obj_unlock(vdev);
399 }
400 
401 QDF_STATUS wlan_objmgr_pdev_iterate_obj_list(
402 		struct wlan_objmgr_pdev *pdev,
403 		enum wlan_objmgr_obj_type obj_type,
404 		wlan_objmgr_pdev_op_handler handler,
405 		void *arg, uint8_t lock_free_op,
406 		wlan_objmgr_ref_dbgid dbg_id)
407 {
408 	struct wlan_objmgr_pdev_objmgr *objmgr = &pdev->pdev_objmgr;
409 	qdf_list_t *vdev_list = NULL;
410 	struct wlan_objmgr_vdev *vdev = NULL;
411 	struct wlan_objmgr_vdev *vdev_next = NULL;
412 
413 	/* If caller requests for lock free opeation, do not acquire
414 		handler will handle the synchronization*/
415 	if (!lock_free_op)
416 		wlan_pdev_obj_lock(pdev);
417 	/* VDEV list */
418 	vdev_list = &objmgr->wlan_vdev_list;
419 	switch (obj_type) {
420 	case WLAN_VDEV_OP:
421 		/* Iterate through all VDEV object, and invoke handler for each
422 			VDEV object */
423 		vdev = wlan_pdev_vdev_list_peek_head(vdev_list);
424 		while (vdev != NULL) {
425 			/*
426 			 * Get next vdev (handler can be invoked for
427 			 * vdev deletion also
428 			 */
429 			vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list,
430 						vdev);
431 			if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) ==
432 						QDF_STATUS_SUCCESS) {
433 				handler(pdev, (void *)vdev, arg);
434 				wlan_objmgr_vdev_release_ref(vdev, dbg_id);
435 			}
436 			vdev = vdev_next;
437 		}
438 		break;
439 	case WLAN_PEER_OP:
440 		vdev = wlan_pdev_vdev_list_peek_head(vdev_list);
441 		while (vdev != NULL) {
442 			/* Get Next VDEV */
443 			vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list,
444 						vdev);
445 			if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) ==
446 						QDF_STATUS_SUCCESS) {
447 				wlan_objmgr_pdev_vdev_iterate_peers(pdev, vdev,
448 								handler, arg,
449 								lock_free_op,
450 								dbg_id);
451 				wlan_objmgr_vdev_release_ref(vdev, dbg_id);
452 			}
453 			vdev = vdev_next;
454 		}
455 		break;
456 	default:
457 		break;
458 	}
459 	if (!lock_free_op)
460 		wlan_pdev_obj_unlock(pdev);
461 
462 	return QDF_STATUS_SUCCESS;
463 }
464 EXPORT_SYMBOL(wlan_objmgr_pdev_iterate_obj_list);
465 
466 QDF_STATUS wlan_objmgr_trigger_pdev_comp_priv_object_creation(
467 		struct wlan_objmgr_pdev *pdev,
468 		enum wlan_umac_comp_id id)
469 {
470 	wlan_objmgr_pdev_create_handler handler;
471 	void *arg;
472 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
473 
474 	/* Component id is invalid */
475 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
476 		return QDF_STATUS_MAXCOMP_FAIL;
477 
478 	wlan_pdev_obj_lock(pdev);
479 	/* If component object is already created, delete old
480 		component object, then invoke creation */
481 	if (pdev->pdev_comp_priv_obj[id] != NULL) {
482 		wlan_pdev_obj_unlock(pdev);
483 		return QDF_STATUS_E_FAILURE;
484 	}
485 	wlan_pdev_obj_unlock(pdev);
486 
487 	/* Invoke registered create handlers */
488 	handler = g_umac_glb_obj->pdev_create_handler[id];
489 	arg = g_umac_glb_obj->pdev_create_handler_arg[id];
490 	if (handler != NULL)
491 		pdev->obj_status[id] = handler(pdev, arg);
492 	else
493 		return QDF_STATUS_E_FAILURE;
494 	/* If object status is created, then only handle this object status */
495 	if (pdev->obj_state == WLAN_OBJ_STATE_CREATED) {
496 		/* Derive object status */
497 		obj_status = wlan_objmgr_pdev_object_status(pdev);
498 		/* Move PDEV object state to Partially created state */
499 		if (obj_status == QDF_STATUS_COMP_ASYNC) {
500 			/*TODO atomic */
501 			pdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED;
502 		}
503 	}
504 	return obj_status;
505 }
506 
507 QDF_STATUS wlan_objmgr_trigger_pdev_comp_priv_object_deletion(
508 		struct wlan_objmgr_pdev *pdev,
509 		enum wlan_umac_comp_id id)
510 {
511 	wlan_objmgr_pdev_destroy_handler handler;
512 	void *arg;
513 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
514 
515 	/* component id is invalid */
516 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
517 		return QDF_STATUS_MAXCOMP_FAIL;
518 
519 	wlan_pdev_obj_lock(pdev);
520 	/* Component object was never created, invalid operation */
521 	if (pdev->pdev_comp_priv_obj[id] == NULL) {
522 		wlan_pdev_obj_unlock(pdev);
523 		return QDF_STATUS_E_FAILURE;
524 	}
525 	wlan_pdev_obj_unlock(pdev);
526 
527 	/* Invoke registered create handlers */
528 	handler = g_umac_glb_obj->pdev_destroy_handler[id];
529 	arg = g_umac_glb_obj->pdev_destroy_handler_arg[id];
530 	if (handler != NULL)
531 		pdev->obj_status[id] = handler(pdev, arg);
532 	else
533 		return QDF_STATUS_E_FAILURE;
534 
535 	/* If object status is created, then only handle this object status */
536 	if (pdev->obj_state == WLAN_OBJ_STATE_CREATED) {
537 		obj_status = wlan_objmgr_pdev_object_status(pdev);
538 		/* move object state to DEL progress */
539 		if (obj_status == QDF_STATUS_COMP_ASYNC)
540 			pdev->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS;
541 	}
542 	return obj_status;
543 }
544 
545 static void wlan_obj_pdev_vdevlist_add_tail(qdf_list_t *obj_list,
546 				struct wlan_objmgr_vdev *obj)
547 {
548 	qdf_list_insert_back(obj_list, &obj->vdev_node);
549 }
550 
551 static QDF_STATUS wlan_obj_pdev_vdevlist_remove_vdev(
552 				qdf_list_t *obj_list,
553 				struct wlan_objmgr_vdev *vdev)
554 {
555 	qdf_list_node_t *vdev_node = NULL;
556 
557 	if (vdev == NULL)
558 		return QDF_STATUS_E_FAILURE;
559 	/* get vdev list node element */
560 	vdev_node = &vdev->vdev_node;
561 	/* list is empty, return failure */
562 	if (qdf_list_remove_node(obj_list, vdev_node) != QDF_STATUS_SUCCESS)
563 		return QDF_STATUS_E_FAILURE;
564 
565 	return QDF_STATUS_SUCCESS;
566 }
567 
568 QDF_STATUS wlan_objmgr_pdev_vdev_attach(struct wlan_objmgr_pdev *pdev,
569 					struct wlan_objmgr_vdev *vdev)
570 {
571 	struct wlan_objmgr_pdev_objmgr *objmgr = &pdev->pdev_objmgr;
572 
573 	wlan_pdev_obj_lock(pdev);
574 	/* If Max vdev count exceeds, return failure */
575 	if (objmgr->wlan_vdev_count > objmgr->max_vdev_count) {
576 		wlan_pdev_obj_unlock(pdev);
577 		return QDF_STATUS_E_FAILURE;
578 	}
579 	/* Add vdev to pdev's vdev list */
580 	wlan_obj_pdev_vdevlist_add_tail(&objmgr->wlan_vdev_list, vdev);
581 	/* Increment pdev ref count to make sure it won't be destroyed before */
582 	wlan_objmgr_pdev_get_ref(pdev, WLAN_OBJMGR_ID);
583 	/* Increment vdev count of pdev */
584 	objmgr->wlan_vdev_count++;
585 	wlan_pdev_obj_unlock(pdev);
586 
587 	return QDF_STATUS_SUCCESS;
588 }
589 
590 QDF_STATUS wlan_objmgr_pdev_vdev_detach(struct wlan_objmgr_pdev *pdev,
591 				struct wlan_objmgr_vdev *vdev)
592 {
593 	struct wlan_objmgr_pdev_objmgr *objmgr = &pdev->pdev_objmgr;
594 
595 	wlan_pdev_obj_lock(pdev);
596 	/* if vdev count is 0, return failure */
597 	if (objmgr->wlan_vdev_count == 0) {
598 		wlan_pdev_obj_unlock(pdev);
599 		return QDF_STATUS_E_FAILURE;
600 	}
601 	/* remove vdev from pdev's vdev list */
602 	wlan_obj_pdev_vdevlist_remove_vdev(&objmgr->wlan_vdev_list, vdev);
603 	/* decrement vdev count */
604 	objmgr->wlan_vdev_count--;
605 	wlan_pdev_obj_unlock(pdev);
606 	/* Decrement pdev ref count since vdev is releasing reference */
607 	wlan_objmgr_pdev_release_ref(pdev, WLAN_OBJMGR_ID);
608 	return QDF_STATUS_SUCCESS;
609 }
610 
611 struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev(
612 			struct wlan_objmgr_pdev *pdev, uint8_t vdev_id,
613 			wlan_objmgr_ref_dbgid dbg_id)
614 {
615 	struct wlan_objmgr_vdev *vdev;
616 	struct wlan_objmgr_vdev *vdev_next;
617 	struct wlan_objmgr_pdev_objmgr *objmgr;
618 	qdf_list_t *vdev_list;
619 
620 	wlan_pdev_obj_lock(pdev);
621 
622 	objmgr = &pdev->pdev_objmgr;
623 	vdev_list = &objmgr->wlan_vdev_list;
624 	/* Get first vdev */
625 	vdev = wlan_pdev_vdev_list_peek_head(vdev_list);
626 	/* Iterate through pdev's vdev list, till vdev id matches with
627 	entry of vdev list */
628 	while (vdev != NULL) {
629 		if (wlan_vdev_get_id(vdev) == vdev_id) {
630 			if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) !=
631 							QDF_STATUS_SUCCESS)
632 				vdev = NULL;
633 
634 			wlan_pdev_obj_unlock(pdev);
635 			return vdev;
636 		}
637 		/* get next vdev */
638 		vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev);
639 		vdev = vdev_next;
640 	}
641 	wlan_pdev_obj_unlock(pdev);
642 	return NULL;
643 }
644 EXPORT_SYMBOL(wlan_objmgr_get_vdev_by_id_from_pdev);
645 
646 struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev_no_state(
647 			struct wlan_objmgr_pdev *pdev, uint8_t vdev_id,
648 			wlan_objmgr_ref_dbgid dbg_id)
649 {
650 	struct wlan_objmgr_vdev *vdev;
651 	struct wlan_objmgr_vdev *vdev_next;
652 	struct wlan_objmgr_pdev_objmgr *objmgr;
653 	qdf_list_t *vdev_list;
654 
655 	wlan_pdev_obj_lock(pdev);
656 
657 	objmgr = &pdev->pdev_objmgr;
658 	vdev_list = &objmgr->wlan_vdev_list;
659 	/* Get first vdev */
660 	vdev = wlan_pdev_vdev_list_peek_head(vdev_list);
661 	/**
662 	 * Iterate through pdev's vdev list, till vdev id matches with
663 	 * entry of vdev list
664 	 */
665 	while (vdev != NULL) {
666 		if (wlan_vdev_get_id(vdev) == vdev_id) {
667 			wlan_objmgr_vdev_get_ref(vdev, dbg_id);
668 			wlan_pdev_obj_unlock(pdev);
669 
670 			return vdev;
671 		}
672 		/* get next vdev */
673 		vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev);
674 		vdev = vdev_next;
675 	}
676 	wlan_pdev_obj_unlock(pdev);
677 
678 	return NULL;
679 }
680 EXPORT_SYMBOL(wlan_objmgr_get_vdev_by_id_from_pdev_no_state);
681 
682 struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev(
683 		struct wlan_objmgr_pdev *pdev, uint8_t *macaddr,
684 		wlan_objmgr_ref_dbgid dbg_id)
685 {
686 	struct wlan_objmgr_vdev *vdev;
687 	struct wlan_objmgr_vdev *vdev_next;
688 	struct wlan_objmgr_pdev_objmgr *objmgr;
689 	qdf_list_t *vdev_list;
690 
691 	wlan_pdev_obj_lock(pdev);
692 	objmgr = &pdev->pdev_objmgr;
693 	vdev_list = &objmgr->wlan_vdev_list;
694 	/* Get first vdev */
695 	vdev = wlan_pdev_vdev_list_peek_head(vdev_list);
696 	/* Iterate through pdev's vdev list, till vdev macaddr matches with
697 	entry of vdev list */
698 	while (vdev != NULL) {
699 		if (WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), macaddr)
700 					== QDF_STATUS_SUCCESS) {
701 			if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) !=
702 							QDF_STATUS_SUCCESS)
703 				vdev = NULL;
704 
705 			wlan_pdev_obj_unlock(pdev);
706 			return vdev;
707 		}
708 		/* get next vdev */
709 		vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev);
710 		vdev = vdev_next;
711 	}
712 	wlan_pdev_obj_unlock(pdev);
713 
714 	return NULL;
715 }
716 
717 struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev_no_state(
718 		struct wlan_objmgr_pdev *pdev, uint8_t *macaddr,
719 		wlan_objmgr_ref_dbgid dbg_id)
720 {
721 	struct wlan_objmgr_vdev *vdev;
722 	struct wlan_objmgr_vdev *vdev_next;
723 	struct wlan_objmgr_pdev_objmgr *objmgr;
724 	qdf_list_t *vdev_list;
725 
726 	wlan_pdev_obj_lock(pdev);
727 	objmgr = &pdev->pdev_objmgr;
728 	vdev_list = &objmgr->wlan_vdev_list;
729 	/* Get first vdev */
730 	vdev = wlan_pdev_vdev_list_peek_head(vdev_list);
731 	/* Iterate through pdev's vdev list, till vdev macaddr matches with
732 	entry of vdev list */
733 	while (vdev != NULL) {
734 		if (WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), macaddr)
735 					== QDF_STATUS_SUCCESS) {
736 			wlan_objmgr_vdev_get_ref(vdev, dbg_id);
737 			wlan_pdev_obj_unlock(pdev);
738 
739 			return vdev;
740 		}
741 		/* get next vdev */
742 		vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev);
743 		vdev = vdev_next;
744 	}
745 	wlan_pdev_obj_unlock(pdev);
746 
747 	return NULL;
748 }
749 
750 void *wlan_objmgr_pdev_get_comp_private_obj(
751 		struct wlan_objmgr_pdev *pdev,
752 		enum wlan_umac_comp_id id)
753 {
754 	void *comp_priv_obj;
755 
756 	/* This API is invoked with lock acquired, don't add any debug prints */
757 
758 	/* component id is invalid */
759 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
760 		QDF_BUG(0);
761 		return NULL;
762 	}
763 
764 	if (pdev == NULL) {
765 		QDF_BUG(0);
766 		return NULL;
767 	}
768 
769 	comp_priv_obj = pdev->pdev_comp_priv_obj[id];
770 
771 	return comp_priv_obj;
772 }
773 EXPORT_SYMBOL(wlan_objmgr_pdev_get_comp_private_obj);
774 
775 void wlan_objmgr_pdev_get_ref(struct wlan_objmgr_pdev *pdev,
776 					wlan_objmgr_ref_dbgid id)
777 {
778 	if (pdev == NULL) {
779 		qdf_print("%s: pdev obj is NULL\n", __func__);
780 		QDF_ASSERT(0);
781 		return;
782 	}
783 	qdf_atomic_inc(&pdev->pdev_objmgr.ref_cnt);
784 	qdf_atomic_inc(&pdev->pdev_objmgr.ref_id_dbg[id]);
785 
786 	return;
787 }
788 EXPORT_SYMBOL(wlan_objmgr_pdev_get_ref);
789 
790 QDF_STATUS wlan_objmgr_pdev_try_get_ref(struct wlan_objmgr_pdev *pdev,
791 						wlan_objmgr_ref_dbgid id)
792 {
793 	if (pdev == NULL) {
794 		qdf_print("%s: pdev obj is NULL\n", __func__);
795 		QDF_ASSERT(0);
796 		return QDF_STATUS_E_FAILURE;
797 	}
798 
799 	wlan_pdev_obj_lock(pdev);
800 	if (pdev->obj_state == WLAN_OBJ_STATE_LOGICALLY_DELETED) {
801 		wlan_pdev_obj_unlock(pdev);
802 		qdf_print("%s: pdev obj is in Deletion Progress state\n",
803 			  __func__);
804 		return QDF_STATUS_E_RESOURCES;
805 	}
806 
807 	wlan_objmgr_pdev_get_ref(pdev, id);
808 	wlan_pdev_obj_unlock(pdev);
809 
810 	return QDF_STATUS_SUCCESS;
811 }
812 EXPORT_SYMBOL(wlan_objmgr_pdev_try_get_ref);
813 
814 void wlan_objmgr_pdev_release_ref(struct wlan_objmgr_pdev *pdev,
815 						wlan_objmgr_ref_dbgid id)
816 {
817 	if (pdev == NULL) {
818 		qdf_print("%s: pdev obj is NULL\n", __func__);
819 		QDF_ASSERT(0);
820 		return;
821 	}
822 
823 	if (!qdf_atomic_read(&pdev->pdev_objmgr.ref_id_dbg[id])) {
824 		qdf_print("%s: pdev ref cnt was not taken by %d\n",
825 			  __func__, id);
826 		wlan_objmgr_print_ref_ids(pdev->pdev_objmgr.ref_id_dbg);
827 		WLAN_OBJMGR_BUG(0);
828 	}
829 
830 	if (!qdf_atomic_read(&pdev->pdev_objmgr.ref_cnt)) {
831 		qdf_print("%s: pdev ref cnt is 0\n", __func__);
832 		WLAN_OBJMGR_BUG(0);
833 		return;
834 	}
835 
836 	qdf_atomic_dec(&pdev->pdev_objmgr.ref_id_dbg[id]);
837 	/* Decrement ref count, free pdev, if ref count == 0 */
838 	if (qdf_atomic_dec_and_test(&pdev->pdev_objmgr.ref_cnt))
839 		wlan_objmgr_pdev_obj_destroy(pdev);
840 
841 	return;
842 }
843 EXPORT_SYMBOL(wlan_objmgr_pdev_release_ref);
844