Forráskód Böngészése

qcacld-3.0: Don't set link_agnostic to true if dest addr is not AP addr

Currently, mlo_link_agnostic is set to true without validating
destination address which means FW is free to choose
transmission link L0 or L1 due to which GAS frame TX is failing.

Fix is to set mlo_link_agnostic to false when dest address is not
AP address, so that FW can choose freq as per channel which is
sent as part of mgmt frame.

Change-Id: Icacc4ce06b0eda341342ac1cdcf347de74e59e39
CRs-Fixed: 3666152
(cherry picked from commit d3cbd7154a31479cb79230643a0a8818b41d2a67)
Sheenam Monga 1 éve
szülő
commit
4bce8122a0

+ 17 - 0
components/mlme/core/inc/wlan_mlme_main.h

@@ -1653,6 +1653,16 @@ wlan_set_sap_user_config_freq(struct wlan_objmgr_vdev *vdev,
  */
 void wlan_clear_mlo_sta_link_removed_flag(struct wlan_objmgr_vdev *vdev);
 
+/**
+ * wlan_get_mlo_link_agnostic_flag() - Update mlo link agnostic flag
+ *
+ * @vdev: pointer to vdev
+ * @dest_addr: destination address
+ *
+ * Return: true/false
+ */
+bool wlan_get_mlo_link_agnostic_flag(struct wlan_objmgr_vdev *vdev,
+				     uint8_t *dest_addr);
 /**
  * wlan_set_vdev_link_removed_flag_by_vdev_id() - Set link removal flag
  * on vdev
@@ -1692,6 +1702,13 @@ wlan_clear_mlo_sta_link_removed_flag(struct wlan_objmgr_vdev *vdev)
 {
 }
 
+static inline
+bool wlan_get_mlo_link_agnostic_flag(struct wlan_objmgr_vdev *vdev,
+				     uint8_t *dest_addr)
+{
+	return false;
+}
+
 static inline QDF_STATUS
 wlan_set_vdev_link_removed_flag_by_vdev_id(struct wlan_objmgr_psoc *psoc,
 					   uint8_t vdev_id, bool removed)

+ 29 - 0
components/mlme/core/src/wlan_mlme_main.c

@@ -2694,6 +2694,35 @@ void wlan_clear_mlo_sta_link_removed_flag(struct wlan_objmgr_vdev *vdev)
 				     &link_info[i].link_status_flags);
 }
 
+bool wlan_get_mlo_link_agnostic_flag(struct wlan_objmgr_vdev *vdev,
+				     uint8_t *dest_addr)
+{
+	struct wlan_objmgr_peer *bss_peer = NULL;
+	bool mlo_link_agnostic = false;
+	uint8_t *peer_mld_addr = NULL;
+
+	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
+		return mlo_link_agnostic;
+
+	bss_peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_MLME_OBJMGR_ID);
+	if (bss_peer) {
+		peer_mld_addr = wlan_peer_mlme_get_mldaddr(bss_peer);
+		if (!qdf_mem_cmp(bss_peer->macaddr, dest_addr,
+				 QDF_MAC_ADDR_SIZE) ||
+		    (peer_mld_addr && !qdf_mem_cmp(peer_mld_addr, dest_addr,
+						   QDF_MAC_ADDR_SIZE))) {
+			mlme_legacy_debug("dest address" QDF_MAC_ADDR_FMT "bss peer address"
+					  QDF_MAC_ADDR_FMT "mld addr" QDF_MAC_ADDR_FMT,
+					  QDF_MAC_ADDR_REF(dest_addr),
+					  QDF_MAC_ADDR_REF(bss_peer->macaddr),
+					  QDF_MAC_ADDR_REF(peer_mld_addr));
+			mlo_link_agnostic = true;
+		}
+		wlan_objmgr_peer_release_ref(bss_peer, WLAN_MLME_OBJMGR_ID);
+	}
+	return mlo_link_agnostic;
+}
+
 bool wlan_drop_mgmt_frame_on_link_removal(struct wlan_objmgr_vdev *vdev)
 {
 	if (!vdev || !mlo_is_mld_sta(vdev))

+ 6 - 3
components/p2p/core/src/wlan_p2p_off_chan_tx.c

@@ -1185,13 +1185,14 @@ static QDF_STATUS p2p_mgmt_tx(struct tx_action_context *tx_ctx,
 	mgmt_tx_download_comp_cb tx_comp_cb;
 	mgmt_ota_comp_cb tx_ota_comp_cb;
 	struct wlan_frame_hdr *wh;
-	struct wlan_objmgr_peer *peer;
+	struct wlan_objmgr_peer *peer = NULL;
 	struct wmi_mgmt_params mgmt_param = { 0 };
 	struct wlan_objmgr_psoc *psoc;
 	void *mac_addr;
 	uint8_t pdev_id;
 	struct wlan_objmgr_vdev *vdev;
 	enum QDF_OPMODE opmode;
+	bool mlo_link_agnostic;
 
 	psoc = tx_ctx->p2p_soc_obj->soc;
 	mgmt_param.tx_frame = packet;
@@ -1217,6 +1218,8 @@ static QDF_STATUS p2p_mgmt_tx(struct tx_action_context *tx_ctx,
 		return QDF_STATUS_E_INVAL;
 	}
 
+	mlo_link_agnostic = wlan_get_mlo_link_agnostic_flag(vdev, mac_addr);
+
 	peer = wlan_objmgr_get_peer(psoc, pdev_id,  mac_addr, WLAN_P2P_ID);
 	if (!peer) {
 		mac_addr = wh->i_addr2;
@@ -1265,10 +1268,10 @@ static QDF_STATUS p2p_mgmt_tx(struct tx_action_context *tx_ctx,
 	tx_ctx->nbuf = packet;
 
 	if (mlo_is_mld_sta(vdev) && tx_ctx->frame_info.type == P2P_FRAME_MGMT &&
-	    tx_ctx->frame_info.sub_type == P2P_MGMT_ACTION) {
+	    tx_ctx->frame_info.sub_type == P2P_MGMT_ACTION &&
+	    mlo_link_agnostic) {
 		mgmt_param.mlo_link_agnostic = true;
 	}
-
 	status = wlan_mgmt_txrx_mgmt_frame_tx(peer, tx_ctx->p2p_soc_obj,
 			packet, tx_comp_cb, tx_ota_comp_cb,
 			WLAN_UMAC_COMP_P2P, &mgmt_param);

+ 21 - 2
core/mac/src/pe/lim/lim_send_management_frames.c

@@ -7496,8 +7496,10 @@ static QDF_STATUS lim_update_mld_to_link_address(struct mac_context *mac_ctx,
 	struct qdf_mac_addr *self_link_addr;
 	struct tLimPreAuthNode *pre_auth_node;
 	struct qdf_mac_addr peer_link_addr;
+	struct wlan_objmgr_peer *bss_peer = NULL;
 	struct qdf_mac_addr *peer_roaming_link_addr;
 	enum QDF_OPMODE opmode;
+	uint8_t *peer_mld_addr = NULL;
 	QDF_STATUS status;
 
 	if (!wlan_cm_is_sae_auth_addr_conversion_required(vdev))
@@ -7539,16 +7541,33 @@ static QDF_STATUS lim_update_mld_to_link_address(struct mac_context *mac_ctx,
 							    &peer_link_addr);
 			if (QDF_IS_STATUS_ERROR(status))
 				return status;
+			bss_peer = wlan_objmgr_vdev_try_get_bsspeer(
+						vdev, WLAN_MLME_OBJMGR_ID);
+			if (bss_peer) {
+				peer_mld_addr =
+					wlan_peer_mlme_get_mldaddr(bss_peer);
+				wlan_objmgr_peer_release_ref(
+						bss_peer, WLAN_MLME_OBJMGR_ID);
+			}
 		} else {
 			peer_roaming_link_addr =
 				wlan_cm_roaming_get_peer_link_addr(vdev);
 			if (!peer_roaming_link_addr)
 				return QDF_STATUS_E_FAILURE;
 			peer_link_addr = *peer_roaming_link_addr;
+			peer_mld_addr = (uint8_t *)
+					wlan_cm_roaming_get_peer_mld_addr(vdev);
 		}
+		if (!peer_mld_addr)
+			return QDF_STATUS_SUCCESS;
+
+		pe_debug("dest address"QDF_MAC_ADDR_FMT"mld addr"QDF_MAC_ADDR_FMT,
+			 QDF_MAC_ADDR_REF(mac_hdr->da),
+			 QDF_MAC_ADDR_REF(peer_mld_addr));
+		if (!qdf_mem_cmp(mac_hdr->da, peer_mld_addr, QDF_MAC_ADDR_SIZE))
+			qdf_mem_copy(mac_hdr->da, peer_link_addr.bytes,
+				     QDF_MAC_ADDR_SIZE);
 
-		qdf_mem_copy(mac_hdr->da, peer_link_addr.bytes,
-			     QDF_MAC_ADDR_SIZE);
 		qdf_mem_copy(mac_hdr->bssId, peer_link_addr.bytes,
 			     QDF_MAC_ADDR_SIZE);
 		break;

+ 8 - 2
core/wma/src/wma_data.c

@@ -2333,6 +2333,7 @@ QDF_STATUS wma_tx_packet(void *wma_context, void *tx_frame, uint16_t frmLen,
 	uint8_t *mld_addr = NULL;
 	bool is_5g = false;
 	uint8_t pdev_id;
+	bool mlo_link_agnostic;
 
 	if (wma_validate_handle(wma_handle)) {
 		cds_packet_free((void *)tx_frame);
@@ -2713,6 +2714,11 @@ QDF_STATUS wma_tx_packet(void *wma_context, void *tx_frame, uint16_t frmLen,
 	if (wlan_reg_is_5ghz_ch_freq(wma_handle->interfaces[vdev_id].ch_freq))
 		is_5g = true;
 
+	wh = (struct ieee80211_frame *)(qdf_nbuf_data(tx_frame));
+
+	mlo_link_agnostic =
+		wlan_get_mlo_link_agnostic_flag(iface->vdev, wh->i_addr1);
+
 	mgmt_param.tx_frame = tx_frame;
 	mgmt_param.frm_len = frmLen;
 	mgmt_param.vdev_id = vdev_id;
@@ -2729,7 +2735,8 @@ QDF_STATUS wma_tx_packet(void *wma_context, void *tx_frame, uint16_t frmLen,
 	    pFc->subType != SIR_MAC_MGMT_PROBE_REQ &&
 	    pFc->subType != SIR_MAC_MGMT_AUTH &&
 	    action != (ACTION_CATEGORY_PUBLIC << 8 | TDLS_DISCOVERY_RESPONSE) &&
-	    action != (ACTION_CATEGORY_BACK << 8 | ADDBA_RESPONSE))
+	    action != (ACTION_CATEGORY_BACK << 8 | ADDBA_RESPONSE) &&
+	    mlo_link_agnostic)
 		mgmt_param.mlo_link_agnostic = true;
 
 	if (tx_flag & HAL_USE_INCORRECT_KEY_PMF)
@@ -2760,7 +2767,6 @@ QDF_STATUS wma_tx_packet(void *wma_context, void *tx_frame, uint16_t frmLen,
 	}
 
 	pdev_id = wlan_objmgr_pdev_get_pdev_id(wma_handle->pdev);
-	wh = (struct ieee80211_frame *)(qdf_nbuf_data(tx_frame));
 	mac_addr = wh->i_addr1;
 	peer = wlan_objmgr_get_peer(psoc, pdev_id, mac_addr, WLAN_MGMT_NB_ID);
 	if (!peer) {