Browse Source

qcacld-3.0: Process MLO LL_STATS based on vdev_id bitmap

In the current driver implementation for processing MLO LL_STATS,
host expects to receive Radio Stats as the last stats event sent
by FW in response to unified_ll_stats_get_sta command. But, if the
FW sends a dummy Radio stats event as the first stats event,
then it leads to an assertion in the host.

To avoid this issue, add logic to process MLO LL_STATS based on the
mlo_vdev_id_bitmap.

Change-Id: I83dc539c6624963cf054130ff2e3cfb3660cbaf3
CRs-Fixed: 3275406
Aditya Kodukula 2 years ago
parent
commit
2e178c71b5
1 changed files with 27 additions and 13 deletions
  1. 27 13
      core/hdd/src/wlan_hdd_stats.c

+ 27 - 13
core/hdd/src/wlan_hdd_stats.c

@@ -473,6 +473,8 @@ struct hdd_ll_stats {
  * @request_bitmap: userspace-assigned link layer stats request bitmap
  * @ll_stats_lock: Lock to serially access request_bitmap
  * @vdev_id: id of vdev handle
+ * @is_mlo_req: is the request for mlo link layer stats
+ * @mlo_vdev_id_bitmap: bitmap of all ml vdevs
  */
 struct hdd_ll_stats_priv {
 	qdf_list_t ll_stats_q;
@@ -480,6 +482,8 @@ struct hdd_ll_stats_priv {
 	uint32_t request_bitmap;
 	qdf_spinlock_t ll_stats_lock;
 	uint8_t vdev_id;
+	bool is_mlo_req;
+	uint32_t mlo_vdev_id_bitmap;
 };
 
 /*
@@ -1548,6 +1552,12 @@ static void hdd_process_ll_stats(tSirLLStatsResults *results,
 		if (!results->num_peers)
 			priv->request_bitmap &= ~(WMI_LINK_STATS_ALL_PEER);
 		priv->request_bitmap &= ~stats->result_param_id;
+
+		/* Firmware sends interface stats based on vdev_id_bitmap
+		 * So, clear the mlo_vdev_id_bitmap in the host accordingly
+		 */
+		if (priv->is_mlo_req)
+			priv->mlo_vdev_id_bitmap &= ~(1 << results->ifaceId);
 	} else if (results->paramId & WMI_LINK_STATS_ALL_PEER) {
 		struct wifi_peer_stat *peer_stat = (struct wifi_peer_stat *)
 						   results->results;
@@ -1590,6 +1600,8 @@ static void hdd_process_ll_stats(tSirLLStatsResults *results,
 		qdf_list_insert_back(&priv->ll_stats_q, &stats->ll_stats_node);
 
 	if (!priv->request_bitmap) {
+		if (priv->is_mlo_req && priv->mlo_vdev_id_bitmap)
+			goto out;
 exit:
 		qdf_spin_unlock(&priv->ll_stats_lock);
 
@@ -1601,7 +1613,7 @@ exit:
 		osif_request_complete(request);
 		return;
 	}
-
+out:
 	qdf_spin_unlock(&priv->ll_stats_lock);
 }
 
@@ -1632,6 +1644,12 @@ static void hdd_debugfs_process_ll_stats(struct hdd_adapter *adapter,
 			priv->request_bitmap &= ~(WMI_LINK_STATS_ALL_PEER);
 
 		priv->request_bitmap &= ~(WMI_LINK_STATS_IFACE);
+
+		/* Firmware sends interface stats based on vdev_id_bitmap
+		 * So, clear the mlo_vdev_id_bitmap in the host accordingly
+		 */
+		if (priv->is_mlo_req)
+			priv->mlo_vdev_id_bitmap &= ~(1 << results->ifaceId);
 	} else if (results->paramId & WMI_LINK_STATS_ALL_PEER) {
 		hdd_debugfs_process_peer_stats(adapter, results->results);
 		if (!results->moreResultToFollow)
@@ -1641,6 +1659,8 @@ static void hdd_debugfs_process_ll_stats(struct hdd_adapter *adapter,
 	}
 
 	if (!priv->request_bitmap) {
+		if (priv->is_mlo_req && priv->mlo_vdev_id_bitmap)
+			return;
 		/* Thread which invokes this function has allocated memory in
 		 * WMA for radio stats, that memory should be freed from the
 		 * same thread to avoid any race conditions between two threads
@@ -1664,22 +1684,11 @@ wlan_hdd_update_ll_stats_request_bitmap(struct hdd_context *hdd_ctx,
 		return;
 	}
 
-	/* The radio stats event is expected at the last, for MLO ll_stats */
-	if (priv->request_bitmap != WMI_LINK_STATS_RADIO &&
-	    results->paramId == WMI_LINK_STATS_RADIO) {
-		hdd_err("req_id %d resp_id %u req_bitmap 0x%x resp_bitmap 0x%x",
-			priv->request_id, results->rspId,
-			priv->request_bitmap, results->paramId);
-		QDF_DEBUG_PANIC("Out of order event received for MLO_LL_STATS");
-	}
-
 	is_mlo_link = wlan_vdev_mlme_get_is_mlo_link(hdd_ctx->psoc,
 						     results->ifaceId);
 	/* In case of MLO Connection, set the request_bitmap */
 	if (is_mlo_link && results->paramId == WMI_LINK_STATS_IFACE) {
-		/* The radio stats are received at the last, hence set
-		 * the request_bitmap for MLO link vdev iface stats.
-		 */
+		/* Set the request_bitmap for MLO link vdev iface stats */
 		if (!(priv->request_bitmap & results->paramId))
 			priv->request_bitmap |= results->paramId;
 
@@ -2272,6 +2281,11 @@ static int wlan_hdd_send_ll_stats_req(struct hdd_adapter *adapter,
 	priv->request_id = req->reqId;
 	priv->request_bitmap = req->paramIdMask;
 	priv->vdev_id = adapter->vdev_id;
+	priv->is_mlo_req = wlan_vdev_mlme_get_is_mlo_vdev(hdd_ctx->psoc,
+							  adapter->vdev_id);
+	if (priv->is_mlo_req)
+		priv->mlo_vdev_id_bitmap = req->mlo_vdev_id_bitmap;
+
 	qdf_spinlock_create(&priv->ll_stats_lock);
 	qdf_list_create(&priv->ll_stats_q, HDD_LINK_STATS_MAX);