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
This commit is contained in:
gaurank kathpalia 2018-01-29 18:09:06 +05:30 • committed by snandini
commit 26f9833fb8
6 changed files with 144 additions and 24 deletions

View file

@ -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

View file

@ -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 =
cfg80211_inform_bss_frame(wiphy, chan, mgmt,
frame_len, rssi, GFP_KERNEL);
qdf_mem_free(mgmt);
bss_status = wlan_cfg80211_inform_bss_frame_data(wiphy, &bss_data);
if (!bss_status)
cfg80211_err("failed to inform bss");
qdf_mem_free(bss_data.mgmt);
}

View file

@ -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

View file

@ -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;

View file

@ -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();

View file

@ -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;