From 2f8f8b5addf729c6b6d558d4a66da201a34f851b Mon Sep 17 00:00:00 2001 From: Srinivas Pitla Date: Wed, 8 Feb 2017 12:55:36 +0530 Subject: [PATCH] qcacmn: Add support for Ref count debug mechanism This debug framework maintains module/API level counters and increments on get_ref and decrements on release, on release if the caller count is 0 exception would be thrown. This would help to identify any caller is releasing the reference more times or not releaseing the reference Change-Id: Ib3bc0dd5fb28587033142291a785c20f8775f9a0 CRS-Fixed: 1096009 --- .../obj_mgr/inc/wlan_objmgr_cmn.h | 2 + .../obj_mgr/inc/wlan_objmgr_pdev_obj.h | 11 +-- .../obj_mgr/inc/wlan_objmgr_peer_obj.h | 2 + .../obj_mgr/inc/wlan_objmgr_psoc_obj.h | 21 ++++- .../obj_mgr/inc/wlan_objmgr_vdev_obj.h | 10 ++- .../obj_mgr/src/wlan_objmgr_global_obj.c | 15 ++++ .../obj_mgr/src/wlan_objmgr_global_obj_i.h | 10 +++ .../obj_mgr/src/wlan_objmgr_pdev_obj.c | 9 +++ .../obj_mgr/src/wlan_objmgr_peer_obj.c | 9 +++ .../obj_mgr/src/wlan_objmgr_psoc_obj.c | 77 ++++++++++++++++++- .../obj_mgr/src/wlan_objmgr_vdev_obj.c | 9 +++ 11 files changed, 161 insertions(+), 14 deletions(-) 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 1286f46b0ef4..160514047055 100644 --- a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h +++ b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h @@ -157,6 +157,7 @@ typedef void (*wlan_objmgr_peer_status_handler)( * @WLAN_MLME_NB_ID: MLME Northbound operations * @WLAN_MGMT_SB_ID: MGMT Northbound operations * @WLAN_MGMT_NB_ID: MGMT Southbound operations + * @WLAN_REF_ID_MAX: Max ID, this should be the last one in enum */ typedef enum { WLAN_OBJMGR_ID = 0, @@ -164,6 +165,7 @@ typedef enum { WLAN_MLME_NB_ID = 2, WLAN_MGMT_SB_ID = 3, WLAN_MGMT_NB_ID = 4, + WLAN_REF_ID_MAX, } wlan_objmgr_ref_dbgid; #ifdef WLAN_OBJMGR_DEBUG 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 367a0d9611e6..fe7843b17ccb 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 @@ -139,6 +139,7 @@ struct wlan_objmgr_pdev_mlme { * @max_vdev_count: Max no. of VDEVs supported by this PDEV * @wlan_psoc: back pointer to PSOC, its attached to * @ref_cnt: Ref count + * @ref_id_dbg: Array to track Ref count */ struct wlan_objmgr_pdev_objmgr { uint8_t wlan_pdev_id; @@ -147,6 +148,7 @@ struct wlan_objmgr_pdev_objmgr { uint8_t max_vdev_count; struct wlan_objmgr_psoc *wlan_psoc; qdf_atomic_t ref_cnt; + qdf_atomic_t ref_id_dbg[WLAN_REF_ID_MAX]; }; /** @@ -244,6 +246,10 @@ QDF_STATUS wlan_objmgr_pdev_component_obj_detach( ** APIs to operations on pdev objects */ +typedef void (*wlan_objmgr_pdev_op_handler)(struct wlan_objmgr_pdev *pdev, + void *object, + void *arg); + /** * wlan_objmgr_pdev_iterate_obj_list() - operate on all objects of pdev * @pdev: PDEV object @@ -261,11 +267,6 @@ QDF_STATUS wlan_objmgr_pdev_component_obj_detach( * * Return: SUCCESS/FAILURE */ - -typedef void (*wlan_objmgr_pdev_op_handler)(struct wlan_objmgr_pdev *pdev, - void *object, - void *arg); - QDF_STATUS wlan_objmgr_pdev_iterate_obj_list( struct wlan_objmgr_pdev *pdev, enum wlan_objmgr_obj_type obj_type, 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 7f6432f10611..22fafb0a544c 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 @@ -137,10 +137,12 @@ 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 + * @ref_id_dbg: Array to track Ref count */ struct wlan_objmgr_peer_objmgr { struct wlan_objmgr_vdev *vdev; qdf_atomic_t ref_cnt; + qdf_atomic_t ref_id_dbg[WLAN_REF_ID_MAX]; }; /** 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 ec270e1ae7cb..d41b33b8fc47 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 @@ -193,6 +193,7 @@ struct wlan_objmgr_psoc_nif { * @wlan_peer_count: PEER count * @peer_list: Peer list * @ref_cnt: Ref count + * @ref_id_dbg: Array to track Ref count */ struct wlan_objmgr_psoc_objmgr { uint8_t wlan_pdev_count; @@ -205,6 +206,7 @@ struct wlan_objmgr_psoc_objmgr { uint16_t wlan_peer_count; struct wlan_peer_list peer_list; qdf_atomic_t ref_cnt; + qdf_atomic_t ref_id_dbg[WLAN_REF_ID_MAX]; }; /** @@ -334,6 +336,10 @@ QDF_STATUS wlan_objmgr_psoc_component_obj_detach( /** ** APIs to operations on psoc objects */ +typedef void (*wlan_objmgr_op_handler)(struct wlan_objmgr_psoc *psoc, + void *object, + void *arg); + /** * wlan_objmgr_iterate_obj_list() - iterate through all psoc objects * @psoc: PSOC object @@ -351,10 +357,6 @@ QDF_STATUS wlan_objmgr_psoc_component_obj_detach( * * Return: SUCCESS/FAILURE */ -typedef void (*wlan_objmgr_op_handler)(struct wlan_objmgr_psoc *psoc, - void *object, - void *arg); -/* handler should not take obj lock */ QDF_STATUS wlan_objmgr_iterate_obj_list( struct wlan_objmgr_psoc *psoc, enum wlan_objmgr_obj_type obj_type, @@ -1022,4 +1024,15 @@ QDF_STATUS wlan_objmgr_psoc_try_get_ref(struct wlan_objmgr_psoc *psoc, void wlan_objmgr_psoc_release_ref(struct wlan_objmgr_psoc *psoc, wlan_objmgr_ref_dbgid id); +/** + * wlan_objmgr_print_ref_all_objects_per_psoc() - print all psoc objects' + * ref counts + * @psoc: PSOC object + * + * API to be used for printing all the objects(pdev/vdev/peer) ref counts + * + * Return: SUCCESS/FAILURE + */ +QDF_STATUS wlan_objmgr_print_ref_all_objects_per_psoc( + struct wlan_objmgr_psoc *psoc); #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 94ae68cc651e..3de5fc5abd35 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 @@ -300,6 +300,7 @@ struct wlan_objmgr_vdev_nif { * @max_peer_count: Max Peer count * @c_flags: creation specific flags * @ref_cnt: Ref count + * @ref_id_dbg: Array to track Ref count */ struct wlan_objmgr_vdev_objmgr { uint8_t vdev_id; @@ -311,6 +312,7 @@ struct wlan_objmgr_vdev_objmgr { uint16_t max_peer_count; uint32_t c_flags; qdf_atomic_t ref_cnt; + qdf_atomic_t ref_id_dbg[WLAN_REF_ID_MAX]; }; /** @@ -408,6 +410,10 @@ QDF_STATUS wlan_objmgr_vdev_component_obj_detach( ** APIs to operations on vdev objects */ +typedef void (*wlan_objmgr_vdev_op_handler)(struct wlan_objmgr_vdev *vdev, + void *object, + void *arg); + /** * wlan_objmgr_iterate_peerobj_list() - iterate vdev's peer list * @vdev: vdev object @@ -421,10 +427,6 @@ QDF_STATUS wlan_objmgr_vdev_component_obj_detach( * * Return: SUCCESS/FAILURE */ -typedef void (*wlan_objmgr_vdev_op_handler)(struct wlan_objmgr_vdev *vdev, - void *object, - void *arg); - QDF_STATUS wlan_objmgr_iterate_peerobj_list( struct wlan_objmgr_vdev *vdev, wlan_objmgr_vdev_op_handler handler, 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 b61516ea2870..ae0eca5dbb83 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 @@ -772,3 +772,18 @@ QDF_STATUS wlan_objmgr_global_obj_can_destroyed(void) return status; } EXPORT_SYMBOL(wlan_objmgr_global_obj_can_destroyed); + +void wlan_objmgr_print_ref_ids(qdf_atomic_t *id) +{ + uint32_t i; + uint32_t pending_ref; + + qdf_print(" Pending references of object\n"); + for (i = 0; i < WLAN_REF_ID_MAX; i++) { + pending_ref = qdf_atomic_read(&id[i]); + if (pending_ref) + qdf_print(" %d -- %d\n", i, pending_ref); + } + + return; +} 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 34e4f423f5ab..2b852b4592e6 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 @@ -120,4 +120,14 @@ QDF_STATUS wlan_objmgr_psoc_object_attach( */ QDF_STATUS wlan_objmgr_psoc_object_detach( struct wlan_objmgr_psoc *psoc); + +/** + * wlan_objmgr_print_ref_ids() - Print ref counts of modules + * @id - array of ref debug + * + * Itertes through array, and prints the ref count debug + * + * Return: nothing + */ +void wlan_objmgr_print_ref_ids(qdf_atomic_t *id); #endif /* _WLAN_OBJMGR_GLOBAL_OBJ_I_H_ */ 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 555f0b964939..fd4651f6d278 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 @@ -778,6 +778,7 @@ void wlan_objmgr_pdev_get_ref(struct wlan_objmgr_pdev *pdev, return; } qdf_atomic_inc(&pdev->pdev_objmgr.ref_cnt); + qdf_atomic_inc(&pdev->pdev_objmgr.ref_id_dbg[id]); return; } @@ -816,12 +817,20 @@ void wlan_objmgr_pdev_release_ref(struct wlan_objmgr_pdev *pdev, return; } + if (!qdf_atomic_read(&pdev->pdev_objmgr.ref_id_dbg[id])) { + qdf_print("%s: pdev ref cnt was not taken by %d\n", + __func__, id); + wlan_objmgr_print_ref_ids(pdev->pdev_objmgr.ref_id_dbg); + WLAN_OBJMGR_BUG(0); + } + if (!qdf_atomic_read(&pdev->pdev_objmgr.ref_cnt)) { qdf_print("%s: pdev ref cnt is 0\n", __func__); WLAN_OBJMGR_BUG(0); return; } + qdf_atomic_dec(&pdev->pdev_objmgr.ref_id_dbg[id]); /* 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); 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 6c46783945f0..593a5e70a396 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 @@ -505,6 +505,7 @@ void wlan_objmgr_peer_get_ref(struct wlan_objmgr_peer *peer, } /* Increment ref count */ qdf_atomic_inc(&peer->peer_objmgr.ref_cnt); + qdf_atomic_inc(&peer->peer_objmgr.ref_id_dbg[id]); return; } @@ -543,11 +544,19 @@ void wlan_objmgr_peer_release_ref(struct wlan_objmgr_peer *peer, return; } + if (!qdf_atomic_read(&peer->peer_objmgr.ref_id_dbg[id])) { + qdf_print("%s: peer ref cnt was not taken by %d\n", + __func__, id); + wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg); + WLAN_OBJMGR_BUG(0); + } + if (!qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) { qdf_print("%s: peer ref cnt is 0\n", __func__); WLAN_OBJMGR_BUG(0); return; } + qdf_atomic_dec(&peer->peer_objmgr.ref_id_dbg[id]); /* Decrement ref count, free vdev, if ref acount == 0 */ if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt)) 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 448dc97c1e4d..1a70966cc6df 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 @@ -1321,7 +1321,7 @@ void wlan_objmgr_psoc_get_ref(struct wlan_objmgr_psoc *psoc, } /* Increment ref count */ qdf_atomic_inc(&psoc->soc_objmgr.ref_cnt); - + qdf_atomic_inc(&psoc->soc_objmgr.ref_id_dbg[id]); return; } EXPORT_SYMBOL(wlan_objmgr_psoc_get_ref); @@ -1360,12 +1360,20 @@ void wlan_objmgr_psoc_release_ref(struct wlan_objmgr_psoc *psoc, return; } + if (!qdf_atomic_read(&psoc->soc_objmgr.ref_id_dbg[id])) { + qdf_print("%s: psoc ref cnt was not taken by %d\n", + __func__, id); + wlan_objmgr_print_ref_ids(psoc->soc_objmgr.ref_id_dbg); + WLAN_OBJMGR_BUG(0); + } + if (!qdf_atomic_read(&psoc->soc_objmgr.ref_cnt)) { qdf_print("%s: psoc ref cnt is 0\n", __func__); WLAN_OBJMGR_BUG(0); return; } + qdf_atomic_dec(&psoc->soc_objmgr.ref_id_dbg[id]); /* 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); @@ -1373,3 +1381,70 @@ void wlan_objmgr_psoc_release_ref(struct wlan_objmgr_psoc *psoc, return; } EXPORT_SYMBOL(wlan_objmgr_psoc_release_ref); + +static void wlan_objmgr_psoc_peer_ref_print(struct wlan_objmgr_psoc *psoc, + void *obj, void *args) +{ + struct wlan_objmgr_peer *peer = (struct wlan_objmgr_peer *)obj; + uint8_t *macaddr; + + wlan_peer_obj_lock(peer); + macaddr = wlan_peer_get_macaddr(peer); + wlan_peer_obj_unlock(peer); + + qdf_print(" Peer MAC is %02x:%02x:%02x:%02x:%02x:%02x\n", + macaddr[0], macaddr[1], macaddr[2], macaddr[3], + macaddr[4], macaddr[5]); + wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg); +} + +static void wlan_objmgr_psoc_vdev_ref_print(struct wlan_objmgr_psoc *psoc, + void *obj, void *args) +{ + struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)obj; + uint8_t id; + + wlan_vdev_obj_lock(vdev); + id = wlan_vdev_get_id(vdev); + wlan_vdev_obj_unlock(vdev); + qdf_print(" Vdev ID is %d\n", id); + + wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg); +} + +static void wlan_objmgr_psoc_pdev_ref_print(struct wlan_objmgr_psoc *psoc, + void *obj, void *args) +{ + struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)obj; + uint8_t id; + + wlan_pdev_obj_lock(pdev); + id = pdev->pdev_objmgr.wlan_pdev_id; + wlan_pdev_obj_unlock(pdev); + qdf_print(" pdev ID is %d\n", id); + + wlan_objmgr_print_ref_ids(pdev->pdev_objmgr.ref_id_dbg); +} + +QDF_STATUS wlan_objmgr_print_ref_all_objects_per_psoc( + struct wlan_objmgr_psoc *psoc) +{ + qdf_print(" Ref counts of PEER\n"); + wlan_objmgr_iterate_obj_list(psoc, WLAN_PEER_OP, + wlan_objmgr_psoc_peer_ref_print, NULL, 1, + WLAN_OBJMGR_ID); + qdf_print(" Ref counts of VDEV\n"); + wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP, + wlan_objmgr_psoc_vdev_ref_print, NULL, 1, + WLAN_OBJMGR_ID); + qdf_print(" Ref counts of PDEV\n"); + wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, + wlan_objmgr_psoc_pdev_ref_print, NULL, 1, + WLAN_OBJMGR_ID); + + qdf_print(" Ref counts of PSOC\n"); + wlan_objmgr_print_ref_ids(psoc->soc_objmgr.ref_id_dbg); + + return QDF_STATUS_SUCCESS; +} +EXPORT_SYMBOL(wlan_objmgr_print_ref_all_objects_per_psoc); 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 fc6259466046..1c5e309f1394 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 @@ -663,6 +663,7 @@ void wlan_objmgr_vdev_get_ref(struct wlan_objmgr_vdev *vdev, } /* Increment ref count */ qdf_atomic_inc(&vdev->vdev_objmgr.ref_cnt); + qdf_atomic_inc(&vdev->vdev_objmgr.ref_id_dbg[id]); return; } @@ -702,11 +703,19 @@ void wlan_objmgr_vdev_release_ref(struct wlan_objmgr_vdev *vdev, return; } + if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_id_dbg[id])) { + qdf_print("%s: vdev ref cnt was not taken by %d\n", + __func__, id); + wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg); + WLAN_OBJMGR_BUG(0); + } + if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_cnt)) { qdf_print("%s: vdev ref cnt is 0\n", __func__); WLAN_OBJMGR_BUG(0); return; } + qdf_atomic_dec(&vdev->vdev_objmgr.ref_id_dbg[id]); /* Decrement ref count, free vdev, if ref count == 0 */ if (qdf_atomic_dec_and_test(&vdev->vdev_objmgr.ref_cnt))