From c624ae701c573149761d059963b3fe924ec1c949 Mon Sep 17 00:00:00 2001 From: Ian Lin Date: Tue, 10 May 2022 04:53:27 -0500 Subject: [PATCH 094/296] brcmfmac: support signal monitor feature for wpa_supplicant bgscan Add nl80211 operation and notify event for background scan After connect to target AP, wpa_supplicant will continually send scan request to driver with an given interval, and apply the short/long interval according to signal level. Signed-off-by: Ian Lin --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 38 +++++++++++++++++++ .../broadcom/brcm80211/brcmfmac/cfg80211.h | 6 +++ 2 files changed, 44 insertions(+) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 948cb7fc3d06..418739828069 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -3617,6 +3617,41 @@ next_bss_le(struct brcmf_scan_results *list, struct brcmf_bss_info_le *bss) le32_to_cpu(bss->length)); } +static s32 brcmf_singal_monitor(struct brcmf_cfg80211_info *cfg, + struct brcmf_if *ifp) +{ + s32 err = 0, rssi = 0; + int i; + u8 bssid[ETH_ALEN] = {0}; + struct brcmf_scan_results *bss_list; + struct brcmf_bss_info_le *bi = NULL; + + if(!cfg->cqm_info.enable) + return 0; + + err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSSID, bssid, ETH_ALEN); + bss_list = (struct brcmf_scan_results *)cfg->escan_info.escan_buf; + + /* wpa bgscan feature: wpa will send scan request after associated + * to the target AP, when we get the scan result of this associated + * AP, send the rssi threshold event upward */ + for (i = 0; i < bss_list->count; i++) { + bi = next_bss_le(bss_list, bi); + if (err == 0 && memcmp(bi->BSSID, bssid, ETH_ALEN) == 0) { + rssi = (s16)le16_to_cpu(bi->RSSI); + brcmf_dbg(TRACE, "%s(%pM), rssi: %d, threshold: %d, send event(%s)\n", + bi->SSID, bi->BSSID, rssi, cfg->cqm_info.rssi_threshold, + rssi > cfg->cqm_info.rssi_threshold ? "HIGH" : "LOW"); + cfg80211_cqm_rssi_notify(cfg_to_ndev(cfg), + (rssi > cfg->cqm_info.rssi_threshold ? + NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH : + NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW), + rssi, GFP_KERNEL); + } + } + return 0; +} + static s32 brcmf_inform_bss(struct brcmf_cfg80211_info *cfg) { struct brcmf_pub *drvr = cfg->pub; @@ -3924,6 +3959,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, goto exit; if (cfg->int_escan_map || cfg->scan_request) { brcmf_inform_bss(cfg); + brcmf_singal_monitor(cfg, ifp); aborted = status != BRCMF_E_STATUS_SUCCESS; brcmf_notify_escan_complete(cfg, ifp, aborted, false); } else @@ -8428,6 +8464,8 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) brcmf_feat_is_enabled(ifp, BRCMF_FEAT_OKC)) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ROAM_OFFLOAD); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); + wiphy->mgmt_stypes = brcmf_txrx_stypes; wiphy->max_remain_on_channel_duration = 5000; if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO)) { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h index 452f8843d6ab..e67c5dba098f 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h @@ -303,6 +303,11 @@ struct escan_info { struct cfg80211_scan_request *request); }; +struct cqm_rssi_info { + bool enable; + s32 rssi_threshold; +}; + /** * struct brcmf_cfg80211_vif_event - virtual interface event information. * @@ -399,6 +404,7 @@ struct brcmf_cfg80211_info { struct escan_info escan_info; struct timer_list escan_timeout; struct work_struct escan_timeout_work; + struct cqm_rssi_info cqm_info; struct list_head vif_list; struct brcmf_cfg80211_vif_event vif_event; struct completion vif_disabled; -- 2.25.1