wlan: Add support to get SAP client RSSI

Add support to get the RSSI value of the connected SAP client
as part of get station stats cfg80211 command.

Change-Id: I86ff918f9dbe592af248bd6ee497315191b39e31
CRs-Fixed: 2115615
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 539b20d..8803c2e 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -16768,8 +16768,25 @@
 }
 
 /**
+ * wlan_hdd_sap_get_sta_rssi() - get RSSI of the SAP client
+ * @adapter: sap adapter pointer
+ * @staid: station id of the client
+ * @rssi: rssi value to fill
+ *
+ * Return: None
+ */
+static void
+wlan_hdd_sap_get_sta_rssi(hdd_adapter_t *adapter, uint8_t staid, s8 *rssi)
+{
+	v_CONTEXT_t pVosContext =  (WLAN_HDD_GET_CTX(adapter))->pvosContext;
+
+	WLANTL_GetSAPStaRSSi(pVosContext, staid, rssi);
+}
+
+/**
  * wlan_hdd_get_sap_stats() - get aggregate SAP stats
  * @adapter: sap adapter to get stats for
+ * @mac: mac address of the station
  * @info: kernel station_info struct to populate
  *
  * Fetch the vdev-level aggregate stats for the given SAP adapter. This is to
@@ -16779,9 +16796,18 @@
  * Return: errno
  */
 static int
-wlan_hdd_get_sap_stats(hdd_adapter_t *adapter, struct station_info *info)
+wlan_hdd_get_sap_stats(hdd_adapter_t *adapter,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0))
+		       const u8* mac,
+#else
+		       u8* mac,
+#endif
+		       struct station_info *info)
 {
+	v_MACADDR_t *peerMacAddr;
+	uint8_t staid;
 	VOS_STATUS status;
+	bool bc_mac_addr;
 
 	status = wlan_hdd_get_station_stats(adapter);
 	if (!VOS_IS_STATUS_SUCCESS(status)) {
@@ -16790,6 +16816,16 @@
 		return 0;
 	}
 
+	peerMacAddr = (v_MACADDR_t *)mac;
+	bc_mac_addr = vos_is_macaddr_broadcast(peerMacAddr);
+	staid = hdd_sta_id_find_from_mac_addr(adapter, peerMacAddr);
+	hddLog(VOS_TRACE_LEVEL_INFO, "Get SAP stats for sta id:%d", staid);
+
+	if (staid < WLAN_MAX_STA_COUNT && !bc_mac_addr) {
+		wlan_hdd_sap_get_sta_rssi(adapter, staid, &info->signal);
+		info->filled |= STATION_INFO_SIGNAL;
+	}
+
 	wlan_hdd_fill_summary_stats(&adapter->hdd_stats.summary_stat, info);
 
 	return 0;
@@ -16842,7 +16878,7 @@
     }
 
     if (pAdapter->device_mode == WLAN_HDD_SOFTAP)
-        return wlan_hdd_get_sap_stats(pAdapter, sinfo);
+        return wlan_hdd_get_sap_stats(pAdapter, mac, sinfo);
 
     if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
             (0 == ssidlen))
diff --git a/CORE/TL/inc/wlan_qct_tl.h b/CORE/TL/inc/wlan_qct_tl.h
index 45f3b9d..353a28a 100644
--- a/CORE/TL/inc/wlan_qct_tl.h
+++ b/CORE/TL/inc/wlan_qct_tl.h
@@ -3427,4 +3427,14 @@
  * Return: void
  */
 void WLANTL_SetARPFWDatapath(void * pvosGCtx, bool flag);
+
+/**
+ * WLANTL_GetSAPStaRSSi() - get RSSI for the SAP client
+ * @pvosGCtx: global vos context
+ * @ucSTAId: station id to get rssi for
+ * @rssi: pointer to fill station rssi value
+ *
+ * Return: void
+ */
+void WLANTL_GetSAPStaRSSi(void * pvosGCtx, uint8_t ucSTAId, s8 *rssi);
 #endif /* #ifndef WLAN_QCT_WLANTL_H */
diff --git a/CORE/TL/src/wlan_qct_tl.c b/CORE/TL/src/wlan_qct_tl.c
index d67aa30..475d42a 100755
--- a/CORE/TL/src/wlan_qct_tl.c
+++ b/CORE/TL/src/wlan_qct_tl.c
@@ -6123,6 +6123,42 @@
    }
 }
 
+/**
+ * WLANTL_SampleRxRSSI() - Collect RX rssi samples
+ * @pTLCb: TL context pointer
+ * @pBDHeader: RX Meta data pointer
+ * @sta_id: Station ID
+ *
+ * This function records the last twenty RX RSSI samples
+ *
+ * Return: void
+ */
+static void WLANTL_SampleRxRSSI(WLANTL_CbType* pTLCb, void * pBDHeader,
+                                uint8_t sta_id)
+{
+   WLANTL_STAClientType *pClientSTA = pTLCb->atlSTAClients[sta_id];
+   uint8_t count = pClientSTA->rssi_sample_cnt;
+   uint8_t old_idx = pClientSTA->rssi_stale_idx;
+   s8 curr_RSSI, curr_RSSI0, curr_RSSI1;
+
+   curr_RSSI0 = WLANTL_GETRSSI0(pBDHeader);
+   curr_RSSI1 = WLANTL_GETRSSI1(pBDHeader);
+
+   curr_RSSI  = (curr_RSSI0 > curr_RSSI1) ? curr_RSSI0 : curr_RSSI1;
+
+   if (count >= WLANTL_RSSI_SAMPLE_CNT) {
+      pClientSTA->rssi_sample_sum -= pClientSTA->rssi_sample[old_idx];
+      pClientSTA->rssi_sample[old_idx] = curr_RSSI;
+      pClientSTA->rssi_sample_sum += pClientSTA->rssi_sample[old_idx];
+      old_idx >= WLANTL_RSSI_SAMPLE_CNT ? old_idx = 0 : old_idx++;
+      pClientSTA->rssi_stale_idx = old_idx;
+   } else {
+      pClientSTA->rssi_sample[count] = curr_RSSI;
+      pClientSTA->rssi_sample_sum += pClientSTA->rssi_sample[count];
+      pClientSTA->rssi_sample_cnt++;
+   }
+}
+
 /*==========================================================================
 
   FUNCTION    WLANTL_RxFrames
@@ -6361,6 +6397,9 @@
             pClientSTA->interfaceStats.mgmtRx++;
         }
 #endif
+
+        WLANTL_SampleRxRSSI(pTLCb, pvBDHeader, ucSTAId);
+
       }
 
       pTLCb->tlMgmtFrmClient.pfnTlMgmtFrmRx( pvosGCtx, vosTempBuff); 
@@ -6671,6 +6710,8 @@
                            FL("Failed to Read SNR")));
         }
 
+        WLANTL_SampleRxRSSI(pTLCb, pvBDHeader, ucSTAId);
+
         pfnSTAFsm( pvosGCtx, ucSTAId, &vosTempBuff, bForwardIAPPwithLLC);
       }
       else
@@ -14378,6 +14419,24 @@
 
 }
 
+void WLANTL_GetSAPStaRSSi(void *pvosGCtx, uint8_t ucSTAId, s8 *rssi)
+{
+   WLANTL_CbType*  pTLCb = NULL;
+   uint8_t count;
+
+   pTLCb = VOS_GET_TL_CB(pvosGCtx);
+   if (NULL == pTLCb) {
+      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
+             "%s: Invalid TL pointer from pvosGCtx", __func__));
+      return;
+   }
+
+   count = pTLCb->atlSTAClients[ucSTAId]->rssi_sample_cnt;
+   count < WLANTL_RSSI_SAMPLE_CNT ? count++ : count;
+
+   *rssi = pTLCb->atlSTAClients[ucSTAId]->rssi_sample_sum / count;
+}
+
 #ifdef WLAN_FEATURE_RMC
 VOS_STATUS WLANTL_RmcInit
 (
diff --git a/CORE/TL/src/wlan_qct_tli.h b/CORE/TL/src/wlan_qct_tli.h
index cb6414a..7780655 100644
--- a/CORE/TL/src/wlan_qct_tli.h
+++ b/CORE/TL/src/wlan_qct_tli.h
@@ -257,6 +257,9 @@
    (WLANTL_BT_AMP_TYPE_LS_REQ == usType) || (WLANTL_BT_AMP_TYPE_LS_REP == usType))
 
 #define WLANTL_CACHE_TRACE_WATERMARK 100
+
+#define WLANTL_RSSI_SAMPLE_CNT 20
+
 /*---------------------------------------------------------------------------
   TL signals for TX thread
 ---------------------------------------------------------------------------*/
@@ -746,6 +749,11 @@
   uint16_t queue;
   uint16_t trate;
 
+  /* RSSI sample avg */
+  s8 rssi_sample[WLANTL_RSSI_SAMPLE_CNT];
+  s16 rssi_sample_sum;
+  uint8_t rssi_sample_cnt;
+  uint8_t rssi_stale_idx;
 }WLANTL_STAClientType;
 
 /*---------------------------------------------------------------------------