diff --git a/umac/scan/core/src/wlan_scan_cache_db.c b/umac/scan/core/src/wlan_scan_cache_db.c index a6774e98a788..33569ad61d35 100644 --- a/umac/scan/core/src/wlan_scan_cache_db.c +++ b/umac/scan/core/src/wlan_scan_cache_db.c @@ -955,7 +955,19 @@ QDF_STATUS __scm_handle_bcn_probe(struct scan_bcn_probe_event *bcn) qdf_mem_free(scan_node); continue; } - + /* Do not add invalid channel entry as kernel will reject it */ + if (scan_obj->drop_bcn_on_invalid_freq && + wlan_reg_is_disable_for_freq(pdev, + scan_entry->channel.chan_freq)) { + scm_nofl_debug("Drop frame for invalid freq %d: %pM Seq Num: %d RSSI %d", + scan_entry->channel.chan_freq, + scan_entry->bssid.bytes, + scan_entry->seq_num, + scan_entry->rssi_raw); + util_scan_free_cache_entry(scan_entry); + qdf_mem_free(scan_node); + continue; + } if (scan_obj->cb.update_beacon) scan_obj->cb.update_beacon(pdev, scan_entry); diff --git a/umac/scan/core/src/wlan_scan_main.h b/umac/scan/core/src/wlan_scan_main.h index acdfee3ffc52..ff6261721aa8 100644 --- a/umac/scan/core/src/wlan_scan_main.h +++ b/umac/scan/core/src/wlan_scan_main.h @@ -493,6 +493,7 @@ struct scan_cb { * @miracast_enabled: miracast enabled * @disable_timeout: command timeout disabled * @drop_bcn_on_chan_mismatch: drop bcn if channel mismatch + * @drop_bcn_on_invalid_freq: drop bcn if freq is invalid in IEs (DS/HT/HE) * @scan_start_request_buff: buffer used to pass * scan config to event handlers * @rnr_channel_db: RNR channel list database @@ -519,6 +520,7 @@ struct wlan_scan_obj { bool miracast_enabled; bool disable_timeout; bool drop_bcn_on_chan_mismatch; + bool drop_bcn_on_invalid_freq; struct scan_start_request scan_start_request_buff; #ifdef FEATURE_6G_SCAN_CHAN_SORT_ALGO struct channel_list_db rnr_channel_db; diff --git a/umac/scan/dispatcher/inc/wlan_scan_cfg.h b/umac/scan/dispatcher/inc/wlan_scan_cfg.h index 57ee69d56fd4..e14c31bbe3cb 100644 --- a/umac/scan/dispatcher/inc/wlan_scan_cfg.h +++ b/umac/scan/dispatcher/inc/wlan_scan_cfg.h @@ -58,6 +58,27 @@ enum scan_mode_6ghz { true,\ "drop bcn on channel mismatch") +/* + * + * drop_bcn_on_invalid_freq - drop the beacon or probe resp with invalid freq + * @Min: 0 + * @Max: 1 + * @Default: 1 + * + * This ini is used to decide whether to drop the beacon/probe resp or not + * if channel received in DS param, HT info and HE IE is invalid. + * + * Related: None + * + * Usage: External + * + * + */ +#define CFG_DROP_BCN_ON_INVALID_FREQ CFG_INI_BOOL(\ + "drop_bcn_on_invalid_freq",\ + true,\ + "drop bcn on invalid freq in HT, DS, HE IE") + /* * * gActiveMaxChannelTime - Set max channel time for active scan @@ -1206,6 +1227,7 @@ enum scan_mode_6ghz { #define CFG_SCAN_ALL \ CFG(CFG_DROP_BCN_ON_CHANNEL_MISMATCH) \ + CFG(CFG_DROP_BCN_ON_INVALID_FREQ) \ CFG(CFG_ENABLE_WAKE_LOCK_IN_SCAN) \ CFG(CFG_ACTIVE_MAX_CHANNEL_TIME) \ CFG(CFG_ENABLE_DFS_SCAN) \ diff --git a/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c b/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c index 5e0d60f071b5..748df4d6fb79 100644 --- a/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c @@ -936,6 +936,8 @@ wlan_scan_global_init(struct wlan_objmgr_psoc *psoc, scan_obj->scan_disabled = 0; scan_obj->drop_bcn_on_chan_mismatch = cfg_get(psoc, CFG_DROP_BCN_ON_CHANNEL_MISMATCH); + scan_obj->drop_bcn_on_invalid_freq = + cfg_get(psoc, CFG_DROP_BCN_ON_INVALID_FREQ); scan_obj->disable_timeout = false; scan_obj->scan_def.active_dwell = cfg_get(psoc, CFG_ACTIVE_MAX_CHANNEL_TIME); diff --git a/umac/scan/dispatcher/src/wlan_scan_utils_api.c b/umac/scan/dispatcher/src/wlan_scan_utils_api.c index fe269cc9b7b3..859630d0c03d 100644 --- a/umac/scan/dispatcher/src/wlan_scan_utils_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_utils_api.c @@ -236,25 +236,52 @@ static struct he_oper_6g_param *util_scan_get_he_6g_params(uint8_t *he_ops) return (struct he_oper_6g_param *)he_ops; } -static void -util_scan_get_chan_from_he_6g_params(struct scan_cache_entry *scan_params, - uint8_t *chan_idx, bool *he_6g_dup_bcon) +static QDF_STATUS +util_scan_get_chan_from_he_6g_params(struct wlan_objmgr_pdev *pdev, + struct scan_cache_entry *scan_params, + qdf_freq_t *chan_freq, + bool *he_6g_dup_bcon, uint8_t band_mask) { struct he_oper_6g_param *he_6g_params; uint8_t *he_ops; + struct wlan_scan_obj *scan_obj; + struct wlan_objmgr_psoc *psoc; + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + scm_err("psoc is NULL"); + return QDF_STATUS_E_INVAL; + } + + scan_obj = wlan_psoc_get_scan_obj(psoc); + if (!scan_obj) { + scm_err("scan_obj is NULL"); + return QDF_STATUS_E_INVAL; + } *he_6g_dup_bcon = false; he_ops = util_scan_entry_heop(scan_params); if (!util_scan_entry_hecap(scan_params) || !he_ops) - return; + return QDF_STATUS_SUCCESS; he_6g_params = util_scan_get_he_6g_params(he_ops); if (!he_6g_params) - return; + return QDF_STATUS_SUCCESS; - *chan_idx = he_6g_params->primary_channel; + *chan_freq = wlan_reg_chan_band_to_freq(pdev, + he_6g_params->primary_channel, + band_mask); + if (scan_obj->drop_bcn_on_invalid_freq && + wlan_reg_is_disable_for_freq(pdev, *chan_freq)) { + scm_debug_rl("%pM: Drop as invalid channel %d freq %d in HE 6Ghz params", + scan_params->bssid.bytes, + he_6g_params->primary_channel, *chan_freq); + return QDF_STATUS_E_INVAL; + } *he_6g_dup_bcon = he_6g_params->duplicate_beacon ? true : false; + + return QDF_STATUS_SUCCESS; } static enum wlan_phymode @@ -312,10 +339,15 @@ util_scan_get_phymode_6g(struct wlan_objmgr_pdev *pdev, return phymode; } #else -static void -util_scan_get_chan_from_he_6g_params(struct scan_cache_entry *scan_params, - uint8_t *chan_idx, bool *he_6g_dup_bcon) -{} +static QDF_STATUS +util_scan_get_chan_from_he_6g_params(struct wlan_objmgr_pdev *pdev, + struct scan_cache_entry *scan_params, + qdf_freq_t *chan_freq, + bool *he_6g_dup_bcon, + uint8_t band_mask) +{ + return QDF_STATUS_SUCCESS; +} static inline enum wlan_phymode util_scan_get_phymode_6g(struct wlan_objmgr_pdev *pdev, struct scan_cache_entry *scan_params) @@ -842,12 +874,28 @@ util_scan_parse_vendor_ie(struct scan_cache_entry *scan_params, } static QDF_STATUS -util_scan_populate_bcn_ie_list(struct scan_cache_entry *scan_params, - uint8_t *chan_idx) +util_scan_populate_bcn_ie_list(struct wlan_objmgr_pdev *pdev, + struct scan_cache_entry *scan_params, + qdf_freq_t *chan_freq, uint8_t band_mask) { struct ie_header *ie, *sub_ie; uint32_t ie_len, sub_ie_len; QDF_STATUS status; + uint8_t chan_idx; + struct wlan_scan_obj *scan_obj; + struct wlan_objmgr_psoc *psoc; + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + scm_err("psoc is NULL"); + return QDF_STATUS_E_INVAL; + } + + scan_obj = wlan_psoc_get_scan_obj(psoc); + if (!scan_obj) { + scm_err("scan_obj is NULL"); + return QDF_STATUS_E_INVAL; + } ie_len = util_scan_entry_ie_len(scan_params); ie = (struct ie_header *) @@ -883,8 +931,18 @@ util_scan_populate_bcn_ie_list(struct scan_cache_entry *scan_params, if (ie->ie_len != WLAN_DS_PARAM_IE_MAX_LEN) return QDF_STATUS_E_INVAL; scan_params->ie_list.ds_param = (uint8_t *)ie; - *chan_idx = + chan_idx = ((struct ds_ie *)ie)->cur_chan; + *chan_freq = wlan_reg_chan_band_to_freq(pdev, chan_idx, + band_mask); + /* Drop if invalid freq */ + if (scan_obj->drop_bcn_on_invalid_freq && + wlan_reg_is_disable_for_freq(pdev, *chan_freq)) { + scm_debug_rl("%pM: Drop as invalid channel %d freq %d in DS IE", + scan_params->bssid.bytes, + chan_idx, *chan_freq); + return QDF_STATUS_E_INVAL; + } break; case WLAN_ELEMID_TIM: if (ie->ie_len < WLAN_TIM_IE_MIN_LENGTH) @@ -961,9 +1019,18 @@ util_scan_populate_bcn_ie_list(struct scan_cache_entry *scan_params, goto err; scan_params->ie_list.htinfo = (uint8_t *)&(((struct wlan_ie_htinfo *) ie)->hi_ie); - *chan_idx = - ((struct wlan_ie_htinfo_cmn *) - (scan_params->ie_list.htinfo))->hi_ctrlchannel; + chan_idx = ((struct wlan_ie_htinfo_cmn *) + (scan_params->ie_list.htinfo))->hi_ctrlchannel; + *chan_freq = wlan_reg_chan_band_to_freq(pdev, chan_idx, + band_mask); + /* Drop if invalid freq */ + if (scan_obj->drop_bcn_on_invalid_freq && + wlan_reg_is_disable_for_freq(pdev, *chan_freq)) { + scm_debug_rl("%pM: Drop as invalid channel %d freq %d in HT_INFO IE", + scan_params->bssid.bytes, + chan_idx, *chan_freq); + return QDF_STATUS_E_INVAL; + } break; case WLAN_ELEMID_WAPI: if (ie->ie_len < WLAN_WAPI_IE_MIN_LEN) @@ -1412,8 +1479,10 @@ util_scan_gen_scan_entry(struct wlan_objmgr_pdev *pdev, struct scan_cache_entry *scan_entry; struct qbss_load_ie *qbss_load; struct scan_cache_node *scan_node; - uint8_t i, chan_idx = 0; + uint8_t i; + qdf_freq_t chan_freq = 0; bool he_6g_dup_bcon = false; + uint8_t band_mask; scan_entry = qdf_mem_malloc_atomic(sizeof(*scan_entry)); if (!scan_entry) { @@ -1454,6 +1523,7 @@ util_scan_gen_scan_entry(struct wlan_objmgr_pdev *pdev, /* Copy per chain rssi to scan entry */ qdf_mem_copy(scan_entry->per_chain_rssi, rx_param->rssi_ctl, WLAN_MGMT_TXRX_HOST_MAX_ANTENNA); + band_mask = BIT(wlan_reg_freq_to_band(rx_param->chan_freq)); if (!wlan_psoc_nif_fw_ext_cap_get(wlan_pdev_get_psoc(pdev), WLAN_SOC_CEXT_HW_DB2DBM)) { @@ -1490,9 +1560,11 @@ util_scan_gen_scan_entry(struct wlan_objmgr_pdev *pdev, scan_entry->raw_frame.len = frame_len; qdf_mem_copy(scan_entry->raw_frame.ptr, frame, frame_len); - status = util_scan_populate_bcn_ie_list(scan_entry, &chan_idx); + status = util_scan_populate_bcn_ie_list(pdev, scan_entry, &chan_freq, + band_mask); if (QDF_IS_STATUS_ERROR(status)) { - scm_debug("failed to parse beacon IE"); + scm_debug("%pM: failed to parse beacon IE", + scan_entry->bssid.bytes); qdf_mem_free(scan_entry->raw_frame.ptr); qdf_mem_free(scan_entry); return QDF_STATUS_E_FAILURE; @@ -1510,19 +1582,21 @@ util_scan_gen_scan_entry(struct wlan_objmgr_pdev *pdev, if (scan_entry->ie_list.p2p) scan_entry->is_p2p = true; - if (!chan_idx && util_scan_entry_hecap(scan_entry)) - util_scan_get_chan_from_he_6g_params(scan_entry, &chan_idx, - &he_6g_dup_bcon); - - if (chan_idx) { - uint8_t band_mask = BIT(wlan_reg_freq_to_band( - rx_param->chan_freq)); - - scan_entry->channel.chan_freq = - wlan_reg_chan_band_to_freq( - pdev, chan_idx, - band_mask); + if (!chan_freq && util_scan_entry_hecap(scan_entry)) { + status = util_scan_get_chan_from_he_6g_params(pdev, scan_entry, + &chan_freq, + &he_6g_dup_bcon, + band_mask); + if (QDF_IS_STATUS_ERROR(status)) { + qdf_mem_free(scan_entry->raw_frame.ptr); + qdf_mem_free(scan_entry); + return QDF_STATUS_E_FAILURE; + } } + + if (chan_freq) + scan_entry->channel.chan_freq = chan_freq; + /* If no channel info is present in beacon use meta channel */ if (!scan_entry->channel.chan_freq) { scan_entry->channel.chan_freq = rx_param->chan_freq;