diff --git a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h index 328d3edf40f4..d919392c992d 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h @@ -1722,6 +1722,7 @@ struct fw_scan_channels { * @sae_single_pmk_feature_enabled: Contains value of ini * sae_single_pmk_feature_enabled * @enable_ft_over_ds: Flag to enable/disable FT-over-DS + * @roam_ho_delay_config: Roam HO delay value */ struct wlan_mlme_lfr_cfg { bool mawc_roam_enabled; @@ -1840,6 +1841,7 @@ struct wlan_mlme_lfr_cfg { bool sae_single_pmk_feature_enabled; #endif bool enable_ft_over_ds; + uint16_t roam_ho_delay_config; }; /** diff --git a/components/target_if/connection_mgr/src/target_if_cm_roam_offload.c b/components/target_if/connection_mgr/src/target_if_cm_roam_offload.c index f2f046b22c48..8ca5ec7aae17 100644 --- a/components/target_if/connection_mgr/src/target_if_cm_roam_offload.c +++ b/components/target_if/connection_mgr/src/target_if_cm_roam_offload.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2020, The Linux Foundation. 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 @@ -130,11 +131,44 @@ target_if_cm_roam_rt_stats_config(struct wlan_objmgr_vdev *vdev, return status; } +/** + * target_if_cm_roam_ho_delay_config() - Send roam HO delay value to wmi + * @vdev: vdev object + * @vdev_id: vdev id + * @roam_ho_delay: roam hand-off delay value + * + * Return: QDF_STATUS + */ +static QDF_STATUS +target_if_cm_roam_ho_delay_config(struct wlan_objmgr_vdev *vdev, + uint8_t vdev_id, uint16_t roam_ho_delay) +{ + QDF_STATUS status = QDF_STATUS_E_FAILURE; + wmi_unified_t wmi_handle; + + wmi_handle = target_if_cm_roam_get_wmi_handle_from_vdev(vdev); + if (!wmi_handle) + return status; + + status = target_if_roam_set_param( + wmi_handle, + vdev_id, + WMI_ROAM_PARAM_ROAM_HO_DELAY_RUNTIME_CONFIG, + roam_ho_delay); + + if (QDF_IS_STATUS_ERROR(status)) + target_if_err("Failed to set " + "WMI_ROAM_PARAM_ROAM_HO_DELAY_RUNTIME_CONFIG"); + + return status; +} + static void target_if_cm_roam_register_lfr3_ops(struct wlan_cm_roam_tx_ops *tx_ops) { tx_ops->send_vdev_set_pcl_cmd = target_if_cm_roam_send_vdev_set_pcl_cmd; tx_ops->send_roam_rt_stats_config = target_if_cm_roam_rt_stats_config; + tx_ops->send_roam_ho_delay_config = target_if_cm_roam_ho_delay_config; } #else static inline void @@ -147,6 +181,13 @@ target_if_cm_roam_rt_stats_config(struct wlan_objmgr_vdev *vdev, { return QDF_STATUS_E_NOSUPPORT; } + +static QDF_STATUS +target_if_cm_roam_ho_delay_config(struct wlan_objmgr_vdev *vdev, + uint8_t vdev_id, uint16_t roam_ho_delay) +{ + return QDF_STATUS_E_NOSUPPORT; +} #endif /** @@ -1032,6 +1073,10 @@ target_if_cm_roam_send_start(struct wlan_objmgr_vdev *vdev, if (req->wlan_roam_rt_stats_config) target_if_cm_roam_rt_stats_config(vdev, vdev_id, req->wlan_roam_rt_stats_config); + + if (req->wlan_roam_ho_delay_config) + target_if_cm_roam_ho_delay_config( + vdev, vdev_id, req->wlan_roam_ho_delay_config); /* add other wmi commands */ end: return status; @@ -1254,6 +1299,11 @@ target_if_cm_roam_send_update_config(struct wlan_objmgr_vdev *vdev, target_if_cm_roam_rt_stats_config( vdev, vdev_id, req->wlan_roam_rt_stats_config); + + if (req->wlan_roam_ho_delay_config) + target_if_cm_roam_ho_delay_config( + vdev, vdev_id, + req->wlan_roam_ho_delay_config); } end: return status; diff --git a/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c b/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c index d1618afbcce8..2fa20d946d65 100644 --- a/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c +++ b/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c @@ -272,6 +272,21 @@ cm_roam_send_rt_stats_config(struct wlan_objmgr_psoc *psoc, return status; } + +QDF_STATUS +cm_roam_send_ho_delay_config(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, uint16_t param_value) +{ + QDF_STATUS status; + + wlan_cm_roam_set_ho_delay_config(psoc, param_value); + status = wlan_cm_tgt_send_roam_ho_delay_config(psoc, + vdev_id, param_value); + if (QDF_IS_STATUS_ERROR(status)) + mlme_debug("fail to send roam HO delay config"); + + return status; +} #else static inline void cm_roam_reason_vsie(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, @@ -526,6 +541,9 @@ cm_roam_start_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, start_req->wlan_roam_rt_stats_config = wlan_cm_get_roam_rt_stats(psoc, ROAM_RT_STATS_ENABLE); + start_req->wlan_roam_ho_delay_config = + wlan_cm_roam_get_ho_delay_config(psoc); + status = wlan_cm_tgt_send_roam_start_req(psoc, vdev_id, start_req); if (QDF_IS_STATUS_ERROR(status)) mlme_debug("fail to send roam start"); @@ -575,6 +593,9 @@ cm_roam_update_config_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, update_req->wlan_roam_rt_stats_config = wlan_cm_get_roam_rt_stats(psoc, ROAM_RT_STATS_ENABLE); + update_req->wlan_roam_ho_delay_config = + wlan_cm_roam_get_ho_delay_config(psoc); + status = wlan_cm_tgt_send_roam_update_req(psoc, vdev_id, update_req); if (QDF_IS_STATUS_ERROR(status)) mlme_debug("fail to send update config"); diff --git a/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.h b/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.h index e05eb0b8d1de..6fd45b0e987d 100644 --- a/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.h +++ b/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2020 The Linux Foundation. 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 @@ -114,6 +115,20 @@ cm_roam_fill_rssi_change_params(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, QDF_STATUS cm_roam_send_rt_stats_config(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, uint8_t param_value); + +/** + * cm_roam_send_ho_delay_config() - Send HO delay value to FW to delay + * hand-off (in msec) by the specified duration to receive pending rx frames + * from current BSS. + * @psoc: PSOC pointer + * @vdev_id: vdev id + * @param_value: HO delay value + * + * Return: QDF_STATUS + */ +QDF_STATUS +cm_roam_send_ho_delay_config(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, uint16_t param_value); #else static inline QDF_STATUS cm_roam_send_rt_stats_config(struct wlan_objmgr_psoc *psoc, @@ -121,6 +136,13 @@ cm_roam_send_rt_stats_config(struct wlan_objmgr_psoc *psoc, { return QDF_STATUS_E_NOSUPPORT; } + +static inline QDF_STATUS +cm_roam_send_ho_delay_config(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, uint16_t param_value) +{ + return QDF_STATUS_E_NOSUPPORT; +} #endif /** diff --git a/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_api.h b/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_api.h index 478d6a477160..6551c3b40193 100644 --- a/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_api.h +++ b/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_api.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2020, The Linux Foundation. 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 @@ -621,6 +622,26 @@ wlan_cm_update_roam_rt_stats(struct wlan_objmgr_psoc *psoc, uint8_t wlan_cm_get_roam_rt_stats(struct wlan_objmgr_psoc *psoc, enum roam_rt_stats_params stats); + +/** + * wlan_cm_roam_set_ho_delay_config() - Set roam hand-off delay + * @psoc: PSOC pointer + * @roam_ho_delay: vendor configured roam HO delay value + * + * Return: none + */ +void +wlan_cm_roam_set_ho_delay_config(struct wlan_objmgr_psoc *psoc, + uint16_t roam_ho_delay); + +/** + * wlan_cm_roam_get_ho_delay_config() - Get roam hand-off delay + * @psoc: PSOC pointer + * + * Return: Roam HO delay value + */ +uint16_t +wlan_cm_roam_get_ho_delay_config(struct wlan_objmgr_psoc *psoc); #else static inline void wlan_cm_roam_activate_pcl_per_vdev(struct wlan_objmgr_psoc *psoc, @@ -737,5 +758,11 @@ wlan_cm_get_roam_rt_stats(struct wlan_objmgr_psoc *psoc, { return 0; } + +static inline uint16_t +wlan_cm_roam_get_ho_delay_config(struct wlan_objmgr_psoc *psoc) +{ + return 0; +} #endif /* FEATURE_ROAM_OFFLOAD */ #endif /* WLAN_CM_ROAM_API_H__ */ diff --git a/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_public_struct.h b/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_public_struct.h index 058b92f4f5db..f0d99dbb487e 100644 --- a/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_public_struct.h +++ b/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_public_struct.h @@ -1168,6 +1168,7 @@ enum roam_rt_stats_params { * @disconnect_params: disconnect params * @idle_params: idle params * @wlan_roam_rt_stats_config: roam events stats config + * @wlan_roam_ho_delay_config: roam HO delay value */ struct wlan_roam_start_config { struct wlan_roam_offload_scan_rssi_params rssi_params; @@ -1187,6 +1188,7 @@ struct wlan_roam_start_config { struct wlan_roam_disconnect_params disconnect_params; struct wlan_roam_idle_params idle_params; uint8_t wlan_roam_rt_stats_config; + uint16_t wlan_roam_ho_delay_config; /* other wmi cmd structures */ }; @@ -1232,6 +1234,7 @@ struct wlan_roam_stop_config { * @idle_params: idle params * @roam_triggers: roam triggers parameters * @wlan_roam_rt_stats_config: roam events stats config + * @wlan_roam_ho_delay_config: roam HO delay value */ struct wlan_roam_update_config { struct wlan_roam_beacon_miss_cnt beacon_miss_cnt; @@ -1246,6 +1249,7 @@ struct wlan_roam_update_config { struct wlan_roam_idle_params idle_params; struct wlan_roam_triggers roam_triggers; uint8_t wlan_roam_rt_stats_config; + uint16_t wlan_roam_ho_delay_config; }; #if defined(WLAN_FEATURE_HOST_ROAM) || defined(WLAN_FEATURE_ROAM_OFFLOAD) @@ -1371,6 +1375,7 @@ struct set_pcl_req { * @send_roam_abort: send roam abort * @send_roam_disable_config: send roam disable config * @send_roam_rt_stats_config: Send roam events vendor command param value to FW + * @send_roam_ho_delay_config: Send roam Hand-off delay value to FW */ struct wlan_cm_roam_tx_ops { QDF_STATUS (*send_vdev_set_pcl_cmd)(struct wlan_objmgr_vdev *vdev, @@ -1398,6 +1403,9 @@ struct wlan_cm_roam_tx_ops { #ifdef WLAN_FEATURE_ROAM_OFFLOAD QDF_STATUS (*send_roam_rt_stats_config)(struct wlan_objmgr_vdev *vdev, uint8_t vdev_id, uint8_t value); + QDF_STATUS (*send_roam_ho_delay_config)(struct wlan_objmgr_vdev *vdev, + uint8_t vdev_id, + uint16_t value); #endif }; diff --git a/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_ucfg_api.h b/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_ucfg_api.h index 6272fb622c2f..7bc847bd699f 100644 --- a/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_ucfg_api.h +++ b/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_ucfg_api.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2020, The Linux Foundation. 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 @@ -184,6 +185,18 @@ ucfg_cm_get_roam_rt_stats(struct wlan_objmgr_psoc *psoc, QDF_STATUS ucfg_cm_roam_send_rt_stats_config(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id, uint8_t param_value); + +/** + * ucfg_cm_roam_send_ho_delay_config() - Send the HO delay value to Firmware + * @pdev: Pointer to pdev + * @vdev_id: vdev id + * @param_value: Value will be from range 20 to 1000 in msec. + * + * Return: QDF_STATUS + */ +QDF_STATUS +ucfg_cm_roam_send_ho_delay_config(struct wlan_objmgr_pdev *pdev, + uint8_t vdev_id, uint16_t param_value); #else static inline QDF_STATUS ucfg_cm_update_roam_scan_scheme_bitmap(struct wlan_objmgr_psoc *psoc, @@ -213,4 +226,11 @@ ucfg_cm_roam_send_rt_stats_config(struct wlan_objmgr_pdev *pdev, { return QDF_STATUS_SUCCESS; } + +static inline QDF_STATUS +ucfg_cm_roam_send_ho_delay_config(struct wlan_objmgr_pdev *pdev, + uint8_t vdev_id, uint16_t param_value) +{ + return QDF_STATUS_SUCCESS; +} #endif diff --git a/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_tgt_if_tx_api.h b/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_tgt_if_tx_api.h index f814c4f6b626..781b1f8a604c 100644 --- a/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_tgt_if_tx_api.h +++ b/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_tgt_if_tx_api.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2020, The Linux Foundation. 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 @@ -47,6 +48,19 @@ wlan_cm_roam_send_set_vdev_pcl(struct wlan_objmgr_psoc *psoc, */ QDF_STATUS wlan_cm_tgt_send_roam_rt_stats_config(struct wlan_objmgr_psoc *psoc, struct roam_disable_cfg *req); + +/** + * wlan_cm_tgt_send_roam_ho_delay_config() - Send roam HO delay config command + * to FW + * @psoc: psoc pointer + * @vdev_id: vdev id + * @roam_ho_delay: roam hand-off delay value + * + * Return: QDF_STATUS + */ +QDF_STATUS wlan_cm_tgt_send_roam_ho_delay_config(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, + uint16_t roam_ho_delay); #else static inline QDF_STATUS wlan_cm_roam_send_set_vdev_pcl(struct wlan_objmgr_psoc *psoc, @@ -61,6 +75,13 @@ wlan_cm_tgt_send_roam_rt_stats_config(struct wlan_objmgr_psoc *psoc, { return QDF_STATUS_E_FAILURE; } + +static inline QDF_STATUS +wlan_cm_tgt_send_roam_ho_delay_config(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, uint16_t roam_ho_delay) +{ + return QDF_STATUS_E_FAILURE; +} #endif /* WLAN_FEATURE_ROAM_OFFLOAD */ #if defined(WLAN_FEATURE_HOST_ROAM) || defined(WLAN_FEATURE_ROAM_OFFLOAD) diff --git a/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c b/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c index b542d4d2b24f..84f8eba88ffc 100644 --- a/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c +++ b/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c @@ -889,4 +889,31 @@ uint8_t wlan_cm_get_roam_rt_stats(struct wlan_objmgr_psoc *psoc, return rstats_value; } + +void +wlan_cm_roam_set_ho_delay_config(struct wlan_objmgr_psoc *psoc, + uint16_t roam_ho_delay) +{ + struct wlan_mlme_psoc_ext_obj *mlme_obj; + + mlme_obj = mlme_get_psoc_ext_obj(psoc); + if (!mlme_obj) + return; + + mlme_obj->cfg.lfr.roam_ho_delay_config = roam_ho_delay; +} + +uint16_t +wlan_cm_roam_get_ho_delay_config(struct wlan_objmgr_psoc *psoc) +{ + struct wlan_mlme_psoc_ext_obj *mlme_obj; + + mlme_obj = mlme_get_psoc_ext_obj(psoc); + if (!mlme_obj) { + mlme_legacy_err("Failed to get MLME Obj"); + return 0; + } + + return mlme_obj->cfg.lfr.roam_ho_delay_config; +} #endif diff --git a/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_ucfg_api.c b/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_ucfg_api.c index 630deff30cf4..d2709aa2c136 100644 --- a/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_ucfg_api.c +++ b/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_ucfg_api.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2020, The Linux Foundation. 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 @@ -137,4 +138,13 @@ ucfg_cm_roam_send_rt_stats_config(struct wlan_objmgr_pdev *pdev, return cm_roam_send_rt_stats_config(psoc, vdev_id, param_value); } + +QDF_STATUS +ucfg_cm_roam_send_ho_delay_config(struct wlan_objmgr_pdev *pdev, + uint8_t vdev_id, uint16_t param_value) +{ + struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); + + return cm_roam_send_ho_delay_config(psoc, vdev_id, param_value); +} #endif /* WLAN_FEATURE_ROAM_OFFLOAD */ diff --git a/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_tgt_if_tx_api.c b/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_tgt_if_tx_api.c index 7b556f9b0d9c..fe50d993fa2a 100644 --- a/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_tgt_if_tx_api.c +++ b/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_tgt_if_tx_api.c @@ -202,6 +202,37 @@ QDF_STATUS wlan_cm_tgt_send_roam_rt_stats_config(struct wlan_objmgr_psoc *psoc, return status; } + +QDF_STATUS wlan_cm_tgt_send_roam_ho_delay_config(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, + uint16_t roam_ho_delay) +{ + QDF_STATUS status; + struct wlan_cm_roam_tx_ops *roam_tx_ops; + struct wlan_objmgr_vdev *vdev; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, + WLAN_MLME_NB_ID); + if (!vdev) + return QDF_STATUS_E_INVAL; + + roam_tx_ops = wlan_cm_roam_get_tx_ops_from_vdev(vdev); + if (!roam_tx_ops || !roam_tx_ops->send_roam_ho_delay_config) { + mlme_err("vdev %d send_roam_ho_delay_config is NULL", vdev_id); + wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); + return QDF_STATUS_E_INVAL; + } + + status = roam_tx_ops->send_roam_ho_delay_config(vdev, vdev_id, + roam_ho_delay); + if (QDF_IS_STATUS_ERROR(status)) + mlme_debug("vdev %d fail to send roam HO delay config", + vdev_id); + + wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); + + return status; +} #endif #if defined(WLAN_FEATURE_HOST_ROAM) || defined(WLAN_FEATURE_ROAM_OFFLOAD) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 08b6ed22fc77..486cd4f52528 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -4645,6 +4645,7 @@ roam_control_policy[QCA_ATTR_ROAM_CONTROL_MAX + 1] = { .type = NLA_U32}, [QCA_ATTR_ROAM_CONTROL_USER_REASON] = {.type = NLA_U32}, [QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS] = {.type = NLA_U32}, + [QCA_ATTR_ROAM_CONTROL_HO_DELAY_FOR_RX] = {.type = NLA_U16}, }; /** @@ -5036,6 +5037,10 @@ hdd_send_roam_scan_period_to_sme(struct hdd_context *hdd_ctx, return status; } +/* Roam Hand-off delay range is 20 to 1000 msec */ +#define MIN_ROAM_HO_DELAY 20 +#define MAX_ROAM_HO_DELAY 1000 + /** * hdd_set_roam_with_control_config() - Set roam control configuration * @hdd_ctx: HDD context @@ -5229,6 +5234,22 @@ hdd_set_roam_with_control_config(struct hdd_context *hdd_ctx, sme_send_vendor_btm_params(hdd_ctx->mac_handle, vdev_id); } + attr = tb2[QCA_ATTR_ROAM_CONTROL_HO_DELAY_FOR_RX]; + if (attr) { + value = nla_get_u16(attr); + if (value < MIN_ROAM_HO_DELAY || value > MAX_ROAM_HO_DELAY) { + hdd_err("Invalid roam HO delay value: %d", value); + return -EINVAL; + } + + hdd_debug("Received roam HO delay value: %d", value); + + status = ucfg_cm_roam_send_ho_delay_config(hdd_ctx->pdev, + vdev_id, value); + if (QDF_IS_STATUS_ERROR(status)) + hdd_err("failed to set hand-off delay"); + } + return qdf_status_to_os_return(status); }