From 5fb48b575000906d2c358d8e6fd0209069313fb7 Mon Sep 17 00:00:00 2001 From: Pragaspathi Thilagaraj Date: Sun, 26 Jul 2020 23:36:11 +0530 Subject: [PATCH] qcacld-3.0: Connection manager add ucfg API for sme roam operations Add changes to handle north bound roaming operations/ configurations in connection manager. Add equivalent connection manager api for userspace triggered roaming operations & driver internally triggered roaming offload operations: sme_enable_roaming() - ucfg_cm_rso_init_deinit : Driver internally triggered sme_config_fast_roaming() - ucfg_user_space_enable_disable_rso: Userspace triggered sme_start_roaming() - ucfg_cm_enable_rso() - Driver internally triggered sme_stop_roaming() - ucfg_cm_disable_rso() - Driver internally triggered sme_abort_roam_scan() - ucfg_user_space_abort_roam_scan() -User space triggered Change-Id: I65130f69f2afff61b9ef7334ec365d3ce7519930 CRs-Fixed: 2741055 --- .../dispatcher/inc/wlan_cm_roam_api.h | 23 ++++ .../dispatcher/inc/wlan_cm_roam_ucfg_api.h | 56 ++++++++ .../dispatcher/src/wlan_cm_roam_api.c | 23 ++++ .../dispatcher/src/wlan_cm_roam_ucfg_api.c | 124 ++++++++++++++++++ core/hdd/src/wlan_hdd_cfg80211.c | 94 +++++++++++++ core/hdd/src/wlan_hdd_main.c | 110 ++++++++++++++++ core/sme/src/common/sme_api.c | 22 ++++ 7 files changed, 452 insertions(+) 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 6cdf4c9eca77..69312191bd5a 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 @@ -134,6 +134,29 @@ wlan_cm_roam_send_rso_cmd(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_E_NOSUPPORT; } #endif + +/** + * cm_roam_acquire_lock - Wrapper for sme_acquire_global_lock. + * + * Return: QDF_STATUS + */ +QDF_STATUS cm_roam_acquire_lock(void); + +/** + * cm_roam_release_lock - Wrapper for sme_release_global_lock() + * + * Return: QDF_STATUS + */ +QDF_STATUS cm_roam_release_lock(void); + +/** + * cm_roam_get_requestor_string - RSO control requestor to string api + * @requestor: Requestor of type enum wlan_cm_rso_control_requestor + * + * Return: Pointer to converted string + */ +char +*cm_roam_get_requestor_string(enum wlan_cm_rso_control_requestor requestor); #endif #ifdef WLAN_FEATURE_ROAM_OFFLOAD 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 0c11761374f9..738c8ee7302a 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 @@ -23,4 +23,60 @@ #ifndef _WLAN_CM_ROAM_UCFG_API_H_ #define _WLAN_CM_ROAM_UCFG_API_H_ +#ifdef ROAM_OFFLOAD_V1 +/** + * ucfg_user_space_enable_disable_rso - Enable/Disable Roam Scan offload + * to firmware. + * @pdev: Pointer to pdev + * @vdev_id: vdev id + * @is_fast_roam_enabled: Value provided by userspace. + * is_fast_roam_enabled - true: enable RSO if FastRoamEnabled ini is enabled + * false: disable RSO + * + * Return: QDF_STATUS + */ +QDF_STATUS +ucfg_user_space_enable_disable_rso(struct wlan_objmgr_pdev *pdev, + uint8_t vdev_id, + const bool is_fast_roam_enabled); + +/** + * ucfg_cm_rso_init_deinit - Init or Deinit roaming module at firmware + * @pdev: Pointer to pdev + * @vdev_id: vdev id + * @enable: true: Send RSO init and RSO enable + * false: Send RSO stop + * + * Return: QDF_STATUS + */ +QDF_STATUS +ucfg_cm_rso_init_deinit(struct wlan_objmgr_pdev *pdev, + uint8_t vdev_id, bool enable); + +/** + * ucfg_cm_disable_rso - Disable roam scan offload to firmware + * @pdev: Pointer to pdev + * @vdev_id: vdev id + * @requestor: RSO disable requestor + * @reason: Reason for RSO disable + * + * Return: QDF_STATUS + */ +QDF_STATUS ucfg_cm_disable_rso(struct wlan_objmgr_pdev *pdev, uint32_t vdev_id, + enum wlan_cm_rso_control_requestor requestor, + uint8_t reason); + +/** + * ucfg_cm_enable_rso - Enable roam scan offload to firmware + * @pdev: Pointer to pdev + * @vdev_id: vdev id + * @requestor: RSO disable requestor + * @reason: Reason for RSO disable + * + * Return: QDF_STATUS + */ +QDF_STATUS ucfg_cm_enable_rso(struct wlan_objmgr_pdev *pdev, uint32_t vdev_id, + enum wlan_cm_rso_control_requestor requestor, + uint8_t reason); +#endif #endif 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 1732a0ccdc6e..2e387e5eec8f 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 @@ -329,3 +329,26 @@ wlan_cm_roam_get_vendor_btm_params(struct wlan_objmgr_psoc *psoc, wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); } #endif + +#ifdef ROAM_OFFLOAD_V1 +char *cm_roam_get_requestor_string(enum wlan_cm_rso_control_requestor requestor) +{ + switch (requestor) { + case RSO_INVALID_REQUESTOR: + default: + return "No requestor"; + case RSO_START_BSS: + return "SAP start"; + case RSO_CHANNEL_SWITCH: + return "CSA"; + case RSO_CONNECT_START: + return "STA connection"; + case RSO_SAP_CHANNEL_CHANGE: + return "SAP Ch switch"; + case RSO_NDP_CON_ON_NDI: + return "NDP connection"; + case RSO_SET_PCL: + return "Set PCL"; + } +} +#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 9777b3ea9e8c..ec4ca711e3fd 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 @@ -22,3 +22,127 @@ #include "wlan_cm_roam_ucfg_api.h" +#ifdef ROAM_OFFLOAD_V1 +QDF_STATUS +ucfg_user_space_enable_disable_rso(struct wlan_objmgr_pdev *pdev, + uint8_t vdev_id, + const bool is_fast_roam_enabled) +{ + bool supplicant_disabled_roaming; + struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); + QDF_STATUS status; + + /* + * If the ini "FastRoamEnabled" is disabled, don't allow the + * userspace to enable roam offload + */ + ucfg_mlme_is_lfr_enabled(psoc, &lfr_enabled); + if (!lfr_enabled) { + mlme_legacy_debug("ROAM_CONFIG: Fast roam ini is disabled"); + if (!is_fast_roam_enabled) + return QDF_STATUS_SUCCESS; + + return QDF_STATUS_E_FAILURE; + } + + /* + * Supplicant_disabled_roaming flag is the global flag to control + * roam offload from supplicant. Driver cannot enable roaming if + * supplicant disabled roaming is set. + * is_fast_roam_enabled: true - enable RSO if not disabled by driver + * false - Disable RSO. Send RSO stop if false + * is set. + */ + supplicant_disabled_roaming = + mlme_get_supplicant_disabled_roaming(psoc, vdev_id); + if (!is_fast_roam_enabled && supplicant_disabled_roaming) { + mlme_legacy_debug("ROAM_CONFIG: RSO already disabled by supplicant"); + return QDF_STATUS_E_ALREADY; + } + + mlme_set_supplicant_disabled_roaming(psoc, vdev_id, + !is_fast_roam_enabled); + + state = (is_fast_roam_enabled) ? + WLAN_ROAM_RSO_ENABLED : WLAN_ROAM_RSO_STOPPED; + status = cm_roam_state_change(pdev, vdev_id, state, + REASON_SUPPLICANT_DISABLED_ROAMING); + + return status; +} + +/* + * Driver internally invoked RSO operation/configuration APIs. + */ +QDF_STATUS +ucfg_cm_rso_init_deinit(struct wlan_objmgr_pdev *pdev, + uint8_t vdev_id, bool enable) +{ + struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); + uint8_t reason = REASON_SUPPLICANT_DE_INIT_ROAMING; + QDF_STATUS status; + + status = cm_roam_acquire_lock(); + if (QDF_IS_STATUS_ERROR(status)) + return QDF_STATUS_E_FAILURE; + + if (enable) + reason = REASON_SUPPLICANT_INIT_ROAMING; + + status = cm_roam_state_change( + pdev, vdev_id, + enable ? WLAN_ROAM_RSO_ENABLED : WLAN_ROAM_DEINIT, + reason); + cm_roam_release_lock(); + + return status; +} + +QDF_STATUS ucfg_cm_disable_rso(struct wlan_objmgr_pdev *pdev, uint32_t vdev_id, + enum wlan_cm_rso_control_requestor requestor, + uint8_t reason) +{ + struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); + QDF_STATUS status; + + status = cm_roam_acquire_lock(); + if (QDF_IS_STATUS_ERROR(status)) + return QDF_STATUS_E_FAILURE; + + if (reason == REASON_DRIVER_DISABLED && requestor) + mlme_set_operations_bitmap(psoc, vdev_id, requestor, false); + + mlme_legacy_debug("ROAM_CONFIG: vdev[%d] Disable roaming - requestor:%s", + vdev_id, cm_roam_get_requestor_string(requestor)); + + status = cm_roam_state_change(pdev, vdev_id, WLAN_ROAM_RSO_STOPPED, + REASON_DRIVER_DISABLED); + cm_roam_release_lock(); + + return status; +} + +QDF_STATUS ucfg_cm_enable_rso(struct wlan_objmgr_pdev *pdev, uint32_t vdev_id, + enum wlan_cm_rso_control_requestor requestor, + uint8_t reason) +{ + struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); + QDF_STATUS status; + + if (reason == REASON_DRIVER_DISABLED && requestor) + mlme_set_operations_bitmap(mac->psoc, vdev_id, requestor, true); + + status = cm_roam_acquire_lock(); + if (QDF_IS_STATUS_ERROR(status)) + return QDF_STATUS_E_FAILURE; + + mlme_legacy_debug("ROAM_CONFIG: vdev[%d] Enable roaming - requestor:%s", + vdev_id, cm_roam_get_requestor_string(requestor)); + + status = cm_roam_state_change(pdev, vdev_id, WLAN_ROAM_RSO_STARTED, + REASON_DRIVER_ENABLED); + cm_roam_release_lock(); + + return status; +} +#endif diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 71a19b76ea07..e05ea20278c4 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -13026,6 +13026,99 @@ void wlan_hdd_rso_cmd_status_cb(hdd_handle_t hdd_handle, complete(&adapter->lfr_fw_status.disable_lfr_event); } +#ifdef ROAM_OFFLOAD_V1 +/** + * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming + * @wiphy: Pointer to wireless phy + * @wdev: Pointer to wireless device + * @data: Pointer to data + * @data_len: Length of @data + * + * This function is used to enable/disable roaming using vendor commands + * + * Return: 0 on success, negative errno on failure + */ +static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + struct hdd_context *hdd_ctx = wiphy_priv(wiphy); + struct net_device *dev = wdev->netdev; + struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1]; + uint32_t is_fast_roam_enabled; + int ret; + QDF_STATUS qdf_status; + unsigned long rc; + struct hdd_station_ctx *hdd_sta_ctx = + WLAN_HDD_GET_STATION_CTX_PTR(adapter); + mac_handle_t mac_handle; + + hdd_enter_dev(dev); + + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EINVAL; + } + + ret = wlan_cfg80211_nla_parse(tb, + QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, + qca_wlan_vendor_attr); + if (ret) { + hdd_err("Invalid ATTR"); + return -EINVAL; + } + + /* Parse and fetch Enable flag */ + if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) { + hdd_err("attr enable failed"); + return -EINVAL; + } + + is_fast_roam_enabled = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]); + hdd_debug("ROAM_CONFIG: isFastRoamEnabled %d", is_fast_roam_enabled); + + /* Update roaming */ + mac_handle = hdd_ctx->mac_handle; + qdf_status = ucfg_user_space_enable_disable_rso(hdd_ctx->pdev, + adapter->vdev_id, + is_fast_roam_enabled); + if (QDF_IS_STATUS_ERROR(qdf_status)) + hdd_err("ROAM_CONFIG: sme_config_fast_roaming failed with status=%d", + qdf_status); + + ret = qdf_status_to_os_return(qdf_status); + + if (eConnectionState_Associated == hdd_sta_ctx->conn_info.conn_state && + QDF_IS_STATUS_SUCCESS(qdf_status) && !is_fast_roam_enabled) { + INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event); + /* + * wait only for LFR disable in fw as LFR enable + * is always success + */ + rc = wait_for_completion_timeout( + &adapter->lfr_fw_status.disable_lfr_event, + msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS)); + if (!rc) { + hdd_err("Timed out waiting for RSO CMD status"); + return -ETIMEDOUT; + } + + if (!adapter->lfr_fw_status.is_disabled) { + hdd_err("Roam disable attempt in FW fails"); + return -EBUSY; + } + } + + hdd_exit(); + return ret; +} +#else /** * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming * @wiphy: Pointer to wireless phy @@ -13116,6 +13209,7 @@ static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy, hdd_exit(); return ret; } +#endif /** * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 78758cf4f54f..dbd164d37a0a 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -191,6 +191,7 @@ #include "wlan_global_lmac_if_api.h" #include "wlan_coex_ucfg_api.h" #include "wlan_cm_roam_api.h" +#include "wlan_cm_roam_ucfg_api.h" #ifdef MODULE #define WLAN_MODULE_NAME module_name(THIS_MODULE) @@ -5293,6 +5294,114 @@ hdd_vdev_destroy_procedure: return errno; } +#ifdef ROAM_OFFLOAD_V1 +QDF_STATUS hdd_init_station_mode(struct hdd_adapter *adapter) +{ + struct hdd_station_ctx *sta_ctx = &adapter->session.station; + struct hdd_context *hdd_ctx; + QDF_STATUS status; + int ret_val; + mac_handle_t mac_handle; + bool bval = false; + uint8_t enable_sifs_burst = 0; + uint32_t fine_time_meas_cap = 0, roam_triggers; + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + mac_handle = hdd_ctx->mac_handle; + sme_set_curr_device_mode(mac_handle, adapter->device_mode); + status = ucfg_mlme_get_vht_enable2x2(hdd_ctx->psoc, &bval); + if (!QDF_IS_STATUS_SUCCESS(status)) + hdd_err("unable to get vht_enable2x2"); + sme_set_pdev_ht_vht_ies(mac_handle, bval); + + sme_set_vdev_ies_per_band(mac_handle, adapter->vdev_id); + + hdd_roam_profile_init(adapter); + hdd_register_wext(adapter->dev); + + hdd_conn_set_connection_state(adapter, eConnectionState_NotConnected); + sme_roam_reset_configs(mac_handle, adapter->vdev_id); + + /* set fast roaming capability in sme session */ + status = ucfg_user_space_enable_disable_rso(hdd_ctx->pdev, + adapter->vdev_id, + true); + if (QDF_IS_STATUS_ERROR(status)) + hdd_err("ROAM_CONFIG: sme_config_fast_roaming failed with status=%d", + status); + + /* Set the default operation channel freq*/ + sta_ctx->conn_info.chan_freq = hdd_ctx->config->operating_chan_freq; + + /* Make the default Auth Type as OPEN */ + sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_OPEN_SYSTEM; + + status = hdd_init_tx_rx(adapter); + if (QDF_STATUS_SUCCESS != status) { + hdd_err("hdd_init_tx_rx() failed, status code %08d [x%08x]", + status, status); + goto error_init_txrx; + } + + set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags); + + status = hdd_wmm_adapter_init(adapter); + if (QDF_STATUS_SUCCESS != status) { + hdd_err("hdd_wmm_adapter_init() failed, status code %08d [x%08x]", + status, status); + goto error_wmm_init; + } + + set_bit(WMM_INIT_DONE, &adapter->event_flags); + + status = ucfg_get_enable_sifs_burst(hdd_ctx->psoc, &enable_sifs_burst); + if (!QDF_IS_STATUS_SUCCESS(status)) + hdd_err("Failed to get sifs burst value, use default"); + + ret_val = sme_cli_set_command(adapter->vdev_id, + WMI_PDEV_PARAM_BURST_ENABLE, + enable_sifs_burst, + PDEV_CMD); + if (ret_val) + hdd_err("WMI_PDEV_PARAM_BURST_ENABLE set failed %d", ret_val); + + hdd_set_netdev_flags(adapter); + + /* rcpi info initialization */ + qdf_mem_zero(&adapter->rcpi, sizeof(adapter->rcpi)); + + if (adapter->device_mode == QDF_STA_MODE) { + roam_triggers = ucfg_mlme_get_roaming_triggers(hdd_ctx->psoc); + mlme_set_roam_trigger_bitmap(hdd_ctx->psoc, adapter->vdev_id, + roam_triggers); + wlan_cm_roam_disable_vendor_btm(hdd_ctx->psoc, + adapter->vdev_id); + ucfg_mlme_get_fine_time_meas_cap(hdd_ctx->psoc, + &fine_time_meas_cap); + sme_cli_set_command( + adapter->vdev_id, + WMI_VDEV_PARAM_ENABLE_DISABLE_RTT_RESPONDER_ROLE, + (bool)(fine_time_meas_cap & WMI_FW_STA_RTT_RESPR), + VDEV_CMD); + sme_cli_set_command( + adapter->vdev_id, + WMI_VDEV_PARAM_ENABLE_DISABLE_RTT_INITIATOR_ROLE, + (bool)(fine_time_meas_cap & WMI_FW_STA_RTT_INITR), + VDEV_CMD); + } + + return QDF_STATUS_SUCCESS; + +error_wmm_init: + clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags); + hdd_deinit_tx_rx(adapter); +error_init_txrx: + hdd_unregister_wext(adapter->dev); + QDF_BUG(!hdd_vdev_destroy(adapter)); + + return status; +} +#else QDF_STATUS hdd_init_station_mode(struct hdd_adapter *adapter) { struct hdd_station_ctx *sta_ctx = &adapter->session.station; @@ -5395,6 +5504,7 @@ error_init_txrx: return status; } +#endif /** * hdd_deinit_station_mode() - De-initialize the station adapter diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 9b4bce1e13af..99564f8de56a 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -103,6 +103,28 @@ QDF_STATUS sme_release_global_lock(struct sme_context *sme) return qdf_mutex_release(&sme->sme_global_lock); } +#ifdef ROAM_OFFLOAD_V1 +QDF_STATUS cm_roam_acquire_lock(void) +{ + struct mac_context *mac = cds_get_context(QDF_MODULE_ID_SME); + + if (!mac) + return QDF_STATUS_E_FAILURE; + + return sme_acquire_global_lock(&mac->sme); +} + +QDF_STATUS cm_roam_release_lock(void) +{ + struct mac_context *mac = cds_get_context(QDF_MODULE_ID_SME); + + if (!mac) + return QDF_STATUS_E_FAILURE; + + return sme_release_global_lock(&mac->sme); +} +#endif + struct mac_context *sme_get_mac_context(void) { struct mac_context *mac_ctx;