ソースを参照

qcacmn: Remove lock free option in object manager iterate APIs

Object manager iterate APIs are provided with an option to decide
lock protection by the caller, as that is leading to race conditions
in SMP scenarios.

Locks are made default and handled possible deadlock scenarios,
handlers can take any object lock as required

Change-Id: I74b5d9d7440bc48b2ec2918c3b4ddd7057f3ac48
CRs-Fixed: 2238529
Srinivas Pitla 7 年 前
コミット
77e179103b

+ 1 - 3
umac/cmn_services/obj_mgr/inc/wlan_objmgr_pdev_obj.h

@@ -279,9 +279,7 @@ typedef void (*wlan_objmgr_pdev_op_handler)(struct wlan_objmgr_pdev *pdev,
  * @handler: the handler will be called for each object of requested type
  *           the handler should be implemented to perform required operation
  * @arg: agruments passed by caller
- * @lock_free_op: This gives provision to run this API with out lock protected
- *                It would be useful, for operations like Obj Delete, where
- *                lock should not be taken by caller.
+ * @lock_free_op: its obsolete
  * @dbg_id: id of the caller
  *
  * API to be used for performing the operations on all VDEV/PEER objects

+ 107 - 0
umac/cmn_services/obj_mgr/inc/wlan_objmgr_peer_obj.h

@@ -432,6 +432,39 @@ static inline struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head(
 	return peer;
 }
 
+/**
+ * wlan_psoc_peer_list_peek_active_head() - get active head of psoc peer list
+ * @peer_list: wlan_peer_list
+ * @hash_index: peer list hash index
+ * @dbg_id: Ref count debug module id
+ *
+ * API to get the head peer of given peer (of psoc's peer list)
+ *
+ * Return:
+ * @peer: head peer
+ */
+struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_active_head(
+					struct wlan_peer_list *peer_list,
+					uint8_t hash_index,
+					wlan_objmgr_ref_dbgid dbg_id);
+
+/**
+ * wlan_psoc_peer_list_peek_head_lock_ref() - get head of psoc peer list
+ *                                            with ref and lock protected
+ * @peer_list: wlan_peer_list
+ * @hash_index: peer list hash index
+ * @dbg_id: Ref count debug module id
+ *
+ * API to get the head peer of given peer (of psoc's peer list)
+ *
+ * Return:
+ * @peer: head peer
+ */
+struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head_ref(
+					struct wlan_peer_list *peer_list,
+					uint8_t hash_index,
+					wlan_objmgr_ref_dbgid dbg_id);
+
 /**
  * wlan_vdev_peer_list_peek_head() - get head of vdev peer list
  * @peer_list: qdf_list_t
@@ -457,6 +490,22 @@ static inline struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_head(
 	return peer;
 }
 
+/**
+ * wlan_vdev_peer_list_peek_active_head() - get active head of vdev peer list
+ * @vdev: VDEV object
+ * @peer_list: qdf_list_t
+ * @dbg_id: Ref count debug module id
+ *
+ * API to get the active head peer of given peer (of vdev's peer list)
+ *
+ * Return:
+ * @peer: active head peer
+ */
+struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_active_head(
+				struct wlan_objmgr_vdev *vdev,
+				qdf_list_t *peer_list,
+				wlan_objmgr_ref_dbgid dbg_id);
+
 /**
  * wlan_peer_get_next_peer_of_vdev() - get next peer of vdev list
  * @peer: PEER object
@@ -489,6 +538,24 @@ static inline struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_vdev(
 	return peer_next;
 }
 
+/**
+ * wlan_peer_get_next_active_peer_of_vdev() - get next active_peer of vdev list
+ * @vdev: VDEV object
+ * @peer_list: Peer object list
+ * @peer: PEER object
+ * @dbg_id: Ref count debug module id
+ *
+ * API to get the next active peer of given peer (of vdev's peer list)
+ *
+ * Return:
+ * @next_peer: PEER object
+ */
+struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_vdev(
+				struct wlan_objmgr_vdev *vdev,
+				qdf_list_t *peer_list,
+				struct wlan_objmgr_peer *peer,
+				wlan_objmgr_ref_dbgid dbg_id);
+
 /**
  * wlan_peer_set_next_peer_of_vdev() - add peer to vdev peer list
  * @peer: PEER object
@@ -511,6 +578,7 @@ static inline void wlan_peer_set_next_peer_of_vdev(qdf_list_t *peer_list,
 
 /**
  * wlan_peer_get_next_peer_of_psoc() - get next peer to psoc peer list
+ * @peer_list: Peer list
  * @peer: PEER object
  *
  * API to get the next peer of given peer (of psoc's peer list)
@@ -541,6 +609,45 @@ static inline struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc(
 	return peer_next;
 }
 
+/**
+ * wlan_peer_get_next_active_peer_of_psoc() - get next active peer to psoc peer
+ *                                            list
+ * @peer_list: Peer list
+ * @hash_index: peer list hash index
+ * @peer: PEER object
+ * @dbg_id: Ref count debug module id
+ *
+ * API to get the next peer of given peer (of psoc's peer list)
+ *
+ * Return:
+ * @next_peer: PEER object
+ */
+struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_psoc(
+					struct wlan_peer_list *peer_list,
+					uint8_t hash_index,
+					struct wlan_objmgr_peer *peer,
+					wlan_objmgr_ref_dbgid dbg_id);
+
+
+/**
+ * wlan_peer_get_next_peer_of_psoc_ref() - get next peer to psoc peer list
+ *                                         with lock and ref taken
+ * @peer_list: Peer list
+ * @hash_index: peer list hash index
+ * @peer: PEER object
+ * @dbg_id: Ref count debug module id
+ *
+ * API to get the next peer of given peer (of psoc's peer list)
+ *
+ * Return:
+ * @next_peer: PEER object
+ */
+struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc_ref(
+				struct wlan_peer_list *peer_list,
+				uint8_t hash_index,
+				struct wlan_objmgr_peer *peer,
+				wlan_objmgr_ref_dbgid dbg_id);
+
 /**
  * wlan_peer_set_next_peer_of_psoc() - add peer to psoc peer list
  * @peer: PEER object

+ 2 - 8
umac/cmn_services/obj_mgr/inc/wlan_objmgr_psoc_obj.h

@@ -442,9 +442,7 @@ typedef void (*wlan_objmgr_op_handler)(struct wlan_objmgr_psoc *psoc,
  * @handler: the handler will be called for each object of requested type
  *            the handler should be implemented to perform required operation
  * @arg:     agruments passed by caller
- * @lock_free_op: This gives provision to run this API with out lock protected
- *                 It would be useful, for operations like Obj Delete, where
- *                 lock should not be taken by caller.
+ * @lock_free_op: its obsolete
  * @dbg_id: id of the caller
  *
  * API to be used for performing the operations on all PDEV/VDEV/PEER objects
@@ -466,11 +464,7 @@ QDF_STATUS wlan_objmgr_iterate_obj_list(
  * @handler: the handler will be called for each object of requested type
  *            the handler should be implemented to perform required operation
  * @arg:     agruments passed by caller
- * @lock_free_op: This gives provision to run this API with out lock protected
- *                 It would be useful, for operations like Obj Delete, where
- *                 lock should not be taken by caller.
- *                 Please be cautious, when you do lock_free_op, it would cause
- *                 issues in SMP scenarios
+ * @lock_free_op: its obsolete
  * @dbg_id: id of the caller
  *
  * API to be used for performing the operations on all PDEV/VDEV/PEER objects

+ 38 - 3
umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h

@@ -495,8 +495,8 @@ QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_creation(
 		enum wlan_umac_comp_id id);
 
 /**
- * wlan_objmgr_trigger_vdev_comp_priv_object_deletion() - vdev
- * comp object deletion
+ * wlan_objmgr_trigger_vdev_comp_priv_object_deletion() - vdev comp
+ *                                                        object deletion
  * @vdev: VDEV object
  * @id: Component id
  *
@@ -544,7 +544,7 @@ static inline struct wlan_objmgr_pdev *wlan_vdev_get_pdev(
  * wlan_pdev_vdev_list_peek_head() - get first vdev from pdev list
  * @peer_list: qdf_list_t
  *
- * API to get the head vdev of given peer (of pdev's vdev list)
+ * API to get the head vdev of given vdev (of pdev's vdev list)
  *
  * Caller need to acquire lock with wlan_vdev_obj_lock()
  *
@@ -565,6 +565,22 @@ static inline struct wlan_objmgr_vdev *wlan_pdev_vdev_list_peek_head(
 	return vdev;
 }
 
+/**
+ * wlan_pdev_vdev_list_peek_active_head() - get first active vdev from pdev list
+ * @vdev: VDEV object
+ * @vdev_list: qdf_list_t
+ * @dbg_id: id of the caller
+ *
+ * API to get the head active vdev of given vdev (of pdev's vdev list)
+ *
+ * Return:
+ * @peer: head peer
+ */
+struct wlan_objmgr_vdev *wlan_pdev_vdev_list_peek_active_head(
+				struct wlan_objmgr_pdev *pdev,
+				qdf_list_t *vdev_list,
+				wlan_objmgr_ref_dbgid dbg_id);
+
 /**
  * wlan_vdev_get_next_vdev_of_pdev() - get next vdev
  * @vdev: VDEV object
@@ -597,6 +613,25 @@ static inline struct wlan_objmgr_vdev *wlan_vdev_get_next_vdev_of_pdev(
 	return vdev_next;
 }
 
+/**
+ * wlan_vdev_get_next_active_vdev_of_pdev() - get next active vdev
+ * @pdev: PDEV object
+ * @vdev_list: qdf_list_t
+ * @vdev: VDEV object
+ * @dbg_id: id of the caller
+ *
+ * API to get next active vdev object pointer of vdev
+ *
+ * Return:
+ * @vdev_next: VDEV object
+ */
+struct wlan_objmgr_vdev *wlan_vdev_get_next_active_vdev_of_pdev(
+					struct wlan_objmgr_pdev *pdev,
+					qdf_list_t *vdev_list,
+					struct wlan_objmgr_vdev *vdev,
+					wlan_objmgr_ref_dbgid dbg_id);
+
+
 /**
  * wlan_vdev_set_pdev() - set pdev
  * @vdev: VDEV object

+ 24 - 46
umac/cmn_services/obj_mgr/src/wlan_objmgr_pdev_obj.c

@@ -411,29 +411,21 @@ static void wlan_objmgr_pdev_vdev_iterate_peers(struct wlan_objmgr_pdev *pdev,
 
 	/* Iterating through vdev's peer list, so lock is
 		needed */
-	if (!lock_free_op)
-		wlan_vdev_obj_lock(vdev);
 	/* Get peer list of the vdev */
 	peer_list = &vdev->vdev_objmgr.wlan_peer_list;
 	if (peer_list != NULL) {
-		peer = wlan_vdev_peer_list_peek_head(peer_list);
+		peer = wlan_vdev_peer_list_peek_active_head(vdev, peer_list,
+								dbg_id);
 		while (peer != NULL) {
-			/* Get next peer pointer */
-			peer_next = wlan_peer_get_next_peer_of_vdev(peer_list,
-								    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);
-			}
+			/* Invoke the handler */
+			handler(pdev, (void *)peer, arg);
+			/* Get next peer pointer, increments the ref count */
+			peer_next = wlan_peer_get_next_active_peer_of_vdev(vdev,
+						peer_list, peer, dbg_id);
+			wlan_objmgr_peer_release_ref(peer, dbg_id);
 			peer = peer_next;
 		}
 	}
-	if (!lock_free_op)
-		wlan_vdev_obj_unlock(vdev);
 }
 
 QDF_STATUS wlan_objmgr_pdev_iterate_obj_list(
@@ -448,54 +440,40 @@ QDF_STATUS wlan_objmgr_pdev_iterate_obj_list(
 	struct wlan_objmgr_vdev *vdev = NULL;
 	struct wlan_objmgr_vdev *vdev_next = NULL;
 
-	/* If caller requests for lock free opeation, do not acquire
-		handler will handle the synchronization*/
-	if (!lock_free_op)
-		wlan_pdev_obj_lock(pdev);
 	/* VDEV list */
 	vdev_list = &objmgr->wlan_vdev_list;
+
 	switch (obj_type) {
 	case WLAN_VDEV_OP:
 		/* Iterate through all VDEV object, and invoke handler for each
 			VDEV object */
-		vdev = wlan_pdev_vdev_list_peek_head(vdev_list);
+		vdev = wlan_pdev_vdev_list_peek_active_head(pdev, vdev_list,
+								dbg_id);
 		while (vdev != NULL) {
-			/*
-			 * Get next vdev (handler can be invoked for
-			 * vdev deletion also
-			 */
-			vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list,
-						vdev);
-			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);
-			}
+			handler(pdev, (void *)vdev, arg);
+			 /* Get next vdev, it increments ref of next vdev */
+			vdev_next = wlan_vdev_get_next_active_vdev_of_pdev(
+					pdev, vdev_list, vdev, dbg_id);
+			wlan_objmgr_vdev_release_ref(vdev, dbg_id);
 			vdev = vdev_next;
 		}
 		break;
 	case WLAN_PEER_OP:
-		vdev = wlan_pdev_vdev_list_peek_head(vdev_list);
-		while (vdev != NULL) {
-			/* Get Next VDEV */
-			vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list,
-						vdev);
-			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,
+		vdev = wlan_pdev_vdev_list_peek_active_head(pdev, vdev_list,
 								dbg_id);
-				wlan_objmgr_vdev_release_ref(vdev, dbg_id);
-			}
+		while (vdev != NULL) {
+			wlan_objmgr_pdev_vdev_iterate_peers(pdev, vdev,	handler,
+						arg, lock_free_op, dbg_id);
+			 /* Get next vdev, it increments ref of next vdev */
+			vdev_next = wlan_vdev_get_next_active_vdev_of_pdev(
+					pdev, vdev_list, vdev, dbg_id);
+			wlan_objmgr_vdev_release_ref(vdev, dbg_id);
 			vdev = vdev_next;
 		}
 		break;
 	default:
 		break;
 	}
-	if (!lock_free_op)
-		wlan_pdev_obj_unlock(pdev);
 
 	return QDF_STATUS_SUCCESS;
 }

+ 190 - 0
umac/cmn_services/obj_mgr/src/wlan_objmgr_peer_obj.c

@@ -672,3 +672,193 @@ void wlan_objmgr_peer_release_ref(struct wlan_objmgr_peer *peer,
 	return;
 }
 qdf_export_symbol(wlan_objmgr_peer_release_ref);
+
+struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_active_head(
+				struct wlan_objmgr_vdev *vdev,
+				qdf_list_t *peer_list,
+				wlan_objmgr_ref_dbgid dbg_id)
+{
+	struct wlan_objmgr_peer *peer;
+	qdf_list_node_t *vdev_node = NULL;
+	qdf_list_node_t *prev_vdev_node = NULL;
+
+	wlan_vdev_obj_lock(vdev);
+
+	if (qdf_list_peek_front(peer_list, &vdev_node) != QDF_STATUS_SUCCESS) {
+		wlan_vdev_obj_unlock(vdev);
+		return NULL;
+	}
+
+	do {
+		peer = qdf_container_of(vdev_node, struct wlan_objmgr_peer,
+						vdev_peer);
+
+		if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) ==
+				QDF_STATUS_SUCCESS) {
+			wlan_vdev_obj_unlock(vdev);
+			return peer;
+		}
+
+		prev_vdev_node = vdev_node;
+	} while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) ==
+							QDF_STATUS_SUCCESS);
+
+	wlan_vdev_obj_unlock(vdev);
+
+	return NULL;
+}
+
+struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_vdev(
+					struct wlan_objmgr_vdev *vdev,
+					qdf_list_t *peer_list,
+					struct wlan_objmgr_peer *peer,
+					wlan_objmgr_ref_dbgid dbg_id)
+{
+	struct wlan_objmgr_peer *peer_next;
+	qdf_list_node_t *vdev_node = NULL;
+	qdf_list_node_t *prev_vdev_node = NULL;
+
+	if (peer == NULL)
+		return NULL;
+
+	wlan_vdev_obj_lock(vdev);
+
+	prev_vdev_node = &peer->vdev_peer;
+	while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) ==
+						QDF_STATUS_SUCCESS) {
+		peer_next = qdf_container_of(vdev_node, struct wlan_objmgr_peer,
+					vdev_peer);
+
+		if (wlan_objmgr_peer_try_get_ref(peer_next, dbg_id) ==
+				QDF_STATUS_SUCCESS) {
+			wlan_vdev_obj_unlock(vdev);
+			return peer_next;
+		}
+
+		prev_vdev_node = vdev_node;
+	}
+
+	wlan_vdev_obj_unlock(vdev);
+
+	return NULL;
+}
+
+struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_psoc(
+					struct wlan_peer_list *peer_list,
+					uint8_t hash_index,
+					struct wlan_objmgr_peer *peer,
+					wlan_objmgr_ref_dbgid dbg_id)
+{
+	struct wlan_objmgr_peer *peer_next = NULL;
+	qdf_list_node_t *psoc_node = NULL;
+	qdf_list_node_t *prev_psoc_node = NULL;
+	qdf_list_t *obj_list;
+
+	qdf_spin_lock_bh(&peer_list->peer_list_lock);
+	obj_list = &peer_list->peer_hash[hash_index];
+
+	prev_psoc_node = &peer->psoc_peer;
+	while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) ==
+						QDF_STATUS_SUCCESS) {
+		peer_next = qdf_container_of(psoc_node, struct wlan_objmgr_peer,
+						psoc_peer);
+
+		if (wlan_objmgr_peer_try_get_ref(peer_next, dbg_id) ==
+				QDF_STATUS_SUCCESS) {
+			qdf_spin_unlock_bh(&peer_list->peer_list_lock);
+			return peer_next;
+		}
+
+		prev_psoc_node = psoc_node;
+	}
+
+	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
+
+	return NULL;
+}
+
+struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_active_head(
+					struct wlan_peer_list *peer_list,
+					uint8_t hash_index,
+					wlan_objmgr_ref_dbgid dbg_id)
+{
+	struct wlan_objmgr_peer *peer;
+	qdf_list_node_t *psoc_node = NULL;
+	qdf_list_node_t *prev_psoc_node = NULL;
+	qdf_list_t *obj_list;
+
+	qdf_spin_lock_bh(&peer_list->peer_list_lock);
+	obj_list = &peer_list->peer_hash[hash_index];
+
+	if (qdf_list_peek_front(obj_list, &psoc_node) != QDF_STATUS_SUCCESS) {
+		qdf_spin_unlock_bh(&peer_list->peer_list_lock);
+		return NULL;
+	}
+
+	do {
+		peer = qdf_container_of(psoc_node, struct wlan_objmgr_peer,
+						psoc_peer);
+		if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) ==
+				QDF_STATUS_SUCCESS) {
+			qdf_spin_unlock_bh(&peer_list->peer_list_lock);
+			return peer;
+		}
+
+		prev_psoc_node = psoc_node;
+	} while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) ==
+						QDF_STATUS_SUCCESS);
+
+	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
+	return NULL;
+}
+
+struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head_ref(
+					struct wlan_peer_list *peer_list,
+					uint8_t hash_index,
+					wlan_objmgr_ref_dbgid dbg_id)
+{
+	struct wlan_objmgr_peer *peer;
+	qdf_list_t *obj_list;
+
+	qdf_spin_lock_bh(&peer_list->peer_list_lock);
+	obj_list = &peer_list->peer_hash[hash_index];
+
+	peer = wlan_psoc_peer_list_peek_head(obj_list);
+
+	/**
+	 * This API is invoked by caller, only when caller need to access the
+	 * peer object, though object is not in active state, this API should be
+	 * used carefully, where multiple object frees are not triggered
+	 */
+	if (peer)
+		wlan_objmgr_peer_get_ref(peer, dbg_id);
+
+	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
+
+	return peer;
+}
+
+struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc_ref(
+			struct wlan_peer_list *peer_list, uint8_t hash_index,
+			struct wlan_objmgr_peer *peer,
+			wlan_objmgr_ref_dbgid dbg_id)
+{
+	qdf_list_t *obj_list;
+	struct wlan_objmgr_peer *peer_next;
+
+	qdf_spin_lock_bh(&peer_list->peer_list_lock);
+	obj_list = &peer_list->peer_hash[hash_index];
+
+	peer_next = wlan_peer_get_next_peer_of_psoc(obj_list, peer);
+	/**
+	 * This API is invoked by caller, only when caller need to access the
+	 * peer object, though object is not in active state, this API should be
+	 * used carefully, where multiple free on object are not triggered
+	 */
+	if (peer_next)
+		wlan_objmgr_peer_get_ref(peer_next, dbg_id);
+
+	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
+
+	return peer_next;
+}

+ 23 - 52
umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj.c

@@ -416,27 +416,18 @@ QDF_STATUS wlan_objmgr_iterate_obj_list(
 	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;
 	uint16_t max_vdev_cnt;
 
-	/* If caller requests for lock free opeation, do not acquire,
-	 * handler will handle the synchronization
-	 */
-	if (!lock_free_op)
-		wlan_psoc_obj_lock(psoc);
-
 	switch (obj_type) {
 	case WLAN_PDEV_OP:
 		/* Iterate through PDEV list, invoke handler for each pdev */
 		for (obj_id = 0; obj_id < WLAN_UMAC_MAX_PDEVS; obj_id++) {
-			pdev = objmgr->wlan_pdev_list[obj_id];
-			if ((pdev != NULL) &&
-			    (wlan_objmgr_pdev_try_get_ref(pdev, dbg_id) ==
-				QDF_STATUS_SUCCESS)) {
+			pdev = wlan_objmgr_get_pdev_by_id(psoc, obj_id, dbg_id);
+			if (pdev != NULL) {
 				handler(psoc, (void *)pdev, arg);
 				wlan_objmgr_pdev_release_ref(pdev, dbg_id);
 			}
@@ -446,10 +437,9 @@ QDF_STATUS wlan_objmgr_iterate_obj_list(
 		/* Iterate through VDEV list, invoke handler for each vdev */
 		max_vdev_cnt = wlan_psoc_get_max_vdev_count(psoc);
 		for (obj_id = 0; obj_id < max_vdev_cnt; obj_id++) {
-			vdev = objmgr->wlan_vdev_list[obj_id];
-			if ((vdev != NULL) &&
-			    (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) ==
-				QDF_STATUS_SUCCESS)) {
+			vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
+						obj_id, dbg_id);
+			if (vdev != NULL) {
 				handler(psoc, vdev, arg);
 				wlan_objmgr_vdev_release_ref(vdev, dbg_id);
 			}
@@ -458,34 +448,24 @@ QDF_STATUS wlan_objmgr_iterate_obj_list(
 	case WLAN_PEER_OP:
 		/* Iterate through PEER list, invoke handler for each peer */
 		peer_list = &objmgr->peer_list;
-		/* psoc lock should be taken before list lock */
-		if (!lock_free_op)
-			qdf_spin_lock_bh(&peer_list->peer_list_lock);
 		/* Since peer list has sublist, iterate through sublists */
 		for (i = 0; i < WLAN_PEER_HASHSIZE; i++) {
-			obj_list = &peer_list->peer_hash[i];
-			peer = wlan_psoc_peer_list_peek_head(obj_list);
+			peer = wlan_psoc_peer_list_peek_active_head(peer_list,
+					i, dbg_id);
 			while (peer) {
+				handler(psoc, (void *)peer, arg);
 				/* Get next peer */
-				peer_next = wlan_peer_get_next_peer_of_psoc(
-								obj_list, 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_next =
+					wlan_peer_get_next_active_peer_of_psoc(
+						peer_list, i, peer, dbg_id);
+				wlan_objmgr_peer_release_ref(peer,  dbg_id);
 				peer = peer_next;
 			}
 		}
-		if (!lock_free_op)
-			qdf_spin_unlock_bh(&peer_list->peer_list_lock);
 		break;
 	default:
 		break;
 	}
-	if (!lock_free_op)
-		wlan_psoc_obj_unlock(psoc);
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -502,7 +482,6 @@ QDF_STATUS wlan_objmgr_iterate_obj_list_all(
 	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;
@@ -512,16 +491,14 @@ QDF_STATUS wlan_objmgr_iterate_obj_list_all(
 	/* If caller requests for lock free opeation, do not acquire,
 	 * handler will handle the synchronization
 	 */
-	if (!lock_free_op)
-		wlan_psoc_obj_lock(psoc);
 
 	switch (obj_type) {
 	case WLAN_PDEV_OP:
 		/* Iterate through PDEV list, invoke handler for each pdev */
 		for (obj_id = 0; obj_id < WLAN_UMAC_MAX_PDEVS; obj_id++) {
-			pdev = objmgr->wlan_pdev_list[obj_id];
+			pdev = wlan_objmgr_get_pdev_by_id_no_state(psoc,
+							obj_id, dbg_id);
 			if (pdev != NULL) {
-				wlan_objmgr_pdev_get_ref(pdev, dbg_id);
 				handler(psoc, (void *)pdev, arg);
 				wlan_objmgr_pdev_release_ref(pdev, dbg_id);
 			}
@@ -531,9 +508,9 @@ QDF_STATUS wlan_objmgr_iterate_obj_list_all(
 		/* Iterate through VDEV list, invoke handler for each vdev */
 		max_vdev_cnt = wlan_psoc_get_max_vdev_count(psoc);
 		for (obj_id = 0; obj_id < max_vdev_cnt; obj_id++) {
-			vdev = objmgr->wlan_vdev_list[obj_id];
+			vdev = wlan_objmgr_get_vdev_by_id_from_psoc_no_state(
+					psoc, obj_id, dbg_id);
 			if (vdev != NULL) {
-				wlan_objmgr_vdev_get_ref(vdev, dbg_id);
 				handler(psoc, vdev, arg);
 				wlan_objmgr_vdev_release_ref(vdev, dbg_id);
 			}
@@ -542,31 +519,25 @@ QDF_STATUS wlan_objmgr_iterate_obj_list_all(
 	case WLAN_PEER_OP:
 		/* Iterate through PEER list, invoke handler for each peer */
 		peer_list = &objmgr->peer_list;
-		/* psoc lock should be taken before list lock */
-		if (!lock_free_op)
-			qdf_spin_lock_bh(&peer_list->peer_list_lock);
 		/* Since peer list has sublist, iterate through sublists */
 		for (i = 0; i < WLAN_PEER_HASHSIZE; i++) {
-			obj_list = &peer_list->peer_hash[i];
-			peer = wlan_psoc_peer_list_peek_head(obj_list);
+			peer = wlan_psoc_peer_list_peek_head_ref(peer_list, i,
+									dbg_id);
+
 			while (peer) {
-				/* Get next peer */
-				peer_next = wlan_peer_get_next_peer_of_psoc(
-								obj_list, peer);
-				wlan_objmgr_peer_get_ref(peer, dbg_id);
 				handler(psoc, (void *)peer, arg);
+				/* Get next peer */
+				peer_next = wlan_peer_get_next_peer_of_psoc_ref(
+								peer_list, i,
+								peer, dbg_id);
 				wlan_objmgr_peer_release_ref(peer, dbg_id);
 				peer = peer_next;
 			}
 		}
-		if (!lock_free_op)
-			qdf_spin_unlock_bh(&peer_list->peer_list_lock);
 		break;
 	default:
 		break;
 	}
-	if (!lock_free_op)
-		wlan_psoc_obj_unlock(psoc);
 
 	return QDF_STATUS_SUCCESS;
 }

+ 66 - 0
umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c

@@ -898,3 +898,69 @@ bool wlan_vdev_is_connected(struct wlan_objmgr_vdev *vdev)
 	return true;
 }
 qdf_export_symbol(wlan_vdev_is_connected);
+
+struct wlan_objmgr_vdev *wlan_pdev_vdev_list_peek_active_head(
+			struct wlan_objmgr_pdev *pdev,
+			qdf_list_t *vdev_list, wlan_objmgr_ref_dbgid dbg_id)
+{
+	struct wlan_objmgr_vdev *vdev;
+	qdf_list_node_t *node = NULL;
+	qdf_list_node_t *prev_node = NULL;
+
+	wlan_pdev_obj_lock(pdev);
+
+	if (qdf_list_peek_front(vdev_list, &node) != QDF_STATUS_SUCCESS) {
+		wlan_pdev_obj_unlock(pdev);
+		return NULL;
+	}
+
+	do {
+		vdev = qdf_container_of(node, struct wlan_objmgr_vdev,
+								vdev_node);
+		if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) ==
+						QDF_STATUS_SUCCESS) {
+			wlan_pdev_obj_unlock(pdev);
+			return vdev;
+		}
+
+		prev_node = node;
+	} while (qdf_list_peek_next(vdev_list, prev_node, &node) ==
+						QDF_STATUS_SUCCESS);
+
+	wlan_pdev_obj_unlock(pdev);
+
+	return NULL;
+}
+
+struct wlan_objmgr_vdev *wlan_vdev_get_next_active_vdev_of_pdev(
+			struct wlan_objmgr_pdev *pdev,
+			qdf_list_t *vdev_list,
+			struct wlan_objmgr_vdev *vdev,
+			wlan_objmgr_ref_dbgid dbg_id)
+{
+	struct wlan_objmgr_vdev *vdev_next;
+	qdf_list_node_t *node = &vdev->vdev_node;
+	qdf_list_node_t *prev_node = NULL;
+
+	if (node == NULL)
+		return NULL;
+
+	wlan_pdev_obj_lock(pdev);
+	prev_node = node;
+	while (qdf_list_peek_next(vdev_list, prev_node, &node) ==
+							QDF_STATUS_SUCCESS) {
+		vdev_next = qdf_container_of(node, struct wlan_objmgr_vdev,
+								vdev_node);
+		if (wlan_objmgr_vdev_try_get_ref(vdev_next, dbg_id) ==
+						QDF_STATUS_SUCCESS) {
+			wlan_pdev_obj_unlock(pdev);
+			return vdev_next;
+		}
+
+		prev_node = node;
+	}
+	wlan_pdev_obj_unlock(pdev);
+
+	return NULL;
+}
+