Browse Source

qcacld-3.0: Support roam start and roam abort request in CM

Add change to support roam start and roam abort request
in connection manager.

Change-Id: Ibc1f2887902e2020c93b2827f8ffa247001cfa5f
CRs-Fixed: 2882221
Amruta Kulkarni 4 years ago
parent
commit
33a5b0a35d

+ 2 - 1
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_fw_sync.c

@@ -27,6 +27,7 @@
 #include "wlan_objmgr_vdev_obj.h"
 #include "wlan_cm_roam_i.h"
 
+#ifdef FEATURE_CM_ENABLE
 QDF_STATUS cm_fw_roam_sync_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
 {
 	return QDF_STATUS_SUCCESS;
@@ -37,4 +38,4 @@ cm_fw_roam_sync_propagation(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
 {
 	return QDF_STATUS_SUCCESS;
 }
-
+#endif

+ 26 - 8
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_i.h

@@ -25,11 +25,30 @@
 #ifndef _WLAN_CM_ROAM_I_H_
 #define _WLAN_CM_ROAM_I_H_
 
+#ifdef FEATURE_CM_ENABLE
 #include "qdf_types.h"
 #include "wlan_objmgr_psoc_obj.h"
 #include "wlan_objmgr_pdev_obj.h"
 #include "wlan_objmgr_vdev_obj.h"
+#include "connection_mgr/core/src/wlan_cm_main.h"
 
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+/**
+ * cm_add_fw_roam_dummy_ser_cb() - Add dummy blocking command
+ * @pdev: pdev pointer
+ * @cm_ctx: connection mgr context
+ * @cm_req: connect req
+ *
+ * This function adds dummy blocking command with high priority to avoid
+ * any other vdev command till roam is completed.Any NB operations will be
+ * blocked in serailization until roam logic completes execution.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+cm_add_fw_roam_dummy_ser_cb(struct wlan_objmgr_pdev *pdev,
+			    struct cnx_mgr *cm_ctx,
+			    struct cm_req *cm_req);
 /**
  * cm_fw_roam_start_req() - Post roam start req to CM SM
  * @psoc: psoc pointer
@@ -41,20 +60,17 @@
  * Return: QDF_STATUS
  */
 QDF_STATUS cm_fw_roam_start_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id);
-
 /**
- * cm_fw_roam_start() - Handle roam start event
- * @cm_ctx: connection mgr context
+ * cm_fw_roam_abort_req() - Post roam abort req to CM SM
+ * @psoc: psoc pointer
  * @vdev_id: vdev id
- * @pause_serialization: boolean indicating to pause serialization
  *
- * This function handles the roam start event received from FW.
+ * This function posts roam abort event change to connection manager
+ * state machine
  *
  * Return: QDF_STATUS
  */
-QDF_STATUS cm_fw_roam_start(struct cnx_mgr *cm_ctx, uint8_t vdev_id,
-			    bool pause_serialization);
-
+QDF_STATUS cm_fw_roam_abort_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id);
 /**
  * cm_fw_roam_sync_req() - Post roam sync to CM SM
  * @psoc: psoc pointer
@@ -79,4 +95,6 @@ QDF_STATUS cm_fw_roam_sync_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id);
  */
 QDF_STATUS
 cm_fw_roam_sync_propagation(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id);
+#endif /*WLAN_FEATURE_ROAM_OFFLOAD */
+#endif /*FEATURE_CM_ENABLE */
 #endif /* _WLAN_CM_ROAM_I_H_ */

+ 307 - 3
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload_event.c

@@ -26,14 +26,318 @@
 #include "wlan_objmgr_pdev_obj.h"
 #include "wlan_objmgr_vdev_obj.h"
 #include "wlan_cm_roam_i.h"
+#include <wlan_cm_public_struct.h>
+#include "wlan_scan_public_structs.h"
+#include "wlan_cm_roam_public_struct.h"
+#include "wlan_serialization_api.h"
+#include "wlan_cm_roam_api.h"
+#include <wlan_cfg80211_scan.h>
+#ifdef FEATURE_CM_ENABLE
+#include "connection_mgr/core/src/wlan_cm_roam.h"
+#include "connection_mgr/core/src/wlan_cm_sm.h"
+#include "connection_mgr/core/src/wlan_cm_main_api.h"
+#define FW_ROAM_SYNC_TIMEOUT 7000
 
-QDF_STATUS cm_fw_roam_start_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
+static QDF_STATUS cm_abort_fw_roam(struct cnx_mgr *cm_ctx,
+				   wlan_cm_id cm_id)
+{
+	QDF_STATUS status;
+
+	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);
+
+	return status;
+}
+
+static QDF_STATUS
+cm_fw_roam_ser_cb(struct wlan_serialization_command *cmd,
+		  enum wlan_serialization_cb_reason reason)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	struct wlan_objmgr_vdev *vdev;
+	struct cnx_mgr *cm_ctx;
+
+	if (!cmd) {
+		mlme_err("cmd is NULL, reason: %d", reason);
+		QDF_ASSERT(0);
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	vdev = cmd->vdev;
+
+	cm_ctx = cm_get_cm_ctx(vdev);
+	if (!cm_ctx)
+		return QDF_STATUS_E_NULL_VALUE;
+
+	switch (reason) {
+	case WLAN_SER_CB_ACTIVATE_CMD:
+		cm_ctx->active_cm_id = cmd->cmd_id;
+		break;
+	case WLAN_SER_CB_CANCEL_CMD:
+		/* command removed from pending list. */
+		break;
+	case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT:
+		mlme_err(CM_PREFIX_FMT "Active command timeout",
+			 CM_PREFIX_REF(wlan_vdev_get_id(vdev), cmd->cmd_id));
+
+		cm_abort_fw_roam(cm_ctx, cmd->cmd_id);
+		break;
+	case WLAN_SER_CB_RELEASE_MEM_CMD:
+		cm_reset_active_cm_id(vdev, cmd->cmd_id);
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
+		break;
+	default:
+		QDF_ASSERT(0);
+		status = QDF_STATUS_E_INVAL;
+		break;
+	}
+
+	return status;
+}
+
+QDF_STATUS
+cm_add_fw_roam_dummy_ser_cb(struct wlan_objmgr_pdev *pdev,
+			    struct cnx_mgr *cm_ctx,
+			    struct cm_req *cm_req)
 {
+	struct wlan_serialization_command cmd = {0, };
+	enum wlan_serialization_status ser_cmd_status;
+	QDF_STATUS status;
+	uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
+
+	status = wlan_objmgr_vdev_try_get_ref(cm_ctx->vdev, WLAN_MLME_CM_ID);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		mlme_err(CM_PREFIX_FMT "unable to get reference",
+			 CM_PREFIX_REF(vdev_id, cm_req->cm_id));
+		return status;
+	}
+
+	cmd.cmd_type = WLAN_SER_CMD_VDEV_ROAM;
+	cmd.cmd_id = cm_req->cm_id;
+	cmd.cmd_cb = cm_fw_roam_ser_cb;
+	cmd.source = WLAN_UMAC_COMP_MLME;
+	cmd.is_high_priority = true;
+	cmd.cmd_timeout_duration = FW_ROAM_SYNC_TIMEOUT;
+	cmd.vdev = cm_ctx->vdev;
+	cmd.is_blocking = cm_ser_get_blocking_cmd();
+
+	ser_cmd_status = wlan_serialization_request(&cmd);
+	switch (ser_cmd_status) {
+	case WLAN_SER_CMD_PENDING:
+		/* command moved to pending list.Do nothing */
+		break;
+	case WLAN_SER_CMD_ACTIVE:
+		/* command moved to active list. Do nothing */
+		break;
+	default:
+		mlme_err(CM_PREFIX_FMT "ser cmd status %d",
+			 CM_PREFIX_REF(vdev_id, cm_req->cm_id), ser_cmd_status);
+		wlan_objmgr_vdev_release_ref(cm_ctx->vdev, WLAN_MLME_CM_ID);
+
+		return QDF_STATUS_E_FAILURE;
+	}
+
 	return QDF_STATUS_SUCCESS;
 }
 
-QDF_STATUS cm_fw_roam_start(struct cnx_mgr *cm_ctx, uint8_t vdev_id,
-			    bool pause_serialization)
+QDF_STATUS cm_prepare_roam_cmd(struct cnx_mgr *cm_ctx,
+			       struct cm_req **roam_req,
+			       enum wlan_cm_source source)
 {
+	struct cm_req *req;
+
+	*roam_req = qdf_mem_malloc(sizeof(**roam_req));
+	if (!*roam_req)
+		return QDF_STATUS_E_NOMEM;
+
+	req = *roam_req;
+	req->roam_req.req.source = source;
+
 	return QDF_STATUS_SUCCESS;
 }
+
+QDF_STATUS cm_add_fw_roam_cmd_to_list_n_ser(struct cnx_mgr *cm_ctx,
+					    struct cm_req *cm_req)
+{
+	struct wlan_objmgr_pdev *pdev;
+	QDF_STATUS status;
+
+	pdev = wlan_vdev_get_pdev(cm_ctx->vdev);
+
+	if (!pdev) {
+		mlme_err("Failed to find pdev for vdev id %d",
+			 wlan_vdev_get_id(cm_ctx->vdev));
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	status = cm_add_roam_req_to_list(cm_ctx, cm_req);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		cm_abort_fw_roam(cm_ctx, CM_ID_INVALID);
+		cm_free_roam_req_mem(&cm_req->roam_req);
+		qdf_mem_free(cm_req);
+		return status;
+	}
+
+	status = cm_add_fw_roam_dummy_ser_cb(pdev, cm_ctx, cm_req);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		cm_abort_fw_roam(cm_ctx, cm_req->roam_req.cm_id);
+		return status;
+	}
+
+	return status;
+}
+
+QDF_STATUS cm_fw_roam_start_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
+{
+	QDF_STATUS status;
+	struct wlan_objmgr_vdev *vdev;
+
+	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;
+	}
+
+	status = cm_sm_deliver_event(vdev, WLAN_CM_SM_EV_ROAM_START,
+				     0, NULL);
+
+	if (QDF_IS_STATUS_ERROR(status))
+		mlme_err("EV ROAM START not handled");
+
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
+
+	return status;
+}
+
+QDF_STATUS cm_fw_roam_start(struct cnx_mgr *cm_ctx)
+{
+	struct wlan_objmgr_pdev *pdev;
+	struct wlan_objmgr_psoc *psoc;
+	QDF_STATUS status;
+	wlan_scan_id scan_id;
+	bool abort_host_scan_cap = false;
+	wlan_cm_id cm_id;
+	struct cm_roam_req *roam_req = NULL;
+
+	roam_req = cm_get_first_roam_command(cm_ctx->vdev);
+	if (!roam_req) {
+		mlme_err("Failed to find roam req from list");
+		cm_id = CM_ID_INVALID;
+		status = QDF_STATUS_E_FAILURE;
+		goto error;
+	}
+
+	cm_id = roam_req->cm_id;
+	pdev = wlan_vdev_get_pdev(cm_ctx->vdev);
+	if (!pdev) {
+		mlme_err(CM_PREFIX_FMT "Failed to find pdev",
+			 CM_PREFIX_REF(roam_req->req.vdev_id,
+				       roam_req->cm_id));
+		status = QDF_STATUS_E_FAILURE;
+		goto error;
+	}
+	psoc = wlan_pdev_get_psoc(pdev);
+	if (!psoc) {
+		mlme_err(CM_PREFIX_FMT "Failed to find psoc",
+			 CM_PREFIX_REF(roam_req->req.vdev_id,
+				       roam_req->cm_id));
+		status = QDF_STATUS_E_FAILURE;
+		goto error;
+	}
+
+	status = wlan_cm_roam_state_change(pdev,
+					   roam_req->req.vdev_id,
+					   WLAN_ROAMING_IN_PROG,
+					   REASON_ROAM_CANDIDATE_FOUND);
+
+	if (QDF_IS_STATUS_ERROR(status))
+		goto error;
+
+	mlme_cm_osif_roam_start_ind(cm_ctx->vdev);
+	/*
+	 * For emergency deauth roaming, firmware sends ROAM start
+	 * instead of ROAM scan start notification as data path queues
+	 * will be stopped only during roam start notification.
+	 * This is because, for deauth/disassoc triggered roam, the
+	 * AP has sent deauth, and packets shouldn't be sent to AP
+	 * after that. Since firmware is sending roam start directly
+	 * host sends scan abort during roam scan, but in other
+	 * triggers, the host receives roam start after candidate
+	 * selection and roam scan is complete. So when host sends
+	 * roam abort for emergency deauth roam trigger, the firmware
+	 * roam scan is also aborted. This results in roaming failure.
+	 * So send scan_id as CANCEL_HOST_SCAN_ID to scan module to
+	 * abort only host triggered scans.
+	 */
+	abort_host_scan_cap =
+		wlan_mlme_get_host_scan_abort_support(psoc);
+	if (abort_host_scan_cap)
+		scan_id = CANCEL_HOST_SCAN_ID;
+	else
+		scan_id = INVAL_SCAN_ID;
+
+	wlan_abort_scan(pdev, INVAL_PDEV_ID,
+			roam_req->req.vdev_id,
+			scan_id, false);
+error:
+	if (QDF_IS_STATUS_ERROR(status))
+		cm_abort_fw_roam(cm_ctx, cm_id);
+
+	return status;
+}
+
+QDF_STATUS cm_fw_roam_abort_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
+{
+	struct wlan_objmgr_pdev *pdev;
+	struct wlan_objmgr_vdev *vdev;
+	struct cnx_mgr *cm_ctx;
+	QDF_STATUS status;
+	struct cm_roam_req *roam_req = NULL;
+	wlan_cm_id cm_id;
+
+	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;
+	}
+
+	cm_ctx = cm_get_cm_ctx(vdev);
+	roam_req = cm_get_first_roam_command(vdev);
+	if (!roam_req) {
+		mlme_err("Failed to find roam req from list");
+		cm_id = CM_ID_INVALID;
+		status = QDF_STATUS_E_FAILURE;
+		goto end;
+	}
+
+	cm_id = roam_req->cm_id;
+	pdev = wlan_vdev_get_pdev(vdev);
+	if (!pdev) {
+		mlme_err("Failed to find pdev for vdev id %d",
+			 roam_req->req.vdev_id);
+		status = QDF_STATUS_E_FAILURE;
+		goto end;
+	}
+
+	mlme_cm_osif_roam_abort_ind(cm_ctx->vdev);
+	status = wlan_cm_roam_state_change(pdev,
+					   roam_req->req.vdev_id,
+					   WLAN_ROAM_RSO_ENABLED,
+					   REASON_ROAM_ABORT);
+
+	if (QDF_IS_STATUS_ERROR(status))
+		goto end;
+end:
+	cm_abort_fw_roam(cm_ctx, cm_id);
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
+
+	return status;
+}
+#endif /*FEATURE_CM_ENABLE */

+ 1 - 0
core/hdd/src/wlan_hdd_assoc.c

@@ -5225,6 +5225,7 @@ struct osif_cm_ops osif_ops = {
 	.connect_complete_cb = hdd_cm_connect_complete,
 	.disconnect_complete_cb = hdd_cm_disconnect_complete,
 	.netif_queue_control_cb = hdd_cm_netif_queue_control,
+	.napi_serialize_control_cb = hdd_cm_napi_serialize_control,
 #ifdef WLAN_FEATURE_FILS_SK
 	.save_gtk_cb = hdd_cm_save_gtk,
 	.set_hlp_data_cb = hdd_cm_set_hlp_data,

+ 9 - 0
core/hdd/src/wlan_hdd_cm_api.h

@@ -83,6 +83,15 @@ QDF_STATUS hdd_cm_netif_queue_control(struct wlan_objmgr_vdev *vdev,
 QDF_STATUS hdd_cm_connect_complete(struct wlan_objmgr_vdev *vdev,
 				   struct wlan_cm_connect_resp *rsp,
 				   enum osif_cb_type type);
+/**
+ * hdd_cm_napi_serialize_control() - NAPI serialize hdd cb
+ * @action: serialize or de-serialize NAPI activities
+ *
+ * This function is for napi serialize
+ *
+ * Return: qdf status
+ */
+QDF_STATUS hdd_cm_napi_serialize_control(bool action);
 
 #ifdef WLAN_FEATURE_FILS_SK
 /**

+ 8 - 0
core/hdd/src/wlan_hdd_cm_disconnect.c

@@ -352,5 +352,13 @@ QDF_STATUS hdd_cm_netif_queue_control(struct wlan_objmgr_vdev *vdev,
 
 	return QDF_STATUS_SUCCESS;
 }
+
+QDF_STATUS hdd_cm_napi_serialize_control(bool action)
+{
+	hdd_napi_serialize(action);
+
+	return QDF_STATUS_SUCCESS;
+}
+
 #endif
 

+ 10 - 2
core/wma/src/wma_scan_roam.c

@@ -85,6 +85,9 @@
 #ifdef FEATURE_WLAN_DIAG_SUPPORT    /* FEATURE_WLAN_DIAG_SUPPORT */
 #include "host_diag_core_log.h"
 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
+#ifdef FEATURE_CM_ENABLE
+#include <../../core/src/wlan_cm_roam_i.h>
+#endif
 
 #ifdef FEATURE_WLAN_EXTSCAN
 #define WMA_EXTSCAN_CYCLE_WAKE_LOCK_DURATION WAKELOCK_DURATION_RECOMMENDED
@@ -4230,7 +4233,6 @@ static void wma_invalid_roam_reason_handler(tp_wma_handle wma_handle,
 		wma_debug("Invalid notif %d", notif);
 		return;
 	}
-
 	roam_synch_data = qdf_mem_malloc(sizeof(*roam_synch_data));
 	if (!roam_synch_data)
 		return;
@@ -4239,9 +4241,15 @@ static void wma_invalid_roam_reason_handler(tp_wma_handle wma_handle,
 	if (notif != WMI_ROAM_NOTIF_ROAM_START)
 		wma_handle->pe_roam_synch_cb(wma_handle->mac_context,
 					     roam_synch_data, NULL, op_code);
-
+#if defined(FEATURE_CM_ENABLE) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
+	if (notif == WMI_ROAM_NOTIF_ROAM_START)
+		cm_fw_roam_start_req(wma_handle->psoc, vdev_id);
+	else
+		cm_fw_roam_abort_req(wma_handle->psoc, vdev_id);
+#else
 	wma_handle->csr_roam_synch_cb(wma_handle->mac_context, roam_synch_data,
 				      NULL, op_code);
+#endif
 	qdf_mem_free(roam_synch_data);
 }