Wlan: Changes for tx packet statistics that fixes google bug
Change-Id: Ie96030089382c06c691de415a37665a2473f8b3a
CR-Fixed: 6968549
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 9dea1c4..e024861 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -5237,7 +5237,7 @@
wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
sinfo->filled |= STATION_INFO_SIGNAL;
- wlan_hdd_get_classAstats(pAdapter);
+ wlan_hdd_get_station_stats(pAdapter);
rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
//convert to the UI units of 100kbps
@@ -5433,8 +5433,31 @@
}
sinfo->filled |= STATION_INFO_TX_BITRATE;
- EXIT();
- return 0;
+ sinfo->tx_packets =
+ pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
+ pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
+ pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
+ pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
+
+ sinfo->tx_retries =
+ pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
+ pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
+ pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
+ pAdapter->hdd_stats.summary_stat.retry_cnt[3];
+
+ sinfo->tx_failed =
+ pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
+ pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
+ pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
+ pAdapter->hdd_stats.summary_stat.fail_cnt[3];
+
+ sinfo->filled |=
+ STATION_INFO_TX_PACKETS |
+ STATION_INFO_TX_RETRIES |
+ STATION_INFO_TX_FAILED;
+
+ EXIT();
+ return 0;
}
static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c
index ae645e8..88112ed 100644
--- a/CORE/HDD/src/wlan_hdd_wext.c
+++ b/CORE/HDD/src/wlan_hdd_wext.c
@@ -1986,6 +1986,123 @@
return VOS_STATUS_SUCCESS;
}
+static void hdd_get_station_statisticsCB(void *pStats, void *pContext)
+{
+ struct statsContext *pStatsContext;
+ tCsrSummaryStatsInfo *pSummaryStats;
+ tCsrGlobalClassAStatsInfo *pClassAStats;
+ hdd_adapter_t *pAdapter;
+
+ if (ioctl_debug)
+ {
+ pr_info("%s: pStats [%p] pContext [%p]\n",
+ __FUNCTION__, pStats, pContext);
+ }
+
+ if ((NULL == pStats) || (NULL == pContext))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Bad param, pStats [%p] pContext [%p]",
+ __FUNCTION__, pStats, pContext);
+ return;
+ }
+
+ /* 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'll assume the timeout hasn't
+ occurred, but we'll verify that right before we save our work */
+
+ pSummaryStats = (tCsrSummaryStatsInfo *)pStats;
+ pClassAStats = (tCsrGlobalClassAStatsInfo *)( pSummaryStats + 1 );
+ pStatsContext = pContext;
+ pAdapter = pStatsContext->pAdapter;
+ if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
+ {
+ /* the caller presumably timed out so there is nothing we can do */
+ hddLog(VOS_TRACE_LEVEL_WARN,
+ "%s: Invalid context, pAdapter [%p] magic [%08x]",
+ __FUNCTION__, pAdapter, pStatsContext->magic);
+ if (ioctl_debug)
+ {
+ pr_info("%s: Invalid context, pAdapter [%p] magic [%08x]\n",
+ __FUNCTION__, pAdapter, pStatsContext->magic);
+ }
+ return;
+ }
+
+ /* the race is on. caller could have timed out immediately after
+ we verified the magic, but if so, caller will wait a short time
+ for us to copy over the stats. do so as a struct copy */
+ pAdapter->hdd_stats.summary_stat = *pSummaryStats;
+ pAdapter->hdd_stats.ClassA_stat = *pClassAStats;
+
+ /* and notify the caller */
+ complete(&pStatsContext->completion);
+}
+
+VOS_STATUS wlan_hdd_get_station_stats(hdd_adapter_t *pAdapter)
+{
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ eHalStatus hstatus;
+ long lrc;
+ struct statsContext context;
+
+ if (NULL == pAdapter)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Padapter is NULL", __func__);
+ return VOS_STATUS_SUCCESS;
+ }
+
+ /* we are connected
+ prepare our callback context */
+ init_completion(&context.completion);
+ context.pAdapter = pAdapter;
+ context.magic = STATS_CONTEXT_MAGIC;
+
+ /* query only for Summary & Class A statistics */
+ hstatus = sme_GetStatistics(WLAN_HDD_GET_HAL_CTX(pAdapter),
+ eCSR_HDD,
+ SME_SUMMARY_STATS |
+ SME_GLOBAL_CLASSA_STATS,
+ hdd_get_station_statisticsCB,
+ 0, // not periodic
+ FALSE, //non-cached results
+ pHddStaCtx->conn_info.staId[0],
+ &context);
+ if (eHAL_STATUS_SUCCESS != hstatus)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Unable to retrieve statistics",
+ __FUNCTION__);
+ /* we'll return with cached values */
+ }
+ else
+ {
+ /* request was sent -- wait for the response */
+ lrc = wait_for_completion_interruptible_timeout(&context.completion,
+ msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
+ /* either we have a response or we timed out
+ either way, first invalidate our magic */
+ context.magic = 0;
+ if (lrc <= 0)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: SME %s while retrieving statistics",
+ __FUNCTION__, (0 == lrc) ? "timeout" : "interrupt");
+ /* 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 hasn't yet set the completion
+ variable. Since the completion variable is on our
+ stack, we'll delay just a bit to make sure the data is
+ still valid if that is the case */
+ msleep(50);
+ }
+ }
+ return VOS_STATUS_SUCCESS;
+}
+
+
/*
* Support for the LINKSPEED private command
* Per the WiFi framework the response must be of the form