Browse Source

qcacmn: Fix local_link_id assignment for link peers

Currently the local_link_id is assigned to each
link peer, during peer setup, with an incremental
number, based on the number of peer setup being
done for the link peers corresponding to the same MLD.

The above logic does not handle the link switch case,
where any particular link peer can be created and deleted
multiple times, thereby leading to 'n' number of peer
setups, each assigning an incremental number as the
local_link_id to the link peer. Due to this the local_link_id
value will exceed the MAX_MLO_LINKS ceiling value, and
when this local_link_id is used to set the frequency band
it leads to an out-of-bound array access.

In order to fix the above mentioned scenario, maintain
a mapping of link peer mac address to local_link_id inside
the txrx_peer (common for all link peers) and use this mapping
table to get the local_link_id. This will make sure that during
any link re-purpose, the link peer being setup will regain the
local_link_id which it was assigned during the first time it was
setup.

Change-Id: Ia78413efe328c81bab74b3a048214d3807b6c6c4
CRs-Fixed: 3658539
Rakesh Pillai 1 year ago
parent
commit
a7fe389b77
3 changed files with 62 additions and 4 deletions
  1. 0 1
      dp/wifi3.0/dp_main.c
  2. 45 1
      dp/wifi3.0/dp_rings_main.c
  3. 17 2
      dp/wifi3.0/dp_types.h

+ 0 - 1
dp/wifi3.0/dp_main.c

@@ -5568,7 +5568,6 @@ dp_txrx_peer_reset_local_link_id(struct dp_txrx_peer *txrx_peer)
 {
 	int i;
 
-	txrx_peer->local_link_id = 0;
 	for (i = 0; i <= DP_MAX_MLO_LINKS; i++)
 		txrx_peer->ll_band[i] = DP_BAND_INVALID;
 }

+ 45 - 1
dp/wifi3.0/dp_rings_main.c

@@ -2511,6 +2511,45 @@ static void dp_peer_setup_get_reo_hash(struct dp_vdev *vdev,
 }
 #endif /* IPA_OFFLOAD */
 #if defined WLAN_FEATURE_11BE_MLO && defined DP_MLO_LINK_STATS_SUPPORT
+
+static inline uint8_t
+dp_peer_get_local_link_id(struct dp_peer *peer, struct dp_txrx_peer *txrx_peer)
+{
+	struct dp_local_link_id_peer_map *ll_id_peer_map =
+						&txrx_peer->ll_id_peer_map[0];
+	int i;
+
+	/*
+	 * Search for the peer entry in the
+	 * local_link_id to peer mac_addr mapping table
+	 */
+	for (i = 0; i < DP_MAX_MLO_LINKS; i++) {
+		if (ll_id_peer_map[i].in_use &&
+		    !qdf_mem_cmp(&peer->mac_addr.raw[0],
+				 &ll_id_peer_map[i].mac_addr.raw[0],
+				 QDF_MAC_ADDR_SIZE))
+			return ll_id_peer_map[i].local_link_id + 1;
+	}
+
+	/*
+	 * Create new entry for peer in the
+	 * local_link_id to peer mac_addr mapping table
+	 */
+	for (i = 0; i < DP_MAX_MLO_LINKS; i++) {
+		if (ll_id_peer_map[i].in_use)
+			continue;
+
+		ll_id_peer_map[i].in_use = 1;
+		ll_id_peer_map[i].local_link_id = i;
+		qdf_mem_copy(&ll_id_peer_map[i].mac_addr.raw[0],
+			     &peer->mac_addr.raw[0], QDF_MAC_ADDR_SIZE);
+		return ll_id_peer_map[i].local_link_id + 1;
+	}
+
+	/* We should not hit this case..!! Assert ?? */
+	return 0;
+}
+
 /**
  *  dp_peer_set_local_link_id() - Set local link id
  *  @peer: dp peer handle
@@ -2527,7 +2566,12 @@ dp_peer_set_local_link_id(struct dp_peer *peer)
 
 	txrx_peer = dp_get_txrx_peer(peer);
 	if (txrx_peer)
-		peer->local_link_id = ++txrx_peer->local_link_id;
+		peer->local_link_id = dp_peer_get_local_link_id(peer,
+								txrx_peer);
+
+	dp_info("Peer " QDF_MAC_ADDR_FMT " txrx_peer %pK local_link_id %d",
+		QDF_MAC_ADDR_REF(peer->mac_addr.raw), txrx_peer,
+		peer->local_link_id);
 }
 #else
 static inline void

+ 17 - 2
dp/wifi3.0/dp_types.h

@@ -4884,6 +4884,20 @@ struct dp_peer_stats {
 #endif
 };
 
+/**
+ * struct dp_local_link_id_peer_map - Mapping table entry for link peer mac
+ *				      address to local_link_id
+ * @in_use: set if this entry is having valid mapping between local_link_id
+ *	    and the link peer mac address.
+ * @local_link_id: local_link_id assigned to the link peer
+ * @mac_addr: link peer mac address
+ */
+struct dp_local_link_id_peer_map {
+	uint8_t in_use;
+	uint8_t local_link_id;
+	union dp_align_mac_addr mac_addr;
+};
+
 /**
  * struct dp_txrx_peer: DP txrx_peer structure used in per pkt path
  * @vdev: VDEV to which this peer is associated
@@ -4914,7 +4928,7 @@ struct dp_peer_stats {
  * @bw: bandwidth of peer connection
  * @mpdu_retry_threshold: MPDU retry threshold to increment tx bad count
  * @band: Link ID to band mapping
- * @local_link_id: Local host link ID.
+ * @ll_id_peer_map: Mapping table for link peer mac address to local_link_id
  * @ll_band: Local link id band mapping
  * @stats_arr_size: peer stats array size
  * @stats: Peer link and mld statistics
@@ -4969,7 +4983,8 @@ struct dp_txrx_peer {
 #if defined WLAN_FEATURE_11BE_MLO && defined DP_MLO_LINK_STATS_SUPPORT
 	/* Link ID to band mapping, (1 MLD + DP_MAX_MLO_LINKS) */
 	uint8_t band[DP_MAX_MLO_LINKS + 1];
-	uint8_t local_link_id;
+
+	struct dp_local_link_id_peer_map ll_id_peer_map[DP_MAX_MLO_LINKS];
 	uint8_t ll_band[DP_MAX_MLO_LINKS + 1];
 #endif
 	uint8_t stats_arr_size;