Browse Source

qcacmn: Synchronize disconnect in RSO stop req-resp path

Host driver sends RSO stop request to firmware as part of
disconnect and waits for RSO stop response. It pauses the
disconnection and resumes once RSO stop response is received
from the firmware.
But cm_lock is not taken when disconnection is resumed from RSO
stop response path. This causes synchronization issues with
north bound thread which issued the disconnection.
Acquire cm_lock by using cm_sm_deliver_event() API to provide
synchronization between disconnect initiator thread and
scheduler thread.

Change-Id: I3c287a020e0a12abab2ad6237594e022adc904a7
CRs-Fixed: 3287190
Srinivas Dasari 2 years ago
parent
commit
be121546e8

+ 26 - 19
umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c

@@ -415,8 +415,7 @@ QDF_STATUS cm_disconnect_active(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
 	req->req.is_no_disassoc_disconnect =
 	req->req.is_no_disassoc_disconnect =
 			cm_req->discon_req.req.is_no_disassoc_disconnect;
 			cm_req->discon_req.req.is_no_disassoc_disconnect;
 
 
-	cm_disconnect_continue_after_rso_stop(cm_ctx->vdev, false,
-					      req);
+	cm_disconnect_continue_after_rso_stop(cm_ctx->vdev, req);
 	qdf_mem_free(req);
 	qdf_mem_free(req);
 
 
 	return status;
 	return status;
@@ -424,7 +423,6 @@ QDF_STATUS cm_disconnect_active(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
 
 
 QDF_STATUS
 QDF_STATUS
 cm_disconnect_continue_after_rso_stop(struct wlan_objmgr_vdev *vdev,
 cm_disconnect_continue_after_rso_stop(struct wlan_objmgr_vdev *vdev,
-				      bool is_ho_fail,
 				      struct wlan_cm_vdev_discon_req *req)
 				      struct wlan_cm_vdev_discon_req *req)
 {
 {
 	struct cm_req *cm_req;
 	struct cm_req *cm_req;
@@ -435,24 +433,10 @@ cm_disconnect_continue_after_rso_stop(struct wlan_objmgr_vdev *vdev,
 	if (!cm_ctx)
 	if (!cm_ctx)
 		return QDF_STATUS_E_INVAL;
 		return QDF_STATUS_E_INVAL;
 
 
-	if ((CM_ID_GET_PREFIX(req->cm_id)) != DISCONNECT_REQ_PREFIX) {
-		mlme_err(CM_PREFIX_FMT "active req is not disconnect req",
-			 CM_PREFIX_REF(wlan_vdev_get_id(vdev), req->cm_id));
-		return QDF_STATUS_E_INVAL;
-	}
-
 	cm_req = cm_get_req_by_cm_id(cm_ctx, req->cm_id);
 	cm_req = cm_get_req_by_cm_id(cm_ctx, req->cm_id);
 	if (!cm_req)
 	if (!cm_req)
 		return QDF_STATUS_E_INVAL;
 		return QDF_STATUS_E_INVAL;
 
 
-	if (is_ho_fail) {
-		mlme_debug(CM_PREFIX_FMT "Updating source(%d) and reason code (%d) to RSO reason and source as ho fail is received in RSO stop",
-			   CM_PREFIX_REF(req->req.vdev_id, req->cm_id),
-			   req->req.source, req->req.reason_code);
-		req->req.source = CM_MLME_DISCONNECT;
-		req->req.reason_code = REASON_FW_TRIGGERED_ROAM_FAILURE;
-	}
-
 	wlan_vdev_get_bss_peer_mac(cm_ctx->vdev, &bssid);
 	wlan_vdev_get_bss_peer_mac(cm_ctx->vdev, &bssid);
 	/*
 	/*
 	 * for northbound req, bssid is not provided so update it from vdev
 	 * for northbound req, bssid is not provided so update it from vdev
@@ -468,10 +452,10 @@ cm_disconnect_continue_after_rso_stop(struct wlan_objmgr_vdev *vdev,
 					  &cm_req->discon_req);
 					  &cm_req->discon_req);
 
 
 	mlme_debug(CM_PREFIX_FMT "disconnect " QDF_MAC_ADDR_FMT
 	mlme_debug(CM_PREFIX_FMT "disconnect " QDF_MAC_ADDR_FMT
-		   " source %d reason %d is_ho_fail: %u",
+		   " source %d reason %d",
 		   CM_PREFIX_REF(req->req.vdev_id, req->cm_id),
 		   CM_PREFIX_REF(req->req.vdev_id, req->cm_id),
 		   QDF_MAC_ADDR_REF(req->req.bssid.bytes),
 		   QDF_MAC_ADDR_REF(req->req.bssid.bytes),
-		   req->req.source, req->req.reason_code, is_ho_fail);
+		   req->req.source, req->req.reason_code);
 
 
 	status = mlme_cm_disconnect_req(cm_ctx->vdev, req);
 	status = mlme_cm_disconnect_req(cm_ctx->vdev, req);
 	if (QDF_IS_STATUS_ERROR(status)) {
 	if (QDF_IS_STATUS_ERROR(status)) {
@@ -483,6 +467,29 @@ cm_disconnect_continue_after_rso_stop(struct wlan_objmgr_vdev *vdev,
 	return status;
 	return status;
 }
 }
 
 
+QDF_STATUS
+cm_handle_rso_stop_rsp(struct wlan_objmgr_vdev *vdev,
+		       struct wlan_cm_vdev_discon_req *req)
+{
+	struct cnx_mgr *cm_ctx = cm_get_cm_ctx(vdev);
+	wlan_cm_id cm_id;
+
+	if (!cm_ctx)
+		return QDF_STATUS_E_INVAL;
+
+	cm_id = cm_ctx->active_cm_id;
+
+	if ((CM_ID_GET_PREFIX(req->cm_id)) != DISCONNECT_REQ_PREFIX ||
+	    cm_id != req->cm_id) {
+		mlme_err(CM_PREFIX_FMT "active req is not disconnect req",
+			 CM_PREFIX_REF(wlan_vdev_get_id(vdev), req->cm_id));
+		return QDF_STATUS_E_INVAL;
+	}
+
+	return cm_sm_deliver_event(vdev, WLAN_CM_SM_EV_RSO_STOP_RSP,
+				   sizeof(*req), req);
+}
+
 #ifdef CONN_MGR_ADV_FEATURE
 #ifdef CONN_MGR_ADV_FEATURE
 static void
 static void
 cm_inform_dlm_disconnect_complete(struct wlan_objmgr_vdev *vdev,
 cm_inform_dlm_disconnect_complete(struct wlan_objmgr_vdev *vdev,

+ 11 - 2
umac/mlme/connection_mgr/core/src/wlan_cm_main_api.h

@@ -469,16 +469,25 @@ void cm_send_disconnect_resp(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id);
 /**
 /**
  * cm_disconnect_continue_after_rso_stop() - Continue disconnect after RSO stop
  * cm_disconnect_continue_after_rso_stop() - Continue disconnect after RSO stop
  * @vdev: Objmgr vdev
  * @vdev: Objmgr vdev
- * @is_ho_fail: True if ho_fail happened
  * @req: pointer to cm vdev disconnect req
  * @req: pointer to cm vdev disconnect req
  *
  *
  * Return: QDF_STATUS
  * Return: QDF_STATUS
  */
  */
 QDF_STATUS
 QDF_STATUS
 cm_disconnect_continue_after_rso_stop(struct wlan_objmgr_vdev *vdev,
 cm_disconnect_continue_after_rso_stop(struct wlan_objmgr_vdev *vdev,
-				      bool is_ho_fail,
 				      struct wlan_cm_vdev_discon_req *req);
 				      struct wlan_cm_vdev_discon_req *req);
 
 
+/**
+ * cm_handle_rso_stop_rsp() - Handle RSO stop response
+ * @vdev: Objmgr vdev
+ * @req: pointer to cm vdev disconnect req
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+cm_handle_rso_stop_rsp(struct wlan_objmgr_vdev *vdev,
+		       struct wlan_cm_vdev_discon_req *req);
+
 /*************** UTIL APIs ****************/
 /*************** UTIL APIs ****************/
 
 
 /**
 /**

+ 10 - 0
umac/mlme/connection_mgr/core/src/wlan_cm_sm.c

@@ -476,6 +476,9 @@ static bool cm_state_disconnecting_event(void *ctx, uint16_t event,
 					 WLAN_CM_SM_EV_DISCONNECT_START,
 					 WLAN_CM_SM_EV_DISCONNECT_START,
 					 data_len, data);
 					 data_len, data);
 		break;
 		break;
+	case WLAN_CM_SM_EV_RSO_STOP_RSP:
+		cm_disconnect_continue_after_rso_stop(cm_ctx->vdev, data);
+		break;
 	default:
 	default:
 		event_handled = false;
 		event_handled = false;
 		break;
 		break;
@@ -630,6 +633,9 @@ static bool cm_subst_join_pending_event(void *ctx, uint16_t event,
 					 WLAN_CM_SM_EV_DISCONNECT_START,
 					 WLAN_CM_SM_EV_DISCONNECT_START,
 					 data_len, data);
 					 data_len, data);
 		break;
 		break;
+	case WLAN_CM_SM_EV_RSO_STOP_RSP:
+		cm_disconnect_continue_after_rso_stop(cm_ctx->vdev, data);
+		break;
 	default:
 	default:
 		event_handled = false;
 		event_handled = false;
 		break;
 		break;
@@ -730,6 +736,9 @@ static bool cm_subst_scan_event(void *ctx, uint16_t event,
 					 WLAN_CM_SM_EV_DISCONNECT_START,
 					 WLAN_CM_SM_EV_DISCONNECT_START,
 					 data_len, data);
 					 data_len, data);
 		break;
 		break;
+	case WLAN_CM_SM_EV_RSO_STOP_RSP:
+		cm_disconnect_continue_after_rso_stop(cm_ctx->vdev, data);
+		break;
 	default:
 	default:
 		event_handled = false;
 		event_handled = false;
 		break;
 		break;
@@ -1055,6 +1064,7 @@ static const char *cm_sm_event_names[] = {
 	"EV_PREAUTH_RESP",
 	"EV_PREAUTH_RESP",
 	"EV_REASSOC_TIMER",
 	"EV_REASSOC_TIMER",
 	"EV_HO_ROAM_DISCONNECT_DONE",
 	"EV_HO_ROAM_DISCONNECT_DONE",
+	"EV_RSO_STOP_RSP",
 };
 };
 
 
 enum wlan_cm_sm_state cm_get_state(struct cnx_mgr *cm_ctx)
 enum wlan_cm_sm_state cm_get_state(struct cnx_mgr *cm_ctx)

+ 4 - 1
umac/mlme/connection_mgr/core/src/wlan_cm_sm.h

@@ -1,6 +1,6 @@
 /*
 /*
  * Copyright (c) 2012-2015,2020-2021 The Linux Foundation. All rights reserved.
  * Copyright (c) 2012-2015,2020-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  * purpose with or without fee is hereby granted, provided that the above
@@ -68,6 +68,8 @@
  * @WLAN_CM_SM_EV_PREAUTH_RESP:           Preauth response
  * @WLAN_CM_SM_EV_PREAUTH_RESP:           Preauth response
  * @WLAN_CM_SM_EV_REASSOC_TIMER:         Reassoc timer expired
  * @WLAN_CM_SM_EV_REASSOC_TIMER:         Reassoc timer expired
  * @WLAN_CM_SM_EV_HO_ROAM_DISCONNECT_DONE: Disconnect done for hands off/roaming
  * @WLAN_CM_SM_EV_HO_ROAM_DISCONNECT_DONE: Disconnect done for hands off/roaming
+ * @WLAN_CM_SM_EV_RSO_STOP_RSP:           Event to continue disconnect after
+ *                                        RSO stop response is received
  * @WLAN_CM_SM_EV_MAX:                    Max event
  * @WLAN_CM_SM_EV_MAX:                    Max event
  */
  */
 enum wlan_cm_sm_evt {
 enum wlan_cm_sm_evt {
@@ -108,6 +110,7 @@ enum wlan_cm_sm_evt {
 	WLAN_CM_SM_EV_PREAUTH_RESP = 34,
 	WLAN_CM_SM_EV_PREAUTH_RESP = 34,
 	WLAN_CM_SM_EV_REASSOC_TIMER = 35,
 	WLAN_CM_SM_EV_REASSOC_TIMER = 35,
 	WLAN_CM_SM_EV_HO_ROAM_DISCONNECT_DONE = 36,
 	WLAN_CM_SM_EV_HO_ROAM_DISCONNECT_DONE = 36,
+	WLAN_CM_SM_EV_RSO_STOP_RSP = 37,
 	WLAN_CM_SM_EV_MAX,
 	WLAN_CM_SM_EV_MAX,
 };
 };
 
 

+ 3 - 3
umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_api.h

@@ -464,15 +464,15 @@ struct reduced_neighbor_report *wlan_cm_get_rnr(struct wlan_objmgr_vdev *vdev,
 /**
 /**
  * wlan_cm_disc_cont_after_rso_stop() - Continue disconnect after RSO stop
  * wlan_cm_disc_cont_after_rso_stop() - Continue disconnect after RSO stop
  * @vdev: Objmgr vdev
  * @vdev: Objmgr vdev
- * @is_ho_fail: True if ho_fail happened
  * @req: pointer to cm vdev disconnect req
  * @req: pointer to cm vdev disconnect req
-
+ *
+ * Continue disconnect after RSO stop response is receive from south bound.
  * This is a wrapper to call core API cm_disconnect_continue_after_rso_stop
  * This is a wrapper to call core API cm_disconnect_continue_after_rso_stop
+ * by acquiring cm_lock through cm_sm_deliver_event.
  *
  *
  * Return: QDF_STATUS
  * Return: QDF_STATUS
  */
  */
 QDF_STATUS
 QDF_STATUS
 wlan_cm_disc_cont_after_rso_stop(struct wlan_objmgr_vdev *vdev,
 wlan_cm_disc_cont_after_rso_stop(struct wlan_objmgr_vdev *vdev,
-				 bool is_ho_fail,
 				 struct wlan_cm_vdev_discon_req *req);
 				 struct wlan_cm_vdev_discon_req *req);
 #endif /* __WLAN_CM_UCFG_API_H */
 #endif /* __WLAN_CM_UCFG_API_H */

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

@@ -374,9 +374,7 @@ struct reduced_neighbor_report *wlan_cm_get_rnr(struct wlan_objmgr_vdev *vdev,
 
 
 QDF_STATUS
 QDF_STATUS
 wlan_cm_disc_cont_after_rso_stop(struct wlan_objmgr_vdev *vdev,
 wlan_cm_disc_cont_after_rso_stop(struct wlan_objmgr_vdev *vdev,
-				 bool is_ho_fail,
 				 struct wlan_cm_vdev_discon_req *req)
 				 struct wlan_cm_vdev_discon_req *req)
 {
 {
-	return cm_disconnect_continue_after_rso_stop(vdev, is_ho_fail,
-						     req);
+	return cm_handle_rso_stop_rsp(vdev, req);
 }
 }