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)
|
int hostapd_drv_do_acs(struct hostapd_data *hapd)
|
||||||
{
|
{
|
||||||
struct drv_acs_params params;
|
struct drv_acs_params params;
|
||||||
|
@ -750,6 +769,7 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd)
|
||||||
u8 *channels = NULL;
|
u8 *channels = NULL;
|
||||||
unsigned int num_channels = 0;
|
unsigned int num_channels = 0;
|
||||||
struct hostapd_hw_modes *mode;
|
struct hostapd_hw_modes *mode;
|
||||||
|
int *freq_list = NULL;
|
||||||
|
|
||||||
if (hapd->driver == NULL || hapd->driver->do_acs == NULL)
|
if (hapd->driver == NULL || hapd->driver->do_acs == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -765,24 +785,35 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd)
|
||||||
acs_ch_list_all = 1;
|
acs_ch_list_all = 1;
|
||||||
|
|
||||||
mode = hapd->iface->current_mode;
|
mode = hapd->iface->current_mode;
|
||||||
if (mode == NULL)
|
if (mode) {
|
||||||
return -1;
|
channels = os_malloc(mode->num_channels);
|
||||||
channels = os_malloc(mode->num_channels);
|
if (channels == NULL)
|
||||||
if (channels == NULL)
|
return -1;
|
||||||
return -1;
|
|
||||||
|
|
||||||
for (i = 0; i < mode->num_channels; i++) {
|
for (i = 0; i < mode->num_channels; i++) {
|
||||||
struct hostapd_channel_data *chan = &mode->channels[i];
|
struct hostapd_channel_data *chan = &mode->channels[i];
|
||||||
if (!acs_ch_list_all &&
|
if (!acs_ch_list_all &&
|
||||||
!freq_range_list_includes(&hapd->iface->conf->acs_ch_list,
|
!freq_range_list_includes(
|
||||||
chan->chan))
|
&hapd->iface->conf->acs_ch_list,
|
||||||
continue;
|
chan->chan))
|
||||||
if (!(chan->flag & HOSTAPD_CHAN_DISABLED))
|
continue;
|
||||||
channels[num_channels++] = chan->chan;
|
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 = channels;
|
||||||
params.ch_list_len = num_channels;
|
params.ch_list_len = num_channels;
|
||||||
|
params.freq_list = freq_list;
|
||||||
|
|
||||||
params.ht_enabled = !!(hapd->iface->conf->ieee80211n);
|
params.ht_enabled = !!(hapd->iface->conf->ieee80211n);
|
||||||
params.ht40_enabled = !!(hapd->iface->conf->ht_capab &
|
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_CH_LIST,
|
||||||
QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
|
QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
|
||||||
QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
|
QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST,
|
||||||
/* keep last */
|
/* keep last */
|
||||||
QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST,
|
QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST,
|
||||||
QCA_WLAN_VENDOR_ATTR_ACS_MAX =
|
QCA_WLAN_VENDOR_ATTR_ACS_MAX =
|
||||||
|
|
|
@ -1602,6 +1602,7 @@ struct drv_acs_params {
|
||||||
/* ACS channel list info */
|
/* ACS channel list info */
|
||||||
unsigned int ch_list_len;
|
unsigned int ch_list_len;
|
||||||
const u8 *ch_list;
|
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)
|
static int wpa_driver_do_acs(void *priv, struct drv_acs_params *params)
|
||||||
{
|
{
|
||||||
struct i802_bss *bss = priv;
|
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_width) ||
|
||||||
(params->ch_list_len &&
|
(params->ch_list_len &&
|
||||||
nla_put(msg, QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST, 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);
|
nlmsg_free(msg);
|
||||||
return -ENOBUFS;
|
return -ENOBUFS;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue