瀏覽代碼

qcacmn: Set link switch conf inline with link switch connect

Successful link switch connect implies that the VDEV-Link mapping
changed in driver and FW expects success notification in link switch
confirmation after which FW updates internal fields to reflect this
VDEV-Link mapping same as in driver.
If driver receives SB disconnect while link switch is in progress,
it defers the SB disconnect and moves link switch to abort state.
As current state is in abort, host will forcefully sends failure
status to FW in link switch confirmation and immediately starts SB
disconnect and sends VDEV_STOP to FW. As link switch status is
failure, VDEV-Link mapping is not updated in FW and FW might send
another link switch request with params corresponding to previous
VDEV-Link mapping and leads to Host-FW out of sync issue.

If the status of link switch connect is success, then force link
switch confirmation status to success so that FW can update new
VDEV-Link mapping.

Change-Id: Iaa9836f9089a2f8fcbf4d49e3c598f9a01aa8d06
CRs-Fixed: 3665211
Vinod Kumar Pirla 1 年之前
父節點
當前提交
b0ca707783
共有 1 個文件被更改,包括 27 次插入3 次删除
  1. 27 3
      umac/mlo_mgr/src/wlan_mlo_mgr_link_switch.c

+ 27 - 3
umac/mlo_mgr/src/wlan_mlo_mgr_link_switch.c

@@ -779,6 +779,31 @@ out:
 	return status;
 }
 
+static void
+mlo_mgr_link_switch_connect_success_trans_state(struct wlan_objmgr_vdev *vdev)
+{
+	enum mlo_link_switch_req_state curr_state;
+
+	/*
+	 * If connection is success, then sending link switch failure to FW
+	 * might result in not updating VDEV to link mapping in FW and FW may
+	 * immediately send next link switch with params corresponding to
+	 * pre-link switch which may vary post-link switch in host and might
+	 * not be valid and results in Host-FW out-of-sync.
+	 *
+	 * Force the result of link switch in align with link switch connect
+	 * so that Host and FW are not out of sync.
+	 */
+	mlo_dev_lock_acquire(vdev->mlo_dev_ctx);
+	curr_state = vdev->mlo_dev_ctx->link_ctx->last_req.state;
+	vdev->mlo_dev_ctx->link_ctx->last_req.state =
+					MLO_LINK_SWITCH_STATE_COMPLETE_SUCCESS;
+	mlo_dev_lock_release(vdev->mlo_dev_ctx);
+
+	if (curr_state != MLO_LINK_SWITCH_STATE_CONNECT_NEW_LINK)
+		mlo_debug("Current link switch state %d changed", curr_state);
+}
+
 void mlo_mgr_link_switch_connect_done(struct wlan_objmgr_vdev *vdev,
 				      QDF_STATUS status)
 {
@@ -786,7 +811,7 @@ void mlo_mgr_link_switch_connect_done(struct wlan_objmgr_vdev *vdev,
 
 	req = &vdev->mlo_dev_ctx->link_ctx->last_req;
 	if (QDF_IS_STATUS_SUCCESS(status))
-		mlo_mgr_link_switch_trans_next_state(vdev->mlo_dev_ctx);
+		mlo_mgr_link_switch_connect_success_trans_state(vdev);
 	else
 		mlo_err("VDEV %d link switch connect failed", req->vdev_id);
 
@@ -948,8 +973,7 @@ void mlo_mgr_remove_link_switch_cmd(struct wlan_objmgr_vdev *vdev)
 	mlo_mgr_link_switch_notify(vdev, req);
 
 	/* Handle any pending disconnect */
-	if (cur_state == MLO_LINK_SWITCH_STATE_ABORT_TRANS)
-		mlo_handle_pending_disconnect(vdev);
+	mlo_handle_pending_disconnect(vdev);
 
 	if (req->reason == MLO_LINK_SWITCH_REASON_HOST_FORCE) {
 		mlo_debug("Link switch not serialized");