qcacld-3.0: Code cleanup for connection manager in HDD

Remove unused code related to ndef FEATURE_CM_ENABLE in HDD.

Change-Id: I2934e4a867458561c50170b0e786e63f20f1af4a
CRs-Fixed: 2977577
Tento commit je obsažen v:
Abhishek Singh
2021-05-27 19:41:47 +05:30
odevzdal Madan Koyyalamudi
rodič 02492ff860
revize af34815a41
21 změnil soubory, kde provedl 13 přidání a 7405 odebrání

Zobrazit soubor

@@ -279,28 +279,6 @@ QDF_STATUS hdd_sme_roam_callback(void *context,
eRoamCmdStatus roam_status,
eCsrRoamResult roam_result);
#ifndef FEATURE_CM_ENABLE
/**
* hdd_set_genie_to_csr() - set genie to csr
* @adapter: pointer to adapter
* @rsn_auth_type: pointer to auth type
*
* Return: 0 on success, error number otherwise
*/
int hdd_set_genie_to_csr(struct hdd_adapter *adapter,
enum csr_akm_type *rsn_auth_type);
/**
* hdd_set_csr_auth_type() - set csr auth type
* @adapter: pointer to adapter
* @rsn_auth_type: auth type
*
* Return: 0 on success, error number otherwise
*/
int hdd_set_csr_auth_type(struct hdd_adapter *adapter,
enum csr_akm_type rsn_auth_type);
#endif
#ifdef FEATURE_WLAN_TDLS
/**
* hdd_roam_register_tdlssta() - register new TDLS station
@@ -397,37 +375,6 @@ bool hdd_save_peer(struct hdd_station_ctx *sta_ctx,
void hdd_delete_peer(struct hdd_station_ctx *sta_ctx,
struct qdf_mac_addr *peer_mac_addr);
#ifndef FEATURE_CM_ENABLE
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
QDF_STATUS
hdd_wma_send_fastreassoc_cmd(struct hdd_adapter *adapter,
const tSirMacAddr bssid, uint32_t ch_freq);
/**
* hdd_save_gtk_params() - Save GTK offload params
* @adapter: HDD adapter
* @csr_roam_info: CSR roam info
* @is_reassoc: boolean to indicate roaming
*
* Return: None
*/
void hdd_save_gtk_params(struct hdd_adapter *adapter,
struct csr_roam_info *csr_roam_info, bool is_reassoc);
#else
static inline void hdd_save_gtk_params(struct hdd_adapter *adapter,
struct csr_roam_info *csr_roam_info,
bool is_reassoc)
{
}
static inline QDF_STATUS
hdd_wma_send_fastreassoc_cmd(struct hdd_adapter *adapter,
const tSirMacAddr bssid, uint32_t ch_freq)
{
return QDF_STATUS_SUCCESS;
}
#endif
#endif
/**
* hdd_copy_ht_caps()- copy ht caps info from roam ht caps
* info to source ht_cap info of type ieee80211_ht_cap.
@@ -481,7 +428,6 @@ void hdd_roam_profile_init(struct hdd_adapter *adapter);
*/
bool hdd_any_valid_peer_present(struct hdd_adapter *adapter);
#ifdef FEATURE_CM_ENABLE
/**
* hdd_cm_register_cb() - Sets legacy callbacks to osif
*
@@ -500,20 +446,8 @@ QDF_STATUS hdd_cm_register_cb(void);
*
* Return: QDF_STATUS
*/
void hdd_cm_unregister_cb(void);
#else
static inline QDF_STATUS hdd_cm_register_cb(void)
{
return QDF_STATUS_SUCCESS;
}
static inline void hdd_cm_unregister_cb(void)
{
}
#endif
/**
* hdd_conn_remove_connect_info() - remove connection info
* @sta_ctx: pointer to global HDD station context

Zobrazit soubor

@@ -878,14 +878,6 @@ struct hdd_mon_set_ch_info {
* to immediately go into power save?
*/
struct hdd_station_ctx {
#ifndef FEATURE_CM_ENABLE
uint8_t security_ie[WLAN_MAX_IE_LEN];
tSirAddie assoc_additional_ie;
enum nl80211_wpa_versions wpa_versions;
enum hdd_auth_key_mgmt auth_key_mgmt;
struct qdf_mac_addr requested_bssid;
bool ft_carrier_on;
#endif
uint32_t reg_phymode;
struct csr_roam_profile roam_profile;
struct hdd_connection_info conn_info;
@@ -1270,11 +1262,6 @@ struct hdd_adapter {
#endif
struct hdd_mic_work mic_work;
#ifndef FEATURE_CM_ENABLE
bool disconnection_in_progress;
qdf_mutex_t disconnection_status_lock;
struct completion roaming_comp_var;
#endif
unsigned long event_flags;
/**Device TX/RX statistics*/
@@ -3819,22 +3806,6 @@ QDF_STATUS hdd_sme_open_session_callback(uint8_t vdev_id,
QDF_STATUS qdf_status);
QDF_STATUS hdd_sme_close_session_callback(uint8_t vdev_id);
#ifndef FEATURE_CM_ENABLE
/**
* hdd_reassoc() - perform a userspace-directed reassoc
* @adapter: Adapter upon which the command was received
* @bssid: BSSID with which to reassociate
* @ch_freq: channel upon which to reassociate
* @src: The source for the trigger of this action
*
* This function performs a userspace-directed reassoc operation
*
* Return: 0 for success non-zero for failure
*/
int hdd_reassoc(struct hdd_adapter *adapter, const uint8_t *bssid,
uint32_t ch_freq, const handoff_src src);
#endif
int hdd_register_cb(struct hdd_context *hdd_ctx);
void hdd_deregister_cb(struct hdd_context *hdd_ctx);
int hdd_start_station_adapter(struct hdd_adapter *adapter);
@@ -3908,15 +3879,6 @@ void hdd_populate_random_mac_addr(struct hdd_context *hdd_ctx, uint32_t num);
*/
bool hdd_is_interface_up(struct hdd_adapter *adapter);
#ifndef FEATURE_CM_ENABLE
void hdd_connect_result(struct net_device *dev, const u8 *bssid,
struct csr_roam_info *roam_info, const u8 *req_ie,
size_t req_ie_len, const u8 *resp_ie,
size_t resp_ie_len, u16 status, gfp_t gfp,
bool connect_timeout,
tSirResultCodes timeout_reason);
#endif
#ifdef WLAN_FEATURE_FASTPATH
void hdd_enable_fastpath(struct hdd_context *hdd_ctx,
void *context);
@@ -3998,56 +3960,6 @@ struct csr_roam_profile *hdd_roam_profile(struct hdd_adapter *adapter)
return &sta_ctx->roam_profile;
}
#ifndef FEATURE_CM_ENABLE
/**
* hdd_security_ie() - Get adapter's security IE
* @adapter: The adapter being queried
*
* Given an adapter this function returns a pointer to its security IE
* buffer. Note that this buffer is maintained outside the roam
* profile but, when in use, is referenced by a pointer within the
* roam profile.
*
* NOTE WELL: Caller is responsible for ensuring this interface is only
* invoked for STA-type interfaces
*
* Return: pointer to the adapter's roam profile security IE buffer
*/
static inline
uint8_t *hdd_security_ie(struct hdd_adapter *adapter)
{
struct hdd_station_ctx *sta_ctx;
sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
return sta_ctx->security_ie;
}
/**
* hdd_assoc_additional_ie() - Get adapter's assoc additional IE
* @adapter: The adapter being queried
*
* Given an adapter this function returns a pointer to its assoc
* additional IE buffer. Note that this buffer is maintained outside
* the roam profile but, when in use, is referenced by a pointer
* within the roam profile.
*
* NOTE WELL: Caller is responsible for ensuring this interface is only
* invoked for STA-type interfaces
*
* Return: pointer to the adapter's assoc additional IE buffer
*/
static inline
tSirAddie *hdd_assoc_additional_ie(struct hdd_adapter *adapter)
{
struct hdd_station_ctx *sta_ctx;
sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
return &sta_ctx->assoc_additional_ie;
}
#endif
/**
* hdd_is_roaming_in_progress() - check if roaming is in progress
* @hdd_ctx - Global HDD context
@@ -4287,29 +4199,6 @@ int hdd_get_rssi_snr_by_bssid(struct hdd_adapter *adapter, const uint8_t *bssid,
*/
int hdd_reset_limit_off_chan(struct hdd_adapter *adapter);
#ifndef FEATURE_CM_ENABLE
#if defined(WLAN_FEATURE_FILS_SK) && \
(defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
/**
* hdd_update_hlp_info() - Update HLP packet received in FILS (re)assoc rsp
* @dev: net device
* @roam_fils_params: Fils join rsp params
*
* This API is used to send the received HLP packet in Assoc rsp(FILS AKM)
* to the network layer.
*
* Return: None
*/
void hdd_update_hlp_info(struct net_device *dev,
struct csr_roam_info *roam_info);
#else
static inline void hdd_update_hlp_info(struct net_device *dev,
struct csr_roam_info *roam_info)
{}
#endif
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
static inline void hdd_dev_setup_destructor(struct net_device *dev)
{
@@ -4445,17 +4334,6 @@ static inline void hdd_driver_mem_cleanup(void)
}
#endif /* WLAN_FEATURE_MEMDUMP_ENABLE */
#ifndef FEATURE_CM_ENABLE
/**
* hdd_set_disconnect_status() - set adapter disconnection status
* @hdd_adapter: Pointer to hdd adapter
* @disconnecting: Disconnect status to set
*
* Return: None
*/
void hdd_set_disconnect_status(struct hdd_adapter *adapter, bool disconnecting);
#endif
#ifdef FEATURE_MONITOR_MODE_SUPPORT
/**
* wlan_hdd_set_mon_chan() - Set capture channel on the monitor mode interface.

Rozdílový obsah nebyl zobrazen, protože je příliš veliký Načíst rozdílové porovnání

Zobrazit soubor

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2020-2021, The Linux Foundation. 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
@@ -99,13 +99,8 @@ wlan_hdd_btc_chain_mode_handler(struct wlan_objmgr_vdev *vdev)
switch (adapter->device_mode) {
case QDF_STA_MODE:
case QDF_P2P_CLIENT_MODE:
/* This is temp ifdef will be removed in near future */
#ifdef FEATURE_CM_ENABLE
wlan_hdd_cm_issue_disconnect(adapter,
REASON_PREV_AUTH_NOT_VALID, false);
#else
wlan_hdd_disconnect(adapter, 0, REASON_PREV_AUTH_NOT_VALID);
#endif
break;
case QDF_SAP_MODE:
case QDF_P2P_GO_MODE:

Zobrazit soubor

@@ -941,9 +941,7 @@ QDF_STATUS hdd_set_sme_config(struct hdd_context *hdd_ctx)
*/
sme_config->csr_config.phyMode =
hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
#ifndef FEATURE_CM_ENABLE
sme_update_nud_config(mac_handle, config->enable_nud_tracking);
#endif
if (config->dot11Mode == eHDD_DOT11_MODE_abg ||
config->dot11Mode == eHDD_DOT11_MODE_11b ||
config->dot11Mode == eHDD_DOT11_MODE_11g ||

Rozdílový obsah nebyl zobrazen, protože je příliš veliký Načíst rozdílové porovnání

Zobrazit soubor

@@ -287,12 +287,6 @@ typedef enum {
#define PCL_CHANNEL_SUPPORT_CLI BIT(1)
#define PCL_CHANNEL_EXCLUDE_IN_GO_NEG BIT(3)
#ifndef FEATURE_CM_ENABLE
struct cfg80211_bss *
wlan_hdd_cfg80211_update_bss_db(struct hdd_adapter *adapter,
struct csr_roam_info *roam_info);
#endif
#define CONNECTIVITY_CHECK_SET_ARP \
QCA_WLAN_VENDOR_CONNECTIVITY_CHECK_SET_ARP
#define CONNECTIVITY_CHECK_SET_DNS \
@@ -337,25 +331,6 @@ wlan_hdd_wifi_test_config_policy[
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX) \
},
#ifndef FEATURE_CM_ENABLE
int wlan_hdd_cfg80211_pmksa_candidate_notify(struct hdd_adapter *adapter,
struct csr_roam_info *roam_info,
int index, bool preauth);
#ifdef FEATURE_WLAN_LFR_METRICS
QDF_STATUS
wlan_hdd_cfg80211_roam_metrics_preauth(struct hdd_adapter *adapter,
struct csr_roam_info *roam_info);
QDF_STATUS
wlan_hdd_cfg80211_roam_metrics_preauth_status(struct hdd_adapter *adapter,
struct csr_roam_info *roam_info,
bool preauth_status);
QDF_STATUS
wlan_hdd_cfg80211_roam_metrics_handover(struct hdd_adapter *adapter,
struct csr_roam_info *roam_info);
#endif
#endif
extern const struct nla_policy
qca_wlan_vendor_set_nud_stats_policy
[QCA_ATTR_NUD_STATS_SET_MAX + 1];
@@ -508,22 +483,6 @@ int wlan_hdd_send_avoid_freq_for_dnbs(struct hdd_context *hdd_ctx,
void wlan_hdd_rso_cmd_status_cb(hdd_handle_t hdd_handle,
struct rso_cmd_status *rso_status);
#ifndef FEATURE_CM_ENABLE
/*
* wlan_hdd_cfg80211_unlink_bss :to inform nl80211
* interface that BSS might have been lost.
* @adapter: adapter
* @bssid: bssid which might have been lost
* @ssid: SSID
* @ssid_len: length of the SSID
*
* Return: void
*/
void wlan_hdd_cfg80211_unlink_bss(struct hdd_adapter *adapter,
tSirMacAddr bssid, uint8_t *ssid,
uint8_t ssid_len);
#endif
void wlan_hdd_cfg80211_acs_ch_select_evt(struct hdd_adapter *adapter);
#ifdef WLAN_CFR_ENABLE
@@ -561,23 +520,7 @@ void hdd_cfr_data_send_nl_event(uint8_t vdev_id, uint32_t pid,
void hdd_send_roam_scan_ch_list_event(struct hdd_context *hdd_ctx,
uint8_t vdev_id, uint16_t buf_len,
uint8_t *buf);
#ifndef FEATURE_CM_ENABLE
int wlan_hdd_send_roam_auth_event(struct hdd_adapter *adapter, uint8_t *bssid,
uint8_t *req_rsn_ie, uint32_t req_rsn_length, uint8_t
*rsp_rsn_ie, uint32_t rsp_rsn_length, struct csr_roam_info
*roam_info_ptr);
#endif
#else
#ifndef FEATURE_CM_ENABLE
static inline int wlan_hdd_send_roam_auth_event(struct hdd_adapter *adapter,
uint8_t *bssid, uint8_t *req_rsn_ie, uint32_t req_rsn_length,
uint8_t *rsp_rsn_ie, uint32_t rsp_rsn_length,
struct csr_roam_info *roam_info_ptr)
{
return 0;
}
#endif
static inline
void hdd_send_roam_scan_ch_list_event(struct hdd_context *hdd_ctx,
uint8_t vdev_id, uint16_t buf_len,
@@ -620,29 +563,6 @@ int wlan_hdd_cfg80211_update_band(struct hdd_context *hdd_ctx,
struct wiphy *wiphy,
enum band_info new_band);
#ifndef FEATURE_CM_ENABLE
/**
* wlan_hdd_cfg80211_indicate_disconnect() - Indicate disconnnect to userspace
* @adapter: Pointer to adapter
* @locally_generated: True if the disconnection is internally generated.
* False if the disconnection is received from peer.
* @reason: Disconnect reason as per @enum wlan_reason_code
* @disconnect_ies: IEs received in Deauth/Disassoc from peer
* @disconnect_ies_len: Length of @disconnect_ies
*
* This function is indicate disconnect to the kernel which thus indicates
* to the userspace.
*
* Return: None
*/
void
wlan_hdd_cfg80211_indicate_disconnect(struct hdd_adapter *adapter,
bool locally_generated,
enum wlan_reason_code reason,
uint8_t *disconnect_ies,
uint16_t disconnect_ies_len);
#endif
/**
* wlan_hdd_change_hw_mode_for_given_chnl() - change HW mode for given channel
* @adapter: pointer to adapter
@@ -703,33 +623,6 @@ void hdd_set_rate_bw(struct rate_info *info, enum hdd_rate_info_bw hdd_bw);
*/
uint8_t hdd_get_sap_operating_band(struct hdd_context *hdd_ctx);
#ifndef FEATURE_CM_ENABLE
/**
* wlan_hdd_try_disconnect() - try disconnnect from previous connection
* @adapter: Pointer to adapter
* @reason: Mac Disconnect reason code as per @enum wlan_reason_code
*
* This function is used to disconnect from previous connection
*
* Return: 0 for success, non-zero for failure
*/
int wlan_hdd_try_disconnect(struct hdd_adapter *adapter,
enum wlan_reason_code reason);
/**
* wlan_hdd_disconnect() - hdd disconnect api
* @adapter: Pointer to adapter
* @reason: CSR disconnect reason code as per @enum eCsrRoamDisconnectReason
* @mac_reason: Mac Disconnect reason code as per @enum wlan_reason_code
*
* This function is used to issue a disconnect request to SME
*
* Return: 0 for success, non-zero for failure
*/
int wlan_hdd_disconnect(struct hdd_adapter *adapter, u16 reason,
enum wlan_reason_code mac_reason);
#endif
/**
* wlan_hdd_merge_avoid_freqs(): Merge two tHddAvoidFreqList
* @destFreqList: Destination list in which merged frequency

Zobrazit soubor

@@ -27,7 +27,6 @@
#include "wlan_cm_public_struct.h"
#include "osif_cm_util.h"
#ifdef FEATURE_CM_ENABLE
/**
* wlan_hdd_cm_connect() - cfg80211 connect api
* @wiphy: Pointer to wiphy
@@ -150,7 +149,6 @@ QDF_STATUS hdd_cm_cckm_preauth_complete(struct wlan_objmgr_vdev *vdev,
struct wlan_preauth_rsp *rsp);
#endif
#endif
#endif
#ifdef WLAN_FEATURE_MSCS
/**
@@ -170,13 +168,6 @@ void reset_mscs_params(struct hdd_adapter *adapter)
}
#endif
static const uint8_t acm_mask_bit[WLAN_MAX_AC] = {
0x4, /* SME_AC_BK */
0x8, /* SME_AC_BE */
0x2, /* SME_AC_VI */
0x1 /* SME_AC_VO */
};
/**
* hdd_handle_disassociation_event() - Handle disassociation event
* @adapter: Pointer to adapter
@@ -308,4 +299,4 @@ bool hdd_cm_is_disconnecting(struct hdd_adapter *adapter);
*/
bool hdd_cm_is_vdev_roaming(struct hdd_adapter *adapter);
#endif
#endif /* __WLAN_HDD_CM_API_H */

Zobrazit soubor

@@ -48,7 +48,6 @@
#include "wlan_roam_debug.h"
#include <wlan_hdd_regulatory.h>
#ifdef FEATURE_CM_ENABLE
bool hdd_cm_is_vdev_associated(struct hdd_adapter *adapter)
{
struct wlan_objmgr_vdev *vdev;
@@ -165,44 +164,6 @@ bool hdd_cm_is_vdev_roaming(struct hdd_adapter *adapter)
return is_vdev_roaming;
}
#else
bool hdd_cm_is_vdev_associated(struct hdd_adapter *adapter)
{
struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
return (sta_ctx->conn_info.conn_state == eConnectionState_Associated ||
sta_ctx->conn_info.conn_state == eConnectionState_NdiConnected);
}
bool hdd_cm_is_connecting(struct hdd_adapter *adapter)
{
struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
return sta_ctx->conn_info.conn_state == eConnectionState_Connecting;
}
bool hdd_cm_is_disconnected(struct hdd_adapter *adapter)
{
struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
return sta_ctx->conn_info.conn_state == eConnectionState_NotConnected;
}
bool hdd_cm_is_disconnecting(struct hdd_adapter *adapter)
{
struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
return sta_ctx->conn_info.conn_state == eConnectionState_Disconnecting;
}
bool hdd_cm_is_vdev_roaming(struct hdd_adapter *adapter)
{
struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
return sme_roaming_in_progress(hdd_ctx->mac_handle, adapter->vdev_id);
}
#endif
void hdd_cm_set_peer_authenticate(struct hdd_adapter *adapter,
struct qdf_mac_addr *bssid,
bool is_auth_required)
@@ -309,8 +270,6 @@ void hdd_cm_save_connect_status(struct hdd_adapter *adapter,
adapter->connect_req_status = reason_code;
}
#ifdef FEATURE_CM_ENABLE
#ifdef FEATURE_WLAN_WAPI
static bool hdd_cm_is_wapi_sta(enum csr_akm_type auth_type)
{
@@ -646,6 +605,13 @@ static bool hdd_is_ese_assoc(enum csr_akm_type auth_type,
}
#endif
static const uint8_t acm_mask_bit[WLAN_MAX_AC] = {
0x4, /* SME_AC_BK */
0x8, /* SME_AC_BE */
0x2, /* SME_AC_VI */
0x1 /* SME_AC_VO */
};
static void hdd_wmm_cm_connect(struct wlan_objmgr_vdev *vdev,
struct hdd_adapter *adapter,
tDot11fBeaconIEs *bcn_ie,
@@ -1517,4 +1483,3 @@ QDF_STATUS hdd_cm_cckm_preauth_complete(struct wlan_objmgr_vdev *vdev,
}
#endif /* FEATURE_WLAN_ESE */
#endif /* WLAN_FEATURE_PREAUTH_ENABLE */
#endif

Zobrazit soubor

@@ -189,16 +189,6 @@ void __hdd_cm_disconnect_handler_post_user_update(struct hdd_adapter *adapter)
adapter->hdd_stats.tx_rx_stats.cont_txtimeout_cnt = 0;
#ifndef FEATURE_CM_ENABLE
/*
* Reset hdd_reassoc_scenario to false here. After roaming in
* 802.1x or WPA3 security, EAPOL is handled at supplicant and
* the hdd_reassoc_scenario flag will not be reset if disconnection
* happens before EAP/EAPOL at supplicant is complete.
*/
sta_ctx->ft_carrier_on = false;
#endif
hdd_nud_reset_tracking(adapter);
hdd_reset_limit_off_chan(adapter);
@@ -213,7 +203,6 @@ void reset_mscs_params(struct hdd_adapter *adapter)
}
#endif
#ifdef FEATURE_CM_ENABLE
QDF_STATUS wlan_hdd_cm_issue_disconnect(struct hdd_adapter *adapter,
enum wlan_reason_code reason,
bool sync)
@@ -417,6 +406,3 @@ QDF_STATUS hdd_cm_napi_serialize_control(bool action)
return QDF_STATUS_SUCCESS;
}
#endif

Zobrazit soubor

@@ -4920,13 +4920,7 @@ hdd_check_and_disconnect_sta_on_invalid_channel(struct hdd_context *hdd_ctx,
}
hdd_err("chan %d not valid, issue disconnect", sta_chan_freq);
/* This is temp ifdef will be removed in near future */
#ifdef FEATURE_CM_ENABLE
wlan_hdd_cm_issue_disconnect(sta_adapter, reason, false);
#else
/* Issue Disconnect request */
wlan_hdd_disconnect(sta_adapter, eCSR_DISCONNECT_REASON_DEAUTH, reason);
#endif
}
#ifdef DISABLE_CHANNEL_LIST

Zobrazit soubor

@@ -528,148 +528,6 @@ static int hdd_parse_reassoc_command_v1_data(const uint8_t *command,
return 0;
}
#ifndef FEATURE_CM_ENABLE
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
QDF_STATUS hdd_wma_send_fastreassoc_cmd(struct hdd_adapter *adapter,
const tSirMacAddr bssid,
uint32_t ch_freq)
{
struct hdd_station_ctx *hdd_sta_ctx =
WLAN_HDD_GET_STATION_CTX_PTR(adapter);
struct csr_roam_profile *roam_profile;
tSirMacAddr connected_bssid;
roam_profile = hdd_roam_profile(adapter);
qdf_mem_copy(connected_bssid, hdd_sta_ctx->conn_info.bssid.bytes,
ETH_ALEN);
return sme_fast_reassoc(adapter->hdd_ctx->mac_handle,
roam_profile, bssid, ch_freq,
adapter->vdev_id, connected_bssid);
}
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
/**
* hdd_is_fast_reassoc_allowed - check if roaming offload init is
* done. If roaming offload is not initialized, don't allow roam invoke
* to be triggered.
* @psoc: Pointer to psoc object
* @vdev_id: vdev_id
*
* This API should return true if kernel version is less than 4.9, because
* the earlier versions don't have the fix to handle reassociation failure.
*
* Return: true if roaming module initialization is done else false
*/
static bool
hdd_is_fast_reassoc_allowed(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
{
return MLME_IS_ROAM_INITIALIZED(psoc, vdev_id);
}
#else
static inline bool
hdd_is_fast_reassoc_allowed(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
{
return true;
}
#endif
int hdd_reassoc(struct hdd_adapter *adapter, const uint8_t *bssid,
uint32_t ch_freq, const handoff_src src)
{
struct hdd_station_ctx *sta_ctx;
struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
int ret = 0;
QDF_STATUS status;
uint8_t connected_vdev;
if (!hdd_ctx) {
hdd_err("Invalid hdd ctx");
return -EINVAL;
}
if (QDF_STA_MODE != adapter->device_mode) {
hdd_warn("Unsupported in mode %s(%d)",
qdf_opmode_str(adapter->device_mode),
adapter->device_mode);
return -EINVAL;
}
sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
/*
* pHddStaCtx->conn_info.conn_state is set to disconnected only
* after the disconnect done indication from SME. If the SME is
* in the process of disconnecting, the SME Connection state is
* set to disconnected and the pHddStaCtx->conn_info.conn_state
* will still be associated till the disconnect is done.
* So check both the HDD state and SME state here.
* If not associated, no need to proceed with reassoc
*/
if (!hdd_cm_is_vdev_associated(adapter)) {
hdd_warn("Not associated");
ret = -EINVAL;
goto exit;
}
if (!sme_is_conn_state_connected(hdd_ctx->mac_handle,
adapter->vdev_id)) {
hdd_warn("Not in connected state");
ret = -EINVAL;
goto exit;
}
/*
* if the target bssid is same as currently associated AP,
* use the current connections's channel.
*/
if (!memcmp(bssid, sta_ctx->conn_info.bssid.bytes,
QDF_MAC_ADDR_SIZE)) {
hdd_warn("Reassoc BSSID is same as currently associated AP bssid");
ch_freq = sta_ctx->conn_info.chan_freq;
}
if (QDF_STATUS_SUCCESS !=
wlan_hdd_validate_operation_channel(adapter, ch_freq)) {
hdd_err("Invalid Ch freq: %d", ch_freq);
ret = -EINVAL;
goto exit;
}
if (wlan_get_connected_vdev_by_bssid(hdd_ctx->pdev, (uint8_t *)bssid,
&connected_vdev) &&
connected_vdev != adapter->vdev_id) {
hdd_err("bssid "QDF_MAC_ADDR_FMT" connected by other vdev %d",
QDF_MAC_ADDR_REF(bssid), connected_vdev);
ret = -EPERM;
goto exit;
}
/* Proceed with reassoc */
if (roaming_offload_enabled(hdd_ctx)) {
if (!hdd_is_fast_reassoc_allowed(hdd_ctx->psoc,
adapter->vdev_id)) {
hdd_err("LFR3: vdev[%d] Roaming module is not initialized",
adapter->vdev_id);
ret = -EPERM;
goto exit;
}
status = hdd_wma_send_fastreassoc_cmd(adapter, bssid, ch_freq);
if (status != QDF_STATUS_SUCCESS) {
hdd_err("Failed to send fast reassoc cmd");
ret = -EINVAL;
}
} else {
tCsrHandoffRequest handoff;
handoff.ch_freq = ch_freq;
handoff.src = src;
qdf_mem_copy(handoff.bssid.bytes, bssid, QDF_MAC_ADDR_SIZE);
sme_handoff_request(hdd_ctx->mac_handle, adapter->vdev_id,
&handoff);
}
exit:
return ret;
}
#endif /* FEATURE_CM_ENABLE */
/**
* hdd_parse_reassoc_v1() - parse version 1 of the REASSOC command
* @adapter: Adapter upon which the command was received
@@ -693,11 +551,10 @@ static int hdd_parse_reassoc_v1(struct hdd_adapter *adapter, const char *command
qdf_freq_t freq = 0;
tSirMacAddr bssid;
int ret;
#ifdef FEATURE_CM_ENABLE
struct qdf_mac_addr target_bssid;
struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
QDF_STATUS status;
#endif
struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(adapter->vdev);
ret = hdd_parse_reassoc_command_v1_data(command, bssid, &freq, pdev);
@@ -706,18 +563,12 @@ static int hdd_parse_reassoc_v1(struct hdd_adapter *adapter, const char *command
return ret;
}
#ifdef FEATURE_CM_ENABLE
qdf_mem_copy(target_bssid.bytes, bssid, sizeof(tSirMacAddr));
status = ucfg_wlan_cm_roam_invoke(hdd_ctx->pdev,
adapter->vdev_id,
&target_bssid, freq,
CM_ROAMING_HOST);
return qdf_status_to_os_return(status);
#else
ret = hdd_reassoc(adapter, bssid, freq, REASSOC);
return ret;
#endif
}
/**
@@ -741,11 +592,9 @@ static int hdd_parse_reassoc_v2(struct hdd_adapter *adapter,
tSirMacAddr bssid;
qdf_freq_t freq = 0;
int ret;
#ifdef FEATURE_CM_ENABLE
struct qdf_mac_addr target_bssid;
struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
QDF_STATUS status;
#endif
struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(adapter->vdev);
if (total_len < sizeof(params) + 8) {
@@ -769,16 +618,12 @@ static int hdd_parse_reassoc_v2(struct hdd_adapter *adapter,
if (!hdd_check_and_fill_freq(params.channel, &freq, pdev))
return -EINVAL;
#ifdef FEATURE_CM_ENABLE
qdf_mem_copy(target_bssid.bytes, bssid, sizeof(tSirMacAddr));
status = ucfg_wlan_cm_roam_invoke(hdd_ctx->pdev,
adapter->vdev_id,
&target_bssid, freq,
CM_ROAMING_HOST);
ret = qdf_status_to_os_return(status);
#else
ret = hdd_reassoc(adapter, bssid, freq, REASSOC);
#endif
}
return ret;
@@ -4613,16 +4458,7 @@ static int drv_cmd_fast_reassoc(struct hdd_adapter *adapter,
uint8_t *value = command;
qdf_freq_t freq = 0;
tSirMacAddr bssid;
#ifdef FEATURE_CM_ENABLE
struct qdf_mac_addr target_bssid;
#else
uint32_t roam_id = INVALID_ROAM_ID;
tCsrRoamModifyProfileFields mod_fields;
tCsrHandoffRequest req;
mac_handle_t mac_handle;
qdf_freq_t chan_freq;
struct qdf_mac_addr connected_bssid;
#endif
if (QDF_STA_MODE != adapter->device_mode) {
hdd_warn("Unsupported in mode %s(%d)",
@@ -4647,52 +4483,10 @@ static int drv_cmd_fast_reassoc(struct hdd_adapter *adapter,
goto exit;
}
#ifdef FEATURE_CM_ENABLE
qdf_mem_copy(target_bssid.bytes, bssid, sizeof(tSirMacAddr));
ucfg_wlan_cm_roam_invoke(hdd_ctx->pdev, adapter->vdev_id,
&target_bssid, freq, CM_ROAMING_HOST);
#else
mac_handle = hdd_ctx->mac_handle;
chan_freq = wlan_get_operation_chan_freq(adapter->vdev);
wlan_mlme_get_bssid_vdev_id(hdd_ctx->pdev, adapter->vdev_id,
&connected_bssid);
/*
* if the target bssid is same as currently associated AP,
* issue reassoc to same AP
*/
if (!qdf_mem_cmp(bssid, connected_bssid.bytes,
QDF_MAC_ADDR_SIZE)) {
hdd_warn("Reassoc BSSID is same as currently associated AP bssid");
if (roaming_offload_enabled(hdd_ctx)) {
hdd_wma_send_fastreassoc_cmd(
adapter, bssid, chan_freq);
} else {
sme_get_modify_profile_fields(mac_handle,
adapter->vdev_id,
&mod_fields);
sme_roam_reassoc(mac_handle, adapter->vdev_id,
NULL, mod_fields, &roam_id, 1);
}
return 0;
}
/* Check freq number is a valid freq number */
if (freq && QDF_STATUS_SUCCESS !=
wlan_hdd_validate_operation_channel(adapter, freq)) {
hdd_err("Invalid freq [%d]", freq);
return -EINVAL;
}
if (roaming_offload_enabled(hdd_ctx)) {
hdd_wma_send_fastreassoc_cmd(adapter, bssid, freq);
goto exit;
}
/* Proceed with reassoc */
req.ch_freq = freq;
req.src = FASTREASSOC;
qdf_mem_copy(req.bssid.bytes, bssid, sizeof(tSirMacAddr));
sme_handoff_request(mac_handle, adapter->vdev_id, &req);
#endif
exit:
return ret;
}

Zobrazit soubor

@@ -5513,10 +5513,6 @@ hdd_alloc_station_adapter(struct hdd_context *hdd_ctx, tSirMacAddr mac_addr,
adapter->offloads_configured = false;
adapter->is_link_up_service_needed = false;
/* This is temp ifdef will be removed in near future */
#ifndef FEATURE_CM_ENABLE
adapter->disconnection_in_progress = false;
#endif
adapter->send_mode_change = true;
/* Cache station count initialize to zero */
@@ -5971,9 +5967,6 @@ QDF_STATUS hdd_init_station_mode(struct hdd_adapter *adapter)
hdd_roam_profile_init(adapter);
hdd_register_wext(adapter->dev);
#ifndef FEATURE_CM_ENABLE
hdd_conn_set_connection_state(adapter, eConnectionState_NotConnected);
#endif
/* set fast roaming capability in sme session */
status = ucfg_user_space_enable_disable_rso(hdd_ctx->pdev,
adapter->vdev_id,
@@ -6266,10 +6259,6 @@ static void hdd_cleanup_adapter(struct hdd_context *hdd_ctx,
hdd_nud_deinit_tracking(adapter);
hdd_mic_deinit_work(adapter);
/* This is temp ifdef will be removed in near future */
#ifndef FEATURE_CM_ENABLE
qdf_mutex_destroy(&adapter->disconnection_status_lock);
#endif
hdd_periodic_sta_stats_mutex_destroy(adapter);
hdd_apf_context_destroy(adapter);
qdf_spinlock_destroy(&adapter->vdev_lock);
@@ -6776,9 +6765,6 @@ error:
static void hdd_init_completion(struct hdd_adapter *adapter)
{
init_completion(&adapter->disconnect_comp_var);
#ifndef FEATURE_CM_ENABLE
init_completion(&adapter->roaming_comp_var);
#endif
init_completion(&adapter->linkup_event_var);
init_completion(&adapter->sta_authorized_event);
init_completion(&adapter->offchannel_tx_event);
@@ -7062,11 +7048,6 @@ struct hdd_adapter *hdd_open_adapter(struct hdd_context *hdd_ctx, uint8_t sessio
hdd_sta_info_init(&adapter->sta_info_list);
hdd_sta_info_init(&adapter->cache_sta_info_list);
/* This is temp ifdef will be removed in near future */
#ifndef FEATURE_CM_ENABLE
qdf_mutex_create(&adapter->disconnection_status_lock);
#endif
for (i = 0; i < NET_DEV_HOLD_ID_MAX; i++)
qdf_atomic_init(
&adapter->net_dev_hold_ref_count[NET_DEV_HOLD_ID_MAX]);
@@ -7372,14 +7353,9 @@ QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx,
sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
if (adapter->device_mode == QDF_NDI_MODE ||
#ifdef FEATURE_CM_ENABLE
((adapter->device_mode == QDF_STA_MODE ||
adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
!hdd_cm_is_disconnected(adapter))
#else
hdd_cm_is_vdev_associated(adapter) ||
hdd_cm_is_connecting(adapter)
#endif
) {
INIT_COMPLETION(adapter->disconnect_comp_var);
if (cds_is_driver_recovering())
@@ -7404,11 +7380,6 @@ QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx,
}
} else if (adapter->device_mode == QDF_STA_MODE ||
adapter->device_mode == QDF_P2P_CLIENT_MODE) {
/*
* This is temp ifdef will be removed in near
* future
*/
#ifdef FEATURE_CM_ENABLE
/*
* On vdev delete wait for disconnect to
* complete. i.e use sync API, so that the
@@ -7419,15 +7390,6 @@ QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx,
status = wlan_hdd_cm_issue_disconnect(adapter,
reason,
true);
#else
status = QDF_STATUS_SUCCESS;
rc = wlan_hdd_disconnect(
adapter,
eCSR_DISCONNECT_REASON_DEAUTH,
reason);
if (rc != 0)
status = QDF_STATUS_E_TIMEOUT;
#endif
if (QDF_IS_STATUS_ERROR(status) &&
ucfg_ipa_is_enabled()) {
hdd_err("STA disconnect failed");
@@ -7936,13 +7898,6 @@ QDF_STATUS hdd_reset_all_adapters(struct hdd_context *hdd_ctx)
clear_bit(WMM_INIT_DONE, &adapter->event_flags);
}
/* This is temp ifdef will be removed in near future */
#ifndef FEATURE_CM_ENABLE
if (adapter->device_mode != QDF_SAP_MODE &&
adapter->device_mode != QDF_P2P_GO_MODE &&
adapter->device_mode != QDF_FTM_MODE)
hdd_set_disconnect_status(adapter, false);
#endif
hdd_debug("Flush any mgmt references held by peer");
hdd_stop_adapter(hdd_ctx, adapter);
hdd_adapter_dev_put_debug(adapter,
@@ -7987,515 +7942,6 @@ bool hdd_is_interface_up(struct hdd_adapter *adapter)
else
return false;
}
#ifndef FEATURE_CM_ENABLE
#if defined CFG80211_CONNECT_BSS || \
(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
#if defined CFG80211_CONNECT_TIMEOUT_REASON_CODE || \
(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) || \
(defined(WLAN_FEATURE_FILS_SK) && \
(defined(CFG80211_CONNECT_DONE)))
/**
* hdd_convert_timeout_reason() - Convert to kernel specific enum
* @timeout_reason: reason for connect timeout
*
* This function is used to convert host timeout
* reason enum to kernel specific enum.
*
* Return: nl timeout enum
*/
static enum nl80211_timeout_reason hdd_convert_timeout_reason(
tSirResultCodes timeout_reason)
{
switch (timeout_reason) {
case eSIR_SME_JOIN_TIMEOUT_RESULT_CODE:
return NL80211_TIMEOUT_SCAN;
case eSIR_SME_AUTH_TIMEOUT_RESULT_CODE:
return NL80211_TIMEOUT_AUTH;
case eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE:
return NL80211_TIMEOUT_ASSOC;
default:
return NL80211_TIMEOUT_UNSPECIFIED;
}
}
#endif
#if defined CFG80211_CONNECT_TIMEOUT_REASON_CODE || \
(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
/**
* hdd_cfg80211_connect_timeout() - API to send connection timeout reason
* @dev: network device
* @bssid: bssid to which we want to associate
* @timeout_reason: reason for connect timeout
*
* This API is used to send connection timeout reason to supplicant
*
* Return: void
*/
static void hdd_cfg80211_connect_timeout(struct net_device *dev,
const u8 *bssid,
tSirResultCodes timeout_reason)
{
enum nl80211_timeout_reason nl_timeout_reason;
nl_timeout_reason = hdd_convert_timeout_reason(timeout_reason);
cfg80211_connect_timeout(dev, bssid, NULL, 0, GFP_KERNEL,
nl_timeout_reason);
}
/**
* __hdd_connect_bss() - API to send connection status to supplicant
* @dev: network device
* @bssid: bssid to which we want to associate
* @req_ie: Request Information Element
* @req_ie_len: len of the req IE
* @resp_ie: Response IE
* @resp_ie_len: len of ht response IE
* @status: status
* @gfp: Kernel Flag
* @timeout_reason: reason for connect timeout
*
* Return: void
*/
static void __hdd_connect_bss(struct net_device *dev, const u8 *bssid,
struct cfg80211_bss *bss, const u8 *req_ie,
size_t req_ie_len, const u8 *resp_ie,
size_t resp_ie_len, int status, gfp_t gfp,
tSirResultCodes timeout_reason)
{
enum nl80211_timeout_reason nl_timeout_reason;
nl_timeout_reason = hdd_convert_timeout_reason(timeout_reason);
cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
resp_ie, resp_ie_len, status, gfp,
nl_timeout_reason);
}
#else
#if defined CFG80211_CONNECT_TIMEOUT || \
(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
static void hdd_cfg80211_connect_timeout(struct net_device *dev,
const u8 *bssid,
tSirResultCodes timeout_reason)
{
cfg80211_connect_timeout(dev, bssid, NULL, 0, GFP_KERNEL);
}
#endif
static void __hdd_connect_bss(struct net_device *dev, const u8 *bssid,
struct cfg80211_bss *bss, const u8 *req_ie,
size_t req_ie_len, const u8 *resp_ie,
size_t resp_ie_len, int status, gfp_t gfp,
tSirResultCodes timeout_reason)
{
cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
resp_ie, resp_ie_len, status, gfp);
}
#endif
/**
* hdd_connect_bss() - API to send connection status to supplicant
* @dev: network device
* @bssid: bssid to which we want to associate
* @req_ie: Request Information Element
* @req_ie_len: len of the req IE
* @resp_ie: Response IE
* @resp_ie_len: len of ht response IE
* @status: status
* @gfp: Kernel Flag
* @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
* @timeout_reason: reason for connect timeout
*
* The API is a wrapper to send connection status to supplicant
*
* Return: Void
*/
#if defined CFG80211_CONNECT_TIMEOUT || \
(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
struct cfg80211_bss *bss, const u8 *req_ie,
size_t req_ie_len, const u8 *resp_ie,
size_t resp_ie_len, int status, gfp_t gfp,
bool connect_timeout,
tSirResultCodes timeout_reason)
{
if (connect_timeout)
hdd_cfg80211_connect_timeout(dev, bssid, timeout_reason);
else
__hdd_connect_bss(dev, bssid, bss, req_ie, req_ie_len, resp_ie,
resp_ie_len, status, gfp, timeout_reason);
}
#else
static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
struct cfg80211_bss *bss, const u8 *req_ie,
size_t req_ie_len, const u8 *resp_ie,
size_t resp_ie_len, int status, gfp_t gfp,
bool connect_timeout,
tSirResultCodes timeout_reason)
{
__hdd_connect_bss(dev, bssid, bss, req_ie, req_ie_len, resp_ie,
resp_ie_len, status, gfp, timeout_reason);
}
#endif
#if defined(WLAN_FEATURE_FILS_SK)
#if (defined(CFG80211_CONNECT_DONE) || \
(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))) && \
(LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0))
#if defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
/**
* hdd_populate_fils_params() - Populate FILS keys to connect response
* @fils_params: connect response to supplicant
* @fils_kek: FILS kek
* @fils_kek_len: FILS kek length
* @pmk: FILS PMK
* @pmk_len: FILS PMK length
* @pmkid: PMKID
* @fils_seq_num: FILS Seq number
*
* Return: None
*/
static void hdd_populate_fils_params(struct cfg80211_connect_resp_params
*fils_params, const uint8_t *fils_kek,
size_t fils_kek_len, const uint8_t *pmk,
size_t pmk_len, const uint8_t *pmkid,
uint16_t fils_seq_num)
{
/* Increament seq number to be used for next FILS */
fils_params->fils_erp_next_seq_num = fils_seq_num + 1;
fils_params->update_erp_next_seq_num = true;
fils_params->fils_kek = fils_kek;
fils_params->fils_kek_len = fils_kek_len;
fils_params->pmk = pmk;
fils_params->pmk_len = pmk_len;
fils_params->pmkid = pmkid;
hdd_debug("FILS erp_next_seq_num:%d",
fils_params->fils_erp_next_seq_num);
}
#else
static inline void hdd_populate_fils_params(struct cfg80211_connect_resp_params
*fils_params, const uint8_t
*fils_kek, size_t fils_kek_len,
const uint8_t *pmk, size_t pmk_len,
const uint8_t *pmkid,
uint16_t fils_seq_num)
{ }
#endif
#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0))
/**
* hdd_populate_fils_params() - Populate FILS keys to connect response
* @fils_params: connect response to supplicant
* @fils_kek: FILS kek
* @fils_kek_len: FILS kek length
* @pmk: FILS PMK
* @pmk_len: FILS PMK length
* @pmkid: PMKID
* @fils_seq_num: FILS Seq number
*
* Return: None
*/
static void hdd_populate_fils_params(struct cfg80211_connect_resp_params
*fils_params, const uint8_t *fils_kek,
size_t fils_kek_len, const uint8_t *pmk,
size_t pmk_len, const uint8_t *pmkid,
uint16_t fils_seq_num)
{
/* Increament seq number to be used for next FILS */
fils_params->fils.erp_next_seq_num = fils_seq_num + 1;
fils_params->fils.update_erp_next_seq_num = true;
fils_params->fils.kek = fils_kek;
fils_params->fils.kek_len = fils_kek_len;
fils_params->fils.pmk = pmk;
fils_params->fils.pmk_len = pmk_len;
fils_params->fils.pmkid = pmkid;
hdd_debug("FILS erp_next_seq_num:%d",
fils_params->fils.erp_next_seq_num);
}
#endif /* CFG80211_CONNECT_DONE */
#if defined(CFG80211_CONNECT_DONE) || \
(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
void hdd_update_hlp_info(struct net_device *dev,
struct csr_roam_info *roam_info)
{
struct sk_buff *skb;
uint16_t skb_len;
struct llc_snap_hdr_t *llc_hdr;
QDF_STATUS status;
uint8_t *hlp_data;
uint16_t hlp_data_len;
struct fils_join_rsp_params *roam_fils_params
= roam_info->fils_join_rsp;
struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (!roam_fils_params) {
hdd_err("FILS Roam Param NULL");
return;
}
if (!roam_fils_params->hlp_data_len) {
hdd_debug("FILS HLP Data NULL, len %d",
roam_fils_params->hlp_data_len);
return;
}
hlp_data = roam_fils_params->hlp_data;
hlp_data_len = roam_fils_params->hlp_data_len;
/* Calculate skb length */
skb_len = (2 * ETH_ALEN) + hlp_data_len;
skb = qdf_nbuf_alloc(NULL, skb_len, 0, 4, false);
if (!skb) {
hdd_err("HLP packet nbuf alloc fails");
return;
}
qdf_mem_copy(skb_put(skb, ETH_ALEN), roam_fils_params->dst_mac.bytes,
QDF_MAC_ADDR_SIZE);
qdf_mem_copy(skb_put(skb, ETH_ALEN), roam_fils_params->src_mac.bytes,
QDF_MAC_ADDR_SIZE);
llc_hdr = (struct llc_snap_hdr_t *) hlp_data;
if (IS_SNAP(llc_hdr)) {
hlp_data += LLC_SNAP_HDR_OFFSET_ETHERTYPE;
hlp_data_len += LLC_SNAP_HDR_OFFSET_ETHERTYPE;
}
qdf_mem_copy(skb_put(skb, hlp_data_len), hlp_data, hlp_data_len);
/*
* This HLP packet is formed from HLP info encapsulated
* in assoc response frame which is AEAD encrypted.
* Hence, this checksum validation can be set unnecessary.
* i.e. network layer need not worry about checksum.
*/
skb->ip_summed = CHECKSUM_UNNECESSARY;
status = hdd_rx_packet_cbk(adapter, skb);
if (QDF_IS_STATUS_ERROR(status)) {
hdd_err("Sending HLP packet fails");
return;
}
hdd_debug("send HLP packet to netif successfully");
}
/**
* hdd_connect_done() - Wrapper API to call cfg80211_connect_done
* @dev: network device
* @bssid: bssid to which we want to associate
* @bss: cfg80211 bss info
* @roam_info: information about connected bss
* @req_ie: Request Information Element
* @req_ie_len: len of the req IE
* @resp_ie: Response IE
* @resp_ie_len: len of ht response IE
* @status: status
* @gfp: allocation flags
* @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
* @timeout_reason: reason for connect timeout
*
* This API is used as wrapper to send FILS key/sequence number
* params etc. to supplicant in case of FILS connection
*
* Return: None
*/
static void hdd_connect_done(struct net_device *dev, const u8 *bssid,
struct cfg80211_bss *bss,
struct csr_roam_info *roam_info,
const u8 *req_ie, size_t req_ie_len,
const u8 *resp_ie, size_t resp_ie_len, u16 status,
gfp_t gfp, bool connect_timeout,
tSirResultCodes timeout_reason)
{
struct cfg80211_connect_resp_params fils_params;
struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
struct fils_join_rsp_params *roam_fils_params =
roam_info->fils_join_rsp;
qdf_mem_zero(&fils_params, sizeof(fils_params));
if (!roam_fils_params) {
fils_params.status = WLAN_STATUS_UNSPECIFIED_FAILURE;
} else {
fils_params.status = status;
fils_params.bssid = bssid;
fils_params.timeout_reason =
hdd_convert_timeout_reason(timeout_reason);
fils_params.req_ie = req_ie;
fils_params.req_ie_len = req_ie_len;
fils_params.resp_ie = resp_ie;
fils_params.resp_ie_len = resp_ie_len;
fils_params.bss = bss;
hdd_populate_fils_params(&fils_params, roam_fils_params->kek,
roam_fils_params->kek_len,
roam_fils_params->fils_pmk,
roam_fils_params->fils_pmk_len,
roam_fils_params->fils_pmkid,
roam_info->fils_seq_num);
hdd_save_gtk_params(adapter, roam_info, false);
}
hdd_debug("FILS indicate connect status %d", fils_params.status);
cfg80211_connect_done(dev, &fils_params, gfp);
if (roam_fils_params && roam_fils_params->hlp_data_len)
hdd_update_hlp_info(dev, roam_info);
/* Clear all the FILS key info */
if (roam_fils_params && roam_fils_params->fils_pmk)
qdf_mem_free(roam_fils_params->fils_pmk);
if (roam_fils_params)
qdf_mem_free(roam_fils_params);
roam_info->fils_join_rsp = NULL;
}
#else /* CFG80211_CONNECT_DONE */
static inline void
hdd_connect_done(struct net_device *dev, const u8 *bssid,
struct cfg80211_bss *bss, struct csr_roam_info *roam_info,
const u8 *req_ie, size_t req_ie_len,
const u8 *resp_ie, size_t resp_ie_len, u16 status,
gfp_t gfp, bool connect_timeout,
tSirResultCodes timeout_reason)
{ }
#endif
#endif /* WLAN_FEATURE_FILS_SK */
#if defined(WLAN_FEATURE_FILS_SK) && \
(defined(CFG80211_CONNECT_DONE) || \
(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)))
/**
* hdd_fils_update_connect_results() - API to send fils connection status to
* supplicant.
* @dev: network device
* @bssid: bssid to which we want to associate
* @bss: cfg80211 bss info
* @roam_info: information about connected bss
* @req_ie: Request Information Element
* @req_ie_len: len of the req IE
* @resp_ie: Response IE
* @resp_ie_len: len of ht response IE
* @status: status
* @gfp: allocation flags
* @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
* @timeout_reason: reason for connect timeout
*
* The API is a wrapper to send connection status to supplicant
*
* Return: 0 if success else failure
*/
static int hdd_fils_update_connect_results(struct net_device *dev,
const u8 *bssid,
struct cfg80211_bss *bss,
struct csr_roam_info *roam_info, const u8 *req_ie,
size_t req_ie_len, const u8 *resp_ie,
size_t resp_ie_len, u16 status, gfp_t gfp,
bool connect_timeout,
tSirResultCodes timeout_reason)
{
hdd_enter();
if (!roam_info || !roam_info->is_fils_connection)
return -EINVAL;
hdd_connect_done(dev, bssid, bss, roam_info, req_ie, req_ie_len,
resp_ie, resp_ie_len, status, gfp, connect_timeout,
timeout_reason);
return 0;
}
#else
static inline int hdd_fils_update_connect_results(struct net_device *dev,
const u8 *bssid,
struct cfg80211_bss *bss,
struct csr_roam_info *roam_info, const u8 *req_ie,
size_t req_ie_len, const u8 *resp_ie,
size_t resp_ie_len, u16 status, gfp_t gfp,
bool connect_timeout,
tSirResultCodes timeout_reason)
{
return -EINVAL;
}
#endif
/**
* hdd_connect_result() - API to send connection status to supplicant
* @dev: network device
* @bssid: bssid to which we want to associate
* @roam_info: information about connected bss
* @req_ie: Request Information Element
* @req_ie_len: len of the req IE
* @resp_ie: Response IE
* @resp_ie_len: len of ht response IE
* @status: status
* @gfp: Kernel Flag
* @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
* @timeout_reason: reason for connect timeout
*
* The API is a wrapper to send connection status to supplicant
* and allow runtime suspend
*
* Return: Void
*/
void hdd_connect_result(struct net_device *dev, const u8 *bssid,
struct csr_roam_info *roam_info, const u8 *req_ie,
size_t req_ie_len, const u8 *resp_ie,
size_t resp_ie_len, u16 status, gfp_t gfp,
bool connect_timeout,
tSirResultCodes timeout_reason)
{
struct hdd_adapter *adapter = netdev_priv(dev);
struct cfg80211_bss *bss = NULL;
struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
if (WLAN_STATUS_SUCCESS == status) {
struct ieee80211_channel *chan;
struct wlan_ssid ssid;
wlan_mlme_get_ssid_vdev_id(hdd_ctx->pdev, adapter->vdev_id,
ssid.ssid, &ssid.length);
chan = ieee80211_get_channel(adapter->wdev.wiphy,
roam_info->bss_desc->chan_freq);
bss = wlan_cfg80211_get_bss(adapter->wdev.wiphy, chan, bssid,
ssid.ssid, ssid.length);
}
wlan_rec_conn_info(adapter->vdev_id, DEBUG_CONN_CONNECT_RESULT,
bssid ? bssid : NULL,
status << 16 | connect_timeout, timeout_reason);
if (hdd_fils_update_connect_results(dev, bssid, bss,
roam_info, req_ie, req_ie_len, resp_ie,
resp_ie_len, status, gfp, connect_timeout,
timeout_reason) != 0) {
hdd_connect_bss(dev, bssid, bss, req_ie,
req_ie_len, resp_ie, resp_ie_len,
status, gfp, connect_timeout, timeout_reason);
}
qdf_runtime_pm_allow_suspend(&hdd_ctx->runtime_context.connect);
hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_CONNECT);
}
#else
void hdd_connect_result(struct net_device *dev, const u8 *bssid,
struct csr_roam_info *roam_info, const u8 *req_ie,
size_t req_ie_len, const u8 *resp_ie,
size_t resp_ie_len, u16 status, gfp_t gfp,
bool connect_timeout,
tSirResultCodes timeout_reason)
{
struct hdd_adapter *adapter = netdev_priv(dev);
struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
cfg80211_connect_result(dev, bssid, req_ie, req_ie_len,
resp_ie, resp_ie_len, status, gfp);
qdf_runtime_pm_allow_suspend(&hdd_ctx->runtime_context.connect);
hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_CONNECT);
}
#endif
#endif /* ifndef FEATURE_CM_ENABLE*/
#ifdef FEATURE_MONITOR_MODE_SUPPORT
int wlan_hdd_set_mon_chan(struct hdd_adapter *adapter, qdf_freq_t freq,
@@ -9288,16 +8734,6 @@ static QDF_STATUS hdd_abort_sched_scan_all_adapters(struct hdd_context *hdd_ctx)
return QDF_STATUS_SUCCESS;
}
#ifndef FEATURE_CM_ENABLE
void hdd_set_disconnect_status(struct hdd_adapter *adapter, bool status)
{
qdf_mutex_acquire(&adapter->disconnection_status_lock);
adapter->disconnection_in_progress = status;
qdf_mutex_release(&adapter->disconnection_status_lock);
}
#endif
/**
* hdd_unregister_notifiers - Unregister netdev notifiers.
* @hdd_ctx: HDD context
@@ -19045,10 +18481,6 @@ wlan_hdd_add_monitor_check(struct hdd_context *hdd_ctx,
struct hdd_adapter *mon_adapter;
uint8_t num_open_session = 0;
QDF_STATUS status;
#ifndef FEATURE_CM_ENABLE
int errno;
#endif
/* if no interface is up do not add monitor mode */
if (!hdd_is_any_interface_open(hdd_ctx))
@@ -19079,19 +18511,9 @@ wlan_hdd_add_monitor_check(struct hdd_context *hdd_ctx,
if (num_open_session == 1) {
hdd_ctx->disconnect_for_sta_mon_conc = true;
/* Try disconnecting if already in connected state */
/* This is temp ifdef will be removed in near future */
#ifdef FEATURE_CM_ENABLE
wlan_hdd_cm_issue_disconnect(sta_adapter,
REASON_UNSPEC_FAILURE,
true);
#else
errno = wlan_hdd_try_disconnect(sta_adapter,
REASON_UNSPEC_FAILURE);
if (errno > 0) {
hdd_err("Failed to disconnect the existing connection");
return -EALREADY;
}
#endif
}
}

Zobrazit soubor

@@ -235,20 +235,8 @@ hdd_handle_nud_fail_sta(struct hdd_context *hdd_ctx,
{
struct reject_ap_info ap_info;
struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
#ifdef FEATURE_CM_ENABLE
struct qdf_mac_addr bssid;
#endif
/* This is temp ifdef will be removed in near future */
#ifndef FEATURE_CM_ENABLE
qdf_mutex_acquire(&adapter->disconnection_status_lock);
if (adapter->disconnection_in_progress) {
qdf_mutex_release(&adapter->disconnection_status_lock);
hdd_debug("Disconnect is in progress");
return;
}
qdf_mutex_release(&adapter->disconnection_status_lock);
#endif
if (hdd_is_roaming_in_progress(hdd_ctx)) {
hdd_debug("Roaming already in progress, cannot trigger roam.");
return;
@@ -264,51 +252,19 @@ hdd_handle_nud_fail_sta(struct hdd_context *hdd_ctx,
ucfg_blm_add_bssid_to_reject_list(hdd_ctx->pdev, &ap_info);
if (roaming_offload_enabled(hdd_ctx)) {
#ifndef FEATURE_CM_ENABLE
sme_roam_invoke_nud_fail(hdd_ctx->mac_handle,
adapter->vdev_id);
#else
qdf_zero_macaddr(&bssid);
ucfg_wlan_cm_roam_invoke(hdd_ctx->pdev,
adapter->vdev_id,
&bssid, 0, CM_ROAMING_NUD_FAILURE);
#endif
}
}
static void
hdd_handle_nud_fail_non_sta(struct hdd_adapter *adapter)
{
/* This is temp ifdef will be removed in near future */
#ifdef FEATURE_CM_ENABLE
wlan_hdd_cm_issue_disconnect(adapter,
REASON_GATEWAY_REACHABILITY_FAILURE,
false);
#else
int status;
qdf_mutex_acquire(&adapter->disconnection_status_lock);
if (adapter->disconnection_in_progress) {
qdf_mutex_release(&adapter->disconnection_status_lock);
hdd_debug("Disconnect is in progress");
return;
}
adapter->disconnection_in_progress = true;
qdf_mutex_release(&adapter->disconnection_status_lock);
hdd_debug("Disconnecting vdev with vdev id: %d",
adapter->vdev_id);
/* Issue Disconnect */
status = wlan_hdd_disconnect(adapter, eCSR_DISCONNECT_REASON_DEAUTH,
REASON_GATEWAY_REACHABILITY_FAILURE);
if (0 != status) {
hdd_err("wlan_hdd_disconnect failed, status: %d",
status);
hdd_set_disconnect_status(adapter, false);
}
#endif
}
#ifdef WLAN_NUD_TRACKING

Zobrazit soubor

@@ -1841,10 +1841,6 @@ QDF_STATUS hdd_wlan_re_init(void)
hdd_start_all_adapters(hdd_ctx);
hdd_init_scan_reject_params(hdd_ctx);
#ifndef FEATURE_CM_ENABLE
complete(&adapter->roaming_comp_var);
#endif
hdd_ctx->bt_coex_mode_set = false;
/* Allow the phone to go to sleep */

Zobrazit soubor

@@ -1491,18 +1491,9 @@ static void hdd_country_change_update_sta(struct hdd_context *hdd_ctx)
phy_changed = (sta_ctx->reg_phymode != csr_phy_mode);
if (phy_changed || freq_changed) {
/* This is temp ifdef will be removed in near future */
#ifdef FEATURE_CM_ENABLE
wlan_hdd_cm_issue_disconnect(adapter,
REASON_UNSPEC_FAILURE,
false);
#else
sme_roam_disconnect(
hdd_ctx->mac_handle,
adapter->vdev_id,
eCSR_DISCONNECT_REASON_UNSPECIFIED,
REASON_UNSPEC_FAILURE);
#endif
sta_ctx->reg_phymode = csr_phy_mode;
}
break;

Zobrazit soubor

@@ -310,20 +310,6 @@ void hdd_init_scan_reject_params(struct hdd_context *hdd_ctx)
}
}
#ifndef FEATURE_CM_ENABLE
void hdd_reset_scan_reject_params(struct hdd_context *hdd_ctx,
eRoamCmdStatus roam_status,
eCsrRoamResult roam_result)
{
if ((roam_status == eCSR_ROAM_ASSOCIATION_FAILURE) ||
(roam_status == eCSR_ROAM_CANCELLED) ||
(roam_result == eCSR_ROAM_RESULT_ASSOCIATED)) {
hdd_debug("Reset scan reject params");
hdd_init_scan_reject_params(hdd_ctx);
}
}
#endif
/*
* wlan_hdd_update_scan_ies() - API to update the scan IEs of scan request
* with already stored default scan IEs
@@ -655,20 +641,6 @@ static int __wlan_hdd_cfg80211_scan(struct wiphy *wiphy,
}
}
#ifndef FEATURE_CM_ENABLE
if ((QDF_STA_MODE == adapter->device_mode) ||
(QDF_P2P_CLIENT_MODE == adapter->device_mode) ||
(QDF_P2P_DEVICE_MODE == adapter->device_mode)) {
struct csr_roam_profile *roam_profile =
hdd_roam_profile(adapter);
roam_profile->pAddIEScan =
scan_info->scan_add_ie.addIEdata;
roam_profile->nAddIEScanLength =
scan_info->scan_add_ie.length;
}
#endif
if (QDF_P2P_CLIENT_MODE == adapter->device_mode ||
QDF_P2P_DEVICE_MODE == adapter->device_mode) {
/* Disable NAN Discovery if enabled */

Zobrazit soubor

@@ -130,21 +130,6 @@ void wlan_hdd_cfg80211_abort_scan(struct wiphy *wiphy,
*/
void hdd_init_scan_reject_params(struct hdd_context *hdd_ctx);
#ifndef FEATURE_CM_ENABLE
/**
* hdd_reset_scan_reject_params() - reset scan reject params per roam stats
* @hdd_ctx: hdd contxt
* @roam_status: roam status
* @roam_result: roam result
*
* Return: None
*/
void hdd_reset_scan_reject_params(struct hdd_context *hdd_ctx,
eRoamCmdStatus roam_status,
eCsrRoamResult roam_result);
#endif
/**
* wlan_hdd_cfg80211_scan_block() - scan block handler
* @adapter: HDD adapter to work against

Zobrazit soubor

@@ -36,11 +36,6 @@ __wlan_hdd_store_reassoc_sysfs(struct net_device *net_dev, char const *buf,
mac_handle_t mac_handle;
uint32_t operating_ch;
int ret;
#ifndef FEATURE_CM_ENABLE
tCsrRoamModifyProfileFields mod_fields;
uint32_t roam_id = INVALID_ROAM_ID;
tSirMacAddr bssid;
#endif
struct qdf_mac_addr target_bssid;
if (hdd_validate_adapter(adapter))
@@ -59,25 +54,8 @@ __wlan_hdd_store_reassoc_sysfs(struct net_device *net_dev, char const *buf,
wlan_mlme_get_bssid_vdev_id(hdd_ctx->pdev, adapter->vdev_id,
&target_bssid);
hdd_debug("reassoc: net_devname %s", net_dev->name);
#ifdef FEATURE_CM_ENABLE
ucfg_wlan_cm_roam_invoke(hdd_ctx->pdev, adapter->vdev_id,
&target_bssid, operating_ch, CM_ROAMING_HOST);
#else
sme_get_modify_profile_fields(mac_handle, adapter->vdev_id,
&mod_fields);
if (roaming_offload_enabled(hdd_ctx)) {
qdf_mem_copy(bssid,
&target_bssid,
sizeof(bssid));
hdd_wma_send_fastreassoc_cmd(adapter,
bssid, operating_ch);
} else {
sme_roam_reassoc(mac_handle, adapter->vdev_id,
NULL, mod_fields, &roam_id, 1);
}
#endif
return count;
}

Zobrazit soubor

@@ -6591,36 +6591,15 @@ static int __iw_setnone_getnone(struct net_device *dev,
case WE_SET_REASSOC_TRIGGER:
{
struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
#ifndef FEATURE_CM_ENABLE
tSirMacAddr bssid;
tCsrRoamModifyProfileFields mod_fields;
uint32_t roam_id = INVALID_ROAM_ID;
#endif
uint8_t operating_ch =
wlan_get_operation_chan_freq(adapter->vdev);
struct qdf_mac_addr target_bssid;
wlan_mlme_get_bssid_vdev_id(hdd_ctx->pdev, adapter->vdev_id,
&target_bssid);
#ifdef FEATURE_CM_ENABLE
ucfg_wlan_cm_roam_invoke(hdd_ctx->pdev, adapter->vdev_id,
&target_bssid, operating_ch,
CM_ROAMING_HOST);
#else
sme_get_modify_profile_fields(mac_handle, adapter->vdev_id,
&mod_fields);
if (roaming_offload_enabled(hdd_ctx)) {
qdf_mem_copy(bssid,
&target_bssid,
sizeof(bssid));
hdd_wma_send_fastreassoc_cmd(adapter,
bssid, operating_ch);
} else {
sme_roam_reassoc(mac_handle, adapter->vdev_id,
NULL, mod_fields, &roam_id, 1);
}
#endif
return 0;
}

Zobrazit soubor

@@ -2361,73 +2361,20 @@ QDF_STATUS hdd_wmm_connect(struct hdd_adapter *adapter,
bool qap = true;
bool qos_connection = true;
uint8_t acm_mask = 0x0;
#ifndef FEATURE_CM_ENABLE
mac_handle_t mac_handle;
#endif
#ifndef FEATURE_CM_ENABLE
if ((eCSR_BSS_TYPE_INFRASTRUCTURE == bss_type) &&
roam_info && roam_info->u.pConnectedProfile) {
qap = roam_info->u.pConnectedProfile->qap;
qos_connection = roam_info->u.pConnectedProfile->qosConnection;
acm_mask = roam_info->u.pConnectedProfile->acm_mask;
}
#endif
hdd_debug("qap is %d, qos_connection is %d, acm_mask is 0x%x",
qap, qos_connection, acm_mask);
adapter->hdd_wmm_status.qap = qap;
adapter->hdd_wmm_status.qos_connection = qos_connection;
#ifndef FEATURE_CM_ENABLE
mac_handle = hdd_adapter_get_mac_handle(adapter);
for (ac = 0; ac < WLAN_MAX_AC; ac++) {
if (qap && qos_connection && (acm_mask & acm_mask_bit[ac])) {
hdd_debug("ac %d on", ac);
/* admission is required */
adapter->hdd_wmm_status.ac_status[ac].
is_access_required = true;
adapter->hdd_wmm_status.ac_status[ac].
is_access_allowed = false;
adapter->hdd_wmm_status.ac_status[ac].
was_access_granted = false;
/* after reassoc if we have valid tspec, allow access */
if (adapter->hdd_wmm_status.ac_status[ac].
is_tspec_valid
&& (adapter->hdd_wmm_status.ac_status[ac].
tspec.ts_info.direction !=
SME_QOS_WMM_TS_DIR_DOWNLINK)) {
adapter->hdd_wmm_status.ac_status[ac].
is_access_allowed = true;
}
if (!roam_info->fReassocReq &&
!sme_neighbor_roam_is11r_assoc(
mac_handle,
adapter->vdev_id) &&
!sme_roam_is_ese_assoc(roam_info)) {
adapter->hdd_wmm_status.ac_status[ac].
is_tspec_valid = false;
adapter->hdd_wmm_status.ac_status[ac].
is_access_allowed = false;
}
} else {
hdd_debug("ac %d off", ac);
/* admission is not required so access is allowed */
adapter->hdd_wmm_status.ac_status[ac].
is_access_required = false;
adapter->hdd_wmm_status.ac_status[ac].
is_access_allowed = true;
}
}
#else
for (ac = 0; ac < WLAN_MAX_AC; ac++) {
hdd_debug("ac %d off", ac);
/* admission is not required so access is allowed */
adapter->hdd_wmm_status.ac_status[ac].is_access_required = false;
adapter->hdd_wmm_status.ac_status[ac].is_access_allowed = true;
}
#endif
return QDF_STATUS_SUCCESS;
}