Wlan: Changes for tx packet statistics that fixes google bug

Change-Id: Ie96030089382c06c691de415a37665a2473f8b3a
CR-Fixed: 6968549
diff --git a/CORE/HDD/inc/wlan_hdd_wext.h b/CORE/HDD/inc/wlan_hdd_wext.h
index b1ea49a..579cefe 100644
--- a/CORE/HDD/inc/wlan_hdd_wext.h
+++ b/CORE/HDD/inc/wlan_hdd_wext.h
@@ -386,6 +386,8 @@
 
 VOS_STATUS wlan_hdd_get_classAstats(hdd_adapter_t *pAdapter);
 
+VOS_STATUS wlan_hdd_get_station_stats(hdd_adapter_t *pAdapter);
+
 VOS_STATUS wlan_hdd_get_rssi(hdd_adapter_t *pAdapter, v_S7_t *rssi_value);
 
 #endif // __WEXT_IW_H__
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