diff --git a/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c b/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c index c5e3447bc02b..4c67c23e5ab9 100644 --- a/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c +++ b/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c @@ -831,10 +831,10 @@ QDF_STATUS tgt_mgmt_txrx_rx_frame_handler( * scenario. */ mac_addr = (uint8_t *)wh->i_addr2; - peer = wlan_objmgr_find_peer(psoc, mac_addr); + peer = wlan_objmgr_get_peer(psoc, mac_addr, WLAN_MGMT_SB_ID); if (!peer) { mac_addr = (uint8_t *)wh->i_addr1; - peer = wlan_objmgr_find_peer(psoc, mac_addr); + peer = wlan_objmgr_get_peer(psoc, mac_addr, WLAN_MGMT_SB_ID); } /** @@ -922,7 +922,7 @@ rx_handler_mem_free: } dec_peer_ref_cnt: if (peer) - wlan_objmgr_peer_unref_peer(peer); + wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_SB_ID); return status; } @@ -994,7 +994,7 @@ no_registered_cb: * passing peer in wlan_mgmt_txrx_mgmt_frame_tx or * wlan_mgmt_txrx_beacon_frame_tx APIs. */ - wlan_objmgr_peer_unref_peer(mgmt_desc->peer); + wlan_objmgr_peer_release_ref(mgmt_desc->peer, WLAN_MGMT_NB_ID); wlan_mgmt_txrx_desc_put(mgmt_txrx_ctx, desc_id); return QDF_STATUS_SUCCESS; } diff --git a/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_utils_api.c b/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_utils_api.c index b8bbe764cc95..b9dc92e1f39f 100644 --- a/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_utils_api.c +++ b/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_utils_api.c @@ -106,17 +106,17 @@ err_desc_pool_init: } /** - * wlan_mgmt_txrx_psoc_obj_delete_notification() - called from objmgr when psoc - * is deleted + * wlan_mgmt_txrx_psoc_obj_destroy_notification() - called from objmgr when + * psoc is destroyed * @psoc: psoc context * @arg: argument * - * This function gets called from object manager when psoc is being deleted and - * deletes mgmt_txrx context, mgmt desc pool. + * This function gets called from object manager when psoc is being destroyed + * psoc deletes mgmt_txrx context, mgmt desc pool. * * Return: QDF_STATUS_SUCCESS - in case of success */ -static QDF_STATUS wlan_mgmt_txrx_psoc_obj_delete_notification( +static QDF_STATUS wlan_mgmt_txrx_psoc_obj_destroy_notification( struct wlan_objmgr_psoc *psoc, void *arg) { @@ -166,16 +166,16 @@ QDF_STATUS wlan_mgmt_txrx_init(void) goto err_psoc_create; } - status = wlan_objmgr_register_psoc_delete_handler( + status = wlan_objmgr_register_psoc_destroy_handler( WLAN_UMAC_COMP_MGMT_TXRX, - wlan_mgmt_txrx_psoc_obj_delete_notification, + wlan_mgmt_txrx_psoc_obj_destroy_notification, NULL); if (status != QDF_STATUS_SUCCESS) { - mgmt_txrx_err("Failed to register mgmt txrx obj delete handler"); + mgmt_txrx_err("Failed to register mgmt txrx obj destroy handler"); goto err_psoc_delete; } - mgmt_txrx_info("Successfully registered create and delete handlers with objmgr"); + mgmt_txrx_info("Successfully registered create and destroy handlers with objmgr"); return QDF_STATUS_SUCCESS; err_psoc_delete: @@ -194,14 +194,15 @@ QDF_STATUS wlan_mgmt_txrx_deinit(void) return QDF_STATUS_E_FAILURE; } - if (wlan_objmgr_unregister_psoc_delete_handler(WLAN_UMAC_COMP_MGMT_TXRX, - wlan_mgmt_txrx_psoc_obj_delete_notification, + if (wlan_objmgr_unregister_psoc_destroy_handler( + WLAN_UMAC_COMP_MGMT_TXRX, + wlan_mgmt_txrx_psoc_obj_destroy_notification, NULL) != QDF_STATUS_SUCCESS) { return QDF_STATUS_E_FAILURE; } - mgmt_txrx_info("Successfully unregistered create and delete handlers with objmgr"); + mgmt_txrx_info("Successfully unregistered create and destroy handlers with objmgr"); return QDF_STATUS_SUCCESS; } diff --git a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h index dbba18e5eacb..1286f46b0ef4 100644 --- a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h +++ b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -26,6 +26,7 @@ #include "qdf_list.h" #include "qdf_status.h" #include "wlan_cmn.h" +#include "qdf_atomic.h" /* No. of PSOCs can be supported */ #define WLAN_OBJMGR_MAX_DEVICES 2 @@ -40,20 +41,23 @@ /** * enum WLAN_OBJ_STATE - State of Object * @WLAN_OBJ_STATE_CREATED: All component objects are created - * @WLAN_OBJ_STATE_DELETED: All component objects are deleted + * @WLAN_OBJ_STATE_DELETED: All component objects are destroyed * @WLAN_OBJ_STATE_PARTIALLY_CREATED: Few/All component objects creation is * in progress - * @WLAN_OBJ_STATE_PARTIALLY_DELETED: Few/All component objects yet to be - * deleted + * @WLAN_OBJ_STATE_PARTIALLY_DELETED: Component objects deletion is triggered, + * they are yet to be destroyed * @WLAN_OBJ_STATE_COMP_DEL_PROGRESS: If a component is disabled run time, * and this state is used to represent the * deletion in progress after that - * component object is deleted, object + * component object is destroyed, object * state would be moved to CREATED state + * @WLAN_OBJ_STATE_LOGICALLY_DELETED: Object deletion has been initiated, + * object destroy invoked once references + * are released * @WLAN_OBJ_STATE_CREATION_FAILED: any component object is failed to be * created * @WLAN_OBJ_STATE_DELETION_FAILED: any component object is failed to be - * deleted + * destroyed */ typedef enum { WLAN_OBJ_STATE_CREATED = 0, @@ -61,8 +65,9 @@ typedef enum { WLAN_OBJ_STATE_PARTIALLY_CREATED = 2, WLAN_OBJ_STATE_PARTIALLY_DELETED = 3, WLAN_OBJ_STATE_COMP_DEL_PROGRESS = 4, - WLAN_OBJ_STATE_CREATION_FAILED = 5, - WLAN_OBJ_STATE_DELETION_FAILED = 6, + WLAN_OBJ_STATE_LOGICALLY_DELETED = 5, + WLAN_OBJ_STATE_CREATION_FAILED = 6, + WLAN_OBJ_STATE_DELETION_FAILED = 7, } WLAN_OBJ_STATE; /* Object type is assigned with value */ @@ -116,14 +121,14 @@ struct wlan_objmgr_peer; */ typedef QDF_STATUS (*wlan_objmgr_psoc_create_handler)( struct wlan_objmgr_psoc *psoc, void *arg); -typedef QDF_STATUS (*wlan_objmgr_psoc_delete_handler)( +typedef QDF_STATUS (*wlan_objmgr_psoc_destroy_handler)( struct wlan_objmgr_psoc *psoc, void *arg); typedef void (*wlan_objmgr_psoc_status_handler)(struct wlan_objmgr_psoc *psoc, void *arg, QDF_STATUS status); typedef QDF_STATUS (*wlan_objmgr_pdev_create_handler)( struct wlan_objmgr_pdev *pdev, void *arg); -typedef QDF_STATUS (*wlan_objmgr_pdev_delete_handler)( +typedef QDF_STATUS (*wlan_objmgr_pdev_destroy_handler)( struct wlan_objmgr_pdev *pdev, void *arg); typedef void (*wlan_objmgr_pdev_status_handler)( struct wlan_objmgr_pdev *pdev, void *arg, @@ -131,7 +136,7 @@ typedef void (*wlan_objmgr_pdev_status_handler)( typedef QDF_STATUS (*wlan_objmgr_vdev_create_handler)( struct wlan_objmgr_vdev *vdev, void *arg); -typedef QDF_STATUS (*wlan_objmgr_vdev_delete_handler)( +typedef QDF_STATUS (*wlan_objmgr_vdev_destroy_handler)( struct wlan_objmgr_vdev *vdev, void *arg); typedef void (*wlan_objmgr_vdev_status_handler)( struct wlan_objmgr_vdev *vdev, void *arg, @@ -139,10 +144,31 @@ typedef void (*wlan_objmgr_vdev_status_handler)( typedef QDF_STATUS (*wlan_objmgr_peer_create_handler)( struct wlan_objmgr_peer *peer, void *arg); -typedef QDF_STATUS (*wlan_objmgr_peer_delete_handler)( +typedef QDF_STATUS (*wlan_objmgr_peer_destroy_handler)( struct wlan_objmgr_peer *peer, void *arg); typedef void (*wlan_objmgr_peer_status_handler)( struct wlan_objmgr_peer *peer, void *arg, QDF_STATUS status); +/** + * enum wlan_objmgr_ref_dbgid - ref count debug id + * @WLAN_OBJMGR_ID: Object manager internal operations + * @WLAN_MLME_SB_ID: MLME Southbound operations + * @WLAN_MLME_NB_ID: MLME Northbound operations + * @WLAN_MGMT_SB_ID: MGMT Northbound operations + * @WLAN_MGMT_NB_ID: MGMT Southbound operations + */ +typedef enum { + WLAN_OBJMGR_ID = 0, + WLAN_MLME_SB_ID = 1, + WLAN_MLME_NB_ID = 2, + WLAN_MGMT_SB_ID = 3, + WLAN_MGMT_NB_ID = 4, +} wlan_objmgr_ref_dbgid; + +#ifdef WLAN_OBJMGR_DEBUG +#define WLAN_OBJMGR_BUG(val) QDF_BUG(val) +#else +#define WLAN_OBJMGR_BUG(val) +#endif #endif /* _WLAN_OBJMGR_CMN_H_*/ diff --git a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_global_obj.h b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_global_obj.h index 7a0c597a4641..ef9494b07a91 100644 --- a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_global_obj.h +++ b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_global_obj.h @@ -44,17 +44,17 @@ QDF_STATUS wlan_objmgr_global_obj_init(void); QDF_STATUS wlan_objmgr_global_obj_deinit(void); /** - * wlan_objmgr_global_obj_can_deleted() - Checks whether global object - * can be deleted + * wlan_objmgr_global_obj_can_destroyed() - Checks whether global object + * can be destroyed * * Checks the psoc table of global object, if psoc table is empty * returns the SUCCESS * - * Return: SUCCESS on can be deleted, - * FAILURE on can't be deleted + * Return: SUCCESS on can be destroyed, + * FAILURE on can't be destroyed * */ -QDF_STATUS wlan_objmgr_global_obj_can_deleted(void); +QDF_STATUS wlan_objmgr_global_obj_can_destroyed(void); /** * wlan_objmgr_register_psoc_create_handler() - register psoc create handler @@ -92,7 +92,7 @@ QDF_STATUS wlan_objmgr_unregister_psoc_create_handler( void *args); /** - * wlan_objmgr_register_psoc_delete_handler() - register delete handler + * wlan_objmgr_register_psoc_destroy_handler() - register destroy handler * @id: component id * @handler: function pointer of the component * @args: args, if component wants certain args to be passed on PSOC deletion @@ -104,13 +104,13 @@ QDF_STATUS wlan_objmgr_unregister_psoc_create_handler( * Failure (if registration fails, each failure has different error * code) */ -QDF_STATUS wlan_objmgr_register_psoc_delete_handler( +QDF_STATUS wlan_objmgr_register_psoc_destroy_handler( enum wlan_umac_comp_id id, - wlan_objmgr_psoc_delete_handler handler, + wlan_objmgr_psoc_destroy_handler handler, void *args); /** - * wlan_objmgr_unregister_psoc_delete_handler() - unregister delete handler + * wlan_objmgr_unregister_psoc_destroy_handler() - unregister destroy handler * @id: component id * @handler: function pointer of the component * @args: args, if component wants certain args to be passed on PSOC deletion @@ -121,9 +121,9 @@ QDF_STATUS wlan_objmgr_register_psoc_delete_handler( * Failure (if handler is not present, each failure has different error * code) */ -QDF_STATUS wlan_objmgr_unregister_psoc_delete_handler( +QDF_STATUS wlan_objmgr_unregister_psoc_destroy_handler( enum wlan_umac_comp_id id, - wlan_objmgr_psoc_delete_handler handler, + wlan_objmgr_psoc_destroy_handler handler, void *args); /** @@ -198,7 +198,7 @@ QDF_STATUS wlan_objmgr_unregister_pdev_create_handler( void *args); /** - * wlan_objmgr_register_pdev_delete_handler() - register pdev delete handler + * wlan_objmgr_register_pdev_destroy_handler() - register pdev destroy handler * @id: component id * @handler: function pointer of the component * @args: args, if component wants certain args to be passed on PDEV deletion @@ -210,13 +210,13 @@ QDF_STATUS wlan_objmgr_unregister_pdev_create_handler( * Failure (if registration fails, each failure has different error * code) */ -QDF_STATUS wlan_objmgr_register_pdev_delete_handler( +QDF_STATUS wlan_objmgr_register_pdev_destroy_handler( enum wlan_umac_comp_id id, - wlan_objmgr_pdev_delete_handler handler, + wlan_objmgr_pdev_destroy_handler handler, void *args); /** - * wlan_objmgr_unregister_pdev_delete_handler() - unregister pdev delete handler + * wlan_objmgr_unregister_pdev_destroy_handler() - unregister pdev destroy handler * @id: component id * @handler: function pointer of the component * @args: args, if component wants certain args to be passed on PDEV deletion @@ -227,9 +227,9 @@ QDF_STATUS wlan_objmgr_register_pdev_delete_handler( * Failure (if handler is not present, each failure has different error * code) */ -QDF_STATUS wlan_objmgr_unregister_pdev_delete_handler( +QDF_STATUS wlan_objmgr_unregister_pdev_destroy_handler( enum wlan_umac_comp_id id, - wlan_objmgr_pdev_delete_handler handler, + wlan_objmgr_pdev_destroy_handler handler, void *args); /** @@ -304,7 +304,7 @@ QDF_STATUS wlan_objmgr_unregister_vdev_create_handler( void *args); /** - * wlan_objmgr_register_vdev_delete_handler() - register vdev delete handler + * wlan_objmgr_register_vdev_destroy_handler() - register vdev destroy handler * @id: component id * @handler: function pointer of the component * @args: args, if component wants certain args to be passed on VDEV deletion @@ -316,13 +316,13 @@ QDF_STATUS wlan_objmgr_unregister_vdev_create_handler( * Failure (if registration fails, each failure has different error * code) */ -QDF_STATUS wlan_objmgr_register_vdev_delete_handler( +QDF_STATUS wlan_objmgr_register_vdev_destroy_handler( enum wlan_umac_comp_id id, - wlan_objmgr_vdev_delete_handler handler, + wlan_objmgr_vdev_destroy_handler handler, void *args); /** - * wlan_objmgr_unregister_vdev_delete_handler() - unregister vdev delete handler + * wlan_objmgr_unregister_vdev_destroy_handler() - unregister vdev destroy handler * @id: component id * @handler: function pointer of the component * @args: args, if component wants certain args to be passed on VDEV deletion @@ -333,9 +333,9 @@ QDF_STATUS wlan_objmgr_register_vdev_delete_handler( * Failure (if handler is not present, each failure has different error * code) */ -QDF_STATUS wlan_objmgr_unregister_vdev_delete_handler( +QDF_STATUS wlan_objmgr_unregister_vdev_destroy_handler( enum wlan_umac_comp_id id, - wlan_objmgr_vdev_delete_handler handler, + wlan_objmgr_vdev_destroy_handler handler, void *args); /** @@ -410,7 +410,7 @@ QDF_STATUS wlan_objmgr_unregister_peer_create_handler( void *args); /** - * wlan_objmgr_register_peer_delete_handler() - register peer delete handler + * wlan_objmgr_register_peer_destroy_handler() - register peer destroy handler * @id: component id * @handler: function pointer of the component * @args: args, if component wants certain args to be passed on PEER deletion @@ -422,13 +422,13 @@ QDF_STATUS wlan_objmgr_unregister_peer_create_handler( * Failure (if registration fails, each failure has different error * code) */ -QDF_STATUS wlan_objmgr_register_peer_delete_handler( +QDF_STATUS wlan_objmgr_register_peer_destroy_handler( enum wlan_umac_comp_id id, - wlan_objmgr_peer_delete_handler handler, + wlan_objmgr_peer_destroy_handler handler, void *args); /** - * wlan_objmgr_unregister_peer_delete_handler() - unregister peer delete handler + * wlan_objmgr_unregister_peer_destroy_handler() - unregister peer destroy handler * @id: component id * @handler: function pointer of the component * @args: args, if component wants certain args to be passed on PEER deletion @@ -439,9 +439,9 @@ QDF_STATUS wlan_objmgr_register_peer_delete_handler( * Failure (if handler is not present, each failure has different error * code) */ -QDF_STATUS wlan_objmgr_unregister_peer_delete_handler( +QDF_STATUS wlan_objmgr_unregister_peer_destroy_handler( enum wlan_umac_comp_id id, - wlan_objmgr_peer_delete_handler handler, + wlan_objmgr_peer_destroy_handler handler, void *args); /** diff --git a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_pdev_obj.h b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_pdev_obj.h index 266f095f09ef..367a0d9611e6 100644 --- a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_pdev_obj.h +++ b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_pdev_obj.h @@ -133,11 +133,12 @@ struct wlan_objmgr_pdev_mlme { /** * struct wlan_objmgr_pdev_objmgr - pdev object object manager structure - * @wlan_pdev_id: PDEV id - * @wlan_vdev_list: List maintains the VDEVs created on this PDEV - * @wlan_vdev_count: VDEVs count - * @max_vdev_count: Max no. of VDEVs supported by this PDEV - * @wlan_psoc: back pointer to PSOC, its attached to + * @wlan_pdev_id: PDEV id + * @wlan_vdev_list: List maintains the VDEVs created on this PDEV + * @wlan_vdev_count: VDEVs count + * @max_vdev_count: Max no. of VDEVs supported by this PDEV + * @wlan_psoc: back pointer to PSOC, its attached to + * @ref_cnt: Ref count */ struct wlan_objmgr_pdev_objmgr { uint8_t wlan_pdev_id; @@ -145,6 +146,7 @@ struct wlan_objmgr_pdev_objmgr { uint8_t wlan_vdev_count; uint8_t max_vdev_count; struct wlan_objmgr_psoc *wlan_psoc; + qdf_atomic_t ref_cnt; }; /** @@ -192,8 +194,9 @@ struct wlan_objmgr_pdev *wlan_objmgr_pdev_obj_create( * wlan_objmgr_pdev_obj_delete() - pdev delete * @psoc: PDEV object * - * Deletes PDEV object, - * Invokes the registered notifiers to delete component objects + * Logically deletes PDEV object, + * Once all the references are released, object manager invokes the registered + * notifiers to destroy component objects * * Return: SUCCESS/FAILURE */ @@ -251,6 +254,7 @@ QDF_STATUS wlan_objmgr_pdev_component_obj_detach( * @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 VDEV/PEER objects * of pdev @@ -266,7 +270,8 @@ QDF_STATUS wlan_objmgr_pdev_iterate_obj_list( struct wlan_objmgr_pdev *pdev, enum wlan_objmgr_obj_type obj_type, wlan_objmgr_pdev_op_handler handler, - void *arg, uint8_t lock_free_op); + void *arg, uint8_t lock_free_op, + wlan_objmgr_ref_dbgid dbg_id); /** * wlan_objmgr_trigger_pdev_comp_priv_object_creation() - create @@ -285,12 +290,12 @@ QDF_STATUS wlan_objmgr_trigger_pdev_comp_priv_object_creation( enum wlan_umac_comp_id id); /** - * wlan_objmgr_trigger_pdev_comp_priv_object_deletion() - delete + * wlan_objmgr_trigger_pdev_comp_priv_object_deletion() - destroy * comp object of pdev * @pdev: PDEV object * @id: Component id * - * API to delete component private object in run time, this would + * API to destroy component private object in run time, this would * be used for features which gets disabled in run time * * Return: SUCCESS on successful deletion @@ -301,30 +306,66 @@ QDF_STATUS wlan_objmgr_trigger_pdev_comp_priv_object_deletion( enum wlan_umac_comp_id id); /** - * wlan_objmgr_find_vdev_by_id_from_pdev() - find vdev using id from pdev + * wlan_objmgr_get_vdev_by_id_from_pdev() - find vdev using id from pdev * @pdev: PDEV object * @vdev_id: vdev id + * @dbg_id: id of the caller * * API to find vdev object pointer by vdev id from pdev's vdev list * * Return: vdev pointer * NULL on FAILURE */ -struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_id_from_pdev( - struct wlan_objmgr_pdev *pdev, uint8_t vdev_id); +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev( + struct wlan_objmgr_pdev *pdev, uint8_t vdev_id, + wlan_objmgr_ref_dbgid dbg_id); /** - * wlan_objmgr_find_vdev_by_macaddr_from_pdev() - find vdev using macaddr + * wlan_objmgr_get_vdev_by_id_from_pdev_no_state() - find vdev using id from + * pdev + * @pdev: PDEV object + * @vdev_id: vdev id + * @dbg_id: id of the caller + * + * API to find vdev object pointer by vdev id from pdev's vdev list + * + * Return: vdev pointer + * NULL on FAILURE + */ +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev_no_state( + struct wlan_objmgr_pdev *pdev, uint8_t vdev_id, + wlan_objmgr_ref_dbgid dbg_id); + +/** + * wlan_objmgr_get_vdev_by_macaddr_from_pdev() - find vdev using macaddr * @pdev: PDEV object * @macaddr: MAC address + * @dbg_id: id of the caller * * API to find vdev object pointer by vdev mac addr from pdev's vdev list * * Return: vdev pointer * NULL on FAILURE */ -struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_macaddr_from_pdev( - struct wlan_objmgr_pdev *pdev, uint8_t *macaddr); +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev( + struct wlan_objmgr_pdev *pdev, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id); + +/** + * wlan_objmgr_get_vdev_by_macaddr_from_pdev_no_state() - find vdev using + * macaddr + * @pdev: PDEV object + * @macaddr: MAC address + * @dbg_id: id of the caller + * + * API to find vdev object pointer by vdev mac addr from pdev's vdev list + * + * Return: vdev pointer + * NULL on FAILURE + */ +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev_no_state( + struct wlan_objmgr_pdev *pdev, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id); /** * wlan_objmgr_pdev_get_comp_private_obj() - get pdev component private object @@ -601,4 +642,82 @@ static inline uint8_t wlan_pdev_get_max_vdev_count( /* This API is invoked with lock acquired, do not add log prints */ return pdev->pdev_objmgr.max_vdev_count; } + +/** + * DOC: Examples to use PDEV ref count APIs + * + * In all the scenarios, the pair of API should be followed + * otherwise it lead to memory leak + * + * scenario 1: + * + * wlan_objmgr_pdev_obj_create() + * ---- + * wlan_objmgr_pdev_obj_delete() + * + * scenario 2: + * + * wlan_objmgr_pdev_get_ref() + * ---- + * the operations which are done on + * pdev object + * ---- + * wlan_objmgr_pdev_release_ref() + * + * scenario 3: + * + * wlan_objmgr_get_pdev_by_id[_no_state]() + * ---- + * the operations which are done on + * pdev object + * ---- + * wlan_objmgr_pdev_release_ref() + * + * scenario 4: + * + * wlan_objmgr_get_pdev_by_macaddr[_no_state]() + * ---- + * the operations which are done on + * pdev object + * ---- + * wlan_objmgr_pdev_release_ref() + */ + +/** + * wlan_objmgr_pdev_get_ref() - increment ref count + * @pdev: PDEV object + * @id: Object Manager ref debug id + * + * API to increment ref count of pdev + * + * Return: void + */ +void wlan_objmgr_pdev_get_ref(struct wlan_objmgr_pdev *pdev, + wlan_objmgr_ref_dbgid id); + +/** + * wlan_objmgr_pdev_try_get_ref() - increment ref count, if allowed + * @pdev: PDEV object + * @id: Object Manager ref debug id + * + * API to increment ref count of pdev after checking valid object state + * + * Return: void + */ +QDF_STATUS wlan_objmgr_pdev_try_get_ref(struct wlan_objmgr_pdev *pdev, + wlan_objmgr_ref_dbgid id); + +/** + * wlan_objmgr_pdev_release_ref() - decrement ref count + * @pdev: PDEV object + * @id: Object Manager ref debug id + * + * API to decrement ref count of pdev, if ref count is 1, it initiates the + * PDEV deletion + * + * Return: void + */ +void wlan_objmgr_pdev_release_ref(struct wlan_objmgr_pdev *pdev, + wlan_objmgr_ref_dbgid id); + #endif /* _WLAN_OBJMGR_PDEV_H_*/ diff --git a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_peer_obj.h b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_peer_obj.h index 7fb02cde9864..7f6432f10611 100644 --- a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_peer_obj.h +++ b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_peer_obj.h @@ -21,6 +21,7 @@ */ #ifndef _WLAN_OBJMGR_PEER_OBJ_H_ #define _WLAN_OBJMGR_PEER_OBJ_H_ + #include #include @@ -134,8 +135,8 @@ struct wlan_objmgr_peer_mlme { /** * struct wlan_objmgr_peer_objmgr - object manager data of peer - * @vdev: VDEV pointer to which it is associated - * @ref_cnt: Ref count + * @vdev: VDEV pointer to which it is associated + * @ref_cnt: Ref count */ struct wlan_objmgr_peer_objmgr { struct wlan_objmgr_vdev *vdev; @@ -203,7 +204,7 @@ struct wlan_objmgr_peer *wlan_objmgr_peer_obj_create( * @peer: PEER object * * Deletes PEER object, removes it from PSOC's, VDEV's peer list - * Invokes the registered notifiers to delete component objects + * Invokes the registered notifiers to destroy component objects * * Return: SUCCESS/FAILURE */ @@ -268,12 +269,12 @@ QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_creation( enum wlan_umac_comp_id id); /** - * wlan_objmgr_trigger_peer_comp_priv_object_deletion() - delete + * wlan_objmgr_trigger_peer_comp_priv_object_deletion() - destroy * peer comp object * @peer: PEER object * @id: Component id * - * API to delete component private object in run time, this would + * API to destroy component private object in run time, this would * be used for features which gets disabled in run time * * Return: SUCCESS on successful deletion @@ -324,45 +325,74 @@ static inline void wlan_peer_obj_unlock(struct wlan_objmgr_peer *peer) { qdf_spin_unlock_bh(&peer->peer_lock); } + /** - * wlan_objmgr_peer_ref_peer() - increment ref count + * DOC: Examples to use PEER ref count APIs + * + * In all the scenarios, the pair of API should be followed + * other it lead to memory leak + * + * scenario 1: + * + * wlan_objmgr_peer_obj_create() + * ---- + * wlan_objmgr_peer_obj_delete() + * + * scenario 2: + * + * wlan_objmgr_peer_get_ref() + * ---- + * the operations which are done on + * peer object + * ---- + * wlan_objmgr_peer_release_ref() + * + * scenario 3: + * + * API to retrieve peer (xxx_get_peer_xxx()) + * ---- + * the operations which are done on + * peer object + * ---- + * wlan_objmgr_peer_release_ref() + */ + +/** + * wlan_objmgr_peer_get_ref() - increment ref count * @peer: PEER object + * @id: Object Manager ref debug id * * API to increment ref count of peer * * Return: void */ -static inline void wlan_objmgr_peer_ref_peer(struct wlan_objmgr_peer *peer) -{ - if (peer == NULL) { - qdf_print("%s: peer obj is NULL\n", __func__); - return; - } - /* Increment ref count */ - qdf_atomic_inc(&peer->peer_objmgr.ref_cnt); - return; -} +void wlan_objmgr_peer_get_ref(struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid id); /** - * wlan_objmgr_peer_unref_peer() - decrement ref count + * wlan_objmgr_peer_try_get_ref() - increment ref count, if allowed * @peer: PEER object + * @id: Object Manager ref debug id + * + * API to increment ref count of peer, if object state is valid + * + * Return: void + */ +QDF_STATUS wlan_objmgr_peer_try_get_ref(struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid id); + +/** + * wlan_objmgr_peer_release_ref() - decrement ref count + * @peer: PEER object + * @id: Object Manager ref debug id * * API to decrement ref count of peer, if ref count is 1, it initiates the * peer deletion * * Return: void */ -static inline void wlan_objmgr_peer_unref_peer(struct wlan_objmgr_peer *peer) -{ - if (peer == NULL) { - qdf_print("%s: peer obj is NULL\n", __func__); - return; - } - /* Decrement ref count, free peer, if count becomes 0 */ - if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt)) - wlan_objmgr_peer_obj_delete(peer); - return; -} +void wlan_objmgr_peer_release_ref(struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid id); /** * wlan_psoc_peer_list_peek_head() - get head of psoc peer list 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 f8a8efb50cf5..ec270e1ae7cb 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 @@ -192,6 +192,7 @@ struct wlan_objmgr_psoc_nif { * @wlan_vdev_id_map[]: VDEV id map, to allocate free ids * @wlan_peer_count: PEER count * @peer_list: Peer list + * @ref_cnt: Ref count */ struct wlan_objmgr_psoc_objmgr { uint8_t wlan_pdev_count; @@ -203,6 +204,7 @@ struct wlan_objmgr_psoc_objmgr { uint32_t wlan_vdev_id_map[2]; uint16_t wlan_peer_count; struct wlan_peer_list peer_list; + qdf_atomic_t ref_cnt; }; /** @@ -282,8 +284,9 @@ struct wlan_objmgr_psoc *wlan_objmgr_psoc_obj_create(uint32_t phy_version, * wlan_objmgr_psoc_obj_delete() - psoc object delete * @psoc: PSOC object * - * Deletes PSOC object, - * Invokes the registered notifiers to delete component objects + * Logically deletes PSOC object, + * Once all the references are released, object manager invokes the registered + * notifiers to destroy component objects * * Return: SUCCESS/FAILURE */ @@ -341,6 +344,7 @@ QDF_STATUS wlan_objmgr_psoc_component_obj_detach( * @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 @@ -355,7 +359,8 @@ QDF_STATUS wlan_objmgr_iterate_obj_list( struct wlan_objmgr_psoc *psoc, enum wlan_objmgr_obj_type obj_type, wlan_objmgr_op_handler handler, - void *arg, uint8_t lock_free_op); + void *arg, uint8_t lock_free_op, + wlan_objmgr_ref_dbgid dbg_id); /** * wlan_objmgr_free_all_objects_per_psoc() - free all psoc objects @@ -385,12 +390,12 @@ QDF_STATUS wlan_objmgr_trigger_psoc_comp_priv_object_creation( enum wlan_umac_comp_id id); /** - * wlan_objmgr_trigger_psoc_comp_priv_object_deletion() - delete + * wlan_objmgr_trigger_psoc_comp_priv_object_deletion() - destroy * psoc comp object * @psoc: PSOC object * @id: Component id * - * API to delete component private object in run time, this would + * API to destroy component private object in run time, this would * be used for features which gets disabled in run time * * Return: SUCCESS on successful deletion @@ -401,85 +406,192 @@ QDF_STATUS wlan_objmgr_trigger_psoc_comp_priv_object_deletion( enum wlan_umac_comp_id id); /** - * wlan_objmgr_find_peer() - find peer from psoc's peer list + * wlan_objmgr_get_peer() - find peer from psoc's peer list * @psoc: PSOC object * @macaddr: MAC address + * @dbg_id: id of the caller * * API to find peer object pointer by MAC addr * * Return: peer pointer * NULL on FAILURE */ -struct wlan_objmgr_peer *wlan_objmgr_find_peer( - struct wlan_objmgr_psoc *psoc, uint8_t *macaddr); +struct wlan_objmgr_peer *wlan_objmgr_get_peer( + struct wlan_objmgr_psoc *psoc, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id); /** - * wlan_objmgr_find_peer_by_mac_n_vdev() - find peer from psoc's peer list + * wlan_objmgr_get_peer_no_state() - find peer from psoc's peer list + * @psoc: PSOC object + * @macaddr: MAC address + * @dbg_id: id of the caller + * + * API to find peer object pointer by MAC addr, ignores the state check + * + * Return: peer pointer + * NULL on FAILURE + */ +struct wlan_objmgr_peer *wlan_objmgr_get_peer_no_state( + struct wlan_objmgr_psoc *psoc, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id); + +/** + * wlan_objmgr_get_peer_by_mac_n_vdev() - find peer from psoc's peer list * using mac address and bssid * @psoc: PSOC object * @macaddr: MAC address * @bssid: MAC address of AP its associated + * @dbg_id: id of the caller * * API to find peer object pointer by MAC addr and vdev self mac address * * Return: peer pointer * NULL on FAILURE */ -struct wlan_objmgr_peer *wlan_objmgr_find_peer_by_mac_n_vdev( +struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac_n_vdev( struct wlan_objmgr_psoc *psoc, uint8_t *macaddr, - uint8_t *bssid); + uint8_t *bssid, wlan_objmgr_ref_dbgid dbg_id); /** - * wlan_objmgr_find_pdev_by_id() - retrieve pdev by id + * wlan_objmgr_get_peer_by_mac_n_vdev_no_state() - find peer from psoc's peer + * list using mac address and bssid + * @psoc: PSOC object + * @macaddr: MAC address + * @bssid: MAC address of AP its associated + * @dbg_id: id of the caller + * + * API to find peer object pointer by MAC addr and vdev self mac address, + * ignores the state + * + * Return: peer pointer + * NULL on FAILURE + */ +struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac_n_vdev_no_state( + struct wlan_objmgr_psoc *psoc, uint8_t *macaddr, + uint8_t *bssid, wlan_objmgr_ref_dbgid dbg_id); + +/** + * wlan_objmgr_get_pdev_by_id() - retrieve pdev by id * @psoc: PSOC object * @id: pdev id + * @dbg_id: id of the caller * * API to find pdev object pointer by pdev id * * Return: pdev pointer * NULL on FAILURE */ -struct wlan_objmgr_pdev *wlan_objmgr_find_pdev_by_id( - struct wlan_objmgr_psoc *psoc, uint8_t id); +struct wlan_objmgr_pdev *wlan_objmgr_get_pdev_by_id( + struct wlan_objmgr_psoc *psoc, uint8_t id, + wlan_objmgr_ref_dbgid dbg_id); /** - * wlan_objmgr_find_pdev_by_macaddr() - retrieve pdev by macaddr + * wlan_objmgr_get_pdev_by_id_no_state() - retrieve pdev by id + * @psoc: PSOC object + * @id: pdev id + * @dbg_id: id of the caller + * + * API to find pdev object pointer by pdev id, Ignores the state check + * + * Return: pdev pointer + * NULL on FAILURE + */ +struct wlan_objmgr_pdev *wlan_objmgr_get_pdev_by_id_no_state( + struct wlan_objmgr_psoc *psoc, uint8_t id, + wlan_objmgr_ref_dbgid dbg_id); + +/** + * wlan_objmgr_get_pdev_by_macaddr() - retrieve pdev by macaddr * @psoc: PSOC object * @macaddr: MAC address + * @dbg_id: id of the caller * * API to find pdev object pointer by pdev macaddr * * Return: pdev pointer * NULL on FAILURE */ -struct wlan_objmgr_pdev *wlan_objmgr_find_pdev_by_macaddr( - struct wlan_objmgr_psoc *psoc, uint8_t *macaddr); +struct wlan_objmgr_pdev *wlan_objmgr_get_pdev_by_macaddr( + struct wlan_objmgr_psoc *psoc, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id); /** - * wlan_objmgr_find_vdev_by_id_from_psoc() - retrieve vdev by id + * wlan_objmgr_get_pdev_by_macaddr_no_state() - retrieve pdev by macaddr + * @psoc: PSOC object + * @macaddr: MAC address + * @dbg_id: id of the caller + * + * API to find pdev object pointer by pdev macaddr, ignores the state check + * + * Return: pdev pointer + * NULL on FAILURE + */ +struct wlan_objmgr_pdev *wlan_objmgr_get_pdev_by_macaddr_no_state( + struct wlan_objmgr_psoc *psoc, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id); + +/** + * wlan_objmgr_get_vdev_by_id_from_psoc() - retrieve vdev by id * @psoc: PSOC object * @id: vdev id + * @dbg_id: id of the caller * * API to find vdev object pointer by vdev id from psoc * * Return: vdev pointer * NULL on FAILURE */ -struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_id_from_psoc( - struct wlan_objmgr_psoc *psoc, uint8_t vdev_id); +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_psoc( + struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, + wlan_objmgr_ref_dbgid dbg_id); /** - * wlan_objmgr_find_vdev_by_macaddr_from_psoc() - retrieve vdev by macaddr + * wlan_objmgr_get_vdev_by_id_from_psoc_no_state() - retrieve vdev by id + * @psoc: PSOC object + * @id: vdev id + * @dbg_id: id of the caller + * + * API to find vdev object pointer by vdev id from psoc, ignores the + * state check + * + * Return: vdev pointer + * NULL on FAILURE + */ +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_psoc_no_state( + struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, + wlan_objmgr_ref_dbgid dbg_id); + +/** + * wlan_objmgr_get_vdev_by_macaddr_from_psoc() - retrieve vdev by macaddr * @psoc: PSOC object * @macaddr: macaddr + * @dbg_id: id of the caller * * API to find vdev object pointer by vdev macaddr from psoc * * Return: vdev pointer * NULL on FAILURE */ -struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_macaddr_from_psoc( - struct wlan_objmgr_psoc *psoc, uint8_t *macaddr); +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_psoc( + struct wlan_objmgr_psoc *psoc, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id); + +/** + * wlan_objmgr_get_vdev_by_macaddr_from_psoc_no_state() - retrieve vdev by + * macaddr + * @psoc: PSOC object + * @macaddr: macaddr + * @dbg_id: id of the caller + * + * API to find vdev object pointer by vdev macaddr from psoc, ignores the state + * check + * + * Return: vdev pointer + * NULL on FAILURE + */ +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_psoc_no_state( + struct wlan_objmgr_psoc *psoc, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id); /** * wlan_psoc_obj_lock() - Acquire PSOC spinlock @@ -851,4 +963,63 @@ static inline void *wlan_psoc_get_tgt_if_handle(struct wlan_objmgr_psoc *psoc) return psoc->tgt_if_handle; } +/** + * DOC: Examples to use PSOC ref count APIs + * + * In all the scenarios, the pair of API should be followed + * other it lead to memory leak + * + * scenario 1: + * + * wlan_objmgr_psoc_obj_create() + * ---- + * wlan_objmgr_psoc_obj_delete() + * + * scenario 2: + * + * wlan_objmgr_psoc_get_ref() + * ---- + * the operations which are done on + * psoc object + * ---- + * wlan_objmgr_psoc_release_ref() + */ + +/** + * wlan_objmgr_psoc_get_ref() - increment ref count + * @psoc: PSOC object + * @id: Object Manager ref debug id + * + * API to increment ref count of psoc + * + * Return: void + */ +void wlan_objmgr_psoc_get_ref(struct wlan_objmgr_psoc *psoc, + wlan_objmgr_ref_dbgid id); + +/** + * wlan_objmgr_psoc_try_get_ref() - increment ref count, if allowed + * @psoc: PSOC object + * @id: Object Manager ref debug id + * + * API to increment ref count after checking valid object state + * + * Return: void + */ +QDF_STATUS wlan_objmgr_psoc_try_get_ref(struct wlan_objmgr_psoc *psoc, + wlan_objmgr_ref_dbgid id); + +/** + * wlan_objmgr_psoc_release_ref() - decrement ref count + * @psoc: PSOC object + * @id: Object Manager ref debug id + * + * API to decrement ref count of psoc, if ref count is 1, it initiates the + * PSOC deletion + * + * Return: void + */ +void wlan_objmgr_psoc_release_ref(struct wlan_objmgr_psoc *psoc, + wlan_objmgr_ref_dbgid id); + #endif /* _WLAN_OBJMGR_PSOC_OBJ_H_*/ diff --git a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h index 085caf7b0b4c..94ae68cc651e 100644 --- a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h +++ b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h @@ -136,7 +136,7 @@ #define WLAN_VDEV_FEXT_NON_BEACON 0x00400000 /* VDEV OP flags */ - /* if the vap deleted by user */ + /* if the vap destroyed by user */ #define WLAN_VDEV_OP_DELETE_PROGRESS 0x00000001 /* set to enable sta-fws fweature */ #define WLAN_VDEV_OP_STAFWD 0x00000002 @@ -291,14 +291,15 @@ struct wlan_objmgr_vdev_nif { /** * struct wlan_objmgr_vdev_objmgr - vdev object manager sub structure - * @vdev_id: VDEV id - * @self_peer: Self PEER - * @bss_peer: BSS PEER - * @wlan_peer_list: PEER list - * @wlan_pdev: PDEV pointer - * @wlan_peer_count: Peer count - * @max_peer_count: Max Peer count - * @c_flags: creation specific flags + * @vdev_id: VDEV id + * @self_peer: Self PEER + * @bss_peer: BSS PEER + * @wlan_peer_list: PEER list + * @wlan_pdev: PDEV pointer + * @wlan_peer_count: Peer count + * @max_peer_count: Max Peer count + * @c_flags: creation specific flags + * @ref_cnt: Ref count */ struct wlan_objmgr_vdev_objmgr { uint8_t vdev_id; @@ -309,6 +310,7 @@ struct wlan_objmgr_vdev_objmgr { uint16_t wlan_peer_count; uint16_t max_peer_count; uint32_t c_flags; + qdf_atomic_t ref_cnt; }; /** @@ -357,8 +359,9 @@ struct wlan_objmgr_vdev *wlan_objmgr_vdev_obj_create( * wlan_objmgr_vdev_obj_delete() - vdev object delete * @vdev: vdev object * - * Deletes VDEV object, removes it from PSOC's, PDEV's VDEV list - * Invokes the registered notifiers to delete component objects + * Logically deletes VDEV object, + * Once all the references are released, object manager invokes the registered + * notifiers to destroy component objects * * Return: SUCCESS/FAILURE */ @@ -411,6 +414,7 @@ QDF_STATUS wlan_objmgr_vdev_component_obj_detach( * @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 + * @dbg_id: id of the caller * * API to be used for performing the operations on all PEER objects * of vdev @@ -424,7 +428,7 @@ typedef void (*wlan_objmgr_vdev_op_handler)(struct wlan_objmgr_vdev *vdev, QDF_STATUS wlan_objmgr_iterate_peerobj_list( struct wlan_objmgr_vdev *vdev, wlan_objmgr_vdev_op_handler handler, - void *arg); + void *arg, wlan_objmgr_ref_dbgid dbg_id); /** * wlan_objmgr_trigger_vdev_comp_priv_object_creation() - vdev @@ -448,7 +452,7 @@ QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_creation( * @vdev: VDEV object * @id: Component id * - * API to delete component private object in run time, this would + * API to destroy component private object in run time, this would * be used for features which gets disabled in run time * * Return: SUCCESS on successful deletion @@ -1364,4 +1368,89 @@ static inline void *wlan_vdev_get_ospriv(struct wlan_objmgr_vdev *vdev) /* This API is invoked with lock acquired, do not add log prints */ return vdev->vdev_nif.osdev; } + +/** + * wlan_vdev_get_peer_count() - get vdev peer count + * @vdev: VDEV object + * + * API to get OS private pointer from VDEV + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: peer_count - vdev's peer count + */ +static inline uint16_t wlan_vdev_get_peer_count(struct wlan_objmgr_vdev *vdev) +{ + /* This API is invoked with lock acquired, do not add log prints */ + return vdev->vdev_objmgr.wlan_peer_count; +} + +/** + * DOC: Examples to use VDEV ref count APIs + * + * In all the scenarios, the pair of API should be followed + * other it lead to memory leak + * + * scenario 1: + * + * wlan_objmgr_vdev_obj_create() + * ---- + * wlan_objmgr_vdev_obj_delete() + * + * scenario 2: + * + * wlan_objmgr_vdev_get_ref() + * ---- + * the operations which are done on + * vdev object + * ---- + * wlan_objmgr_vdev_release_ref() + * + * scenario 3: + * + * API to retrieve vdev (xxx_get_vdev_xxx()) + * ---- + * the operations which are done on + * vdev object + * ---- + * wlan_objmgr_vdev_release_ref() + */ + +/** + * wlan_objmgr_vdev_get_ref() - increment ref count + * @vdev: VDEV object + * @id: Object Manager ref debug id + * + * API to increment ref count of vdev + * + * Return: void + */ +void wlan_objmgr_vdev_get_ref(struct wlan_objmgr_vdev *vdev, + wlan_objmgr_ref_dbgid id); + +/** + * wlan_objmgr_vdev_try_get_ref() - increment ref count, if allowed + * @vdev: VDEV object + * @id: Object Manager ref debug id + * + * API to increment ref count of vdev after checking valid object state + * + * Return: void + */ +QDF_STATUS wlan_objmgr_vdev_try_get_ref(struct wlan_objmgr_vdev *vdev, + wlan_objmgr_ref_dbgid id); + +/** + * wlan_objmgr_vdev_release_ref() - decrement ref count + * @vdev: VDEV object + * @id: Object Manager ref debug id + * + * API to decrement ref count of vdev, if ref count is 1, it initiates the + * VDEV deletion + * + * Return: void + */ +void wlan_objmgr_vdev_release_ref(struct wlan_objmgr_vdev *vdev, + wlan_objmgr_ref_dbgid id); + #endif /* _WLAN_OBJMGR_VDEV_OBJ_H_*/ diff --git a/umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj.c b/umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj.c index 0075d8b420d7..b61516ea2870 100644 --- a/umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj.c +++ b/umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj.c @@ -64,7 +64,7 @@ EXPORT_SYMBOL(wlan_objmgr_global_obj_init); QDF_STATUS wlan_objmgr_global_obj_deinit(void) { - /* If it is already deleted */ + /* If it is already destroyed */ if (g_umac_glb_obj == NULL) { qdf_print("%s: Global object is not allocated\n", __func__); return QDF_STATUS_E_FAILURE; @@ -138,9 +138,9 @@ QDF_STATUS wlan_objmgr_unregister_psoc_create_handler( return QDF_STATUS_SUCCESS; } -QDF_STATUS wlan_objmgr_register_psoc_delete_handler( +QDF_STATUS wlan_objmgr_register_psoc_destroy_handler( enum wlan_umac_comp_id id, - wlan_objmgr_psoc_delete_handler handler, + wlan_objmgr_psoc_destroy_handler handler, void *arg) { /* If id is not within valid range, return */ @@ -150,23 +150,23 @@ QDF_STATUS wlan_objmgr_register_psoc_delete_handler( } qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); /* If there is a valid entry, return failure */ - if (g_umac_glb_obj->psoc_delete_handler[id] != NULL) { + if (g_umac_glb_obj->psoc_destroy_handler[id] != NULL) { qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); qdf_print("%s:callback for comp %d is already registered\n", __func__, id); return QDF_STATUS_E_FAILURE; } /* Store handler and args in Global object table */ - g_umac_glb_obj->psoc_delete_handler[id] = handler; - g_umac_glb_obj->psoc_delete_handler_arg[id] = arg; + g_umac_glb_obj->psoc_destroy_handler[id] = handler; + g_umac_glb_obj->psoc_destroy_handler_arg[id] = arg; qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); return QDF_STATUS_SUCCESS; } -QDF_STATUS wlan_objmgr_unregister_psoc_delete_handler( +QDF_STATUS wlan_objmgr_unregister_psoc_destroy_handler( enum wlan_umac_comp_id id, - wlan_objmgr_psoc_delete_handler handler, + wlan_objmgr_psoc_destroy_handler handler, void *arg) { /* If id is not within valid range, return */ @@ -176,15 +176,15 @@ QDF_STATUS wlan_objmgr_unregister_psoc_delete_handler( } qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); /* If there is an invalid entry, return failure */ - if (g_umac_glb_obj->psoc_delete_handler[id] != handler) { + if (g_umac_glb_obj->psoc_destroy_handler[id] != handler) { qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); qdf_print("%s:callback for comp %d is not registered\n", __func__, id); return QDF_STATUS_E_FAILURE; } /* Reset handlers, and args to NULL */ - g_umac_glb_obj->psoc_delete_handler[id] = NULL; - g_umac_glb_obj->psoc_delete_handler_arg[id] = NULL; + g_umac_glb_obj->psoc_destroy_handler[id] = NULL; + g_umac_glb_obj->psoc_destroy_handler_arg[id] = NULL; qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); return QDF_STATUS_SUCCESS; @@ -295,9 +295,9 @@ QDF_STATUS wlan_objmgr_unregister_pdev_create_handler( return QDF_STATUS_SUCCESS; } -QDF_STATUS wlan_objmgr_register_pdev_delete_handler( +QDF_STATUS wlan_objmgr_register_pdev_destroy_handler( enum wlan_umac_comp_id id, - wlan_objmgr_pdev_delete_handler handler, + wlan_objmgr_pdev_destroy_handler handler, void *arg) { /* If id is not within valid range, return */ @@ -307,23 +307,23 @@ QDF_STATUS wlan_objmgr_register_pdev_delete_handler( } qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); /* If there is a valid entry, return failure */ - if (g_umac_glb_obj->pdev_delete_handler[id] != NULL) { + if (g_umac_glb_obj->pdev_destroy_handler[id] != NULL) { qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); qdf_print("%s:callback for comp %d is already registered\n", __func__, id); return QDF_STATUS_E_FAILURE; } /* Store handler and args in Global object table */ - g_umac_glb_obj->pdev_delete_handler[id] = handler; - g_umac_glb_obj->pdev_delete_handler_arg[id] = arg; + g_umac_glb_obj->pdev_destroy_handler[id] = handler; + g_umac_glb_obj->pdev_destroy_handler_arg[id] = arg; qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); return QDF_STATUS_SUCCESS; } -QDF_STATUS wlan_objmgr_unregister_pdev_delete_handler( +QDF_STATUS wlan_objmgr_unregister_pdev_destroy_handler( enum wlan_umac_comp_id id, - wlan_objmgr_pdev_delete_handler handler, + wlan_objmgr_pdev_destroy_handler handler, void *arg) { /* If id is not within valid range, return */ @@ -333,15 +333,15 @@ QDF_STATUS wlan_objmgr_unregister_pdev_delete_handler( } qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); /* If there is an invalid entry, return failure */ - if (g_umac_glb_obj->pdev_delete_handler[id] != handler) { + if (g_umac_glb_obj->pdev_destroy_handler[id] != handler) { qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); qdf_print("%s:callback for component %d is not registered\n", __func__, id); return QDF_STATUS_E_FAILURE; } /* Reset handlers, and args to NULL */ - g_umac_glb_obj->pdev_delete_handler[id] = NULL; - g_umac_glb_obj->pdev_delete_handler_arg[id] = NULL; + g_umac_glb_obj->pdev_destroy_handler[id] = NULL; + g_umac_glb_obj->pdev_destroy_handler_arg[id] = NULL; qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); return QDF_STATUS_SUCCESS; @@ -452,9 +452,9 @@ QDF_STATUS wlan_objmgr_unregister_vdev_create_handler( return QDF_STATUS_SUCCESS; } -QDF_STATUS wlan_objmgr_register_vdev_delete_handler( +QDF_STATUS wlan_objmgr_register_vdev_destroy_handler( enum wlan_umac_comp_id id, - wlan_objmgr_vdev_delete_handler handler, + wlan_objmgr_vdev_destroy_handler handler, void *arg) { /* If id is not within valid range, return */ @@ -464,23 +464,23 @@ QDF_STATUS wlan_objmgr_register_vdev_delete_handler( } qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); /* If there is a valid entry, return failure */ - if (g_umac_glb_obj->vdev_delete_handler[id] != NULL) { + if (g_umac_glb_obj->vdev_destroy_handler[id] != NULL) { qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); qdf_print("%s:callback for comp %d is already registered\n", __func__, id); return QDF_STATUS_E_FAILURE; } /* Store handler and args in Global object table */ - g_umac_glb_obj->vdev_delete_handler[id] = handler; - g_umac_glb_obj->vdev_delete_handler_arg[id] = arg; + g_umac_glb_obj->vdev_destroy_handler[id] = handler; + g_umac_glb_obj->vdev_destroy_handler_arg[id] = arg; qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); return QDF_STATUS_SUCCESS; } -QDF_STATUS wlan_objmgr_unregister_vdev_delete_handler( +QDF_STATUS wlan_objmgr_unregister_vdev_destroy_handler( enum wlan_umac_comp_id id, - wlan_objmgr_vdev_delete_handler handler, + wlan_objmgr_vdev_destroy_handler handler, void *arg) { /* If id is not within valid range, return */ @@ -490,15 +490,15 @@ QDF_STATUS wlan_objmgr_unregister_vdev_delete_handler( } qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); /* If there is an invalid entry, return failure */ - if (g_umac_glb_obj->vdev_delete_handler[id] != handler) { + if (g_umac_glb_obj->vdev_destroy_handler[id] != handler) { qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); qdf_print("%s:callback for comp %d is not registered\n", __func__, id); return QDF_STATUS_E_FAILURE; } /* Reset handlers, and args to NULL */ - g_umac_glb_obj->vdev_delete_handler[id] = NULL; - g_umac_glb_obj->vdev_delete_handler_arg[id] = NULL; + g_umac_glb_obj->vdev_destroy_handler[id] = NULL; + g_umac_glb_obj->vdev_destroy_handler_arg[id] = NULL; qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); return QDF_STATUS_SUCCESS; @@ -610,9 +610,9 @@ QDF_STATUS wlan_objmgr_unregister_peer_create_handler( return QDF_STATUS_SUCCESS; } -QDF_STATUS wlan_objmgr_register_peer_delete_handler( +QDF_STATUS wlan_objmgr_register_peer_destroy_handler( enum wlan_umac_comp_id id, - wlan_objmgr_peer_delete_handler handler, + wlan_objmgr_peer_destroy_handler handler, void *arg) { /* If id is not within valid range, return */ @@ -622,23 +622,23 @@ QDF_STATUS wlan_objmgr_register_peer_delete_handler( } qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); /* If there is a valid entry, return failure */ - if (g_umac_glb_obj->peer_delete_handler[id] != NULL) { + if (g_umac_glb_obj->peer_destroy_handler[id] != NULL) { qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); qdf_print("%s:callback for comp %d is already registered\n", __func__, id); return QDF_STATUS_E_FAILURE; } /* Store handler and args in Global object table */ - g_umac_glb_obj->peer_delete_handler[id] = handler; - g_umac_glb_obj->peer_delete_handler_arg[id] = arg; + g_umac_glb_obj->peer_destroy_handler[id] = handler; + g_umac_glb_obj->peer_destroy_handler_arg[id] = arg; qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); return QDF_STATUS_SUCCESS; } -QDF_STATUS wlan_objmgr_unregister_peer_delete_handler( +QDF_STATUS wlan_objmgr_unregister_peer_destroy_handler( enum wlan_umac_comp_id id, - wlan_objmgr_peer_delete_handler handler, + wlan_objmgr_peer_destroy_handler handler, void *arg) { /* If id is not within valid range, return */ @@ -648,15 +648,15 @@ QDF_STATUS wlan_objmgr_unregister_peer_delete_handler( } qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); /* If there is an invalid entry, return failure */ - if (g_umac_glb_obj->peer_delete_handler[id] != handler) { + if (g_umac_glb_obj->peer_destroy_handler[id] != handler) { qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); qdf_print("%s:callback for comp %d is not registered\n", __func__, id); return QDF_STATUS_E_FAILURE; } /* Reset handlers, and args to NULL */ - g_umac_glb_obj->peer_delete_handler[id] = NULL; - g_umac_glb_obj->peer_delete_handler_arg[id] = NULL; + g_umac_glb_obj->peer_destroy_handler[id] = NULL; + g_umac_glb_obj->peer_destroy_handler_arg[id] = NULL; qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); return QDF_STATUS_SUCCESS; @@ -754,7 +754,7 @@ QDF_STATUS wlan_objmgr_psoc_object_detach(struct wlan_objmgr_psoc *psoc) return status; } -QDF_STATUS wlan_objmgr_global_obj_can_deleted(void) +QDF_STATUS wlan_objmgr_global_obj_can_destroyed(void) { uint8_t index = 0; QDF_STATUS status = QDF_STATUS_SUCCESS; @@ -771,4 +771,4 @@ QDF_STATUS wlan_objmgr_global_obj_can_deleted(void) qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); return status; } -EXPORT_SYMBOL(wlan_objmgr_global_obj_can_deleted); +EXPORT_SYMBOL(wlan_objmgr_global_obj_can_destroyed); diff --git a/umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj_i.h b/umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj_i.h index ffcfad3b625c..34e4f423f5ab 100644 --- a/umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj_i.h +++ b/umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj_i.h @@ -28,26 +28,26 @@ * its optional * @psoc_create_handler[]: PSOC create handler array * @psoc_create_handler_arg[]: PSOC create handler args array - * @psoc_delete_handler[]: PSOC delete handler array - * @psoc_delete_handler_arg[]: PSOC delete handler args array + * @psoc_destroy_handler[]: PSOC destroy handler array + * @psoc_destroy_handler_arg[]: PSOC destroy handler args array * @psoc_status_handler[]: PSOC status handler array * @psoc_status_handler_arg[]: PSOC status handler args array * @pdev_create_handler[]: PDEV create handler array * @pdev_create_handler_arg[]: PDEV create handler args array - * @pdev_delete_handler[]: PDEV delete handler array - * @pdev_delete_handler_arg[]: PDEV delete handler args array + * @pdev_destroy_handler[]: PDEV destroy handler array + * @pdev_destroy_handler_arg[]: PDEV destroy handler args array * @pdev_status_handler[]: PDEV status handler array * @pdev_status_handler_arg[]: PDEV status handler args array * @vdev_create_handler[]: VDEV create handler array * @vdev_create_handler_arg[]: VDEV create handler args array - * @vdev_delete_handler[]: VDEV delete handler array - * @vdev_delete_handler_arg[]: VDEV delete handler args array + * @vdev_destroy_handler[]: VDEV destroy handler array + * @vdev_destroy_handler_arg[]: VDEV destroy handler args array * @vdev_status_handler[]: VDEV status handler array * @vdev_status_handler_arg[]: VDEV status handler args array * @peer_create_handler[]: PEER create handler array * @peer_create_handler_arg[]: PEER create handler args array - * @peer_delete_handler[]: PEER delete handler array - * @peer_delete_handler_arg[]: PEER delete handler args array + * @peer_destroy_handler[]: PEER destroy handler array + * @peer_destroy_handler_arg[]: PEER destroy handler args array * @peer_status_handler[]: PEER status handler array * @peer_status_handler_arg[]: PEER status handler args array * @global_lock: Global lock @@ -57,36 +57,36 @@ struct wlan_objmgr_global { wlan_objmgr_psoc_create_handler psoc_create_handler[WLAN_UMAC_MAX_COMPONENTS]; void *psoc_create_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; - wlan_objmgr_psoc_delete_handler - psoc_delete_handler[WLAN_UMAC_MAX_COMPONENTS]; - void *psoc_delete_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; + wlan_objmgr_psoc_destroy_handler + psoc_destroy_handler[WLAN_UMAC_MAX_COMPONENTS]; + void *psoc_destroy_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; wlan_objmgr_psoc_status_handler psoc_status_handler[WLAN_UMAC_MAX_COMPONENTS]; void *psoc_status_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; wlan_objmgr_pdev_create_handler pdev_create_handler[WLAN_UMAC_MAX_COMPONENTS]; void *pdev_create_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; - wlan_objmgr_pdev_delete_handler - pdev_delete_handler[WLAN_UMAC_MAX_COMPONENTS]; - void *pdev_delete_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; + wlan_objmgr_pdev_destroy_handler + pdev_destroy_handler[WLAN_UMAC_MAX_COMPONENTS]; + void *pdev_destroy_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; wlan_objmgr_pdev_status_handler pdev_status_handler[WLAN_UMAC_MAX_COMPONENTS]; void *pdev_status_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; wlan_objmgr_vdev_create_handler vdev_create_handler[WLAN_UMAC_MAX_COMPONENTS]; void *vdev_create_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; - wlan_objmgr_vdev_delete_handler - vdev_delete_handler[WLAN_UMAC_MAX_COMPONENTS]; - void *vdev_delete_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; + wlan_objmgr_vdev_destroy_handler + vdev_destroy_handler[WLAN_UMAC_MAX_COMPONENTS]; + void *vdev_destroy_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; wlan_objmgr_vdev_status_handler vdev_status_handler[WLAN_UMAC_MAX_COMPONENTS]; void *vdev_status_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; wlan_objmgr_peer_create_handler peer_create_handler[WLAN_UMAC_MAX_COMPONENTS]; void *peer_create_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; - wlan_objmgr_peer_delete_handler - peer_delete_handler[WLAN_UMAC_MAX_COMPONENTS]; - void *peer_delete_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; + wlan_objmgr_peer_destroy_handler + peer_destroy_handler[WLAN_UMAC_MAX_COMPONENTS]; + void *peer_destroy_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; wlan_objmgr_peer_status_handler peer_status_handler[WLAN_UMAC_MAX_COMPONENTS]; void *peer_status_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; diff --git a/umac/cmn_services/obj_mgr/src/wlan_objmgr_pdev_obj.c b/umac/cmn_services/obj_mgr/src/wlan_objmgr_pdev_obj.c index 4894d5ac1209..555f0b964939 100644 --- a/umac/cmn_services/obj_mgr/src/wlan_objmgr_pdev_obj.c +++ b/umac/cmn_services/obj_mgr/src/wlan_objmgr_pdev_obj.c @@ -64,6 +64,20 @@ static QDF_STATUS wlan_objmgr_pdev_object_status( return status; } +static QDF_STATUS wlan_objmgr_pdev_obj_free(struct wlan_objmgr_pdev *pdev) +{ + /* Detach PDEV from PSOC PDEV's list */ + if (wlan_objmgr_psoc_pdev_detach(pdev->pdev_objmgr.wlan_psoc, pdev) == + QDF_STATUS_E_FAILURE) { + qdf_print("%s: PSOC PDEV detach failed\n", __func__); + return QDF_STATUS_E_FAILURE; + } + qdf_spinlock_destroy(&pdev->pdev_lock); + qdf_mem_free(pdev); + + return QDF_STATUS_SUCCESS; +} + struct wlan_objmgr_pdev *wlan_objmgr_pdev_obj_create( struct wlan_objmgr_psoc *psoc, void *osdev_priv) { @@ -102,7 +116,8 @@ struct wlan_objmgr_pdev *wlan_objmgr_pdev_obj_create( pdev->pdev_objmgr.max_vdev_count = WLAN_UMAC_PDEV_MAX_VDEVS; /* Save HDD/OSIF pointer */ pdev->pdev_nif.pdev_ospriv = osdev_priv; - + qdf_atomic_init(&pdev->pdev_objmgr.ref_cnt); + wlan_objmgr_pdev_get_ref(pdev, WLAN_OBJMGR_ID); /* Invoke registered create handlers */ for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { handler = g_umac_glb_obj->pdev_create_handler[id]; @@ -143,10 +158,10 @@ struct wlan_objmgr_pdev *wlan_objmgr_pdev_obj_create( } EXPORT_SYMBOL(wlan_objmgr_pdev_obj_create); -QDF_STATUS wlan_objmgr_pdev_obj_delete(struct wlan_objmgr_pdev *pdev) +static QDF_STATUS wlan_objmgr_pdev_obj_destroy(struct wlan_objmgr_pdev *pdev) { uint8_t id; - wlan_objmgr_pdev_delete_handler handler; + wlan_objmgr_pdev_destroy_handler handler; QDF_STATUS obj_status; void *arg; @@ -155,10 +170,15 @@ QDF_STATUS wlan_objmgr_pdev_obj_delete(struct wlan_objmgr_pdev *pdev) return QDF_STATUS_E_FAILURE; } - /* Invoke registered delete handlers */ + if (pdev->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) { + qdf_print("%s:pdev object delete is not invoked\n", __func__); + WLAN_OBJMGR_BUG(0); + } + + /* Invoke registered destroy handlers */ for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { - handler = g_umac_glb_obj->pdev_delete_handler[id]; - arg = g_umac_glb_obj->pdev_delete_handler_arg[id]; + handler = g_umac_glb_obj->pdev_destroy_handler[id]; + arg = g_umac_glb_obj->pdev_destroy_handler_arg[id]; if (handler != NULL) pdev->obj_status[id] = handler(pdev, arg); else @@ -168,7 +188,7 @@ QDF_STATUS wlan_objmgr_pdev_obj_delete(struct wlan_objmgr_pdev *pdev) obj_status = wlan_objmgr_pdev_object_status(pdev); if (obj_status == QDF_STATUS_E_FAILURE) { - qdf_print("%s: PDEV component objects delete failed\n", + qdf_print("%s: PDEV component objects destroy failed\n", __func__); /* Ideally should not happen */ /* This leads to memleak ??? how to handle */ @@ -179,20 +199,27 @@ QDF_STATUS wlan_objmgr_pdev_obj_delete(struct wlan_objmgr_pdev *pdev) if (obj_status == QDF_STATUS_COMP_ASYNC) { pdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED; return QDF_STATUS_COMP_ASYNC; - } else { - /* Detach PDEV from PSOC PDEV's list */ - if (wlan_objmgr_psoc_pdev_detach(pdev->pdev_objmgr.wlan_psoc, - pdev) == - QDF_STATUS_E_FAILURE) { - qdf_print("%s: PSOC PDEV detach failed\n", - __func__); - return QDF_STATUS_E_FAILURE; - } - /* de-init lock */ - qdf_spinlock_destroy(&pdev->pdev_lock); - /* Free the memory */ - qdf_mem_free(pdev); } + + /* Free PDEV object */ + return wlan_objmgr_pdev_obj_free(pdev); +} + +QDF_STATUS wlan_objmgr_pdev_obj_delete(struct wlan_objmgr_pdev *pdev) +{ + if (pdev == NULL) { + qdf_print("%s:pdev is NULL\n", __func__); + return QDF_STATUS_E_FAILURE; + } + /* + * Update PDEV object state to LOGICALLY DELETED + * It prevents further access of this object + */ + wlan_pdev_obj_lock(pdev); + pdev->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED; + wlan_pdev_obj_unlock(pdev); + wlan_objmgr_pdev_release_ref(pdev, WLAN_OBJMGR_ID); + return QDF_STATUS_SUCCESS; } EXPORT_SYMBOL(wlan_objmgr_pdev_obj_delete); @@ -228,13 +255,16 @@ QDF_STATUS wlan_objmgr_pdev_component_obj_attach( /* Save component's pointer and status */ pdev->pdev_comp_priv_obj[id] = comp_priv_obj; pdev->obj_status[id] = status; + wlan_pdev_obj_unlock(pdev); if (pdev->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED) return QDF_STATUS_SUCCESS; - /* If PDEV object status is partially created means, this API is - invoked with differnt context, this block should be executed for async - components only */ + /** + * If PDEV object status is partially created means, this API is + * invoked with differnt context, this block should be executed for + * async components only + */ /* Derive status */ obj_status = wlan_objmgr_pdev_object_status(pdev); /* STATUS_SUCCESS means, object is CREATED */ @@ -281,7 +311,7 @@ QDF_STATUS wlan_objmgr_pdev_component_obj_detach( pdev->obj_status[id] = QDF_STATUS_SUCCESS; wlan_pdev_obj_unlock(pdev); - /* If PDEV object status is partially deleted means, this API is + /* If PDEV object status is partially destroyed means, this API is invoked with differnt context, this block should be executed for async components only */ if ((pdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) || @@ -318,15 +348,8 @@ QDF_STATUS wlan_objmgr_pdev_component_obj_detach( /* Delete pdev object */ if ((obj_status == QDF_STATUS_SUCCESS) && (pdev->obj_state == WLAN_OBJ_STATE_DELETED)) { - /* Detach pdev object from psoc */ - if (wlan_objmgr_psoc_pdev_detach( - pdev->pdev_objmgr.wlan_psoc, pdev) == - QDF_STATUS_E_FAILURE) - return QDF_STATUS_E_FAILURE; - /* Destroy spinlock */ - qdf_spinlock_destroy(&pdev->pdev_lock); - /* Free PDEV memory */ - qdf_mem_free(pdev); + /* Free PDEV object */ + return wlan_objmgr_pdev_obj_free(pdev); } } return QDF_STATUS_SUCCESS; @@ -338,7 +361,8 @@ QDF_STATUS wlan_objmgr_pdev_component_obj_detach( static void wlan_objmgr_pdev_vdev_iterate_peers(struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_vdev *vdev, wlan_objmgr_pdev_op_handler handler, - void *arg, uint8_t lock_free_op) + void *arg, uint8_t lock_free_op, + wlan_objmgr_ref_dbgid dbg_id) { qdf_list_t *peer_list = NULL; struct wlan_objmgr_peer *peer = NULL; @@ -353,17 +377,17 @@ static void wlan_objmgr_pdev_vdev_iterate_peers(struct wlan_objmgr_pdev *pdev, if (peer_list != NULL) { peer = wlan_vdev_peer_list_peek_head(peer_list); while (peer != NULL) { - /* Increment ref count, to hold the - peer pointer */ - wlan_objmgr_peer_ref_peer(peer); /* Get next peer pointer */ peer_next = wlan_peer_get_next_peer_of_vdev(peer_list, peer); - /* Invoke the handler */ - handler(pdev, (void *)peer, arg); - /* Decrement ref count, this can lead - to peer deletion also */ - wlan_objmgr_peer_unref_peer(peer); + /* Increment ref count, to hold the + peer pointer */ + if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) == + QDF_STATUS_SUCCESS) { + /* Invoke the handler */ + handler(pdev, (void *)peer, arg); + wlan_objmgr_peer_release_ref(peer, dbg_id); + } peer = peer_next; } } @@ -375,7 +399,8 @@ QDF_STATUS wlan_objmgr_pdev_iterate_obj_list( struct wlan_objmgr_pdev *pdev, enum wlan_objmgr_obj_type obj_type, wlan_objmgr_pdev_op_handler handler, - void *arg, uint8_t lock_free_op) + void *arg, uint8_t lock_free_op, + wlan_objmgr_ref_dbgid dbg_id) { struct wlan_objmgr_pdev_objmgr *objmgr = &pdev->pdev_objmgr; qdf_list_t *vdev_list = NULL; @@ -394,26 +419,35 @@ QDF_STATUS wlan_objmgr_pdev_iterate_obj_list( VDEV object */ vdev = wlan_pdev_vdev_list_peek_head(vdev_list); while (vdev != NULL) { - /* TODO increment ref count */ - /* Get next vdev (handler can be invoked for - vdev deletion also */ + /* + * Get next vdev (handler can be invoked for + * vdev deletion also + */ vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev); - handler(pdev, (void *)vdev, arg); + if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) == + QDF_STATUS_SUCCESS) { + handler(pdev, (void *)vdev, arg); + wlan_objmgr_vdev_release_ref(vdev, dbg_id); + } vdev = vdev_next; - /* TODO decrement ref count */ } break; case WLAN_PEER_OP: vdev = wlan_pdev_vdev_list_peek_head(vdev_list); while (vdev != NULL) { - /* TODO increment ref count */ - wlan_objmgr_pdev_vdev_iterate_peers(pdev, vdev, handler, - arg, lock_free_op); /* Get Next VDEV */ vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev); - /* TODO decrement ref count */ + if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) == + QDF_STATUS_SUCCESS) { + wlan_objmgr_pdev_vdev_iterate_peers(pdev, vdev, + handler, arg, + lock_free_op, + dbg_id); + wlan_objmgr_vdev_release_ref(vdev, dbg_id); + } + vdev = vdev_next; } break; default: @@ -471,7 +505,7 @@ QDF_STATUS wlan_objmgr_trigger_pdev_comp_priv_object_deletion( struct wlan_objmgr_pdev *pdev, enum wlan_umac_comp_id id) { - wlan_objmgr_pdev_delete_handler handler; + wlan_objmgr_pdev_destroy_handler handler; void *arg; QDF_STATUS obj_status = QDF_STATUS_SUCCESS; @@ -488,8 +522,8 @@ QDF_STATUS wlan_objmgr_trigger_pdev_comp_priv_object_deletion( wlan_pdev_obj_unlock(pdev); /* Invoke registered create handlers */ - handler = g_umac_glb_obj->pdev_delete_handler[id]; - arg = g_umac_glb_obj->pdev_delete_handler_arg[id]; + handler = g_umac_glb_obj->pdev_destroy_handler[id]; + arg = g_umac_glb_obj->pdev_destroy_handler_arg[id]; if (handler != NULL) pdev->obj_status[id] = handler(pdev, arg); else @@ -541,6 +575,8 @@ QDF_STATUS wlan_objmgr_pdev_vdev_attach(struct wlan_objmgr_pdev *pdev, } /* Add vdev to pdev's vdev list */ wlan_obj_pdev_vdevlist_add_tail(&objmgr->wlan_vdev_list, vdev); + /* Increment pdev ref count to make sure it won't be destroyed before */ + wlan_objmgr_pdev_get_ref(pdev, WLAN_OBJMGR_ID); /* Increment vdev count of pdev */ objmgr->wlan_vdev_count++; wlan_pdev_obj_unlock(pdev); @@ -563,13 +599,15 @@ QDF_STATUS wlan_objmgr_pdev_vdev_detach(struct wlan_objmgr_pdev *pdev, wlan_obj_pdev_vdevlist_remove_vdev(&objmgr->wlan_vdev_list, vdev); /* decrement vdev count */ objmgr->wlan_vdev_count--; - wlan_pdev_obj_unlock(pdev); + /* Decrement pdev ref count since vdev is releasing reference */ + wlan_objmgr_pdev_release_ref(pdev, WLAN_OBJMGR_ID); return QDF_STATUS_SUCCESS; } -struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_id_from_pdev( - struct wlan_objmgr_pdev *pdev, uint8_t vdev_id) +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev( + struct wlan_objmgr_pdev *pdev, uint8_t vdev_id, + wlan_objmgr_ref_dbgid dbg_id) { struct wlan_objmgr_vdev *vdev; struct wlan_objmgr_vdev *vdev_next; @@ -586,6 +624,10 @@ struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_id_from_pdev( entry of vdev list */ while (vdev != NULL) { if (wlan_vdev_get_id(vdev) == vdev_id) { + if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) != + QDF_STATUS_SUCCESS) + vdev = NULL; + wlan_pdev_obj_unlock(pdev); return vdev; } @@ -596,10 +638,47 @@ struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_id_from_pdev( wlan_pdev_obj_unlock(pdev); return NULL; } -EXPORT_SYMBOL(wlan_objmgr_find_vdev_by_id_from_pdev); +EXPORT_SYMBOL(wlan_objmgr_get_vdev_by_id_from_pdev); -struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_macaddr_from_pdev( - struct wlan_objmgr_pdev *pdev, uint8_t *macaddr) +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev_no_state( + struct wlan_objmgr_pdev *pdev, uint8_t vdev_id, + wlan_objmgr_ref_dbgid dbg_id) +{ + struct wlan_objmgr_vdev *vdev; + struct wlan_objmgr_vdev *vdev_next; + struct wlan_objmgr_pdev_objmgr *objmgr; + qdf_list_t *vdev_list; + + wlan_pdev_obj_lock(pdev); + + objmgr = &pdev->pdev_objmgr; + vdev_list = &objmgr->wlan_vdev_list; + /* Get first vdev */ + vdev = wlan_pdev_vdev_list_peek_head(vdev_list); + /** + * Iterate through pdev's vdev list, till vdev id matches with + * entry of vdev list + */ + while (vdev != NULL) { + if (wlan_vdev_get_id(vdev) == vdev_id) { + wlan_objmgr_vdev_get_ref(vdev, dbg_id); + wlan_pdev_obj_unlock(pdev); + + return vdev; + } + /* get next vdev */ + vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev); + vdev = vdev_next; + } + wlan_pdev_obj_unlock(pdev); + + return NULL; +} +EXPORT_SYMBOL(wlan_objmgr_get_vdev_by_id_from_pdev_no_state); + +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev( + struct wlan_objmgr_pdev *pdev, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id) { struct wlan_objmgr_vdev *vdev; struct wlan_objmgr_vdev *vdev_next; @@ -616,6 +695,10 @@ struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_macaddr_from_pdev( while (vdev != NULL) { if (WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), macaddr) == QDF_STATUS_SUCCESS) { + if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) != + QDF_STATUS_SUCCESS) + vdev = NULL; + wlan_pdev_obj_unlock(pdev); return vdev; } @@ -624,6 +707,40 @@ struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_macaddr_from_pdev( vdev = vdev_next; } wlan_pdev_obj_unlock(pdev); + + return NULL; +} + +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev_no_state( + struct wlan_objmgr_pdev *pdev, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id) +{ + struct wlan_objmgr_vdev *vdev; + struct wlan_objmgr_vdev *vdev_next; + struct wlan_objmgr_pdev_objmgr *objmgr; + qdf_list_t *vdev_list; + + wlan_pdev_obj_lock(pdev); + objmgr = &pdev->pdev_objmgr; + vdev_list = &objmgr->wlan_vdev_list; + /* Get first vdev */ + vdev = wlan_pdev_vdev_list_peek_head(vdev_list); + /* Iterate through pdev's vdev list, till vdev macaddr matches with + entry of vdev list */ + while (vdev != NULL) { + if (WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), macaddr) + == QDF_STATUS_SUCCESS) { + wlan_objmgr_vdev_get_ref(vdev, dbg_id); + wlan_pdev_obj_unlock(pdev); + + return vdev; + } + /* get next vdev */ + vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev); + vdev = vdev_next; + } + wlan_pdev_obj_unlock(pdev); + return NULL; } @@ -647,6 +764,68 @@ void *wlan_objmgr_pdev_get_comp_private_obj( } comp_priv_obj = pdev->pdev_comp_priv_obj[id]; + return comp_priv_obj; } EXPORT_SYMBOL(wlan_objmgr_pdev_get_comp_private_obj); + +void wlan_objmgr_pdev_get_ref(struct wlan_objmgr_pdev *pdev, + wlan_objmgr_ref_dbgid id) +{ + if (pdev == NULL) { + qdf_print("%s: pdev obj is NULL\n", __func__); + QDF_ASSERT(0); + return; + } + qdf_atomic_inc(&pdev->pdev_objmgr.ref_cnt); + + return; +} +EXPORT_SYMBOL(wlan_objmgr_pdev_get_ref); + +QDF_STATUS wlan_objmgr_pdev_try_get_ref(struct wlan_objmgr_pdev *pdev, + wlan_objmgr_ref_dbgid id) +{ + if (pdev == NULL) { + qdf_print("%s: pdev obj is NULL\n", __func__); + QDF_ASSERT(0); + return QDF_STATUS_E_FAILURE; + } + + wlan_pdev_obj_lock(pdev); + if (pdev->obj_state == WLAN_OBJ_STATE_LOGICALLY_DELETED) { + wlan_pdev_obj_unlock(pdev); + qdf_print("%s: pdev obj is in Deletion Progress state\n", + __func__); + return QDF_STATUS_E_RESOURCES; + } + + wlan_objmgr_pdev_get_ref(pdev, id); + wlan_pdev_obj_unlock(pdev); + + return QDF_STATUS_SUCCESS; +} +EXPORT_SYMBOL(wlan_objmgr_pdev_try_get_ref); + +void wlan_objmgr_pdev_release_ref(struct wlan_objmgr_pdev *pdev, + wlan_objmgr_ref_dbgid id) +{ + if (pdev == NULL) { + qdf_print("%s: pdev obj is NULL\n", __func__); + QDF_ASSERT(0); + return; + } + + if (!qdf_atomic_read(&pdev->pdev_objmgr.ref_cnt)) { + qdf_print("%s: pdev ref cnt is 0\n", __func__); + WLAN_OBJMGR_BUG(0); + return; + } + + /* Decrement ref count, free pdev, if ref count == 0 */ + if (qdf_atomic_dec_and_test(&pdev->pdev_objmgr.ref_cnt)) + wlan_objmgr_pdev_obj_destroy(pdev); + + return; +} +EXPORT_SYMBOL(wlan_objmgr_pdev_release_ref); diff --git a/umac/cmn_services/obj_mgr/src/wlan_objmgr_peer_obj.c b/umac/cmn_services/obj_mgr/src/wlan_objmgr_peer_obj.c index dbfca3e341f2..6c46783945f0 100644 --- a/umac/cmn_services/obj_mgr/src/wlan_objmgr_peer_obj.c +++ b/umac/cmn_services/obj_mgr/src/wlan_objmgr_peer_obj.c @@ -65,6 +65,47 @@ static QDF_STATUS wlan_objmgr_peer_object_status( return status; } +static QDF_STATUS wlan_objmgr_peer_obj_free(struct wlan_objmgr_peer *peer) +{ + struct wlan_objmgr_psoc *psoc; + struct wlan_objmgr_vdev *vdev; + + vdev = wlan_peer_get_vdev(peer); + if (vdev == NULL) { + qdf_print("%s: VDEV is NULL\n", __func__); + return QDF_STATUS_E_FAILURE; + } + + /* get PSOC from VDEV, if it is NULL, return */ + psoc = wlan_vdev_get_psoc(vdev); + if (psoc == NULL) { + qdf_print("%s: PSOC is NULL\n", __func__); + return QDF_STATUS_E_FAILURE; + } + + /* Decrement ref count for BSS peer, so that BSS peer deletes last*/ + if ((wlan_peer_get_peer_type(peer) == WLAN_PEER_STA) || + (wlan_peer_get_peer_type(peer) == WLAN_PEER_STA_TEMP)) + wlan_objmgr_peer_release_ref(wlan_vdev_get_bsspeer(vdev), + WLAN_OBJMGR_ID); + + /* Detach peer from VDEV's peer list */ + if (wlan_objmgr_vdev_peer_detach(vdev, peer) == QDF_STATUS_E_FAILURE) { + qdf_print("%s: Peer VDEV detach failure\n", __func__); + return QDF_STATUS_E_FAILURE; + } + /* Detach peer from PSOC's peer list */ + if (wlan_objmgr_psoc_peer_detach(psoc, peer) == QDF_STATUS_E_FAILURE) { + qdf_print("%s: Peer PSOC detach failure\n", __func__); + return QDF_STATUS_E_FAILURE; + } + qdf_spinlock_destroy(&peer->peer_lock); + qdf_mem_free(peer); + + return QDF_STATUS_SUCCESS; + +} + struct wlan_objmgr_peer *wlan_objmgr_peer_obj_create( struct wlan_objmgr_vdev *vdev, enum wlan_peer_type type, @@ -102,6 +143,7 @@ struct wlan_objmgr_peer *wlan_objmgr_peer_obj_create( wlan_peer_set_macaddr(peer, macaddr); /* initialize peer state */ wlan_peer_mlme_set_state(peer, WLAN_INIT_STATE); + qdf_atomic_init(&peer->peer_objmgr.ref_cnt); /* Attach peer to psoc, psoc maintains the node table for the device */ if (wlan_objmgr_psoc_peer_attach(psoc, peer) != QDF_STATUS_SUCCESS) { @@ -118,11 +160,12 @@ struct wlan_objmgr_peer *wlan_objmgr_peer_obj_create( qdf_mem_free(peer); return NULL; } - /* init spinlock */ qdf_spinlock_create(&peer->peer_lock); + wlan_objmgr_peer_get_ref(peer, WLAN_OBJMGR_ID); /* Increment ref count for BSS peer, so that BSS peer deletes last*/ if ((type == WLAN_PEER_STA) || (type == WLAN_PEER_STA_TEMP)) - wlan_objmgr_peer_ref_peer(wlan_vdev_get_bsspeer(vdev)); + wlan_objmgr_peer_get_ref(wlan_vdev_get_bsspeer(vdev), + WLAN_OBJMGR_ID); /* TODO init other parameters */ /* Invoke registered create handlers */ for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { @@ -159,40 +202,27 @@ struct wlan_objmgr_peer *wlan_objmgr_peer_obj_create( return peer; } -QDF_STATUS wlan_objmgr_peer_obj_delete(struct wlan_objmgr_peer *peer) +static QDF_STATUS wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer *peer) { uint8_t id; - wlan_objmgr_peer_delete_handler handler; + wlan_objmgr_peer_destroy_handler handler; QDF_STATUS obj_status; void *arg; - struct wlan_objmgr_psoc *psoc; - struct wlan_objmgr_vdev *vdev; if (peer == NULL) { qdf_print("%s: PEER is NULL\n", __func__); return QDF_STATUS_E_FAILURE; } - /* get VDEV from peer, if it is NULL, return */ - vdev = wlan_peer_get_vdev(peer); - if (vdev == NULL) { - qdf_print("%s: VDEV is NULL\n", __func__); - return QDF_STATUS_E_FAILURE; - } - /* get PSOC from VDEV, if it is NULL, return */ - psoc = wlan_vdev_get_psoc(vdev); - if (psoc == NULL) { - qdf_print("%s: PSOC is NULL\n", __func__); - return QDF_STATUS_E_FAILURE; - } - /* Decrement ref count for BSS peer, so that BSS peer deletes last*/ - if ((wlan_peer_get_peer_type(peer) == WLAN_PEER_STA) || - (wlan_peer_get_peer_type(peer) == WLAN_PEER_STA_TEMP)) - wlan_objmgr_peer_unref_peer(wlan_vdev_get_bsspeer(vdev)); - /* Invoke registered delete handlers */ + if (peer->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) { + qdf_print("%s:peer object delete is not invoked\n", __func__); + WLAN_OBJMGR_BUG(0); + } + + /* Invoke registered destroy handlers */ for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { - handler = g_umac_glb_obj->peer_delete_handler[id]; - arg = g_umac_glb_obj->peer_delete_handler_arg[id]; + handler = g_umac_glb_obj->peer_destroy_handler[id]; + arg = g_umac_glb_obj->peer_destroy_handler_arg[id]; if (handler != NULL) peer->obj_status[id] = handler(peer, arg); else @@ -209,27 +239,31 @@ QDF_STATUS wlan_objmgr_peer_obj_delete(struct wlan_objmgr_peer *peer) if (obj_status == QDF_STATUS_COMP_ASYNC) { peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED; return QDF_STATUS_COMP_ASYNC; - } else { - /* Detach peer from VDEV's peer list */ - if (wlan_objmgr_vdev_peer_detach(vdev, peer) - == QDF_STATUS_E_FAILURE) { - qdf_print("%s: Peer VDEV detach failure\n", __func__); - return QDF_STATUS_E_FAILURE; - } - /* Detach peer from PSOC's peer list */ - if (wlan_objmgr_psoc_peer_detach(psoc, peer) - == QDF_STATUS_E_FAILURE) { - qdf_print("%s: Peer PSOC detach failure\n", __func__); - return QDF_STATUS_E_FAILURE; - } - /* destroy spinlock */ - qdf_spinlock_destroy(&peer->peer_lock); - /* Free memory */ - qdf_mem_free(peer); } - return QDF_STATUS_SUCCESS; + + /* Free the peer object */ + return wlan_objmgr_peer_obj_free(peer); } +QDF_STATUS wlan_objmgr_peer_obj_delete(struct wlan_objmgr_peer *peer) +{ + if (peer == NULL) { + qdf_print("%s: PEER is NULL\n", __func__); + return QDF_STATUS_E_FAILURE; + } + + /** + * Update VDEV object state to LOGICALLY DELETED + * It prevents further access of this object + */ + wlan_peer_obj_lock(peer); + peer->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED; + wlan_peer_obj_unlock(peer); + wlan_objmgr_peer_release_ref(peer, WLAN_OBJMGR_ID); + + return QDF_STATUS_SUCCESS; +} +EXPORT_SYMBOL(wlan_objmgr_peer_obj_delete); /** ** APIs to attach/detach component objects */ @@ -295,27 +329,11 @@ QDF_STATUS wlan_objmgr_peer_component_obj_detach( void *comp_priv_obj) { QDF_STATUS obj_status; - struct wlan_objmgr_psoc *psoc; - struct wlan_objmgr_vdev *vdev; /* component id is invalid */ if (id >= WLAN_UMAC_MAX_COMPONENTS) return QDF_STATUS_MAXCOMP_FAIL; - /* get VDEV from peer, if it is NULL, return */ - vdev = wlan_peer_get_vdev(peer); - if (vdev == NULL) { - qdf_print("%s: VDEV is NULL\n", __func__); - return QDF_STATUS_E_FAILURE; - } - - /* get PSOC from VDEV, if it is NULL, return */ - psoc = wlan_vdev_get_psoc(vdev); - if (psoc == NULL) { - qdf_print("%s: PSOC is NULL\n", __func__); - return QDF_STATUS_E_FAILURE; - } - wlan_peer_obj_lock(peer); /* If there is a invalid entry, return failure */ if (peer->peer_comp_priv_obj[id] != comp_priv_obj) { @@ -328,7 +346,7 @@ QDF_STATUS wlan_objmgr_peer_component_obj_detach( peer->obj_status[id] = QDF_STATUS_SUCCESS; wlan_peer_obj_unlock(peer); - /* If PEER object status is partially deleted means, this API is + /* If PEER object status is partially destroyed means, this API is invoked with differnt context, this block should be executed for async components only */ if ((peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) || @@ -361,22 +379,11 @@ QDF_STATUS wlan_objmgr_peer_component_obj_detach( /* Delete peer object */ if ((obj_status == QDF_STATUS_SUCCESS) && (peer->obj_state == WLAN_OBJ_STATE_DELETED)) { - /* delete peer from vdev's peer list */ - if (wlan_objmgr_vdev_peer_detach(vdev, peer) == - QDF_STATUS_E_FAILURE) - return QDF_STATUS_E_FAILURE; - - /* delete peer from psoc's peer list */ - if (wlan_objmgr_psoc_peer_detach(psoc, peer) == - QDF_STATUS_E_FAILURE) - return QDF_STATUS_E_FAILURE; - /* Destroy spinlock */ - qdf_spinlock_destroy(&peer->peer_lock); - /* free memory */ - qdf_mem_free(peer); - return QDF_STATUS_SUCCESS; + /* Free the peer object */ + return wlan_objmgr_peer_obj_free(peer); } } + return QDF_STATUS_SUCCESS; } @@ -429,7 +436,7 @@ QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_deletion( struct wlan_objmgr_peer *peer, enum wlan_umac_comp_id id) { - wlan_objmgr_peer_delete_handler handler; + wlan_objmgr_peer_destroy_handler handler; void *arg; QDF_STATUS obj_status = QDF_STATUS_SUCCESS; @@ -446,9 +453,9 @@ QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_deletion( wlan_peer_obj_unlock(peer); - /* Invoke registered delete handlers */ - handler = g_umac_glb_obj->peer_delete_handler[id]; - arg = g_umac_glb_obj->peer_delete_handler_arg[id]; + /* Invoke registered destroy handlers */ + handler = g_umac_glb_obj->peer_destroy_handler[id]; + arg = g_umac_glb_obj->peer_destroy_handler_arg[id]; if (handler != NULL) peer->obj_status[id] = handler(peer, arg); else @@ -487,3 +494,65 @@ void *wlan_objmgr_peer_get_comp_private_obj( return comp_priv_obj; } EXPORT_SYMBOL(wlan_objmgr_peer_get_comp_private_obj); + +void wlan_objmgr_peer_get_ref(struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid id) +{ + if (peer == NULL) { + qdf_print("%s: peer obj is NULL\n", __func__); + QDF_ASSERT(0); + return; + } + /* Increment ref count */ + qdf_atomic_inc(&peer->peer_objmgr.ref_cnt); + + return; +} +EXPORT_SYMBOL(wlan_objmgr_peer_get_ref); + +QDF_STATUS wlan_objmgr_peer_try_get_ref(struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid id) +{ + if (peer == NULL) { + qdf_print("%s: peer obj is NULL\n", __func__); + QDF_ASSERT(0); + return QDF_STATUS_E_FAILURE; + } + + wlan_peer_obj_lock(peer); + if (peer->obj_state == WLAN_OBJ_STATE_LOGICALLY_DELETED) { + wlan_peer_obj_unlock(peer); + qdf_print("%s: peer obj is in Deletion Progress state\n", + __func__); + return QDF_STATUS_E_RESOURCES; + } + + wlan_objmgr_peer_get_ref(peer, id); + wlan_peer_obj_unlock(peer); + + return QDF_STATUS_SUCCESS; +} +EXPORT_SYMBOL(wlan_objmgr_peer_try_get_ref); + +void wlan_objmgr_peer_release_ref(struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid id) +{ + if (peer == NULL) { + qdf_print("%s: peer obj is NULL\n", __func__); + QDF_ASSERT(0); + return; + } + + if (!qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) { + qdf_print("%s: peer ref cnt is 0\n", __func__); + WLAN_OBJMGR_BUG(0); + return; + } + + /* Decrement ref count, free vdev, if ref acount == 0 */ + if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt)) + wlan_objmgr_peer_obj_destroy(peer); + + return; +} +EXPORT_SYMBOL(wlan_objmgr_peer_release_ref); 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 823240b04b1c..448dc97c1e4d 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 @@ -86,6 +86,20 @@ static void wlan_objmgr_psoc_peer_list_deinit(struct wlan_peer_list *peer_list) for (i = 0; i < WLAN_PEER_HASHSIZE; i++) qdf_list_destroy(&peer_list->peer_hash[i]); } + +static QDF_STATUS wlan_objmgr_psoc_obj_free(struct wlan_objmgr_psoc *psoc) +{ + /* Detach PSOC from global object's psoc list */ + if (wlan_objmgr_psoc_object_detach(psoc) == QDF_STATUS_E_FAILURE) { + qdf_print("%s: PSOC object detach failed\n", __func__); + return QDF_STATUS_E_FAILURE; + } + wlan_objmgr_psoc_peer_list_deinit(&psoc->soc_objmgr.peer_list); + qdf_spinlock_destroy(&psoc->psoc_lock); + qdf_mem_free(psoc); + + return QDF_STATUS_SUCCESS; +} /* * wlan_objmgr_psco_create_handler would return following status values */ @@ -106,7 +120,6 @@ struct wlan_objmgr_psoc *wlan_objmgr_psoc_obj_create(uint32_t phy_version, qdf_print("%s: PSOC allocation failed\n", __func__); return NULL; } - /* Init spinlock */ qdf_spinlock_create(&psoc->psoc_lock); /* Initialize with default values */ objmgr = &psoc->soc_objmgr; @@ -114,11 +127,13 @@ struct wlan_objmgr_psoc *wlan_objmgr_psoc_obj_create(uint32_t phy_version, objmgr->wlan_vdev_count = 0; objmgr->max_vdev_count = WLAN_UMAC_PSOC_MAX_VDEVS; objmgr->wlan_peer_count = 0; + qdf_atomic_init(&objmgr->ref_cnt); /* set phy version, dev_type in psoc */ wlan_psoc_set_nif_phy_version(psoc, phy_version); wlan_psoc_set_dev_type(psoc, dev_type); /* Initialize peer list */ wlan_objmgr_psoc_peer_list_init(&objmgr->peer_list); + wlan_objmgr_psoc_get_ref(psoc, WLAN_OBJMGR_ID); /* Invoke registered create handlers */ for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { handler = g_umac_glb_obj->psoc_create_handler[id]; @@ -167,10 +182,10 @@ struct wlan_objmgr_psoc *wlan_objmgr_psoc_obj_create(uint32_t phy_version, } EXPORT_SYMBOL(wlan_objmgr_psoc_obj_create); -QDF_STATUS wlan_objmgr_psoc_obj_delete(struct wlan_objmgr_psoc *psoc) +static QDF_STATUS wlan_objmgr_psoc_obj_destroy(struct wlan_objmgr_psoc *psoc) { uint8_t id; - wlan_objmgr_psoc_delete_handler handler; + wlan_objmgr_psoc_destroy_handler handler; QDF_STATUS obj_status; void *arg; @@ -180,10 +195,15 @@ QDF_STATUS wlan_objmgr_psoc_obj_delete(struct wlan_objmgr_psoc *psoc) return QDF_STATUS_E_FAILURE; } + if (psoc->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) { + qdf_print("%s:psoc object delete is not invoked\n", __func__); + WLAN_OBJMGR_BUG(0); + } + /* Invoke registered create handlers */ for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { - handler = g_umac_glb_obj->psoc_delete_handler[id]; - arg = g_umac_glb_obj->psoc_delete_handler_arg[id]; + handler = g_umac_glb_obj->psoc_destroy_handler[id]; + arg = g_umac_glb_obj->psoc_destroy_handler_arg[id]; if (handler != NULL) psoc->obj_status[id] = handler(psoc, arg); else @@ -203,20 +223,28 @@ QDF_STATUS wlan_objmgr_psoc_obj_delete(struct wlan_objmgr_psoc *psoc) if (obj_status == QDF_STATUS_COMP_ASYNC) { psoc->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED; return QDF_STATUS_COMP_ASYNC; - } else { - /* Detach PSOC from global object's psoc list */ - if (wlan_objmgr_psoc_object_detach(psoc) == - QDF_STATUS_E_FAILURE) { - qdf_print("%s: PSOC object detach failed\n", __func__); - return QDF_STATUS_E_FAILURE; - } - wlan_objmgr_psoc_peer_list_deinit(&psoc->soc_objmgr.peer_list); - /* Destroy spinlock */ - qdf_spinlock_destroy(&psoc->psoc_lock); - /* Free the memory */ - qdf_mem_free(psoc); } + /* Free psoc object */ + return wlan_objmgr_psoc_obj_free(psoc); +} + + +QDF_STATUS wlan_objmgr_psoc_obj_delete(struct wlan_objmgr_psoc *psoc) +{ + if (psoc == NULL) { + qdf_print("%s:psoc is NULL\n", __func__); + return QDF_STATUS_E_FAILURE; + } + /* + * Update PSOC object state to LOGICALLY DELETED + * It prevents further access of this object + */ + wlan_psoc_obj_lock(psoc); + psoc->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED; + wlan_psoc_obj_unlock(psoc); + wlan_objmgr_psoc_release_ref(psoc, WLAN_OBJMGR_ID); + return QDF_STATUS_SUCCESS; } EXPORT_SYMBOL(wlan_objmgr_psoc_obj_delete); @@ -248,6 +276,7 @@ QDF_STATUS wlan_objmgr_psoc_component_obj_attach( /* Save component's pointer and status */ psoc->soc_comp_priv_obj[id] = comp_priv_obj; psoc->obj_status[id] = status; + wlan_psoc_obj_unlock(psoc); if (psoc->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED) @@ -345,17 +374,8 @@ QDF_STATUS wlan_objmgr_psoc_component_obj_detach( /* Delete psoc object */ if ((obj_status == QDF_STATUS_SUCCESS) && (psoc->obj_state == WLAN_OBJ_STATE_DELETED)) { - /* Detach PSOC from global object's psoc list */ - if (wlan_objmgr_psoc_object_detach(psoc) == - QDF_STATUS_E_FAILURE) - return QDF_STATUS_E_FAILURE; - - wlan_objmgr_psoc_peer_list_deinit( - &psoc->soc_objmgr.peer_list); - /* Destroy spinlock */ - qdf_spinlock_destroy(&psoc->psoc_lock); - /* Free memory */ - qdf_mem_free(psoc); + /* Free psoc object */ + return wlan_objmgr_psoc_obj_free(psoc); } } @@ -370,13 +390,16 @@ QDF_STATUS wlan_objmgr_iterate_obj_list( struct wlan_objmgr_psoc *psoc, enum wlan_objmgr_obj_type obj_type, wlan_objmgr_op_handler handler, - void *arg, uint8_t lock_free_op) + 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; @@ -390,24 +413,26 @@ QDF_STATUS wlan_objmgr_iterate_obj_list( 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++) { - if (objmgr->wlan_pdev_list[obj_id] != NULL) { - /* TODO increment ref count */ - handler(psoc, - (void *)objmgr->wlan_pdev_list[obj_id], - arg); - /* TODO decrement ref count */ + pdev = objmgr->wlan_pdev_list[obj_id]; + if ((pdev != NULL) && + (pdev->obj_state != + WLAN_OBJ_STATE_LOGICALLY_DELETED)) { + 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++) { - if (objmgr->wlan_vdev_list[obj_id] != NULL) { - /* TODO increment ref count */ - handler(psoc, - (void *)objmgr->wlan_vdev_list[obj_id], - arg); - /* TODO decrement ref count */ + vdev = objmgr->wlan_vdev_list[obj_id]; + if ((vdev != NULL) && + (vdev->obj_state != + WLAN_OBJ_STATE_LOGICALLY_DELETED)) { + wlan_objmgr_vdev_get_ref(vdev, dbg_id); + handler(psoc, vdev, arg); + wlan_objmgr_vdev_release_ref(vdev, dbg_id); } } break; @@ -422,16 +447,15 @@ QDF_STATUS wlan_objmgr_iterate_obj_list( obj_list = &peer_list->peer_hash[i]; peer = wlan_psoc_peer_list_peek_head(obj_list); while (peer) { - /* Increment ref count, to hold the - peer pointer */ - wlan_objmgr_peer_ref_peer(peer); - handler(psoc, (void *)peer, arg); /* Get next peer */ peer_next = wlan_peer_get_next_peer_of_psoc( obj_list, peer); - /* Decrement ref count, this can lead - to peer deletion also */ - wlan_objmgr_peer_unref_peer(peer); + if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) + == QDF_STATUS_SUCCESS) { + handler(psoc, (void *)peer, arg); + wlan_objmgr_peer_release_ref(peer, + dbg_id); + } peer = peer_next; } } @@ -477,13 +501,16 @@ QDF_STATUS wlan_objmgr_free_all_objects_per_psoc( { /* Free all peers */ wlan_objmgr_iterate_obj_list(psoc, WLAN_PEER_OP, - wlan_objmgr_psoc_peer_delete, NULL, 1); + wlan_objmgr_psoc_peer_delete, NULL, 1, + WLAN_OBJMGR_ID); /* Free all vdevs */ wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP, - wlan_objmgr_psoc_vdev_delete, NULL, 1); + wlan_objmgr_psoc_vdev_delete, NULL, 1, + WLAN_OBJMGR_ID); /* Free all PDEVs */ wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, - wlan_objmgr_psoc_pdev_delete, NULL, 1); + wlan_objmgr_psoc_pdev_delete, NULL, 1, + WLAN_OBJMGR_ID); return QDF_STATUS_SUCCESS; } @@ -535,7 +562,7 @@ QDF_STATUS wlan_objmgr_trigger_psoc_comp_priv_object_deletion( struct wlan_objmgr_psoc *psoc, enum wlan_umac_comp_id id) { - wlan_objmgr_psoc_delete_handler handler; + wlan_objmgr_psoc_destroy_handler handler; void *arg; QDF_STATUS obj_status = QDF_STATUS_SUCCESS; @@ -551,8 +578,8 @@ QDF_STATUS wlan_objmgr_trigger_psoc_comp_priv_object_deletion( } wlan_psoc_obj_unlock(psoc); /* Invoke registered create handlers */ - handler = g_umac_glb_obj->psoc_delete_handler[id]; - arg = g_umac_glb_obj->psoc_delete_handler_arg[id]; + handler = g_umac_glb_obj->psoc_destroy_handler[id]; + arg = g_umac_glb_obj->psoc_destroy_handler_arg[id]; if (handler != NULL) psoc->obj_status[id] = handler(psoc, arg); else @@ -600,6 +627,8 @@ QDF_STATUS wlan_objmgr_psoc_pdev_attach(struct wlan_objmgr_psoc *psoc, /* save pdev id */ pdev->pdev_objmgr.wlan_pdev_id = id; status = QDF_STATUS_SUCCESS; + /* Inrement psoc ref count to block its free before pdev */ + wlan_objmgr_psoc_get_ref(psoc, WLAN_OBJMGR_ID); } wlan_psoc_obj_unlock(psoc); @@ -625,12 +654,15 @@ QDF_STATUS wlan_objmgr_psoc_pdev_detach(struct wlan_objmgr_psoc *psoc, objmgr->wlan_pdev_count--; pdev->pdev_objmgr.wlan_pdev_id = 0xff; wlan_psoc_obj_unlock(psoc); + /* Release ref count of psoc */ + wlan_objmgr_psoc_release_ref(psoc, WLAN_OBJMGR_ID); return QDF_STATUS_SUCCESS; } -struct wlan_objmgr_pdev *wlan_objmgr_find_pdev_by_id( - struct wlan_objmgr_psoc *psoc, uint8_t id) +struct wlan_objmgr_pdev *wlan_objmgr_get_pdev_by_id( + struct wlan_objmgr_psoc *psoc, uint8_t id, + wlan_objmgr_ref_dbgid dbg_id) { struct wlan_objmgr_psoc_objmgr *objmgr; struct wlan_objmgr_pdev *pdev = NULL; @@ -639,11 +671,37 @@ struct wlan_objmgr_pdev *wlan_objmgr_find_pdev_by_id( objmgr = &psoc->soc_objmgr; /* get pdev from pdev list */ pdev = objmgr->wlan_pdev_list[id]; + /* Do not return object, if it is not CREATED state */ + if (pdev != NULL) { + if (wlan_objmgr_pdev_try_get_ref(pdev, dbg_id) != + QDF_STATUS_SUCCESS) + pdev = NULL; + } + wlan_psoc_obj_unlock(psoc); return pdev; } +struct wlan_objmgr_pdev *wlan_objmgr_get_pdev_by_id_no_state( + struct wlan_objmgr_psoc *psoc, uint8_t id, + wlan_objmgr_ref_dbgid dbg_id) +{ + struct wlan_objmgr_psoc_objmgr *objmgr; + struct wlan_objmgr_pdev *pdev = NULL; + + wlan_psoc_obj_lock(psoc); + objmgr = &psoc->soc_objmgr; + /* get pdev from pdev list */ + pdev = objmgr->wlan_pdev_list[id]; + /* Do not return object, if it is not CREATED state */ + if (pdev != NULL) + wlan_objmgr_pdev_get_ref(pdev, dbg_id); + + wlan_psoc_obj_unlock(psoc); + + return pdev; +} QDF_STATUS wlan_objmgr_psoc_vdev_attach(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_vdev *vdev) { @@ -724,8 +782,9 @@ QDF_STATUS wlan_objmgr_psoc_vdev_detach(struct wlan_objmgr_psoc *psoc, } -struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_id_from_psoc( - struct wlan_objmgr_psoc *psoc, uint8_t vdev_id) +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_psoc( + struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, + wlan_objmgr_ref_dbgid dbg_id) { struct wlan_objmgr_vdev *vdev; @@ -739,13 +798,45 @@ struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_id_from_psoc( wlan_psoc_obj_lock(psoc); /* retrieve vdev pointer from vdev list */ vdev = psoc->soc_objmgr.wlan_vdev_list[vdev_id]; + if (vdev != NULL) { + if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) != + QDF_STATUS_SUCCESS) + vdev = NULL; + } wlan_psoc_obj_unlock(psoc); return vdev; } +EXPORT_SYMBOL(wlan_objmgr_get_vdev_by_id_from_psoc); -struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_macaddr_from_psoc( - struct wlan_objmgr_psoc *psoc, uint8_t *macaddr) +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_psoc_no_state( + struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, + wlan_objmgr_ref_dbgid dbg_id) +{ + struct wlan_objmgr_vdev *vdev; + + /* if PSOC is NULL, return */ + if (psoc == NULL) + return NULL; + /* vdev id is invalid */ + if (vdev_id >= WLAN_UMAC_PSOC_MAX_VDEVS) + return NULL; + + wlan_psoc_obj_lock(psoc); + /* retrieve vdev pointer from vdev list */ + vdev = psoc->soc_objmgr.wlan_vdev_list[vdev_id]; + if (vdev != NULL) + wlan_objmgr_vdev_get_ref(vdev, dbg_id); + + wlan_psoc_obj_unlock(psoc); + + return vdev; +} +EXPORT_SYMBOL(wlan_objmgr_get_vdev_by_id_from_psoc_no_state); + +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_psoc( + struct wlan_objmgr_psoc *psoc, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id) { struct wlan_objmgr_vdev *vdev; uint8_t id; @@ -763,7 +854,12 @@ struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_macaddr_from_psoc( /* MAC address matches, break */ if (WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), macaddr) == QDF_STATUS_SUCCESS) { + if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) != + QDF_STATUS_SUCCESS) + vdev = NULL; + wlan_psoc_obj_unlock(psoc); + return vdev; } } @@ -771,6 +867,39 @@ struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_macaddr_from_psoc( return NULL; } +EXPORT_SYMBOL(wlan_objmgr_get_vdev_by_macaddr_from_psoc); + +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_psoc_no_state( + struct wlan_objmgr_psoc *psoc, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id) +{ + struct wlan_objmgr_vdev *vdev; + uint8_t id; + + /* if PSOC is NULL, return */ + if (psoc == NULL) + return NULL; + + wlan_psoc_obj_lock(psoc); + /* Iterate through PSOC's vdev list */ + for (id = 0; id < WLAN_UMAC_PSOC_MAX_VDEVS; id++) { + vdev = psoc->soc_objmgr.wlan_vdev_list[id]; + if (vdev == NULL) + continue; + /* MAC address matches, break */ + if (WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), macaddr) + == QDF_STATUS_SUCCESS) { + wlan_objmgr_vdev_get_ref(vdev, dbg_id); + wlan_psoc_obj_unlock(psoc); + + return vdev; + } + } + wlan_psoc_obj_unlock(psoc); + + return NULL; +} +EXPORT_SYMBOL(wlan_objmgr_get_vdev_by_macaddr_from_psoc_no_state); static void wlan_obj_psoc_peerlist_add_tail(qdf_list_t *obj_list, struct wlan_objmgr_peer *obj) @@ -818,7 +947,8 @@ static QDF_STATUS wlan_peer_bssid_match(struct wlan_objmgr_peer *peer, * NULL on FAILURE */ static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer( - qdf_list_t *obj_list, uint8_t *macaddr) + qdf_list_t *obj_list, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id) { struct wlan_objmgr_peer *peer; struct wlan_objmgr_peer *peer_temp; @@ -829,8 +959,44 @@ static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer( /* For peer, macaddr is key */ if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) == QDF_STATUS_SUCCESS) { - /* Increment ref count for access */ - wlan_objmgr_peer_ref_peer(peer); + if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) != + QDF_STATUS_SUCCESS) { + /* BSS peer can have multiple peer instances. + * Iterate through the list to return the + * active peer incase of BSS else return NULL. + */ + if (wlan_peer_get_peer_type(peer) != + WLAN_PEER_AP) + return NULL; + + } else { + return peer; + } + } + /* Move to next peer */ + peer_temp = peer; + peer = wlan_peer_get_next_peer_of_psoc(obj_list, peer_temp); + } + + /* Not found, return NULL */ + return NULL; +} + +static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer_no_state( + qdf_list_t *obj_list, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id) +{ + struct wlan_objmgr_peer *peer; + struct wlan_objmgr_peer *peer_temp; + + /* Iterate through hash list to get the peer */ + peer = wlan_psoc_peer_list_peek_head(obj_list); + while (peer != NULL) { + /* For peer, macaddr is key */ + if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) + == QDF_STATUS_SUCCESS) { + wlan_objmgr_peer_get_ref(peer, dbg_id); + return peer; } /* Move to next peer */ @@ -858,7 +1024,8 @@ static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer( */ static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid( qdf_list_t *obj_list, uint8_t *macaddr, - uint8_t *bssid) + uint8_t *bssid, + wlan_objmgr_ref_dbgid dbg_id) { struct wlan_objmgr_peer *peer; struct wlan_objmgr_peer *peer_temp; @@ -876,8 +1043,46 @@ static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid( */ if (wlan_peer_bssid_match(peer, bssid) == QDF_STATUS_SUCCESS) { - /* Increment ref count for access */ - wlan_objmgr_peer_ref_peer(peer); + if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) + != QDF_STATUS_SUCCESS) + peer = NULL; + + return peer; + } + } + /* Move to next peer */ + peer_temp = peer; + peer = wlan_peer_get_next_peer_of_psoc(obj_list, peer_temp); + } + + /* Not found, return NULL */ + return NULL; +} + +static struct wlan_objmgr_peer + *wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid_no_state( + qdf_list_t *obj_list, uint8_t *macaddr, + uint8_t *bssid, + wlan_objmgr_ref_dbgid dbg_id) +{ + struct wlan_objmgr_peer *peer; + struct wlan_objmgr_peer *peer_temp; + + /* Iterate through hash list to get the peer */ + peer = wlan_psoc_peer_list_peek_head(obj_list); + while (peer != NULL) { + /* For peer, macaddr is key */ + if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) + == QDF_STATUS_SUCCESS) { + /* + * BSSID match is requested by caller, check BSSID + * (vdev mac == bssid) -- return peer + * (vdev mac != bssid) -- perform next iteration + */ + if (wlan_peer_bssid_match(peer, bssid) == + QDF_STATUS_SUCCESS) { + wlan_objmgr_peer_get_ref(peer, dbg_id); + return peer; } } @@ -958,8 +1163,9 @@ QDF_STATUS wlan_objmgr_psoc_peer_detach(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_SUCCESS; } -struct wlan_objmgr_peer *wlan_objmgr_find_peer( - struct wlan_objmgr_psoc *psoc, uint8_t *macaddr) +struct wlan_objmgr_peer *wlan_objmgr_get_peer( + struct wlan_objmgr_psoc *psoc, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id) { struct wlan_objmgr_psoc_objmgr *objmgr; uint8_t hash_index; @@ -980,16 +1186,48 @@ struct wlan_objmgr_peer *wlan_objmgr_find_peer( qdf_spin_lock_bh(&peer_list->peer_list_lock); /* Iterate through peer list, get peer */ peer = wlan_obj_psoc_peerlist_get_peer( - &peer_list->peer_hash[hash_index], macaddr); + &peer_list->peer_hash[hash_index], macaddr, dbg_id); qdf_spin_unlock_bh(&peer_list->peer_list_lock); wlan_psoc_obj_unlock(psoc); return peer; } +EXPORT_SYMBOL(wlan_objmgr_get_peer); -struct wlan_objmgr_peer *wlan_objmgr_find_peer_by_mac_n_vdev( +struct wlan_objmgr_peer *wlan_objmgr_get_peer_no_state( struct wlan_objmgr_psoc *psoc, uint8_t *macaddr, - uint8_t *bssid) + wlan_objmgr_ref_dbgid dbg_id) +{ + struct wlan_objmgr_psoc_objmgr *objmgr; + uint8_t hash_index; + struct wlan_objmgr_peer *peer = NULL; + struct wlan_peer_list *peer_list; + + /* psoc lock should be taken before peer list lock */ + wlan_psoc_obj_lock(psoc); + objmgr = &psoc->soc_objmgr; + /* List is empty, return NULL */ + if (objmgr->wlan_peer_count == 0) { + wlan_psoc_obj_unlock(psoc); + return NULL; + } + /* reduce the search window, with hash key */ + hash_index = WLAN_PEER_HASH(macaddr); + peer_list = &objmgr->peer_list; + qdf_spin_lock_bh(&peer_list->peer_list_lock); + /* Iterate through peer list, get peer */ + peer = wlan_obj_psoc_peerlist_get_peer_no_state( + &peer_list->peer_hash[hash_index], macaddr, dbg_id); + qdf_spin_unlock_bh(&peer_list->peer_list_lock); + wlan_psoc_obj_unlock(psoc); + + return peer; +} +EXPORT_SYMBOL(wlan_objmgr_get_peer_no_state); + +struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac_n_vdev( + struct wlan_objmgr_psoc *psoc, uint8_t *macaddr, + uint8_t *bssid, wlan_objmgr_ref_dbgid dbg_id) { struct wlan_objmgr_psoc_objmgr *objmgr; uint8_t hash_index; @@ -1010,12 +1248,44 @@ struct wlan_objmgr_peer *wlan_objmgr_find_peer_by_mac_n_vdev( qdf_spin_lock_bh(&peer_list->peer_list_lock); /* Iterate through peer list, get peer */ peer = wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid( - &peer_list->peer_hash[hash_index], macaddr, bssid); + &peer_list->peer_hash[hash_index], macaddr, bssid, dbg_id); qdf_spin_unlock_bh(&peer_list->peer_list_lock); wlan_psoc_obj_unlock(psoc); return peer; } +EXPORT_SYMBOL(wlan_objmgr_get_peer_by_mac_n_vdev); + +struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac_n_vdev_no_state( + struct wlan_objmgr_psoc *psoc, uint8_t *macaddr, + uint8_t *bssid, wlan_objmgr_ref_dbgid dbg_id) +{ + struct wlan_objmgr_psoc_objmgr *objmgr; + uint8_t hash_index; + struct wlan_objmgr_peer *peer = NULL; + struct wlan_peer_list *peer_list; + + /* psoc lock should be taken before peer list lock */ + wlan_psoc_obj_lock(psoc); + objmgr = &psoc->soc_objmgr; + /* List is empty, return NULL */ + if (objmgr->wlan_peer_count == 0) { + wlan_psoc_obj_unlock(psoc); + return NULL; + } + /* reduce the search window, with hash key */ + hash_index = WLAN_PEER_HASH(macaddr); + peer_list = &objmgr->peer_list; + qdf_spin_lock_bh(&peer_list->peer_list_lock); + /* Iterate through peer list, get peer */ + peer = wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid_no_state( + &peer_list->peer_hash[hash_index], macaddr, bssid, dbg_id); + qdf_spin_unlock_bh(&peer_list->peer_list_lock); + wlan_psoc_obj_unlock(psoc); + + return peer; +} +EXPORT_SYMBOL(wlan_objmgr_get_peer_by_mac_n_vdev_no_state); void *wlan_objmgr_psoc_get_comp_private_obj(struct wlan_objmgr_psoc *psoc, enum wlan_umac_comp_id id) @@ -1040,3 +1310,66 @@ void *wlan_objmgr_psoc_get_comp_private_obj(struct wlan_objmgr_psoc *psoc, return comp_private_obj; } EXPORT_SYMBOL(wlan_objmgr_psoc_get_comp_private_obj); + +void wlan_objmgr_psoc_get_ref(struct wlan_objmgr_psoc *psoc, + wlan_objmgr_ref_dbgid id) +{ + if (psoc == NULL) { + qdf_print("%s: psoc obj is NULL\n", __func__); + QDF_ASSERT(0); + return; + } + /* Increment ref count */ + qdf_atomic_inc(&psoc->soc_objmgr.ref_cnt); + + return; +} +EXPORT_SYMBOL(wlan_objmgr_psoc_get_ref); + +QDF_STATUS wlan_objmgr_psoc_try_get_ref(struct wlan_objmgr_psoc *psoc, + wlan_objmgr_ref_dbgid id) +{ + if (psoc == NULL) { + qdf_print("%s: psoc obj is NULL\n", __func__); + QDF_ASSERT(0); + return QDF_STATUS_E_FAILURE; + } + + wlan_psoc_obj_lock(psoc); + if (psoc->obj_state == WLAN_OBJ_STATE_LOGICALLY_DELETED) { + wlan_psoc_obj_unlock(psoc); + qdf_print("%s: psoc obj is in Deletion Progress staet\n", + __func__); + return QDF_STATUS_E_RESOURCES; + } + + /* Increment ref count */ + wlan_objmgr_psoc_get_ref(psoc, id); + wlan_psoc_obj_unlock(psoc); + + return QDF_STATUS_SUCCESS; +} +EXPORT_SYMBOL(wlan_objmgr_psoc_try_get_ref); + +void wlan_objmgr_psoc_release_ref(struct wlan_objmgr_psoc *psoc, + wlan_objmgr_ref_dbgid id) +{ + if (psoc == NULL) { + qdf_print("%s: psoc obj is NULL\n", __func__); + QDF_ASSERT(0); + return; + } + + if (!qdf_atomic_read(&psoc->soc_objmgr.ref_cnt)) { + qdf_print("%s: psoc ref cnt is 0\n", __func__); + WLAN_OBJMGR_BUG(0); + return; + } + + /* Decrement ref count, free psoc, if ref count == 0 */ + if (qdf_atomic_dec_and_test(&psoc->soc_objmgr.ref_cnt)) + wlan_objmgr_psoc_obj_destroy(psoc); + + return; +} +EXPORT_SYMBOL(wlan_objmgr_psoc_release_ref); diff --git a/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c b/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c index b6d75be55935..fc6259466046 100644 --- a/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c +++ b/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c @@ -67,9 +67,39 @@ static QDF_STATUS wlan_objmgr_vdev_object_status( } } wlan_vdev_obj_unlock(vdev); + return status; } +static QDF_STATUS wlan_objmgr_vdev_obj_free(struct wlan_objmgr_vdev *vdev) +{ + struct wlan_objmgr_pdev *pdev; + + /* if PDEV is NULL, return */ + pdev = wlan_vdev_get_pdev(vdev); + if (pdev == NULL) { + qdf_print("%s:pdev is NULL\n", __func__); + return QDF_STATUS_E_FAILURE; + } + + /* Detach VDEV from PDEV VDEV's list */ + if (wlan_objmgr_pdev_vdev_detach(pdev, vdev) == + QDF_STATUS_E_FAILURE) + return QDF_STATUS_E_FAILURE; + + /* Detach VDEV from PSOC VDEV's list */ + if (wlan_objmgr_psoc_vdev_detach( + pdev->pdev_objmgr.wlan_psoc, vdev) == + QDF_STATUS_E_FAILURE) + return QDF_STATUS_E_FAILURE; + + qdf_spinlock_destroy(&vdev->vdev_lock); + qdf_mem_free(vdev); + + return QDF_STATUS_SUCCESS; + +} + struct wlan_objmgr_vdev *wlan_objmgr_vdev_obj_create( struct wlan_objmgr_pdev *pdev, struct wlan_vdev_create_params *params) @@ -129,6 +159,8 @@ struct wlan_objmgr_vdev *wlan_objmgr_vdev_obj_create( vdev->vdev_nif.osdev = params->osifp; /* peer count to 0 */ vdev->vdev_objmgr.wlan_peer_count = 0; + qdf_atomic_init(&vdev->vdev_objmgr.ref_cnt); + wlan_objmgr_vdev_get_ref(vdev, WLAN_OBJMGR_ID); /* Initialize max peer count based on opmode type */ if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) vdev->vdev_objmgr.max_peer_count = WLAN_UMAC_MAX_STA_PEERS; @@ -181,30 +213,29 @@ struct wlan_objmgr_vdev *wlan_objmgr_vdev_obj_create( } return vdev; } +EXPORT_SYMBOL(wlan_objmgr_vdev_obj_create); -QDF_STATUS wlan_objmgr_vdev_obj_delete(struct wlan_objmgr_vdev *vdev) +static QDF_STATUS wlan_objmgr_vdev_obj_destroy(struct wlan_objmgr_vdev *vdev) { uint8_t id; - wlan_objmgr_vdev_delete_handler handler; + wlan_objmgr_vdev_destroy_handler handler; QDF_STATUS obj_status; void *arg; - struct wlan_objmgr_pdev *pdev; if (vdev == NULL) { qdf_print("%s:vdev is NULL\n", __func__); return QDF_STATUS_E_FAILURE; } - /* if PDEV is NULL, return */ - pdev = wlan_vdev_get_pdev(vdev); - if (pdev == NULL) { - qdf_print("%s:pdev is NULL\n", __func__); - return QDF_STATUS_E_FAILURE; + + if (vdev->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) { + qdf_print("%s:vdev object delete is not invoked\n", __func__); + WLAN_OBJMGR_BUG(0); } /* Invoke registered create handlers */ for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { - handler = g_umac_glb_obj->vdev_delete_handler[id]; - arg = g_umac_glb_obj->vdev_delete_handler_arg[id]; + handler = g_umac_glb_obj->vdev_destroy_handler[id]; + arg = g_umac_glb_obj->vdev_destroy_handler_arg[id]; if (handler != NULL) vdev->obj_status[id] = handler(vdev, arg); else @@ -225,25 +256,30 @@ QDF_STATUS wlan_objmgr_vdev_obj_delete(struct wlan_objmgr_vdev *vdev) if (obj_status == QDF_STATUS_COMP_ASYNC) { vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED; return QDF_STATUS_COMP_ASYNC; - } else { - /* Detach VDEV from PDEV VDEV's list */ - if (wlan_objmgr_pdev_vdev_detach(pdev, vdev) == - QDF_STATUS_E_FAILURE) - return QDF_STATUS_E_FAILURE; - - /* Detach VDEV from PSOC VDEV's list */ - if (wlan_objmgr_psoc_vdev_detach( - pdev->pdev_objmgr.wlan_psoc, vdev) == - QDF_STATUS_E_FAILURE) - return QDF_STATUS_E_FAILURE; - - /* de-init lock */ - qdf_spinlock_destroy(&vdev->vdev_lock); - /* Free the memory */ - qdf_mem_free(vdev); } + + /* Free VDEV object */ + return wlan_objmgr_vdev_obj_free(vdev); +} + +QDF_STATUS wlan_objmgr_vdev_obj_delete(struct wlan_objmgr_vdev *vdev) +{ + if (vdev == NULL) { + qdf_print("%s:vdev is NULL\n", __func__); + return QDF_STATUS_E_FAILURE; + } + /* + * Update VDEV object state to LOGICALLY DELETED + * It prevents further access of this object + */ + wlan_vdev_obj_lock(vdev); + vdev->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED; + wlan_vdev_obj_unlock(vdev); + wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID); + return QDF_STATUS_SUCCESS; } +EXPORT_SYMBOL(wlan_objmgr_vdev_obj_delete); /** ** APIs to attach/detach component objects @@ -273,7 +309,6 @@ QDF_STATUS wlan_objmgr_vdev_component_obj_attach( vdev->vdev_comp_priv_obj[id] = comp_priv_obj; vdev->obj_status[id] = status; wlan_vdev_obj_unlock(vdev); - if (vdev->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED) return QDF_STATUS_SUCCESS; /* @@ -329,7 +364,7 @@ QDF_STATUS wlan_objmgr_vdev_component_obj_detach( wlan_vdev_obj_unlock(vdev); /** - *If VDEV object status is partially deleted means, this API is + *If VDEV object status is partially destroyed means, this API is * invoked with differnt context, this block should be executed for * async components only */ @@ -370,25 +405,13 @@ QDF_STATUS wlan_objmgr_vdev_component_obj_detach( /* Delete vdev object */ if ((obj_status == QDF_STATUS_SUCCESS) && (vdev->obj_state == WLAN_OBJ_STATE_DELETED)) { - /* Detach vdev object from psoc */ - if (wlan_objmgr_pdev_vdev_detach( - wlan_vdev_get_pdev(vdev), vdev) - == QDF_STATUS_E_FAILURE) - return QDF_STATUS_E_FAILURE; - /* Detach vdev object from psoc */ - if (wlan_objmgr_psoc_vdev_detach( - wlan_vdev_get_psoc(vdev), vdev) == - QDF_STATUS_E_FAILURE) - return QDF_STATUS_E_FAILURE; - - /* Destroy spinlock */ - qdf_spinlock_destroy(&vdev->vdev_lock); - /* Free VDEV memory */ - qdf_mem_free(vdev); + /* Free VDEV object */ + return wlan_objmgr_vdev_obj_free(vdev); } } return QDF_STATUS_SUCCESS; } +EXPORT_SYMBOL(wlan_objmgr_vdev_component_obj_detach); /** ** APIs to operations on vdev objects @@ -396,34 +419,43 @@ QDF_STATUS wlan_objmgr_vdev_component_obj_detach( QDF_STATUS wlan_objmgr_iterate_peerobj_list( struct wlan_objmgr_vdev *vdev, wlan_objmgr_vdev_op_handler handler, - void *arg) + void *arg, wlan_objmgr_ref_dbgid dbg_id) { qdf_list_t *peer_list = NULL; struct wlan_objmgr_peer *peer = NULL; - struct wlan_objmgr_peer *prev_peer = NULL; + struct wlan_objmgr_peer *peer_next = NULL; if (vdev == NULL) { qdf_print("%s: VDEV NULL\n", __func__); return QDF_STATUS_E_FAILURE; } - /* TODO increment ref count */ wlan_vdev_obj_lock(vdev); + + if (vdev->obj_state == + WLAN_OBJ_STATE_LOGICALLY_DELETED) { + wlan_vdev_obj_unlock(vdev); + qdf_print("%s: VDEV is in delete progress\n", __func__); + return QDF_STATUS_E_FAILURE; + } + wlan_objmgr_vdev_get_ref(vdev, dbg_id); peer_list = &vdev->vdev_objmgr.wlan_peer_list; if (peer_list != NULL) { /* Iterate through VDEV's peer list */ peer = wlan_vdev_peer_list_peek_head(peer_list); while (peer != NULL) { - wlan_objmgr_peer_ref_peer(peer); - /* Invoke handler for operation */ - handler(vdev, (void *)peer, arg); - prev_peer = peer; - peer = wlan_peer_get_next_peer_of_vdev(peer_list, - prev_peer); - wlan_objmgr_peer_unref_peer(prev_peer); + peer_next = wlan_peer_get_next_peer_of_vdev(peer_list, + peer); + if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) == + QDF_STATUS_SUCCESS) { + /* Invoke handler for operation */ + handler(vdev, (void *)peer, arg); + wlan_objmgr_peer_release_ref(peer, dbg_id); + } + peer = peer_next; } } + wlan_objmgr_vdev_release_ref(vdev, dbg_id); wlan_vdev_obj_unlock(vdev); - /* TODO decrement ref count */ return QDF_STATUS_SUCCESS; } @@ -475,7 +507,7 @@ QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_deletion( struct wlan_objmgr_vdev *vdev, enum wlan_umac_comp_id id) { - wlan_objmgr_vdev_delete_handler handler; + wlan_objmgr_vdev_destroy_handler handler; void *arg; QDF_STATUS obj_status = QDF_STATUS_SUCCESS; @@ -492,8 +524,8 @@ QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_deletion( wlan_vdev_obj_unlock(vdev); /* Invoke registered create handlers */ - handler = g_umac_glb_obj->vdev_delete_handler[id]; - arg = g_umac_glb_obj->vdev_delete_handler_arg[id]; + handler = g_umac_glb_obj->vdev_destroy_handler[id]; + arg = g_umac_glb_obj->vdev_destroy_handler_arg[id]; if (handler != NULL) vdev->obj_status[id] = handler(vdev, arg); else @@ -565,6 +597,8 @@ QDF_STATUS wlan_objmgr_vdev_peer_attach(struct wlan_objmgr_vdev *vdev, if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) wlan_vdev_set_bsspeer(vdev, peer); } + /* Increment vdev ref count to make sure it won't be destroyed before */ + wlan_objmgr_vdev_get_ref(vdev, WLAN_OBJMGR_ID); wlan_vdev_obj_unlock(vdev); return QDF_STATUS_SUCCESS; } @@ -589,6 +623,8 @@ QDF_STATUS wlan_objmgr_vdev_peer_detach(struct wlan_objmgr_vdev *vdev, /* decrement peer count */ objmgr->wlan_peer_count--; wlan_vdev_obj_unlock(vdev); + /* decrement vdev ref count after peer released its reference */ + wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID); return QDF_STATUS_SUCCESS; } @@ -616,3 +652,66 @@ void *wlan_objmgr_vdev_get_comp_private_obj( return comp_priv_obj; } EXPORT_SYMBOL(wlan_objmgr_vdev_get_comp_private_obj); + +void wlan_objmgr_vdev_get_ref(struct wlan_objmgr_vdev *vdev, + wlan_objmgr_ref_dbgid id) +{ + if (vdev == NULL) { + qdf_print("%s: vdev obj is NULL\n", __func__); + QDF_ASSERT(0); + return; + } + /* Increment ref count */ + qdf_atomic_inc(&vdev->vdev_objmgr.ref_cnt); + + return; +} +EXPORT_SYMBOL(wlan_objmgr_vdev_get_ref); + +QDF_STATUS wlan_objmgr_vdev_try_get_ref(struct wlan_objmgr_vdev *vdev, + wlan_objmgr_ref_dbgid id) +{ + if (vdev == NULL) { + qdf_print("%s: vdev obj is NULL\n", __func__); + QDF_ASSERT(0); + return QDF_STATUS_E_FAILURE; + } + + wlan_vdev_obj_lock(vdev); + if (vdev->obj_state == WLAN_OBJ_STATE_LOGICALLY_DELETED) { + wlan_vdev_obj_unlock(vdev); + qdf_print("%s: vdev obj is in Deletion Progress state\n", + __func__); + return QDF_STATUS_E_RESOURCES; + } + + /* Increment ref count */ + wlan_objmgr_vdev_get_ref(vdev, id); + wlan_vdev_obj_unlock(vdev); + + return QDF_STATUS_SUCCESS; +} +EXPORT_SYMBOL(wlan_objmgr_vdev_try_get_ref); + +void wlan_objmgr_vdev_release_ref(struct wlan_objmgr_vdev *vdev, + wlan_objmgr_ref_dbgid id) +{ + if (vdev == NULL) { + qdf_print("%s: vdev obj is NULL\n", __func__); + QDF_ASSERT(0); + return; + } + + if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_cnt)) { + qdf_print("%s: vdev ref cnt is 0\n", __func__); + WLAN_OBJMGR_BUG(0); + return; + } + + /* Decrement ref count, free vdev, if ref count == 0 */ + if (qdf_atomic_dec_and_test(&vdev->vdev_objmgr.ref_cnt)) + wlan_objmgr_vdev_obj_destroy(vdev); + + return; +} +EXPORT_SYMBOL(wlan_objmgr_vdev_release_ref); diff --git a/umac/cmn_services/serialization/src/wlan_serialization_main.c b/umac/cmn_services/serialization/src/wlan_serialization_main.c index e122f303947d..e9ab1e55a106 100644 --- a/umac/cmn_services/serialization/src/wlan_serialization_main.c +++ b/umac/cmn_services/serialization/src/wlan_serialization_main.c @@ -302,7 +302,7 @@ QDF_STATUS wlan_serialization_init(void) goto err_psoc_create; } - status = wlan_objmgr_register_psoc_delete_handler( + status = wlan_objmgr_register_psoc_destroy_handler( WLAN_UMAC_COMP_SERIALIZATION, wlan_serialization_psoc_obj_destroy_notification, NULL); if (status != QDF_STATUS_SUCCESS) { @@ -318,7 +318,7 @@ QDF_STATUS wlan_serialization_init(void) goto err_pdev_create; } - status = wlan_objmgr_register_pdev_delete_handler( + status = wlan_objmgr_register_pdev_destroy_handler( WLAN_UMAC_COMP_SERIALIZATION, wlan_serialization_pdev_obj_destroy_notification, NULL); if (status != QDF_STATUS_SUCCESS) { @@ -334,7 +334,7 @@ err_pdev_delete: wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_SERIALIZATION, wlan_serialization_pdev_obj_create_notification, NULL); err_pdev_create: - wlan_objmgr_unregister_psoc_delete_handler(WLAN_UMAC_COMP_SERIALIZATION, + wlan_objmgr_unregister_psoc_destroy_handler(WLAN_UMAC_COMP_SERIALIZATION, wlan_serialization_psoc_obj_destroy_notification, NULL); err_psoc_delete: wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_SERIALIZATION, @@ -358,7 +358,7 @@ QDF_STATUS wlan_serialization_deinit(void) status); ret_status = QDF_STATUS_E_FAILURE; } - status = wlan_objmgr_unregister_psoc_delete_handler( + status = wlan_objmgr_unregister_psoc_destroy_handler( WLAN_UMAC_COMP_SERIALIZATION, wlan_serialization_psoc_obj_destroy_notification, NULL); @@ -378,7 +378,7 @@ QDF_STATUS wlan_serialization_deinit(void) ret_status = QDF_STATUS_E_FAILURE; } - status = wlan_objmgr_unregister_pdev_delete_handler( + status = wlan_objmgr_unregister_pdev_destroy_handler( WLAN_UMAC_COMP_SERIALIZATION, wlan_serialization_pdev_obj_destroy_notification, NULL);