diff options
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_cfg.h | 19 | ||||
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_main.h | 51 | ||||
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_tgt_cfg.h | 3 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_cfg.c | 7 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_cfg80211.c | 408 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_main.c | 17 | ||||
| -rw-r--r-- | CORE/MAC/inc/sirApi.h | 58 | ||||
| -rw-r--r-- | CORE/MAC/inc/wniApi.h | 3 | ||||
| -rw-r--r-- | CORE/MAC/src/include/sirParams.h | 4 | ||||
| -rw-r--r-- | CORE/SERVICES/WMA/wma.c | 309 | ||||
| -rw-r--r-- | CORE/SERVICES/WMA/wma.h | 1 | ||||
| -rw-r--r-- | CORE/SME/inc/smeInternal.h | 6 | ||||
| -rw-r--r-- | CORE/SME/inc/sme_Api.h | 17 | ||||
| -rw-r--r-- | CORE/SME/src/sme_common/sme_Api.c | 67 | ||||
| -rw-r--r-- | CORE/SYS/legacy/src/utils/src/macTrace.c | 3 | ||||
| -rw-r--r-- | CORE/WDA/inc/wlan_qct_wda.h | 4 |
16 files changed, 968 insertions, 9 deletions
diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h index 9c045ced48b9..40dd9bff46c0 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg.h +++ b/CORE/HDD/inc/wlan_hdd_cfg.h @@ -1548,6 +1548,24 @@ typedef enum #define CFG_MAX_HT_MCS_FOR_TX_DATA_DEFAULT (WNI_CFG_MAX_HT_MCS_TX_DATA_STADEF) /* + * <ini> + * gSapGetPeerInfo - Enable/Disable remote peer info query support + * @Min: 0 - Disable remote peer info query support + * @Max: 1 - Enable remote peer info query support + * @Default: 0 + * + * This ini is used to enable/disable remote peer info query support + * + * Usage: External + * + * </ini> + */ +#define CFG_SAP_GET_PEER_INFO "gSapGetPeerInfo" +#define CFG_SAP_GET_PEER_INFO_MIN (0) +#define CFG_SAP_GET_PEER_INFO_MAX (1) +#define CFG_SAP_GET_PEER_INFO_DEFAULT (0) + +/* * RSSI Thresholds * Used when eHDD_LINK_SPEED_REPORT_SCALED is selected */ @@ -4994,6 +5012,7 @@ struct hdd_config { uint8_t enable_rts_sifsbursting; uint8_t max_mpdus_inampdu; uint16_t max_ht_mcs_txdata; + bool sap_get_peer_info; #ifdef QCA_LL_TX_FLOW_CT v_U32_t TxFlowLowWaterMark; v_U32_t TxFlowHighWaterMarkOffset; diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h index d41a45f58e44..02a6b6803857 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -917,6 +917,55 @@ typedef struct { uint8_t tx_mcs_map; } hdd_station_info_t; +/** + * struct hdd_rate_info - rate_info in HDD + * @rate: tx/rx rate (kbps) + * @mode: 0->11abg legacy, 1->HT, 2->VHT (refer to sir_sme_phy_mode) + * @nss: number of streams + * @mcs: mcs index for HT/VHT mode + * @rate_flags: rate flags for last tx/rx + * + * rate info in HDD + */ +struct hdd_rate_info { + uint32_t rate; + uint8_t mode; + uint8_t nss; + uint8_t mcs; + uint8_t rate_flags; +}; + +/** + * struct hdd_fw_txrx_stats - fw txrx status in HDD + * (refer to station_info struct in Kernel) + * @tx_packets: packets transmitted to this station + * @tx_bytes: bytes transmitted to this station + * @rx_packets: packets received from this station + * @rx_bytes: bytes received from this station + * @rx_retries: cumulative retry counts + * @tx_failed: number of failed transmissions + * @last_tx_rate: last used tx bitrate (kbps) + * @last_rx_rate: last used rx bitrate (kbps) + * @rssi: The signal strength (dbm) + * @tx_rate: last used tx rate info + * @rx_rate: last used rx rate info + * + * fw txrx status in HDD + */ +struct hdd_fw_txrx_stats { + uint32_t tx_packets; + uint64_t tx_bytes; + uint32_t rx_packets; + uint64_t rx_bytes; + uint32_t tx_retries; + uint32_t tx_failed; + uint32_t last_tx_rate; + uint32_t last_rx_rate; + int8_t rssi; + struct hdd_rate_info tx_rate; + struct hdd_rate_info rx_rate; +}; + struct hdd_ap_ctx_s { hdd_hostapd_state_t HostapdState; @@ -968,6 +1017,8 @@ struct hdd_ap_ctx_s #endif v_BOOL_t dfs_cac_block_tx; enum bss_stop_reason bss_stop_reason; + /* Fw txrx stats info */ + struct hdd_fw_txrx_stats txrx_stats; }; typedef struct hdd_scaninfo_s diff --git a/CORE/HDD/inc/wlan_hdd_tgt_cfg.h b/CORE/HDD/inc/wlan_hdd_tgt_cfg.h index 02bf295e1056..bcacb5f0eb62 100644 --- a/CORE/HDD/inc/wlan_hdd_tgt_cfg.h +++ b/CORE/HDD/inc/wlan_hdd_tgt_cfg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -58,6 +58,7 @@ struct hdd_tgt_services { #ifdef SAP_AUTH_OFFLOAD bool sap_auth_offload_service; #endif + bool get_peer_info_enabled; }; struct hdd_tgt_ht_cap { diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c index 836f7028acef..c57cde12a13f 100644 --- a/CORE/HDD/src/wlan_hdd_cfg.c +++ b/CORE/HDD/src/wlan_hdd_cfg.c @@ -2408,6 +2408,13 @@ REG_TABLE_ENTRY g_registry_table[] = CFG_MAX_HT_MCS_FOR_TX_DATA_MIN, CFG_MAX_HT_MCS_FOR_TX_DATA_MAX), + REG_VARIABLE(CFG_SAP_GET_PEER_INFO, WLAN_PARAM_Integer, + hdd_config_t, sap_get_peer_info, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_SAP_GET_PEER_INFO_DEFAULT, + CFG_SAP_GET_PEER_INFO_MIN, + CFG_SAP_GET_PEER_INFO_MAX), + REG_VARIABLE( CFG_ENABLE_FIRST_SCAN_2G_ONLY_NAME, WLAN_PARAM_Integer, hdd_config_t, enableFirstScan2GOnly, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index b152c6f7f6b4..a23c50d2254b 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -12828,7 +12828,7 @@ static int hdd_get_station_remote(hdd_context_t *hdd_ctx, nla_put_u32(skb, REMOTE_TX_PACKETS, stainfo->tx_packets) || nla_put_u64(skb, REMOTE_TX_BYTES, stainfo->tx_bytes) || nla_put_u32(skb, REMOTE_RX_PACKETS, stainfo->rx_packets) || - nla_put_u64(skb, REMOTE_TX_BYTES, stainfo->rx_bytes) || + nla_put_u64(skb, REMOTE_RX_BYTES, stainfo->rx_bytes) || nla_put_u8(skb, REMOTE_WMM, stainfo->isQosEnabled) || nla_put_u8(skb, REMOTE_SUPPORTED_MODE, stainfo->mode)) { hddLog(LOGE, FL("put fail")); @@ -23028,6 +23028,409 @@ static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, return ret; } +/** + * hdd_get_rate_flags_ht() - get HT rate flags based on rate, nss and mcs + * @rate: Data rate (100 kbps) + * @nss: Number of streams + * @mcs: HT mcs index + * + * This function is used to construct HT rate flag with rate, nss and mcs + * + * Return: rate flags for success, 0 on failure. + */ +static uint8_t hdd_get_rate_flags_ht(uint32_t rate, + uint8_t nss, + uint8_t mcs) +{ + struct index_data_rate_type *mcs_rate; + uint8_t flags = 0; + + mcs_rate = (struct index_data_rate_type *) + ((nss == 1) ? &supported_mcs_rate_nss1 : + &supported_mcs_rate_nss2); + + if (rate == mcs_rate[mcs].supported_rate[0]) { + flags |= eHAL_TX_RATE_HT20; + } else if (rate == mcs_rate[mcs].supported_rate[1]) { + flags |= eHAL_TX_RATE_HT40; + } else if (rate == mcs_rate[mcs].supported_rate[2]) { + flags |= eHAL_TX_RATE_HT20; + flags |= eHAL_TX_RATE_SGI; + } else if (rate == mcs_rate[mcs].supported_rate[3]) { + flags |= eHAL_TX_RATE_HT40; + flags |= eHAL_TX_RATE_SGI; + } else { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("invalid params rate %d nss %d mcs %d"), + rate, nss, mcs); + } + + return flags; +} + +#ifdef WLAN_FEATURE_11AC +/** + * hdd_get_rate_flags_vht() - get VHT rate flags based on rate, nss and mcs + * @rate: Data rate (100 kbps) + * @nss: Number of streams + * @mcs: VHT mcs index + * + * This function is used to construct VHT rate flag with rate, nss and mcs + * + * Return: rate flags for success, 0 on failure. + */ +static uint8_t hdd_get_rate_flags_vht(uint32_t rate, + uint8_t nss, + uint8_t mcs) +{ + struct index_vht_data_rate_type *mcs_rate; + uint8_t flags = 0; + + mcs_rate = (struct index_vht_data_rate_type *) + ((nss == 1) ? + &supported_vht_mcs_rate_nss1 : + &supported_vht_mcs_rate_nss2); + + if (rate == mcs_rate[mcs].supported_VHT80_rate[0]) { + flags |= eHAL_TX_RATE_VHT80; + } else if (rate == mcs_rate[mcs].supported_VHT80_rate[1]) { + flags |= eHAL_TX_RATE_VHT80; + flags |= eHAL_TX_RATE_SGI; + } else if (rate == mcs_rate[mcs].supported_VHT40_rate[0]) { + flags |= eHAL_TX_RATE_VHT40; + } else if (rate == mcs_rate[mcs].supported_VHT40_rate[1]) { + flags |= eHAL_TX_RATE_VHT40; + flags |= eHAL_TX_RATE_SGI; + } else if (rate == mcs_rate[mcs].supported_VHT20_rate[0]) { + flags |= eHAL_TX_RATE_VHT20; + } else if (rate == mcs_rate[mcs].supported_VHT20_rate[1]) { + flags |= eHAL_TX_RATE_VHT20; + flags |= eHAL_TX_RATE_SGI; + } else { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("invalid params rate %d nss %d mcs %d"), + rate, nss, mcs); + } + + return flags; +} +#else +static uint8_t hdd_get_rate_flags_vht(uint32_t rate, + uint8_t nss, + uint8_t mcs) +{ + return 0; +} +#endif + +/** + * hdd_get_rate_flags() - get HT/VHT rate flags based on rate, nss and mcs + * @rate: Data rate (100 kbps) + * @mode: Tx/Rx mode + * @nss: Number of streams + * @mcs: Mcs index + * + * This function is used to construct rate flag with rate, nss and mcs + * + * Return: rate flags for success, 0 on failure. + */ +static uint8_t hdd_get_rate_flags(uint32_t rate, + uint8_t mode, + uint8_t nss, + uint8_t mcs) +{ + uint8_t flags = 0; + + if (mode == SIR_SME_PHY_MODE_HT) + flags = hdd_get_rate_flags_ht(rate, nss, mcs); + else if (mode == SIR_SME_PHY_MODE_VHT) + flags = hdd_get_rate_flags_vht(rate, nss, mcs); + else + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("invalid mode param %d"), + mode); + + return flags; +} + +/** + * wlan_hdd_fill_rate_info() - fill HDD rate info from SIR peer info + * @ap_ctx: AP Context + * @peer_info: SIR peer info pointer + * + * This function is used to fill HDD rate info rom SIR peer info + * + * Return: None + */ +static void wlan_hdd_fill_rate_info(hdd_ap_ctx_t *ap_ctx, + struct sir_peer_info_ext *peer_info) +{ + uint8_t flags; + uint32_t rate_code; + + /* tx rate info */ + ap_ctx->txrx_stats.tx_rate.rate = peer_info->tx_rate; + rate_code = peer_info->tx_rate_code; + + ap_ctx->txrx_stats.tx_rate.mode = SIR_SME_PHY_MODE_LEGACY; + if ((WMI_GET_HW_RATECODE_PREAM_V1(rate_code)) == + WMI_RATE_PREAMBLE_HT) + ap_ctx->txrx_stats.tx_rate.mode = SIR_SME_PHY_MODE_HT; + else if ((WMI_GET_HW_RATECODE_PREAM_V1(rate_code)) == + WMI_RATE_PREAMBLE_VHT) + ap_ctx->txrx_stats.tx_rate.mode = SIR_SME_PHY_MODE_VHT; + + ap_ctx->txrx_stats.tx_rate.nss = + WMI_GET_HW_RATECODE_NSS_V1(rate_code) + 1; + ap_ctx->txrx_stats.tx_rate.mcs = + WMI_GET_HW_RATECODE_RATE_V1(rate_code); + + flags = hdd_get_rate_flags(ap_ctx->txrx_stats.tx_rate.rate/100, + ap_ctx->txrx_stats.tx_rate.mode, + ap_ctx->txrx_stats.tx_rate.nss, + ap_ctx->txrx_stats.tx_rate.mcs); + if (flags != 0) + ap_ctx->txrx_stats.tx_rate.rate_flags = flags; + + hddLog(VOS_TRACE_LEVEL_INFO, + FL("tx: mode %d nss %d mcs %d rate_flags %x flags %x"), + ap_ctx->txrx_stats.tx_rate.mode, + ap_ctx->txrx_stats.tx_rate.nss, + ap_ctx->txrx_stats.tx_rate.mcs, + ap_ctx->txrx_stats.tx_rate.rate_flags, + flags); + + /* rx rate info */ + ap_ctx->txrx_stats.rx_rate.rate = peer_info->rx_rate; + rate_code = peer_info->rx_rate_code; + + ap_ctx->txrx_stats.rx_rate.mode = SIR_SME_PHY_MODE_LEGACY; + if ((WMI_GET_HW_RATECODE_PREAM_V1(rate_code)) == + WMI_RATE_PREAMBLE_HT) + ap_ctx->txrx_stats.rx_rate.mode = SIR_SME_PHY_MODE_HT; + else if ((WMI_GET_HW_RATECODE_PREAM_V1(rate_code)) == + WMI_RATE_PREAMBLE_VHT) + ap_ctx->txrx_stats.rx_rate.mode = SIR_SME_PHY_MODE_VHT; + + ap_ctx->txrx_stats.rx_rate.nss = + WMI_GET_HW_RATECODE_NSS_V1(rate_code) + 1; + ap_ctx->txrx_stats.rx_rate.mcs = + WMI_GET_HW_RATECODE_RATE_V1(rate_code); + + flags = hdd_get_rate_flags(ap_ctx->txrx_stats.rx_rate.rate/100, + ap_ctx->txrx_stats.rx_rate.mode, + ap_ctx->txrx_stats.rx_rate.nss, + ap_ctx->txrx_stats.rx_rate.mcs); + if (flags != 0) + ap_ctx->txrx_stats.rx_rate.rate_flags = flags; + + hddLog(VOS_TRACE_LEVEL_INFO, + FL("rx: mode %d nss %d mcs %d rate_flags %x flags %x"), + ap_ctx->txrx_stats.rx_rate.mode, + ap_ctx->txrx_stats.rx_rate.nss, + ap_ctx->txrx_stats.rx_rate.mcs, + ap_ctx->txrx_stats.rx_rate.rate_flags, + flags); +} + +/** + * wlan_hdd_get_peer_info_cb() - get peer info callback + * @sta_info: pointer of peer information + * @context: get peer info callback context + * + * This function will fill stats info of AP Context + * + */ +void wlan_hdd_get_peer_info_cb(struct sir_peer_info_ext_resp *sta_info, + void *context) +{ + struct statsContext *get_peer_info_context; + struct sir_peer_info_ext *peer_info; + hdd_adapter_t *adapter; + hdd_ap_ctx_t *ap_ctx; + + if ((NULL == sta_info) || (NULL == context)) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Bad param, sta_info [%p] context [%p]", + __func__, sta_info, context); + return; + } + + spin_lock(&hdd_context_lock); + /* + * there is a race condition that exists between this callback + * function and the caller since the caller could time out either + * before or while this code is executing. we use a spinlock to + * serialize these actions + */ + get_peer_info_context = context; + if (PEER_INFO_CONTEXT_MAGIC != + get_peer_info_context->magic) { + /* + * the caller presumably timed out so there is nothing + * we can do + */ + spin_unlock(&hdd_context_lock); + hddLog(VOS_TRACE_LEVEL_WARN, + "%s: Invalid context, magic [%08x]", + __func__, + get_peer_info_context->magic); + return; + } + + if (!sta_info->count) { + spin_unlock(&hdd_context_lock); + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("Fail to get remote peer info")); + return; + } + + adapter = get_peer_info_context->pAdapter; + ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter); + vos_mem_zero(&ap_ctx->txrx_stats, + sizeof(struct hdd_fw_txrx_stats)); + + peer_info = sta_info->info; + ap_ctx->txrx_stats.tx_packets = peer_info->tx_packets; + ap_ctx->txrx_stats.tx_bytes = peer_info->tx_bytes; + ap_ctx->txrx_stats.rx_packets = peer_info->rx_packets; + ap_ctx->txrx_stats.rx_bytes = peer_info->rx_bytes; + ap_ctx->txrx_stats.tx_retries = peer_info->tx_retries; + ap_ctx->txrx_stats.tx_failed = peer_info->tx_failed; + ap_ctx->txrx_stats.rssi = + peer_info->rssi + WLAN_HDD_TGT_NOISE_FLOOR_DBM; + wlan_hdd_fill_rate_info(ap_ctx, peer_info); + + get_peer_info_context->magic = 0; + + /* notify the caller */ + complete(&get_peer_info_context->completion); + + /* serialization is complete */ + spin_unlock(&hdd_context_lock); +} + +/** + * wlan_hdd_get_peer_info() - get peer info + * @adapter: hostapd interface + * @macaddress: request peer mac address + * + * This function will call sme_get_peer_info_ext to get peer info + * + * Return: 0 on success, otherwise error value + */ +static int wlan_hdd_get_peer_info(hdd_adapter_t *adapter, + v_MACADDR_t macaddress) +{ + eHalStatus hstatus; + int ret; + struct statsContext context; + struct sir_peer_info_ext_req peer_info_req; + + if (NULL == adapter) { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", + __func__); + return -EFAULT; + } + + init_completion(&context.completion); + context.magic = PEER_INFO_CONTEXT_MAGIC; + context.pAdapter = adapter; + + vos_mem_copy(&(peer_info_req.peer_macaddr), &macaddress, + VOS_MAC_ADDR_SIZE); + peer_info_req.sessionid = adapter->sessionId; + peer_info_req.reset_after_request = 0; + hstatus = sme_get_peer_info_ext(WLAN_HDD_GET_HAL_CTX(adapter), + &peer_info_req, + &context, + wlan_hdd_get_peer_info_cb); + if (eHAL_STATUS_SUCCESS != hstatus) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Unable to retrieve statistics for peer info", + __func__); + ret = -EFAULT; + } else { + if (!wait_for_completion_timeout(&context.completion, + msecs_to_jiffies(WLAN_WAIT_TIME_STATS))) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: SME timed out while retrieving peer info", + __func__); + ret = -EFAULT; + } else + ret = 0; + } + /* + * either we never sent a request, we sent a request and received a + * response or we sent a request and timed out. if we never sent a + * request or if we sent a request and got a response, we want to + * clear the magic out of paranoia. if we timed out there is a + * race condition such that the callback function could be + * executing at the same time we are. of primary concern is if the + * callback function had already verified the "magic" but had not + * yet set the completion variable when a timeout occurred. we + * serialize these activities by invalidating the magic while + * holding a shared spinlock which will cause us to block if the + * callback is currently executing + */ + spin_lock(&hdd_context_lock); + context.magic = 0; + spin_unlock(&hdd_context_lock); + return ret; +} + +/** + * wlan_hdd_get_station_remote() - NL80211_CMD_GET_STATION handler for SoftAP + * @wiphy: pointer to wiphy + * @dev: pointer to net_device structure + * @mac: request peer mac address + * @sinfo: pointer to station_info struct + * + * This function will get remote peer info from fw and fill sinfo struct + * + * Return: 0 on success, otherwise error value + */ +static int wlan_hdd_get_station_remote(struct wiphy *wiphy, + struct net_device *dev, + const u8 *mac, + struct station_info *sinfo) +{ + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hddctx = (hdd_context_t *)wiphy_priv(wiphy); + hdd_station_info_t *stainfo = NULL; + v_MACADDR_t macaddr; + int status; + int i; + + status = wlan_hdd_validate_context(hddctx); + if (0 != status) + return status; + + hddLog(VOS_TRACE_LEVEL_INFO, FL("get peer %pM info"), mac); + + for (i = 0; i < WLAN_MAX_STA_COUNT; i++) { + if (vos_mem_compare(adapter->aStaInfo[i].macAddrSTA.bytes, + mac, + VOS_MAC_ADDR_SIZE)) { + stainfo = &adapter->aStaInfo[i]; + break; + } + } + + if (!stainfo) { + hddLog(LOGE, FL("peer %pM not found"), mac); + return -EINVAL; + } + + vos_mem_copy(macaddr.bytes, mac, VOS_MAC_ADDR_SIZE); + status = wlan_hdd_get_peer_info(adapter, macaddr); + if (status) { + hddLog(LOGE, FL("fail to get peer info from fw")); + return -EPERM; + } + + return status; +} static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, @@ -23074,6 +23477,9 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } + if (pAdapter->device_mode == WLAN_HDD_SOFTAP && + pCfg->sap_get_peer_info) + return wlan_hdd_get_station_remote(wiphy, dev, mac, sinfo); if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) || (0 == ssidlen)) diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index b70e3eff77e7..4e1c0a464119 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -8294,6 +8294,7 @@ static void hdd_update_tgt_services(hdd_context_t *hdd_ctx, #ifdef SAP_AUTH_OFFLOAD cfg_ini->enable_sap_auth_offload &= cfg->sap_auth_offload_service; #endif + cfg_ini->sap_get_peer_info &= cfg->get_peer_info_enabled; } /** @@ -15344,6 +15345,20 @@ int hdd_wlan_startup(struct device *dev, v_VOID_t *hif_sc) __func__, ret); } + if (pHddCtx->cfg_ini->sap_get_peer_info) { + hddLog(VOS_TRACE_LEVEL_INFO, + "%s Send WMI_PDEV_PARAM_PEER_STATS_INFO_ENABLE", + __func__); + ret = process_wma_set_command(0, + WMI_PDEV_PARAM_PEER_STATS_INFO_ENABLE, + pHddCtx->cfg_ini->sap_get_peer_info, + PDEV_CMD); + if (0 != ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: WMI_PDEV_PARAM_PEER_STATS_INFO_ENABLE failed %d", + __func__, ret); + } + } status = hdd_set_sme_chan_list(pHddCtx); if (status != VOS_STATUS_SUCCESS) { diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h index b4c0ac2c57c8..1e5acbf90b20 100644 --- a/CORE/MAC/inc/sirApi.h +++ b/CORE/MAC/inc/sirApi.h @@ -4820,6 +4820,64 @@ struct sir_peer_info_resp { struct sir_peer_info info[0]; }; +/** + * struct sir_peer_info_ext_req - peer info request struct + * @peer_macaddr: MAC address + * @sessionId: vdev id + * @reset_after_request: fw reset statistics after query + * + * peer info request message's struct + */ +struct sir_peer_info_ext_req { + v_MACADDR_t peer_macaddr; + uint8_t sessionid; + uint8_t reset_after_request; +}; + +/** + * struct sir_peer_info_ext - peer info information struct + * (refer to station_info struct in Kernel) + * @peer_macaddr: MAC address + * @tx_packets: packets transmitted to this station + * @tx_bytes: bytes transmitted to this station + * @rx_packets: packets received from this station + * @rx_bytes: bytes received from this station + * @rx_retries: cumulative retry counts + * @tx_failed: number of failed transmissions + * @rssi: The signal strength + * @tx_rate: last used tx bitrate (kbps) + * @tx_rate_code: last tx rate code (last_tx_rate_code of wmi_peer_stats_info) + * @rx_rate: last used rx bitrate (kbps) + * @rx_rate_code: last rx rate code (last_rx_rate_code of wmi_peer_stats_info) + * + * a station's information + */ +struct sir_peer_info_ext { + tSirMacAddr peer_macaddr; + uint32_t tx_packets; + uint64_t tx_bytes; + uint32_t rx_packets; + uint64_t rx_bytes; + uint32_t tx_retries; + uint32_t tx_failed; + int32_t rssi; + uint32_t tx_rate; + uint32_t tx_rate_code; + uint32_t rx_rate; + uint32_t rx_rate_code; +}; + +/** + * struct sir_peer_info_ext_resp - all peers' information struct + * @count: peer's number + * @info: peer information + * + * all station's information + */ +struct sir_peer_info_ext_resp { + uint8_t count; + struct sir_peer_info_ext info[0]; +}; typedef struct sSirAddPeriodicTxPtrn { diff --git a/CORE/MAC/inc/wniApi.h b/CORE/MAC/inc/wniApi.h index cce52fc7f92f..09bc23d1c1bd 100644 --- a/CORE/MAC/inc/wniApi.h +++ b/CORE/MAC/inc/wniApi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -399,6 +399,7 @@ enum eWniMsgTypes eWNI_SME_EXT_CHANGE_CHANNEL_IND, eWNI_SME_LOST_LINK_INFO_IND, eWNI_SME_GET_PEER_INFO_IND, + eWNI_SME_GET_PEER_INFO_EXT_IND, eWNI_SME_ROAM_SCAN_OFFLOAD_REQ, eWNI_SME_SMPS_FORCE_MODE_IND, eWNI_SME_REGISTER_MGMT_FRAME_CB, diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h index c4cf7baf3c98..0fe84ba295ac 100644 --- a/CORE/MAC/src/include/sirParams.h +++ b/CORE/MAC/src/include/sirParams.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -792,6 +792,8 @@ typedef struct sSirMbMsgP2p #define SIR_HAL_SET_RX_BLOCKSIZE_CMDID (SIR_HAL_ITC_MSG_TYPES_BEGIN + 369) #define SIR_HAL_GET_CHAIN_RSSI_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 370) #define SIR_HAL_POWER_DEBUG_STATS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 371) +#define SIR_HAL_GET_PEER_INFO_EXT (SIR_HAL_ITC_MSG_TYPES_BEGIN + 372) +#define SIR_HAL_GET_PEER_INFO_EXT_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 373) #define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF) diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c index 82f4f9f8542e..698e823cbc8f 100644 --- a/CORE/SERVICES/WMA/wma.c +++ b/CORE/SERVICES/WMA/wma.c @@ -3236,6 +3236,299 @@ static int wma_stats_event_handler(void *handle, u_int8_t *cmd_param_info, return 0; } +/** + * wma_fill_peer_info() - fill SIR peer info from WMI peer info struct + * @wma: wma interface + * @stats_info: WMI peer info pointer + * @peer_info: SIR peer info pointer + * + * This function will fill SIR peer info from WMI peer info struct + * + * Return: None + */ +static void wma_fill_peer_info(tp_wma_handle wma, + wmi_peer_stats_info *stats_info, + struct sir_peer_info_ext *peer_info) +{ + peer_info->tx_packets = stats_info->tx_packets.low_32; + peer_info->tx_bytes = stats_info->tx_bytes.high_32; + peer_info->tx_bytes <<= 32; + peer_info->tx_bytes += stats_info->tx_bytes.low_32; + peer_info->rx_packets = stats_info->rx_packets.low_32; + peer_info->rx_bytes = stats_info->rx_bytes.high_32; + peer_info->rx_bytes <<= 32; + peer_info->rx_bytes += stats_info->rx_bytes.low_32; + peer_info->tx_retries = stats_info->tx_retries; + peer_info->tx_failed = stats_info->tx_failed; + peer_info->rssi = stats_info->peer_rssi; + peer_info->tx_rate = stats_info->last_tx_bitrate_kbps; + peer_info->tx_rate_code = stats_info->last_tx_rate_code; + peer_info->rx_rate = stats_info->last_rx_bitrate_kbps; + peer_info->rx_rate_code = stats_info->last_rx_rate_code; +} + +/** + * wma_peer_info_ext_rsp() - fill SIR peer info from WMI peer info struct + * @handle: wma interface + * @buf: wmi event buf pointer + * + * This function will send eWNI_SME_GET_PEER_INFO_EXT_IND to SME + * + * Return: 0 on success, error code otherwise + */ +static VOS_STATUS wma_peer_info_ext_rsp(tp_wma_handle wma, u_int8_t *buf) +{ + wmi_peer_stats_info_event_fixed_param *event; + wmi_peer_stats_info *stats_info = NULL; + struct sir_peer_info_ext_resp *resp; + struct sir_peer_info_ext *peer_info; + vos_msg_t sme_msg = {0}; + int i, j = 0; + VOS_STATUS vos_status; + + event = (wmi_peer_stats_info_event_fixed_param *)buf; + stats_info = (wmi_peer_stats_info *)(buf + + sizeof(wmi_peer_stats_info_event_fixed_param)); + + if (wma->get_one_peer_info) { + resp = vos_mem_malloc(sizeof(struct sir_peer_info_ext_resp) + + sizeof(resp->info[0])); + if (!resp) { + WMA_LOGE(FL("resp allocation failed.")); + return VOS_STATUS_E_NOMEM; + } + resp->count = 0; + peer_info = &resp->info[0]; + for (i = 0; i < event->num_peers; i++) { + WMI_MAC_ADDR_TO_CHAR_ARRAY(&stats_info->peer_macaddr, + peer_info->peer_macaddr); + + if (TRUE == vos_mem_compare( + peer_info->peer_macaddr, + wma->peer_macaddr.bytes, + VOS_MAC_ADDR_SIZE)) { + wma_fill_peer_info(wma, stats_info, peer_info); + resp->count++; + break; + } + + stats_info = stats_info + 1; + } + } else { + resp = vos_mem_malloc(sizeof(struct sir_peer_info_ext_resp) + + event->num_peers * sizeof(resp->info[0])); + if (!resp) { + WMA_LOGE(FL("resp allocation failed.")); + return VOS_STATUS_E_NOMEM; + } + resp->count = event->num_peers; + for (i = 0; i < event->num_peers; i++) { + peer_info = &resp->info[j]; + WMI_MAC_ADDR_TO_CHAR_ARRAY(&stats_info->peer_macaddr, + peer_info->peer_macaddr); + + if (TRUE == vos_mem_compare( + peer_info->peer_macaddr, + wma->myaddr, VOS_MAC_ADDR_SIZE)) { + resp->count = resp->count - 1; + continue; + } + wma_fill_peer_info(wma, stats_info, peer_info); + stats_info = stats_info + 1; + j++; + } + } + + sme_msg.type = eWNI_SME_GET_PEER_INFO_EXT_IND; + sme_msg.bodyptr = resp; + sme_msg.bodyval = 0; + + vos_status = vos_mq_post_message(VOS_MODULE_ID_SME, &sme_msg); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + WMA_LOGE("%s: Fail to post get peer info msg", __func__); + vos_mem_free(resp); + } + + return vos_status; +} + +/** + * dump_peer_stats_info() - dump wmi peer info struct + * @event: wmi peer info fixed param pointer + * @peer_stats: wmi peer stats info pointer + * + * This function will dump wmi peer info struct + * + * Return: None + */ +static void dump_peer_stats_info(wmi_peer_stats_info_event_fixed_param *event, + wmi_peer_stats_info *peer_stats) +{ + int i; + wmi_peer_stats_info *stats = peer_stats; + char mac[6]; + + WMA_LOGI("%s vdev_id %d, num_peers %d more_data %d", + __func__, event->vdev_id, + event->num_peers, event->more_data); + + for (i = 0; i < event->num_peers; i++) { + WMI_MAC_ADDR_TO_CHAR_ARRAY(&stats->peer_macaddr, mac); + WMA_LOGI("%s mac %pM", __func__, mac); + WMA_LOGI("%s tx_bytes %d %d tx_packets %d %d", + __func__, + stats->tx_bytes.low_32, + stats->tx_bytes.high_32, + stats->tx_packets.low_32, + stats->tx_packets.high_32); + WMA_LOGI("%s rx_bytes %d %d rx_packets %d %d", + __func__, + stats->rx_bytes.low_32, + stats->rx_bytes.high_32, + stats->rx_packets.low_32, + stats->rx_packets.high_32); + WMA_LOGI("%s tx_retries %d tx_failed %d", + __func__, stats->tx_retries, stats->tx_failed); + WMA_LOGI("%s tx_rate_code %x rx_rate_code %x", + __func__, + stats->last_tx_rate_code, + stats->last_rx_rate_code); + WMA_LOGI("%s tx_rate %x rx_rate %x", + __func__, + stats->last_tx_bitrate_kbps, + stats->last_rx_bitrate_kbps); + WMA_LOGI("%s peer_rssi %d", __func__, stats->peer_rssi); + stats++; + } +} + +/** + * wma_peer_info_event_handler() - Handler for WMI_PEER_STATS_INFO_EVENTID + * @handle: WMA global handle + * @cmd_param_info: Command event data + * @len: Length of @cmd_param_info + * + * This function will handle WMI_PEER_STATS_INFO_EVENTID + * + * Return: 0 on success, error code otherwise + */ +static int wma_peer_info_event_handler(void *handle, u_int8_t *cmd_param_info, + u_int32_t len) +{ + WMI_PEER_STATS_INFO_EVENTID_param_tlvs *param_buf; + wmi_peer_stats_info_event_fixed_param *event; + vos_msg_t vos_msg = {0}; + u_int32_t buf_size; + u_int8_t *buf; + + param_buf = + (WMI_PEER_STATS_INFO_EVENTID_param_tlvs *)cmd_param_info; + if (!param_buf) { + WMA_LOGA("%s: Invalid stats event", __func__); + return -EINVAL; + } + + WMA_LOGI("%s Recv WMI_PEER_STATS_INFO_EVENTID", __func__); + event = param_buf->fixed_param; + buf_size = sizeof(wmi_peer_stats_info_event_fixed_param) + + sizeof(wmi_peer_stats_info) * event->num_peers; + buf = vos_mem_malloc(buf_size); + if (!buf) { + WMA_LOGE("%s: Failed alloc memory for buf", __func__); + return -ENOMEM; + } + + vos_mem_zero(buf, buf_size); + vos_mem_copy(buf, param_buf->fixed_param, + sizeof(wmi_peer_stats_info_event_fixed_param)); + vos_mem_copy((buf + sizeof(wmi_peer_stats_info_event_fixed_param)), + param_buf->peer_stats_info, + sizeof(wmi_peer_stats_info) * event->num_peers); + WMA_LOGI("%s dump peer stats info", __func__); + dump_peer_stats_info(event, param_buf->peer_stats_info); + + vos_msg.type = WDA_GET_PEER_INFO_EXT_IND; + vos_msg.bodyptr = buf; + vos_msg.bodyval = 0; + + if (VOS_STATUS_SUCCESS != + vos_mq_post_message(VOS_MQ_ID_WDA, &vos_msg)) { + WMA_LOGP("%s: Failed to post WDA_GET_LINK_STATUS_RSP_IND msg", + __func__); + vos_mem_free(buf); + return eHAL_STATUS_FAILURE; + } + WMA_LOGD("posted WDA_GET_PEER_INFO_EXT_IND"); + + return 0; +} + +/** + * wma_get_peer_info_ext() - get peer info + * @handle: wma interface + * @prssi_req: get peer info request information + * + * This function will send WMI_REQUEST_PEER_STATS_INFO_CMDID to FW + * + * Return: 0 on success, otherwise error value + */ +static VOS_STATUS wma_get_peer_info_ext(WMA_HANDLE handle, + struct sir_peer_info_ext_req *peer_info_req) +{ + tp_wma_handle wma_handle = (tp_wma_handle)handle; + wmi_request_peer_stats_info_cmd_fixed_param *cmd; + wmi_buf_t wmi_buf; + uint32_t len; + uint8_t *buf_ptr; + + if (!wma_handle || !wma_handle->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue get rssi", + __func__); + return VOS_STATUS_E_INVAL; + } + + WMA_LOGI("%s send WMI_REQUEST_PEER_STATS_INFO_CMDID", __func__); + + len = sizeof(wmi_request_peer_stats_info_cmd_fixed_param); + wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + buf_ptr = (uint8_t *)wmi_buf_data(wmi_buf); + + cmd = (wmi_request_peer_stats_info_cmd_fixed_param *)buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_request_peer_stats_info_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_request_peer_stats_info_cmd_fixed_param)); + cmd->vdev_id = peer_info_req->sessionid; + cmd->request_type = WMI_REQUEST_ONE_PEER_STATS_INFO; + wma_handle->get_one_peer_info = TRUE; + WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_info_req->peer_macaddr.bytes, + &cmd->peer_macaddr); + cmd->reset_after_request = peer_info_req->reset_after_request; + + if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len, + WMI_REQUEST_PEER_STATS_INFO_CMDID)) { + WMA_LOGE("Failed to send host stats request to fw"); + wmi_buf_free(wmi_buf); + return VOS_STATUS_E_FAILURE; + } + + WMA_LOGI("%s vdev_id %d, mac %pM, req_type %x, reset %x", + __func__, + cmd->vdev_id, + peer_info_req->peer_macaddr.bytes, + cmd->request_type, + cmd->reset_after_request); + + vos_mem_copy(&(wma_handle->peer_macaddr), + &(peer_info_req->peer_macaddr), + VOS_MAC_ADDR_SIZE); + + return VOS_STATUS_SUCCESS; +} + static VOS_STATUS wma_send_link_speed(u_int32_t link_speed) { VOS_STATUS vos_status = VOS_STATUS_SUCCESS; @@ -8514,6 +8807,11 @@ VOS_STATUS WDA_open(v_VOID_t *vos_context, v_VOID_t *os_ctx, wmi_unified_register_event_handler(wma_handle->wmi_handle, WMI_UPDATE_STATS_EVENTID, wma_stats_event_handler); + /* register for peer info response event */ + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_PEER_STATS_INFO_EVENTID, + wma_peer_info_event_handler); + /* register for linkspeed response event */ wmi_unified_register_event_handler(wma_handle->wmi_handle, WMI_PEER_ESTIMATED_LINKSPEED_EVENTID, @@ -32461,6 +32759,10 @@ VOS_STATUS wma_mc_process_msg(v_VOID_t *vos_context, vos_msg_t *msg) wma_get_peer_info(wma_handle, msg->bodyptr); vos_mem_free(msg->bodyptr); break; + case WDA_GET_PEER_INFO_EXT: + wma_get_peer_info_ext(wma_handle, msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; case WDA_MODEM_POWER_STATE_IND: wma_notify_modem_power_state(wma_handle, (tSirModemPowerStateInd *)msg->bodyptr); @@ -32653,6 +32955,10 @@ VOS_STATUS wma_mc_process_msg(v_VOID_t *vos_context, vos_msg_t *msg) wma_link_status_rsp(wma_handle, msg->bodyptr); vos_mem_free(msg->bodyptr); break; + case WDA_GET_PEER_INFO_EXT_IND: + wma_peer_info_ext_rsp(wma_handle, msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; case WDA_GET_TEMPERATURE_REQ: wma_get_temperature(wma_handle); vos_mem_free(msg->bodyptr); @@ -35173,6 +35479,9 @@ static inline void wma_update_target_services(tp_wma_handle wh, #endif cfg->chain_mask_2g = wh->txrx_chainmask & 0xFF; cfg->chain_mask_5g = (wh->txrx_chainmask >> 16 ) & 0xFF; + if (WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, + WMI_SERVICE_PEER_STATS_INFO)) + cfg->get_peer_info_enabled = 1; } static inline void wma_update_target_ht_cap(tp_wma_handle wh, diff --git a/CORE/SERVICES/WMA/wma.h b/CORE/SERVICES/WMA/wma.h index d42030a99715..21eaeef546e9 100644 --- a/CORE/SERVICES/WMA/wma.h +++ b/CORE/SERVICES/WMA/wma.h @@ -938,6 +938,7 @@ typedef struct wma_handle { struct sir_allowed_action_frames allowed_action_frames; tSirAddonPsReq psSetting; bool sub_20_support; + bool get_one_peer_info; }t_wma_handle, *tp_wma_handle; struct wma_target_cap { diff --git a/CORE/SME/inc/smeInternal.h b/CORE/SME/inc/smeInternal.h index f39efe97949d..07871ee526c2 100644 --- a/CORE/SME/inc/smeInternal.h +++ b/CORE/SME/inc/smeInternal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -210,6 +210,10 @@ typedef struct tagSmeStruct void (*pget_peer_info_ind_cb) (struct sir_peer_info_resp *param, void *pcontext); void *pget_peer_info_cb_context; + /* get extended peer info callback */ + void (*pget_peer_info_ext_ind_cb) (struct sir_peer_info_ext_resp *param, + void *pcontext); + void *pget_peer_info_ext_cb_context; #ifdef FEATURE_WLAN_EXTSCAN void (*pExtScanIndCb) (void *, const tANI_U16, void *); #endif /* FEATURE_WLAN_EXTSCAN */ diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h index f4d05c3eb8b3..1faabd332c6a 100644 --- a/CORE/SME/inc/sme_Api.h +++ b/CORE/SME/inc/sme_Api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -3851,6 +3851,21 @@ eHalStatus sme_get_peer_info(tHalHandle hal, struct sir_peer_info_req req, void *pcontext)); /*---------------------------------------------------------------------------- + \fn sme_get_peer_info_ext + \brief This function sends msg to get info for remote peer + \param hHal - global structure + \param req - get peer info request pointer + \param context - event handle context + \param callbackfn - callback fn with response + \- return Success or failure +-----------------------------------------------------------------------------*/ +eHalStatus sme_get_peer_info_ext(tHalHandle hal, + struct sir_peer_info_ext_req *req, + void *context, + void (*callbackfn)(struct sir_peer_info_ext_resp *param, + void *pcontext)); + +/*---------------------------------------------------------------------------- \fn sme_ModifyAddIE \brief This function sends msg to updates the additional IE buffers in PE \param hHal - global structure diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c index 0d8e5e4759b2..e89fedf2dcd7 100644 --- a/CORE/SME/src/sme_common/sme_Api.c +++ b/CORE/SME/src/sme_common/sme_Api.c @@ -3222,6 +3222,12 @@ eHalStatus sme_ProcessMsg(tHalHandle hHal, vos_msg_t* pMsg) pMac->sme.pget_peer_info_cb_context); vos_mem_free(pMsg->bodyptr); break; + case eWNI_SME_GET_PEER_INFO_EXT_IND: + if (pMac->sme.pget_peer_info_ext_ind_cb) + pMac->sme.pget_peer_info_ext_ind_cb(pMsg->bodyptr, + pMac->sme.pget_peer_info_ext_cb_context); + vos_mem_free(pMsg->bodyptr); + break; case eWNI_SME_CSA_OFFLOAD_EVENT: if (pMsg->bodyptr) { @@ -12600,6 +12606,67 @@ eHalStatus sme_get_peer_info(tHalHandle hal, struct sir_peer_info_req req, return status; } +/** + * sme_get_peer_info_ext() - get info for remote peer + * @hal: hal interface + * @req: get peer info request pointer + * @context: event handle context + * @callbackfn: callback function pointer + * + * This function will send WDA_GET_PEER_INFO_EXT to WMA + * + * Return: 0 on success, otherwise error value + */ +eHalStatus sme_get_peer_info_ext(tHalHandle hal, + struct sir_peer_info_ext_req *req, + void *context, + void (*callbackfn)(struct sir_peer_info_ext_resp *param, + void *pcontext)) +{ + + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosstatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + vos_msg_t vosmessage; + + status = sme_AcquireGlobalLock(&mac->sme); + if (eHAL_STATUS_SUCCESS == status) { + if (NULL == callbackfn) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Indication Call back is NULL", + __func__); + sme_ReleaseGlobalLock(&mac->sme); + return eHAL_STATUS_FAILURE; + } + + mac->sme.pget_peer_info_ext_ind_cb = callbackfn; + mac->sme.pget_peer_info_ext_cb_context = context; + + /* serialize the req through MC thread */ + vosmessage.bodyptr = + vos_mem_malloc(sizeof(struct sir_peer_info_ext_req)); + if (NULL == vosmessage.bodyptr) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Memory allocation failed.", __func__); + sme_ReleaseGlobalLock(&mac->sme); + return eHAL_STATUS_E_MALLOC_FAILED; + } + vos_mem_copy(vosmessage.bodyptr, + req, + sizeof(struct sir_peer_info_ext_req)); + vosmessage.type = WDA_GET_PEER_INFO_EXT; + vosstatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosmessage); + if (!VOS_IS_STATUS_SUCCESS(vosstatus)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Post get rssi msg fail", __func__); + vos_mem_free(vosmessage.bodyptr); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&mac->sme); + } + return status; +} + /* --------------------------------------------------------------------------- \fn sme_IsPmcBmps \API to Check if PMC state is BMPS. diff --git a/CORE/SYS/legacy/src/utils/src/macTrace.c b/CORE/SYS/legacy/src/utils/src/macTrace.c index 034aee52c8b8..ea7bb57b530f 100644 --- a/CORE/SYS/legacy/src/utils/src/macTrace.c +++ b/CORE/SYS/legacy/src/utils/src/macTrace.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -577,6 +577,7 @@ tANI_U8* macTraceGetSmeMsgString(tANI_U16 smeMsg) CASE_RETURN_STRING(eWNI_SME_EXT_CHANGE_CHANNEL_IND); CASE_RETURN_STRING(eWNI_SME_LOST_LINK_INFO_IND); CASE_RETURN_STRING(eWNI_SME_GET_PEER_INFO_IND); + CASE_RETURN_STRING(eWNI_SME_GET_PEER_INFO_EXT_IND); CASE_RETURN_STRING(eWNI_SME_ROAM_SCAN_OFFLOAD_REQ); CASE_RETURN_STRING(eWNI_SME_SMPS_FORCE_MODE_IND); CASE_RETURN_STRING(eWNI_SME_REGISTER_MGMT_FRAME_CB); diff --git a/CORE/WDA/inc/wlan_qct_wda.h b/CORE/WDA/inc/wlan_qct_wda.h index 36d44255e9b9..5fa36324979a 100644 --- a/CORE/WDA/inc/wlan_qct_wda.h +++ b/CORE/WDA/inc/wlan_qct_wda.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -969,6 +969,8 @@ tSirRetStatus uMacPostCtrlMsg(void* pSirGlobal, tSirMbMsg* pMb); #define WDA_GET_LINK_SPEED SIR_HAL_GET_LINK_SPEED #define WDA_GET_PEER_INFO SIR_HAL_GET_PEER_INFO +#define WDA_GET_PEER_INFO_EXT SIR_HAL_GET_PEER_INFO_EXT +#define WDA_GET_PEER_INFO_EXT_IND SIR_HAL_GET_PEER_INFO_EXT_IND #define WDA_MODEM_POWER_STATE_IND SIR_HAL_MODEM_POWER_STATE_IND |
