Browse Source

qcacmn: Fix 4.9GHz cfg80211 issues

Send correct channel list to Firmware. When cfg80211 is enabled, STA
is scanning in a set of wrong channels. When scan callback happens
from cfg80211 module the cfg80211 module gives us the channel numbers.
There are some channel numbers which are same in both 5GHz and in
2.4Ghz bands. For example, channel number 1 maps to frequency 4942MHz
in 5GHz band, but in 2.4GHz band channel number 1 maps to frequency
2412MHz. So cfg80211 may give us a wrong channel number. Since we have
the exact frequency of the channel we should use that instead of the
one given by cfg80211.
The channel object given to the driver by cfg80211 during scan callback
is the same as the one registered to cfg80211 by the driver. So we can
use the channel frequency inside the channel object for scan which is
not changed by the cfg80211 module.

Use regdb function to convert channel number to frequency while receiving
scan entries from FW. Use pdev band (5/2.4GHz) information to map to
correct 2.4Ghz/5Ghz channel frequency.

Half/Quarter rate flags in the scan_ctrl_flags are not set. Set
Half/Quarter rate flags in scan_ctrl_flags.

Change-Id: I9df8f0e90938f86f6987574f8259a5cf66b672aa
CRs-Fixed: 2180273
Shashikala Prabhu 7 years ago
parent
commit
48ecda84bf

+ 4 - 1
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;
 };
 
 /**

+ 16 - 22
os_if/linux/scan/src/wlan_cfg80211_scan.c

@@ -37,6 +37,7 @@
 #ifdef WLAN_POLICY_MGR_ENABLE
 #include <wlan_policy_mgr_api.h>
 #endif
+#include <wlan_reg_services_api.h>
 
 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);

+ 89 - 2
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

+ 25 - 0
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

+ 2 - 0
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

+ 7 - 0
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

+ 9 - 0
umac/scan/dispatcher/src/wlan_scan_utils_api.c

@@ -25,6 +25,7 @@
 #include <wlan_scan_utils_api.h>
 #include <../../core/src/wlan_scan_cache_db.h>
 #include <../../core/src/wlan_scan_main.h>
+#include <wlan_reg_services_api.h>
 
 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)