diff --git a/core/hdd/inc/wlan_hdd_assoc.h b/core/hdd/inc/wlan_hdd_assoc.h index 8a31c9c76e1e..0b9fae19f913 100644 --- a/core/hdd/inc/wlan_hdd_assoc.h +++ b/core/hdd/inc/wlan_hdd_assoc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -378,4 +378,27 @@ static inline void hdd_save_gtk_params(struct hdd_adapter *adapter, } #endif +/** + * hdd_copy_ht_caps()- copy ht caps info from roam ht caps + * info to source ht_cap info of type ieee80211_ht_cap. + * @hdd_ht_cap: pointer to Source ht_cap info of type ieee80211_ht_cap + * @roam_ht_cap: pointer to roam ht_caps info + * + * Return: None + */ + +void hdd_copy_ht_caps(struct ieee80211_ht_cap *hdd_ht_cap, + tDot11fIEHTCaps *roam_ht_cap); + +/** + * hdd_copy_vht_caps()- copy vht caps info from roam vht caps + * info to source vht_cap info of type ieee80211_vht_cap. + * @hdd_vht_cap: pointer to Source vht_cap info of type ieee80211_vht_cap + * @roam_vht_cap: pointer to roam vht_caps info + * + * Return: None + */ +void hdd_copy_vht_caps(struct ieee80211_vht_cap *hdd_vht_cap, + tDot11fIEVHTCaps *roam_vht_cap); + #endif diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 87ed0a8c7b05..d6e2e5c03d17 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include "sir_mac_prot_def.h" @@ -821,6 +822,13 @@ struct hdd_station_info { uint8_t max_mcs_idx; uint8_t rx_mcs_map; uint8_t tx_mcs_map; + uint32_t freq; + bool ht_present; + bool vht_present; + struct ieee80211_ht_cap ht_caps; + struct ieee80211_vht_cap vht_caps; + uint32_t reason_code; + int8_t rssi; }; /** @@ -1082,6 +1090,7 @@ struct hdd_adapter { /** Per-station structure */ spinlock_t sta_info_lock; /* To protect access to station Info */ struct hdd_station_info sta_info[WLAN_MAX_STA_COUNT]; + struct hdd_station_info cache_sta_info[WLAN_MAX_STA_COUNT]; #ifdef FEATURE_WLAN_WAPI @@ -2837,6 +2846,18 @@ void hdd_pld_ipa_uc_shutdown_pipes(void); * Return: per_index_score within the max limit */ uint32_t hdd_limit_max_per_index_score(uint32_t per_index_score); +/** + * hdd_get_stainfo() - get stainfo for the specified peer + * @astainfo: array of the station info in which the sta info + * corresponding to mac_addr needs to be searched + * @mac_addr: mac address of requested peer + * + * This function find the stainfo for the peer with mac_addr + * + * Return: stainfo if found, NULL if not found + */ +struct hdd_station_info *hdd_get_stainfo(struct hdd_station_info *astainfo, + struct qdf_mac_addr mac_addr); int hdd_driver_memdump_init(void); void hdd_driver_memdump_deinit(void); diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index 4d522ac3cc0c..fc5160ddabf2 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -349,19 +349,10 @@ static int hdd_add_beacon_filter(struct hdd_adapter *adapter) return 0; } -/** - * hdd_copy_vht_caps()- copy vht caps info from roam info to - * hdd station context. - * @hdd_sta_ctx: pointer to hdd station context - * @roam_info: pointer to roam info - * - * Return: None - */ -static void hdd_copy_ht_caps(struct hdd_station_ctx *hdd_sta_ctx, - struct csr_roam_info *roam_info) +void hdd_copy_ht_caps(struct ieee80211_ht_cap *hdd_ht_cap, + tDot11fIEHTCaps *roam_ht_cap) + { - tDot11fIEHTCaps *roam_ht_cap = &roam_info->ht_caps; - struct ieee80211_ht_cap *hdd_ht_cap = &hdd_sta_ctx->conn_info.ht_caps; uint32_t i, temp_ht_cap; qdf_mem_zero(hdd_ht_cap, sizeof(struct ieee80211_ht_cap)); @@ -543,20 +534,9 @@ static void hdd_copy_ht_caps(struct hdd_station_ctx *hdd_sta_ctx, (0x03800000 >> VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK_SHIFT) #define VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB_SHIFT 26 -/** - * hdd_copy_ht_caps()- copy ht caps info from roam info to - * hdd station context. - * @hdd_sta_ctx: pointer to hdd station context - * @roam_info: pointer to roam info - * - * Return: None - */ -static void hdd_copy_vht_caps(struct hdd_station_ctx *hdd_sta_ctx, - struct csr_roam_info *roam_info) +void hdd_copy_vht_caps(struct ieee80211_vht_cap *hdd_vht_cap, + tDot11fIEVHTCaps *roam_vht_cap) { - tDot11fIEVHTCaps *roam_vht_cap = &roam_info->vht_caps; - struct ieee80211_vht_cap *hdd_vht_cap = - &hdd_sta_ctx->conn_info.vht_caps; uint32_t temp_vht_cap; qdf_mem_zero(hdd_vht_cap, sizeof(struct ieee80211_vht_cap)); @@ -811,13 +791,15 @@ static void hdd_save_bss_info(struct hdd_adapter *adapter, hdd_sta_ctx->conn_info.operationChannel); if (roam_info->vht_caps.present) { hdd_sta_ctx->conn_info.conn_flag.vht_present = true; - hdd_copy_vht_caps(hdd_sta_ctx, roam_info); + hdd_copy_vht_caps(&hdd_sta_ctx->conn_info.vht_caps, + &roam_info->vht_caps); } else { hdd_sta_ctx->conn_info.conn_flag.vht_present = false; } if (roam_info->ht_caps.present) { hdd_sta_ctx->conn_info.conn_flag.ht_present = true; - hdd_copy_ht_caps(hdd_sta_ctx, roam_info); + hdd_copy_ht_caps(&hdd_sta_ctx->conn_info.ht_caps, + &roam_info->ht_caps); } else { hdd_sta_ctx->conn_info.conn_flag.ht_present = false; } diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 48a73ad81f6d..dce8cf3b4363 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -4925,26 +4925,19 @@ fail: return -EINVAL; } -/** - * hdd_get_stainfo() - get stainfo for the specified peer - * @adapter: hostapd interface - * @mac_addr: mac address of requested peer - * - * This function find the stainfo for the peer with mac_addr - * - * Return: stainfo if found, NULL if not found - */ -static struct hdd_station_info *hdd_get_stainfo(struct hdd_adapter *adapter, - struct qdf_mac_addr mac_addr) +struct hdd_station_info *hdd_get_stainfo(struct hdd_station_info *astainfo, + struct qdf_mac_addr mac_addr) { struct hdd_station_info *stainfo = NULL; int i; for (i = 0; i < WLAN_MAX_STA_COUNT; i++) { - if (!qdf_mem_cmp(&adapter->sta_info[i].sta_mac, + if (!qdf_mem_cmp(&astainfo[i].sta_mac, &mac_addr, - QDF_MAC_ADDR_SIZE)) - stainfo = &adapter->sta_info[i]; + QDF_MAC_ADDR_SIZE)) { + stainfo = &astainfo[i]; + break; + } } return stainfo; @@ -4980,7 +4973,8 @@ static int hdd_get_station_remote(struct hdd_context *hdd_ctx, struct hdd_adapter *adapter, struct qdf_mac_addr mac_addr) { - struct hdd_station_info *stainfo = hdd_get_stainfo(adapter, mac_addr); + struct hdd_station_info *stainfo = hdd_get_stainfo(adapter->sta_info, + mac_addr); struct sk_buff *skb = NULL; struct sir_peer_info_ext peer_info; uint32_t nl_buf_len; @@ -18936,6 +18930,9 @@ int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, SME_CMD_TIMEOUT_VALUE); if (!QDF_IS_STATUS_SUCCESS(qdf_status)) hdd_warn("Deauth wait time expired"); + + adapter->cache_sta_info[staId].reason_code = + pDelStaParams->reason_code; } } diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 7ee8e6e31808..230be63725bb 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -1405,9 +1405,25 @@ static int calcuate_max_phy_rate(int mode, int nss, int ch_width, * * Return: None. */ -static void hdd_fill_station_info(struct hdd_station_info *stainfo, +static void hdd_fill_station_info(struct hdd_adapter *adapter, tSap_StationAssocReassocCompleteEvent *event) { + struct hdd_station_info *stainfo; + uint8_t i = 0; + + if (event->staId >= WLAN_MAX_STA_COUNT) { + hdd_err("invalid sta id"); + return; + } + + stainfo = &adapter->sta_info[event->staId]; + + if (!stainfo) { + hdd_err("invalid stainfo"); + return; + } + + stainfo->freq = cds_chan_to_freq(event->chan_info.chan_id); stainfo->sta_type = event->staType; stainfo->nss = event->chan_info.nss; stainfo->rate_flags = event->chan_info.rate_flags; @@ -1434,6 +1450,40 @@ static void hdd_fill_station_info(struct hdd_station_info *stainfo, stainfo->rx_mcs_map); /* expect max_phy_rate report in kbps */ stainfo->max_phy_rate *= 100; + + if (event->vht_caps.present) { + stainfo->vht_present = true; + hdd_copy_vht_caps(&stainfo->vht_caps, &event->vht_caps); + } + if (event->ht_caps.present) { + stainfo->ht_present = true; + hdd_copy_ht_caps(&stainfo->ht_caps, &event->ht_caps); + } + + while (i < WLAN_MAX_STA_COUNT) { + if (!qdf_mem_cmp(adapter->cache_sta_info[i].sta_mac.bytes, + event->staMac.bytes, + QDF_MAC_ADDR_SIZE)) { + qdf_mem_zero(&adapter->cache_sta_info[i], + sizeof(*stainfo)); + break; + } + i++; + } + if (i >= WLAN_MAX_STA_COUNT) { + i = 0; + while (i < WLAN_MAX_STA_COUNT) { + if (adapter->cache_sta_info[i].in_use != TRUE) + break; + i++; + } + } + if (i < WLAN_MAX_STA_COUNT) + qdf_mem_copy(&adapter->cache_sta_info[i], + stainfo, sizeof(struct hdd_station_info)); + else + hdd_debug("reached max staid, stainfo can't be cached"); + hdd_debug("cap %d %d %d %d %d %d %d %d %d %x %d", stainfo->ampdu, stainfo->sgi_enable, @@ -1529,6 +1579,8 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, struct ch_params sap_ch_param = {0}; eCsrPhyMode phy_mode; bool legacy_phymode; + tSap_StationDisassocCompleteEvent *disassoc_comp; + struct hdd_station_info *stainfo; dev = (struct net_device *)usrDataForCallback; if (!dev) { @@ -2027,13 +2079,8 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, } staId = event->staId; - if (QDF_IS_STATUS_SUCCESS(qdf_status)) { - hdd_fill_station_info( - &adapter->sta_info[staId], - event); - hdd_debug("hdd_hostapd_sap_event_cb, StaID: %d, Type: %d", - staId, adapter->sta_info[staId].sta_type); - } + if (QDF_IS_STATUS_SUCCESS(qdf_status)) + hdd_fill_station_info(adapter, event); if (hdd_ipa_is_enabled(hdd_ctx)) { status = hdd_ipa_wlan_evt(adapter, @@ -2148,12 +2195,22 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, break; case eSAP_STA_DISASSOC_EVENT: + disassoc_comp = + &pSapEvent->sapevt.sapStationDisassocCompleteEvent; memcpy(wrqu.addr.sa_data, - &pSapEvent->sapevt.sapStationDisassocCompleteEvent. - staMac, QDF_MAC_ADDR_SIZE); + &disassoc_comp->staMac, QDF_MAC_ADDR_SIZE); hdd_notice(" disassociated " MAC_ADDRESS_STR, MAC_ADDR_ARRAY(wrqu.addr.sa_data)); + stainfo = hdd_get_stainfo(adapter->cache_sta_info, + disassoc_comp->staMac); + if (stainfo) { + stainfo->rssi = disassoc_comp->rssi; + stainfo->tx_rate = disassoc_comp->tx_rate; + stainfo->rx_rate = disassoc_comp->rx_rate; + stainfo->reason_code = disassoc_comp->reason_code; + } + qdf_status = qdf_event_set(&hostapd_state->qdf_sta_disassoc_event); if (!QDF_IS_STATUS_SUCCESS(qdf_status)) hdd_err("Station Deauth event Set failed"); @@ -4672,6 +4729,7 @@ static __iw_softap_disassoc_sta(struct net_device *dev, (SIR_MAC_MGMT_DISASSOC >> 4), &del_sta_params); hdd_softap_sta_disassoc(adapter, &del_sta_params); + EXIT(); return 0; } diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 2ccb9913f0fd..494f047a3c56 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -10605,12 +10605,26 @@ QDF_STATUS hdd_softap_sta_deauth(struct hdd_adapter *adapter, void hdd_softap_sta_disassoc(struct hdd_adapter *adapter, struct csr_del_sta_params *pDelStaParams) { + struct sir_peer_sta_info peer_sta_info; + struct hdd_station_info *stainfo; ENTER(); /* Ignore request to disassoc bcmc station */ if (pDelStaParams->peerMacAddr.bytes[0] & 0x1) return; + wlan_hdd_get_peer_rssi(adapter, &pDelStaParams->peerMacAddr, + &peer_sta_info); + stainfo = hdd_get_stainfo(adapter->cache_sta_info, + pDelStaParams->peerMacAddr); + if (stainfo) { + stainfo->rssi = peer_sta_info.info[0].rssi; + stainfo->tx_rate = peer_sta_info.info[0].tx_rate; + stainfo->rx_rate = peer_sta_info.info[0].rx_rate; + } + + stainfo->reason_code = pDelStaParams->reason_code; + wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter), pDelStaParams); } diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 9b6e35ab4f6c..35899918e68c 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -3857,9 +3857,8 @@ static void hdd_get_peer_rssi_cb(struct sir_peer_info_resp *sta_rssi, struct sir_peer_info *rssi_info; uint8_t peer_num; - if ((!sta_rssi) || (!context)) { - hdd_err("Bad param, sta_rssi [%pK] context [%pK]", - sta_rssi, context); + if ((!sta_rssi)) { + hdd_err("Bad param, sta_rssi [%pK]", sta_rssi); return; } @@ -3887,6 +3886,7 @@ static void hdd_get_peer_rssi_cb(struct sir_peer_info_resp *sta_rssi, hdd_request_complete(request); hdd_request_put(request); + } int wlan_hdd_get_peer_rssi(struct hdd_adapter *adapter, diff --git a/core/mac/inc/ani_global.h b/core/mac/inc/ani_global.h index 9b1b08c86dc0..ff5402f2d857 100644 --- a/core/mac/inc/ani_global.h +++ b/core/mac/inc/ani_global.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -959,6 +959,9 @@ typedef struct sAniSirGlobal { void (*chan_info_cb)(struct scan_chan_info *chan_info); uint32_t rx_packet_drop_counter; bool ignore_assoc_disallowed; + uint32_t peer_rssi; + uint32_t peer_txrate; + uint32_t peer_rxrate; } tAniSirGlobal; diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 21c38d06e3d4..50ff0fc70e05 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1410,6 +1410,8 @@ typedef struct sSirSmeAssocInd { uint8_t tx_mcs_map; /* Extended CSA capability of station */ uint8_t ecsa_capable; + tDot11fIEHTCaps HTCaps; + tDot11fIEVHTCaps VHTCaps; } tSirSmeAssocInd, *tpSirSmeAssocInd; /* / Definition for Association confirm */ diff --git a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c index 8213372694ff..947e6a317a1b 100644 --- a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c +++ b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -2077,9 +2077,12 @@ static void lim_fill_assoc_ind_wapi_info(tpAniSirGlobal mac_ctx, static void lim_fill_assoc_ind_vht_info(tpAniSirGlobal mac_ctx, tpPESession session_entry, tpSirAssocReq assoc_req, - tpLimMlmAssocInd assoc_ind) + tpLimMlmAssocInd assoc_ind, + tpDphHashNode sta_ds) { uint8_t chan; + uint8_t i; + bool nw_type_11b = true; if (session_entry->limRFBand == BAND_2G) { if (session_entry->vhtCapability && assoc_req->VHTCaps.present) @@ -2087,8 +2090,19 @@ static void lim_fill_assoc_ind_vht_info(tpAniSirGlobal mac_ctx, else if (session_entry->htCapability && assoc_req->HTCaps.present) assoc_ind->chan_info.info = MODE_11NG_HT20; - else - assoc_ind->chan_info.info = MODE_11G; + else { + for (i = 0; i < SIR_NUM_11A_RATES; i++) { + if (sirIsArate(sta_ds-> + supportedRates.llaRates[i] + & 0x7F)) { + assoc_ind->chan_info.info = MODE_11G; + nw_type_11b = false; + break; + } + } + if (nw_type_11b) + assoc_ind->chan_info.info = MODE_11B; + } return; } @@ -2311,6 +2325,9 @@ void lim_send_mlm_assoc_ind(tpAniSirGlobal mac_ctx, * processing in hostapd */ if (assoc_req->HTCaps.present) { + qdf_mem_copy(&assoc_ind->ht_caps, &assoc_req->HTCaps, + sizeof(tDot11fIEHTCaps)); + rsn_len = assoc_ind->addIE.length; if (assoc_ind->addIE.length + DOT11F_IE_HTCAPS_MIN_LEN + 2 < SIR_MAC_MAX_IE_LENGTH) { @@ -2423,8 +2440,10 @@ void lim_send_mlm_assoc_ind(tpAniSirGlobal mac_ctx, ext_chan_switch; /* updates VHT information in assoc indication */ + qdf_mem_copy(&assoc_ind->vht_caps, &assoc_req->VHTCaps, + sizeof(tDot11fIEVHTCaps)); lim_fill_assoc_ind_vht_info(mac_ctx, session_entry, assoc_req, - assoc_ind); + assoc_ind, sta_ds); lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_IND, (uint32_t *) assoc_ind); qdf_mem_free(assoc_ind); diff --git a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c index 03c5286240a9..6697ebc45636 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -784,6 +784,11 @@ lim_fill_assoc_ind_params(tpAniSirGlobal mac_ctx, sme_assoc_ind->rx_mcs_map = assoc_ind->rx_mcs_map; sme_assoc_ind->tx_mcs_map = assoc_ind->tx_mcs_map; sme_assoc_ind->ecsa_capable = assoc_ind->ecsa_capable; + + if (assoc_ind->ht_caps.present) + sme_assoc_ind->HTCaps = assoc_ind->ht_caps; + if (assoc_ind->vht_caps.present) + sme_assoc_ind->VHTCaps = assoc_ind->vht_caps; } /** diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index 6998137891fe..91978d9aad0a 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -278,6 +278,9 @@ typedef struct sLimMlmAssocInd { uint8_t rx_mcs_map; uint8_t tx_mcs_map; uint8_t ecsa_capable; + + tDot11fIEHTCaps ht_caps; + tDot11fIEVHTCaps vht_caps; } tLimMlmAssocInd, *tpLimMlmAssocInd; typedef struct sLimMlmReassocReq { diff --git a/core/sap/inc/sap_api.h b/core/sap/inc/sap_api.h index 9cff66e52177..15d9986c98bc 100644 --- a/core/sap/inc/sap_api.h +++ b/core/sap/inc/sap_api.h @@ -295,6 +295,8 @@ typedef struct sap_StationAssocReassocCompleteEvent_s { uint8_t rx_mcs_map; uint8_t tx_mcs_map; uint8_t ecsa_capable; + tDot11fIEHTCaps ht_caps; + tDot11fIEVHTCaps vht_caps; } tSap_StationAssocReassocCompleteEvent; typedef struct sap_StationDisassocCompleteEvent_s { @@ -302,7 +304,11 @@ typedef struct sap_StationDisassocCompleteEvent_s { uint8_t staId; /* STAID should not be used */ uint8_t status; uint32_t statusCode; + uint32_t reason_code; eSapDisassocReason reason; + int rssi; + int tx_rate; + int rx_rate; } tSap_StationDisassocCompleteEvent; typedef struct sap_StationSetKeyCompleteEvent_s { diff --git a/core/sap/src/sap_fsm.c b/core/sap/src/sap_fsm.c index 29c8e9b6b027..7d2a80693168 100644 --- a/core/sap/src/sap_fsm.c +++ b/core/sap/src/sap_fsm.c @@ -2469,10 +2469,14 @@ QDF_STATUS sap_signal_hdd_event(struct sap_context *sap_ctx, reassoc_complete->rx_mcs_map = csr_roaminfo->rx_mcs_map; reassoc_complete->tx_mcs_map = csr_roaminfo->tx_mcs_map; reassoc_complete->ecsa_capable = csr_roaminfo->ecsa_capable; + if (csr_roaminfo->ht_caps.present) + reassoc_complete->ht_caps = csr_roaminfo->ht_caps; + if (csr_roaminfo->vht_caps.present) + reassoc_complete->vht_caps = csr_roaminfo->vht_caps; + break; case eSAP_STA_DISASSOC_EVENT: - if (!csr_roaminfo) { QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR, FL("Invalid CSR Roam Info")); @@ -2485,13 +2489,17 @@ QDF_STATUS sap_signal_hdd_event(struct sap_context *sap_ctx, qdf_copy_macaddr(&disassoc_comp->staMac, &csr_roaminfo->peerMac); disassoc_comp->staId = csr_roaminfo->staId; - if (csr_roaminfo->reasonCode == eCSR_ROAM_RESULT_FORCED) + if (csr_roaminfo->disassoc_reason == eCSR_ROAM_RESULT_FORCED) disassoc_comp->reason = eSAP_USR_INITATED_DISASSOC; else disassoc_comp->reason = eSAP_MAC_INITATED_DISASSOC; disassoc_comp->statusCode = csr_roaminfo->statusCode; disassoc_comp->status = (eSapStatus) context; + disassoc_comp->rssi = csr_roaminfo->rssi; + disassoc_comp->rx_rate = csr_roaminfo->rx_rate; + disassoc_comp->tx_rate = csr_roaminfo->tx_rate; + disassoc_comp->reason_code = csr_roaminfo->reasonCode; break; case eSAP_STA_SET_KEY_EVENT: diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index 3595d37415eb..6d73c2c3ca0a 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1415,6 +1415,9 @@ struct csr_roam_info { tSirResultCodes statusCode; /* this'd be our own defined or sent from otherBSS(per 802.11spec) */ uint32_t reasonCode; + + uint8_t disassoc_reason; + uint8_t staId; /* Peer stationId when connected */ /* * The DPU signatures will be sent eventually to TL to help it @@ -1523,6 +1526,9 @@ struct csr_roam_info { uint16_t fils_seq_num; struct fils_join_rsp_params *fils_join_rsp; #endif + int rssi; + int tx_rate; + int rx_rate; }; typedef struct tagCsrFreqScanInfo { @@ -1563,6 +1569,9 @@ typedef struct sSirSmeAssocIndToUpperLayerCnf { uint8_t tx_mcs_map; /* Extended capabilities of STA */ uint8_t ecsa_capable; + + tDot11fIEHTCaps ht_caps; + tDot11fIEVHTCaps vht_caps; } tSirSmeAssocIndToUpperLayerCnf, *tpSirSmeAssocIndToUpperLayerCnf; typedef struct tagCsrSummaryStatsInfo { diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 0936fcb9a0d4..bbee8f3f4564 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1737,6 +1737,18 @@ QDF_STATUS sme_set_bt_activity_info_cb(tHalHandle hal, QDF_STATUS sme_set_smps_cfg(uint32_t vdev_id, uint32_t param_id, uint32_t param_val); + +/** + * sme_get_peer_stats() - sme api to post peer info request + * @mac: mac handle + * @req: peer info request struct send to wma + * + * Return: QDF_STATUS_SUCCESS or non-zero on failure + */ + +QDF_STATUS sme_get_peer_stats(tpAniSirGlobal mac, + struct sir_peer_info_req req); + /** * sme_get_peer_info() - sme api to get peer info * @hal: hal handle for getting global mac struct diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 1433aa488564..adcce7bd5547 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1954,6 +1954,8 @@ QDF_STATUS sme_process_msg(tHalHandle hHal, struct scheduler_msg *pMsg) { QDF_STATUS status = QDF_STATUS_E_FAILURE; tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + struct sir_peer_info *peer_stats; + struct sir_peer_info_resp *peer_info_rsp; if (pMsg == NULL) { sme_err("Empty message for SME"); @@ -2141,6 +2143,17 @@ QDF_STATUS sme_process_msg(tHalHandle hHal, struct scheduler_msg *pMsg) if (pMac->sme.pget_peer_info_ind_cb) pMac->sme.pget_peer_info_ind_cb(pMsg->bodyptr, pMac->sme.pget_peer_info_cb_context); + if (pMsg->bodyptr) { + peer_info_rsp = (struct sir_peer_info_resp *) + (pMsg->bodyptr); + peer_stats = (struct sir_peer_info *) + (peer_info_rsp->info); + if (peer_stats) { + pMac->peer_rssi = peer_stats[0].rssi; + pMac->peer_txrate = peer_stats[0].tx_rate; + pMac->peer_rxrate = peer_stats[0].rx_rate; + } + } qdf_mem_free(pMsg->bodyptr); break; case eWNI_SME_GET_PEER_INFO_EXT_IND: @@ -8581,6 +8594,39 @@ QDF_STATUS sme_get_link_speed(tHalHandle hHal, tSirLinkSpeedInfo *lsReq, return status; } +QDF_STATUS sme_get_peer_stats(tpAniSirGlobal mac, + struct sir_peer_info_req req) +{ + QDF_STATUS qdf_status; + struct scheduler_msg message = {0}; + + qdf_status = sme_acquire_global_lock(&mac->sme); + if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { + sme_debug("Failed to get Lock"); + return qdf_status; + } + /* serialize the req through MC thread */ + message.bodyptr = qdf_mem_malloc(sizeof(req)); + if (NULL == message.bodyptr) { + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, + "%s: Memory allocation failed.", __func__); + sme_release_global_lock(&mac->sme); + return QDF_STATUS_E_NOMEM; + } + qdf_mem_copy(message.bodyptr, &req, sizeof(req)); + message.type = WMA_GET_PEER_INFO; + message.reserved = 0; + qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA, &message); + if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, + "%s: Post get peer info msg fail", __func__); + qdf_mem_free(message.bodyptr); + qdf_status = QDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&mac->sme); + return qdf_status; +} + QDF_STATUS sme_get_peer_info(tHalHandle hal, struct sir_peer_info_req req, void *context, void (*callbackfn)(struct sir_peer_info_resp *param, @@ -8615,6 +8661,7 @@ QDF_STATUS sme_get_peer_info(tHalHandle hal, struct sir_peer_info_req req, } qdf_mem_copy(message.bodyptr, &req, sizeof(req)); message.type = WMA_GET_PEER_INFO; + message.reserved = 0; qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA, &message); if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 65b78fd92220..3602184bb0d9 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -6816,6 +6816,10 @@ static void csr_roam_process_results_default(tpAniSirGlobal mac_ctx, break; case eCsrForcedDisassocSta: case eCsrForcedDeauthSta: + roam_info.rssi = mac_ctx->peer_rssi; + roam_info.tx_rate = mac_ctx->peer_txrate; + roam_info.rx_rate = mac_ctx->peer_rxrate; + csr_roam_state_change(mac_ctx, eCSR_ROAMING_STATE_JOINED, session_id); session = CSR_GET_SESSION(mac_ctx, session_id); @@ -6826,7 +6830,8 @@ static void csr_roam_process_results_default(tpAniSirGlobal mac_ctx, qdf_mem_copy(roam_info.peerMac.bytes, cmd->u.roamCmd.peerMac, sizeof(tSirMacAddr)); - roam_info.reasonCode = eCSR_ROAM_RESULT_FORCED; + roam_info.reasonCode = cmd->u.roamCmd.reason; + roam_info.disassoc_reason = eCSR_ROAM_RESULT_FORCED; roam_info.statusCode = eSIR_SME_SUCCESS; status = csr_roam_call_callback(mac_ctx, session_id, &roam_info, cmd->u.roamCmd.roamId, @@ -10363,6 +10368,10 @@ void csr_roam_joined_state_msg_processor(tpAniSirGlobal pMac, void *pMsgBuf) roam_info->rx_mcs_map = pUpperLayerAssocCnf->rx_mcs_map; roam_info->tx_mcs_map = pUpperLayerAssocCnf->tx_mcs_map; roam_info->ecsa_capable = pUpperLayerAssocCnf->ecsa_capable; + if (pUpperLayerAssocCnf->ht_caps.present) + roam_info->ht_caps = pUpperLayerAssocCnf->ht_caps; + if (pUpperLayerAssocCnf->vht_caps.present) + roam_info->vht_caps = pUpperLayerAssocCnf->vht_caps; if (CSR_IS_INFRA_AP(roam_info->u.pConnectedProfile)) { pMac->roam.roamSession[sessionId].connectState = eCSR_ASSOC_STATE_TYPE_INFRA_CONNECTED; @@ -11209,6 +11218,16 @@ csr_roam_chk_lnk_assoc_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) qdf_mem_copy(&roam_info_ptr->chan_info, &pAssocInd->chan_info, sizeof(tSirSmeChanInfo)); + + if (pAssocInd->HTCaps.present) + qdf_mem_copy(&roam_info_ptr->ht_caps, + &pAssocInd->HTCaps, + sizeof(tDot11fIEHTCaps)); + if (pAssocInd->VHTCaps.present) + qdf_mem_copy(&roam_info_ptr->vht_caps, + &pAssocInd->VHTCaps, + sizeof(tDot11fIEVHTCaps)); + if (CSR_IS_INFRA_AP(roam_info_ptr->u.pConnectedProfile)) { if (session->pCurRoamProfile && CSR_IS_ENC_TYPE_STATIC( @@ -11364,6 +11383,11 @@ csr_roam_send_disconnect_done_indication(tpAniSirGlobal mac_ctx, tSirSmeRsp roam_info.statusCode = eSIR_SME_STA_NOT_ASSOCIATED; qdf_mem_copy(roam_info.peerMac.bytes, discon_ind->peer_mac, ETH_ALEN); + + roam_info.rssi = mac_ctx->peer_rssi; + roam_info.tx_rate = mac_ctx->peer_txrate; + roam_info.rx_rate = mac_ctx->peer_rxrate; + csr_roam_call_callback(mac_ctx, discon_ind->session_id, &roam_info, 0, eCSR_ROAM_LOSTLINK, eCSR_ROAM_RESULT_DISASSOC_IND); @@ -12656,6 +12680,7 @@ QDF_STATUS csr_roam_lost_link(tpAniSirGlobal pMac, uint32_t sessionId, sme_err("session: %d not found", sessionId); return QDF_STATUS_E_FAILURE; } + qdf_mem_set(&roamInfo, sizeof(struct csr_roam_info), 0); #ifndef NAPIER_SCAN pSession->fCancelRoaming = false; #endif @@ -12665,22 +12690,34 @@ QDF_STATUS csr_roam_lost_link(tpAniSirGlobal pMac, uint32_t sessionId, pSession->roamingStatusCode = pDisassocIndMsg->statusCode; pSession->joinFailStatusCode.reasonCode = pDisassocIndMsg->reasonCode; + + qdf_copy_macaddr(&roamInfo.peerMac, + &pDisassocIndMsg->peer_macaddr); } else if (eWNI_SME_DEAUTH_IND == type) { result = eCSR_ROAM_RESULT_DEAUTH_IND; pDeauthIndMsg = (tSirSmeDeauthInd *) pSirMsg; pSession->roamingStatusCode = pDeauthIndMsg->statusCode; pSession->joinFailStatusCode.reasonCode = pDeauthIndMsg->reasonCode; + + qdf_copy_macaddr(&roamInfo.peerMac, + &pDeauthIndMsg->peer_macaddr); + } else { sme_warn("gets an unknown type (%d)", type); result = eCSR_ROAM_RESULT_NONE; pSession->joinFailStatusCode.reasonCode = 1; } - /* call profile lost link routine here */ - if (!CSR_IS_INFRA_AP(&pSession->connectedProfile)) - csr_roam_call_callback(pMac, sessionId, NULL, 0, - eCSR_ROAM_LOSTLINK_DETECTED, result); + if (type == eWNI_SME_DISASSOC_IND || type == eWNI_SME_DEAUTH_IND) { + struct sir_peer_info_req req; + + req.sessionid = sessionId; + req.peer_macaddr = roamInfo.peerMac; + sme_get_peer_stats(pMac, req); + } + csr_roam_call_callback(pMac, sessionId, NULL, 0, + eCSR_ROAM_LOSTLINK_DETECTED, result); if (eWNI_SME_DISASSOC_IND == type) status = csr_send_mb_disassoc_cnf_msg(pMac, pDisassocIndMsg); @@ -15958,6 +15995,11 @@ QDF_STATUS csr_send_assoc_ind_to_upper_layer_cnf_msg(tpAniSirGlobal pMac, pBuf = (uint8_t *)&pMsg->ecsa_capable; *pBuf = pAssocInd->ecsa_capable; + if (pAssocInd->HTCaps.present) + pMsg->ht_caps = pAssocInd->HTCaps; + if (pAssocInd->VHTCaps.present) + pMsg->vht_caps = pAssocInd->VHTCaps; + msgQ.type = eWNI_SME_UPPER_LAYER_ASSOC_CNF; msgQ.bodyptr = pMsg; msgQ.bodyval = 0;