qcacld-3.0: Optionally report raw rssi value to supplicant

qcacld-2.0 to qcacld-3.0 propagation

Add raw rssi in the beacon header from WMI to beacon descriptor.
Pass it up to SME and report it to supplicant through a call to
wlan_hdd_cfg80211_inform_bss_frame().
It can be enabled as a .ini configuration parameter "gInformBssRssiRaw".
Default is 1, it will report raw rssi by default.
Roaming decisions are based on rssi field of beacon descriptor,
its interpretation and usage are unchanged.

CRs-Fixed: 815344
Change-Id: I6dacdc0b333c093d16a74f8cf36471dfc183ce56
diff --git a/core/cds/src/i_cds_packet.h b/core/cds/src/i_cds_packet.h
index 23858fe..0a0e3a6 100644
--- a/core/cds/src/i_cds_packet.h
+++ b/core/cds/src/i_cds_packet.h
@@ -42,8 +42,29 @@
    Include Files
    ------------------------------------------------------------------------*/
 #include "cdf_types.h"
-/*
+/**
  * Rx Packet Struct
+ * Buffer for the packet received from WMA has pointers to 802.11
+ * frame fields and additional information based on the type of frame.
+ * @channel: Channel number
+ * @snr: Signal to noise ratio
+ * @rssi: Received signal strength indicator, normalized to -96 dBm as
+ *        normal noise floor by adding -96 to snr. All the configured
+ *        thresholds in the driver assume that noise floor is -96 dBm.
+ * @timestamp: System timestamp when frame was received. Set to jiffies.
+ * @mpdu_hdr_ptr: Pointer to beginning of 802.11 MPDU
+ * @mpdu_data_ptr: Pointer to beginning of payload
+ * @mpdu_len: Length of 802.11 MPDU
+ * @mpdu_hdr_len: Length of 802.11 MPDU header
+ * @mpdu_data_len: Length of 802.11 MPDU payload
+ * @offloadScanLearn: Bit set to 1 for beacons received during roaming scan
+ * @roamCandidateInd: Bit set to 1 when roaming candidate is found by fw
+ * @scan: Bit set to 1 if packet received during scanning
+ * @scan_src: Source of scan
+ * @dpuFeedback: DPU feedback for frame
+ * @sessionId: PE session
+ * @tsf_delta: Delta between tsf in frame and local value of tsf
+ * @rssi_raw: rssi based on actual noise floor in hardware.
  */
 typedef struct {
 	uint8_t channel;
@@ -62,6 +83,7 @@
 	uint8_t dpuFeedback;
 	uint8_t sessionId;
 	uint32_t tsf_delta;
+	uint32_t rssi_raw;
 } t_packetmeta, *tp_packetmeta;
 
 /* implementation specific cds packet type */
diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h
index d37bdcd..92c51b7 100644
--- a/core/hdd/inc/wlan_hdd_cfg.h
+++ b/core/hdd/inc/wlan_hdd_cfg.h
@@ -2853,6 +2853,14 @@
 #define CFG_ENABLE_LFR_SUBNET_MAX          (1)
 #define CFG_ENABLE_LFR_SUBNET_DEFAULT      (1)
 #endif /* FEATURE_LFR_SUBNET_DETECTION */
+/* Option to report rssi in cfg80211_inform_bss_frame()
+ * 0 = use rssi value based on noise floor = -96 dBm
+ * 1 = use rssi value based on actual noise floor in hardware
+ */
+#define CFG_INFORM_BSS_RSSI_RAW_NAME               "gInformBssRssiRaw"
+#define CFG_INFORM_BSS_RSSI_RAW_MIN                (0)
+#define CFG_INFORM_BSS_RSSI_RAW_MAX                (1)
+#define CFG_INFORM_BSS_RSSI_RAW_DEFAULT            (1)
 
 /*---------------------------------------------------------------------------
    Type declarations
@@ -3441,6 +3449,7 @@
 #ifdef FEATURE_LFR_SUBNET_DETECTION
 	bool enable_lfr_subnet_detection;
 #endif
+	uint8_t inform_bss_rssi_raw;
 };
 
 #define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var))
@@ -3530,7 +3539,7 @@
 typedef struct tREG_TABLE_ENTRY {
 
 	char *RegName;          /* variable name in the qcom_cfg.ini file */
-	WLAN_PARAMETER_TYPE RegType;    /* variable type in the hdd_config_t structure */
+	WLAN_PARAMETER_TYPE RegType;    /* variable type in hdd_config struct */
 	unsigned long Flags;    /* Specify optional parms and if RangeCheck is performed */
 	unsigned short VarOffset;       /* offset to field from the base address of the structure */
 	unsigned short VarSize; /* size (in bytes) of the field */
diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c
index 33a41f0..3cb0e6b 100644
--- a/core/hdd/src/wlan_hdd_cfg.c
+++ b/core/hdd/src/wlan_hdd_cfg.c
@@ -3666,6 +3666,13 @@
 		     CFG_ENABLE_LFR_SUBNET_MIN,
 		     CFG_ENABLE_LFR_SUBNET_MAX),
 #endif
+
+	REG_VARIABLE(CFG_INFORM_BSS_RSSI_RAW_NAME, WLAN_PARAM_Integer,
+		struct hdd_config, inform_bss_rssi_raw,
+		VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+		CFG_INFORM_BSS_RSSI_RAW_DEFAULT,
+		CFG_INFORM_BSS_RSSI_RAW_MIN,
+		CFG_INFORM_BSS_RSSI_RAW_MAX),
 };
 
 
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index 99de1e3..ac59b0b 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -7307,6 +7307,7 @@
 #ifdef CONFIG_CNSS
 	struct timespec ts;
 #endif
+	struct hdd_config *cfg_param;
 
 	ENTER();
 
@@ -7315,6 +7316,7 @@
 	if (0 != status)
 		return NULL;
 
+	cfg_param = pHddCtx->config;
 	mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
 	if (!mgmt) {
 		hddLog(LOGE, FL("memory allocation failed"));
@@ -7408,8 +7410,15 @@
 		return NULL;
 	}
 
+	/* Based on .ini configuration, raw rssi can be reported for bss.
+	 * Raw rssi is typically used for estimating power.
+	 */
+
+	rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
+			bss_desc->rssi;
+
 	/* Supplicant takes the signal strength in terms of mBm(100*dBm) */
-	rssi = (CDF_MIN((bss_desc->rssi + bss_desc->sinr), 0)) * 100;
+	rssi = CDF_MIN(rssi, 0) * 100;
 
 	hddLog(LOG1, FL("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d"),
 	       MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h
index 219c5ec..2577959 100644
--- a/core/mac/inc/sir_api.h
+++ b/core/mac/inc/sir_api.h
@@ -625,8 +625,8 @@
 	uint16_t beaconInterval;
 	uint16_t capabilityInfo;
 	tSirNwType nwType;      /* Indicates 11a/b/g */
-	uint8_t reserved_padding0;
 	int8_t rssi;
+	int8_t rssi_raw;
 	int8_t sinr;
 	/* channelId what peer sent in beacon/probersp. */
 	uint8_t channelId;
diff --git a/core/mac/src/pe/lim/lim_process_action_frame.c b/core/mac/src/pe/lim/lim_process_action_frame.c
index 2ef83fd..277234c 100644
--- a/core/mac/src/pe/lim/lim_process_action_frame.c
+++ b/core/mac/src/pe/lim/lim_process_action_frame.c
@@ -1895,7 +1895,7 @@
 		case SIR_MAC_WNM_BSS_TM_RESPONSE:
 		case SIR_MAC_WNM_NOTIF_REQUEST:
 		case SIR_MAC_WNM_NOTIF_RESPONSE:
-			rssi = WMA_GET_RX_RSSI_DB(rx_pkt_info);
+			rssi = WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info);
 			mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
 			/* Forward to the SME to HDD to wpa_supplicant */
 			lim_send_sme_mgmt_frame_ind(mac_ctx,
@@ -2056,7 +2056,7 @@
 
 			mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
 			frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
-			rssi = WMA_GET_RX_RSSI_DB(rx_pkt_info);
+			rssi = WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info);
 			CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
 				  ("Public Action TDLS Discovery RSP .."));
 			lim_send_sme_mgmt_frame_ind(mac_ctx,
diff --git a/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c
index be37a64..8e0ed5a 100644
--- a/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c
+++ b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c
@@ -611,7 +611,7 @@
 		"and mlmstate: %d RSSI %d from " MAC_ADDRESS_STR), subtype,
 		session_entry->peSessionId, GET_LIM_SYSTEM_ROLE(session_entry),
 		session_entry->limMlmState,
-		(uint) abs((int8_t) WMA_GET_RX_RSSI_DB(rx_pkt_info)),
+		(uint) abs((int8_t) WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info)),
 		MAC_ADDR_ARRAY(hdr->sa));
 
 	beacon = cdf_mem_malloc(sizeof(tSchBeaconStruct));
diff --git a/core/mac/src/pe/lim/lim_process_auth_frame.c b/core/mac/src/pe/lim/lim_process_auth_frame.c
index 9871cff..526b5f4 100644
--- a/core/mac/src/pe/lim/lim_process_auth_frame.c
+++ b/core/mac/src/pe/lim/lim_process_auth_frame.c
@@ -190,7 +190,7 @@
 		   "Frame Received: BSSID: " MAC_ADDRESS_STR " (RSSI %d)"),
 		psessionEntry->peSessionId, GET_LIM_SYSTEM_ROLE(psessionEntry),
 		psessionEntry->limMlmState, MAC_ADDR_ARRAY(pHdr->bssId),
-		(uint) abs((int8_t) WMA_GET_RX_RSSI_DB(pRxPacketInfo)));
+		(uint) abs((int8_t) WMA_GET_RX_RSSI_NORMALIZED(pRxPacketInfo)));
 
 	pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
 
@@ -1775,7 +1775,7 @@
 	lim_log(pMac, LOG1,
 		FL("Auth Frame Received: BSSID " MAC_ADDRESS_STR " (RSSI %d)"),
 		MAC_ADDR_ARRAY(pHdr->bssId),
-		(uint) abs((int8_t) WMA_GET_RX_RSSI_DB(pBd)));
+		(uint) abs((int8_t) WMA_GET_RX_RSSI_NORMALIZED(pBd)));
 
 	/* Auth frame has come on a new BSS, however, we need to find the session
 	 * from where the auth-req was sent to the new AP
diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c
index 928e5d7..ca614fe 100644
--- a/core/mac/src/pe/lim/lim_process_message_queue.c
+++ b/core/mac/src/pe/lim/lim_process_message_queue.c
@@ -352,7 +352,7 @@
 		result->ap[i].capability =
 			lim_get_u16((uint8_t *) &frame->capabilityInfo);
 		result->ap[i].channel = WMA_GET_RX_CH(rx_pkt_info);
-		result->ap[i].rssi = WMA_GET_RX_RSSI_DB(rx_pkt_info);
+		result->ap[i].rssi = WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info);
 		result->ap[i].rtt = 0;
 		result->ap[i].rtt_sd = 0;
 		result->ap[i].ieLength = ie_len;
@@ -403,7 +403,7 @@
 	result->ap.capability =
 			lim_get_u16((uint8_t *) &frame->capabilityInfo);
 	result->ap.channel = WMA_GET_RX_CH(rx_pkt_info);
-	result->ap.rssi = WMA_GET_RX_RSSI_DB(rx_pkt_info);
+	result->ap.rssi = WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info);
 	result->ap.rtt = 0;
 	result->ap.rtt_sd = 0;
 	result->ap.ieLength = ie_len;
diff --git a/core/mac/src/pe/lim/lim_process_probe_rsp_frame.c b/core/mac/src/pe/lim/lim_process_probe_rsp_frame.c
index 1cfd743..16b960c 100644
--- a/core/mac/src/pe/lim/lim_process_probe_rsp_frame.c
+++ b/core/mac/src/pe/lim/lim_process_probe_rsp_frame.c
@@ -129,7 +129,7 @@
 		FL("Probe Resp Frame Received: BSSID "
 		MAC_ADDRESS_STR " (RSSI %d)"),
 		MAC_ADDR_ARRAY(header->bssId),
-		(uint) abs((int8_t)WMA_GET_RX_RSSI_DB(rx_Packet_info)));
+		(uint) abs((int8_t)WMA_GET_RX_RSSI_NORMALIZED(rx_Packet_info)));
 	/* Get pointer to Probe Response frame body */
 	body = WMA_GET_RX_MPDU_DATA(rx_Packet_info);
 		/* Enforce Mandatory IEs */
@@ -349,7 +349,8 @@
 		  FL("Probe Resp Frame Received: BSSID "
 		  MAC_ADDRESS_STR " (RSSI %d)"),
 		  MAC_ADDR_ARRAY(header->bssId),
-		  (uint) abs((int8_t)WMA_GET_RX_RSSI_DB(rx_packet_info)));
+		  (uint) abs((int8_t)WMA_GET_RX_RSSI_NORMALIZED(
+					rx_packet_info)));
 	/*
 	 * Get pointer to Probe Response frame body
 	 */
diff --git a/core/mac/src/pe/lim/lim_scan_result_utils.c b/core/mac/src/pe/lim/lim_scan_result_utils.c
index 387152e..85d6093 100644
--- a/core/mac/src/pe/lim/lim_scan_result_utils.c
+++ b/core/mac/src/pe/lim/lim_scan_result_utils.c
@@ -177,10 +177,15 @@
 	sir_dump_buf(pMac, SIR_LIM_MODULE_ID, LOG4,
 		(uint8_t *) pRxPacketInfo, 36);
 
-	pBssDescr->rssi = (int8_t) WMA_GET_RX_RSSI_DB(pRxPacketInfo);
+	pBssDescr->rssi = (int8_t) WMA_GET_RX_RSSI_NORMALIZED(pRxPacketInfo);
+	pBssDescr->rssi_raw = (int8_t) WMA_GET_RX_RSSI_RAW(pRxPacketInfo);
 
 	/* SINR no longer reported by HW */
 	pBssDescr->sinr = 0;
+	lim_log(pMac, LOG3,
+		FL(MAC_ADDRESS_STR " rssi: normalized = %d, absolute = %d"),
+		MAC_ADDR_ARRAY(pHdr->bssId), pBssDescr->rssi,
+		pBssDescr->rssi_raw);
 
 	pBssDescr->nReceivedTime = (uint32_t) cdf_mc_timer_get_system_ticks();
 	pBssDescr->tsf_delta = WMA_GET_RX_TSF_DELTA(pRxPacketInfo);
diff --git a/core/mac/src/pe/rrm/rrm_api.c b/core/mac/src/pe/rrm/rrm_api.c
index 38f748a..1104a93 100644
--- a/core/mac/src/pe/rrm/rrm_api.c
+++ b/core/mac/src/pe/rrm/rrm_api.c
@@ -306,7 +306,7 @@
 	LinkReport.dialogToken = pLinkReq->DialogToken.token;
 	LinkReport.rxAntenna = 0;
 	LinkReport.txAntenna = 0;
-	currentRSSI = WMA_GET_RX_RSSI_DB(pRxPacketInfo);
+	currentRSSI = WMA_GET_RX_RSSI_RAW(pRxPacketInfo);
 
 	lim_log(pMac, LOG1, "Received Link report frame with %d", currentRSSI);
 
diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c
index a11a106..b775de7 100644
--- a/core/sme/src/csr/csr_api_scan.c
+++ b/core/sme/src/csr/csr_api_scan.c
@@ -2506,7 +2506,6 @@
 	tListElem *pEntry;
 	tCsrScanResult *scan_entry;
 	bool fRC = false;
-	int8_t scan_entry_rssi = 0;
 
 	/*
 	 * Walk through all the chained BssDescriptions. If we find a chained
@@ -2526,17 +2525,24 @@
 		if (csr_is_duplicate_bss_description(pMac,
 			&scan_entry->Result.BssDescriptor,
 			bss_dscp, pIes, fForced)) {
-			/*
-			 * Following is mathematically a = (aX + b(100-X))/100
-			 * where:
-			 * a = bss_dscp->rssi, b = scan_entry_rssi
-			 * and X = CSR_SCAN_RESULT_RSSI_WEIGHT
-			 */
-			scan_entry_rssi = scan_entry->Result.BssDescriptor.rssi;
-			bss_dscp->rssi = (int8_t) ((((int32_t) bss_dscp->rssi *
-						CSR_SCAN_RESULT_RSSI_WEIGHT) +
-				((int32_t) scan_entry_rssi *
-				 (100 - CSR_SCAN_RESULT_RSSI_WEIGHT))) / 100);
+			int32_t rssi_new, rssi_old;
+
+			rssi_new = (int32_t) bss_dscp->rssi;
+			rssi_old = (int32_t) scan_entry->
+					Result.BssDescriptor.rssi;
+			rssi_new = ((rssi_new * CSR_SCAN_RESULT_RSSI_WEIGHT) +
+				rssi_old *
+				(100 - CSR_SCAN_RESULT_RSSI_WEIGHT)) / 100;
+			bss_dscp->rssi = (int8_t) rssi_new;
+
+			rssi_new = (int32_t) bss_dscp->rssi_raw;
+			rssi_old = (int32_t) scan_entry->
+					Result.BssDescriptor.rssi_raw;
+			rssi_new = ((rssi_new * CSR_SCAN_RESULT_RSSI_WEIGHT) +
+				rssi_old *
+				(100 - CSR_SCAN_RESULT_RSSI_WEIGHT)) / 100;
+			bss_dscp->rssi_raw = (int8_t) rssi_new;
+
 			/* Remove the old entry from the list */
 			if (csr_ll_remove_entry
 				    (&pMac->scan.scanResultList, pEntry,
diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h
index 0f24498..d769a78 100644
--- a/core/wma/inc/wma_types.h
+++ b/core/wma/inc/wma_types.h
@@ -123,9 +123,14 @@
 
 #define WMA_GET_RX_RFBAND(pRxMeta) 0
 
-#define WMA_MAX_TXPOWER_INVALID		127
-#define WMA_GET_RX_RSSI_DB(pRxMeta) \
-	(((t_packetmeta *)pRxMeta)->rssi)
+#define WMA_MAX_TXPOWER_INVALID        127
+/* rssi value normalized to noise floor of -96 dBm */
+#define WMA_GET_RX_RSSI_NORMALIZED(pRxMeta) \
+		       (((t_packetmeta *)pRxMeta)->rssi)
+
+/* raw rssi based on actual noise floor in hardware */
+#define WMA_GET_RX_RSSI_RAW(pRxMeta) \
+		       (((t_packetmeta *)pRxMeta)->rssi_raw)
 
 /* WMA Messages */
 #define WMA_MSG_TYPES_BEGIN            SIR_HAL_MSG_TYPES_BEGIN
diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c
index 9d4d402..9e46b64 100644
--- a/core/wma/src/wma_mgmt.c
+++ b/core/wma/src/wma_mgmt.c
@@ -3191,10 +3191,21 @@
 	 */
 	rx_pkt->pkt_meta.channel = hdr->channel;
 	rx_pkt->pkt_meta.scan_src = hdr->flags;
-	/*Get the absolute rssi value from the current rssi value
-	 *the sinr value is hardcoded into 0 in the core stack*/
-	rx_pkt->pkt_meta.rssi = hdr->snr + WMA_TGT_NOISE_FLOOR_DBM;
+
+	/*
+	 * Get the rssi value from the current snr value
+	 * using standard noise floor of -96.
+	 */
+	rx_pkt->pkt_meta.rssi = hdr->snr + WMA_NOISE_FLOOR_DBM_DEFAULT;
 	rx_pkt->pkt_meta.snr = hdr->snr;
+
+	/* If absolute rssi is available from firmware, use it */
+	if (hdr->rssi != 0)
+		rx_pkt->pkt_meta.rssi_raw = hdr->rssi;
+	else
+		rx_pkt->pkt_meta.rssi_raw = rx_pkt->pkt_meta.rssi;
+
+
 	/*
 	 * FIXME: Assigning the local timestamp as hw timestamp is not
 	 * available. Need to see if pe/lim really uses this data.
@@ -3253,6 +3264,11 @@
 	cdf_mem_copy(wh, param_tlvs->bufp, hdr->buf_len);
 #endif
 
+	WMA_LOGD(
+		FL("BSSID: "MAC_ADDRESS_STR" snr = %d, rssi = %d, rssi_raw = %d"),
+			MAC_ADDR_ARRAY(wh->i_addr3),
+			hdr->snr, rx_pkt->pkt_meta.rssi,
+			rx_pkt->pkt_meta.rssi_raw);
 	if (!wma_handle->mgmt_rx) {
 		WMA_LOGE("Not registered for Mgmt rx, dropping the frame");
 		cds_pkt_return_packet(rx_pkt);