summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CORE/HDD/inc/wlan_hdd_cfg.h19
-rw-r--r--CORE/HDD/inc/wlan_hdd_main.h51
-rw-r--r--CORE/HDD/inc/wlan_hdd_tgt_cfg.h3
-rw-r--r--CORE/HDD/src/wlan_hdd_cfg.c7
-rw-r--r--CORE/HDD/src/wlan_hdd_cfg80211.c408
-rw-r--r--CORE/HDD/src/wlan_hdd_main.c17
-rw-r--r--CORE/MAC/inc/sirApi.h58
-rw-r--r--CORE/MAC/inc/wniApi.h3
-rw-r--r--CORE/MAC/src/include/sirParams.h4
-rw-r--r--CORE/SERVICES/WMA/wma.c309
-rw-r--r--CORE/SERVICES/WMA/wma.h1
-rw-r--r--CORE/SME/inc/smeInternal.h6
-rw-r--r--CORE/SME/inc/sme_Api.h17
-rw-r--r--CORE/SME/src/sme_common/sme_Api.c67
-rw-r--r--CORE/SYS/legacy/src/utils/src/macTrace.c3
-rw-r--r--CORE/WDA/inc/wlan_qct_wda.h4
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