summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimanshu Agarwal <himanaga@qti.qualcomm.com>2016-05-23 19:25:56 +0530
committerGerrit - the friendly Code Review server <code-review@localhost>2016-05-25 02:30:41 -0700
commit63b70dcadb5fc5dbc641f8eb461f94812c219284 (patch)
tree39e9eb4de6a37706fd6c3c5427210607e73cc7e6
parenta31cfe19f921e9857b1ff882e3b17e4f1e88f7dc (diff)
qcacld-2.0: Add support to get per chain rssi stats
Add support to get per chain rssi from fw through the already existing WMI command WMI_REQUEST_STATS_CMDID and then store it in the station_info structure defined by cfg80211. Change-Id: Id50c96dd322b5ca4db34cf2df901730d8b103251 CRs-Fixed: 1005367
-rw-r--r--CORE/HDD/inc/wlan_hdd_main.h1
-rw-r--r--CORE/HDD/src/wlan_hdd_cfg80211.c57
-rw-r--r--CORE/HDD/src/wlan_hdd_wext.c7
-rw-r--r--CORE/MAC/inc/sirApi.h2
-rw-r--r--CORE/SERVICES/WMA/wma.c178
-rw-r--r--CORE/SME/inc/csrApi.h5
-rw-r--r--CORE/SME/inc/csrInternal.h2
-rw-r--r--CORE/SME/inc/sme_Api.h1
-rw-r--r--CORE/SME/src/csr/csrApiRoam.c14
9 files changed, 255 insertions, 12 deletions
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index 700b5caa2668..652136e6b918 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -399,6 +399,7 @@ typedef struct hdd_stats_s
tCsrGlobalClassCStatsInfo ClassC_stat;
tCsrGlobalClassDStatsInfo ClassD_stat;
tCsrPerStaStatsInfo perStaStats;
+ struct csr_per_chain_rssi_stats_info per_chain_rssi_stats;
hdd_tx_rx_stats_t hddTxRxStats;
#ifdef WLAN_FEATURE_11W
hdd_pmf_stats_t hddPmfStats;
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 740714b06bf4..f939dfb10156 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -129,6 +129,8 @@
#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
#define HDD_WAKE_LOCK_SCAN_DURATION (5 * 1000) /* in msec */
+#define WLAN_HDD_TGT_NOISE_FLOOR_DBM (-96)
+
/* For IBSS, enable obss, fromllb, overlapOBSS & overlapFromllb protection
check. The bit map is defined in:
@@ -20076,6 +20078,9 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy,
int status, mode = 0, maxHtIdx;
struct index_vht_data_rate_type *supported_vht_mcs_rate;
struct index_data_rate_type *supported_mcs_rate;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
+ bool rssi_stats_valid = FALSE;
+#endif
#ifdef WLAN_FEATURE_11AC
tANI_U32 vht_mcs_map;
@@ -20597,6 +20602,29 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy,
sinfo->txrate.mcs, sinfo->txrate.flags, sinfo->tx_packets,
sinfo->rx_packets);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
+ sinfo->signal_avg = WLAN_HDD_TGT_NOISE_FLOOR_DBM;
+ for (i = 0; i < NUM_CHAINS_MAX; i++) {
+ sinfo->chain_signal_avg[i] =
+ pAdapter->hdd_stats.per_chain_rssi_stats.rssi[i];
+ sinfo->chains |= 1 << i;
+ if (sinfo->chain_signal_avg[i] > sinfo->signal_avg &&
+ sinfo->chain_signal_avg[i] != 0)
+ sinfo->signal_avg = sinfo->chain_signal_avg[i];
+
+ hddLog(LOG1, FL("RSSI for chain %d, vdev_id %d is %d"),
+ i, pAdapter->sessionId, sinfo->chain_signal_avg[i]);
+
+ if (sinfo->chain_signal_avg[i] && !rssi_stats_valid)
+ rssi_stats_valid = TRUE;
+ }
+
+ if (rssi_stats_valid) {
+ sinfo->filled |= STATION_INFO_CHAIN_SIGNAL_AVG;
+ sinfo->filled |= STATION_INFO_SIGNAL_AVG;
+ }
+#endif
+
MTRACE(vos_trace(VOS_MODULE_ID_HDD,
TRACE_CODE_HDD_CFG80211_GET_STA,
pAdapter->sessionId, maxRate));
@@ -20604,6 +20632,34 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy,
return 0;
}
+static int __wlan_hdd_cfg80211_dump_station(struct wiphy *wiphy,
+ struct net_device *dev,
+ int idx, u8 *mac,
+ struct station_info *sinfo)
+{
+ hdd_context_t *hdd_ctx = (hdd_context_t *) wiphy_priv(wiphy);
+
+ hddLog(VOS_TRACE_LEVEL_DEBUG, "%s: idx %d", __func__, idx);
+ if (idx != 0)
+ return -ENOENT;
+ vos_mem_copy(mac, hdd_ctx->cfg_ini->intfMacAddr[0].bytes,
+ VOS_MAC_ADDR_SIZE);
+ return __wlan_hdd_cfg80211_get_station(wiphy, dev, mac, sinfo);
+}
+
+static int wlan_hdd_cfg80211_dump_station(struct wiphy *wiphy,
+ struct net_device *dev,
+ int idx, u8 *mac,
+ struct station_info *sinfo)
+{
+ int ret;
+
+ vos_ssr_protect(__func__);
+ ret = __wlan_hdd_cfg80211_dump_station(wiphy, dev, idx, mac, sinfo);
+ vos_ssr_unprotect(__func__);
+ return ret;
+}
+
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)) || defined(WITH_BACKPORTS)
static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy,
struct net_device *dev,
@@ -25487,6 +25543,7 @@ static struct cfg80211_ops wlan_hdd_cfg80211_ops =
.mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
.set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
.set_txq_params = wlan_hdd_set_txq_params,
+ .dump_station = wlan_hdd_cfg80211_dump_station,
.get_station = wlan_hdd_cfg80211_get_station,
.set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
.del_station = wlan_hdd_cfg80211_del_station,
diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c
index 7a6657834214..d6cf499036d6 100644
--- a/CORE/HDD/src/wlan_hdd_wext.c
+++ b/CORE/HDD/src/wlan_hdd_wext.c
@@ -3812,6 +3812,7 @@ static void hdd_get_station_statisticsCB(void *pStats, void *pContext)
struct statsContext *pStatsContext;
tCsrSummaryStatsInfo *pSummaryStats;
tCsrGlobalClassAStatsInfo *pClassAStats;
+ struct csr_per_chain_rssi_stats_info *per_chain_rssi_stats;
hdd_adapter_t *pAdapter;
if (ioctl_debug)
@@ -3836,6 +3837,8 @@ static void hdd_get_station_statisticsCB(void *pStats, void *pContext)
pSummaryStats = (tCsrSummaryStatsInfo *)pStats;
pClassAStats = (tCsrGlobalClassAStatsInfo *)( pSummaryStats + 1 );
+ per_chain_rssi_stats = (struct csr_per_chain_rssi_stats_info *)
+ (pClassAStats + 1);
pStatsContext = pContext;
pAdapter = pStatsContext->pAdapter;
if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
@@ -3861,6 +3864,7 @@ static void hdd_get_station_statisticsCB(void *pStats, void *pContext)
/* copy over the stats. do so as a struct copy */
pAdapter->hdd_stats.summary_stat = *pSummaryStats;
pAdapter->hdd_stats.ClassA_stat = *pClassAStats;
+ pAdapter->hdd_stats.per_chain_rssi_stats = *per_chain_rssi_stats;
/* notify the caller */
complete(&pStatsContext->completion);
@@ -3892,7 +3896,8 @@ VOS_STATUS wlan_hdd_get_station_stats(hdd_adapter_t *pAdapter)
hstatus = sme_GetStatistics(WLAN_HDD_GET_HAL_CTX(pAdapter),
eCSR_HDD,
SME_SUMMARY_STATS |
- SME_GLOBAL_CLASSA_STATS,
+ SME_GLOBAL_CLASSA_STATS |
+ SME_PER_CHAIN_RSSI_STATS,
hdd_get_station_statisticsCB,
0, // not periodic
FALSE, //non-cached results
diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h
index 8ceace5b5883..7874c9f9e5ba 100644
--- a/CORE/MAC/inc/sirApi.h
+++ b/CORE/MAC/inc/sirApi.h
@@ -100,6 +100,8 @@ typedef tANI_U8 tSirVersionString[SIR_VERSION_STRING_LEN];
#define WLAN_EXTSCAN_MAX_SIGNIFICANT_CHANGE_APS 64
#define WLAN_EXTSCAN_MAX_HOTLIST_SSIDS 8
+#define NUM_CHAINS_MAX 2
+
typedef enum
{
eSIR_EXTSCAN_INVALID,
diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c
index 2d9c68739b17..c9365daa47ee 100644
--- a/CORE/SERVICES/WMA/wma.c
+++ b/CORE/SERVICES/WMA/wma.c
@@ -138,11 +138,13 @@
#define FW_PDEV_STATS_SET 0x1
#define FW_VDEV_STATS_SET 0x2
#define FW_PEER_STATS_SET 0x4
-#define FW_STATS_SET 0x7
+#define FW_RSSI_PER_CHAIN_STATS_SET 0x8
+#define FW_STATS_SET 0xf
/*AR9888/AR6320 noise floor approx value
* similar to the mentioned the TLSHIM
*/
#define WMA_TGT_NOISE_FLOOR_DBM (-96)
+#define WMA_TGT_RSSI_INVALID 96
/*
* Make sure that link monitor and keep alive
@@ -2796,11 +2798,6 @@ static void wma_update_peer_stats(tp_wma_handle wma, wmi_peer_stats *peer_stats)
node->rate_flags, node->nss,
classa_stats->max_pwr);
}
-
- if (node->fw_stats_set & FW_STATS_SET) {
- WMA_LOGD("<--STATS RSP VDEV_ID:%d", vdev_id);
- wma_post_stats(wma, node);
- }
}
}
@@ -2822,6 +2819,109 @@ static void wma_post_link_status(tAniGetLinkStatus *pGetLinkStatus,
}
}
+/**
+ * wma_update_per_chain_rssi_stats() - to store per chain rssi stats for
+ * all vdevs for which the stats were requested into csr stats structure.
+ * @wma: wma handle
+ * @rssi_stats: rssi stats
+ * @rssi_per_chain_stats: buffer where rssi stats to be stored
+ *
+ * This function stores per chain rssi stats received from fw for all vdevs for
+ * which the stats were requested into a csr stats structure.
+ *
+ * Return: void
+ */
+static void wma_update_per_chain_rssi_stats(tp_wma_handle wma,
+ wmi_rssi_stats *rssi_stats,
+ struct csr_per_chain_rssi_stats_info *rssi_per_chain_stats)
+{
+ int i;
+ int8_t bcn_snr, dat_snr;
+
+ for (i = 0; i < NUM_CHAINS_MAX; i++) {
+ bcn_snr = rssi_stats->rssi_avg_beacon[i];
+ dat_snr = rssi_stats->rssi_avg_data[i];
+ WMA_LOGD("chain %d beacon snr %d data snr %d",
+ i, bcn_snr, dat_snr);
+ if ((dat_snr != WMA_TGT_INVALID_SNR_OLD &&
+ dat_snr != WMA_TGT_INVALID_SNR_NEW))
+ rssi_per_chain_stats->rssi[i] = dat_snr;
+ else if ((bcn_snr != WMA_TGT_INVALID_SNR_OLD &&
+ bcn_snr != WMA_TGT_INVALID_SNR_NEW))
+ rssi_per_chain_stats->rssi[i] = bcn_snr;
+ else
+ /*
+ * Firmware sends invalid snr till it sees
+ * Beacon/Data after connection since after
+ * vdev up fw resets the snr to invalid.
+ * In this duartion Host will return an invalid rssi
+ * value.
+ */
+ rssi_per_chain_stats->rssi[i] = WMA_TGT_RSSI_INVALID;
+
+ /*
+ * Get the absolute rssi value from the current rssi value the
+ * sinr value is hardcoded into 0 in the CORE stack
+ */
+ rssi_per_chain_stats->rssi[i] += WMA_TGT_NOISE_FLOOR_DBM;
+ WMI_MAC_ADDR_TO_CHAR_ARRAY(&(rssi_stats->peer_macaddr),
+ rssi_per_chain_stats->peer_mac_addr);
+ }
+}
+
+/**
+ * wma_update_rssi_stats() - to update rssi stats for all vdevs
+ * for which the stats were requested.
+ * @wma: wma handle
+ * @rssi_stats: rssi stats
+ *
+ * This function updates the rssi stats for all vdevs for which
+ * the stats were requested.
+ *
+ * Return: void
+ */
+static void wma_update_rssi_stats(tp_wma_handle wma,
+ wmi_rssi_stats *rssi_stats)
+{
+ tAniGetPEStatsRsp *stats_rsp_params;
+ struct csr_per_chain_rssi_stats_info *rssi_per_chain_stats = NULL;
+ struct wma_txrx_node *node;
+ uint8_t *stats_buf;
+ uint32_t temp_mask;
+ uint8_t vdev_id;
+
+ vdev_id = rssi_stats->vdev_id;
+ node = &wma->interfaces[vdev_id];
+ if (node->stats_rsp) {
+ node->fw_stats_set |= FW_RSSI_PER_CHAIN_STATS_SET;
+ WMA_LOGD("<-- FW RSSI PER CHAIN STATS received for vdevId:%d",
+ vdev_id);
+ stats_rsp_params = (tAniGetPEStatsRsp *) node->stats_rsp;
+ stats_buf = (tANI_U8 *) (stats_rsp_params + 1);
+ temp_mask = stats_rsp_params->statsMask;
+
+ if (temp_mask & (1 << eCsrSummaryStats))
+ stats_buf += sizeof(tCsrSummaryStatsInfo);
+ if (temp_mask & (1 << eCsrGlobalClassAStats))
+ stats_buf += sizeof(tCsrGlobalClassAStatsInfo);
+ if (temp_mask & (1 << eCsrGlobalClassBStats))
+ stats_buf += sizeof(tCsrGlobalClassBStatsInfo);
+ if (temp_mask & (1 << eCsrGlobalClassCStats))
+ stats_buf += sizeof(tCsrGlobalClassCStatsInfo);
+ if (temp_mask & (1 << eCsrGlobalClassDStats))
+ stats_buf += sizeof(tCsrGlobalClassDStatsInfo);
+ if (temp_mask & (1 << eCsrPerStaStats))
+ stats_buf += sizeof(tCsrPerStaStatsInfo);
+
+ if (temp_mask & (1 << csr_per_chain_rssi_stats)) {
+ rssi_per_chain_stats =
+ (struct csr_per_chain_rssi_stats_info *)stats_buf;
+ wma_update_per_chain_rssi_stats(wma, rssi_stats,
+ rssi_per_chain_stats);
+ }
+ }
+}
+
#ifdef WLAN_FEATURE_MEMDUMP
/**
* wma_fw_mem_dump_rsp() - send fw mem dump response to SME
@@ -3079,9 +3179,11 @@ static int wma_stats_event_handler(void *handle, u_int8_t *cmd_param_info,
{
WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
wmi_stats_event_fixed_param *event;
+ wmi_per_chain_rssi_stats *rssi_event;
vos_msg_t vos_msg = {0};
- u_int32_t buf_size;
- u_int8_t *buf;
+ u_int32_t buf_size, buf_data_size;
+ u_int8_t *buf, *temp;
+ bool rssi_stats_present = FALSE;
param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *)cmd_param_info;
if (!param_buf) {
@@ -3094,6 +3196,19 @@ static int wma_stats_event_handler(void *handle, u_int8_t *cmd_param_info,
(event->num_vdev_stats * sizeof(wmi_vdev_stats)) +
(event->num_peer_stats * sizeof(wmi_peer_stats)) +
(event->num_mib_stats * sizeof(wmi_mib_stats));
+ buf_data_size = buf_size - sizeof(*event);
+ if (param_buf->data) {
+ rssi_event = (wmi_per_chain_rssi_stats *)
+ ((uint8_t *)param_buf->data + buf_data_size);
+ if (((rssi_event->tlv_header & 0xFFFF0000) >> 16) ==
+ WMITLV_TAG_STRUC_wmi_per_chain_rssi_stats) {
+ buf_size += sizeof(*rssi_event) +
+ (rssi_event->num_per_chain_rssi_stats *
+ sizeof(wmi_rssi_stats));
+ rssi_stats_present = TRUE;
+ }
+ }
+
buf = vos_mem_malloc(buf_size);
if (!buf) {
WMA_LOGE("%s: Failed alloc memory for buf", __func__);
@@ -3101,8 +3216,18 @@ static int wma_stats_event_handler(void *handle, u_int8_t *cmd_param_info,
}
vos_mem_zero(buf, buf_size);
vos_mem_copy(buf, event, sizeof(*event));
- vos_mem_copy(buf + sizeof(*event), (u_int8_t *)param_buf->data,
- (buf_size - sizeof(*event)));
+ temp = buf + sizeof(*event);
+ vos_mem_copy(temp, (u_int8_t *)param_buf->data,
+ buf_data_size);
+ temp += buf_data_size;
+ if (rssi_stats_present) {
+ vos_mem_copy(temp, (u_int8_t *)param_buf->chain_stats,
+ sizeof(*param_buf->chain_stats));
+ temp += sizeof(*param_buf->chain_stats);
+ vos_mem_copy(temp, (u_int8_t *)param_buf->rssi_stats,
+ (rssi_event->num_per_chain_rssi_stats *
+ sizeof(wmi_rssi_stats)));
+ }
vos_msg.type = WDA_FW_STATS_IND;
vos_msg.bodyptr = buf;
vos_msg.bodyval = 0;
@@ -3265,6 +3390,9 @@ static void wma_fw_stats_ind(tp_wma_handle wma, u_int8_t *buf)
wmi_vdev_stats *vdev_stats;
wmi_peer_stats *peer_stats;
wmi_mib_stats *mib_stats;
+ wmi_rssi_stats *rssi_stats;
+ wmi_per_chain_rssi_stats *rssi_event;
+ struct wma_txrx_node *node;
u_int8_t i, *temp;
temp = buf + sizeof(*event);
@@ -3312,6 +3440,30 @@ static void wma_fw_stats_ind(tp_wma_handle wma, u_int8_t *buf)
temp += sizeof(wmi_mib_stats);
}
}
+
+ rssi_event = (wmi_per_chain_rssi_stats *)temp;
+ if ((rssi_event->tlv_header & 0xFFFF0000) >> 16 ==
+ WMITLV_TAG_STRUC_wmi_per_chain_rssi_stats) {
+ WMA_LOGD("%s: num_rssi_stats %u", __func__,
+ rssi_event->num_per_chain_rssi_stats);
+ if (rssi_event->num_per_chain_rssi_stats > 0) {
+ temp += sizeof(*rssi_event);
+ for (i = 0; i < rssi_event->num_per_chain_rssi_stats;
+ i++) {
+ rssi_stats = (wmi_rssi_stats *)temp;
+ wma_update_rssi_stats(wma, rssi_stats);
+ temp += sizeof(wmi_rssi_stats);
+ }
+ }
+ }
+
+ for (i = 0; i < wma->max_bssid; i++) {
+ node = &wma->interfaces[i];
+ if (node->fw_stats_set & FW_PEER_STATS_SET) {
+ WMA_LOGD("<--STATS RSP VDEV_ID:%d", i);
+ wma_post_stats(wma, node);
+ }
+ }
}
#ifdef FEATURE_WLAN_EXTSCAN
@@ -23102,6 +23254,10 @@ tAniGetPEStatsRsp * wma_get_stats_rsp_buf(tAniGetPEStatsReq *get_stats_param)
case eCsrPerStaStats:
len += sizeof(tCsrPerStaStatsInfo);
break;
+ case csr_per_chain_rssi_stats:
+ len +=
+ sizeof(struct csr_per_chain_rssi_stats_info);
+ break;
}
}
@@ -23177,7 +23333,7 @@ static void wma_get_stats_req(WMA_HANDLE handle,
WMITLV_TAG_STRUC_wmi_request_stats_cmd_fixed_param,
WMITLV_GET_STRUCT_TLVLEN(wmi_request_stats_cmd_fixed_param));
cmd->stats_id = WMI_REQUEST_PEER_STAT|WMI_REQUEST_PDEV_STAT|
- WMI_REQUEST_VDEV_STAT;
+ WMI_REQUEST_VDEV_STAT|WMI_REQUEST_RSSI_PER_CHAIN_STAT;
cmd->vdev_id = get_stats_param->sessionId;
WMI_CHAR_ARRAY_TO_MAC_ADDR(node->bssid, &cmd->peer_macaddr);
WMA_LOGD("STATS REQ VDEV_ID:%d-->", cmd->vdev_id);
diff --git a/CORE/SME/inc/csrApi.h b/CORE/SME/inc/csrApi.h
index d73c53aedaf2..53c403aa32b7 100644
--- a/CORE/SME/inc/csrApi.h
+++ b/CORE/SME/inc/csrApi.h
@@ -1617,6 +1617,11 @@ typedef struct tagCsrPerStaStatsInfo
tANI_U32 tx_mpdu_in_ampdu_cnt;
} tCsrPerStaStatsInfo;
+struct csr_per_chain_rssi_stats_info {
+ int8 rssi[NUM_CHAINS_MAX];
+ tSirMacAddr peer_mac_addr;
+};
+
typedef struct tagCsrRoamSetKey
{
eCsrEncryptionType encType;
diff --git a/CORE/SME/inc/csrInternal.h b/CORE/SME/inc/csrInternal.h
index 8d2ae8df0342..1cb1d7b8914c 100644
--- a/CORE/SME/inc/csrInternal.h
+++ b/CORE/SME/inc/csrInternal.h
@@ -270,6 +270,7 @@ typedef enum
eCsrGlobalClassCStats,
eCsrGlobalClassDStats,
eCsrPerStaStats,
+ csr_per_chain_rssi_stats,
eCsrMaxStats
}eCsrRoamStatsClassTypes;
@@ -1091,6 +1092,7 @@ typedef struct tagCsrRoamStruct
tCsrGlobalClassCStatsInfo classCStatsInfo;
tCsrGlobalClassDStatsInfo classDStatsInfo;
tCsrPerStaStatsInfo perStaStatsInfo[CSR_MAX_STA];
+ struct csr_per_chain_rssi_stats_info per_chain_rssi_stats;
tDblLinkList statsClientReqList;
tDblLinkList peStatsReqList;
tCsrTlStatsReqInfo tlStatsReqInfo;
diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h
index 55d6f83aaafd..06250009356b 100644
--- a/CORE/SME/inc/sme_Api.h
+++ b/CORE/SME/inc/sme_Api.h
@@ -74,6 +74,7 @@
#define SME_GLOBAL_CLASSC_STATS 8
#define SME_GLOBAL_CLASSD_STATS 16
#define SME_PER_STA_STATS 32
+#define SME_PER_CHAIN_RSSI_STATS 64
#define SME_INVALID_COUNTRY_CODE "XX"
diff --git a/CORE/SME/src/csr/csrApiRoam.c b/CORE/SME/src/csr/csrApiRoam.c
index 83d46a8151cf..0d313b7df2ed 100644
--- a/CORE/SME/src/csr/csrApiRoam.c
+++ b/CORE/SME/src/csr/csrApiRoam.c
@@ -16333,6 +16333,14 @@ void csrRoamStatsRspProcessor(tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg)
pStats += sizeof(tCsrPerStaStatsInfo);
length -= sizeof(tCsrPerStaStatsInfo);
break;
+ case csr_per_chain_rssi_stats:
+ smsLog(pMac, LOG2,
+ FL("csrRoamStatsRspProcessor:Per Chain RSSI stats"));
+ vos_mem_copy((tANI_U8 *)&pMac->roam.per_chain_rssi_stats,
+ pStats, sizeof(struct csr_per_chain_rssi_stats_info));
+ pStats += sizeof(struct csr_per_chain_rssi_stats_info);
+ length -= sizeof(struct csr_per_chain_rssi_stats_info);
+ break;
default:
smsLog( pMac, LOGW, FL("csrRoamStatsRspProcessor:unknown stats type"));
break;
@@ -18266,6 +18274,12 @@ void csrRoamReportStatistics(tpAniSirGlobal pMac, tANI_U32 statsMask,
sizeof(tCsrPerStaStatsInfo));
pStats += sizeof(tCsrPerStaStatsInfo);
break;
+ case csr_per_chain_rssi_stats:
+ smsLog(pMac, LOG2, FL("Per Chain RSSI stats"));
+ vos_mem_copy(pStats, (tANI_U8 *)&pMac->roam.per_chain_rssi_stats,
+ sizeof(struct csr_per_chain_rssi_stats_info));
+ pStats += sizeof(struct csr_per_chain_rssi_stats_info);
+ break;
default:
smsLog( pMac, LOGE, FL("Unknown stats type and counter %d"), counter);
break;