Fix generating offloaded ACS channel list when hw_mode is set to any
When ACS is offloaded to device driver and the hw_mode parameter is set to any, the current_mode structure is NULL which fails the ACS command. Fix this by populating the ACS channel list with channels from all bands when current_mode is NULL. Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
844dfeb804
commit
d0cdccd307
4 changed files with 68 additions and 14 deletions
|
@ -743,6 +743,25 @@ int hostapd_drv_set_qos_map(struct hostapd_data *hapd,
|
|||
}
|
||||
|
||||
|
||||
static void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd,
|
||||
struct hostapd_hw_modes *mode,
|
||||
int acs_ch_list_all,
|
||||
int **freq_list)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < mode->num_channels; i++) {
|
||||
struct hostapd_channel_data *chan = &mode->channels[i];
|
||||
|
||||
if ((acs_ch_list_all ||
|
||||
freq_range_list_includes(&hapd->iface->conf->acs_ch_list,
|
||||
chan->chan)) &&
|
||||
!(chan->flag & HOSTAPD_CHAN_DISABLED))
|
||||
int_array_add_unique(freq_list, chan->freq);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_do_acs(struct hostapd_data *hapd)
|
||||
{
|
||||
struct drv_acs_params params;
|
||||
|
@ -750,6 +769,7 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd)
|
|||
u8 *channels = NULL;
|
||||
unsigned int num_channels = 0;
|
||||
struct hostapd_hw_modes *mode;
|
||||
int *freq_list = NULL;
|
||||
|
||||
if (hapd->driver == NULL || hapd->driver->do_acs == NULL)
|
||||
return 0;
|
||||
|
@ -765,8 +785,7 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd)
|
|||
acs_ch_list_all = 1;
|
||||
|
||||
mode = hapd->iface->current_mode;
|
||||
if (mode == NULL)
|
||||
return -1;
|
||||
if (mode) {
|
||||
channels = os_malloc(mode->num_channels);
|
||||
if (channels == NULL)
|
||||
return -1;
|
||||
|
@ -774,15 +793,27 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd)
|
|||
for (i = 0; i < mode->num_channels; i++) {
|
||||
struct hostapd_channel_data *chan = &mode->channels[i];
|
||||
if (!acs_ch_list_all &&
|
||||
!freq_range_list_includes(&hapd->iface->conf->acs_ch_list,
|
||||
!freq_range_list_includes(
|
||||
&hapd->iface->conf->acs_ch_list,
|
||||
chan->chan))
|
||||
continue;
|
||||
if (!(chan->flag & HOSTAPD_CHAN_DISABLED))
|
||||
if (!(chan->flag & HOSTAPD_CHAN_DISABLED)) {
|
||||
channels[num_channels++] = chan->chan;
|
||||
int_array_add_unique(&freq_list, chan->freq);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < hapd->iface->num_hw_features; i++) {
|
||||
mode = &hapd->iface->hw_features[i];
|
||||
hostapd_get_hw_mode_any_channels(hapd, mode,
|
||||
acs_ch_list_all,
|
||||
&freq_list);
|
||||
}
|
||||
}
|
||||
|
||||
params.ch_list = channels;
|
||||
params.ch_list_len = num_channels;
|
||||
params.freq_list = freq_list;
|
||||
|
||||
params.ht_enabled = !!(hapd->iface->conf->ieee80211n);
|
||||
params.ht40_enabled = !!(hapd->iface->conf->ht_capab &
|
||||
|
|
|
@ -223,6 +223,7 @@ enum qca_wlan_vendor_attr_acs_offload {
|
|||
QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST,
|
||||
QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
|
||||
QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
|
||||
QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST,
|
||||
/* keep last */
|
||||
QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST,
|
||||
QCA_WLAN_VENDOR_ATTR_ACS_MAX =
|
||||
|
|
|
@ -1602,6 +1602,7 @@ struct drv_acs_params {
|
|||
/* ACS channel list info */
|
||||
unsigned int ch_list_len;
|
||||
const u8 *ch_list;
|
||||
const int *freq_list;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -8385,6 +8385,26 @@ static int hw_mode_to_qca_acs(enum hostapd_hw_mode hw_mode)
|
|||
}
|
||||
|
||||
|
||||
static int add_acs_freq_list(struct nl_msg *msg, const int *freq_list)
|
||||
{
|
||||
int i, len, ret;
|
||||
u32 *freqs;
|
||||
|
||||
if (!freq_list)
|
||||
return 0;
|
||||
len = int_array_len(freq_list);
|
||||
freqs = os_malloc(sizeof(u32) * len);
|
||||
if (!freqs)
|
||||
return -1;
|
||||
for (i = 0; i < len; i++)
|
||||
freqs[i] = freq_list[i];
|
||||
ret = nla_put(msg, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST,
|
||||
sizeof(u32) * len, freqs);
|
||||
os_free(freqs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_driver_do_acs(void *priv, struct drv_acs_params *params)
|
||||
{
|
||||
struct i802_bss *bss = priv;
|
||||
|
@ -8414,7 +8434,8 @@ static int wpa_driver_do_acs(void *priv, struct drv_acs_params *params)
|
|||
params->ch_width) ||
|
||||
(params->ch_list_len &&
|
||||
nla_put(msg, QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST, params->ch_list_len,
|
||||
params->ch_list))) {
|
||||
params->ch_list)) ||
|
||||
add_acs_freq_list(msg, params->freq_list)) {
|
||||
nlmsg_free(msg);
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue