qcacld-3.0: Cache deleted station's information in case of SAP

During disconnection process, cache disconnecting STA information
so that the same information is updated to upper-layer on receiving
GET_STATION vendor command, after disconnection.

Change-Id: I2e5a0be42d81b86e6f4490de1bdf9d7e0797506d
CRs-Fixed: 2126182
This commit is contained in:
Ashish Kumar Dhanotiya 2017-10-13 12:41:19 +05:30 • committed by snandini
commit 443d31f5f8
18 changed files with 328 additions and 77 deletions

View file

@ -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

View file

@ -56,6 +56,7 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/cfg80211.h>
#include <linux/ieee80211.h>
#include <qdf_list.h>
#include <qdf_types.h>
#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);

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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,

View file

@ -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;

View file

@ -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 */

View file

@ -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);

View file

@ -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;
}
/**

View file

@ -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 {

View file

@ -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 {

View file

@ -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:

View file

@ -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 {

View file

@ -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

View file

@ -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,

View file

@ -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;