Эх сурвалжийг харах

qcacmn: Add self reassoc and Hw mode change logic for LFR2

Add self reassoc and Hw mode change logic for LFR2.

Change-Id: I366bd6ba3650343a2f829359a2a42695f089d121
CRs-Fixed: 2941760
Huashan Qu 4 жил өмнө
parent
commit
36af7eda02

+ 168 - 9
umac/mlme/connection_mgr/core/src/wlan_cm_host_roam.c

@@ -23,6 +23,9 @@
 #include <wlan_serialization_api.h>
 #include <wlan_utility.h>
 #include <wlan_cm_api.h>
+#ifdef WLAN_POLICY_MGR_ENABLE
+#include "wlan_policy_mgr_api.h"
+#endif
 
 static void
 cm_fill_roam_fail_resp_from_cm_id(struct cnx_mgr *cm_ctx,
@@ -222,6 +225,27 @@ static QDF_STATUS cm_roam_get_candidates(struct wlan_objmgr_pdev *pdev,
 static QDF_STATUS cm_host_roam_start(struct cnx_mgr *cm_ctx,
 				     struct cm_req *cm_req)
 {
+	struct wlan_cm_roam_req *req;
+	struct qdf_mac_addr connected_bssid;
+
+	req = &cm_req->roam_req.req;
+
+	wlan_vdev_get_bss_peer_mac(cm_ctx->vdev, &connected_bssid);
+	if (qdf_is_macaddr_equal(&req->bssid, &connected_bssid))
+		req->self_reassoc = true;
+
+	/* if self reassoc continue with reassoc and skip preauth */
+	if (req->self_reassoc)
+		return cm_sm_deliver_event_sync(cm_ctx,
+						WLAN_CM_SM_EV_START_REASSOC,
+						sizeof(cm_req->roam_req),
+						&cm_req->roam_req);
+	/*
+	 * if not self reassoc reset cur candidate to perform preauth with
+	 * all candidate.
+	 */
+	cm_req->roam_req.cur_candidate = NULL;
+
 	/* start preauth process */
 
 	return QDF_STATUS_SUCCESS;
@@ -302,6 +326,11 @@ QDF_STATUS cm_reassoc_active(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
 		return QDF_STATUS_E_INVAL;
 
 	cm_ctx->active_cm_id = *cm_id;
+
+	/* For self reassoc no need to disconnect or create peer */
+	if (cm_req->roam_req.req.self_reassoc)
+		return cm_resume_reassoc_after_peer_create(cm_ctx, cm_id);
+
 	qdf_mem_zero(&req, sizeof(req));
 	req.cm_id = *cm_id;
 	req.req.vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
@@ -367,13 +396,16 @@ cm_resume_reassoc_after_peer_create(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
 
 	req->vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
 	req->cm_id = *cm_id;
+	req->self_reassoc = cm_req->roam_req.req.self_reassoc;
 	req->bss = cm_req->roam_req.cur_candidate;
 
 	status = mlme_cm_reassoc_req(cm_ctx->vdev, req);
 	if (QDF_IS_STATUS_ERROR(status)) {
 		mlme_err(CM_PREFIX_FMT "Reassoc request failed",
 			 CM_PREFIX_REF(req->vdev_id, req->cm_id));
-		mlme_cm_bss_peer_delete_req(cm_ctx->vdev);
+		/* Delete peer only if not self reassoc */
+		if (!cm_req->roam_req.req.self_reassoc)
+			mlme_cm_bss_peer_delete_req(cm_ctx->vdev);
 		status = cm_send_reassoc_start_fail(cm_ctx, *cm_id,
 						    CM_JOIN_FAILED, true);
 	}
@@ -626,21 +658,148 @@ static QDF_STATUS cm_ser_reassoc_req(struct cnx_mgr *cm_ctx,
 	return QDF_STATUS_SUCCESS;
 }
 
+#ifdef WLAN_POLICY_MGR_ENABLE
+QDF_STATUS
+cm_handle_reassoc_hw_mode_change(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id,
+				 enum wlan_cm_sm_evt event)
+{
+	struct cm_req *cm_req;
+	enum wlan_cm_connect_fail_reason reason = CM_GENERIC_FAILURE;
+	struct wlan_objmgr_pdev *pdev;
+	QDF_STATUS status;
+
+	if (!cm_id)
+		return QDF_STATUS_E_FAILURE;
+
+	cm_req = cm_get_req_by_cm_id(cm_ctx, *cm_id);
+	if (!cm_req)
+		return QDF_STATUS_E_INVAL;
+
+	pdev = wlan_vdev_get_pdev(cm_ctx->vdev);
+	if (!pdev) {
+		mlme_err(CM_PREFIX_FMT "Failed to find pdev",
+			 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev),
+				       cm_req->cm_id));
+		goto send_failure;
+	}
+
+	if (event == WLAN_CM_SM_EV_HW_MODE_SUCCESS) {
+		status = cm_ser_reassoc_req(cm_ctx, &cm_req->roam_req);
+		if (QDF_IS_STATUS_ERROR(status)) {
+			reason = CM_SER_FAILURE;
+			goto send_failure;
+		}
+		return status;
+	}
+
+	/* Set reason HW mode fail for event WLAN_CM_SM_EV_HW_MODE_FAILURE */
+	reason = CM_HW_MODE_FAILURE;
+
+send_failure:
+	return cm_send_reassoc_start_fail(cm_ctx, cm_req->cm_id, reason, true);
+}
+
+void cm_reassoc_hw_mode_change_resp(struct wlan_objmgr_pdev *pdev,
+				    uint8_t vdev_id, wlan_cm_id cm_id,
+				    QDF_STATUS status)
+{
+	struct wlan_objmgr_vdev *vdev;
+	QDF_STATUS qdf_status;
+	enum wlan_cm_sm_evt event = WLAN_CM_SM_EV_HW_MODE_SUCCESS;
+	struct cnx_mgr *cm_ctx;
+
+	mlme_debug(CM_PREFIX_FMT "Continue Reassoc after HW mode change, status %d",
+		   CM_PREFIX_REF(vdev_id, cm_id), status);
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
+						    WLAN_MLME_CM_ID);
+	if (!vdev)
+		return;
+
+	cm_ctx = cm_get_cm_ctx(vdev);
+	if (!cm_ctx) {
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
+		return;
+	}
+
+	if (QDF_IS_STATUS_ERROR(status))
+		event = WLAN_CM_SM_EV_HW_MODE_FAILURE;
+	qdf_status = cm_sm_deliver_event(vdev, event, sizeof(wlan_cm_id),
+					 &cm_id);
+
+	/*
+	 * Handle failure if posting fails, i.e. the SM state has
+	 * changed or head cm_id doesn't match the active cm_id.
+	 * hw mode change resp should be handled in REASSOC state. If
+	 * new command has been received reassoc should be
+	 * aborted from here with reassoc req cleanup.
+	 */
+	if (QDF_IS_STATUS_ERROR(status))
+		cm_reassoc_handle_event_post_fail(cm_ctx, cm_id);
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
+}
+
+static QDF_STATUS
+cm_check_for_reassoc_hw_mode_change(struct cnx_mgr *cm_ctx,
+				    struct cm_roam_req *cm_req)
+{
+	qdf_freq_t candidate_freq;
+	struct wlan_objmgr_psoc *psoc;
+
+	psoc = wlan_vdev_get_psoc(cm_ctx->vdev);
+	if (!psoc)
+		return QDF_STATUS_E_INVAL;
+
+	if (!cm_req->cur_candidate)
+		return QDF_STATUS_E_EMPTY;
+
+	/* HW mode change not required for self reassoc */
+	if (cm_req->req.self_reassoc)
+		return QDF_STATUS_E_ALREADY;
+
+	candidate_freq = cm_req->cur_candidate->entry->channel.chan_freq;
+	return policy_mgr_handle_conc_multiport(psoc, cm_req->req.vdev_id,
+					candidate_freq,
+					POLICY_MGR_UPDATE_REASON_LFR2_ROAM,
+					cm_req->cm_id);
+}
+#else
+static inline QDF_STATUS
+cm_check_for_reassoc_hw_mode_change(struct cnx_mgr *cm_ctx,
+				    struct cm_roam_req *cm_req)
+{
+	return QDF_STATUS_E_ALREADY;
+}
+#endif
+
 QDF_STATUS cm_reassoc_start(struct cnx_mgr *cm_ctx,
 			    struct cm_roam_req *cm_req)
 {
-	QDF_STATUS status;
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
 	uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
+	enum wlan_cm_connect_fail_reason reason = CM_GENERIC_FAILURE;
 
-	status = cm_ser_reassoc_req(cm_ctx, cm_req);
-	if (QDF_IS_STATUS_ERROR(status)) {
-		mlme_err(CM_PREFIX_FMT "Serialization of reassoc failed",
-			 CM_PREFIX_REF(vdev_id, cm_req->cm_id));
-		return cm_send_reassoc_start_fail(cm_ctx, cm_req->cm_id,
-						  CM_SER_FAILURE, true);
+	status = cm_check_for_reassoc_hw_mode_change(cm_ctx, cm_req);
+	if (QDF_IS_STATUS_ERROR(status) && status != QDF_STATUS_E_ALREADY) {
+		reason = CM_HW_MODE_FAILURE;
+		mlme_err(CM_PREFIX_FMT "Failed to set HW mode change status %d",
+			 CM_PREFIX_REF(vdev_id, cm_req->cm_id), status);
+		goto err;
+	} else if (QDF_IS_STATUS_SUCCESS(status)) {
+		mlme_debug(CM_PREFIX_FMT "Reassoc will continue after HW mode change",
+			   CM_PREFIX_REF(vdev_id, cm_req->cm_id));
+		return QDF_STATUS_SUCCESS;
 	}
 
-	return status;
+	status = cm_ser_reassoc_req(cm_ctx, cm_req);
+	if (QDF_IS_STATUS_SUCCESS(status))
+		return status;
+
+	reason = CM_SER_FAILURE;
+	mlme_err(CM_PREFIX_FMT "Serialization of reassoc failed",
+		 CM_PREFIX_REF(vdev_id, cm_req->cm_id));
+err:
+	return cm_send_reassoc_start_fail(cm_ctx, cm_req->cm_id, reason, true);
 }
 
 QDF_STATUS cm_reassoc_rsp(struct wlan_objmgr_vdev *vdev,

+ 44 - 0
umac/mlme/connection_mgr/core/src/wlan_cm_roam.h

@@ -24,6 +24,7 @@
 #define __WLAN_CM_ROAM_H__
 
 #include "wlan_cm_main.h"
+#include "wlan_cm_sm.h"
 
 #ifdef WLAN_FEATURE_HOST_ROAM
 /**
@@ -106,6 +107,41 @@ QDF_STATUS cm_host_roam_start_req(struct cnx_mgr *cm_ctx,
  */
 QDF_STATUS cm_reassoc_start(struct cnx_mgr *cm_ctx, struct cm_roam_req *req);
 
+#ifdef WLAN_POLICY_MGR_ENABLE
+/**
+ * cm_reassoc_hw_mode_change_resp() - HW mode change response
+ * @pdev: pdev pointer
+ * @vdev_id: vdev id
+ * @cm_id: reassoc ID which gave the hw mode change request
+ * @status: status of the HW mode change.
+ *
+ * Return: void
+ */
+void cm_reassoc_hw_mode_change_resp(struct wlan_objmgr_pdev *pdev,
+				    uint8_t vdev_id,
+				    wlan_cm_id cm_id, QDF_STATUS status);
+
+/**
+ * cm_handle_reassoc_hw_mode_change() - SM handling of reassoc hw mode change
+ * resp
+ * @cm_ctx: connection manager context
+ * @cm_id: Connection mgr ID assigned to this connect request.
+ * @event: HW mode success or failure event
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+cm_handle_reassoc_hw_mode_change(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id,
+				 enum wlan_cm_sm_evt event);
+#else
+static inline QDF_STATUS
+cm_handle_reassoc_hw_mode_change(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id,
+				 enum wlan_cm_sm_evt event)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
 /**
  * cm_reassoc_active() - This API would be called after the reassoc
  * request gets activated in serialization.
@@ -167,6 +203,14 @@ cm_send_reassoc_start_fail(struct cnx_mgr *cm_ctx,
 			   bool sync);
 
 #else
+
+#ifdef WLAN_POLICY_MGR_ENABLE
+static inline
+void cm_reassoc_hw_mode_change_resp(struct wlan_objmgr_pdev *pdev,
+				    uint8_t vdev_id,
+				    wlan_cm_id cm_id, QDF_STATUS status) {}
+#endif
+
 static inline QDF_STATUS cm_reassoc_complete(struct cnx_mgr *cm_ctx,
 					     struct wlan_cm_connect_resp *resp)
 {

+ 14 - 6
umac/mlme/connection_mgr/core/src/wlan_cm_roam_sm.c

@@ -169,6 +169,8 @@ void cm_subst_preauth_entry(void *ctx)
 		QDF_BUG(0);
 
 	cm_set_substate(cm_ctx, WLAN_CM_SS_PREAUTH);
+	/* set preauth to true when we enter preauth state */
+	cm_ctx->preauth_in_progress = true;
 }
 
 void cm_subst_preauth_exit(void *ctx)
@@ -189,16 +191,11 @@ bool cm_subst_preauth_event(void *ctx, uint16_t event,
 							     data_len, data);
 		break;
 	case WLAN_CM_SM_EV_ROAM_START:
-		/* set preauth to true when we enter preauth state */
-		cm_ctx->preauth_in_progress = true;
 		cm_host_roam_start_req(cm_ctx, data);
 		break;
 	case WLAN_CM_SM_EV_START_REASSOC:
-		/* set preauth to false as soon as we move to reassoc state */
-		cm_ctx->preauth_in_progress = false;
 		cm_sm_transition_to(cm_ctx, WLAN_CM_SS_REASSOC);
-		cm_sm_deliver_event_sync(cm_ctx, WLAN_CM_SM_EV_START_REASSOC,
-					 data_len, data);
+		cm_sm_deliver_event_sync(cm_ctx, event, data_len, data);
 		break;
 	case WLAN_CM_SM_EV_REASSOC_FAILURE:
 		cm_reassoc_complete(cm_ctx, data);
@@ -219,6 +216,8 @@ void cm_subst_reassoc_entry(void *ctx)
 		QDF_BUG(0);
 
 	cm_set_substate(cm_ctx, WLAN_CM_SS_REASSOC);
+	/* set preauth to false as soon as we move to reassoc state */
+	cm_ctx->preauth_in_progress = false;
 }
 
 void cm_subst_reassoc_exit(void *ctx)
@@ -269,6 +268,15 @@ bool cm_subst_reassoc_event(void *ctx, uint16_t event,
 	case WLAN_CM_SM_EV_REASSOC_FAILURE:
 		cm_reassoc_complete(cm_ctx, data);
 		break;
+	case WLAN_CM_SM_EV_HW_MODE_SUCCESS:
+	case WLAN_CM_SM_EV_HW_MODE_FAILURE:
+		/* check if cm id is valid for the current req */
+		if (!cm_check_cmid_match_list_head(cm_ctx, data)) {
+			event_handled = false;
+			break;
+		}
+		cm_handle_reassoc_hw_mode_change(cm_ctx, data, event);
+		break;
 	default:
 		event_handled = false;
 		break;

+ 6 - 2
umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_public_struct.h

@@ -256,20 +256,22 @@ struct wlan_cm_vdev_connect_req {
 
 /**
  * struct wlan_cm_roam_req - roam req from requester
+ * @forced_roaming: Roaming to be done without giving bssid, and channel.
+ * @self_reassoc: used to determine self reassoc in host roaming
  * @vdev_id: vdev id
  * @source: source of the req
  * @bssid: bssid given
  * @prev_bssid: prev AP bssid, given in case supplican want to roam to new BSSID
  * @chan_freq: channel of the AP
- * @forced_roaming: Roaming to be done without giving bssid, and channel.
  */
 struct wlan_cm_roam_req {
+	uint8_t forced_roaming:1,
+		self_reassoc:1;
 	uint8_t vdev_id;
 	enum wlan_cm_source source;
 	struct qdf_mac_addr bssid;
 	struct qdf_mac_addr prev_bssid;
 	uint32_t chan_freq;
-	bool forced_roaming;
 };
 
 /**
@@ -277,11 +279,13 @@ struct wlan_cm_roam_req {
  * vdev mgr
  * @vdev_id: vdev id
  * @cm_id: Connect manager id
+ * @self_reassoc: if self reassoc
  * @bss: scan entry for the candidate
  */
 struct wlan_cm_vdev_reassoc_req {
 	uint8_t vdev_id;
 	wlan_cm_id cm_id;
+	bool self_reassoc;
 	struct qdf_mac_addr prev_bssid;
 	struct scan_cache_node *bss;
 };

+ 7 - 1
umac/mlme/connection_mgr/dispatcher/src/wlan_cm_api.c

@@ -298,7 +298,13 @@ const char *wlan_cm_reason_code_to_str(enum wlan_reason_code reason)
 void wlan_cm_hw_mode_change_resp(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id,
 				 wlan_cm_id cm_id, QDF_STATUS status)
 {
-	cm_hw_mode_change_resp(pdev, vdev_id, cm_id, status);
+	uint32_t prefix;
+
+	prefix = CM_ID_GET_PREFIX(cm_id);
+	if (prefix == ROAM_REQ_PREFIX)
+		cm_reassoc_hw_mode_change_resp(pdev, vdev_id, cm_id, status);
+	else
+		cm_hw_mode_change_resp(pdev, vdev_id, cm_id, status);
 }
 #endif /* ifdef POLICY_MGR_ENABLE */