Bladeren bron

qcacld-3.0: Correct logic for roam fails in NUD case

If roaming is triggered by source CM_ROAMING_NUD_FAILURE,
then per the INI gEnableNUDTracking to check whether
disconnect current connection or not.
gEnableNUDTracking=2, keeping the connection
gEnableNUDTracking=3, disconnect the connection

Change-Id: I0f321dcf5f3fc1bf7d0c93fa0d70bf4770ccaf35
CRs-Fixed: 3412213
Paul Zhang 2 jaren geleden
bovenliggende
commit
afd194fb4e

+ 9 - 0
components/dp/dispatcher/inc/wlan_dp_ucfg_api.h

@@ -44,12 +44,21 @@
 #ifdef WLAN_NUD_TRACKING
 bool
 ucfg_dp_is_roam_after_nud_enabled(struct wlan_objmgr_psoc *psoc);
+
+bool
+ucfg_dp_is_disconect_after_roam_fail(struct wlan_objmgr_psoc *psoc);
 #else
 static inline bool
 ucfg_dp_is_roam_after_nud_enabled(struct wlan_objmgr_psoc *psoc)
 {
 	return false;
 }
+
+static inline bool
+ucfg_dp_is_disconect_after_roam_fail(struct wlan_objmgr_psoc *psoc)
+{
+	return false;
+}
 #endif
 
 /**

+ 12 - 0
components/dp/dispatcher/src/wlan_dp_ucfg_api.c

@@ -1351,6 +1351,18 @@ ucfg_dp_is_roam_after_nud_enabled(struct wlan_objmgr_psoc *psoc)
 
 	return false;
 }
+
+bool
+ucfg_dp_is_disconect_after_roam_fail(struct wlan_objmgr_psoc *psoc)
+{
+	struct wlan_dp_psoc_context *dp_ctx = dp_psoc_get_priv(psoc);
+	struct wlan_dp_psoc_cfg *dp_cfg = &dp_ctx->dp_cfg;
+
+	if (dp_cfg->enable_nud_tracking == DP_DISCONNECT_AFTER_ROAM_FAIL)
+		return true;
+
+	return false;
+}
 #endif
 
 int ucfg_dp_bbm_context_init(struct wlan_objmgr_psoc *psoc)

+ 3 - 0
components/mlme/dispatcher/inc/wlan_mlme_public_struct.h

@@ -1969,6 +1969,8 @@ struct fw_scan_channels {
  * are already scanned as part of partial scan.
  * @roam_full_scan_6ghz_on_disc: Include the 6 GHz channels in roam full scan
  * only on prior discovery of any 6 GHz support in the environment.
+ * @disconnect_on_nud_roam_invoke_fail: indicate whether disconnect ap when
+ * roam invoke fail on nud.
  */
 struct wlan_mlme_lfr_cfg {
 	bool mawc_roam_enabled;
@@ -2096,6 +2098,7 @@ struct wlan_mlme_lfr_cfg {
 	uint16_t roam_ho_delay_config;
 	uint8_t exclude_rm_partial_scan_freq;
 	uint8_t roam_full_scan_6ghz_on_disc;
+	bool disconnect_on_nud_roam_invoke_fail;
 };
 
 /**

+ 50 - 18
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_fw_sync.c

@@ -1190,6 +1190,55 @@ end:
 	return status;
 }
 
+QDF_STATUS
+cm_disconnect_roam_abort_fail(struct wlan_objmgr_vdev *vdev,
+			      enum wlan_cm_source source,
+			      struct qdf_mac_addr *bssid,
+			      wlan_cm_id cm_id)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	struct wlan_mlme_psoc_ext_obj *mlme_obj;
+	bool nud_disconnect;
+	struct wlan_objmgr_psoc *psoc;
+	uint8_t vdev_id = wlan_vdev_get_id(vdev);
+
+	psoc = wlan_vdev_get_psoc(vdev);
+	if (!psoc) {
+		mlme_err(CM_PREFIX_FMT "psoc not found",
+			 CM_PREFIX_REF(vdev_id, cm_id));
+		return QDF_STATUS_E_INVAL;
+	}
+
+	mlme_obj = mlme_get_psoc_ext_obj(psoc);
+	if (!mlme_obj)
+		return QDF_STATUS_E_NULL_VALUE;
+
+	nud_disconnect = mlme_obj->cfg.lfr.disconnect_on_nud_roam_invoke_fail;
+	mlme_debug(CM_PREFIX_FMT "disconnect on NUD %d, source %d bssid " QDF_MAC_ADDR_FMT,
+		   CM_PREFIX_REF(vdev_id, cm_id),
+		   nud_disconnect, source, QDF_MAC_ADDR_REF(bssid));
+
+	/*
+	 * If reassoc MAC from user space is broadcast MAC as:
+	 * "wpa_cli DRIVER FASTREASSOC ff:ff:ff:ff:ff:ff 0",
+	 * user space invoked roaming candidate selection will base on firmware
+	 * score algorithm, current connection will be kept if current AP has
+	 * highest score. It is requirement from customer which can avoid
+	 * ping-pong roaming.
+	 */
+	if (qdf_is_macaddr_broadcast(bssid))
+		return status;
+
+	if (source == CM_ROAMING_HOST ||
+	    (source == CM_ROAMING_NUD_FAILURE && nud_disconnect) ||
+	     source == CM_ROAMING_LINK_REMOVAL)
+		status = mlo_disconnect(vdev, CM_ROAM_DISCONNECT,
+					REASON_USER_TRIGGERED_ROAM_FAILURE,
+					NULL);
+
+	return status;
+}
+
 QDF_STATUS cm_fw_roam_invoke_fail(struct wlan_objmgr_psoc *psoc,
 				  uint8_t vdev_id)
 {
@@ -1204,7 +1253,6 @@ QDF_STATUS cm_fw_roam_invoke_fail(struct wlan_objmgr_psoc *psoc,
 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
 						    vdev_id,
 						    WLAN_MLME_SB_ID);
-
 	if (!vdev) {
 		mlme_err("vdev object is NULL");
 		return QDF_STATUS_E_NULL_VALUE;
@@ -1229,26 +1277,10 @@ QDF_STATUS cm_fw_roam_invoke_fail(struct wlan_objmgr_psoc *psoc,
 
 	status = cm_sm_deliver_event(vdev, WLAN_CM_SM_EV_ROAM_INVOKE_FAIL,
 				     sizeof(wlan_cm_id), &cm_id);
-
 	if (QDF_IS_STATUS_ERROR(status))
 		cm_remove_cmd(cm_ctx, &cm_id);
-	/*
-	 * If reassoc MAC from user space is broadcast MAC as:
-	 * "wpa_cli DRIVER FASTREASSOC ff:ff:ff:ff:ff:ff 0",
-	 * user space invoked roaming candidate selection will base on firmware
-	 * score algorithm, current connection will be kept if current AP has
-	 * highest score. It is requirement from customer which can avoid
-	 * ping-pong roaming.
-	 */
-	if (qdf_is_macaddr_broadcast(&bssid))
-		mlme_debug("Keep current connection");
-	else if (source == CM_ROAMING_HOST ||
-		 source == CM_ROAMING_NUD_FAILURE ||
-		 source == CM_ROAMING_LINK_REMOVAL)
-		status = mlo_disconnect(vdev, CM_ROAM_DISCONNECT,
-					REASON_USER_TRIGGERED_ROAM_FAILURE,
-					NULL);
 
+	cm_disconnect_roam_abort_fail(vdev, source, &bssid, cm_id);
 error:
 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
 	return status;

+ 16 - 1
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_i.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 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
@@ -156,6 +156,21 @@ cm_fw_roam_sync_propagation(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
 void cm_fw_ho_fail_req(struct wlan_objmgr_psoc *psoc,
 		       uint8_t vdev_id, struct qdf_mac_addr bssid);
 
+/**
+ * cm_disconnect_roam_abort_fail() - disconnect when roam abort or fail
+ * @vdev: vdev object
+ * @source: the source of trigger roaming
+ * @bssid: bssid pointer
+ * @cm_id: CM command id
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+cm_disconnect_roam_abort_fail(struct wlan_objmgr_vdev *vdev,
+			      enum wlan_cm_source source,
+			      struct qdf_mac_addr *bssid,
+			      wlan_cm_id cm_id);
+
 /**
  * cm_fw_roam_invoke_fail() - Post roam invoke fail to CM SM
  * @psoc: psoc pointer

+ 11 - 1
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload_event.c

@@ -91,15 +91,25 @@ QDF_STATUS cm_abort_fw_roam(struct cnx_mgr *cm_ctx,
 			    wlan_cm_id cm_id)
 {
 	QDF_STATUS status;
+	enum wlan_cm_source source = CM_SOURCE_INVALID;
+	struct cm_roam_req *roam_req;
+	struct qdf_mac_addr bssid = QDF_MAC_ADDR_ZERO_INIT;
+
+	roam_req = cm_get_first_roam_command(cm_ctx->vdev);
+	if (roam_req) {
+		source = roam_req->req.source;
+		bssid = roam_req->req.bssid;
+	}
 
 	mlme_cm_osif_roam_abort_ind(cm_ctx->vdev);
 	status = cm_sm_deliver_event(cm_ctx->vdev,
 				     WLAN_CM_SM_EV_ROAM_ABORT,
 				     sizeof(wlan_cm_id), &cm_id);
-
 	if (QDF_IS_STATUS_ERROR(status))
 		cm_remove_cmd(cm_ctx, &cm_id);
 
+	cm_disconnect_roam_abort_fail(cm_ctx->vdev, source, &bssid, cm_id);
+
 	return status;
 }
 

+ 5 - 0
core/hdd/src/wlan_hdd_cfg.c

@@ -51,6 +51,7 @@
 #include "hdd_dp_cfg.h"
 #include <wma_api.h>
 #include "wlan_hdd_object_manager.h"
+#include "wlan_dp_ucfg_api.h"
 
 #ifndef WLAN_MAC_ADDR_UPDATE_DISABLE
 /**
@@ -927,6 +928,7 @@ QDF_STATUS hdd_set_sme_config(struct hdd_context *hdd_ctx)
 	mac_handle_t mac_handle = hdd_ctx->mac_handle;
 	bool roam_scan_enabled;
 	bool enable_dfs_scan = true;
+	bool disconnect_nud;
 	uint32_t channel_bonding_mode;
 
 #ifdef FEATURE_WLAN_ESE
@@ -1008,6 +1010,9 @@ QDF_STATUS hdd_set_sme_config(struct hdd_context *hdd_ctx)
 		STA_ROAM_POLICY_DFS_ENABLED;
 	mlme_obj->cfg.lfr.rso_user_config.policy_params.skip_unsafe_channels = 0;
 
+	disconnect_nud = ucfg_dp_is_disconect_after_roam_fail(hdd_ctx->psoc);
+	mlme_obj->cfg.lfr.disconnect_on_nud_roam_invoke_fail = disconnect_nud;
+
 	status = hdd_set_sme_cfgs_related_to_mlme(hdd_ctx, sme_config);
 	if (!QDF_IS_STATUS_SUCCESS(status))
 		hdd_err("hdd_set_sme_cfgs_related_to_mlme() fail: %d", status);