Browse Source

qcacld-3.0: Fix for disconnect after roam abort

In roam invoke scenarios, if FW fails to roam
it will send roam invoke failure.
Until roam invoke failure is received FW is trying
to roam.
Currently if FW aborts roam, host will trigger
disconnect and rso stop is sent due to this FW
is unable to retry roaming.

Fix is to not trigger disconnect at roam abort
and wait until FW sends roam invoke failure.
To handle this store roam invoke params in rso cfg.

Change-Id: I32eeda70ef9f4d8a049fec53053f9e0c6eb36e51
CRs-Fixed: 3433320
Amruta Kulkarni 2 years ago
parent
commit
dea51e434d

+ 27 - 28
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_fw_sync.c

@@ -1217,17 +1217,16 @@ 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)
+static QDF_STATUS
+cm_disconnect_roam_invoke_fail(struct wlan_objmgr_vdev *vdev,
+			       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);
+	struct rso_config *rso_cfg;
 
 	psoc = wlan_vdev_get_psoc(vdev);
 	if (!psoc) {
@@ -1240,10 +1239,18 @@ cm_disconnect_roam_abort_fail(struct wlan_objmgr_vdev *vdev,
 	if (!mlme_obj)
 		return QDF_STATUS_E_NULL_VALUE;
 
+	rso_cfg = wlan_cm_get_rso_config(vdev);
+	if (!rso_cfg) {
+		mlme_err(CM_PREFIX_FMT "rso cfg not found",
+			 CM_PREFIX_REF(vdev_id, cm_id));
+		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,
+	mlme_debug(CM_PREFIX_FMT "disconnect on NUD %d, source %d forced roaming %d",
 		   CM_PREFIX_REF(vdev_id, cm_id),
-		   nud_disconnect, source, QDF_MAC_ADDR_REF(bssid));
+		   nud_disconnect, rso_cfg->roam_invoke_source,
+		   rso_cfg->is_forced_roaming);
 
 	/*
 	 * If reassoc MAC from user space is broadcast MAC as:
@@ -1253,16 +1260,22 @@ cm_disconnect_roam_abort_fail(struct wlan_objmgr_vdev *vdev,
 	 * highest score. It is requirement from customer which can avoid
 	 * ping-pong roaming.
 	 */
-	if (qdf_is_macaddr_broadcast(bssid))
+	if (qdf_is_macaddr_broadcast(&rso_cfg->roam_invoke_bssid)) {
+		qdf_zero_macaddr(&rso_cfg->roam_invoke_bssid);
 		return status;
+	}
 
-	if (source == CM_ROAMING_HOST ||
-	    (source == CM_ROAMING_NUD_FAILURE &&
-	    (nud_disconnect || qdf_is_macaddr_zero(bssid))) ||
-	     source == CM_ROAMING_LINK_REMOVAL)
+	if (rso_cfg->roam_invoke_source == CM_ROAMING_HOST ||
+	    (rso_cfg->roam_invoke_source == CM_ROAMING_NUD_FAILURE &&
+	    (nud_disconnect || rso_cfg->is_forced_roaming)) ||
+	     rso_cfg->roam_invoke_source == CM_ROAMING_LINK_REMOVAL) {
+		rso_cfg->roam_invoke_source = CM_SOURCE_INVALID;
+		if (rso_cfg->is_forced_roaming)
+			rso_cfg->is_forced_roaming = false;
 		status = mlo_disconnect(vdev, CM_ROAM_DISCONNECT,
 					REASON_USER_TRIGGERED_ROAM_FAILURE,
 					NULL);
+	}
 
 	return status;
 }
@@ -1272,11 +1285,8 @@ QDF_STATUS cm_fw_roam_invoke_fail(struct wlan_objmgr_psoc *psoc,
 {
 	QDF_STATUS status;
 	struct wlan_objmgr_vdev *vdev;
-	wlan_cm_id cm_id;
-	enum wlan_cm_source source;
+	wlan_cm_id cm_id = CM_ID_INVALID;
 	struct cnx_mgr *cm_ctx;
-	struct cm_roam_req *roam_req = NULL;
-	struct qdf_mac_addr bssid;
 
 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
 						    vdev_id,
@@ -1292,23 +1302,12 @@ QDF_STATUS cm_fw_roam_invoke_fail(struct wlan_objmgr_psoc *psoc,
 		goto error;
 	}
 
-	roam_req = cm_get_first_roam_command(vdev);
-	if (!roam_req) {
-		mlme_err("Failed to find roam req from list");
-		status = QDF_STATUS_E_FAILURE;
-		goto error;
-	}
-
-	cm_id = roam_req->cm_id;
-	source = roam_req->req.source;
-	bssid = roam_req->req.bssid;
-
 	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);
 
-	cm_disconnect_roam_abort_fail(vdev, source, &bssid, cm_id);
+	cm_disconnect_roam_invoke_fail(vdev, cm_id);
 error:
 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
 	return status;

+ 0 - 15
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_i.h

@@ -156,21 +156,6 @@ 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

+ 19 - 0
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c

@@ -5636,6 +5636,7 @@ QDF_STATUS cm_start_roam_invoke(struct wlan_objmgr_psoc *psoc,
 	struct qdf_mac_addr connected_bssid;
 	uint8_t vdev_id = vdev->vdev_objmgr.vdev_id;
 	bool roam_offload_enabled = cm_roam_offload_enabled(psoc);
+	struct rso_config *rso_cfg;
 
 	roam_control_bitmap = mlme_get_operations_bitmap(psoc, vdev_id);
 	if (roam_offload_enabled && (roam_control_bitmap ||
@@ -5655,6 +5656,10 @@ QDF_STATUS cm_start_roam_invoke(struct wlan_objmgr_psoc *psoc,
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	rso_cfg = wlan_cm_get_rso_config(vdev);
+	if (!rso_cfg)
+		return QDF_STATUS_E_NULL_VALUE;
+
 	/* Ignore BSSID and channel validation for FW host roam */
 	if (source == CM_ROAMING_FW)
 		goto send_evt;
@@ -5675,13 +5680,17 @@ QDF_STATUS cm_start_roam_invoke(struct wlan_objmgr_psoc *psoc,
 			qdf_mem_free(cm_req);
 			return QDF_STATUS_E_NOSUPPORT;
 		}
+
 		cm_req->roam_req.req.forced_roaming = true;
+		if (source == CM_ROAMING_HOST)
+			rso_cfg->is_forced_roaming = true;
 		source = CM_ROAMING_NUD_FAILURE;
 		goto send_evt;
 	}
 
 	if (qdf_is_macaddr_broadcast(bssid)) {
 		qdf_copy_macaddr(&cm_req->roam_req.req.bssid, bssid);
+		qdf_copy_macaddr(&rso_cfg->roam_invoke_bssid, bssid);
 		mlme_debug("Roam only if better candidate found else stick to current AP");
 		goto send_evt;
 	}
@@ -5705,6 +5714,16 @@ QDF_STATUS cm_start_roam_invoke(struct wlan_objmgr_psoc *psoc,
 send_evt:
 	cm_req->roam_req.req.source = source;
 
+	/* Storing source information in rso cfg as if FW aborts
+	 * roam host will delete roam req from queue.
+	 * In roam invoke failure, host will read rso cfg params
+	 * information and disconnect if needed.
+	 */
+	if (source == CM_ROAMING_HOST ||
+	    source == CM_ROAMING_NUD_FAILURE ||
+	    source == CM_ROAMING_LINK_REMOVAL)
+		rso_cfg->roam_invoke_source = source;
+
 	cm_req->roam_req.req.vdev_id = vdev_id;
 	/*
 	 * For LFR3 WLAN_CM_SM_EV_ROAM_REQ will be converted to

+ 0 - 2
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload_event.c

@@ -108,8 +108,6 @@ QDF_STATUS cm_abort_fw_roam(struct cnx_mgr *cm_ctx,
 	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;
 }
 

+ 6 - 0
components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_public_struct.h

@@ -566,6 +566,9 @@ struct sae_roam_auth_map {
  * @roam_sync_frame_ind: roam sync frame ind
  * @roam_band_bitmask: This allows the driver to roam within this band
  * @sae_roam_auth: structure containing roam peer mld and link address.
+ * @roam_invoke_source: roam invoke source
+ * @roam_invoke_bssid: mac address used for roam invoke
+ * @is_forced_roaming: bool value indicating if its forced roaming
  */
 struct rso_config {
 #ifdef WLAN_FEATURE_HOST_ROAM
@@ -615,6 +618,9 @@ struct rso_config {
 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
 	struct sae_roam_auth_map sae_roam_auth;
 #endif
+	enum wlan_cm_source roam_invoke_source;
+	struct qdf_mac_addr roam_invoke_bssid;
+	bool is_forced_roaming;
 };
 
 /**