diff --git a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_psoc_obj.h b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_psoc_obj.h index e4bee9d5265b..d676ceec2e1c 100644 --- a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_psoc_obj.h +++ b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_psoc_obj.h @@ -378,6 +378,7 @@ typedef void (*wlan_objmgr_op_handler)(struct wlan_objmgr_psoc *psoc, /** * wlan_objmgr_iterate_obj_list() - iterate through all psoc objects + * (CREATED state) * @psoc: PSOC object * @obj_type: PDEV_OP/VDEV_OP/PEER_OP * @handler: the handler will be called for each object of requested type @@ -400,6 +401,30 @@ QDF_STATUS wlan_objmgr_iterate_obj_list( void *arg, uint8_t lock_free_op, wlan_objmgr_ref_dbgid dbg_id); +/** + * wlan_objmgr_iterate_obj_list_all() - iterate through all psoc objects + * @psoc: PSOC object + * @obj_type: PDEV_OP/VDEV_OP/PEER_OP + * @handler: the handler will be called for each object of requested type + * the handler should be implemented to perform required operation + * @arg: agruments passed by caller + * @lock_free_op: This gives provision to run this API with out lock protected + * It would be useful, for operations like Obj Delete, where + * lock should not be taken by caller. + * @dbg_id: id of the caller + * + * API to be used for performing the operations on all PDEV/VDEV/PEER objects + * of psoc + * + * Return: SUCCESS/FAILURE + */ +QDF_STATUS wlan_objmgr_iterate_obj_list_all( + struct wlan_objmgr_psoc *psoc, + enum wlan_objmgr_obj_type obj_type, + wlan_objmgr_op_handler handler, + void *arg, uint8_t lock_free_op, + wlan_objmgr_ref_dbgid dbg_id); + /** * wlan_objmgr_free_all_objects_per_psoc() - free all psoc objects * @psoc: PSOC object diff --git a/umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj.c b/umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj.c index 16e73421194a..7a71ebd5c825 100644 --- a/umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj.c +++ b/umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj.c @@ -464,6 +464,85 @@ QDF_STATUS wlan_objmgr_iterate_obj_list( } EXPORT_SYMBOL(wlan_objmgr_iterate_obj_list); +QDF_STATUS wlan_objmgr_iterate_obj_list_all( + struct wlan_objmgr_psoc *psoc, + enum wlan_objmgr_obj_type obj_type, + wlan_objmgr_op_handler handler, + void *arg, uint8_t lock_free_op, + wlan_objmgr_ref_dbgid dbg_id) +{ + uint16_t obj_id; + uint8_t i; + struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr; + struct wlan_peer_list *peer_list; + qdf_list_t *obj_list; + struct wlan_objmgr_pdev *pdev; + struct wlan_objmgr_vdev *vdev; + struct wlan_objmgr_peer *peer; + struct wlan_objmgr_peer *peer_next; + + /* If caller requests for lock free opeation, do not acquire, + * handler will handle the synchronization + */ + if (!lock_free_op) + wlan_psoc_obj_lock(psoc); + + switch (obj_type) { + case WLAN_PDEV_OP: + /* Iterate through PDEV list, invoke handler for each pdev */ + for (obj_id = 0; obj_id < WLAN_UMAC_MAX_PDEVS; obj_id++) { + pdev = objmgr->wlan_pdev_list[obj_id]; + if (pdev != NULL) { + wlan_objmgr_pdev_get_ref(pdev, dbg_id); + handler(psoc, (void *)pdev, arg); + wlan_objmgr_pdev_release_ref(pdev, dbg_id); + } + } + break; + case WLAN_VDEV_OP: + /* Iterate through VDEV list, invoke handler for each vdev */ + for (obj_id = 0; obj_id < WLAN_UMAC_PSOC_MAX_VDEVS; obj_id++) { + vdev = objmgr->wlan_vdev_list[obj_id]; + if (vdev != NULL) { + wlan_objmgr_vdev_get_ref(vdev, dbg_id); + handler(psoc, vdev, arg); + wlan_objmgr_vdev_release_ref(vdev, dbg_id); + } + } + break; + case WLAN_PEER_OP: + /* Iterate through PEER list, invoke handler for each peer */ + peer_list = &objmgr->peer_list; + /* psoc lock should be taken before list lock */ + if (!lock_free_op) + qdf_spin_lock_bh(&peer_list->peer_list_lock); + /* Since peer list has sublist, iterate through sublists */ + for (i = 0; i < WLAN_PEER_HASHSIZE; i++) { + obj_list = &peer_list->peer_hash[i]; + peer = wlan_psoc_peer_list_peek_head(obj_list); + while (peer) { + /* Get next peer */ + peer_next = wlan_peer_get_next_peer_of_psoc( + obj_list, peer); + wlan_objmgr_peer_get_ref(peer, dbg_id); + handler(psoc, (void *)peer, arg); + wlan_objmgr_peer_release_ref(peer, dbg_id); + peer = peer_next; + } + } + if (!lock_free_op) + qdf_spin_unlock_bh(&peer_list->peer_list_lock); + break; + default: + break; + } + if (!lock_free_op) + wlan_psoc_obj_unlock(psoc); + + return QDF_STATUS_SUCCESS; +} +EXPORT_SYMBOL(wlan_objmgr_iterate_obj_list_all); + static void wlan_objmgr_psoc_peer_delete(struct wlan_objmgr_psoc *psoc, void *obj, void *args) { @@ -1617,15 +1696,15 @@ QDF_STATUS wlan_objmgr_print_ref_all_objects_per_psoc( struct wlan_objmgr_psoc *psoc) { qdf_print(" Ref counts of PEER\n"); - wlan_objmgr_iterate_obj_list(psoc, WLAN_PEER_OP, + wlan_objmgr_iterate_obj_list_all(psoc, WLAN_PEER_OP, wlan_objmgr_psoc_peer_ref_print, NULL, 1, WLAN_OBJMGR_ID); qdf_print(" Ref counts of VDEV\n"); - wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP, + wlan_objmgr_iterate_obj_list_all(psoc, WLAN_VDEV_OP, wlan_objmgr_psoc_vdev_ref_print, NULL, 1, WLAN_OBJMGR_ID); qdf_print(" Ref counts of PDEV\n"); - wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, + wlan_objmgr_iterate_obj_list_all(psoc, WLAN_PDEV_OP, wlan_objmgr_psoc_pdev_ref_print, NULL, 1, WLAN_OBJMGR_ID);