#ifndef CONFIG_NO_SCAN_PROCESSING
static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
- int new_scan, int own_request);
+ int new_scan, int own_request,
+ bool trigger_6ghz_scan,
+ union wpa_event_data *data);
#endif /* CONFIG_NO_SCAN_PROCESSING */
#ifdef CONFIG_OWE
static void owe_trans_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
struct wpa_scan_results *scan_res = NULL;
int ret = 0;
int ap = 0;
+ bool trigger_6ghz_scan;
#ifndef CONFIG_NO_RANDOM_POOL
size_t i, num;
#endif /* CONFIG_NO_RANDOM_POOL */
ap = 1;
#endif /* CONFIG_AP */
+ trigger_6ghz_scan = wpa_s->crossed_6ghz_dom &&
+ wpa_s->last_scan_all_chan;
+ wpa_s->crossed_6ghz_dom = false;
+ wpa_s->last_scan_all_chan = false;
+
wpa_supplicant_notify_scanning(wpa_s, 0);
scan_res = wpa_supplicant_get_scan_results(wpa_s,
if (wpa_s->supp_pbc_active && !wpas_wps_partner_link_scan_done(wpa_s))
return ret;
- return wpas_select_network_from_last_scan(wpa_s, 1, own_request);
+ return wpas_select_network_from_last_scan(wpa_s, 1, own_request,
+ trigger_6ghz_scan, data);
scan_work_done:
wpa_scan_results_free(scan_res);
}
+static int wpas_trigger_6ghz_scan(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data)
+{
+ struct wpa_driver_scan_params params;
+ unsigned int j;
+
+ wpa_dbg(wpa_s, MSG_INFO, "Triggering 6GHz-only scan");
+ os_memset(¶ms, 0, sizeof(params));
+ params.non_coloc_6ghz = wpa_s->last_scan_non_coloc_6ghz;
+ for (j = 0; j < data->scan_info.num_ssids; j++)
+ params.ssids[j] = data->scan_info.ssids[j];
+ params.num_ssids = data->scan_info.num_ssids;
+ wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, ¶ms,
+ true, !wpa_s->last_scan_non_coloc_6ghz, false);
+ if (!wpa_supplicant_trigger_scan(wpa_s, ¶ms, true, true)) {
+ os_free(params.freqs);
+ return 1;
+ }
+ wpa_dbg(wpa_s, MSG_INFO, "Failed to trigger 6GHz-only scan");
+ os_free(params.freqs);
+ return 0;
+}
+
+
+/**
+ * Select a network from the last scan
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @new_scan: Whether this function was called right after a scan has finished
+ * @own_request: Whether the scan was requested by this interface
+ * @trigger_6ghz_scan: Whether to trigger a 6ghz-only scan when applicable
+ * @data: Scan data from scan that finished if applicable
+ *
+ * See _wpa_supplicant_event_scan_results() for return values.
+ */
static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
- int new_scan, int own_request)
+ int new_scan, int own_request,
+ bool trigger_6ghz_scan,
+ union wpa_event_data *data)
{
struct wpa_bss *selected;
struct wpa_ssid *ssid = NULL;
if (new_scan)
wpa_supplicant_rsn_preauth_scan_results(wpa_s);
} else if (own_request) {
+ if (wpa_s->support_6ghz && trigger_6ghz_scan && data &&
+ wpas_trigger_6ghz_scan(wpa_s, data) < 0)
+ return 1;
+
/*
* No SSID found. If SCAN results are as a result of
* own scan request and not due to a scan request on
return -1;
}
- return wpas_select_network_from_last_scan(wpa_s, 0, 1);
+ return wpas_select_network_from_last_scan(wpa_s, 0, 1, false, NULL);
#endif /* CONFIG_NO_SCAN_PROCESSING */
}
#ifdef CONFIG_NO_SCAN_PROCESSING
return -1;
#else /* CONFIG_NO_SCAN_PROCESSING */
- return wpas_select_network_from_last_scan(wpa_s, 1, 1);
+ return wpas_select_network_from_last_scan(wpa_s, 1, 1, false, NULL);
#endif /* CONFIG_NO_SCAN_PROCESSING */
}
dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
radio_list) {
+ bool was_6ghz_enabled;
+
wpa_printf(MSG_DEBUG, "%s: Updating hw mode",
ifs->ifname);
free_hw_features(ifs);
ifs->hw.modes = wpa_drv_get_hw_feature_data(
ifs, &ifs->hw.num_modes, &ifs->hw.flags, &dfs_domain);
+ was_6ghz_enabled = ifs->is_6ghz_enabled;
+ ifs->is_6ghz_enabled = wpas_is_6ghz_supported(ifs, true);
+
/* Restart PNO/sched_scan with updated channel list */
if (ifs->pno) {
wpas_stop_pno(ifs);
wpa_dbg(ifs, MSG_DEBUG,
"Channel list changed - restart sched_scan");
wpas_scan_restart_sched_scan(ifs);
+ } else if (ifs->scanning && !was_6ghz_enabled &&
+ ifs->is_6ghz_enabled) {
+ /* Look for APs in the 6 GHz band */
+ wpa_dbg(ifs, MSG_INFO,
+ "Channel list changed - trigger 6 GHz-only scan");
+ ifs->crossed_6ghz_dom = true;
}
}
* shouldn't be set if the IEs have already been set with
* wpa_supplicant_extra_ies(). Otherwise, wpabuf_free() will lead to a
* double-free.
+ * @next: Whether or not to perform this scan as the next radio work
* Returns: 0 on success, -1 on failure
*/
int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s,
struct wpa_driver_scan_params *params,
- bool default_ies)
+ bool default_ies, bool next)
{
struct wpa_driver_scan_params *ctx;
struct wpabuf *ies = NULL;
params->extra_ies = NULL;
params->extra_ies_len = 0;
}
+ wpa_s->last_scan_all_chan = !params->freqs;
+ wpa_s->last_scan_non_coloc_6ghz = params->non_coloc_6ghz;
if (!ctx ||
- radio_add_work(wpa_s, 0, "scan", 0, wpas_trigger_scan_cb, ctx) < 0)
- {
+ radio_add_work(wpa_s, 0, "scan", next, wpas_trigger_scan_cb,
+ ctx) < 0) {
wpa_scan_free_params(ctx);
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_FAILED "ret=-1");
return -1;
wpas_p2p_scan_freqs(wpa_s, ¶ms, true);
#endif /* CONFIG_P2P */
- ret = wpa_supplicant_trigger_scan(wpa_s, scan_params, false);
+ ret = wpa_supplicant_trigger_scan(wpa_s, scan_params, false, false);
if (ret && wpa_s->last_scan_req == MANUAL_SCAN_REQ && params.freqs &&
!wpa_s->manual_scan_freqs) {