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
This commit is contained in:
Srinivas Pitla
2017-02-08 12:55:36 +05:30
committed by qcabuildsw
parent 10aa60c11f
commit 2f8f8b5add
11 changed files with 161 additions and 14 deletions

View File

@@ -157,6 +157,7 @@ typedef void (*wlan_objmgr_peer_status_handler)(
* @WLAN_MLME_NB_ID: MLME Northbound operations * @WLAN_MLME_NB_ID: MLME Northbound operations
* @WLAN_MGMT_SB_ID: MGMT Northbound operations * @WLAN_MGMT_SB_ID: MGMT Northbound operations
* @WLAN_MGMT_NB_ID: MGMT Southbound operations * @WLAN_MGMT_NB_ID: MGMT Southbound operations
* @WLAN_REF_ID_MAX: Max ID, this should be the last one in enum
*/ */
typedef enum { typedef enum {
WLAN_OBJMGR_ID = 0, WLAN_OBJMGR_ID = 0,
@@ -164,6 +165,7 @@ typedef enum {
WLAN_MLME_NB_ID = 2, WLAN_MLME_NB_ID = 2,
WLAN_MGMT_SB_ID = 3, WLAN_MGMT_SB_ID = 3,
WLAN_MGMT_NB_ID = 4, WLAN_MGMT_NB_ID = 4,
WLAN_REF_ID_MAX,
} wlan_objmgr_ref_dbgid; } wlan_objmgr_ref_dbgid;
#ifdef WLAN_OBJMGR_DEBUG #ifdef WLAN_OBJMGR_DEBUG

View File

@@ -139,6 +139,7 @@ struct wlan_objmgr_pdev_mlme {
* @max_vdev_count: Max no. of VDEVs supported by this PDEV * @max_vdev_count: Max no. of VDEVs supported by this PDEV
* @wlan_psoc: back pointer to PSOC, its attached to * @wlan_psoc: back pointer to PSOC, its attached to
* @ref_cnt: Ref count * @ref_cnt: Ref count
* @ref_id_dbg: Array to track Ref count
*/ */
struct wlan_objmgr_pdev_objmgr { struct wlan_objmgr_pdev_objmgr {
uint8_t wlan_pdev_id; uint8_t wlan_pdev_id;
@@ -147,6 +148,7 @@ struct wlan_objmgr_pdev_objmgr {
uint8_t max_vdev_count; uint8_t max_vdev_count;
struct wlan_objmgr_psoc *wlan_psoc; struct wlan_objmgr_psoc *wlan_psoc;
qdf_atomic_t ref_cnt; 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 ** 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 * wlan_objmgr_pdev_iterate_obj_list() - operate on all objects of pdev
* @pdev: PDEV object * @pdev: PDEV object
@@ -261,11 +267,6 @@ QDF_STATUS wlan_objmgr_pdev_component_obj_detach(
* *
* Return: SUCCESS/FAILURE * 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( QDF_STATUS wlan_objmgr_pdev_iterate_obj_list(
struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_pdev *pdev,
enum wlan_objmgr_obj_type obj_type, enum wlan_objmgr_obj_type obj_type,

View File

@@ -137,10 +137,12 @@ struct wlan_objmgr_peer_mlme {
* struct wlan_objmgr_peer_objmgr - object manager data of peer * struct wlan_objmgr_peer_objmgr - object manager data of peer
* @vdev: VDEV pointer to which it is associated * @vdev: VDEV pointer to which it is associated
* @ref_cnt: Ref count * @ref_cnt: Ref count
* @ref_id_dbg: Array to track Ref count
*/ */
struct wlan_objmgr_peer_objmgr { struct wlan_objmgr_peer_objmgr {
struct wlan_objmgr_vdev *vdev; struct wlan_objmgr_vdev *vdev;
qdf_atomic_t ref_cnt; qdf_atomic_t ref_cnt;
qdf_atomic_t ref_id_dbg[WLAN_REF_ID_MAX];
}; };
/** /**

View File

@@ -193,6 +193,7 @@ struct wlan_objmgr_psoc_nif {
* @wlan_peer_count: PEER count * @wlan_peer_count: PEER count
* @peer_list: Peer list * @peer_list: Peer list
* @ref_cnt: Ref count * @ref_cnt: Ref count
* @ref_id_dbg: Array to track Ref count
*/ */
struct wlan_objmgr_psoc_objmgr { struct wlan_objmgr_psoc_objmgr {
uint8_t wlan_pdev_count; uint8_t wlan_pdev_count;
@@ -205,6 +206,7 @@ struct wlan_objmgr_psoc_objmgr {
uint16_t wlan_peer_count; uint16_t wlan_peer_count;
struct wlan_peer_list peer_list; struct wlan_peer_list peer_list;
qdf_atomic_t ref_cnt; 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 ** 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 * wlan_objmgr_iterate_obj_list() - iterate through all psoc objects
* @psoc: PSOC object * @psoc: PSOC object
@@ -351,10 +357,6 @@ QDF_STATUS wlan_objmgr_psoc_component_obj_detach(
* *
* Return: SUCCESS/FAILURE * 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( QDF_STATUS wlan_objmgr_iterate_obj_list(
struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_psoc *psoc,
enum wlan_objmgr_obj_type obj_type, 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, void wlan_objmgr_psoc_release_ref(struct wlan_objmgr_psoc *psoc,
wlan_objmgr_ref_dbgid id); 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_*/ #endif /* _WLAN_OBJMGR_PSOC_OBJ_H_*/

View File

@@ -300,6 +300,7 @@ struct wlan_objmgr_vdev_nif {
* @max_peer_count: Max Peer count * @max_peer_count: Max Peer count
* @c_flags: creation specific flags * @c_flags: creation specific flags
* @ref_cnt: Ref count * @ref_cnt: Ref count
* @ref_id_dbg: Array to track Ref count
*/ */
struct wlan_objmgr_vdev_objmgr { struct wlan_objmgr_vdev_objmgr {
uint8_t vdev_id; uint8_t vdev_id;
@@ -311,6 +312,7 @@ struct wlan_objmgr_vdev_objmgr {
uint16_t max_peer_count; uint16_t max_peer_count;
uint32_t c_flags; uint32_t c_flags;
qdf_atomic_t ref_cnt; 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 ** 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 * wlan_objmgr_iterate_peerobj_list() - iterate vdev's peer list
* @vdev: vdev object * @vdev: vdev object
@@ -421,10 +427,6 @@ QDF_STATUS wlan_objmgr_vdev_component_obj_detach(
* *
* Return: SUCCESS/FAILURE * 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( QDF_STATUS wlan_objmgr_iterate_peerobj_list(
struct wlan_objmgr_vdev *vdev, struct wlan_objmgr_vdev *vdev,
wlan_objmgr_vdev_op_handler handler, wlan_objmgr_vdev_op_handler handler,

View File

@@ -772,3 +772,18 @@ QDF_STATUS wlan_objmgr_global_obj_can_destroyed(void)
return status; return status;
} }
EXPORT_SYMBOL(wlan_objmgr_global_obj_can_destroyed); 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;
}

View File

@@ -120,4 +120,14 @@ QDF_STATUS wlan_objmgr_psoc_object_attach(
*/ */
QDF_STATUS wlan_objmgr_psoc_object_detach( QDF_STATUS wlan_objmgr_psoc_object_detach(
struct wlan_objmgr_psoc *psoc); 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_ */ #endif /* _WLAN_OBJMGR_GLOBAL_OBJ_I_H_ */

View File

@@ -778,6 +778,7 @@ void wlan_objmgr_pdev_get_ref(struct wlan_objmgr_pdev *pdev,
return; return;
} }
qdf_atomic_inc(&pdev->pdev_objmgr.ref_cnt); qdf_atomic_inc(&pdev->pdev_objmgr.ref_cnt);
qdf_atomic_inc(&pdev->pdev_objmgr.ref_id_dbg[id]);
return; return;
} }
@@ -816,12 +817,20 @@ void wlan_objmgr_pdev_release_ref(struct wlan_objmgr_pdev *pdev,
return; 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)) { if (!qdf_atomic_read(&pdev->pdev_objmgr.ref_cnt)) {
qdf_print("%s: pdev ref cnt is 0\n", __func__); qdf_print("%s: pdev ref cnt is 0\n", __func__);
WLAN_OBJMGR_BUG(0); WLAN_OBJMGR_BUG(0);
return; return;
} }
qdf_atomic_dec(&pdev->pdev_objmgr.ref_id_dbg[id]);
/* Decrement ref count, free pdev, if ref count == 0 */ /* Decrement ref count, free pdev, if ref count == 0 */
if (qdf_atomic_dec_and_test(&pdev->pdev_objmgr.ref_cnt)) if (qdf_atomic_dec_and_test(&pdev->pdev_objmgr.ref_cnt))
wlan_objmgr_pdev_obj_destroy(pdev); wlan_objmgr_pdev_obj_destroy(pdev);

View File

@@ -505,6 +505,7 @@ void wlan_objmgr_peer_get_ref(struct wlan_objmgr_peer *peer,
} }
/* Increment ref count */ /* Increment ref count */
qdf_atomic_inc(&peer->peer_objmgr.ref_cnt); qdf_atomic_inc(&peer->peer_objmgr.ref_cnt);
qdf_atomic_inc(&peer->peer_objmgr.ref_id_dbg[id]);
return; return;
} }
@@ -543,11 +544,19 @@ void wlan_objmgr_peer_release_ref(struct wlan_objmgr_peer *peer,
return; 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)) { if (!qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) {
qdf_print("%s: peer ref cnt is 0\n", __func__); qdf_print("%s: peer ref cnt is 0\n", __func__);
WLAN_OBJMGR_BUG(0); WLAN_OBJMGR_BUG(0);
return; return;
} }
qdf_atomic_dec(&peer->peer_objmgr.ref_id_dbg[id]);
/* Decrement ref count, free vdev, if ref acount == 0 */ /* Decrement ref count, free vdev, if ref acount == 0 */
if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt)) if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt))

View File

@@ -1321,7 +1321,7 @@ void wlan_objmgr_psoc_get_ref(struct wlan_objmgr_psoc *psoc,
} }
/* Increment ref count */ /* Increment ref count */
qdf_atomic_inc(&psoc->soc_objmgr.ref_cnt); qdf_atomic_inc(&psoc->soc_objmgr.ref_cnt);
qdf_atomic_inc(&psoc->soc_objmgr.ref_id_dbg[id]);
return; return;
} }
EXPORT_SYMBOL(wlan_objmgr_psoc_get_ref); EXPORT_SYMBOL(wlan_objmgr_psoc_get_ref);
@@ -1360,12 +1360,20 @@ void wlan_objmgr_psoc_release_ref(struct wlan_objmgr_psoc *psoc,
return; 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)) { if (!qdf_atomic_read(&psoc->soc_objmgr.ref_cnt)) {
qdf_print("%s: psoc ref cnt is 0\n", __func__); qdf_print("%s: psoc ref cnt is 0\n", __func__);
WLAN_OBJMGR_BUG(0); WLAN_OBJMGR_BUG(0);
return; return;
} }
qdf_atomic_dec(&psoc->soc_objmgr.ref_id_dbg[id]);
/* Decrement ref count, free psoc, if ref count == 0 */ /* Decrement ref count, free psoc, if ref count == 0 */
if (qdf_atomic_dec_and_test(&psoc->soc_objmgr.ref_cnt)) if (qdf_atomic_dec_and_test(&psoc->soc_objmgr.ref_cnt))
wlan_objmgr_psoc_obj_destroy(psoc); wlan_objmgr_psoc_obj_destroy(psoc);
@@ -1373,3 +1381,70 @@ void wlan_objmgr_psoc_release_ref(struct wlan_objmgr_psoc *psoc,
return; return;
} }
EXPORT_SYMBOL(wlan_objmgr_psoc_release_ref); 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);

View File

@@ -663,6 +663,7 @@ void wlan_objmgr_vdev_get_ref(struct wlan_objmgr_vdev *vdev,
} }
/* Increment ref count */ /* Increment ref count */
qdf_atomic_inc(&vdev->vdev_objmgr.ref_cnt); qdf_atomic_inc(&vdev->vdev_objmgr.ref_cnt);
qdf_atomic_inc(&vdev->vdev_objmgr.ref_id_dbg[id]);
return; return;
} }
@@ -702,11 +703,19 @@ void wlan_objmgr_vdev_release_ref(struct wlan_objmgr_vdev *vdev,
return; 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)) { if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_cnt)) {
qdf_print("%s: vdev ref cnt is 0\n", __func__); qdf_print("%s: vdev ref cnt is 0\n", __func__);
WLAN_OBJMGR_BUG(0); WLAN_OBJMGR_BUG(0);
return; return;
} }
qdf_atomic_dec(&vdev->vdev_objmgr.ref_id_dbg[id]);
/* Decrement ref count, free vdev, if ref count == 0 */ /* Decrement ref count, free vdev, if ref count == 0 */
if (qdf_atomic_dec_and_test(&vdev->vdev_objmgr.ref_cnt)) if (qdf_atomic_dec_and_test(&vdev->vdev_objmgr.ref_cnt))