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:
Peng Xu 2015-06-19 17:19:27 -07:00 committed by Jouni Malinen
parent 844dfeb804
commit d0cdccd307
4 changed files with 68 additions and 14 deletions

View file

@ -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 &

View file

@ -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 =

View file

@ -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;
};

View file

@ -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;
}