qcacld-3.0: Wait for RSO stop response from firmware

Firmware doesn't expect any vdev commands from host while RSO stop
is happening. It sends a response to the RSO_STOP command once
it's done with cleanup. Host needs to run a timer after sending
RSO stop command to firmware and wait for a maximum of 6 seconds
for the response. Host can stop the timer and allow the commands
to firmware in the below cases,
1. RSO_STOP response with success status
2. RSO_STOP response with HO_FAIL status followed by
   HO_FAIL event: Host needs to wait till HO_FAIL event is received

If firmware doesn't send any response in the 6 seconds wait, issue
a recovery to help to check the firmware state.

Also, set WMI_ROAM_SCAN_MODE_FLAG_REPORT_STATUS always when MLO is
supported while sending RSO_STOP to firmware. It's sent only
in case of wpa_supplicant disabled roaming currently.

Change-Id: I8182e60beb9288dba23cc72e978dc781c8ab1707
CRs-Fixed: 3106023
This commit is contained in:
Srinivas Dasari
2021-12-21 16:28:34 +05:30
committed by Madan Koyyalamudi
parent 2bd5e660c5
commit db3c1a98e5
16 changed files with 429 additions and 43 deletions

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 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
@@ -31,6 +31,15 @@
#include <target_if.h>
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
/**
* target_if_cm_get_roam_rx_ops() - Get CM roam rx ops registered
* @psoc: pointer to psoc object
*
* Return: roam rx ops of connection mgr
*/
struct wlan_cm_roam_rx_ops *
target_if_cm_get_roam_rx_ops(struct wlan_objmgr_psoc *psoc);
/**
* target_if_cm_roam_sync_event() - Target IF handler for roam sync events
* @scn: target handle

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
* Copyright (c) 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
@@ -32,4 +33,46 @@
*/
QDF_STATUS
target_if_cm_roam_register_tx_ops(struct wlan_cm_roam_tx_ops *tx_ops);
#ifdef WLAN_FEATURE_11BE_MLO
/**
* target_if_stop_rso_stop_timer() - Stop the RSO_STOP timer
* @roam_event: Roam event data
*
* This stops the RSO stop timer in below cases,
* 1. If the reason is RSO_STATUS and notif is CM_ROAM_NOTIF_SCAN_MODE_SUCCESS
* 2. If wait started already and received HO_FAIL event
*
* Return: QDF_STATUS
*/
QDF_STATUS
target_if_stop_rso_stop_timer(struct roam_offload_roam_event *roam_event);
#else
static inline QDF_STATUS
target_if_stop_rso_stop_timer(struct roam_offload_roam_event *roam_event)
{
roam_event->rso_timer_stopped = false;
return QDF_STATUS_E_NOSUPPORT;
}
#endif
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
/**
* target_if_cm_send_rso_stop_failure_rsp() - Send RSO_STOP failure rsp to CM
* @psoc: psoc object
* @vdev_id: vdev_id on which RSO stop is issued
*
* Return: QDF_STATUS
*/
QDF_STATUS
target_if_cm_send_rso_stop_failure_rsp(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id);
#else
static inline QDF_STATUS
target_if_cm_send_rso_stop_failure_rsp(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id)
{
return QDF_STATUS_E_NOSUPPORT;
}
#endif
#endif

View File

@@ -30,8 +30,9 @@
#include "wlan_mlme_main.h"
#include <../../core/src/wlan_cm_roam_i.h>
#include "wlan_cm_roam_api.h"
#include "target_if_cm_roam_offload.h"
static inline struct wlan_cm_roam_rx_ops *
struct wlan_cm_roam_rx_ops *
target_if_cm_get_roam_rx_ops(struct wlan_objmgr_psoc *psoc)
{
struct wlan_mlme_psoc_ext_obj *psoc_ext_priv;
@@ -238,6 +239,14 @@ int target_if_cm_roam_event(ol_scn_t scn, uint8_t *event, uint32_t len)
roam_event->psoc = psoc;
/**
* Stop the timer upon RSO stop status success. The timer shall continue
* to run upon HO_FAIL status and would be stopped upon HO_FAILED event
*/
if (roam_event->reason == ROAM_REASON_RSO_STATUS ||
roam_event->reason == ROAM_REASON_HO_FAILED)
target_if_stop_rso_stop_timer(roam_event);
roam_rx_ops = target_if_cm_get_roam_rx_ops(psoc);
if (!roam_rx_ops || !roam_rx_ops->roam_event_rx) {
target_if_err("No valid roam rx ops");

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 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
@@ -28,6 +28,9 @@
#include "wlan_crypto_global_api.h"
#include "wlan_mlme_main.h"
#include "wlan_cm_roam_api.h"
#include <target_if_vdev_mgr_rx_ops.h>
#include <target_if_vdev_mgr_tx_ops.h>
#include "target_if_cm_roam_event.h"
static struct wmi_unified
*target_if_cm_roam_get_wmi_handle_from_vdev(struct wlan_objmgr_vdev *vdev)
@@ -1093,6 +1096,141 @@ end:
return status;
}
#ifdef WLAN_FEATURE_11BE_MLO
static QDF_STATUS
target_if_start_rso_stop_timer(struct wlan_objmgr_vdev *vdev)
{
struct wlan_objmgr_psoc *psoc;
uint8_t vdev_id;
struct wlan_lmac_if_mlme_rx_ops *rx_ops;
struct vdev_response_timer *vdev_rsp;
psoc = wlan_vdev_get_psoc(vdev);
if (!psoc) {
target_if_err("psoc handle is NULL");
return QDF_STATUS_E_INVAL;
}
vdev_id = wlan_vdev_get_id(vdev);
rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
if (!rx_ops || !rx_ops->psoc_get_vdev_response_timer_info) {
mlme_err("VEV_%d: PSOC_%d No Rx Ops", vdev_id,
wlan_psoc_get_id(psoc));
return QDF_STATUS_E_INVAL;
}
vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, vdev_id);
if (!vdev_rsp) {
mlme_err("VDEV_%d: PSOC_%d No vdev rsp timer", vdev_id,
wlan_psoc_get_id(psoc));
return QDF_STATUS_E_INVAL;
}
vdev_rsp->expire_time = RSO_STOP_RESPONSE_TIMER;
return target_if_vdev_mgr_rsp_timer_start(psoc, vdev_rsp,
RSO_STOP_RESPONSE_BIT);
}
QDF_STATUS
target_if_stop_rso_stop_timer(struct roam_offload_roam_event *roam_event)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct vdev_response_timer *vdev_rsp;
struct wlan_lmac_if_mlme_rx_ops *rx_ops;
roam_event->rso_timer_stopped = false;
rx_ops = target_if_vdev_mgr_get_rx_ops(roam_event->psoc);
if (!rx_ops || !rx_ops->vdev_mgr_start_response) {
mlme_err("No Rx Ops");
return QDF_STATUS_E_INVAL;
}
vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(roam_event->psoc,
roam_event->vdev_id);
if (!vdev_rsp) {
mlme_err("vdev response timer is null VDEV_%d PSOC_%d",
roam_event->vdev_id,
wlan_psoc_get_id(roam_event->psoc));
return QDF_STATUS_E_INVAL;
}
if ((roam_event->reason == ROAM_REASON_RSO_STATUS &&
(roam_event->notif == CM_ROAM_NOTIF_SCAN_MODE_SUCCESS ||
roam_event->notif == CM_ROAM_NOTIF_SCAN_MODE_FAIL)) ||
roam_event->reason == ROAM_REASON_HO_FAILED) {
status = target_if_vdev_mgr_rsp_timer_stop(roam_event->psoc,
vdev_rsp, RSO_STOP_RESPONSE_BIT);
if (QDF_IS_STATUS_SUCCESS(status))
roam_event->rso_timer_stopped = true;
else
mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed",
roam_event->psoc->soc_objmgr.psoc_id,
roam_event->vdev_id);
} else if (roam_event->reason == ROAM_REASON_RSO_STATUS &&
roam_event->notif == CM_ROAM_NOTIF_HO_FAIL) {
mlme_debug("HO_FAIL happened, wait for HO_FAIL event vdev_id: %u",
roam_event->vdev_id);
}
return status;
}
#else
static inline QDF_STATUS
target_if_start_rso_stop_timer(struct wlan_objmgr_vdev *vdev)
{
return QDF_STATUS_E_NOSUPPORT;
}
#endif
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
QDF_STATUS
target_if_cm_send_rso_stop_failure_rsp(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id)
{
struct wlan_cm_roam_rx_ops *roam_rx_ops;
struct roam_offload_roam_event roam_event = {0};
roam_event.vdev_id = vdev_id;
roam_event.psoc = psoc;
roam_event.reason = ROAM_REASON_RSO_STATUS;
roam_event.notif = CM_ROAM_NOTIF_SCAN_MODE_FAIL;
roam_event.rso_timer_stopped = true;
roam_rx_ops = target_if_cm_get_roam_rx_ops(psoc);
if (!roam_rx_ops || !roam_rx_ops->roam_event_rx) {
target_if_err("No valid roam rx ops");
return QDF_STATUS_E_INVAL;
}
roam_rx_ops->roam_event_rx(&roam_event);
return QDF_STATUS_SUCCESS;
}
#endif
static QDF_STATUS
target_if_cm_roam_abort_rso_stop_timer(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id)
{
struct vdev_response_timer *vdev_rsp;
struct wlan_lmac_if_mlme_rx_ops *rx_ops;
rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
if (!rx_ops || !rx_ops->vdev_mgr_start_response) {
mlme_err("No Rx Ops");
return QDF_STATUS_E_INVAL;
}
vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, vdev_id);
if (!vdev_rsp) {
mlme_err("vdev response timer is null VDEV_%d PSOC_%d",
vdev_id, wlan_psoc_get_id(psoc));
return QDF_STATUS_E_INVAL;
}
return target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp,
RSO_STOP_RESPONSE_BIT);
}
/**
* target_if_cm_roam_send_stop() - Send roam stop related commands
* to wmi
@@ -1108,6 +1246,8 @@ target_if_cm_roam_send_stop(struct wlan_objmgr_vdev *vdev,
struct wlan_roam_stop_config *req)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS timer_start_status = QDF_STATUS_E_NOSUPPORT;
QDF_STATUS rso_stop_status = QDF_STATUS_E_INVAL;
wmi_unified_t wmi_handle;
struct wlan_objmgr_psoc *psoc;
uint8_t vdev_id;
@@ -1116,6 +1256,12 @@ target_if_cm_roam_send_stop(struct wlan_objmgr_vdev *vdev,
if (!wmi_handle)
return QDF_STATUS_E_FAILURE;
psoc = wlan_vdev_get_psoc(vdev);
if (!psoc) {
target_if_err("psoc handle is NULL");
return QDF_STATUS_E_INVAL;
}
/* Send 11k offload disable command to FW as part of RSO Stop */
status = target_if_cm_roam_offload_11k_params(wmi_handle,
&req->roam_11k_params);
@@ -1133,15 +1279,12 @@ target_if_cm_roam_send_stop(struct wlan_objmgr_vdev *vdev,
goto end;
}
psoc = wlan_vdev_get_psoc(vdev);
if (!psoc) {
target_if_err("psoc handle is NULL");
return QDF_STATUS_E_INVAL;
}
if (req->start_rso_stop_timer)
timer_start_status = target_if_start_rso_stop_timer(vdev);
status = target_if_cm_roam_scan_offload_mode(wmi_handle,
&req->rso_config);
if (QDF_IS_STATUS_ERROR(status)) {
rso_stop_status = target_if_cm_roam_scan_offload_mode(wmi_handle,
&req->rso_config);
if (QDF_IS_STATUS_ERROR(rso_stop_status)) {
target_if_err("vdev:%d Send RSO mode cmd failed",
req->rso_config.vdev_id);
goto end;
@@ -1181,13 +1324,32 @@ target_if_cm_roam_send_stop(struct wlan_objmgr_vdev *vdev,
* disconnect
*/
vdev_id = wlan_vdev_get_id(vdev);
if (req->rso_config.rso_mode_info.roam_scan_mode == WMI_ROAM_SCAN_MODE_NONE) {
if (req->rso_config.rso_mode_info.roam_scan_mode ==
WMI_ROAM_SCAN_MODE_NONE) {
req->roam_triggers.vdev_id = vdev_id;
req->roam_triggers.trigger_bitmap = 0;
req->roam_triggers.roam_scan_scheme_bitmap = 0;
target_if_cm_roam_triggers(vdev, &req->roam_triggers);
}
end:
if (QDF_IS_STATUS_SUCCESS(timer_start_status)) {
if (QDF_IS_STATUS_SUCCESS(rso_stop_status)) {
/*
* Started the timer and send RSO stop to firmware
* successfully. Wait for RSO STOP response from fw.
*/
req->send_rso_stop_resp = false;
} else {
/*
* Started the timer and but failed to send RSO stop to
* firmware. Stop the timer and let the response be
* poseted from CM.
*/
target_if_cm_roam_abort_rso_stop_timer(psoc,
wlan_vdev_get_id(vdev));
}
}
return status;
}