From b858abf06439625ce97dade46f599956d170e6e3 Mon Sep 17 00:00:00 2001
From: Pradeep Kumar Chitrapu <pradeepc@codeaurora.org>
Date: Thu, 18 Jun 2020 21:51:13 -0700
Subject: [PATCH] ath11k: fix for accepting bcast presp in GHz scan

A 6GHZ AP may respond to Probe Request frame with having Address 1
field of the Probe Response frame set to the broadcast address when
AP is not indicating its actual SSID in the SSID element of its
Beacon frames. So, without accepting broadcast probe responses in
scan, APs will not be discoverable.

Signed-off-by: Pradeep Kumar Chitrapu <pradeepc@codeaurora.org>
---
 drivers/net/wireless/ath/ath11k/core.h  |  2 +-
 drivers/net/wireless/ath/ath11k/dp_rx.c |  5 ++++-
 drivers/net/wireless/ath/ath11k/mac.c   |  1 +
 drivers/net/wireless/ath/ath11k/wmi.c   |  7 ++++++-
 net/mac80211/scan.c                     | 23 ++++++++++++-----------
 5 files changed, 24 insertions(+), 14 deletions(-)

--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -409,9 +409,9 @@ struct ath11k_sta {
 };
 
 #define ATH11K_MIN_5G_FREQ 4150
-#define ATH11K_MIN_6G_FREQ 5945
-#define ATH11K_MAX_6G_FREQ 7115
-#define ATH11K_NUM_CHANS 100
+#define ATH11K_MIN_6G_FREQ 5925
+#define ATH11K_MAX_6G_FREQ 7125
+#define ATH11K_NUM_CHANS 101
 #define ATH11K_MAX_5G_CHAN 173
 
 enum ath11k_state {
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -2518,7 +2518,7 @@ static void ath11k_dp_rx_h_ppdu(struct a
 	channel_num = meta_data;
 	center_freq = meta_data >> 16;
 
-	if (center_freq >= 5935 && center_freq <= 7105) {
+	if (center_freq >= ATH11K_MIN_6G_FREQ && center_freq <= ATH11K_MAX_6G_FREQ) {
 		rx_status->band = NL80211_BAND_6GHZ;
 	} else if (channel_num >= 1 && channel_num <= 14) {
 		rx_status->band = NL80211_BAND_2GHZ;
@@ -2540,6 +2540,9 @@ static void ath11k_dp_rx_h_ppdu(struct a
 	rx_status->freq = ieee80211_channel_to_frequency(channel_num,
 							 rx_status->band);
 
+	if (rx_status->band == NL80211_BAND_6GHZ)
+		rx_status->freq = center_freq;
+
 	ath11k_dp_rx_h_rate(ar, rx_desc, rx_status);
 }
 
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -96,6 +96,7 @@ static const struct ieee80211_channel at
 
 static const struct ieee80211_channel ath11k_6ghz_channels[] = {
 	CHAN6G(1, 5955, 0),
+	CHAN6G(2, 5935, 0), /* op_class = 136 */
 	CHAN6G(5, 5975, 0),
 	CHAN6G(9, 5995, 0),
 	CHAN6G(13, 6015, 0),
@@ -7087,7 +7088,13 @@ static int ath11k_mac_op_get_survey(stru
 
 	if (!sband)
 		sband = hw->wiphy->bands[NL80211_BAND_5GHZ];
+	if (sband && idx >= sband->n_channels) {
+		idx -= sband->n_channels;
+		sband = NULL;
+	}
 
+	if (!sband)
+		sband = hw->wiphy->bands[NL80211_BAND_6GHZ];
 	if (!sband || idx >= sband->n_channels) {
 		ret = -ENOENT;
 		goto exit;
@@ -7340,7 +7347,8 @@ static int ath11k_mac_setup_channels_rat
 	}
 
 	if (supported_bands & WMI_HOST_WLAN_5G_CAP) {
-		if (reg_cap->high_5ghz_chan >= ATH11K_MAX_6G_FREQ) {
+		if (reg_cap->high_5ghz_chan > ATH11K_MIN_6G_FREQ &&
+		    reg_cap->high_5ghz_chan <= ATH11K_MAX_6G_FREQ) {
 			channels = kmemdup(ath11k_6ghz_channels,
 					   sizeof(ath11k_6ghz_channels), GFP_KERNEL);
 			if (!channels) {
@@ -7361,7 +7369,8 @@ static int ath11k_mac_setup_channels_rat
 						  reg_cap->high_5ghz_chan);
 		}
 
-		if (reg_cap->low_5ghz_chan < ATH11K_MIN_6G_FREQ) {
+		if (reg_cap->low_5ghz_chan < ATH11K_MIN_6G_FREQ &&
+		    reg_cap->low_5ghz_chan >= ATH11K_MIN_5G_FREQ) {
 			channels = kmemdup(ath11k_5ghz_channels,
 					   sizeof(ath11k_5ghz_channels),
 					   GFP_KERNEL);
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -2307,25 +2307,23 @@ int ath11k_wmi_send_scan_start_cmd(struc
 
 	if (params->num_hint_bssid)
 		len += TLV_HDR_SIZE +
-		       params->num_hint_bssid * sizeof(struct hint_bssid);
+			params->num_hint_bssid * sizeof(struct hint_bssid);
 
 	if (params->num_hint_s_ssid)
 		len += TLV_HDR_SIZE +
-		       params->num_hint_s_ssid * sizeof(struct hint_short_ssid);
+			params->num_hint_s_ssid * sizeof(struct hint_short_ssid);
 
 	len += TLV_HDR_SIZE;
 	if (params->scan_f_en_ie_whitelist_in_probe)
 		len += params->ie_whitelist.num_vendor_oui *
-				sizeof(struct wmi_vendor_oui);
-
+			sizeof(struct wmi_vendor_oui);
 	len += TLV_HDR_SIZE;
 	if (params->scan_f_wide_band)
 		phymode_roundup =
 			roundup(params->chan_list.num_chan * sizeof(u8),
-				sizeof(u32));
+					sizeof(u32));
 
 	len += phymode_roundup;
-
 	skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
 	if (!skb)
 		return -ENOMEM;
@@ -2362,6 +2360,7 @@ int ath11k_wmi_send_scan_start_cmd(struc
 	cmd->num_ssids = params->num_ssids;
 	cmd->ie_len = params->extraie.len;
 	cmd->n_probes = params->n_probes;
+	cmd->scan_ctrl_flags_ext = params->scan_ctrl_flags_ext;
 
 	ptr += sizeof(*cmd);
 
@@ -2427,39 +2426,6 @@ int ath11k_wmi_send_scan_start_cmd(struc
 
 	ptr += extraie_len_with_pad;
 
-	if (params->num_hint_s_ssid) {
-		len = params->num_hint_s_ssid * sizeof(struct hint_short_ssid);
-		tlv = ptr;
-		tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_FIXED_STRUCT) |
-			      FIELD_PREP(WMI_TLV_LEN, len);
-		ptr += TLV_HDR_SIZE;
-		s_ssid = ptr;
-		for (i = 0; i < params->num_hint_s_ssid; ++i) {
-			s_ssid->freq_flags = params->hint_s_ssid[i].freq_flags;
-			s_ssid->short_ssid = params->hint_s_ssid[i].short_ssid;
-			s_ssid++;
-		}
-		ptr += len;
-	}
-
-	if (params->num_hint_bssid) {
-		len = params->num_hint_bssid * sizeof(struct hint_bssid);
-		tlv = ptr;
-		tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_FIXED_STRUCT) |
-			      FIELD_PREP(WMI_TLV_LEN, len);
-		ptr += TLV_HDR_SIZE;
-		hint_bssid = ptr;
-		for (i = 0; i < params->num_hint_bssid; ++i) {
-			hint_bssid->freq_flags =
-				params->hint_bssid[i].freq_flags;
-			ether_addr_copy(&params->hint_bssid[i].bssid.addr[0],
-					&hint_bssid->bssid.addr[0]);
-			hint_bssid++;
-		}
-	}
-
-	ptr += extraie_len_with_pad;
-
 	len = params->ie_whitelist.num_vendor_oui * sizeof(struct wmi_vendor_oui);
 	tlv = ptr;
 	tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_STRUCT) |
@@ -2490,6 +2456,36 @@ int ath11k_wmi_send_scan_start_cmd(struc
 	}
 	ptr += phymode_roundup;
 
+	if (params->num_hint_s_ssid) {
+		len = params->num_hint_s_ssid * sizeof(struct hint_short_ssid);
+		tlv = ptr;
+		tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_FIXED_STRUCT) |
+			      FIELD_PREP(WMI_TLV_LEN, len);
+		ptr += TLV_HDR_SIZE;
+		s_ssid = ptr;
+		for (i = 0; i < params->num_hint_s_ssid; ++i) {
+			s_ssid->freq_flags = params->hint_s_ssid[i].freq_flags;
+			s_ssid->short_ssid = params->hint_s_ssid[i].short_ssid;
+			s_ssid++;
+		}
+		ptr += len;
+	}
+
+	if (params->num_hint_bssid) {
+		len = params->num_hint_bssid * sizeof(struct hint_bssid);
+		tlv = ptr;
+		tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_FIXED_STRUCT) |
+			      FIELD_PREP(WMI_TLV_LEN, len);
+		ptr += TLV_HDR_SIZE;
+		hint_bssid = ptr;
+		for (i = 0; i < params->num_hint_bssid; ++i) {
+			hint_bssid->freq_flags =
+				params->hint_bssid[i].freq_flags;
+			ether_addr_copy(&params->hint_bssid[i].bssid.addr[0],
+					&hint_bssid->bssid.addr[0]);
+			hint_bssid++;
+		}
+	}
 	ret = ath11k_wmi_cmd_send(wmi, skb,
 				  WMI_START_SCAN_CMDID);
 	if (ret) {
@@ -5160,7 +5156,7 @@ static int ath11k_pull_mgmt_rx_params_tl
 	}
 
 	hdr->pdev_id =  ev->pdev_id;
-	hdr->chan_freq = ev->chan_freq;
+	hdr->chan_freq = ev->chan_freq?ev->chan_freq:0;;
 	hdr->channel =  ev->channel;
 	hdr->snr =  ev->snr;
 	hdr->rate =  ev->rate;
@@ -6653,7 +6649,8 @@ static void ath11k_mgmt_rx_event(struct
 	if (rx_ev.status & WMI_RX_STATUS_ERR_MIC)
 		status->flag |= RX_FLAG_MMIC_ERROR;
 
-	if (rx_ev.chan_freq >= ATH11K_MIN_6G_FREQ) {
+	if (rx_ev.chan_freq >= ATH11K_MIN_6G_FREQ &&
+	    rx_ev.chan_freq <= ATH11K_MAX_6G_FREQ) {
 		status->band = NL80211_BAND_6GHZ;
 	} else if (rx_ev.channel >= 1 && rx_ev.channel <= 14) {
 		status->band = NL80211_BAND_2GHZ;
@@ -6677,6 +6674,10 @@ static void ath11k_mgmt_rx_event(struct
 
 	status->freq = ieee80211_channel_to_frequency(rx_ev.channel,
 						      status->band);
+
+	if (status->band == NL80211_BAND_6GHZ)
+		status->freq = rx_ev.chan_freq;
+
 	status->signal = rx_ev.snr + ATH11K_DEFAULT_NOISE_FLOOR;
 	status->rate_idx = ath11k_mac_bitrate_to_idx(sband, rx_ev.rate / 100);
 
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -231,13 +231,14 @@ ieee80211_bss_info_update(struct ieee802
 }
 
 static bool ieee80211_scan_accept_presp(struct ieee80211_sub_if_data *sdata,
-					u32 scan_flags, const u8 *da)
+					u32 scan_flags, const u8 *da,
+					struct ieee80211_channel *channel)
 {
 	if (!sdata)
 		return false;
 	/* accept broadcast for OCE */
-	if (scan_flags & NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP &&
-	    is_broadcast_ether_addr(da))
+	if ((scan_flags & NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP ||
+	    channel->band == NL80211_BAND_6GHZ) && is_broadcast_ether_addr(da))
 		return true;
 	if (scan_flags & NL80211_SCAN_FLAG_RANDOM_ADDR)
 		return true;
@@ -266,6 +267,12 @@ void ieee80211_scan_rx(struct ieee80211_
 	if (likely(!sdata1 && !sdata2))
 		return;
 
+	channel = ieee80211_get_channel_khz(local->hw.wiphy,
+					ieee80211_rx_status_to_khz(rx_status));
+
+	if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
+		return;
+
 	if (ieee80211_is_probe_resp(mgmt->frame_control)) {
 		struct cfg80211_scan_request *scan_req;
 		struct cfg80211_sched_scan_request *sched_scan_req;
@@ -284,18 +291,12 @@ void ieee80211_scan_rx(struct ieee80211_
 		 * unless scanning with randomised address
 		 */
 		if (!ieee80211_scan_accept_presp(sdata1, scan_req_flags,
-						 mgmt->da) &&
+						 mgmt->da, channel) &&
 		    !ieee80211_scan_accept_presp(sdata2, sched_scan_req_flags,
-						 mgmt->da))
+						 mgmt->da, channel))
 			return;
 	}
 
-	channel = ieee80211_get_channel_khz(local->hw.wiphy,
-					ieee80211_rx_status_to_khz(rx_status));
-
-	if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
-		return;
-
 	bss = ieee80211_bss_info_update(local, rx_status,
 					mgmt, skb->len,
 					channel);
