@@ -352,9 +352,24 @@ static bool scan_mac_address_randomization_is_disabled(void)
return disabled;
}
+static struct scan_freq_set *scan_get_allowed_freqs(struct scan_context *sc)
+{
+ struct scan_freq_set *allowed = scan_freq_set_new();
+
+ scan_freq_set_merge(allowed, wiphy_get_supported_freqs(sc->wiphy));
+
+ if (!wiphy_constrain_freq_set(sc->wiphy, allowed)) {
+ scan_freq_set_free(allowed);
+ allowed = NULL;
+ }
+
+ return allowed;
+}
+
static struct l_genl_msg *scan_build_cmd(struct scan_context *sc,
bool ignore_flush_flag, bool is_passive,
- const struct scan_parameters *params)
+ const struct scan_parameters *params,
+ const struct scan_freq_set *freqs)
{
struct l_genl_msg *msg;
uint32_t flags = 0;
@@ -366,8 +381,8 @@ static struct l_genl_msg *scan_build_cmd(struct scan_context *sc,
if (wiphy_get_max_scan_ie_len(sc->wiphy))
scan_build_attr_ie(msg, sc, params);
- if (params->freqs)
- scan_build_attr_scan_frequencies(msg, params->freqs);
+ if (freqs)
+ scan_build_attr_scan_frequencies(msg, freqs);
if (params->flush && !ignore_flush_flag && wiphy_has_feature(sc->wiphy,
NL80211_FEATURE_SCAN_FLUSH))
@@ -524,16 +539,36 @@ static bool scan_cmds_add_hidden(const struct network_info *network,
* of all scans in the batch after the last scan is finished.
*/
*data->cmd = scan_build_cmd(data->sc, true, false,
- data->params);
+ data->params,
+ data->params->freqs);
l_genl_msg_enter_nested(*data->cmd, NL80211_ATTR_SCAN_SSIDS);
}
return true;
}
-static void scan_cmds_add(struct l_queue *cmds, struct scan_context *sc,
+static void scan_foreach_freq_split_bands(uint32_t freq, void *user_data)
+{
+ struct scan_freq_set **subsets = user_data;
+ int idx;
+
+ if (freq < 3000)
+ idx = 0;
+ else if (freq < 6000)
+ idx = 1;
+ else
+ idx = 2;
+
+ if (!subsets[idx])
+ subsets[idx] = scan_freq_set_new();
+
+ scan_freq_set_add(subsets[idx], freq);
+}
+
+static void scan_build_next_cmd(struct l_queue *cmds, struct scan_context *sc,
bool passive,
- const struct scan_parameters *params)
+ const struct scan_parameters *params,
+ const struct scan_freq_set *freqs)
{
struct l_genl_msg *cmd;
struct scan_cmds_add_data data = {
@@ -544,7 +579,7 @@ static void scan_cmds_add(struct l_queue *cmds, struct scan_context *sc,
wiphy_get_max_num_ssids_per_scan(sc->wiphy),
};
- cmd = scan_build_cmd(sc, false, passive, params);
+ cmd = scan_build_cmd(sc, false, passive, params, freqs);
if (passive) {
/* passive scan */
@@ -572,6 +607,52 @@ static void scan_cmds_add(struct l_queue *cmds, struct scan_context *sc,
l_queue_push_tail(cmds, cmd);
}
+static void scan_cmds_add(struct l_queue *cmds, struct scan_context *sc,
+ bool passive,
+ const struct scan_parameters *params)
+{
+ unsigned int i;
+ struct scan_freq_set *subsets[3] = { 0 };
+ struct scan_freq_set *allowed;
+
+ /*
+ * If the frequencies are explicit don't break up the request
+ */
+ if (params->freqs) {
+ scan_build_next_cmd(cmds, sc, passive, params, params->freqs);
+ return;
+ }
+
+ /*
+ * Otherwise a full spectrum scan will likely open up the 6GHz
+ * band. The problem is the regdom update occurs after an
+ * individual scan request so a single request isn't going to
+ * include potential 6GHz results.
+ *
+ * Instead we can break this full scan up into individual bands
+ * and increase our chances of the regdom updating after one of
+ * the earlier requests. If it does update to allow 6GHz an
+ * extra 6GHz-only passive scan can be appended to this request
+ * at that time.
+ */
+
+ allowed = scan_get_allowed_freqs(sc);
+ if (L_WARN_ON(!allowed))
+ return;
+
+ scan_freq_set_foreach(allowed, scan_foreach_freq_split_bands, subsets);
+ scan_freq_set_free(allowed);
+
+ for(i = 0; i < L_ARRAY_SIZE(subsets); i++) {
+ if (!subsets[i])
+ continue;
+
+ scan_build_next_cmd(cmds, sc, passive, params,
+ subsets[i]);
+ scan_freq_set_free(subsets[i]);
+ }
+}
+
static int scan_request_send_trigger(struct scan_context *sc,
struct scan_request *sr)
{
@@ -743,7 +824,7 @@ static void add_owe_scan_cmd(struct scan_context *sc, struct scan_request *sr,
params.ssid_len = bss->owe_trans->ssid_len;
params.flush = true;
- cmd = scan_build_cmd(sc, ignore_flush, false, ¶ms);
+ cmd = scan_build_cmd(sc, ignore_flush, false, ¶ms, params.freqs);
l_genl_msg_enter_nested(cmd, NL80211_ATTR_SCAN_SSIDS);
l_genl_msg_append_attr(cmd, 0, params.ssid_len, params.ssid);