diff --git a/os_if/linux/scan/inc/wlan_cfg80211_scan.h b/os_if/linux/scan/inc/wlan_cfg80211_scan.h index ea203bd9553b..6a849cf2a8aa 100644 --- a/os_if/linux/scan/inc/wlan_cfg80211_scan.h +++ b/os_if/linux/scan/inc/wlan_cfg80211_scan.h @@ -119,11 +119,14 @@ struct scan_req { * struct scan_params - Scan params * @source: scan request source * @default_ie: default scan ie - * + * @half_rate: Half rate flag + * @quarter_rate: Quarter rate flag */ struct scan_params { uint8_t source; struct element_info default_ie; + bool half_rate; + bool quarter_rate; }; /** diff --git a/os_if/linux/scan/src/wlan_cfg80211_scan.c b/os_if/linux/scan/src/wlan_cfg80211_scan.c index 7de207c18fba..c7801d27bfac 100644 --- a/os_if/linux/scan/src/wlan_cfg80211_scan.c +++ b/os_if/linux/scan/src/wlan_cfg80211_scan.c @@ -37,6 +37,7 @@ #ifdef WLAN_POLICY_MGR_ENABLE #include #endif +#include static const struct nla_policy scan_policy[QCA_WLAN_VENDOR_ATTR_SCAN_MAX + 1] = { @@ -1212,6 +1213,7 @@ int wlan_cfg80211_scan(struct wlan_objmgr_pdev *pdev, uint8_t i; int status; uint8_t num_chan = 0, channel; + uint32_t c_freq; struct wlan_objmgr_vdev *vdev; wlan_scan_requester req_id; struct pdev_osif_priv *osif_priv; @@ -1293,6 +1295,11 @@ int wlan_cfg80211_scan(struct wlan_objmgr_pdev *pdev, (wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_GO_MODE)) req->scan_req.scan_f_passive = false; + if (params->half_rate) + req->scan_req.scan_f_half_rate = true; + else if (params->quarter_rate) + req->scan_req.scan_f_quarter_rate = true; + if ((request->n_ssids == 1) && request->ssids && !qdf_mem_cmp(&request->ssids[0], "DIRECT-", 7)) is_p2p_scan = true; @@ -1332,7 +1339,8 @@ int wlan_cfg80211_scan(struct wlan_objmgr_pdev *pdev, for (i = 0; i < request->n_channels; i++) { channel = request->channels[i]->hw_value; - if (wlan_is_dsrc_channel(wlan_chan_to_freq(channel))) + c_freq = wlan_reg_chan_to_freq(pdev, channel); + if (wlan_is_dsrc_channel(c_freq)) continue; #ifdef WLAN_POLICY_MGR_ENABLE if (ap_or_go_present) { @@ -1354,9 +1362,8 @@ int wlan_cfg80211_scan(struct wlan_objmgr_pdev *pdev, } #endif len += snprintf(chl + len, 5, "%d ", channel); - req->scan_req.chan_list.chan[num_chan].freq = - wlan_chan_to_freq(channel); - band = util_scan_scm_chan_to_band(channel); + req->scan_req.chan_list.chan[num_chan].freq = c_freq; + band = util_scan_scm_freq_to_band(c_freq); if (band == WLAN_BAND_2_4_GHZ) req->scan_req.chan_list.chan[num_chan].phymode = SCAN_PHY_MODE_11G; @@ -1610,28 +1617,15 @@ int wlan_vendor_abort_scan(struct wlan_objmgr_pdev *pdev, } static inline struct ieee80211_channel * -wlan_get_ieee80211_channel(struct wiphy *wiphy, int chan_no) +wlan_get_ieee80211_channel(struct wiphy *wiphy, + struct wlan_objmgr_pdev *pdev, + int chan_no) { unsigned int freq; struct ieee80211_channel *chan; - if (WLAN_CHAN_IS_2GHZ(chan_no) && - (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) { - freq = - ieee80211_channel_to_frequency(chan_no, - NL80211_BAND_2GHZ); - } else if (WLAN_CHAN_IS_5GHZ(chan_no) && - (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) { - freq = - ieee80211_channel_to_frequency(chan_no, - NL80211_BAND_5GHZ); - } else { - cfg80211_err("Invalid chan_no %d", chan_no); - return NULL; - } - + freq = wlan_reg_chan_to_freq(pdev, chan_no); chan = ieee80211_get_channel(wiphy, freq); - if (!chan) cfg80211_err("chan is NULL, chan_no: %d freq: %d", chan_no, freq); @@ -1806,7 +1800,7 @@ void wlan_cfg80211_inform_bss_frame(struct wlan_objmgr_pdev *pdev, */ bss_data.rssi = scan_params->rssi_raw; - bss_data.chan = wlan_get_ieee80211_channel(wiphy, + bss_data.chan = wlan_get_ieee80211_channel(wiphy, pdev, scan_params->channel.chan_idx); if (!bss_data.chan) { qdf_mem_free(bss_data.mgmt); diff --git a/umac/regulatory/core/src/reg_services.c b/umac/regulatory/core/src/reg_services.c index 267e1bc78798..1f1d54b0037e 100644 --- a/umac/regulatory/core/src/reg_services.c +++ b/umac/regulatory/core/src/reg_services.c @@ -1759,8 +1759,17 @@ uint32_t reg_chan_to_freq(struct wlan_objmgr_pdev *pdev, chan_list = pdev_priv_obj->cur_chan_list; for (count = 0; count < NUM_CHANNELS; count++) - if (chan_list[count].chan_num == chan_num) - return chan_list[count].center_freq; + if (chan_list[count].chan_num == chan_num) { + if (reg_chan_in_range(chan_list, + pdev_priv_obj->range_2g_low, + pdev_priv_obj->range_2g_high, + pdev_priv_obj->range_5g_low, + pdev_priv_obj->range_5g_high, + count)) { + return chan_list[count].center_freq; + } + } + reg_err("invalid channel %d", chan_num); @@ -2283,6 +2292,84 @@ reg_modify_chan_list_for_freq_range(struct regulatory_channel *chan_list, } } +bool reg_chan_in_range(struct regulatory_channel *chan_list, + uint32_t low_freq_2g, + uint32_t high_freq_2g, + uint32_t low_freq_5g, + uint32_t high_freq_5g, + enum channel_enum ch_enum) +{ + uint32_t low_limit_2g = NUM_CHANNELS; + uint32_t high_limit_2g = NUM_CHANNELS; + uint32_t low_limit_5g = NUM_CHANNELS; + uint32_t high_limit_5g = NUM_CHANNELS; + bool chan_in_range; + enum channel_enum chan_enum; + uint16_t min_bw; + uint32_t center_freq; + + for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++) { + min_bw = chan_list[chan_enum].min_bw; + center_freq = chan_list[chan_enum].center_freq; + + if ((center_freq - min_bw/2) >= low_freq_2g) { + low_limit_2g = chan_enum; + break; + } + } + + for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++) { + min_bw = chan_list[chan_enum].min_bw; + center_freq = chan_list[chan_enum].center_freq; + + if ((center_freq - min_bw/2) >= low_freq_5g) { + low_limit_5g = chan_enum; + break; + } + } + + for (chan_enum = NUM_CHANNELS - 1; chan_enum >= 0; chan_enum--) { + min_bw = chan_list[chan_enum].min_bw; + center_freq = chan_list[chan_enum].center_freq; + + if (center_freq + min_bw/2 <= high_freq_2g) { + high_limit_2g = chan_enum; + break; + } + if (chan_enum == 0) + break; + } + + for (chan_enum = NUM_CHANNELS - 1; chan_enum >= 0; chan_enum--) { + min_bw = chan_list[chan_enum].min_bw; + center_freq = chan_list[chan_enum].center_freq; + + if (center_freq + min_bw/2 <= high_freq_5g) { + high_limit_5g = chan_enum; + break; + } + if (chan_enum == 0) + break; + } + + chan_in_range = false; + if ((low_limit_2g <= ch_enum) && + (high_limit_2g >= ch_enum) && + (low_limit_2g != NUM_CHANNELS) && + (high_limit_2g != NUM_CHANNELS)) + chan_in_range = true; + if ((low_limit_5g <= ch_enum) && + (high_limit_5g >= ch_enum) && + (low_limit_5g != NUM_CHANNELS) && + (high_limit_5g != NUM_CHANNELS)) + chan_in_range = true; + + if (chan_in_range) + return true; + else + return false; +} + static void reg_init_pdev_mas_chan_list(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj, struct mas_chan_params diff --git a/umac/regulatory/core/src/reg_services.h b/umac/regulatory/core/src/reg_services.h index 41c1f4b47bfd..57344ad642db 100644 --- a/umac/regulatory/core/src/reg_services.h +++ b/umac/regulatory/core/src/reg_services.h @@ -47,6 +47,13 @@ ((chan_num >= REG_MIN_24GHZ_CH_NUM) && \ (chan_num <= REG_MAX_24GHZ_CH_NUM)) +#define REG_MIN_24GHZ_CH_FREQ channel_map[MIN_24GHZ_CHANNEL].center_freq +#define REG_MAX_24GHZ_CH_FREQ channel_map[MAX_24GHZ_CHANNEL].center_freq + +#define REG_IS_24GHZ_CH_FREQ(freq) \ + ((freq >= REG_MIN_24GHZ_CH_FREQ) && \ + (freq <= REG_MAX_24GHZ_CH_FREQ)) + #ifndef CONFIG_LEGACY_CHAN_ENUM #define REG_MIN_49GHZ_CH_FREQ channel_map[MIN_49GHZ_CHANNEL].center_freq #define REG_MAX_49GHZ_CH_FREQ channel_map[MAX_49GHZ_CHANNEL].center_freq @@ -499,4 +506,22 @@ QDF_STATUS reg_set_hal_reg_cap(struct wlan_objmgr_psoc *psoc, struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap, uint16_t phy_cnt); +/** + * reg_chan_in_range() - Check if the given channel is in pdev's channel range + * @chan_list: Pointer to regulatory channel list. + * @low_freq_2g: Low frequency 2G. + * @high_freq_2g: High frequency 2G. + * @low_freq_5g: Low frequency 5G. + * @high_freq_5g: High frequency 5G. + * @ch_enum: Channel enum. + * + * Return: true if ch_enum is with in pdev's channel range, else false. + */ +bool reg_chan_in_range(struct regulatory_channel *chan_list, + uint32_t low_freq_2g, + uint32_t high_freq_2g, + uint32_t low_freq_5g, + uint32_t high_freq_5g, + enum channel_enum ch_enum); + #endif diff --git a/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h b/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h index e5dcd3bd63ad..746385fea8db 100644 --- a/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h +++ b/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h @@ -41,6 +41,8 @@ #define WLAN_REG_IS_5GHZ_CH(chan) REG_IS_5GHZ_CH(chan) #define WLAN_REG_IS_11P_CH(chan) REG_IS_11P_CH(chan) +#define WLAN_REG_IS_24GHZ_CH_FREQ(freq) REG_IS_24GHZ_CH_FREQ(freq) + #ifndef CONFIG_LEGACY_CHAN_ENUM #define WLAN_REG_IS_49GHZ_FREQ(freq) REG_IS_49GHZ_FREQ(freq) #endif diff --git a/umac/scan/dispatcher/inc/wlan_scan_utils_api.h b/umac/scan/dispatcher/inc/wlan_scan_utils_api.h index aff016e069f9..040e525d3bdc 100644 --- a/umac/scan/dispatcher/inc/wlan_scan_utils_api.h +++ b/umac/scan/dispatcher/inc/wlan_scan_utils_api.h @@ -1444,4 +1444,11 @@ util_scan_entry_mbo_oce(struct scan_cache_entry *scan_entry) */ enum wlan_band util_scan_scm_chan_to_band(uint32_t chan); +/** + * util_scan_scm_freq_to_band() - API to get band from frequency + * @freq: Channel frequency + * + * Return: Band information as per frequency + */ +enum wlan_band util_scan_scm_freq_to_band(uint16_t freq); #endif diff --git a/umac/scan/dispatcher/src/wlan_scan_utils_api.c b/umac/scan/dispatcher/src/wlan_scan_utils_api.c index 716f04b51947..1eb298627e19 100644 --- a/umac/scan/dispatcher/src/wlan_scan_utils_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_utils_api.c @@ -25,6 +25,7 @@ #include #include <../../core/src/wlan_scan_cache_db.h> #include <../../core/src/wlan_scan_main.h> +#include const char* util_scan_get_ev_type_name(enum scan_event_type type) @@ -108,6 +109,14 @@ enum wlan_band util_scan_scm_chan_to_band(uint32_t chan) return WLAN_BAND_5_GHZ; } +enum wlan_band util_scan_scm_freq_to_band(uint16_t freq) +{ + if (WLAN_REG_IS_24GHZ_CH_FREQ(freq)) + return WLAN_BAND_2_4_GHZ; + + return WLAN_BAND_5_GHZ; +} + bool util_is_scan_entry_match( struct scan_cache_entry *entry1, struct scan_cache_entry *entry2)