Browse Source

qcacmn: Send per chain rssi to upper layer

Add support to send the per chain rssi to upper layer
for each beacon and probe responses.

Change-Id: Ife6cb9e8e65591baf485c54a985f84d842400321
CRs-Fixed: 2177638
gaurank kathpalia 7 years ago
parent
commit
26f9833fb8

+ 33 - 1
os_if/linux/scan/inc/wlan_cfg80211_scan.h

@@ -32,7 +32,7 @@
 #include <qdf_list.h>
 #include <qdf_types.h>
 #include <wlan_scan_ucfg_api.h>
-
+#include <wlan_mgmt_txrx_utils_api.h>
 
 /* Max number of scans allowed from userspace */
 #define WLAN_MAX_SCAN_COUNT 8
@@ -126,6 +126,25 @@ struct scan_params {
 	struct element_info default_ie;
 };
 
+/**
+ * struct wlan_cfg80211_inform_bss - BSS inform data
+ * @chan: channel the frame was received on
+ * @mgmt: beacon/probe resp frame
+ * @frame_len: frame length
+ * @rssi: signal strength in mBm (100*dBm)
+ * @boottime_ns: timestamp (CLOCK_BOOTTIME) when the information was received.
+ * @per_chain_snr: per chain snr received
+ */
+struct wlan_cfg80211_inform_bss {
+	struct ieee80211_channel *chan;
+	struct ieee80211_mgmt *mgmt;
+	size_t frame_len;
+	int rssi;
+	uint64_t boottime_ns;
+	uint8_t per_chain_snr[WLAN_MGMT_TXRX_HOST_MAX_ANTENNA];
+};
+
+
 #ifdef FEATURE_WLAN_SCAN_PNO
 /**
  * wlan_cfg80211_sched_scan_start() - cfg80211 scheduled scan(pno) start
@@ -211,6 +230,19 @@ int wlan_cfg80211_scan(struct wlan_objmgr_pdev *pdev,
 		struct cfg80211_scan_request *request,
 		struct scan_params *params);
 
+/**
+ * wlan_cfg80211_inform_bss_frame_data() - API to inform beacon to cfg80211
+ * @wiphy: wiphy
+ * @bss_data: bss data
+ *
+ * API to inform beacon to cfg80211
+ *
+ * Return: pointer to bss entry
+ */
+struct cfg80211_bss *
+wlan_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
+		struct wlan_cfg80211_inform_bss *bss);
+
 /**
  * wlan_cfg80211_inform_bss_frame() - API to inform beacon to cfg80211
  * @pdev: Pointer to pdev

+ 93 - 20
os_if/linux/scan/src/wlan_cfg80211_scan.c

@@ -1574,16 +1574,82 @@ static inline void wlan_add_age_ie(uint8_t *mgmt_frame,
 }
 #endif /* WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS */
 
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) || \
+	defined(CFG80211_INFORM_BSS_FRAME_DATA)
+/**
+ * wlan_fill_per_chain_rssi() - fill per chain RSSI in inform bss
+ * @data: bss data
+ * @per_chain_snr: per chain RSSI
+ *
+ * Return: void
+ */
+#if defined(CFG80211_SCAN_PER_CHAIN_RSSI_SUPPORT) || \
+	   (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0))
+static void wlan_fill_per_chain_rssi(struct cfg80211_inform_bss *data,
+	struct wlan_cfg80211_inform_bss *bss)
+{
+
+	uint32_t i;
+
+	if (!bss || !data) {
+		cfg80211_err("Received bss is NULL");
+		return;
+	}
+	for (i = 0; i < WLAN_MGMT_TXRX_HOST_MAX_ANTENNA; i++) {
+		if (!bss->per_chain_snr[i] ||
+		    (bss->per_chain_snr[i] == WLAN_INVALID_PER_CHAIN_RSSI))
+			continue;
+		/* Add noise margin to SNR to convert it to RSSI */
+		data->chain_signal[i] = bss->per_chain_snr[i] +
+					WLAN_NOISE_FLOOR_DBM_DEFAULT;
+		data->chains |= BIT(i);
+	}
+}
+#else
+static inline void
+wlan_fill_per_chain_rssi(struct cfg80211_inform_bss *data,
+	struct wlan_cfg80211_inform_bss *bss)
+{
+}
+#endif
+
+struct cfg80211_bss *
+wlan_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
+		struct wlan_cfg80211_inform_bss *bss)
+{
+	struct cfg80211_inform_bss data  = {0};
+
+	if (!bss) {
+		cfg80211_err("bss is null");
+		return NULL;
+	}
+	wlan_fill_per_chain_rssi(&data, bss);
+
+	data.chan = bss->chan;
+	data.boottime_ns = bss->boottime_ns;
+	data.signal = bss->rssi;
+	return cfg80211_inform_bss_frame_data(wiphy, &data, bss->mgmt,
+					      bss->frame_len, GFP_KERNEL);
+}
+#else
+struct cfg80211_bss *
+wlan_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
+		struct wlan_cfg80211_inform_bss *bss)
+
+{
+	return cfg80211_inform_bss_frame(wiphy, bss->chan, bss->mgmt,
+					 bss->frame_len,
+					 bss->rssi, GFP_KERNEL);
+}
+#endif
+
 void wlan_cfg80211_inform_bss_frame(struct wlan_objmgr_pdev *pdev,
 		struct scan_cache_entry *scan_params)
 {
 	struct pdev_osif_priv *pdev_ospriv = wlan_pdev_get_ospriv(pdev);
 	struct wiphy *wiphy;
-	int frame_len;
-	struct ieee80211_mgmt *mgmt = NULL;
-	struct ieee80211_channel *chan;
-	int rssi = 0;
 	struct cfg80211_bss *bss_status = NULL;
+	struct wlan_cfg80211_inform_bss bss_data = {0};
 
 	if (!pdev_ospriv) {
 		cfg80211_err("os_priv is NULL");
@@ -1592,31 +1658,31 @@ void wlan_cfg80211_inform_bss_frame(struct wlan_objmgr_pdev *pdev,
 
 	wiphy = pdev_ospriv->wiphy;
 
-	frame_len = wlan_get_frame_len(scan_params);
-	mgmt = qdf_mem_malloc(frame_len);
-	if (!mgmt) {
+	bss_data.frame_len = wlan_get_frame_len(scan_params);
+	bss_data.mgmt = qdf_mem_malloc(bss_data.frame_len);
+	if (!bss_data.mgmt) {
 		cfg80211_err("mem alloc failed");
 		return;
 	}
-	qdf_mem_copy(mgmt,
+	qdf_mem_copy(bss_data.mgmt,
 		 util_scan_entry_frame_ptr(scan_params),
 		 util_scan_entry_frame_len(scan_params));
 	/*
 	 * Android does not want the timestamp from the frame.
 	 * Instead it wants a monotonic increasing value
 	 */
-	mgmt->u.probe_resp.timestamp = qdf_get_monotonic_boottime();
-	wlan_add_age_ie((uint8_t *)mgmt, scan_params);
+	bss_data.mgmt->u.probe_resp.timestamp = qdf_get_monotonic_boottime();
+	wlan_add_age_ie((uint8_t *)bss_data.mgmt, scan_params);
 	/*
 	 * Based on .ini configuration, raw rssi can be reported for bss.
 	 * Raw rssi is typically used for estimating power.
 	 */
-	rssi = scan_params->rssi_raw;
+	bss_data.rssi = scan_params->rssi_raw;
 
-	chan = wlan_get_ieee80211_channel(wiphy,
+	bss_data.chan = wlan_get_ieee80211_channel(wiphy,
 		scan_params->channel.chan_idx);
-	if (!chan) {
-		qdf_mem_free(mgmt);
+	if (!bss_data.chan) {
+		qdf_mem_free(bss_data.mgmt);
 		return;
 	}
 
@@ -1624,13 +1690,20 @@ void wlan_cfg80211_inform_bss_frame(struct wlan_objmgr_pdev *pdev,
 	 * Supplicant takes the signal strength in terms of
 	 * mBm (1 dBm = 100 mBm).
 	 */
-	rssi = QDF_MIN(rssi, 0) * 100;
+	bss_data.rssi = QDF_MIN(bss_data.rssi, 0) * 100;
+
+	bss_data.boottime_ns = scan_params->boottime_ns;
+
+	qdf_mem_copy(bss_data.per_chain_snr, scan_params->per_chain_snr,
+		     WLAN_MGMT_TXRX_HOST_MAX_ANTENNA);
 
 	cfg80211_info("BSSID: %pM Channel:%d RSSI:%d",
-		mgmt->bssid, chan->center_freq, (int)(rssi / 100));
+		bss_data.mgmt->bssid, bss_data.chan->center_freq,
+		(int)(bss_data.rssi / 100));
+
+	bss_status = wlan_cfg80211_inform_bss_frame_data(wiphy, &bss_data);
+	if (!bss_status)
+		cfg80211_err("failed to inform bss");
 
-	bss_status =
-		cfg80211_inform_bss_frame(wiphy, chan, mgmt,
-		frame_len, rssi, GFP_KERNEL);
-	qdf_mem_free(mgmt);
+	qdf_mem_free(bss_data.mgmt);
 }

+ 3 - 2
umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h

@@ -644,8 +644,9 @@ enum mgmt_frame_type {
 	MGMT_MAX_FRAME_TYPE,
 };
 
-#define WLAN_MGMT_TXRX_HOST_MAX_ANTENNA 4
-
+#define WLAN_MGMT_TXRX_HOST_MAX_ANTENNA          4
+#define WLAN_INVALID_PER_CHAIN_RSSI             0x80
+#define WLAN_NOISE_FLOOR_DBM_DEFAULT            -96
 /**
  * struct mgmt_rx_event_params - host mgmt header params
  * @channel: channel on which this frame is received

+ 5 - 0
umac/scan/dispatcher/inc/wlan_scan_public_structs.h

@@ -27,6 +27,7 @@
 #include <qdf_list.h>
 #include <qdf_atomic.h>
 #include <wlan_cmn_ieee80211.h>
+#include <wlan_mgmt_txrx_utils_api.h>
 
 typedef uint16_t wlan_scan_requester;
 typedef uint32_t wlan_scan_id;
@@ -278,6 +279,8 @@ struct security_info {
  * @tsf_delta: TSF delta
  * @bss_score: bss score calculated on basis of RSSI/caps etc.
  * @neg_sec_info: negotiated security info
+ * @per_chain_snr: per chain SNR value received.
+ * boottime_ns: boottime in ns.
  * @rrm_parent_tsf: RRM parent tsf
  * @mlme_info: Mlme info, this will be updated by MLME for the scan entry
  * @alt_wcn_ie: alternate WCN IE
@@ -314,6 +317,8 @@ struct scan_cache_entry {
 	uint32_t tsf_delta;
 	uint32_t bss_score;
 	struct security_info neg_sec_info;
+	uint8_t per_chain_snr[WLAN_MGMT_TXRX_HOST_MAX_ANTENNA];
+	uint64_t boottime_ns;
 	uint32_t rrm_parent_tsf;
 	struct element_info alt_wcn_ie;
 	struct ie_list ie_list;

+ 7 - 0
umac/scan/dispatcher/src/wlan_scan_utils_api.c

@@ -853,6 +853,9 @@ util_scan_unpack_beacon_frame(uint8_t *frame,
 			   (frame + sizeof(*hdr));
 	hdr = (struct wlan_frame_hdr *)frame;
 
+	/* update timestamp in nanoseconds needed by kernel layers */
+	scan_entry->boottime_ns = qdf_get_monotonic_boottime_ns();
+
 	scan_entry->frm_subtype = frm_subtype;
 	qdf_mem_copy(scan_entry->bssid.bytes,
 		hdr->i_addr3, QDF_MAC_ADDR_SIZE);
@@ -866,6 +869,10 @@ util_scan_unpack_beacon_frame(uint8_t *frame,
 	scan_entry->avg_rssi = WLAN_RSSI_IN(scan_entry->rssi_raw);
 	scan_entry->tsf_delta = rx_param->tsf_delta;
 
+	/* Copy per chain rssi to scan entry */
+	qdf_mem_copy(scan_entry->per_chain_snr, rx_param->rssi_ctl,
+		     WLAN_MGMT_TXRX_HOST_MAX_ANTENNA);
+
 	/* store jiffies */
 	scan_entry->rrm_parent_tsf = (u_int32_t) qdf_system_ticks();
 

+ 3 - 1
wmi/src/wmi_unified_tlv.c

@@ -18416,6 +18416,7 @@ static QDF_STATUS extract_mgmt_rx_params_tlv(wmi_unified_t wmi_handle,
 {
 	WMI_MGMT_RX_EVENTID_param_tlvs *param_tlvs = NULL;
 	wmi_mgmt_rx_hdr *ev_hdr = NULL;
+	int i;
 
 	param_tlvs = (WMI_MGMT_RX_EVENTID_param_tlvs *) evt_buf;
 	if (!param_tlvs) {
@@ -18441,7 +18442,8 @@ static QDF_STATUS extract_mgmt_rx_params_tlv(wmi_unified_t wmi_handle,
 	hdr->flags = ev_hdr->flags;
 	hdr->rssi = ev_hdr->rssi;
 	hdr->tsf_delta = ev_hdr->tsf_delta;
-	qdf_mem_copy(hdr->rssi_ctl, ev_hdr->rssi_ctl, sizeof(hdr->rssi_ctl));
+	for (i = 0; i < ATH_MAX_ANTENNA; i++)
+		hdr->rssi_ctl[i] = ev_hdr->rssi_ctl[i];
 
 	*bufp = param_tlvs->bufp;