Explorar o código

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
Srinivas Pitla %!s(int64=8) %!d(string=hai) anos
pai
achega
2f8f8b5add

+ 2 - 0
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

+ 6 - 5
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,

+ 2 - 0
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];
 };
 
 /**

+ 17 - 4
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_*/

+ 6 - 4
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,

+ 15 - 0
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;
+}

+ 10 - 0
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_ */

+ 9 - 0
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);

+ 9 - 0
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))

+ 76 - 1
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);

+ 9 - 0
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))