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