wlan-ap-Telecominfraproject/feeds/wifi-ax/mac80211/patches/qca/036-nl80211-add-wide-band-scan-support.patch
John Crispin 528a778e38 open-converged-wireless: Import 21.02 based uCentral tree
Signed-off-by: John Crispin <john@phrozen.org>
2021-03-25 12:19:47 +01:00

205 lines
6.2 KiB
Diff

--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2047,6 +2047,7 @@ struct cfg80211_scan_info {
* @channels: channels to scan on.
* @n_channels: total number of channels to scan
* @scan_width: channel width for scanning
+ * @chandef: defines the channel to do wide band scan
* @ie: optional information element(s) to add into Probe Request or %NULL
* @ie_len: length of ie in octets
* @duration: how long to listen on each channel, in TUs. If
@@ -2073,6 +2074,7 @@ struct cfg80211_scan_request {
int n_ssids;
u32 n_channels;
enum nl80211_bss_scan_width scan_width;
+ struct cfg80211_chan_def *chandef;
const u8 *ie;
size_t ie_len;
u16 duration;
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -5821,6 +5821,9 @@ enum nl80211_feature_flags {
* handshake with PSK in AP mode (PSK is passed as part of the start AP
* command).
*
+ * @NL80211_EXT_FEATURE_WIDE_BAND_SCAN: Driver/device supports wide band scan
+ * on a frequency along with its corresponding phymode (40Mhz, 80Mhz)
+ *
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
*/
@@ -5878,6 +5881,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS,
NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION,
NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK,
+ NL80211_EXT_FEATURE_WIDE_BAND_SCAN,
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
@@ -5992,6 +5996,8 @@ enum nl80211_timeout_reason {
* @NL80211_SCAN_FLAG_FREQ_KHZ: report scan results with
* %NL80211_ATTR_SCAN_FREQ_KHZ. This also means
* %NL80211_ATTR_SCAN_FREQUENCIES will not be included.
+ * @NL80211_SCAN_FLAG_WIDE_BAND_SCAN: This flag intends the driver to perform
+ * wide band scan only if the driver supports it.
*/
enum nl80211_scan_flags {
NL80211_SCAN_FLAG_LOW_PRIORITY = 1<<0,
@@ -6008,6 +6014,7 @@ enum nl80211_scan_flags {
NL80211_SCAN_FLAG_RANDOM_SN = 1<<11,
NL80211_SCAN_FLAG_MIN_PREQ_CONTENT = 1<<12,
NL80211_SCAN_FLAG_FREQ_KHZ = 1<<13,
+ NL80211_SCAN_FLAG_WIDE_BAND_SCAN = 1<<14,
};
/**
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -694,11 +694,13 @@ static int __ieee80211_start_scan(struct
local->hw_scan_req = kmalloc(
sizeof(*local->hw_scan_req) +
+ sizeof(*req->chandef) +
req->n_channels * sizeof(req->channels[0]) +
local->hw_scan_ies_bufsize, GFP_KERNEL);
if (!local->hw_scan_req)
return -ENOMEM;
+ local->hw_scan_req->req.chandef = req->chandef;
local->hw_scan_req->req.ssids = req->ssids;
local->hw_scan_req->req.n_ssids = req->n_ssids;
ies = (u8 *)local->hw_scan_req +
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -7756,7 +7756,10 @@ nl80211_check_scan_flags(struct wiphy *w
NL80211_EXT_FEATURE_SCAN_RANDOM_SN) ||
!nl80211_check_scan_feat(wiphy, *flags,
NL80211_SCAN_FLAG_MIN_PREQ_CONTENT,
- NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT))
+ NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT) ||
+ !nl80211_check_scan_feat(wiphy, *flags,
+ NL80211_SCAN_FLAG_WIDE_BAND_SCAN,
+ NL80211_EXT_FEATURE_WIDE_BAND_SCAN))
return -EOPNOTSUPP;
if (*flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
@@ -7781,10 +7784,12 @@ static int nl80211_trigger_scan(struct s
struct cfg80211_scan_request *request;
struct nlattr *scan_freqs = NULL;
bool scan_freqs_khz = false;
+ struct cfg80211_chan_def chandef;
struct nlattr *attr;
struct wiphy *wiphy;
- int err, tmp, n_ssids = 0, n_channels, i;
+ int err, tmp, n_ssids = 0, n_channels = 0, i;
size_t ie_len;
+ bool chandef_found = false;
wiphy = &rdev->wiphy;
@@ -7797,7 +7802,12 @@ static int nl80211_trigger_scan(struct s
if (rdev->scan_req || rdev->scan_msg)
return -EBUSY;
- if (info->attrs[NL80211_ATTR_SCAN_FREQ_KHZ]) {
+ if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
+ if (nl80211_parse_chandef(rdev, info, &chandef)) {
+ return -EINVAL;
+ }
+ chandef_found = true;
+ } else if (info->attrs[NL80211_ATTR_SCAN_FREQ_KHZ]) {
if (!wiphy_ext_feature_isset(wiphy,
NL80211_EXT_FEATURE_SCAN_FREQ_KHZ))
return -EOPNOTSUPP;
@@ -7810,6 +7820,8 @@ static int nl80211_trigger_scan(struct s
n_channels = validate_scan_freqs(scan_freqs);
if (!n_channels)
return -EINVAL;
+ } else if (chandef_found) {
+ n_channels = 1;
} else {
n_channels = ieee80211_get_num_supported_channels(wiphy);
}
@@ -7830,12 +7842,19 @@ static int nl80211_trigger_scan(struct s
return -EINVAL;
request = kzalloc(sizeof(*request)
+ + sizeof(*request->chandef)
+ sizeof(*request->ssids) * n_ssids
+ sizeof(*request->channels) * n_channels
+ ie_len, GFP_KERNEL);
if (!request)
return -ENOMEM;
+ if (chandef_found) {
+ request->chandef = &chandef;
+ request->channels[0] = chandef.chan;
+ request->n_channels = n_channels;
+ }
+
if (n_ssids)
request->ssids = (void *)&request->channels[n_channels];
request->n_ssids = n_ssids;
@@ -7869,7 +7888,7 @@ static int nl80211_trigger_scan(struct s
request->channels[i] = chan;
i++;
}
- } else {
+ } else if (!chandef_found) {
enum nl80211_band band;
/* all channels */
@@ -7892,31 +7911,32 @@ static int nl80211_trigger_scan(struct s
}
}
- if (!i) {
- err = -EINVAL;
- goto out_free;
- }
-
- request->n_channels = i;
-
- wdev_lock(wdev);
- if (!cfg80211_off_channel_oper_allowed(wdev)) {
- struct ieee80211_channel *chan;
-
- if (request->n_channels != 1) {
- wdev_unlock(wdev);
- err = -EBUSY;
+ if (!chandef_found) {
+ if (!i) {
+ err = -EINVAL;
goto out_free;
}
+ request->n_channels = i;
- chan = request->channels[0];
- if (chan->center_freq != wdev->chandef.chan->center_freq) {
- wdev_unlock(wdev);
- err = -EBUSY;
- goto out_free;
+ wdev_lock(wdev);
+ if (!cfg80211_off_channel_oper_allowed(wdev)) {
+ struct ieee80211_channel *chan;
+
+ if (request->n_channels != 1) {
+ wdev_unlock(wdev);
+ err = -EBUSY;
+ goto out_free;
+ }
+
+ chan = request->channels[0];
+ if (chan->center_freq != wdev->chandef.chan->center_freq) {
+ wdev_unlock(wdev);
+ err = -EBUSY;
+ goto out_free;
+ }
}
+ wdev_unlock(wdev);
}
- wdev_unlock(wdev);
i = 0;
if (n_ssids) {