Update hw_mode when CSA finishes
The driver might decide to change the operating band on its own, e.g., when trying to use a single channel in AP + AP case. A CSA event will be notified to hostapd to update the channel/frequency, but hw_mode did not get updated accordingly. This may cause hostapd interface restarting to fail, e.g., with control interface DISABLE / ENABLE commands at configured_fixed_chan_to_freq(), because of the mismatch between conf->channel and conf->hw_mode. Update hw_mode right after channel change to fix this. Signed-off-by: ngong <quic_ngong@quicinc.com>
This commit is contained in:
parent
32dcec9529
commit
123d16d860
3 changed files with 41 additions and 6 deletions
|
@ -1085,6 +1085,12 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The operating channel changed when CSA finished, so need to update
|
||||||
|
* hw_mode for all following operations to cover the cases where the
|
||||||
|
* driver changed the operating band. */
|
||||||
|
if (finished && hostapd_csa_update_hwmode(hapd->iface))
|
||||||
|
return;
|
||||||
|
|
||||||
switch (hapd->iface->current_mode->mode) {
|
switch (hapd->iface->current_mode->mode) {
|
||||||
case HOSTAPD_MODE_IEEE80211A:
|
case HOSTAPD_MODE_IEEE80211A:
|
||||||
if (cf1 == 5935)
|
if (cf1 == 5935)
|
||||||
|
|
|
@ -1079,14 +1079,14 @@ static bool skip_mode(struct hostapd_iface *iface,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void hostapd_determine_mode(struct hostapd_iface *iface)
|
int hostapd_determine_mode(struct hostapd_iface *iface)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
enum hostapd_hw_mode target_mode;
|
enum hostapd_hw_mode target_mode;
|
||||||
|
|
||||||
if (iface->current_mode ||
|
if (iface->current_mode ||
|
||||||
iface->conf->hw_mode != HOSTAPD_MODE_IEEE80211ANY)
|
iface->conf->hw_mode != HOSTAPD_MODE_IEEE80211ANY)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
if (iface->freq < 4000)
|
if (iface->freq < 4000)
|
||||||
target_mode = HOSTAPD_MODE_IEEE80211G;
|
target_mode = HOSTAPD_MODE_IEEE80211G;
|
||||||
|
@ -1109,8 +1109,11 @@ void hostapd_determine_mode(struct hostapd_iface *iface)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!iface->current_mode)
|
if (!iface->current_mode) {
|
||||||
wpa_printf(MSG_ERROR, "ACS: Cannot decide mode");
|
wpa_printf(MSG_ERROR, "ACS/CSA: Cannot decide mode");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1215,6 +1218,25 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hostapd_csa_update_hwmode - Update hardware mode
|
||||||
|
* @iface: Pointer to interface data.
|
||||||
|
* Returns: 0 on success, < 0 on failure
|
||||||
|
*
|
||||||
|
* Update hardware mode when the operating channel changed because of CSA.
|
||||||
|
*/
|
||||||
|
int hostapd_csa_update_hwmode(struct hostapd_iface *iface)
|
||||||
|
{
|
||||||
|
if (!iface || !iface->conf)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
iface->current_mode = NULL;
|
||||||
|
iface->conf->hw_mode = HOSTAPD_MODE_IEEE80211ANY;
|
||||||
|
|
||||||
|
return hostapd_determine_mode(iface);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hostapd_select_hw_mode - Select the hardware mode
|
* hostapd_select_hw_mode - Select the hardware mode
|
||||||
* @iface: Pointer to interface data.
|
* @iface: Pointer to interface data.
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
|
void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
|
||||||
size_t num_hw_features);
|
size_t num_hw_features);
|
||||||
int hostapd_get_hw_features(struct hostapd_iface *iface);
|
int hostapd_get_hw_features(struct hostapd_iface *iface);
|
||||||
|
int hostapd_csa_update_hwmode(struct hostapd_iface *iface);
|
||||||
int hostapd_acs_completed(struct hostapd_iface *iface, int err);
|
int hostapd_acs_completed(struct hostapd_iface *iface, int err);
|
||||||
int hostapd_select_hw_mode(struct hostapd_iface *iface);
|
int hostapd_select_hw_mode(struct hostapd_iface *iface);
|
||||||
const char * hostapd_hw_mode_txt(int mode);
|
const char * hostapd_hw_mode_txt(int mode);
|
||||||
|
@ -28,7 +29,7 @@ int hostapd_prepare_rates(struct hostapd_iface *iface,
|
||||||
void hostapd_stop_setup_timers(struct hostapd_iface *iface);
|
void hostapd_stop_setup_timers(struct hostapd_iface *iface);
|
||||||
int hostapd_hw_skip_mode(struct hostapd_iface *iface,
|
int hostapd_hw_skip_mode(struct hostapd_iface *iface,
|
||||||
struct hostapd_hw_modes *mode);
|
struct hostapd_hw_modes *mode);
|
||||||
void hostapd_determine_mode(struct hostapd_iface *iface);
|
int hostapd_determine_mode(struct hostapd_iface *iface);
|
||||||
#else /* NEED_AP_MLME */
|
#else /* NEED_AP_MLME */
|
||||||
static inline void
|
static inline void
|
||||||
hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
|
hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
|
||||||
|
@ -41,6 +42,11 @@ static inline int hostapd_get_hw_features(struct hostapd_iface *iface)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int hostapd_csa_update_hwmode(struct hostapd_iface *iface)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int hostapd_acs_completed(struct hostapd_iface *iface, int err)
|
static inline int hostapd_acs_completed(struct hostapd_iface *iface, int err)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -92,8 +98,9 @@ static inline int hostapd_check_he_6ghz_capab(struct hostapd_iface *iface)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void hostapd_determine_mode(struct hostapd_iface *iface)
|
static inline int hostapd_determine_mode(struct hostapd_iface *iface)
|
||||||
{
|
{
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* NEED_AP_MLME */
|
#endif /* NEED_AP_MLME */
|
||||||
|
|
Loading…
Reference in a new issue