@@ -940,6 +940,85 @@ int hostapd_is_dfs_chan_available(struct hostapd_iface *iface)
return dfs_check_chans_available(iface, start_chan_idx, n_chans);
}
+static int hostapd_dfs_request_channel_switch(struct hostapd_iface *iface,
+ int channel, int freq,
+ int secondary_channel,
+ u8 oper_centr_freq_seg0_idx,
+ u8 oper_centr_freq_seg1_idx)
+{
+ struct hostapd_hw_modes *cmode = iface->current_mode;
+ int ieee80211_mode = IEEE80211_MODE_AP, err, i;
+ struct csa_settings csa_settings;
+ u8 new_vht_oper_chwidth;
+
+ wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d", channel);
+ wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL
+ "freq=%d chan=%d sec_chan=%d", freq, channel,
+ secondary_channel);
+
+ new_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
+ hostapd_set_oper_chwidth(iface->conf,
+ hostapd_get_oper_chwidth(iface->conf));
+
+ /* Setup CSA request */
+ os_memset(&csa_settings, 0, sizeof(csa_settings));
+ csa_settings.cs_count = 5;
+ csa_settings.block_tx = 1;
+#ifdef CONFIG_MESH
+ if (iface->mconf)
+ ieee80211_mode = IEEE80211_MODE_MESH;
+#endif /* CONFIG_MESH */
+ err = hostapd_set_freq_params(&csa_settings.freq_params,
+ iface->conf->hw_mode,
+ freq, channel,
+ iface->conf->enable_edmg,
+ iface->conf->edmg_channel,
+ iface->conf->ieee80211n,
+ iface->conf->ieee80211ac,
+ iface->conf->ieee80211ax,
+ secondary_channel,
+ new_vht_oper_chwidth,
+ oper_centr_freq_seg0_idx,
+ oper_centr_freq_seg1_idx,
+ cmode->vht_capab,
+ &cmode->he_capab[ieee80211_mode]);
+
+ if (err) {
+ wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params");
+ hostapd_disable_iface(iface);
+ return err;
+ }
+
+ for (i = 0; i < iface->num_bss; i++) {
+ err = hostapd_switch_channel(iface->bss[i], &csa_settings);
+ if (err)
+ break;
+ }
+
+ if (err) {
+ wpa_printf(MSG_WARNING, "DFS failed to schedule CSA (%d) - trying fallback",
+ err);
+ iface->freq = freq;
+ iface->conf->channel = channel;
+ iface->conf->secondary_channel = secondary_channel;
+ hostapd_set_oper_chwidth(iface->conf, new_vht_oper_chwidth);
+ hostapd_set_oper_centr_freq_seg0_idx(iface->conf,
+ oper_centr_freq_seg0_idx);
+ hostapd_set_oper_centr_freq_seg1_idx(iface->conf,
+ oper_centr_freq_seg1_idx);
+
+ hostapd_disable_iface(iface);
+ hostapd_enable_iface(iface);
+
+ return 0;
+ }
+
+ /* Channel configuration will be updated once CSA completes and
+ * ch_switch_notify event is received */
+ wpa_printf(MSG_DEBUG, "DFS waiting channel switch event");
+
+ return 0;
+}
static struct hostapd_channel_data *
dfs_downgrade_bandwidth(struct hostapd_iface *iface, int *secondary_channel,
@@ -1179,21 +1258,13 @@ static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface)
return err;
}
-
static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
{
struct hostapd_channel_data *channel;
int secondary_channel;
u8 oper_centr_freq_seg0_idx;
u8 oper_centr_freq_seg1_idx;
- u8 new_vht_oper_chwidth;
int skip_radar = 1;
- struct csa_settings csa_settings;
- unsigned int i;
- int err = 1;
- struct hostapd_hw_modes *cmode = iface->current_mode;
- u8 current_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
- int ieee80211_mode = IEEE80211_MODE_AP;
wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)",
__func__, iface->cac_started ? "yes" : "no",
@@ -1256,73 +1327,11 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
}
}
- wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d",
- channel->chan);
- wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL
- "freq=%d chan=%d sec_chan=%d", channel->freq,
- channel->chan, secondary_channel);
-
- new_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
- hostapd_set_oper_chwidth(iface->conf, current_vht_oper_chwidth);
-
- /* Setup CSA request */
- os_memset(&csa_settings, 0, sizeof(csa_settings));
- csa_settings.cs_count = 5;
- csa_settings.block_tx = 1;
-#ifdef CONFIG_MESH
- if (iface->mconf)
- ieee80211_mode = IEEE80211_MODE_MESH;
-#endif /* CONFIG_MESH */
- err = hostapd_set_freq_params(&csa_settings.freq_params,
- iface->conf->hw_mode,
- channel->freq,
- channel->chan,
- iface->conf->enable_edmg,
- iface->conf->edmg_channel,
- iface->conf->ieee80211n,
- iface->conf->ieee80211ac,
- iface->conf->ieee80211ax,
- secondary_channel,
- new_vht_oper_chwidth,
- oper_centr_freq_seg0_idx,
- oper_centr_freq_seg1_idx,
- cmode->vht_capab,
- &cmode->he_capab[ieee80211_mode]);
-
- if (err) {
- wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params");
- hostapd_disable_iface(iface);
- return err;
- }
-
- for (i = 0; i < iface->num_bss; i++) {
- err = hostapd_switch_channel(iface->bss[i], &csa_settings);
- if (err)
- break;
- }
-
- if (err) {
- wpa_printf(MSG_WARNING, "DFS failed to schedule CSA (%d) - trying fallback",
- err);
- iface->freq = channel->freq;
- iface->conf->channel = channel->chan;
- iface->conf->secondary_channel = secondary_channel;
- hostapd_set_oper_chwidth(iface->conf, new_vht_oper_chwidth);
- hostapd_set_oper_centr_freq_seg0_idx(iface->conf,
- oper_centr_freq_seg0_idx);
- hostapd_set_oper_centr_freq_seg1_idx(iface->conf,
- oper_centr_freq_seg1_idx);
-
- hostapd_disable_iface(iface);
- hostapd_enable_iface(iface);
- return 0;
- }
-
- /* Channel configuration will be updated once CSA completes and
- * ch_switch_notify event is received */
-
- wpa_printf(MSG_DEBUG, "DFS waiting channel switch event");
- return 0;
+ return hostapd_dfs_request_channel_switch(iface, channel->chan,
+ channel->freq,
+ secondary_channel,
+ oper_centr_freq_seg0_idx,
+ oper_centr_freq_seg1_idx);
}