Commit c8cb5b85 authored by Tova Mussai's avatar Tova Mussai Committed by Johannes Berg

nl80211/cfg80211: support 6 GHz scanning

Support 6 GHz scanning, by
 * a new scan flag to scan for colocated BSSes advertised
   by (and found) APs on 2.4 & 5 GHz
 * doing the necessary reduced neighbor report parsing for
   this, to find them
 * adding the ability to split the scan request in case the
   device by itself cannot support this.

Also add some necessary bits in mac80211 to not break with
these changes.
Signed-off-by: default avatarTova Mussai <tova.mussai@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Link: https://lore.kernel.org/r/20200918113313.232917c93af9.Ida22f0212f9122f47094d81659e879a50434a6a2@changeidSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent dba0491f
...@@ -2095,6 +2095,27 @@ struct cfg80211_scan_info { ...@@ -2095,6 +2095,27 @@ struct cfg80211_scan_info {
bool aborted; bool aborted;
}; };
/**
* struct cfg80211_scan_6ghz_params - relevant for 6 GHz only
*
* @short_bssid: short ssid to scan for
* @bssid: bssid to scan for
* @channel_idx: idx of the channel in the channel array in the scan request
* which the above info relvant to
* @unsolicited_probe: the AP transmits unsolicited probe response every 20 TU
* @short_ssid_valid: short_ssid is valid and can be used
* @psc_no_listen: when set, and the channel is a PSC channel, no need to wait
* 20 TUs before starting to send probe requests.
*/
struct cfg80211_scan_6ghz_params {
u32 short_ssid;
u32 channel_idx;
u8 bssid[ETH_ALEN];
bool unsolicited_probe;
bool short_ssid_valid;
bool psc_no_listen;
};
/** /**
* struct cfg80211_scan_request - scan request description * struct cfg80211_scan_request - scan request description
* *
...@@ -2122,6 +2143,10 @@ struct cfg80211_scan_info { ...@@ -2122,6 +2143,10 @@ struct cfg80211_scan_info {
* @mac_addr_mask: MAC address mask used with randomisation, bits that * @mac_addr_mask: MAC address mask used with randomisation, bits that
* are 0 in the mask should be randomised, bits that are 1 should * are 0 in the mask should be randomised, bits that are 1 should
* be taken from the @mac_addr * be taken from the @mac_addr
* @scan_6ghz: relevant for split scan request only,
* true if this is the second scan request
* @n_6ghz_params: number of 6 GHz params
* @scan_6ghz_params: 6 GHz params
* @bssid: BSSID to scan for (most commonly, the wildcard BSSID) * @bssid: BSSID to scan for (most commonly, the wildcard BSSID)
*/ */
struct cfg80211_scan_request { struct cfg80211_scan_request {
...@@ -2149,6 +2174,9 @@ struct cfg80211_scan_request { ...@@ -2149,6 +2174,9 @@ struct cfg80211_scan_request {
struct cfg80211_scan_info info; struct cfg80211_scan_info info;
bool notified; bool notified;
bool no_cck; bool no_cck;
bool scan_6ghz;
u32 n_6ghz_params;
struct cfg80211_scan_6ghz_params *scan_6ghz_params;
/* keep last */ /* keep last */
struct ieee80211_channel *channels[]; struct ieee80211_channel *channels[];
...@@ -4217,6 +4245,8 @@ struct cfg80211_ops { ...@@ -4217,6 +4245,8 @@ struct cfg80211_ops {
/** /**
* enum wiphy_flags - wiphy capability flags * enum wiphy_flags - wiphy capability flags
* *
* @WIPHY_FLAG_SPLIT_SCAN_6GHZ: if set to true, the scan request will be split
* into two, first for legacy bands and second for UHB.
* @WIPHY_FLAG_NETNS_OK: if not set, do not allow changing the netns of this * @WIPHY_FLAG_NETNS_OK: if not set, do not allow changing the netns of this
* wiphy at all * wiphy at all
* @WIPHY_FLAG_PS_ON_BY_DEFAULT: if set to true, powersave will be enabled * @WIPHY_FLAG_PS_ON_BY_DEFAULT: if set to true, powersave will be enabled
...@@ -4260,7 +4290,7 @@ struct cfg80211_ops { ...@@ -4260,7 +4290,7 @@ struct cfg80211_ops {
enum wiphy_flags { enum wiphy_flags {
WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK = BIT(0), WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK = BIT(0),
/* use hole at 1 */ /* use hole at 1 */
/* use hole at 2 */ WIPHY_FLAG_SPLIT_SCAN_6GHZ = BIT(2),
WIPHY_FLAG_NETNS_OK = BIT(3), WIPHY_FLAG_NETNS_OK = BIT(3),
WIPHY_FLAG_PS_ON_BY_DEFAULT = BIT(4), WIPHY_FLAG_PS_ON_BY_DEFAULT = BIT(4),
WIPHY_FLAG_4ADDR_AP = BIT(5), WIPHY_FLAG_4ADDR_AP = BIT(5),
......
...@@ -6059,6 +6059,8 @@ enum nl80211_timeout_reason { ...@@ -6059,6 +6059,8 @@ enum nl80211_timeout_reason {
* @NL80211_SCAN_FLAG_FREQ_KHZ: report scan results with * @NL80211_SCAN_FLAG_FREQ_KHZ: report scan results with
* %NL80211_ATTR_SCAN_FREQ_KHZ. This also means * %NL80211_ATTR_SCAN_FREQ_KHZ. This also means
* %NL80211_ATTR_SCAN_FREQUENCIES will not be included. * %NL80211_ATTR_SCAN_FREQUENCIES will not be included.
* @NL80211_SCAN_FLAG_COLOCATED_6GHZ: scan for colocated APs reported by
* 2.4/5 GHz APs
*/ */
enum nl80211_scan_flags { enum nl80211_scan_flags {
NL80211_SCAN_FLAG_LOW_PRIORITY = 1<<0, NL80211_SCAN_FLAG_LOW_PRIORITY = 1<<0,
...@@ -6075,6 +6077,7 @@ enum nl80211_scan_flags { ...@@ -6075,6 +6077,7 @@ enum nl80211_scan_flags {
NL80211_SCAN_FLAG_RANDOM_SN = 1<<11, NL80211_SCAN_FLAG_RANDOM_SN = 1<<11,
NL80211_SCAN_FLAG_MIN_PREQ_CONTENT = 1<<12, NL80211_SCAN_FLAG_MIN_PREQ_CONTENT = 1<<12,
NL80211_SCAN_FLAG_FREQ_KHZ = 1<<13, NL80211_SCAN_FLAG_FREQ_KHZ = 1<<13,
NL80211_SCAN_FLAG_COLOCATED_6GHZ = 1<<14,
}; };
/** /**
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Copyright 2007, Michael Wu <flamingice@sourmilk.net> * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
* Copyright 2013-2015 Intel Mobile Communications GmbH * Copyright 2013-2015 Intel Mobile Communications GmbH
* Copyright 2016-2017 Intel Deutschland GmbH * Copyright 2016-2017 Intel Deutschland GmbH
* Copyright (C) 2018-2019 Intel Corporation * Copyright (C) 2018-2020 Intel Corporation
*/ */
#include <linux/if_arp.h> #include <linux/if_arp.h>
...@@ -712,6 +712,10 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, ...@@ -712,6 +712,10 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
req->duration_mandatory; req->duration_mandatory;
local->hw_scan_band = 0; local->hw_scan_band = 0;
local->hw_scan_req->req.n_6ghz_params = req->n_6ghz_params;
local->hw_scan_req->req.scan_6ghz_params =
req->scan_6ghz_params;
local->hw_scan_req->req.scan_6ghz = req->scan_6ghz;
/* /*
* After allocating local->hw_scan_req, we must * After allocating local->hw_scan_req, we must
...@@ -1124,7 +1128,8 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, ...@@ -1124,7 +1128,8 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
int max_n; int max_n;
for (band = 0; band < NUM_NL80211_BANDS; band++) { for (band = 0; band < NUM_NL80211_BANDS; band++) {
if (!local->hw.wiphy->bands[band]) if (!local->hw.wiphy->bands[band] ||
band == NL80211_BAND_6GHZ)
continue; continue;
max_n = local->hw.wiphy->bands[band]->n_channels; max_n = local->hw.wiphy->bands[band]->n_channels;
......
...@@ -236,7 +236,9 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, ...@@ -236,7 +236,9 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
rdev->opencount--; rdev->opencount--;
if (rdev->scan_req && rdev->scan_req->wdev == wdev) { if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
if (WARN_ON(!rdev->scan_req->notified)) if (WARN_ON(!rdev->scan_req->notified &&
(!rdev->int_scan_req ||
!rdev->int_scan_req->notified)))
rdev->scan_req->info.aborted = true; rdev->scan_req->info.aborted = true;
___cfg80211_scan_done(rdev, false); ___cfg80211_scan_done(rdev, false);
} }
...@@ -1336,7 +1338,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, ...@@ -1336,7 +1338,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
case NETDEV_DOWN: case NETDEV_DOWN:
cfg80211_update_iface_num(rdev, wdev->iftype, -1); cfg80211_update_iface_num(rdev, wdev->iftype, -1);
if (rdev->scan_req && rdev->scan_req->wdev == wdev) { if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
if (WARN_ON(!rdev->scan_req->notified)) if (WARN_ON(!rdev->scan_req->notified &&
(!rdev->int_scan_req ||
!rdev->int_scan_req->notified)))
rdev->scan_req->info.aborted = true; rdev->scan_req->info.aborted = true;
___cfg80211_scan_done(rdev, false); ___cfg80211_scan_done(rdev, false);
} }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* Wireless configuration interface internals. * Wireless configuration interface internals.
* *
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
* Copyright (C) 2018-2019 Intel Corporation * Copyright (C) 2018-2020 Intel Corporation
*/ */
#ifndef __NET_WIRELESS_CORE_H #ifndef __NET_WIRELESS_CORE_H
#define __NET_WIRELESS_CORE_H #define __NET_WIRELESS_CORE_H
...@@ -72,6 +72,7 @@ struct cfg80211_registered_device { ...@@ -72,6 +72,7 @@ struct cfg80211_registered_device {
u32 bss_generation; u32 bss_generation;
u32 bss_entries; u32 bss_entries;
struct cfg80211_scan_request *scan_req; /* protected by RTNL */ struct cfg80211_scan_request *scan_req; /* protected by RTNL */
struct cfg80211_scan_request *int_scan_req;
struct sk_buff *scan_msg; struct sk_buff *scan_msg;
struct list_head sched_scan_req_list; struct list_head sched_scan_req_list;
time64_t suspend_at; time64_t suspend_at;
...@@ -457,6 +458,8 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev); ...@@ -457,6 +458,8 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev);
bool cfg80211_does_bw_fit_range(const struct ieee80211_freq_range *freq_range, bool cfg80211_does_bw_fit_range(const struct ieee80211_freq_range *freq_range,
u32 center_freq_khz, u32 bw_khz); u32 center_freq_khz, u32 bw_khz);
int cfg80211_scan(struct cfg80211_registered_device *rdev);
extern struct work_struct cfg80211_disconnect_work; extern struct work_struct cfg80211_disconnect_work;
/** /**
......
...@@ -8236,7 +8236,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) ...@@ -8236,7 +8236,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
request->scan_start = jiffies; request->scan_start = jiffies;
rdev->scan_req = request; rdev->scan_req = request;
err = rdev_scan(rdev, request); err = cfg80211_scan(rdev);
if (err) if (err)
goto out_free; goto out_free;
...@@ -15518,6 +15518,7 @@ static int nl80211_add_scan_req(struct sk_buff *msg, ...@@ -15518,6 +15518,7 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
struct cfg80211_scan_request *req = rdev->scan_req; struct cfg80211_scan_request *req = rdev->scan_req;
struct nlattr *nest; struct nlattr *nest;
int i; int i;
struct cfg80211_scan_info *info;
if (WARN_ON(!req)) if (WARN_ON(!req))
return 0; return 0;
...@@ -15561,11 +15562,13 @@ static int nl80211_add_scan_req(struct sk_buff *msg, ...@@ -15561,11 +15562,13 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags)) nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags))
goto nla_put_failure; goto nla_put_failure;
if (req->info.scan_start_tsf && info = rdev->int_scan_req ? &rdev->int_scan_req->info :
&rdev->scan_req->info;
if (info->scan_start_tsf &&
(nla_put_u64_64bit(msg, NL80211_ATTR_SCAN_START_TIME_TSF, (nla_put_u64_64bit(msg, NL80211_ATTR_SCAN_START_TIME_TSF,
req->info.scan_start_tsf, NL80211_BSS_PAD) || info->scan_start_tsf, NL80211_BSS_PAD) ||
nla_put(msg, NL80211_ATTR_SCAN_START_TIME_TSF_BSSID, ETH_ALEN, nla_put(msg, NL80211_ATTR_SCAN_START_TIME_TSF_BSSID, ETH_ALEN,
req->info.tsf_bssid))) info->tsf_bssid)))
goto nla_put_failure; goto nla_put_failure;
return 0; return 0;
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment