From 87b0fe29b407c8c5c8a983ba4d615dac282a0261 Mon Sep 17 00:00:00 2001 From: Sai Pavan Akhil Remella Date: Mon, 31 Jan 2022 13:24:19 +0530 Subject: [PATCH] qcacmn: Allow FW to pno scan 6G chan based on RNR flag only First host checks below two things in PNO scan request: 1. Userspace sets NL80211_SCAN_FLAG_COLOCATED_6GHZ flag in pno scan request. 2. At least one 6G channel is present in the pno scan req. If any of above conditions satisfy, Host fills all remaining (other than channel(s) present in pno scan req) valid 6 GHz channel(s) to pno scan requests and set the flag FLAG_SCAN_ONLY_IF_RNR_FOUND for each remaining channel(s). Host sends this updated channel list via WMI command WMI_START_SCAN_CMDID_param_tlvs->channel_list for pno scan to firmware. By this driver allows Firmware to scan 6G channels based on RNR IEs only (for colocated APs reported by 2.4/5 GHz APs). Change-Id: Ib6118c4525e9fbe233eb6a7e07a4a3345d486e8a CRs-Fixed: 3103923 --- os_if/linux/scan/src/wlan_cfg80211_scan.c | 57 +++++++++++-------- umac/scan/core/src/wlan_scan_manager_6ghz.c | 29 +++++++--- umac/scan/core/src/wlan_scan_manager_6ghz.h | 29 ++++++++++ .../dispatcher/inc/wlan_scan_public_structs.h | 15 +++-- umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h | 26 ++++++++- umac/scan/dispatcher/src/wlan_scan_ucfg_api.c | 23 ++++++++ wmi/src/wmi_unified_tlv.c | 57 ++++++++++++++++--- 7 files changed, 190 insertions(+), 46 deletions(-) diff --git a/os_if/linux/scan/src/wlan_cfg80211_scan.c b/os_if/linux/scan/src/wlan_cfg80211_scan.c index ba113c7da5e8..b58563d998c4 100644 --- a/os_if/linux/scan/src/wlan_cfg80211_scan.c +++ b/os_if/linux/scan/src/wlan_cfg80211_scan.c @@ -52,6 +52,27 @@ const struct nla_policy cfg80211_scan_policy[ [QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE] = {.type = NLA_U64}, }; +/** + * wlan_cfg80211_is_colocated_6ghz_scan_supported() - Check whether colocated + * 6ghz scan flag present in scan request or not + * @scan_flag: Flags bitmap coming from kernel + * + * Return: True if colocated 6ghz scan flag present in scan req + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) +static bool +wlan_cfg80211_is_colocated_6ghz_scan_supported(uint32_t scan_flag) +{ + return !!(scan_flag & NL80211_SCAN_FLAG_COLOCATED_6GHZ); +} +#else +static inline bool +wlan_cfg80211_is_colocated_6ghz_scan_supported(uint32_t scan_flag) +{ + return false; +} +#endif + #if defined(CFG80211_SCAN_RANDOM_MAC_ADDR) || \ (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) /** @@ -430,6 +451,9 @@ int wlan_cfg80211_sched_scan_start(struct wlan_objmgr_vdev *vdev, req->networks_cnt = request->n_match_sets; req->vdev_id = wlan_vdev_get_id(vdev); + req->vdev = vdev; + req->scan_policy_colocated_6ghz = + wlan_cfg80211_is_colocated_6ghz_scan_supported(request->flags); if ((!req->networks_cnt) || (req->networks_cnt > SCAN_PNO_MAX_SUPP_NETWORKS)) { @@ -524,9 +548,15 @@ int wlan_cfg80211_sched_scan_start(struct wlan_objmgr_vdev *vdev, req->networks_list[i].bc_new_type = 0; /*eBCAST_UNKNOWN */ /*Copying list of valid channel into request */ - qdf_mem_copy(req->networks_list[i].channels, valid_ch, - num_chan * sizeof(uint32_t)); - req->networks_list[i].channel_cnt = num_chan; + for (j = 0; j < num_chan; j++) + req->networks_list[i].pno_chan_list.chan[j].freq = + valid_ch[j]; + req->networks_list[i].pno_chan_list.num_chan = num_chan; + + if (ucfg_is_6ghz_pno_scan_optimization_supported(psoc)) + ucfg_scan_pno_add_all_valid_6g_channels(vdev, req, + &num_chan); + req->networks_list[i].rssi_thresh = request->match_sets[i].rssi_thold; } @@ -1304,27 +1334,6 @@ void wlan_cfg80211_cleanup_scan_queue(struct wlan_objmgr_pdev *pdev, return; } -/** - * wlan_cfg80211_is_colocated_6ghz_scan_supported() - Check whether colocated - * 6ghz scan flag present in scan request or not - * @scan_flag: Flags bitmap coming from kernel - * - * Return: True if colocated 6ghz scan flag present in scan req - */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) -static bool -wlan_cfg80211_is_colocated_6ghz_scan_supported(uint32_t scan_flag) -{ - return !!(scan_flag & NL80211_SCAN_FLAG_COLOCATED_6GHZ); -} -#else -static inline bool -wlan_cfg80211_is_colocated_6ghz_scan_supported(uint32_t scan_flag) -{ - return false; -} -#endif - /** * wlan_cfg80211_update_scan_policy_type_flags() - Set scan flags according to * scan request diff --git a/umac/scan/core/src/wlan_scan_manager_6ghz.c b/umac/scan/core/src/wlan_scan_manager_6ghz.c index 3f51f3512da7..319cdbd82675 100644 --- a/umac/scan/core/src/wlan_scan_manager_6ghz.c +++ b/umac/scan/core/src/wlan_scan_manager_6ghz.c @@ -248,8 +248,9 @@ scm_is_scan_type_exempted_from_optimization(struct scan_start_request *req) /** * scm_add_all_valid_6g_channels() - Add all valid 6g channels to scan request * @vdev: vdev on which scan request is issued - * @req: Scan start request + * @chan_list: channel list from userspace * @num_scan_ch: Total number of scan channels + * @is_colocated_6ghz_scan_enabled: colocated 6ghz scan flag enabled in scan req * * If colocated 6ghz scan flag present in host scan request or at least one 6G * channel is present in the host scan request, then this API @@ -260,13 +261,13 @@ scm_is_scan_type_exempted_from_optimization(struct scan_start_request *req) * * Return: None */ -static void scm_add_all_valid_6g_channels(struct wlan_objmgr_pdev *pdev, - struct scan_start_request *req, - uint8_t *num_scan_ch) +void scm_add_all_valid_6g_channels(struct wlan_objmgr_pdev *pdev, + struct chan_list *chan_list, + uint8_t *num_scan_ch, + bool is_colocated_6ghz_scan_enabled) { uint8_t i, j; enum channel_enum freq_idx; - struct chan_list *chan_list = &req->scan_req.chan_list; struct regulatory_channel *cur_chan_list; bool is_6g_ch_present = false, found; QDF_STATUS status; @@ -281,8 +282,8 @@ static void scm_add_all_valid_6g_channels(struct wlan_objmgr_pdev *pdev, } } - if (!is_6g_ch_present && - !req->scan_req.scan_policy_colocated_6ghz) { + if (!is_6g_ch_present && !is_colocated_6ghz_scan_enabled) { + scm_debug("Neither 6G chan present nor flag set in scan req"); return; } @@ -331,6 +332,18 @@ static void scm_add_all_valid_6g_channels(struct wlan_objmgr_pdev *pdev, qdf_mem_free(cur_chan_list); } +static void scm_scan_add_all_valid_6g_channels(struct wlan_objmgr_pdev *pdev, + struct scan_start_request *req, + uint8_t *num_scan_ch) +{ + bool is_colocated_6ghz_scan_enabled = + req->scan_req.scan_policy_colocated_6ghz; + + scm_add_all_valid_6g_channels(pdev, &req->scan_req.chan_list, + num_scan_ch, + is_colocated_6ghz_scan_enabled); +} + static void scm_copy_valid_channels(struct wlan_objmgr_psoc *psoc, enum scan_mode_6ghz scan_mode, @@ -513,7 +526,7 @@ scm_update_6ghz_channel_list(struct scan_start_request *req, * set the flag FLAG_SCAN_ONLY_IF_RNR_FOUND for each remaining * channels. */ - scm_add_all_valid_6g_channels(pdev, req, &num_scan_ch); + scm_scan_add_all_valid_6g_channels(pdev, req, &num_scan_ch); break; default: /* diff --git a/umac/scan/core/src/wlan_scan_manager_6ghz.h b/umac/scan/core/src/wlan_scan_manager_6ghz.h index faee20e44c44..4f4114d10229 100644 --- a/umac/scan/core/src/wlan_scan_manager_6ghz.h +++ b/umac/scan/core/src/wlan_scan_manager_6ghz.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -70,6 +71,27 @@ scm_update_6ghz_channel_list(struct scan_start_request *req, */ bool scm_is_6ghz_scan_optimization_supported(struct wlan_objmgr_psoc *psoc); + +/** + * scm_add_all_valid_6g_channels() - Add all valid 6g channels to scan request + * @vdev: vdev on which scan request is issued + * @req: Scan start request + * @num_scan_ch: Total number of scan channels + * + * If colocated 6ghz scan flag present in host scan request or at least one 6G + * channel is present in the host scan request, then this API + * fills all remaining (other than channel(s) resent in host scan req) valid + * 6 GHz channel(s) to scan requests channel list and set the flag + * FLAG_SCAN_ONLY_IF_RNR_FOUND for each of those added channels. + * By this driver allows Firmware to scan 6G channels based on RNR IEs only. + * + * Return: None + */ +void scm_add_all_valid_6g_channels(struct wlan_objmgr_pdev *pdev, + struct chan_list *chan_list, + uint8_t *num_scan_ch, + bool is_colocated_6ghz); + #else static inline void scm_update_6ghz_channel_list(struct scan_start_request *req, @@ -82,6 +104,13 @@ scm_is_6ghz_scan_optimization_supported(struct wlan_objmgr_psoc *psoc) { return false; } + +static inline void scm_add_all_valid_6g_channels(struct wlan_objmgr_pdev *pdev, + struct chan_list *chan_list, + uint8_t *num_scan_ch, + bool is_colocated_6ghz) +{ +} #endif #endif diff --git a/umac/scan/dispatcher/inc/wlan_scan_public_structs.h b/umac/scan/dispatcher/inc/wlan_scan_public_structs.h index 519ff9544727..cb87e61c0547 100644 --- a/umac/scan/dispatcher/inc/wlan_scan_public_structs.h +++ b/umac/scan/dispatcher/inc/wlan_scan_public_structs.h @@ -1286,18 +1286,17 @@ enum ssid_bc_type { * @ssid: ssid * @authentication: authentication type * @encryption: encryption type - * @bcastNetwType: broadcast nw type - * @ucChannelCount: uc channel count - * @aChannels: pno channel - * @rssiThreshold: rssi threshold + * @bc_new_type: broadcast nw type + * @pno_chan_list: pno channel list info + * @rssi_thresh: rssi threshold */ struct pno_nw_type { struct wlan_ssid ssid; uint32_t authentication; uint32_t encryption; uint32_t bc_new_type; - uint8_t channel_cnt; - uint32_t channels[SCAN_PNO_MAX_NETW_CHANNELS_EX]; + struct chan_list pno_chan_list; + int32_t rssi_thresh; }; @@ -1331,6 +1330,7 @@ struct nlo_mawc_params { /** * struct pno_scan_req_params - PNO Scan request structure + * @vdev: vdev object * @networks_cnt: Number of networks * @do_passive_scan: Flag to request passive scan to fw * @vdev_id: vdev id @@ -1361,8 +1361,10 @@ struct nlo_mawc_params { * slow_scan_period=1800, scan_backoff_multiplier=2 } * Result: 120s x2, 240s x2, 480s x2, 960s x2, 1800s xN * @mawc_params: Configuration parameters for NLO MAWC. + * @scan_policy_colocated_6ghz: colocated_6ghz flag is set in pno scan req */ struct pno_scan_req_params { + struct wlan_objmgr_vdev *vdev; uint32_t networks_cnt; bool do_passive_scan; uint32_t vdev_id; @@ -1385,6 +1387,7 @@ struct pno_scan_req_params { int8_t relative_rssi; struct cpno_band_rssi_pref band_rssi_pref; struct nlo_mawc_params mawc_params; + bool scan_policy_colocated_6ghz; }; /** diff --git a/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h b/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h index e05baa4cf094..70cda95abf46 100644 --- a/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h +++ b/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -98,7 +99,30 @@ ucfg_scan_get_scan_id(struct wlan_objmgr_psoc *psoc); * Return: 0 for success or error code. */ QDF_STATUS ucfg_scan_pno_start(struct wlan_objmgr_vdev *vdev, -struct pno_scan_req_params *req); + struct pno_scan_req_params *req); + +/** + * ucfg_scan_pno_add_all_valid_6g_channels() - This API to update all valid 6g + * channels to pno scan request + * @vdev: vdev pointer + * @req: pno req params + * @num_scan_ch: total number of channels present in pno scan request + * + * Return: None + */ +void ucfg_scan_pno_add_all_valid_6g_channels(struct wlan_objmgr_vdev *vdev, + struct pno_scan_req_params *req, + uint8_t *num_scan_ch); + +/** + * ucfg_is_6ghz_pno_scan_optimization_supported() - Public API to check + * 6ghz pno scan optimization supported in fw + * @psoc: psoc object + * + * Return: 0 for success. + */ +bool +ucfg_is_6ghz_pno_scan_optimization_supported(struct wlan_objmgr_psoc *psoc); /** * ucfg_scan_pno_stop() - Public API to stop PNO diff --git a/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c b/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c index dc64d59faee5..189b8d07a879 100644 --- a/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -152,6 +153,12 @@ QDF_STATUS ucfg_scan_deinit(void) } #ifdef FEATURE_WLAN_SCAN_PNO +bool +ucfg_is_6ghz_pno_scan_optimization_supported(struct wlan_objmgr_psoc *psoc) +{ + return wlan_psoc_nif_fw_ext_cap_get(psoc, + WLAN_SOC_PNO_SCAN_CONFIG_PER_CHANNEL); +} QDF_STATUS ucfg_scan_pno_start(struct wlan_objmgr_vdev *vdev, struct pno_scan_req_params *req) @@ -178,6 +185,22 @@ QDF_STATUS ucfg_scan_pno_start(struct wlan_objmgr_vdev *vdev, return status; } +void ucfg_scan_pno_add_all_valid_6g_channels(struct wlan_objmgr_vdev *vdev, + struct pno_scan_req_params *req, + uint8_t *num_scan_ch) +{ + struct wlan_objmgr_pdev *pdev; + struct chan_list *pno_chan_list = &req->networks_list[0].pno_chan_list; + bool is_colocated_6ghz = req->scan_policy_colocated_6ghz; + + pdev = wlan_vdev_get_pdev(vdev); + if (!pdev) + return; + + scm_add_all_valid_6g_channels(pdev, pno_chan_list, num_scan_ch, + is_colocated_6ghz); +} + QDF_STATUS ucfg_scan_pno_stop(struct wlan_objmgr_vdev *vdev) { struct scan_vdev_obj *scan_vdev_obj; diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index 457c94ac4e3a..534a0371b750 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -4880,6 +4880,40 @@ static QDF_STATUS send_nlo_mawc_cmd_tlv(wmi_unified_t wmi_handle, return QDF_STATUS_SUCCESS; } +/** + * wmi_dump_pno_scan_freq_list() - dump frequency list associated with pno + * scan + * @scan_freq_list: frequency list for pno scan + * + * Return: void + */ +static void wmi_dump_pno_scan_freq_list(struct chan_list *scan_freq_list) +{ + uint32_t i; + uint8_t info[WMI_MAX_CHAN_INFO_LOG]; + uint32_t len = 0; + struct chan_info *chan_info; + int ret; + + wmi_debug("[PNO_SCAN] Total freq %d", scan_freq_list->num_chan); + for (i = 0; i < scan_freq_list->num_chan; i++) { + chan_info = &scan_freq_list->chan[i]; + ret = qdf_scnprintf(info + len, sizeof(info) - len, + " %d[%d]", chan_info->freq, + chan_info->flags); + if (ret <= 0) + break; + len += ret; + if (len >= (sizeof(info) - 20)) { + wmi_nofl_debug("Freq[flag]:%s", + info); + len = 0; + } + } + if (len) + wmi_nofl_debug("Freq[flag]:%s", info); +} + /** * send_pno_start_cmd_tlv() - PNO start request * @wmi_handle: wmi handle @@ -4895,6 +4929,7 @@ static QDF_STATUS send_pno_start_cmd_tlv(wmi_unified_t wmi_handle, nlo_configured_parameters *nlo_list; uint32_t *channel_list; int32_t len; + qdf_freq_t freq; wmi_buf_t buf; uint8_t *buf_ptr; uint8_t i; @@ -4914,7 +4949,7 @@ static QDF_STATUS send_pno_start_cmd_tlv(wmi_unified_t wmi_handle, WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE; - len += sizeof(uint32_t) * pno->networks_list[0].channel_cnt; + len += sizeof(uint32_t) * pno->networks_list[0].pno_chan_list.num_chan; len += sizeof(nlo_configured_parameters) * QDF_MIN(pno->networks_cnt, WMI_NLO_MAX_SSIDS); len += sizeof(nlo_channel_prediction_cfg); @@ -5001,20 +5036,28 @@ static QDF_STATUS send_pno_start_cmd_tlv(wmi_unified_t wmi_handle, buf_ptr += cmd->no_of_ssids * sizeof(nlo_configured_parameters); /* Copy channel info */ - cmd->num_of_channels = pno->networks_list[0].channel_cnt; + cmd->num_of_channels = pno->networks_list[0].pno_chan_list.num_chan; WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, (cmd->num_of_channels * sizeof(uint32_t))); buf_ptr += WMI_TLV_HDR_SIZE; channel_list = (uint32_t *) buf_ptr; for (i = 0; i < cmd->num_of_channels; i++) { - channel_list[i] = pno->networks_list[0].channels[i]; + TARGET_SET_FREQ_IN_CHAN_LIST_TLV(channel_list[i], + pno->networks_list[0].pno_chan_list.chan[i].freq); - if (channel_list[i] < WMI_NLO_FREQ_THRESH) - channel_list[i] = - wlan_chan_to_freq(pno-> - networks_list[0].channels[i]); + if (channel_list[i] < WMI_NLO_FREQ_THRESH) { + freq = pno->networks_list[0].pno_chan_list.chan[i].freq; + TARGET_SET_FREQ_IN_CHAN_LIST_TLV(channel_list[i], + wlan_chan_to_freq(freq)); + } + + TARGET_SET_FLAGS_IN_CHAN_LIST_TLV(channel_list[i], + pno->networks_list[0].pno_chan_list.chan[i].flags); } + + wmi_dump_pno_scan_freq_list(&pno->networks_list[0].pno_chan_list); + buf_ptr += cmd->num_of_channels * sizeof(uint32_t); WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, sizeof(nlo_channel_prediction_cfg));