Parcourir la 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 il y a 2 ans
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 =
 			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);
 
 	return status;
@@ -424,7 +423,6 @@ QDF_STATUS cm_disconnect_active(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
 
 QDF_STATUS
 cm_disconnect_continue_after_rso_stop(struct wlan_objmgr_vdev *vdev,
-				      bool is_ho_fail,
 				      struct wlan_cm_vdev_discon_req *req)
 {
 	struct cm_req *cm_req;
@@ -435,24 +433,10 @@ cm_disconnect_continue_after_rso_stop(struct wlan_objmgr_vdev *vdev,
 	if (!cm_ctx)
 		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);
 	if (!cm_req)
 		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);
 	/*
 	 * 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);
 
 	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),
 		   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);
 	if (QDF_IS_STATUS_ERROR(status)) {
@@ -483,6 +467,29 @@ cm_disconnect_continue_after_rso_stop(struct wlan_objmgr_vdev *vdev,
 	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
 static void
 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
  * @vdev: Objmgr vdev
- * @is_ho_fail: True if ho_fail happened
  * @req: pointer to cm vdev disconnect req
  *
  * Return: QDF_STATUS
  */
 QDF_STATUS
 cm_disconnect_continue_after_rso_stop(struct wlan_objmgr_vdev *vdev,
-				      bool is_ho_fail,
 				      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 ****************/
 
 /**

+ 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,
 					 data_len, data);
 		break;
+	case WLAN_CM_SM_EV_RSO_STOP_RSP:
+		cm_disconnect_continue_after_rso_stop(cm_ctx->vdev, data);
+		break;
 	default:
 		event_handled = false;
 		break;
@@ -630,6 +633,9 @@ static bool cm_subst_join_pending_event(void *ctx, uint16_t event,
 					 WLAN_CM_SM_EV_DISCONNECT_START,
 					 data_len, data);
 		break;
+	case WLAN_CM_SM_EV_RSO_STOP_RSP:
+		cm_disconnect_continue_after_rso_stop(cm_ctx->vdev, data);
+		break;
 	default:
 		event_handled = false;
 		break;
@@ -730,6 +736,9 @@ static bool cm_subst_scan_event(void *ctx, uint16_t event,
 					 WLAN_CM_SM_EV_DISCONNECT_START,
 					 data_len, data);
 		break;
+	case WLAN_CM_SM_EV_RSO_STOP_RSP:
+		cm_disconnect_continue_after_rso_stop(cm_ctx->vdev, data);
+		break;
 	default:
 		event_handled = false;
 		break;
@@ -1055,6 +1064,7 @@ static const char *cm_sm_event_names[] = {
 	"EV_PREAUTH_RESP",
 	"EV_REASSOC_TIMER",
 	"EV_HO_ROAM_DISCONNECT_DONE",
+	"EV_RSO_STOP_RSP",
 };
 
 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) 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
  * 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_REASSOC_TIMER:         Reassoc timer expired
  * @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
  */
 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_REASSOC_TIMER = 35,
 	WLAN_CM_SM_EV_HO_ROAM_DISCONNECT_DONE = 36,
+	WLAN_CM_SM_EV_RSO_STOP_RSP = 37,
 	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
  * @vdev: Objmgr vdev
- * @is_ho_fail: True if ho_fail happened
  * @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
+ * by acquiring cm_lock through cm_sm_deliver_event.
  *
  * Return: QDF_STATUS
  */
 QDF_STATUS
 wlan_cm_disc_cont_after_rso_stop(struct wlan_objmgr_vdev *vdev,
-				 bool is_ho_fail,
 				 struct wlan_cm_vdev_discon_req *req);
 #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
 wlan_cm_disc_cont_after_rso_stop(struct wlan_objmgr_vdev *vdev,
-				 bool is_ho_fail,
 				 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);
 }