wlan: Add SNR monitoring support
Add support to retrieve SNR from the received frame
and return it to the user space.
CRs-Fixed: 529156
Change-Id: Ic63c41e6bc2d9402dc42554e96637dd829a59a53
diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c
index b50c0d3..55b2c35 100644
--- a/CORE/HDD/src/wlan_hdd_wext.c
+++ b/CORE/HDD/src/wlan_hdd_wext.c
@@ -140,7 +140,8 @@
#define STATS_CONTEXT_MAGIC 0x53544154 //STAT
#define RSSI_CONTEXT_MAGIC 0x52535349 //RSSI
-#define POWER_CONTEXT_MAGIC 0x504F5752 // POWR
+#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
+#define SNR_CONTEXT_MAGIC 0x534E5200 //SNR
/* To Validate Channel against the Frequency and Vice-Versa */
static const hdd_freq_chan_map_t freq_chan_map[] = { {2412, 1}, {2417, 2},
@@ -613,6 +614,57 @@
complete(&pStatsContext->completion);
}
+static void hdd_GetSnrCB(tANI_S8 snr, tANI_U32 staId, void *pContext)
+{
+ struct statsContext *pStatsContext;
+ hdd_adapter_t *pAdapter;
+
+ if (ioctl_debug)
+ {
+ pr_info("%s: snr [%d] STA [%d] pContext [%p]\n",
+ __func__, (int)snr, (int)staId, pContext);
+ }
+
+ if (NULL == pContext)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Bad param, pContext [%p]",
+ __func__, 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
+ */
+
+ pStatsContext = pContext;
+ pAdapter = pStatsContext->pAdapter;
+ if ((NULL == pAdapter) || (SNR_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]",
+ __func__, pAdapter, pStatsContext->magic);
+ if (ioctl_debug)
+ {
+ pr_info("%s: Invalid context, pAdapter [%p] magic [%08x]\n",
+ __func__, 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 snr
+ */
+ pAdapter->snr = snr;
+
+ /* and notify the caller */
+ complete(&pStatsContext->completion);
+}
+
VOS_STATUS wlan_hdd_get_rssi(hdd_adapter_t *pAdapter, v_S7_t *rssi_value)
{
struct statsContext context;
@@ -680,6 +732,81 @@
return VOS_STATUS_SUCCESS;
}
+VOS_STATUS wlan_hdd_get_snr(hdd_adapter_t *pAdapter, v_S7_t *snr)
+{
+ struct statsContext context;
+ hdd_context_t *pHddCtx;
+ hdd_station_ctx_t *pHddStaCtx;
+ eHalStatus hstatus;
+ long lrc;
+ int valid;
+
+ if (NULL == pAdapter)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Invalid context, pAdapter", __func__);
+ return VOS_STATUS_E_FAULT;
+ }
+
+ pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+
+ valid = wlan_hdd_validate_context(pHddCtx);
+ if (0 != valid)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid"));
+ return VOS_STATUS_E_FAULT;
+ }
+
+ pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ if (NULL == pHddStaCtx)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD STA context is not valid"));
+ return VOS_STATUS_E_FAULT;
+ }
+
+ init_completion(&context.completion);
+ context.pAdapter = pAdapter;
+ context.magic = SNR_CONTEXT_MAGIC;
+
+ hstatus = sme_GetSnr(pHddCtx->hHal, hdd_GetSnrCB,
+ pHddStaCtx->conn_info.staId[ 0 ],
+ pHddStaCtx->conn_info.bssId,
+ &context);
+ if (eHAL_STATUS_SUCCESS != hstatus)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Unable to retrieve RSSI",
+ __func__);
+ /* we'll returned a cached value below */
+ }
+ 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 SNR ",
+ __func__, (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);
+ /* we'll now returned a cached value below */
+ }
+ }
+ *snr = pAdapter->snr;
+
+ return VOS_STATUS_SUCCESS;
+}
#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_CCX || defined(FEATURE_WLAN_LFR)
static void hdd_GetRoamRssiCB( v_S7_t rssi, tANI_U32 staId, void *pContext )