diff --git a/components/mlme/core/src/wlan_mlme_main.c b/components/mlme/core/src/wlan_mlme_main.c index baee6f56bb..6969d77a2f 100644 --- a/components/mlme/core/src/wlan_mlme_main.c +++ b/components/mlme/core/src/wlan_mlme_main.c @@ -1441,6 +1441,8 @@ static void mlme_init_roam_offload_cfg(struct wlan_objmgr_psoc *psoc, { lfr->lfr3_roaming_offload = cfg_get(psoc, CFG_LFR3_ROAMING_OFFLOAD); + lfr->lfr3_dual_sta_roaming_enabled = + cfg_get(psoc, CFG_ENABLE_DUAL_STA_ROAM_OFFLOAD); lfr->enable_self_bss_roam = cfg_get(psoc, CFG_LFR3_ENABLE_SELF_BSS_ROAM); lfr->enable_roam_reason_vsie = cfg_get(psoc, CFG_ENABLE_ROAM_REASON_VSIE); diff --git a/components/mlme/dispatcher/inc/cfg_mlme_lfr.h b/components/mlme/dispatcher/inc/cfg_mlme_lfr.h index a74fce3cbb..001c9f55bc 100644 --- a/components/mlme/dispatcher/inc/cfg_mlme_lfr.h +++ b/components/mlme/dispatcher/inc/cfg_mlme_lfr.h @@ -2439,6 +2439,36 @@ CFG_VALUE_OR_DEFAULT, \ "disable roam on STA iface if one of the iface mentioned in default is in connected state") +/* + * + * enable_dual_sta_roam_offload - Enable roaming offload on both interfaces + * for STA + STA + * @Min: 0 - Dual STA Roam offload Disabled + * @Max: 1 - Dual STA Roam offload Enabled + * @Default: 1 + * + * Enabling this ini will: + * a) Enforce the STA + STA connection be DBS if the hw is capable. + * b) Enable Roam Scan Offload on both the STA vdev. + * c) Enable firmware to support sequential roaming on both STA vdev + * if the firmware is capable of dual sta roaming. + * + * Related: None. + * + * Supported Feature: ROAM + * + * Usage: External + * + * + */ +#define CFG_ENABLE_DUAL_STA_ROAM_OFFLOAD CFG_INI_UINT( \ + "enable_dual_sta_roam_offload", \ + false, \ + true, \ + true, \ + CFG_VALUE_OR_DEFAULT, \ + "Enable roam on both STA vdev") + #define ROAM_OFFLOAD_ALL \ CFG(CFG_LFR3_ROAMING_OFFLOAD) \ CFG(CFG_LFR3_ENABLE_SELF_BSS_ROAM) \ @@ -2451,6 +2481,7 @@ CFG(CFG_LFR_IDLE_ROAM_BAND) \ CFG(CFG_ROAM_TRIGGER_BITMAP) \ CFG(CFG_STA_DISABLE_ROAM) \ + CFG(CFG_ENABLE_DUAL_STA_ROAM_OFFLOAD) \ #else #define ROAM_OFFLOAD_ALL diff --git a/components/mlme/dispatcher/inc/wlan_mlme_api.h b/components/mlme/dispatcher/inc/wlan_mlme_api.h index 7179ec63fa..afba7bd03c 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_api.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_api.h @@ -812,6 +812,24 @@ QDF_STATUS wlan_mlme_get_bigtk_support(struct wlan_objmgr_psoc *psoc, */ bool wlan_mlme_get_host_scan_abort_support(struct wlan_objmgr_psoc *psoc); +/** + * wlan_mlme_get_peer_create_conf_support - Get if the firmware supports + * peer create confirm event + * @psoc: PSOC object pointer + * + * Return: True if capability is supported, else False + */ +bool wlan_mlme_get_peer_create_conf_support(struct wlan_objmgr_psoc *psoc); + +/** + * wlan_mlme_get_dual_sta_roam_support - Get support for dual sta roaming + * feature + * @psoc: PSOC object pointer + * + * Return: True if capability is supported, else False + */ +bool wlan_mlme_get_dual_sta_roam_support(struct wlan_objmgr_psoc *psoc); + /** * wlan_mlme_get_oce_sap_enabled_info() - Get the OCE feature enable * info for SAP @@ -2521,4 +2539,23 @@ uint32_t wlan_mlme_get_roaming_triggers(struct wlan_objmgr_psoc *psoc) QDF_STATUS wlan_mlme_get_dfs_chan_ageout_time(struct wlan_objmgr_psoc *psoc, uint8_t *dfs_chan_ageout_time); + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +/** + * wlan_mlme_get_dual_sta_roaming_enabled - API to get if the dual sta + * roaming support is enabled. + * @psoc: Pointer to global psoc object + * + * Return: True if dual sta roaming feature is enabled else return false + */ +bool +wlan_mlme_get_dual_sta_roaming_enabled(struct wlan_objmgr_psoc *psoc); +#else +static inline bool +wlan_mlme_get_dual_sta_roaming_enabled(struct wlan_objmgr_psoc *psoc) +{ + return false; +} +#endif + #endif /* _WLAN_MLME_API_H_ */ diff --git a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h index 746a6ccee0..eb61c2f139 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h @@ -952,6 +952,8 @@ struct wlan_mlme_chain_cfg { * @bigtk_support: does the target support bigtk capability or not. * @stop_all_host_scan_support: Target capability that indicates if the target * supports stop all host scan request type. + * @peer_create_conf_support: Peer create confirmation command support + * @dual_sta_roam_fw_support: Firmware support for dual sta roaming feature * * Add all the mlme-tgt related capablities here, and the public API would fill * the related capability in the required mlme cfg structure. @@ -960,6 +962,8 @@ struct mlme_tgt_caps { bool data_stall_recovery_fw_support; bool bigtk_support; bool stop_all_host_scan_support; + bool peer_create_conf_support; + bool dual_sta_roam_fw_support; }; /** @@ -1140,6 +1144,8 @@ struct wlan_mlme_chainmask { * @bigtk_support: Whether BIGTK is supported or not * @stop_all_host_scan_support: Target capability that indicates if the target * supports stop all host scan request type. + * @peer_create_conf_support: Peer create confirmation command support + * @dual_sta_roam_fw_support: Firmware support for dual sta roaming feature */ struct wlan_mlme_generic { enum band_info band_capability; @@ -1178,6 +1184,8 @@ struct wlan_mlme_generic { uint8_t dfs_chan_ageout_time; bool bigtk_support; bool stop_all_host_scan_support; + bool peer_create_conf_support; + bool dual_sta_roam_fw_support; }; /* @@ -1452,6 +1460,8 @@ struct bss_load_trigger { * @mawc_roam_enabled: Enable/Disable MAWC during roaming * @enable_fast_roam_in_concurrency:Enable LFR roaming on STA during concurrency * @lfr3_roaming_offload: Enable/disable roam offload feature + * @lfr3_dual_sta_roaming_enabled: Enable/Disable dual sta roaming offload + * feature * @enable_self_bss_roam: enable roaming to connected BSSID * @enable_disconnect_roam_offload: enable disassoc/deauth roam scan. * @enable_idle_roam: flag to enable/disable idle roam in fw @@ -1563,6 +1573,7 @@ struct wlan_mlme_lfr_cfg { bool enable_fast_roam_in_concurrency; #ifdef WLAN_FEATURE_ROAM_OFFLOAD bool lfr3_roaming_offload; + bool lfr3_dual_sta_roaming_enabled; bool enable_self_bss_roam; bool enable_disconnect_roam_offload; bool enable_idle_roam; diff --git a/components/mlme/dispatcher/src/wlan_mlme_api.c b/components/mlme/dispatcher/src/wlan_mlme_api.c index 76b2a3ab9a..f6e407317c 100644 --- a/components/mlme/dispatcher/src/wlan_mlme_api.c +++ b/components/mlme/dispatcher/src/wlan_mlme_api.c @@ -459,6 +459,11 @@ wlan_mlme_update_cfg_with_tgt_caps(struct wlan_objmgr_psoc *psoc, mlme_obj->cfg.gen.bigtk_support = tgt_caps->bigtk_support; mlme_obj->cfg.gen.stop_all_host_scan_support = tgt_caps->stop_all_host_scan_support; + mlme_obj->cfg.gen.peer_create_conf_support = + tgt_caps->peer_create_conf_support; + mlme_obj->cfg.gen.dual_sta_roam_fw_support = + tgt_caps->dual_sta_roam_fw_support; + } #ifdef WLAN_FEATURE_11AX @@ -2071,6 +2076,26 @@ bool wlan_mlme_get_host_scan_abort_support(struct wlan_objmgr_psoc *psoc) return mlme_obj->cfg.gen.stop_all_host_scan_support; } +bool wlan_mlme_get_peer_create_conf_support(struct wlan_objmgr_psoc *psoc) +{ + struct wlan_mlme_psoc_ext_obj *mlme_obj = mlme_get_psoc_ext_obj(psoc); + + if (!mlme_obj) + return false; + + return mlme_obj->cfg.gen.peer_create_conf_support; +} + +bool wlan_mlme_get_dual_sta_roam_support(struct wlan_objmgr_psoc *psoc) +{ + struct wlan_mlme_psoc_ext_obj *mlme_obj = mlme_get_psoc_ext_obj(psoc); + + if (!mlme_obj) + return false; + + return mlme_obj->cfg.gen.dual_sta_roam_fw_support; +} + QDF_STATUS wlan_mlme_get_oce_sta_enabled_info(struct wlan_objmgr_psoc *psoc, bool *value) { @@ -3902,3 +3927,25 @@ wlan_mlme_get_dfs_chan_ageout_time(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_SUCCESS; } + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +bool +wlan_mlme_get_dual_sta_roaming_enabled(struct wlan_objmgr_psoc *psoc) +{ + struct wlan_mlme_psoc_ext_obj *mlme_obj; + bool dual_sta_roaming_enabled; + + mlme_obj = mlme_get_psoc_ext_obj(psoc); + + if (!mlme_obj) + return cfg_default(CFG_ENABLE_DUAL_STA_ROAM_OFFLOAD); + + dual_sta_roaming_enabled = + mlme_obj->cfg.lfr.lfr3_roaming_offload && + mlme_obj->cfg.lfr.lfr3_dual_sta_roaming_enabled && + wlan_mlme_get_dual_sta_roam_support(psoc) && + policy_mgr_is_hw_dbs_capable(psoc); + + return dual_sta_roaming_enabled; +} +#endif diff --git a/components/wmi/inc/wmi_unified_roam_api.h b/components/wmi/inc/wmi_unified_roam_api.h index ce019082e2..ff86ef743f 100644 --- a/components/wmi/inc/wmi_unified_roam_api.h +++ b/components/wmi/inc/wmi_unified_roam_api.h @@ -218,6 +218,15 @@ QDF_STATUS wmi_unified_send_roam_preauth_status(wmi_unified_t wmi_handle, struct wmi_roam_auth_status_params *param); +/** + * wmi_unified_vdev_set_pcl_cmd - Send Vdev PCL command to fw + * @wmi_handle: WMI handle + * @params: Set VDEV pcl parameters + * + * Return: QDF_STATUS + */ +QDF_STATUS wmi_unified_vdev_set_pcl_cmd(wmi_unified_t wmi_handle, + struct set_pcl_cmd_params *params); #endif /* WLAN_FEATURE_ROAM_OFFLOAD */ /** diff --git a/components/wmi/inc/wmi_unified_roam_param.h b/components/wmi/inc/wmi_unified_roam_param.h index b7759265cc..26723df705 100644 --- a/components/wmi/inc/wmi_unified_roam_param.h +++ b/components/wmi/inc/wmi_unified_roam_param.h @@ -725,4 +725,13 @@ struct roam_triggers { uint32_t trigger_bitmap; }; +/** + * set_pcl_cmd_params - Set PCL command params + * @vdev_id: Vdev id + * @weight: PCL weight + */ +struct set_pcl_cmd_params { + uint8_t vdev_id; + struct wmi_pcl_chan_weights *weights; +}; #endif /* _WMI_UNIFIED_ROAM_PARAM_H_ */ diff --git a/components/wmi/src/wmi_unified_roam_api.c b/components/wmi/src/wmi_unified_roam_api.c index a102eaf2c4..e7e5fe67e6 100644 --- a/components/wmi/src/wmi_unified_roam_api.c +++ b/components/wmi/src/wmi_unified_roam_api.c @@ -163,6 +163,16 @@ wmi_unified_send_roam_preauth_status(wmi_unified_t wmi_handle, params); return QDF_STATUS_E_FAILURE; } + +QDF_STATUS wmi_unified_vdev_set_pcl_cmd(wmi_unified_t wmi_handle, + struct set_pcl_cmd_params *params) +{ + if (wmi_handle->ops->send_vdev_set_pcl_cmd) + return wmi_handle->ops->send_vdev_set_pcl_cmd(wmi_handle, + params); + + return QDF_STATUS_E_FAILURE; +} #endif /* WLAN_FEATURE_ROAM_OFFLOAD */ QDF_STATUS wmi_unified_roam_scan_offload_mode_cmd( diff --git a/components/wmi/src/wmi_unified_roam_tlv.c b/components/wmi/src/wmi_unified_roam_tlv.c index 1db412130d..7dcbd73c79 100644 --- a/components/wmi/src/wmi_unified_roam_tlv.c +++ b/components/wmi/src/wmi_unified_roam_tlv.c @@ -922,6 +922,73 @@ static QDF_STATUS send_roam_invoke_cmd_tlv(wmi_unified_t wmi_handle, return QDF_STATUS_SUCCESS; } +/** + * send_vdev_set_pcl_cmd_tlv() - Send WMI_VDEV_SET_PCL_CMDID to FW + * @wmi_handle: wmi handle + * @params: Set VDEV PCL params + * + * WMI_VDEV_SET_PCL_CMDID provides the Preferred Channel List (PCL) to WLAN + * firmware. The roaming module is the consumer of this information + * in the WLAN firmware. The channel list will be used when a VDEV needs + * to migrate to a new channel without host driver involvement. An example of + * this behavior is Legacy Fast Roaming (LFR 3.0). + * + * WMI_VDEV_SET_PCL_CMDID will carry only the weight list and not the actual + * channel list. The weights corresponds to the channels sent in + * WMI_SCAN_CHAN_LIST_CMDID. The channels from PCL would be having a higher + * weightage compared to the non PCL channels. + * + * When roaming is enabled on STA 1, PDEV pcl will be sent. When STA2 is + * up, VDEV pcl will be sent on STA 1 after calculating pcl again applying + * the bandmask and VDEV pcl will be sent for STA2. When one of the STA + * is disconnected, PDEV pcl will be sent on the other STA again. + * + * Return: Success if the cmd is sent successfully to the firmware + */ +static QDF_STATUS +send_vdev_set_pcl_cmd_tlv(wmi_unified_t wmi_handle, + struct set_pcl_cmd_params *params) +{ + wmi_vdev_set_pcl_cmd_fixed_param *cmd; + wmi_buf_t buf; + uint8_t *buf_ptr; + uint32_t *ch_weight, i; + size_t len; + uint32_t chan_len; + + chan_len = params->weights->saved_num_chan; + len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + (chan_len * sizeof(uint32_t)); + + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) + return QDF_STATUS_E_NOMEM; + + cmd = (wmi_vdev_set_pcl_cmd_fixed_param *)wmi_buf_data(buf); + buf_ptr = (uint8_t *)cmd; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_set_pcl_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_vdev_set_pcl_cmd_fixed_param)); + cmd->vdev_id = params->vdev_id; + buf_ptr += sizeof(wmi_vdev_set_pcl_cmd_fixed_param); + + /* Channel weights uint32 Array TLV */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, + (chan_len * sizeof(uint32_t))); + ch_weight = (uint32_t *)(buf_ptr + WMI_TLV_HDR_SIZE); + for (i = 0; i < chan_len; i++) + ch_weight[i] = params->weights->weighed_valid_list[i]; + + wmi_mtrace(WMI_VDEV_SET_PCL_CMDID, params->vdev_id, 0); + if (wmi_unified_cmd_send(wmi_handle, buf, len, + WMI_VDEV_SET_PCL_CMDID)) { + WMI_LOGE("%s: Failed to send WMI_VDEV_SET_PCL_CMDID", __func__); + wmi_buf_free(buf); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + void wmi_roam_offload_attach_tlv(wmi_unified_t wmi_handle) { struct wmi_ops *ops = wmi_handle->ops; @@ -930,6 +997,7 @@ void wmi_roam_offload_attach_tlv(wmi_unified_t wmi_handle) ops->send_process_roam_synch_complete_cmd = send_process_roam_synch_complete_cmd_tlv; ops->send_roam_invoke_cmd = send_roam_invoke_cmd_tlv; + ops->send_vdev_set_pcl_cmd = send_vdev_set_pcl_cmd_tlv; } #endif /* WLAN_FEATURE_ROAM_OFFLOAD */ diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 3055fe15fd..21013f018a 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -5315,6 +5315,12 @@ static void wma_update_mlme_related_tgt_caps(struct wlan_objmgr_psoc *psoc, mlme_tgt_cfg.stop_all_host_scan_support = wmi_service_enabled(wmi_handle, wmi_service_host_scan_stop_vdev_all); + mlme_tgt_cfg.peer_create_conf_support = + wmi_service_enabled(wmi_handle, + wmi_service_peer_create_conf); + mlme_tgt_cfg.dual_sta_roam_fw_support = + wmi_service_enabled(wmi_handle, + wmi_service_dual_sta_roam_support); wma_debug("beacon protection support %d", mlme_tgt_cfg.bigtk_support);