diff --git a/components/dp/dispatcher/inc/wlan_dp_ucfg_api.h b/components/dp/dispatcher/inc/wlan_dp_ucfg_api.h index e24cd95c38..7974324d76 100644 --- a/components/dp/dispatcher/inc/wlan_dp_ucfg_api.h +++ b/components/dp/dispatcher/inc/wlan_dp_ucfg_api.h @@ -44,12 +44,21 @@ #ifdef WLAN_NUD_TRACKING bool ucfg_dp_is_roam_after_nud_enabled(struct wlan_objmgr_psoc *psoc); + +bool +ucfg_dp_is_disconect_after_roam_fail(struct wlan_objmgr_psoc *psoc); #else static inline bool ucfg_dp_is_roam_after_nud_enabled(struct wlan_objmgr_psoc *psoc) { return false; } + +static inline bool +ucfg_dp_is_disconect_after_roam_fail(struct wlan_objmgr_psoc *psoc) +{ + return false; +} #endif /** diff --git a/components/dp/dispatcher/src/wlan_dp_ucfg_api.c b/components/dp/dispatcher/src/wlan_dp_ucfg_api.c index 8d27fd9277..f841f92a7b 100644 --- a/components/dp/dispatcher/src/wlan_dp_ucfg_api.c +++ b/components/dp/dispatcher/src/wlan_dp_ucfg_api.c @@ -1351,6 +1351,18 @@ ucfg_dp_is_roam_after_nud_enabled(struct wlan_objmgr_psoc *psoc) return false; } + +bool +ucfg_dp_is_disconect_after_roam_fail(struct wlan_objmgr_psoc *psoc) +{ + struct wlan_dp_psoc_context *dp_ctx = dp_psoc_get_priv(psoc); + struct wlan_dp_psoc_cfg *dp_cfg = &dp_ctx->dp_cfg; + + if (dp_cfg->enable_nud_tracking == DP_DISCONNECT_AFTER_ROAM_FAIL) + return true; + + return false; +} #endif int ucfg_dp_bbm_context_init(struct wlan_objmgr_psoc *psoc) diff --git a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h index 8d3a0b1f99..6e0b97fb08 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h @@ -1969,6 +1969,8 @@ struct fw_scan_channels { * are already scanned as part of partial scan. * @roam_full_scan_6ghz_on_disc: Include the 6 GHz channels in roam full scan * only on prior discovery of any 6 GHz support in the environment. + * @disconnect_on_nud_roam_invoke_fail: indicate whether disconnect ap when + * roam invoke fail on nud. */ struct wlan_mlme_lfr_cfg { bool mawc_roam_enabled; @@ -2096,6 +2098,7 @@ struct wlan_mlme_lfr_cfg { uint16_t roam_ho_delay_config; uint8_t exclude_rm_partial_scan_freq; uint8_t roam_full_scan_6ghz_on_disc; + bool disconnect_on_nud_roam_invoke_fail; }; /** diff --git a/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_fw_sync.c b/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_fw_sync.c index a548828dc8..a55d32dd60 100644 --- a/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_fw_sync.c +++ b/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_fw_sync.c @@ -1190,6 +1190,55 @@ end: return status; } +QDF_STATUS +cm_disconnect_roam_abort_fail(struct wlan_objmgr_vdev *vdev, + enum wlan_cm_source source, + struct qdf_mac_addr *bssid, + wlan_cm_id cm_id) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct wlan_mlme_psoc_ext_obj *mlme_obj; + bool nud_disconnect; + struct wlan_objmgr_psoc *psoc; + uint8_t vdev_id = wlan_vdev_get_id(vdev); + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + mlme_err(CM_PREFIX_FMT "psoc not found", + CM_PREFIX_REF(vdev_id, cm_id)); + return QDF_STATUS_E_INVAL; + } + + mlme_obj = mlme_get_psoc_ext_obj(psoc); + if (!mlme_obj) + return QDF_STATUS_E_NULL_VALUE; + + nud_disconnect = mlme_obj->cfg.lfr.disconnect_on_nud_roam_invoke_fail; + mlme_debug(CM_PREFIX_FMT "disconnect on NUD %d, source %d bssid " QDF_MAC_ADDR_FMT, + CM_PREFIX_REF(vdev_id, cm_id), + nud_disconnect, source, QDF_MAC_ADDR_REF(bssid)); + + /* + * If reassoc MAC from user space is broadcast MAC as: + * "wpa_cli DRIVER FASTREASSOC ff:ff:ff:ff:ff:ff 0", + * user space invoked roaming candidate selection will base on firmware + * score algorithm, current connection will be kept if current AP has + * highest score. It is requirement from customer which can avoid + * ping-pong roaming. + */ + if (qdf_is_macaddr_broadcast(bssid)) + return status; + + if (source == CM_ROAMING_HOST || + (source == CM_ROAMING_NUD_FAILURE && nud_disconnect) || + source == CM_ROAMING_LINK_REMOVAL) + status = mlo_disconnect(vdev, CM_ROAM_DISCONNECT, + REASON_USER_TRIGGERED_ROAM_FAILURE, + NULL); + + return status; +} + QDF_STATUS cm_fw_roam_invoke_fail(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id) { @@ -1204,7 +1253,6 @@ QDF_STATUS cm_fw_roam_invoke_fail(struct wlan_objmgr_psoc *psoc, 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; @@ -1229,26 +1277,10 @@ QDF_STATUS cm_fw_roam_invoke_fail(struct wlan_objmgr_psoc *psoc, status = cm_sm_deliver_event(vdev, WLAN_CM_SM_EV_ROAM_INVOKE_FAIL, sizeof(wlan_cm_id), &cm_id); - if (QDF_IS_STATUS_ERROR(status)) cm_remove_cmd(cm_ctx, &cm_id); - /* - * If reassoc MAC from user space is broadcast MAC as: - * "wpa_cli DRIVER FASTREASSOC ff:ff:ff:ff:ff:ff 0", - * user space invoked roaming candidate selection will base on firmware - * score algorithm, current connection will be kept if current AP has - * highest score. It is requirement from customer which can avoid - * ping-pong roaming. - */ - if (qdf_is_macaddr_broadcast(&bssid)) - mlme_debug("Keep current connection"); - else if (source == CM_ROAMING_HOST || - source == CM_ROAMING_NUD_FAILURE || - source == CM_ROAMING_LINK_REMOVAL) - status = mlo_disconnect(vdev, CM_ROAM_DISCONNECT, - REASON_USER_TRIGGERED_ROAM_FAILURE, - NULL); + cm_disconnect_roam_abort_fail(vdev, source, &bssid, cm_id); error: wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID); return status; diff --git a/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_i.h b/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_i.h index f5d5b78de2..7e89ef3bd7 100644 --- a/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_i.h +++ b/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_i.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 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 @@ -156,6 +156,21 @@ cm_fw_roam_sync_propagation(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, void cm_fw_ho_fail_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, struct qdf_mac_addr bssid); +/** + * cm_disconnect_roam_abort_fail() - disconnect when roam abort or fail + * @vdev: vdev object + * @source: the source of trigger roaming + * @bssid: bssid pointer + * @cm_id: CM command id + * + * Return: QDF_STATUS + */ +QDF_STATUS +cm_disconnect_roam_abort_fail(struct wlan_objmgr_vdev *vdev, + enum wlan_cm_source source, + struct qdf_mac_addr *bssid, + wlan_cm_id cm_id); + /** * cm_fw_roam_invoke_fail() - Post roam invoke fail to CM SM * @psoc: psoc pointer diff --git a/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload_event.c b/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload_event.c index 8a2d7da49c..6930c4e58e 100644 --- a/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload_event.c +++ b/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload_event.c @@ -91,15 +91,25 @@ QDF_STATUS cm_abort_fw_roam(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id) { QDF_STATUS status; + enum wlan_cm_source source = CM_SOURCE_INVALID; + struct cm_roam_req *roam_req; + struct qdf_mac_addr bssid = QDF_MAC_ADDR_ZERO_INIT; + + roam_req = cm_get_first_roam_command(cm_ctx->vdev); + if (roam_req) { + source = roam_req->req.source; + bssid = roam_req->req.bssid; + } mlme_cm_osif_roam_abort_ind(cm_ctx->vdev); 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); + cm_disconnect_roam_abort_fail(cm_ctx->vdev, source, &bssid, cm_id); + return status; } diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index e192f8a790..d33d1c85d8 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -51,6 +51,7 @@ #include "hdd_dp_cfg.h" #include #include "wlan_hdd_object_manager.h" +#include "wlan_dp_ucfg_api.h" #ifndef WLAN_MAC_ADDR_UPDATE_DISABLE /** @@ -927,6 +928,7 @@ QDF_STATUS hdd_set_sme_config(struct hdd_context *hdd_ctx) mac_handle_t mac_handle = hdd_ctx->mac_handle; bool roam_scan_enabled; bool enable_dfs_scan = true; + bool disconnect_nud; uint32_t channel_bonding_mode; #ifdef FEATURE_WLAN_ESE @@ -1008,6 +1010,9 @@ QDF_STATUS hdd_set_sme_config(struct hdd_context *hdd_ctx) STA_ROAM_POLICY_DFS_ENABLED; mlme_obj->cfg.lfr.rso_user_config.policy_params.skip_unsafe_channels = 0; + disconnect_nud = ucfg_dp_is_disconect_after_roam_fail(hdd_ctx->psoc); + mlme_obj->cfg.lfr.disconnect_on_nud_roam_invoke_fail = disconnect_nud; + status = hdd_set_sme_cfgs_related_to_mlme(hdd_ctx, sme_config); if (!QDF_IS_STATUS_SUCCESS(status)) hdd_err("hdd_set_sme_cfgs_related_to_mlme() fail: %d", status);