diff --git a/components/mlme/core/inc/wlan_mlme_main.h b/components/mlme/core/inc/wlan_mlme_main.h index 91596c6486..1f8d2c8528 100644 --- a/components/mlme/core/inc/wlan_mlme_main.h +++ b/components/mlme/core/inc/wlan_mlme_main.h @@ -59,10 +59,14 @@ struct wlan_ies { * originated from driver * @peer_discon_ies: Disconnect IEs received in deauth/disassoc frames * from peer + * @discon_reason: Disconnect reason as per enum eSirMacReasonCodes + * @from_ap: True if the disconnection is initiated from AP */ struct wlan_disconnect_info { struct wlan_ies self_discon_ies; struct wlan_ies peer_discon_ies; + uint32_t discon_reason; + bool from_ap; }; /** @@ -360,6 +364,39 @@ void mlme_set_peer_pmf_status(struct wlan_objmgr_peer *peer, */ bool mlme_get_peer_pmf_status(struct wlan_objmgr_peer *peer); +/** + * mlme_set_discon_reason_n_from_ap() - set disconnect reason and from ap flag + * @psoc: PSOC pointer + * @vdev_id: vdev id + * @from_ap: True if the disconnect is initiated from peer. + * False otherwise. + * @reason_code: The disconnect code received from peer or internally generated. + * + * Set the reason code and from_ap. + * + * Return: void + */ +void mlme_set_discon_reason_n_from_ap(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, bool from_ap, + uint32_t reason_code); + +/** + * mlme_get_discon_reason_n_from_ap() - Get disconnect reason and from ap flag + * @psoc: PSOC pointer + * @vdev_id: vdev id + * @from_ap: Get the from_ap cached through mlme_set_discon_reason_n_from_ap + * and copy to this buffer. + * @reason_code: Get the reason_code cached through + * mlme_set_discon_reason_n_from_ap and copy to this buffer. + * + * Copy the contents of from_ap and reason_code to given buffers. + * + * Return: void + */ +void mlme_get_discon_reason_n_from_ap(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, bool *from_ap, + uint32_t *reason_code); + #if defined(WLAN_FEATURE_HOST_ROAM) || defined(WLAN_FEATURE_ROAM_OFFLOAD) /** * mlme_get_supplicant_disabled_roaming() - Get supplicant disabled roaming diff --git a/components/mlme/core/src/wlan_mlme_main.c b/components/mlme/core/src/wlan_mlme_main.c index c08614b66d..f20f5af546 100644 --- a/components/mlme/core/src/wlan_mlme_main.c +++ b/components/mlme/core/src/wlan_mlme_main.c @@ -2564,6 +2564,60 @@ bool mlme_get_peer_pmf_status(struct wlan_objmgr_peer *peer) return peer_priv->is_pmf_enabled; } +void mlme_set_discon_reason_n_from_ap(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, bool from_ap, + uint32_t reason_code) +{ + struct wlan_objmgr_vdev *vdev; + struct mlme_legacy_priv *mlme_priv; + + if (!psoc) + return; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, + WLAN_LEGACY_MAC_ID); + if (!vdev) + 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_LEGACY_MAC_ID); + return; + } + + mlme_priv->disconnect_info.from_ap = from_ap; + mlme_priv->disconnect_info.discon_reason = reason_code; + wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID); +} + +void mlme_get_discon_reason_n_from_ap(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, bool *from_ap, + uint32_t *reason_code) +{ + struct wlan_objmgr_vdev *vdev; + struct mlme_legacy_priv *mlme_priv; + + if (!psoc) + return; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, + WLAN_LEGACY_MAC_ID); + if (!vdev) + 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_LEGACY_MAC_ID); + return; + } + + *from_ap = mlme_priv->disconnect_info.from_ap; + *reason_code = mlme_priv->disconnect_info.discon_reason; + mlme_priv->disconnect_info.from_ap = false; + mlme_priv->disconnect_info.discon_reason = 0; + wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID); +} + #if defined(WLAN_FEATURE_HOST_ROAM) || defined(WLAN_FEATURE_ROAM_OFFLOAD) static const char *mlme_roam_state_to_string(enum roam_offload_state state) diff --git a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h index 494e36487a..c054f05f8a 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h @@ -3993,4 +3993,25 @@ QDF_STATUS ucfg_mlme_get_peer_unmap_conf(struct wlan_objmgr_psoc *psoc) { return wlan_mlme_get_peer_unmap_conf(psoc); } + +/** + * ucfg_mlme_get_discon_reason_n_from_ap() - Get disconnect reason and from ap + * @psoc: PSOC pointer + * @vdev_id: vdev id + * @from_ap: Get the from_ap cached through mlme_set_discon_reason_n_from_ap + * and copy to this buffer. + * @reason_code: Get the reason_code cached through + * mlme_set_discon_reason_n_from_ap and copy to this buffer. + * + * Fetch the contents of from_ap and reason_codes. + * + * Return: void + */ +static inline void +ucfg_mlme_get_discon_reason_n_from_ap(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, bool *from_ap, + uint32_t *reason_code) +{ + mlme_get_discon_reason_n_from_ap(psoc, vdev_id, from_ap, reason_code); +} #endif /* _WLAN_MLME_UCFG_API_H_ */ diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 750cd4ed98..a85953596c 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1039,6 +1039,8 @@ struct hdd_context; * @cache_sta_count: number of currently cached stations * @acs_complete_event: acs complete event * @latency_level: 0 - normal, 1 - moderate, 2 - low, 3 - ultralow + * @last_disconnect_reason: Last disconnected internal reason code + * as per enum eSirMacReasonCodes */ struct hdd_adapter { /* Magic cookie for adapter sanity verification. Note that this @@ -1312,6 +1314,7 @@ struct hdd_adapter { bool motion_det_in_progress; uint32_t motion_det_baseline_value; #endif /* WLAN_FEATURE_MOTION_DETECTION */ + enum eSirMacReasonCodes last_disconnect_reason; }; #define WLAN_HDD_GET_STATION_CTX_PTR(adapter) (&(adapter)->session.station) diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index 5b2ba6b04c..1f381d98ee 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -424,7 +424,8 @@ void hdd_abort_ongoing_sta_connection(struct hdd_context *hdd_ctx) hdd_debug("Disconnecting STA on vdev: %d", sta_adapter->vdev_id); status = wlan_hdd_disconnect(sta_adapter, - eCSR_DISCONNECT_REASON_DEAUTH); + eCSR_DISCONNECT_REASON_DEAUTH, + eSIR_MAC_UNSPEC_FAILURE_REASON); if (QDF_IS_STATUS_ERROR(status)) { hdd_err("wlan_hdd_disconnect failed, status: %d", status); @@ -1696,6 +1697,8 @@ static QDF_STATUS hdd_dis_connect_handler(struct hdd_adapter *adapter, bool sendDisconInd = true; mac_handle_t mac_handle; struct wlan_ies disconnect_ies = {0}; + bool from_ap = false; + uint32_t reason_code = 0; if (!dev) { hdd_err("net_dev is released return"); @@ -1776,9 +1779,13 @@ static QDF_STATUS hdd_dis_connect_handler(struct hdd_adapter *adapter, pr_info("wlan: disconnected due to poor signal, rssi is %d dB\n", roam_info->rxRssi); } + ucfg_mlme_get_discon_reason_n_from_ap(hdd_ctx->psoc, + adapter->vdev_id, + &from_ap, + &reason_code); wlan_hdd_cfg80211_indicate_disconnect( - dev, false, - reason, + adapter, !from_ap, + reason_code, disconnect_ies.data, disconnect_ies.len); @@ -3057,7 +3064,8 @@ hdd_association_completion_handler(struct hdd_adapter *adapter, sme_roam_disconnect( mac_handle, adapter->vdev_id, - eCSR_DISCONNECT_REASON_UNSPECIFIED); + eCSR_DISCONNECT_REASON_UNSPECIFIED, + eSIR_MAC_UNSPEC_FAILURE_REASON); } return QDF_STATUS_E_FAILURE; } @@ -3116,9 +3124,10 @@ hdd_association_completion_handler(struct hdd_adapter *adapter, */ hdd_debug("Disconnecting..."); sme_roam_disconnect( - mac_handle, - adapter->vdev_id, - eCSR_DISCONNECT_REASON_UNSPECIFIED); + mac_handle, + adapter->vdev_id, + eCSR_DISCONNECT_REASON_UNSPECIFIED, + eSIR_MAC_UNSPEC_FAILURE_REASON); } qdf_mem_free(reqRsnIe); qdf_mem_free(rsp_rsn_ie); diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index de6110479e..0e9bb2770d 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -19395,7 +19395,8 @@ static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy, } /*Try disconnecting if already in connected state */ - status = wlan_hdd_try_disconnect(adapter); + status = wlan_hdd_try_disconnect(adapter, + eSIR_MAC_UNSPEC_FAILURE_REASON); if (0 > status) { hdd_err("Failed to disconnect the existing IBSS connection"); return -EALREADY; @@ -19570,7 +19571,8 @@ static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy, INIT_COMPLETION(adapter->disconnect_comp_var); status = sme_roam_disconnect(mac_handle, adapter->vdev_id, - eCSR_DISCONNECT_REASON_IBSS_LEAVE); + eCSR_DISCONNECT_REASON_IBSS_LEAVE, + eSIR_MAC_UNSPEC_FAILURE_REASON); if (!QDF_IS_STATUS_SUCCESS(status)) { hdd_err("sme_roam_disconnect failed status: %d", status); @@ -19840,7 +19842,8 @@ static void wlan_hdd_cfg80211_clear_privacy(struct hdd_adapter *adapter) static int wlan_hdd_wait_for_disconnect(mac_handle_t mac_handle, struct hdd_adapter *adapter, - uint16_t reason) + uint16_t reason, + tSirMacReasonCodes mac_reason) { eConnectionState prev_conn_state; struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); @@ -19862,7 +19865,8 @@ static int wlan_hdd_wait_for_disconnect(mac_handle_t mac_handle, prev_conn_state = sta_ctx->conn_info.conn_state; hdd_conn_set_connection_state(adapter, eConnectionState_Disconnecting); - status = sme_roam_disconnect(mac_handle, adapter->vdev_id, reason); + status = sme_roam_disconnect(mac_handle, adapter->vdev_id, reason, + mac_reason); if (status == QDF_STATUS_CMD_NOT_QUEUED && prev_conn_state == eConnectionState_Connecting) { /* @@ -19942,7 +19946,8 @@ static void wlan_hdd_wait_for_roaming(mac_handle_t mac_handle, } } -int wlan_hdd_try_disconnect(struct hdd_adapter *adapter) +int wlan_hdd_try_disconnect(struct hdd_adapter *adapter, + enum eSirMacReasonCodes reason) { mac_handle_t mac_handle; @@ -19950,7 +19955,8 @@ int wlan_hdd_try_disconnect(struct hdd_adapter *adapter) wlan_hdd_wait_for_roaming(mac_handle, adapter); return wlan_hdd_wait_for_disconnect(mac_handle, adapter, - eCSR_DISCONNECT_REASON_UNSPECIFIED); + eCSR_DISCONNECT_REASON_UNSPECIFIED, + reason); } /** @@ -20215,7 +20221,8 @@ static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy, return status; /* Try disconnecting if already in connected state */ - status = wlan_hdd_try_disconnect(adapter); + status = wlan_hdd_try_disconnect(adapter, + eSIR_MAC_UNSPEC_FAILURE_REASON); if (0 > status) { hdd_err("Failed to disconnect the existing connection"); return -EALREADY; @@ -20274,7 +20281,75 @@ static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy, return errno; } -int wlan_hdd_disconnect(struct hdd_adapter *adapter, u16 reason) +/** + * wlan_hdd_get_ieee80211_disconnect_reason() - Get ieee80211 disconnect reason + * @adapter: pointer to adapter structure + * @reason: Mac Disconnect reason code as per @enum eSirMacReasonCodes + * + * Reason codes that are greater than eSIR_MAC_REASON_PROP_START are internal + * reason codes. Cache the same in hdd_ctx and return UNSPECIFIED. + * Rest of the reason codes are valid ieee80211 reason codes. + * + * Return: Reason code of type ieee80211_reasoncode. + */ +static enum ieee80211_reasoncode +wlan_hdd_get_cfg80211_disconnect_reason(struct hdd_adapter *adapter, + enum eSirMacReasonCodes reason) +{ + enum ieee80211_reasoncode ieee80211_reason = WLAN_REASON_UNSPECIFIED; + + /* + * Cache internal reason code in adapter. This can be sent to + * userspace with a vendor event. + */ + if (reason >= eSIR_MAC_REASON_PROP_START) + adapter->last_disconnect_reason = reason; + else + ieee80211_reason = (enum ieee80211_reasoncode)reason; + + return ieee80211_reason; +} + +#if defined(CFG80211_DISCONNECTED_V2) || \ +(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)) +void +wlan_hdd_cfg80211_indicate_disconnect(struct hdd_adapter *adapter, + bool locally_generated, + enum eSirMacReasonCodes reason, + uint8_t *disconnect_ies, + uint16_t disconnect_ies_len) +{ + enum ieee80211_reasoncode ieee80211_reason; + + ieee80211_reason = wlan_hdd_get_cfg80211_disconnect_reason(adapter, + reason); + hdd_debug("Disconnect reason code - MAC: %u, IEEE80211: %u locally_generated: %u", + reason, ieee80211_reason, locally_generated); + cfg80211_disconnected(adapter->dev, ieee80211_reason, disconnect_ies, + disconnect_ies_len, locally_generated, + GFP_KERNEL); +} +#else +void +wlan_hdd_cfg80211_indicate_disconnect(struct hdd_adapter *adapter, + bool locally_generated, + enum eSirMacReasonCodes reason, + uint8_t *disconnect_ies, + uint16_t disconnect_ies_len) +{ + enum ieee80211_reasoncode ieee80211_reason; + + ieee80211_reason = wlan_hdd_get_cfg80211_disconnect_reason(adapter, + reason); + hdd_debug("Disconnect reason code - MAC: %u, IEEE80211: %u locally_generated: %u", + reason, ieee80211_reason, locally_generated); + cfg80211_disconnected(adapter->dev, ieee80211_reason, disconnect_ies, + disconnect_ies_len, GFP_KERNEL); +} +#endif + +int wlan_hdd_disconnect(struct hdd_adapter *adapter, u16 reason, + tSirMacReasonCodes mac_reason) { int ret; mac_handle_t mac_handle; @@ -20287,15 +20362,16 @@ int wlan_hdd_disconnect(struct hdd_adapter *adapter, u16 reason) wlan_hdd_netif_queue_control(adapter, WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH); - ret = wlan_hdd_wait_for_disconnect(mac_handle, adapter, reason); + ret = wlan_hdd_wait_for_disconnect(mac_handle, adapter, reason, + mac_reason); #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) /* Sending disconnect event to userspace for kernel version < 3.11 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected */ hdd_debug("Send disconnected event to userspace"); - wlan_hdd_cfg80211_indicate_disconnect(adapter->dev, true, - WLAN_REASON_UNSPECIFIED, NULL, 0); + wlan_hdd_cfg80211_indicate_disconnect(adapter, true, + mac_reason, NULL, 0); #endif return ret; @@ -20482,7 +20558,7 @@ static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy, hdd_info("%s(vdevid-%d): Disconnect from userspace; reason:%d (%s)", dev->name, adapter->vdev_id, reason, hdd_ieee80211_reason_code_to_str(reason)); - status = wlan_hdd_disconnect(adapter, reasonCode); + status = wlan_hdd_disconnect(adapter, reasonCode, reason); if (0 != status) { hdd_err("wlan_hdd_disconnect failed, status: %d", status); hdd_set_disconnect_status(adapter, false); diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index 9897e1a786..ed90ac0d58 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -446,39 +446,25 @@ int wlan_hdd_cfg80211_update_band(struct hdd_context *hdd_ctx, enum band_info new_band); /** - * wlan_hdd_try_disconnect() - try disconnnect from previous connection + * 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 eSirMacReasonCodes + * @disconnect_ies: IEs received in Deauth/Disassoc from peer + * @disconnect_ies_len: Length of @disconnect_ies * - * This function is used to disconnect from previous connection + * This function is indicate disconnect to the kernel which thus indicates + * to the userspace. * - * Return: 0 for success, non-zero for failure + * Return: None */ -int wlan_hdd_try_disconnect(struct hdd_adapter *adapter); - -#if defined(CFG80211_DISCONNECTED_V2) || \ -(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)) -static inline void -wlan_hdd_cfg80211_indicate_disconnect(struct net_device *dev, +void +wlan_hdd_cfg80211_indicate_disconnect(struct hdd_adapter *adapter, bool locally_generated, - int reason, + enum eSirMacReasonCodes reason, uint8_t *disconnect_ies, - uint16_t disconnect_ies_len) -{ - cfg80211_disconnected(dev, reason, disconnect_ies, disconnect_ies_len, - locally_generated, GFP_KERNEL); -} -#else -static inline void -wlan_hdd_cfg80211_indicate_disconnect(struct net_device *dev, - bool locally_generated, - int reason, - uint8_t *disconnect_ies, - uint16_t disconnect_ies_len) -{ - cfg80211_disconnected(dev, reason, disconnect_ies, disconnect_ies_len, - GFP_KERNEL); -} -#endif + uint16_t disconnect_ies_len); /** * wlan_hdd_inform_bss_frame() - inform bss details to NL80211 @@ -546,23 +532,27 @@ uint8_t hdd_get_sap_operating_band(struct hdd_context *hdd_ctx); /** * wlan_hdd_try_disconnect() - try disconnnect from previous connection * @adapter: Pointer to adapter + * @reason: Mac Disconnect reason code as per @enum eSirMacReasonCodes * * 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); +int wlan_hdd_try_disconnect(struct hdd_adapter *adapter, + enum eSirMacReasonCodes reason); /** * wlan_hdd_disconnect() - hdd disconnect api * @adapter: Pointer to adapter - * @reason: Disconnect reason code + * @reason: CSR disconnect reason code as per @enum eCsrRoamDisconnectReason + * @mac_reason: Mac Disconnect reason code as per @enum eSirMacReasonCodes * * 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); +int wlan_hdd_disconnect(struct hdd_adapter *adapter, u16 reason, + tSirMacReasonCodes mac_reason); /** * wlan_hdd_get_adjacent_chan(): Gets next/previous channel diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index b7cd5ae013..fa6e02ccc5 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -4648,8 +4648,9 @@ static int wlan_hdd_setup_driver_overrides(struct hdd_adapter *ap_adapter) return 0; } -void hdd_check_and_disconnect_sta_on_invalid_channel( - struct hdd_context *hdd_ctx) +void +hdd_check_and_disconnect_sta_on_invalid_channel(struct hdd_context *hdd_ctx, + tSirMacReasonCodes reason) { struct hdd_adapter *sta_adapter; uint32_t sta_chan_freq; @@ -4676,7 +4677,7 @@ void hdd_check_and_disconnect_sta_on_invalid_channel( hdd_err("chan %d not valid, issue disconnect", sta_chan_freq); /* Issue Disconnect request */ - wlan_hdd_disconnect(sta_adapter, eCSR_DISCONNECT_REASON_DEAUTH); + wlan_hdd_disconnect(sta_adapter, eCSR_DISCONNECT_REASON_DEAUTH, reason); } #ifdef DISABLE_CHANNEL_LIST @@ -5094,7 +5095,8 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter, /* check if STA is on indoor channel*/ if (policy_mgr_is_force_scc(hdd_ctx->psoc)) hdd_check_and_disconnect_sta_on_invalid_channel( - hdd_ctx); + hdd_ctx, + eSIR_MAC_OPER_CHANNEL_DISABLED_INDOOR); } beacon = adapter->session.ap.beacon; diff --git a/core/hdd/src/wlan_hdd_hostapd.h b/core/hdd/src/wlan_hdd_hostapd.h index c957b9669e..4804f10a78 100644 --- a/core/hdd/src/wlan_hdd_hostapd.h +++ b/core/hdd/src/wlan_hdd_hostapd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2020 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 @@ -267,14 +267,16 @@ int wlan_hdd_disable_channels(struct hdd_context *hdd_ctx); * hdd_check_and_disconnect_sta_on_invalid_channel() - Disconnect STA if it is * on invalid channel * @hdd_ctx: pointer to hdd context + * @reason: Mac Disconnect reason code as per @enum eSirMacReasonCodes * * STA should be disconnected before starting the SAP if it is on indoor * channel. * * Return: void */ -void hdd_check_and_disconnect_sta_on_invalid_channel( - struct hdd_context *hdd_ctx); +void +hdd_check_and_disconnect_sta_on_invalid_channel(struct hdd_context *hdd_ctx, + tSirMacReasonCodes reason); /** * hdd_stop_sap_due_to_invalid_channel() - to stop sap in case of invalid chnl diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index 4702d17840..5555d35802 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -7262,6 +7262,7 @@ static bool check_disable_channels(struct hdd_context *hdd_ctx, * disconnect_sta_and_stop_sap() - Disconnect STA and stop SAP * * @hdd_ctx: Pointer to hdd context + * @reason: Disconnect reason code as per @enum eSirMacReasonCodes * * Disable channels provided by user and disconnect STA if it is * connected to any AP, stop SAP and send deauthentication request @@ -7269,7 +7270,8 @@ static bool check_disable_channels(struct hdd_context *hdd_ctx, * * Return: None */ -static void disconnect_sta_and_stop_sap(struct hdd_context *hdd_ctx) +static void disconnect_sta_and_stop_sap(struct hdd_context *hdd_ctx, + enum eSirMacReasonCodes reason) { struct hdd_adapter *adapter, *next = NULL; QDF_STATUS status; @@ -7278,7 +7280,7 @@ static void disconnect_sta_and_stop_sap(struct hdd_context *hdd_ctx) if (!hdd_ctx) return; - hdd_check_and_disconnect_sta_on_invalid_channel(hdd_ctx); + hdd_check_and_disconnect_sta_on_invalid_channel(hdd_ctx, reason); status = hdd_get_front_adapter(hdd_ctx, &adapter); while (adapter && (status == QDF_STATUS_SUCCESS)) { @@ -7475,7 +7477,8 @@ mem_alloc_failed: ret = wlan_hdd_disable_channels(hdd_ctx); if (ret) return ret; - disconnect_sta_and_stop_sap(hdd_ctx); + disconnect_sta_and_stop_sap(hdd_ctx, + eSIR_MAC_OPER_CHANNEL_BAND_CHANGE); } hdd_exit(); diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 971b9f0dc0..03e011170b 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -5965,6 +5965,7 @@ QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx, struct sap_config *sap_config; mac_handle_t mac_handle; struct wlan_objmgr_vdev *vdev; + enum eSirMacReasonCodes reason = eSIR_MAC_IFACE_DOWN; hdd_enter(); @@ -6001,22 +6002,28 @@ QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx, INIT_COMPLETION(adapter->disconnect_comp_var); roam_profile = hdd_roam_profile(adapter); + if (cds_is_driver_recovering()) + reason = eSIR_MAC_DEVICE_RECOVERY; + /* For NDI do not use roam_profile */ if (adapter->device_mode == QDF_NDI_MODE) status = sme_roam_disconnect( mac_handle, adapter->vdev_id, - eCSR_DISCONNECT_REASON_NDI_DELETE); + eCSR_DISCONNECT_REASON_NDI_DELETE, + reason); else if (roam_profile->BSSType == eCSR_BSS_TYPE_START_IBSS) status = sme_roam_disconnect( mac_handle, adapter->vdev_id, - eCSR_DISCONNECT_REASON_IBSS_LEAVE); + eCSR_DISCONNECT_REASON_IBSS_LEAVE, + reason); else if (adapter->device_mode == QDF_STA_MODE) { rc = wlan_hdd_disconnect( adapter, - eCSR_DISCONNECT_REASON_DEAUTH); + eCSR_DISCONNECT_REASON_DEAUTH, + reason); if (rc != 0 && ucfg_ipa_is_enabled()) { hdd_err("STA disconnect failed"); ucfg_ipa_uc_cleanup_sta(hdd_ctx->pdev, @@ -6026,7 +6033,8 @@ QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx, status = sme_roam_disconnect( mac_handle, adapter->vdev_id, - eCSR_DISCONNECT_REASON_UNSPECIFIED); + eCSR_DISCONNECT_REASON_UNSPECIFIED, + reason); } /* success implies disconnect is queued */ if (QDF_IS_STATUS_SUCCESS(status) && @@ -7109,9 +7117,9 @@ QDF_STATUS hdd_start_all_adapters(struct hdd_context *hdd_ctx) /* indicate disconnected event to nl80211 */ wlan_hdd_cfg80211_indicate_disconnect( - adapter->dev, false, - WLAN_REASON_UNSPECIFIED, - NULL, 0); + adapter, true, + eSIR_MAC_DEVICE_RECOVERY, + NULL, 0); } else if (eConnectionState_Connecting == conn_state) { /* * Indicate connect failure to supplicant if we diff --git a/core/hdd/src/wlan_hdd_nud_tracking.c b/core/hdd/src/wlan_hdd_nud_tracking.c index fbf10bfe27..3876202972 100644 --- a/core/hdd/src/wlan_hdd_nud_tracking.c +++ b/core/hdd/src/wlan_hdd_nud_tracking.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020 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 @@ -277,7 +277,8 @@ hdd_handle_nud_fail_non_sta(struct hdd_adapter *adapter) hdd_debug("Disconnecting vdev with vdev id: %d", adapter->vdev_id); /* Issue Disconnect */ - status = wlan_hdd_disconnect(adapter, eCSR_DISCONNECT_REASON_DEAUTH); + status = wlan_hdd_disconnect(adapter, eCSR_DISCONNECT_REASON_DEAUTH, + eSIR_MAC_GATEWAY_REACHABILITY_FAILURE); if (0 != status) { hdd_err("wlan_hdd_disconnect failed, status: %d", status); diff --git a/core/hdd/src/wlan_hdd_regulatory.c b/core/hdd/src/wlan_hdd_regulatory.c index d52e0a94e7..706b9bf3aa 100644 --- a/core/hdd/src/wlan_hdd_regulatory.c +++ b/core/hdd/src/wlan_hdd_regulatory.c @@ -823,7 +823,8 @@ int hdd_reg_set_band(struct net_device *dev, u8 ui_band) status = sme_roam_disconnect( mac_handle, adapter->vdev_id, - eCSR_DISCONNECT_REASON_UNSPECIFIED); + eCSR_DISCONNECT_REASON_UNSPECIFIED, + eSIR_MAC_OPER_CHANNEL_BAND_CHANGE); if (QDF_STATUS_SUCCESS != status) { hdd_err("sme_roam_disconnect failure, status: %d", diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 3a2d1fe5ec..1032651f8e 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1251,6 +1251,7 @@ struct disassoc_ind { struct qdf_mac_addr peer_macaddr; uint16_t staId; uint32_t reasonCode; + bool from_ap; }; /* / Definition for Disassociation confirm */ @@ -1311,6 +1312,7 @@ struct deauth_ind { uint16_t staId; uint32_t reasonCode; int8_t rssi; + bool from_ap; }; /* / Definition for Deauthetication confirm */ diff --git a/core/mac/inc/sir_mac_prot_def.h b/core/mac/inc/sir_mac_prot_def.h index 2dfdfa6d58..3770a251e1 100644 --- a/core/mac/inc/sir_mac_prot_def.h +++ b/core/mac/inc/sir_mac_prot_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2020 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 @@ -439,7 +439,7 @@ typedef enum eSirMacReasonCodes { eSIR_MAC_STA_NOT_PRE_AUTHENTICATED_REASON = 9, /* Station requesting (re)association is not authenticated with responding station */ eSIR_MAC_PWR_CAPABILITY_BAD_REASON = 10, /* Disassociated because the information in the Power Capability element is unacceptable */ eSIR_MAC_SPRTD_CHANNELS_BAD_REASON = 11, /* Disassociated because the information in the Supported Channels element is unacceptable */ - /* reserved 12 */ + eSIR_MAC_BSS_TRANSITION_DISASSOC = 12, eSIR_MAC_INVALID_IE_REASON = 13, /* Invalid information element, i.e., an information element defined in this standard for */ /* which the content does not meet the specifications in Clause 7 */ eSIR_MAC_MIC_FAILURE_REASON = 14, /* Message integrity code (MIC) failure */ @@ -475,7 +475,29 @@ typedef enum eSirMacReasonCodes { eSIR_MAC_CIPHER_NOT_SUPPORTED_REASON = 45, /* Peer STA does not support the requested cipher suite */ eSIR_MAC_DISASSOC_DUE_TO_FTHANDOFF_REASON = 46, /* FT reason */ /* reserved 47 - 65535. */ - eSIR_BEACON_MISSED = 65534, /* We invented this to tell beacon missed case */ + + /* + * Internal reason codes: Add any internal reason code just after + * eSIR_MAC_REASON_PROP_START and decrease the value of + * eSIR_MAC_REASON_PROP_START accordingly. + */ + eSIR_MAC_REASON_PROP_START = 65519, + eSIR_MAC_HOST_TRIGGERED_ROAM_FAILURE = 65519, + eSIR_MAC_FW_TRIGGERED_ROAM_FAILURE = 65520, + eSIR_MAC_GATEWAY_REACHABILITY_FAILURE = 65521, + eSIR_MAC_UNSUPPORTED_CHANNEL_CSA = 65522, + eSIR_MAC_OPER_CHANNEL_DISABLED_INDOOR = 65523, + eSIR_MAC_OPER_CHANNEL_USER_DISABLED = 65524, + eSIR_MAC_DEVICE_RECOVERY = 65525, + eSIR_MAC_KEY_TIMEOUT = 65526, + eSIR_MAC_OPER_CHANNEL_BAND_CHANGE = 65527, + eSIR_MAC_IFACE_DOWN = 65528, + eSIR_MAC_PEER_XRETRY_FAIL = 65529, + eSIR_MAC_PEER_INACTIVITY = 65530, + eSIR_MAC_SA_QUERY_TIMEOUT = 65531, + eSIR_MAC_CHANNEL_SWITCH_FAILED = 65532, + eSIR_MAC_BEACON_MISSED = 65533, + eSIR_MAC_USER_TRIGGERED_ROAM_FAILURE = 65534, } tSirMacReasonCodes; /* / Frame control field format (2 bytes) */ diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index 42ac285a4f..24d0ca76a7 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -2241,7 +2241,8 @@ pe_disconnect_callback(struct mac_context *mac, uint8_t vdev_id, } lim_tear_down_link_with_ap(mac, session->peSessionId, - reason_code); + reason_code, + eLIM_PEER_ENTITY_DEAUTH); return QDF_STATUS_SUCCESS; } diff --git a/core/mac/src/pe/lim/lim_link_monitoring_algo.c b/core/mac/src/pe/lim/lim_link_monitoring_algo.c index 7d7f3765d3..434e35030d 100644 --- a/core/mac/src/pe/lim/lim_link_monitoring_algo.c +++ b/core/mac/src/pe/lim/lim_link_monitoring_algo.c @@ -228,7 +228,8 @@ void lim_delete_sta_context(struct mac_context *mac_ctx, msg->addr2, session_entry, false); lim_tear_down_link_with_ap(mac_ctx, session_entry->peSessionId, - eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON); + eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON, + eLIM_LINK_MONITORING_DEAUTH); /* only break for STA role (non TDLS) */ break; } @@ -256,7 +257,8 @@ void lim_delete_sta_context(struct mac_context *mac_ctx, eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON, session_entry->bssId, session_entry, false); lim_tear_down_link_with_ap(mac_ctx, session_entry->peSessionId, - eSIR_MAC_UNSPEC_FAILURE_REASON); + eSIR_MAC_BSS_TRANSITION_DISASSOC, + eLIM_LINK_MONITORING_DEAUTH); break; default: @@ -323,26 +325,10 @@ lim_trigger_sta_deletion(struct mac_context *mac_ctx, tpDphHashNode sta_ds, lim_send_sme_disassoc_ind(mac_ctx, sta_ds, session_entry); } /*** end lim_trigger_st_adeletion() ***/ -/** - * lim_tear_down_link_with_ap() - * - ***FUNCTION: - * This function is called when heartbeat (beacon reception) - * fails on STA - * - ***LOGIC: - * - ***ASSUMPTIONS: - * - ***NOTE: - * - * @param mac - Pointer to Global MAC structure - * @return None - */ - void lim_tear_down_link_with_ap(struct mac_context *mac, uint8_t sessionId, - tSirMacReasonCodes reasonCode) + tSirMacReasonCodes reasonCode, + enum eLimDisassocTrigger trigger) { tpDphHashNode sta = NULL; @@ -361,8 +347,9 @@ lim_tear_down_link_with_ap(struct mac_context *mac, uint8_t sessionId, */ pe_session->pmmOffloadInfo.bcnmiss = false; - pe_info("No ProbeRsp from AP after HB failure for pe/sme id %d/%d reason code %d", - pe_session->peSessionId, pe_session->smeSessionId, reasonCode); + pe_info("Session %d Vdev %d reason code %d trigger %d", + pe_session->peSessionId, pe_session->vdev_id, reasonCode, + trigger); /* Announce loss of link to Roaming algorithm */ /* and cleanup by sending SME_DISASSOC_REQ to SME */ @@ -388,8 +375,7 @@ lim_tear_down_link_with_ap(struct mac_context *mac, uint8_t sessionId, #endif sta->mlmStaContext.disassocReason = reasonCode; - sta->mlmStaContext.cleanupTrigger = - eLIM_LINK_MONITORING_DEAUTH; + sta->mlmStaContext.cleanupTrigger = trigger; /* / Issue Deauth Indication to SME. */ qdf_mem_copy((uint8_t *) &mlmDeauthInd.peerMacAddr, sta->staAddr, sizeof(tSirMacAddr)); @@ -401,7 +387,7 @@ lim_tear_down_link_with_ap(struct mac_context *mac, uint8_t sessionId, * connection, if we connect to same AP after HB failure. */ if (mac->mlme_cfg->sta.deauth_before_connection && - eSIR_BEACON_MISSED == reasonCode) { + eSIR_MAC_BEACON_MISSED == reasonCode) { int apCount = mac->lim.gLimHeartBeatApMacIndex; if (mac->lim.gLimHeartBeatApMacIndex) @@ -529,7 +515,8 @@ void lim_handle_heart_beat_failure(struct mac_context *mac_ctx, */ lim_tear_down_link_with_ap(mac_ctx, session->peSessionId, - eSIR_BEACON_MISSED); + eSIR_MAC_BEACON_MISSED, + eLIM_LINK_MONITORING_DEAUTH); } } else { /** diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index 0e6a32fb27..25bf7a35bf 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -772,6 +772,14 @@ error: (uint32_t *) pMsg); } /*** end lim_send_sme_disassoc_ntf() ***/ +static bool lim_is_disconnect_from_ap(enum eLimDisassocTrigger trigger) +{ + if (trigger == eLIM_PEER_ENTITY_DEAUTH || + trigger == eLIM_PEER_ENTITY_DISASSOC) + return true; + + return false; +} /** ----------------------------------------------------------------- \brief lim_send_sme_disassoc_ind() - sends SME_DISASSOC_IND @@ -808,6 +816,10 @@ lim_send_sme_disassoc_ind(struct mac_context *mac, tpDphHashNode sta, qdf_mem_copy(pSirSmeDisassocInd->peer_macaddr.bytes, sta->staAddr, QDF_MAC_ADDR_SIZE); + if (LIM_IS_STA_ROLE(pe_session)) + pSirSmeDisassocInd->from_ap = + lim_is_disconnect_from_ap(sta->mlmStaContext.cleanupTrigger); + mmhMsg.type = eWNI_SME_DISASSOC_IND; mmhMsg.bodyptr = pSirSmeDisassocInd; mmhMsg.bodyval = 0; @@ -870,6 +882,10 @@ lim_send_sme_deauth_ind(struct mac_context *mac, tpDphHashNode sta, sta->mlmStaContext.disassocReason) pSirSmeDeauthInd->rssi = sta->del_sta_ctx_rssi; + if (LIM_IS_STA_ROLE(pe_session)) + pSirSmeDeauthInd->from_ap = + lim_is_disconnect_from_ap(sta->mlmStaContext.cleanupTrigger); + mmhMsg.type = eWNI_SME_DEAUTH_IND; mmhMsg.bodyptr = pSirSmeDeauthInd; mmhMsg.bodyval = 0; diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index 5a536f90e7..64cef15c28 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -769,8 +769,21 @@ static inline void lim_update_tdls_set_state_for_fw(struct pe_session /* / Function that handles heartbeat failure */ void lim_handle_heart_beat_failure(struct mac_context *, struct pe_session *); -/* / Function that triggers link tear down with AP upon HB failure */ -void lim_tear_down_link_with_ap(struct mac_context *, uint8_t, tSirMacReasonCodes); +/** + * lim_tear_down_link_with_ap() - Tear down link with AP + * @mac: mac context + * @session_id: PE session id + * @reason_code: Disconnect reason code as per emun eSirMacReasonCodes + * @trigger: Disconnect trigger as per enum eLimDisassocTrigger + * + * Function that triggers link tear down with AP upon HB failure + * + * Return: None + */ +void lim_tear_down_link_with_ap(struct mac_context *mac, + uint8_t session_id, + tSirMacReasonCodes reason_code, + enum eLimDisassocTrigger trigger); /* / Function that defers the messages received */ uint32_t lim_defer_msg(struct mac_context *, struct scheduler_msg *); diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index 6e75b5183d..85ec75f490 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -1874,7 +1874,8 @@ static void __lim_process_channel_switch_timeout(struct pe_session *pe_session) lim_tear_down_link_with_ap(mac, mac->lim.lim_timers. gLimChannelSwitchTimer.sessionId, - eSIR_MAC_UNSPEC_FAILURE_REASON); + eSIR_MAC_UNSUPPORTED_CHANNEL_CSA, + eLIM_LINK_MONITORING_DISASSOC); return; } } @@ -4724,7 +4725,8 @@ void lim_handle_heart_beat_failure_timeout(struct mac_context *mac_ctx) */ lim_tear_down_link_with_ap(mac_ctx, psession_entry->peSessionId, - eSIR_BEACON_MISSED); + eSIR_MAC_BEACON_MISSED, + eLIM_LINK_MONITORING_DISASSOC); mac_ctx->lim.gLimProbeFailureAfterHBfailedCnt++; } else { pe_err("Unexpected wt-probe-timeout in state"); diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index 1d502c84fa..ec16faa941 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2020 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 @@ -288,7 +288,7 @@ struct roam_cmd { bool fStopWds; tSirMacAddr peerMac; tSirMacReasonCodes reason; - eCsrRoamDisconnectReason disconnect_reason; + tSirMacReasonCodes disconnect_reason; }; struct setkey_cmd { diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 834a296de0..924d69a50e 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -533,11 +533,13 @@ QDF_STATUS sme_roam_reassoc(mac_handle_t mac_handle, uint8_t sessionId, * @mac_handle: Opaque handle to the global MAC context * @session: SME session identifier * @reason: Reason to disconnect + * @mac_reason: Reason to disconnect as per enum eSirMacReasonCodes * * Return: QDF Status success or failure */ QDF_STATUS sme_roam_disconnect(mac_handle_t mac_handle, uint8_t session, - eCsrRoamDisconnectReason reason); + eCsrRoamDisconnectReason reason, + tSirMacReasonCodes mac_reason); void sme_dhcp_done_ind(mac_handle_t mac_handle, uint8_t session_id); QDF_STATUS sme_roam_stop_bss(mac_handle_t mac_handle, uint8_t sessionId); diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 1e7447c143..5659722d74 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -63,7 +63,8 @@ static QDF_STATUS init_sme_cmd_list(struct mac_context *mac); -static void sme_disconnect_connected_sessions(struct mac_context *mac); +static void sme_disconnect_connected_sessions(struct mac_context *mac, + enum eSirMacReasonCodes reason); static QDF_STATUS sme_handle_generic_change_country_code(struct mac_context *mac, void *msg_buf); @@ -2859,7 +2860,8 @@ QDF_STATUS sme_roam_reassoc(mac_handle_t mac_handle, uint8_t sessionId, } QDF_STATUS sme_roam_disconnect(mac_handle_t mac_handle, uint8_t session_id, - eCsrRoamDisconnectReason reason) + eCsrRoamDisconnectReason reason, + tSirMacReasonCodes mac_reason) { QDF_STATUS status = QDF_STATUS_E_FAILURE; struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle); @@ -2871,7 +2873,8 @@ QDF_STATUS sme_roam_disconnect(mac_handle_t mac_handle, uint8_t session_id, if (QDF_IS_STATUS_SUCCESS(status)) { if (CSR_IS_SESSION_VALID(mac_ctx, session_id)) status = csr_roam_disconnect(mac_ctx, session_id, - reason); + reason, + mac_reason); else status = QDF_STATUS_E_INVAL; sme_release_global_lock(&mac_ctx->sme); @@ -5283,7 +5286,8 @@ sme_handle_generic_change_country_code(struct mac_context *mac_ctx, mac_ctx->reg_hint_src = SOURCE_UNKNOWN; - sme_disconnect_connected_sessions(mac_ctx); + sme_disconnect_connected_sessions(mac_ctx, + eSIR_MAC_UNSPEC_FAILURE_REASON); return QDF_STATUS_SUCCESS; } @@ -5305,7 +5309,8 @@ QDF_STATUS sme_update_channel_list(mac_handle_t mac_handle) csr_apply_channel_power_info_wrapper(mac_ctx); csr_scan_filter_results(mac_ctx); - sme_disconnect_connected_sessions(mac_ctx); + sme_disconnect_connected_sessions(mac_ctx, + eSIR_MAC_OPER_CHANNEL_USER_DISABLED); sme_release_global_lock(&mac_ctx->sme); } @@ -5337,14 +5342,16 @@ static bool sme_search_in_base_ch_freq_lst( /** * sme_disconnect_connected_sessions() - Disconnect STA and P2P client session * if channel is not supported - * @mac_ctx: mac global context + * @mac_ctx: mac global context + * @reason: Mac Disconnect reason code as per @enum eSirMacReasonCodes * * If new country code does not support the channel on which STA/P2P client * is connetced, it sends the disconnect to the AP/P2P GO * * Return: void */ -static void sme_disconnect_connected_sessions(struct mac_context *mac_ctx) +static void sme_disconnect_connected_sessions(struct mac_context *mac_ctx, + enum eSirMacReasonCodes reason) { uint8_t session_id, found = false; uint32_t chan_freq; @@ -5362,7 +5369,8 @@ static void sme_disconnect_connected_sessions(struct mac_context *mac_ctx) if (!found) { sme_debug("Disconnect Session: %d", session_id); csr_roam_disconnect(mac_ctx, session_id, - eCSR_DISCONNECT_REASON_UNSPECIFIED); + eCSR_DISCONNECT_REASON_UNSPECIFIED, + reason); } } } diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 981d918cf9..b02bbf1bda 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -3982,9 +3982,8 @@ QDF_STATUS csr_roam_call_callback(struct mac_context *mac, uint32_t sessionId, * to 0 if unknown. eSIR_BEACON_MISSED reason code is * not recognizable so that we set to 0 instead. */ - roam_info->reasonCode = - (roam_info->reasonCode == eSIR_BEACON_MISSED) ? - 0 : roam_info->reasonCode; + if (roam_info->reasonCode == eSIR_MAC_BEACON_MISSED) + roam_info->reasonCode = 0; } status = mac->session_roam_complete_cb(mac->psoc, sessionId, roam_info, roamId, u1, u2); @@ -8769,7 +8768,8 @@ QDF_STATUS csr_roam_connect(struct mac_context *mac, uint32_t sessionId, !csr_is_ssid_in_list(&pSession->connectedProfile.SSID, &pProfile->SSIDs)) csr_roam_issue_disassociate_cmd(mac, sessionId, - eCSR_DISCONNECT_REASON_UNSPECIFIED); + eCSR_DISCONNECT_REASON_UNSPECIFIED, + eSIR_MAC_UNSPEC_FAILURE_REASON); /* * If roamSession.connectState is disconnecting that mean * disconnect was received with scan for ssid in progress @@ -9019,7 +9019,8 @@ QDF_STATUS csr_roam_process_disassoc_deauth(struct mac_context *mac, } /* change state to 'Roaming'... */ csr_roam_state_change(mac, eCSR_ROAMING_STATE_JOINING, sessionId); - + mlme_set_discon_reason_n_from_ap(mac->psoc, pCommand->vdev_id, false, + pCommand->u.roamCmd.disconnect_reason); if (csr_is_conn_state_ibss(mac, sessionId)) { /* If we are in an IBSS, then stop the IBSS... */ status = @@ -9100,7 +9101,8 @@ QDF_STATUS csr_roam_process_disassoc_deauth(struct mac_context *mac, QDF_STATUS csr_roam_issue_disassociate_cmd(struct mac_context *mac, uint32_t sessionId, - eCsrRoamDisconnectReason reason) + eCsrRoamDisconnectReason reason, + tSirMacReasonCodes mac_reason) { QDF_STATUS status = QDF_STATUS_SUCCESS; tSmeCmd *pCommand; @@ -9159,7 +9161,7 @@ QDF_STATUS csr_roam_issue_disassociate_cmd(struct mac_context *mac, default: break; } - pCommand->u.roamCmd.disconnect_reason = reason; + pCommand->u.roamCmd.disconnect_reason = mac_reason; status = csr_queue_sme_command(mac, pCommand, true); if (!QDF_IS_STATUS_SUCCESS(status)) sme_err("fail to send message status: %d", status); @@ -9195,7 +9197,8 @@ QDF_STATUS csr_roam_issue_stop_bss_cmd(struct mac_context *mac, uint32_t session } QDF_STATUS csr_roam_disconnect_internal(struct mac_context *mac, uint32_t sessionId, - eCsrRoamDisconnectReason reason) + eCsrRoamDisconnectReason reason, + tSirMacReasonCodes mac_reason) { QDF_STATUS status = QDF_STATUS_E_FAILURE; struct csr_roam_session *pSession = CSR_GET_SESSION(mac, sessionId); @@ -9212,7 +9215,7 @@ QDF_STATUS csr_roam_disconnect_internal(struct mac_context *mac, uint32_t sessio || CSR_IS_CONN_NDI(&pSession->connectedProfile)) { sme_debug("called"); status = csr_roam_issue_disassociate_cmd(mac, sessionId, - reason); + reason, mac_reason); } else if (pSession->scan_info.profile) { mac->roam.roamSession[sessionId].connectState = eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTING; @@ -9226,7 +9229,8 @@ QDF_STATUS csr_roam_disconnect_internal(struct mac_context *mac, uint32_t sessio } QDF_STATUS csr_roam_disconnect(struct mac_context *mac_ctx, uint32_t session_id, - eCsrRoamDisconnectReason reason) + eCsrRoamDisconnectReason reason, + tSirMacReasonCodes mac_reason) { struct csr_roam_session *session = CSR_GET_SESSION(mac_ctx, session_id); @@ -9240,7 +9244,8 @@ QDF_STATUS csr_roam_disconnect(struct mac_context *mac_ctx, uint32_t session_id, csr_roam_remove_duplicate_command(mac_ctx, session_id, NULL, eCsrForcedDisassoc); - return csr_roam_disconnect_internal(mac_ctx, session_id, reason); + return csr_roam_disconnect_internal(mac_ctx, session_id, reason, + mac_reason); } QDF_STATUS @@ -9949,6 +9954,9 @@ static void csr_roam_roaming_state_reassoc_rsp_processor(struct mac_context *mac roam_info = qdf_mem_malloc(sizeof(*roam_info)); if (!roam_info) return; + mlme_set_discon_reason_n_from_ap(mac->psoc, + pSmeJoinRsp->vdev_id, false, + eSIR_MAC_HOST_TRIGGERED_ROAM_FAILURE); csr_roam_call_callback(mac, pSmeJoinRsp->vdev_id, roam_info, roam_id, @@ -10332,6 +10340,8 @@ void csr_handle_disassoc_ho(struct mac_context *mac, uint32_t session_id) csr_scan_result_purge(mac, scan_handle_roam_ap); POST_ROAM_FAILURE: + mlme_set_discon_reason_n_from_ap(mac->psoc, session_id, false, + eSIR_MAC_HOST_TRIGGERED_ROAM_FAILURE); csr_post_roam_failure(mac, session_id, roam_info, NULL); qdf_mem_free(roam_info); } @@ -12007,7 +12017,7 @@ csr_roam_chk_lnk_deauth_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr) session->disconnect_stats.disconnection_cnt++; session->disconnect_stats.deauth_by_peer++; break; - case eSIR_BEACON_MISSED: + case eSIR_MAC_BEACON_MISSED: session->disconnect_stats.disconnection_cnt++; session->disconnect_stats.bmiss++; break; @@ -12060,7 +12070,8 @@ csr_roam_chk_lnk_swt_ch_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr) if (QDF_IS_STATUS_ERROR(pSwitchChnInd->status)) { sme_err("Channel switch failed"); csr_roam_disconnect_internal(mac_ctx, sessionId, - eCSR_DISCONNECT_REASON_DEAUTH); + eCSR_DISCONNECT_REASON_DEAUTH, + eSIR_MAC_CHANNEL_SWITCH_FAILED); return; } session->connectedProfile.op_freq = pSwitchChnInd->freq; @@ -12421,7 +12432,8 @@ csr_roam_chk_lnk_wm_status_change_ntf(struct mac_context *mac_ctx, mac_ctx->roam.curSubState[sessionId]))) { sme_warn("Calling csr_roam_disconnect_internal"); csr_roam_disconnect_internal(mac_ctx, sessionId, - eCSR_DISCONNECT_REASON_UNSPECIFIED); + eCSR_DISCONNECT_REASON_UNSPECIFIED, + eSIR_MAC_UNSPEC_FAILURE_REASON); } else { sme_warn("Skipping the new scan as CSR is in state: %s and sub-state: %s", mac_trace_getcsr_roam_state( @@ -12764,7 +12776,8 @@ bool csr_roam_complete_roaming(struct mac_context *mac, uint32_t sessionId, * detinguish it. For missed beacon, LIM set reason to * be eSIR_BEACON_MISSED */ - if (eSIR_BEACON_MISSED == pSession->roamingStatusCode) { + if (eSIR_MAC_BEACON_MISSED == + pSession->roamingStatusCode) { roamResult = eCSR_ROAM_RESULT_LOSTLINK; } else if (eCsrLostlinkRoamingDisassoc == pSession->roamingReason) { @@ -12991,7 +13004,8 @@ void csr_roam_wait_for_key_time_out_handler(void *pv) pSession->connectedProfile.bssid); if (QDF_IS_STATUS_SUCCESS(status)) { csr_roam_disconnect(mac, vdev_id, - eCSR_DISCONNECT_REASON_UNSPECIFIED); + eCSR_DISCONNECT_REASON_UNSPECIFIED, + eSIR_MAC_KEY_TIMEOUT); } } else { sme_err("session not found"); @@ -13179,6 +13193,7 @@ QDF_STATUS csr_roam_lost_link(struct mac_context *mac, uint32_t sessionId, eCsrRoamResult result = eCSR_ROAM_RESULT_LOSTLINK; struct csr_roam_info *roam_info; struct csr_roam_session *pSession = CSR_GET_SESSION(mac, sessionId); + bool from_ap = false; if (!pSession) { sme_err("session: %d not found", sessionId); @@ -13193,7 +13208,7 @@ QDF_STATUS csr_roam_lost_link(struct mac_context *mac, uint32_t sessionId, pSession->roamingStatusCode = pDisassocIndMsg->status_code; pSession->joinFailStatusCode.reasonCode = pDisassocIndMsg->reasonCode; - + from_ap = pDisassocIndMsg->from_ap; qdf_copy_macaddr(&roam_info->peerMac, &pDisassocIndMsg->peer_macaddr); } else if (eWNI_SME_DEAUTH_IND == type) { @@ -13202,7 +13217,7 @@ QDF_STATUS csr_roam_lost_link(struct mac_context *mac, uint32_t sessionId, pSession->roamingStatusCode = pDeauthIndMsg->status_code; pSession->joinFailStatusCode.reasonCode = pDeauthIndMsg->reasonCode; - + from_ap = pDeauthIndMsg->from_ap; qdf_copy_macaddr(&roam_info->peerMac, &pDeauthIndMsg->peer_macaddr); @@ -13212,6 +13227,9 @@ QDF_STATUS csr_roam_lost_link(struct mac_context *mac, uint32_t sessionId, pSession->joinFailStatusCode.reasonCode = 1; } + mlme_set_discon_reason_n_from_ap(mac->psoc, sessionId, from_ap, + pSession->joinFailStatusCode.reasonCode); + if (type == eWNI_SME_DISASSOC_IND || type == eWNI_SME_DEAUTH_IND) { struct wlan_objmgr_vdev *vdev; struct request_info info = {0}; @@ -20336,7 +20354,8 @@ void csr_process_ho_fail_ind(struct mac_context *mac_ctx, void *msg_buf) QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, "LFR3:Issue Disconnect on session %d", sessionId); csr_roam_disconnect(mac_ctx, sessionId, - eCSR_DISCONNECT_REASON_ROAM_HO_FAIL); + eCSR_DISCONNECT_REASON_ROAM_HO_FAIL, + eSIR_MAC_FW_TRIGGERED_ROAM_FAILURE); if (mac_ctx->mlme_cfg->gen.fatal_event_trigger) cds_flush_logs(WLAN_LOG_TYPE_FATAL, WLAN_LOG_INDICATOR_HOST_DRIVER, @@ -21167,7 +21186,8 @@ static QDF_STATUS csr_process_roam_sync_callback(struct mac_context *mac_ctx, if (vdev_roam_params->source == USERSPACE_INITIATED) { /* Userspace roam req fail, disconnect with AP */ csr_roam_disconnect(mac_ctx, session_id, - eCSR_DISCONNECT_REASON_DEAUTH); + eCSR_DISCONNECT_REASON_DEAUTH, + eSIR_MAC_USER_TRIGGERED_ROAM_FAILURE); } vdev_roam_params->roam_invoke_in_progress = false; goto end; @@ -21184,7 +21204,8 @@ static QDF_STATUS csr_process_roam_sync_callback(struct mac_context *mac_ctx, if (wlan_reg_is_disable_for_freq(mac_ctx->pdev, roam_synch_data->chan_freq)) { csr_roam_disconnect(mac_ctx, session_id, - eCSR_DISCONNECT_REASON_DEAUTH); + eCSR_DISCONNECT_REASON_DEAUTH, + eSIR_MAC_OPER_CHANNEL_BAND_CHANGE); sme_debug("Roaming Failed for disabled channel or band"); vdev_roam_params->roam_invoke_in_progress = false; goto end; diff --git a/core/sme/src/csr/csr_host_scan_roam.c b/core/sme/src/csr/csr_host_scan_roam.c index 09bbc15414..fb96c60305 100644 --- a/core/sme/src/csr/csr_host_scan_roam.c +++ b/core/sme/src/csr/csr_host_scan_roam.c @@ -570,10 +570,11 @@ void csr_neighbor_roam_request_handoff(struct mac_context *mac_ctx, sme_debug("csr_roamHandoffRequested: disassociating with current AP"); - if (!QDF_IS_STATUS_SUCCESS - (csr_roam_issue_disassociate_cmd - (mac_ctx, session_id, - eCSR_DISCONNECT_REASON_HANDOFF))) { + if (!QDF_IS_STATUS_SUCCESS(csr_roam_issue_disassociate_cmd( + mac_ctx, + session_id, + eCSR_DISCONNECT_REASON_HANDOFF, + eSIR_MAC_UNSPEC_FAILURE_REASON))) { sme_warn("csr_roamHandoffRequested: fail to issue disassoc"); qdf_mem_free(roam_info); return; diff --git a/core/sme/src/csr/csr_inside_api.h b/core/sme/src/csr/csr_inside_api.h index 845b5a65cc..7be00e80c2 100644 --- a/core/sme/src/csr/csr_inside_api.h +++ b/core/sme/src/csr/csr_inside_api.h @@ -254,10 +254,12 @@ eRoamCmdStatus csr_get_roam_complete_status(struct mac_context *mac, uint32_t sessionId); /* pBand can be NULL if caller doesn't need to get it */ QDF_STATUS csr_roam_issue_disassociate_cmd(struct mac_context *mac, - uint32_t sessionId, - eCsrRoamDisconnectReason reason); + uint32_t sessionId, + eCsrRoamDisconnectReason reason, + tSirMacReasonCodes mac_reason); QDF_STATUS csr_roam_disconnect_internal(struct mac_context *mac, uint32_t sessionId, - eCsrRoamDisconnectReason reason); + eCsrRoamDisconnectReason reason, + tSirMacReasonCodes mac_reason); /* pCommand may be NULL */ void csr_roam_remove_duplicate_command(struct mac_context *mac, uint32_t sessionId, tSmeCmd *pCommand, @@ -813,15 +815,17 @@ void csr_roam_free_connect_profile(tCsrRoamConnectedProfile *profile); QDF_STATUS csr_apply_channel_and_power_list(struct mac_context *mac); /* - * csr_roam_disconnect() - - * To disconnect from a network + * csr_roam_disconnect() - To disconnect from a network + * @mac: pointer to mac context + * @session_id: Session ID + * @reason: CSR disconnect reason code as per @enum eCsrRoamDisconnectReason + * @mac_reason: Mac Disconnect reason code as per @enum eSirMacReasonCodes * - * Reason -- To indicate the reason for disconnecting. Currently, only - * eCSR_DISCONNECT_REASON_MIC_ERROR is meanful. * Return QDF_STATUS */ -QDF_STATUS csr_roam_disconnect(struct mac_context *mac, uint32_t sessionId, - eCsrRoamDisconnectReason reason); +QDF_STATUS csr_roam_disconnect(struct mac_context *mac, uint32_t session_id, + eCsrRoamDisconnectReason reason, + tSirMacReasonCodes mac_reason); /* This function is used to stop a BSS. It is similar of csr_roamIssueDisconnect * but this function doesn't have any logic other than blindly trying to stop