Ver Fonte

qcacmn: Change to address multiple logically deleted node

In the existing code we check for the first instance of logically deleted
node and return to the caller, but there might be multiple nodes in logically
deleted state at a given instance.

Modify code to populate all the peers in logically deleted state in a list
and return the node with delete response pending from FW, to the caller.

Change-Id: I79ce99cc97404c2260ae18983709707ec6e8cdac
CRs-Fixed: 2058168
Soumya Bhat há 7 anos atrás
pai
commit
5d0786be5e

+ 7 - 3
umac/cmn_services/obj_mgr/inc/wlan_objmgr_psoc_obj.h

@@ -530,7 +530,7 @@ struct wlan_objmgr_peer *wlan_objmgr_get_peer_no_state(
 			wlan_objmgr_ref_dbgid dbg_id);
 
 /**
- * wlan_objmgr_get_peer_logically_deleted_by_mac_n_vdev() - get peer from
+ * wlan_objmgr_populate_logically_deleted_peerlist_by_mac_n_vdev() - get peer from
  *                                                psoc peer list using
  *                                                mac and vdev
  *                                                self mac
@@ -542,10 +542,10 @@ struct wlan_objmgr_peer *wlan_objmgr_get_peer_no_state(
  * API to find peer object pointer by MAC addr and vdev self mac
  * address for a node that is logically in deleted state
  *
- * Return: peer pointer
+ * Return: List of peer pointers
  *         NULL on FAILURE
  */
-struct wlan_objmgr_peer *wlan_objmgr_get_peer_logically_deleted_by_mac_n_vdev(
+qdf_list_t *wlan_objmgr_populate_logically_deleted_peerlist_by_mac_n_vdev(
 			struct wlan_objmgr_psoc *psoc, uint8_t *macaddr,
 			uint8_t *bssid, wlan_objmgr_ref_dbgid dbg_id);
 
@@ -1199,4 +1199,8 @@ static inline uint8_t wlan_objmgr_psoc_get_band_capability(
 	return psoc->soc_nif.user_config.band_capability;
 }
 
+struct wlan_logically_del_peer {
+	qdf_list_node_t list;
+	struct wlan_objmgr_peer *peer;
+};
 #endif /* _WLAN_OBJMGR_PSOC_OBJ_H_*/

+ 10 - 2
umac/cmn_services/obj_mgr/src/wlan_objmgr_peer_obj.c

@@ -631,9 +631,17 @@ void wlan_objmgr_peer_release_ref(struct wlan_objmgr_peer *peer,
 	}
 	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))
+	/* Provide synchronization from the access to add peer
+	 * to logically deleted peer list.
+	 */
+	wlan_peer_obj_lock(peer);
+	/* Decrement ref count, free peer object, if ref count == 0 */
+	if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt)) {
+		wlan_peer_obj_unlock(peer);
 		wlan_objmgr_peer_obj_destroy(peer);
+	} else {
+		wlan_peer_obj_unlock(peer);
+	}
 
 	return;
 }

+ 46 - 18
umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj.c

@@ -1166,7 +1166,7 @@ static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer_no_state(
 }
 
 /**
- * wlan_obj_psoc_peerlist_get_peer_logically_deleted_by_mac_n_bssid() - get peer
+ * wlan_obj_psoc_populate_logically_deleted_peerlist_by_mac_n_bssid() - get peer
  *                                           from psoc peer list using
  *                                           mac and vdev self mac
  * @obj_list: peer object list
@@ -1176,23 +1176,37 @@ static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer_no_state(
  *
  * API to finds peer object pointer by MAC addr and BSSID from
  * peer hash list for a node which is in logically deleted state,
- *  bssid check is done on matching peer
+ * bssid check is done on matching peer
  *
- * Return: peer pointer
+ * Caller to free the list allocated in this function
+ *
+ * Return: list of peer pointers
  *         NULL on FAILURE
  */
-static struct wlan_objmgr_peer
-	*wlan_obj_psoc_peerlist_get_peer_logically_deleted_by_mac_n_bssid(
+static qdf_list_t
+	*wlan_obj_psoc_populate_logically_deleted_peerlist_by_mac_n_bssid(
 				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;
+	struct wlan_logically_del_peer *peer_list = NULL;
+	qdf_list_t *logical_del_peer_list = NULL;
+	bool lock_released = false;
+
+	logical_del_peer_list = qdf_mem_malloc(sizeof(*logical_del_peer_list));
+	if (!logical_del_peer_list) {
+		obj_mgr_err("failed to allocate list");
+		return NULL;
+	}
+
+	qdf_list_create(logical_del_peer_list, WLAN_UMAC_PSOC_MAX_PEERS);
 
 	/* Iterate through hash list to get the peer */
 	peer = wlan_psoc_peer_list_peek_head(obj_list);
 	while (peer != NULL) {
+		wlan_peer_obj_lock(peer);
 		/* For peer, macaddr is key */
 		if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr)
 			== QDF_STATUS_SUCCESS) {
@@ -1204,21 +1218,35 @@ static struct wlan_objmgr_peer
 			if (wlan_peer_bssid_match(peer, bssid) ==
 							QDF_STATUS_SUCCESS) {
 				/* Return peer in logically deleted state */
-				if (peer->obj_state ==
-					WLAN_OBJ_STATE_LOGICALLY_DELETED) {
+				if ((peer->obj_state ==
+					WLAN_OBJ_STATE_LOGICALLY_DELETED) &&
+					qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) {
 					wlan_objmgr_peer_get_ref(peer, dbg_id);
-
-					return peer;
+					wlan_peer_obj_unlock(peer);
+					lock_released = true;
+					peer_list = qdf_mem_malloc(sizeof(struct wlan_logically_del_peer));
+					peer_list->peer = peer;
+					qdf_list_insert_front(logical_del_peer_list, &peer_list->list);
 				}
 			}
 		}
+
+		if (!lock_released)
+			wlan_peer_obj_unlock(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;
+	if (qdf_list_empty(logical_del_peer_list)) {
+		qdf_mem_free(logical_del_peer_list);
+		return NULL;
+	} else {
+		return logical_del_peer_list;
+	}
+
 }
 
 /**
@@ -1526,7 +1554,7 @@ EXPORT_SYMBOL(wlan_objmgr_get_peer_by_mac_n_vdev);
 
 
 /**
- * wlan_objmgr_get_peer_logically_deleted_by_mac_n_vdev() - get peer from psoc
+ * wlan_objmgr_populate_logically_deleted_peerlist_by_mac_n_vdev() - get peer from psoc
  *                                                           peer list using
  *                                                           mac and vdev
  *                                                           self mac
@@ -1538,18 +1566,18 @@ EXPORT_SYMBOL(wlan_objmgr_get_peer_by_mac_n_vdev);
  * API to finds peer object pointer by MAC addr and BSSID from
  * peer hash list, bssid check is done on matching peer
  *
- * Return: peer pointer
+ * Return: list of peer pointer pointers
  *         NULL on FAILURE
  */
 
-struct wlan_objmgr_peer *wlan_objmgr_get_peer_logically_deleted_by_mac_n_vdev(
+qdf_list_t *wlan_objmgr_populate_logically_deleted_peerlist_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;
-	struct wlan_objmgr_peer *peer = NULL;
-	struct wlan_peer_list *peer_list;
+	struct wlan_peer_list *peer_list = NULL;
+	qdf_list_t *logical_del_peer_list = NULL;
 
 	/* psoc lock should be taken before peer list lock */
 	wlan_psoc_obj_lock(psoc);
@@ -1564,14 +1592,14 @@ struct wlan_objmgr_peer *wlan_objmgr_get_peer_logically_deleted_by_mac_n_vdev(
 	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_logically_deleted_by_mac_n_bssid(
+	logical_del_peer_list = wlan_obj_psoc_populate_logically_deleted_peerlist_by_mac_n_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;
+	return logical_del_peer_list;
 }
-EXPORT_SYMBOL(wlan_objmgr_get_peer_logically_deleted_by_mac_n_vdev);
+EXPORT_SYMBOL(wlan_objmgr_populate_logically_deleted_peerlist_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,