diff --git a/components/mlme/core/inc/wlan_mlme_main.h b/components/mlme/core/inc/wlan_mlme_main.h index a2a45c591ae0..be136c853b56 100644 --- a/components/mlme/core/inc/wlan_mlme_main.h +++ b/components/mlme/core/inc/wlan_mlme_main.h @@ -75,6 +75,41 @@ enum vdev_assoc_type { VDEV_FT_REASSOC }; +/** + * wlan_mlme_roam_state_info - Structure containing roaming + * state related details + * @state: Roaming module state. + * @mlme_operations_bitmap: Bitmap containing what mlme operations are in + * progress where roaming should not be allowed. + */ +struct wlan_mlme_roam_state_info { + enum roam_offload_state state; + uint8_t mlme_operations_bitmap; +}; + +/** + * struct wlan_mlme_roaming_config - Roaming configurations structure + * @roam_trigger_bitmap: Master bitmap of roaming triggers. If the bitmap is + * zero, roaming module will be deinitialized at firmware for this vdev. + * @supplicant_disabled_roaming: Enable/disable roam scan in firmware; will be + * used by supplicant to do roam invoke after disabling roam scan in firmware + */ +struct wlan_mlme_roaming_config { + uint32_t roam_trigger_bitmap; + bool supplicant_disabled_roaming; +}; + +/** + * struct wlan_mlme_roam - Roam structure containing roam state and + * roam config info + * @roam_sm: Structure containing roaming state related details + * @roam_config: Roaming configurations structure + */ +struct wlan_mlme_roam { + struct wlan_mlme_roam_state_info roam_sm; + struct wlan_mlme_roaming_config roam_cfg; +}; + /** * struct mlme_legacy_priv - VDEV MLME legacy priv object * @chan_switch_in_progress: flag to indicate that channel switch is in progress @@ -94,6 +129,7 @@ enum vdev_assoc_type { * from peer * @vdev_stop_type: vdev stop type request * @bss_params: Bss params to be used in add bss resp handler + * @roam_off_state: Roam offload state */ struct mlme_legacy_priv { bool chan_switch_in_progress; @@ -110,6 +146,7 @@ struct mlme_legacy_priv { struct wlan_ies peer_disconnect_ies; uint32_t vdev_stop_type; struct bss_params *bss_params; + struct wlan_mlme_roam mlme_roam; }; #ifndef CRYPTO_SET_KEY_CONVERGED @@ -362,4 +399,119 @@ void mlme_set_peer_pmf_status(struct wlan_objmgr_peer *peer, * Return: Value of is_pmf_enabled; True if PMF is enabled by peer */ bool mlme_get_peer_pmf_status(struct wlan_objmgr_peer *peer); + +#if defined(WLAN_FEATURE_HOST_ROAM) || defined(WLAN_FEATURE_ROAM_OFFLOAD) +/** + * mlme_get_supplicant_disabled_roaming() - Get supplicant disabled roaming + * value for a given vdev. + * @psoc: PSOC pointer + * @vdev_id: Vdev for which the supplicant disabled roaming value is being + * requested + * + * Return: True if supplicant disabled roaming else false + */ +bool +mlme_get_supplicant_disabled_roaming(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id); + +/** + * mlme_set_supplicant_disabled_roaming - Set the supplicant disabled + * roaming flag. + * @psoc: PSOC pointer + * @vdev_id: Vdev for which the supplicant disabled roaming needs to + * be set + * @val: value true is to disable RSO and false to enable RSO + * + * Return: None + */ +void mlme_set_supplicant_disabled_roaming(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, bool val); + +/** + * mlme_get_roam_trigger_bitmap() - Get roaming trigger bitmap value for a given + * vdev. + * @psoc: PSOC pointer + * @vdev_id: Vdev for which the roam trigger bitmap is being requested + * + * Return: roaming trigger bitmap + */ +uint32_t +mlme_get_roam_trigger_bitmap(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id); + +/** + * mlme_set_roam_trigger_bitmap() - Set the roaming trigger bitmap value for + * the given vdev. If the bitmap is zero then roaming is completely disabled + * on the vdev which means roam structure in firmware is not allocated and no + * RSO start/stop commands can be sent + * @psoc: PSOC pointer + * @vdev_id: Vdev for which the roam trigger bitmap is to be set + * @val: bitmap value to set + * + * Return: None + */ +void mlme_set_roam_trigger_bitmap(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, uint32_t val); + +/** + * mlme_get_roam_state() - Get roam state from vdev object + * @psoc: psoc pointer + * @vdev_id: vdev id + * + * Return: Returns roam offload state + */ +enum roam_offload_state +mlme_get_roam_state(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id); + +/** + * mlme_set_roam_state() - Set roam state in vdev object + * @psoc: psoc pointer + * @vdev_id: vdev id + * @val: roam offload state + * + * Return: None + */ +void mlme_set_roam_state(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, + enum roam_offload_state val); + +/** + * mlme_get_operations_bitmap() - Get the mlme operations bitmap which + * contains the bitmap of mlme operations which have disabled roaming + * temporarily + * @psoc: PSOC pointer + * @vdev_id: vdev for which the mlme operation bitmap is requested + * + * Return: bitmap value + */ +uint8_t +mlme_get_operations_bitmap(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id); + +/** + * mlme_set_operations_bitmap() - Set the mlme operations bitmap which + * indicates what mlme operations are in progress + * @psoc: PSOC pointer + * @vdev_id: vdev for which the mlme operation bitmap is requested + * @reqs: RSO stop requestor + * @clear: clear bit if true else set bit + * + * Return: bitmap value + */ +void +mlme_set_operations_bitmap(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, + enum roam_control_requestor reqs, bool clear); + +#define MLME_IS_ROAM_STATE_RSO_STARTED(psoc, vdev_id) \ + (mlme_get_roam_state(psoc, vdev_id) == ROAM_RSO_STARTED) + +#define MLME_IS_ROAM_STATE_DEINIT(psoc, vdev_id) \ + (mlme_get_roam_state(psoc, vdev_id) == ROAM_DEINIT) + +#define MLME_IS_ROAM_STATE_INIT(psoc, vdev_id) \ + (mlme_get_roam_state(psoc, vdev_id) == ROAM_INIT) + +#define MLME_IS_ROAM_STATE_STOPPED(psoc, vdev_id) \ + (mlme_get_roam_state(psoc, vdev_id) == ROAM_RSO_STOPPED) + +#define MLME_IS_ROAM_INITIALIZED(psoc, vdev_id) \ + (mlme_get_roam_state(psoc, vdev_id) >= ROAM_INIT) +#endif #endif diff --git a/components/mlme/core/src/wlan_mlme_main.c b/components/mlme/core/src/wlan_mlme_main.c index 471e9b84a384..76841ce2319e 100644 --- a/components/mlme/core/src/wlan_mlme_main.c +++ b/components/mlme/core/src/wlan_mlme_main.c @@ -2509,3 +2509,250 @@ bool mlme_get_peer_pmf_status(struct wlan_objmgr_peer *peer) return peer_priv->is_pmf_enabled; } + +#if defined(WLAN_FEATURE_HOST_ROAM) || defined(WLAN_FEATURE_ROAM_OFFLOAD) +static +const char *mlme_roam_state_to_string(enum roam_offload_state state) +{ + switch (state) { + case ROAM_INIT: + return "ROAM_INIT"; + case ROAM_DEINIT: + return "ROAM_DEINIT"; + case ROAM_RSO_STARTED: + return "ROAM_RSO_STARTED"; + case ROAM_RSO_STOPPED: + return "ROAM_RSO_STOPPED"; + default: + return ""; + } +} + +static void +mlme_print_roaming_state(uint8_t vdev_id, enum roam_offload_state cur_state, + enum roam_offload_state new_state) +{ + mlme_info("ROAM: vdev[%d] ROAM State Changed from [%s] to [%s]", + vdev_id, mlme_roam_state_to_string(cur_state), + mlme_roam_state_to_string(new_state)); + + /* TODO: Try to print the state change requestor also */ +} + +bool +mlme_get_supplicant_disabled_roaming(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id) +{ + struct wlan_objmgr_vdev *vdev; + struct mlme_legacy_priv *mlme_priv; + bool value; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, + WLAN_MLME_OBJMGR_ID); + + if (!vdev) { + mlme_legacy_err("vdev object is NULL"); + return 0; + } + + mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); + if (!mlme_priv) { + mlme_legacy_err("vdev legacy private object is NULL"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); + return 0; + } + + value = mlme_priv->mlme_roam.roam_cfg.supplicant_disabled_roaming; + wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); + + return value; +} + +void mlme_set_supplicant_disabled_roaming(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, bool val) +{ + struct wlan_objmgr_vdev *vdev; + struct mlme_legacy_priv *mlme_priv; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, + WLAN_MLME_OBJMGR_ID); + + if (!vdev) { + mlme_legacy_err("vdev object is NULL"); + return; + } + + mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); + if (!mlme_priv) { + mlme_legacy_err("vdev legacy private object is NULL"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); + return; + } + + mlme_priv->mlme_roam.roam_cfg.supplicant_disabled_roaming = val; + wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); +} + +uint32_t +mlme_get_roam_trigger_bitmap(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id) +{ + struct wlan_objmgr_vdev *vdev; + struct mlme_legacy_priv *mlme_priv; + uint32_t roam_bitmap; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, + WLAN_MLME_OBJMGR_ID); + + if (!vdev) { + mlme_legacy_err("vdev object is NULL"); + return 0; + } + + mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); + if (!mlme_priv) { + mlme_legacy_err("vdev legacy private object is NULL"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); + return 0; + } + + roam_bitmap = mlme_priv->mlme_roam.roam_cfg.roam_trigger_bitmap; + wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); + + return roam_bitmap; +} + +void mlme_set_roam_trigger_bitmap(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, uint32_t val) +{ + struct wlan_objmgr_vdev *vdev; + struct mlme_legacy_priv *mlme_priv; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, + WLAN_MLME_OBJMGR_ID); + if (!vdev) { + mlme_legacy_err("vdev object is NULL"); + return; + } + + mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); + if (!mlme_priv) { + mlme_legacy_err("vdev legacy private object is NULL"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); + return; + } + + mlme_priv->mlme_roam.roam_cfg.roam_trigger_bitmap = val; + wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); +} + +uint8_t +mlme_get_operations_bitmap(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id) +{ + struct wlan_objmgr_vdev *vdev; + struct mlme_legacy_priv *mlme_priv; + uint8_t bitmap; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, + WLAN_MLME_OBJMGR_ID); + + if (!vdev) { + mlme_legacy_err("vdev object is NULL"); + return 0xFF; + } + + mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); + if (!mlme_priv) { + mlme_legacy_err("vdev legacy private object is NULL"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); + return 0xFF; + } + + bitmap = mlme_priv->mlme_roam.roam_sm.mlme_operations_bitmap; + wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); + + return bitmap; +} + +void +mlme_set_operations_bitmap(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, + enum roam_control_requestor reqs, bool clear) +{ + struct wlan_objmgr_vdev *vdev; + struct mlme_legacy_priv *mlme_priv; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, + WLAN_MLME_OBJMGR_ID); + if (!vdev) { + mlme_legacy_err("vdev object is NULL"); + return; + } + + mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); + if (!mlme_priv) { + mlme_legacy_err("vdev legacy private object is NULL"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); + return; + } + + if (clear) + mlme_priv->mlme_roam.roam_sm.mlme_operations_bitmap &= ~reqs; + else + mlme_priv->mlme_roam.roam_sm.mlme_operations_bitmap |= reqs; + wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); +} + +enum roam_offload_state +mlme_get_roam_state(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id) +{ + struct wlan_objmgr_vdev *vdev; + struct mlme_legacy_priv *mlme_priv; + enum roam_offload_state roam_state; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, + WLAN_MLME_OBJMGR_ID); + + if (!vdev) { + mlme_legacy_err("vdev object is NULL"); + return ROAM_DEINIT; + } + + mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); + if (!mlme_priv) { + mlme_legacy_err("vdev legacy private object is NULL"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); + return ROAM_DEINIT; + } + + roam_state = mlme_priv->mlme_roam.roam_sm.state; + wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); + + return roam_state; +} + +void mlme_set_roam_state(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, + enum roam_offload_state new_state) +{ + struct wlan_objmgr_vdev *vdev; + struct mlme_legacy_priv *mlme_priv; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, + WLAN_MLME_OBJMGR_ID); + + if (!vdev) { + mlme_legacy_err("vdev object is NULL"); + return; + } + + mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); + if (!mlme_priv) { + mlme_legacy_err("vdev legacy private object is NULL"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); + return; + } + + mlme_print_roaming_state(vdev_id, mlme_priv->mlme_roam.roam_sm.state, + new_state); + mlme_priv->mlme_roam.roam_sm.state = new_state; + wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); +} +#endif diff --git a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h index 791e62911f41..ab979b7d3ac1 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h @@ -60,6 +60,8 @@ #define MAX_VENDOR_IES_LEN 1532 #define CFG_VALID_CHANNEL_LIST_STRING_LEN (CFG_VALID_CHANNEL_LIST_LEN * 4) + +#define DEFAULT_ROAM_TRIGGER_BITMAP 0xFFFFFFFF /** * struct mlme_cfg_str - generic structure for all mlme CFG string items * @@ -259,6 +261,42 @@ enum mlme_ts_info_ack_policy { TS_INFO_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK = 1, }; +#if defined(WLAN_FEATURE_HOST_ROAM) || defined(WLAN_FEATURE_ROAM_OFFLOAD) +/** + * enum roam_control_requestor - Driver disabled roaming requestor that will + * request the roam module to disable roaming based on the mlme operation + * @RSO_INVALID_REQUESTOR: invalid requestor + * @RSO_START_BSS: disable roaming temporarily due to start bss + * @RSO_CHANNEL_SWITCH: disable roaming due to STA channel switch + * @RSO_CONNECT_START: disable roaming temporarily due to connect + * @RSO_SAP_CHANNEL_CHANGE: disable roaming due to SAP channel change + */ +enum roam_control_requestor { + RSO_INVALID_REQUESTOR, + RSO_START_BSS = BIT(0), + RSO_CHANNEL_SWITCH = BIT(1), + RSO_CONNECT_START = BIT(2), + RSO_SAP_CHANNEL_CHANGE = BIT(3), +}; + +/** + * enum roam_offload_state - Roaming module state for each STA vdev. + * @ROAM_DEINIT: Roaming module is not initialized at the + * firmware. + * @ROAM_INIT: Roaming module initialized at the firmware. + * @ROAM_RSO_STARTED: RSO started, firmware can roam to different AP. + * @ROAM_RSO_STOPPED: RSO stopped - roaming module is initialized at firmware, + * but firmware cannot do roaming due to supplicant disabled roaming/driver + * disabled roaming. + */ +enum roam_offload_state { + ROAM_DEINIT, + ROAM_INIT, + ROAM_RSO_STARTED, + ROAM_RSO_STOPPED +}; +#endif + /** * struct mlme_edca_params - EDCA pramaters related config items *