Pārlūkot izejas kodu

qcacmn: Allow firmware to auto detect tx bssid

In the case of of 5 GHz + non-tx 6 GHz MLO connection, the scan entry
generated from the ML-probe might not carry MBSSID information of the
non-tx partner. The RNR of the assoc link will also not be inherited.
Therefore, the mbssid info is not generated for this non-tx 6 GHz scan
entry. In such cases, if there is a vdev restart, host driver sends zero
mac address in trans bssid, leading to issues with connection.

To fix this:
1. Look up the RNR db for the 6 GHz link, and determine if the bss param
corresponding to the bssid is non-tx MBSSID.
2. If it is a non-tx MBSSID and there is no mbssid info in the scan cache,
then configure the tx-bssid as broadcast mac.
3. This allows the firmware to auto-detect the tx bssid from the upcoming
beacons.
4. Also, save the neighbor entries from the beacon/probes received from
the firmware during roam sync and other events to facilitate the look-up.
5. If there is no existing entry for the roamed non-tx link, then caching
the neighbor info from the assoc partner link would store the valid entry
into the rnr db.

Change-Id: I2c16ed1428b578efaeed98daca08b722b0d40a05
CRs-Fixed: 3784879
Surya Prakash Sivaraj 1 gadu atpakaļ
vecāks
revīzija
836d95ed6f

+ 7 - 0
umac/mlme/vdev_mgr/core/src/vdev_mgr_ops.c

@@ -700,6 +700,7 @@ static QDF_STATUS vdev_mgr_up_param_update(
 	struct vdev_mlme_mbss_11ax *mbss;
 	struct wlan_objmgr_vdev *vdev;
 	uint8_t bssid[QDF_MAC_ADDR_SIZE];
+	struct qdf_mac_addr bcast_mac = QDF_MAC_ADDR_BCAST_INIT;
 
 	vdev = mlme_obj->vdev;
 	param->vdev_id = wlan_vdev_get_id(vdev);
@@ -713,13 +714,19 @@ static QDF_STATUS vdev_mgr_up_param_update(
 			   QDF_MAC_ADDR_REF(mbss->trans_bssid),
 			   QDF_MAC_ADDR_REF(mbss->non_trans_bssid),
 			  mbss->profile_idx, mbss->profile_num);
+		if (!qdf_mem_cmp(bcast_mac.bytes, mbss->trans_bssid,
+				 QDF_MAC_ADDR_SIZE))
+			goto update_tx_prof;
+
 		if ((qdf_mem_cmp(bssid, mbss->trans_bssid, QDF_MAC_ADDR_SIZE)) &&
 		    (qdf_mem_cmp(bssid, mbss->non_trans_bssid, QDF_MAC_ADDR_SIZE)))
 			return QDF_STATUS_SUCCESS;
 	}
 
+update_tx_prof:
 	param->profile_idx = mbss->profile_idx;
 	param->profile_num = mbss->profile_num;
+
 	qdf_mem_copy(param->trans_bssid, mbss->trans_bssid, QDF_MAC_ADDR_SIZE);
 
 	return QDF_STATUS_SUCCESS;

+ 8 - 0
umac/scan/core/src/wlan_scan_cache_db.c

@@ -258,6 +258,11 @@ void scm_filter_rnr_flag_pno(struct wlan_objmgr_vdev *vdev,
 		}
 	}
 }
+#else
+static void scm_add_rnr_channel_db(struct wlan_objmgr_psoc *psoc,
+				   struct scan_cache_entry *entry)
+{
+}
 #endif
 
 /**
@@ -1385,6 +1390,9 @@ QDF_STATUS __scm_handle_bcn_probe(struct scan_bcn_probe_event *bcn)
 			continue;
 		}
 
+		if (bcn->save_rnr_info)
+			scm_add_rnr_channel_db(psoc, scan_entry);
+
 		qdf_mem_free(scan_node);
 	}
 

+ 8 - 0
umac/scan/core/src/wlan_scan_cache_db.h

@@ -54,12 +54,14 @@ struct scan_dbs {
  * @frm_type: frame type
  * @rx_data: mgmt rx data
  * @psoc: psoc pointer
+ * @save_rnr_info: save the RNR entries into RNR db
  * @buf: rx frame
  */
 struct scan_bcn_probe_event {
 	uint32_t frm_type;
 	struct mgmt_rx_event_params *rx_data;
 	struct wlan_objmgr_psoc *psoc;
+	bool save_rnr_info;
 	qdf_nbuf_t buf;
 };
 
@@ -290,6 +292,12 @@ scm_filter_rnr_flag_pno(struct wlan_objmgr_vdev *vdev,
 			struct chan_list *chan_list);
 
 #else
+static inline struct channel_list_db *
+scm_get_rnr_channel_db(struct wlan_objmgr_psoc *psoc)
+{
+	return NULL;
+}
+
 static inline QDF_STATUS scm_channel_list_db_init(struct wlan_objmgr_psoc *psoc)
 {
 	return QDF_STATUS_SUCCESS;

+ 4 - 0
umac/scan/dispatcher/inc/wlan_scan_public_structs.h

@@ -423,7 +423,11 @@ struct non_inheritance_ie {
 	bool non_inh_ie_found;
 };
 
+#define TBTT_BSS_PARAM_MBSSID_BIT      0x04
 #define TBTT_BSS_PARAM_TRANS_BSSID_BIT 0x08
+#define TBTT_BSS_PARAM_MBSSID_TX_MASK  (TBTT_BSS_PARAM_MBSSID_BIT |\
+					TBTT_BSS_PARAM_TRANS_BSSID_BIT)
+#define TBTT_BSS_PARAM_MBSSID_NONTX_MASK TBTT_BSS_PARAM_MBSSID_BIT
 /**
  * struct rnr_bss_info - Reduced Neighbor Report BSS information
  * @neighbor_ap_tbtt_offset: Neighbor AP TBTT offset

+ 11 - 0
umac/scan/dispatcher/inc/wlan_scan_utils_api.h

@@ -1939,4 +1939,15 @@ util_scan_get_6g_oper_channel(uint8_t *he_op_ie)
 	return 0;
 }
 #endif
+/*
+ * util_is_bssid_non_tx() - Is the given BSSID a non-tx neighbor
+ * entry in the RNR db
+ * @psoc: psoc
+ * @bssid: bssid
+ * @freq: frequency corresponding to the bssid
+ *
+ * Return: Is bssid non tx
+ */
+bool util_is_bssid_non_tx(struct wlan_objmgr_psoc *psoc,
+			  struct qdf_mac_addr *bssid, qdf_freq_t freq);
 #endif

+ 11 - 1
umac/scan/dispatcher/src/wlan_scan_api.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -365,6 +365,16 @@ wlan_scan_process_bcn_probe_rx_sync(struct wlan_objmgr_psoc *psoc,
 
 	bcn->psoc = psoc;
 	bcn->buf = buf;
+
+	/*
+	 * Save the rnr entries from the frame into rnr db.
+	 * The RNR entry would have the partner links as well.
+	 * If the partner link is a non-tx profile, and if there
+	 * is no MBSSID info for that partner link, then look up
+	 * into the rnr db will help to identify if that partner
+	 * is a non-tx profile.
+	 */
+	bcn->save_rnr_info = true;
 	qdf_mem_copy(bcn->rx_data, rx_param, sizeof(*rx_param));
 
 	return __scm_handle_bcn_probe(bcn);

+ 2 - 0
umac/scan/dispatcher/src/wlan_scan_tgt_api.c

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -365,6 +366,7 @@ QDF_STATUS tgt_scan_bcn_probe_rx_callback(struct wlan_objmgr_psoc *psoc,
 
 	bcn->psoc = psoc;
 	bcn->buf = buf;
+	bcn->save_rnr_info = false;
 	qdf_mem_copy(bcn->rx_data, rx_param, sizeof(*rx_param));
 
 	msg.bodyptr = bcn;

+ 50 - 31
umac/scan/dispatcher/src/wlan_scan_utils_api.c

@@ -2240,10 +2240,6 @@ util_get_ml_bv_partner_link_info(struct wlan_objmgr_pdev *pdev,
 	uint8_t rnr_idx = 0;
 	struct rnr_bss_info *rnr = NULL;
 	qdf_size_t ml_ie_len = ml_ie[TAG_LEN_POS] + sizeof(struct ie_header);
-	uint16_t freq;
-	struct scan_cache_entry *tmp_entry;
-	struct qdf_mac_addr bcast_addr = QDF_MAC_ADDR_BCAST_INIT;
-	struct scan_mbssid_info *mbssid;
 
 	/* Update partner info  from RNR IE */
 	while ((rnr_idx < MAX_RNR_BSS) && (rnr_idx < scan_entry->rnr.count)) {
@@ -2251,38 +2247,15 @@ util_get_ml_bv_partner_link_info(struct wlan_objmgr_pdev *pdev,
 			break;
 		rnr = &scan_entry->rnr.bss_info[rnr_idx];
 		if (rnr->mld_info_valid && !rnr->mld_info.mld_id) {
-			mbssid = &scan_entry->mbssid_info;
-			freq =
-			     wlan_reg_chan_opclass_to_freq(rnr->channel_number,
-							   rnr->operating_class,
-							   true);
-
-			if ((!scan_entry->mbssid_info.profile_count) &&
-			    !(rnr->bss_params & TBTT_BSS_PARAM_TRANS_BSSID_BIT)) {
-				tmp_entry =
-				       scm_scan_get_scan_entry_by_mac_freq(pdev,
-							     &rnr->bssid, freq);
-				if (tmp_entry) {
-					qdf_mem_copy(mbssid,
-						     &tmp_entry->mbssid_info,
-						     sizeof(*mbssid));
-					util_scan_free_cache_entry(tmp_entry);
-				} else {
-					qdf_mem_copy(mbssid->non_trans_bssid,
-						     rnr->bssid.bytes,
-						     QDF_MAC_ADDR_SIZE);
-					qdf_mem_copy(mbssid->trans_bssid,
-						     bcast_addr.bytes,
-						     QDF_MAC_ADDR_SIZE);
-				}
-			}
-
 			link_info = &scan_entry->ml_info.link_info[link_idx];
 			qdf_mem_copy(&link_info->link_addr,
 				     &rnr->bssid, QDF_MAC_ADDR_SIZE);
 
 			link_info->link_id = rnr->mld_info.link_id;
-			link_info->freq = freq;
+			link_info->freq =
+				wlan_reg_chan_opclass_to_freq(rnr->channel_number,
+							      rnr->operating_class,
+							      true);
 
 			if (!link_info->freq)
 				scm_debug("freq 0 rnr channel %u op_class %u",
@@ -4125,3 +4098,49 @@ util_scan_entry_single_pmk(struct wlan_objmgr_psoc *psoc,
 	return false;
 }
 #endif
+
+bool util_is_bssid_non_tx(struct wlan_objmgr_psoc *psoc,
+			  struct qdf_mac_addr *bssid, qdf_freq_t freq)
+{
+	int i;
+	qdf_list_node_t *cur_node, *next_node;
+	struct meta_rnr_channel *channel;
+	struct scan_rnr_node *rnr_node;
+	struct channel_list_db *rnr_channel_db;
+	bool ret = false;
+
+	if (!psoc)
+		return false;
+
+	rnr_channel_db = scm_get_rnr_channel_db(psoc);
+	if (!rnr_channel_db)
+		return false;
+
+	for (i = 0; i < QDF_ARRAY_SIZE(rnr_channel_db->channel); i++) {
+		channel = &rnr_channel_db->channel[i];
+		if (channel->chan_freq != freq)
+			continue;
+
+		cur_node = NULL;
+		qdf_list_peek_front(&channel->rnr_list, &cur_node);
+
+		while (cur_node) {
+			next_node = NULL;
+			qdf_list_peek_next(&channel->rnr_list, cur_node,
+					   &next_node);
+			rnr_node = qdf_container_of(cur_node,
+						    struct scan_rnr_node,
+						    node);
+			if (qdf_is_macaddr_equal(&rnr_node->entry.bssid, bssid) &&
+			    (rnr_node->entry.bss_params &
+			     TBTT_BSS_PARAM_MBSSID_TX_MASK) ==
+			    TBTT_BSS_PARAM_MBSSID_NONTX_MASK) {
+				ret = true;
+				break;
+			}
+			cur_node = next_node;
+		}
+	}
+
+	return ret;
+}