wpa_supplicant: Unify hardware feature data

The hardware feature data is required in several different places
throughout the code. Previously, the data was acquired and freed on
demand, but with this patch wpa_supplicant will keep a single copy
around at runtime for everyone to use.

Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
This commit is contained in:
Christian Lamparter 2011-10-23 11:58:54 +03:00 committed by Jouni Malinen
parent e3b473eb4e
commit 6bf731e8ce
6 changed files with 42 additions and 49 deletions

View file

@ -56,10 +56,6 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
{
struct hostapd_bss_config *bss = &conf->bss[0];
int pairwise;
#ifdef CONFIG_IEEE80211N
struct hostapd_hw_modes *modes;
u16 num_modes, flags;
#endif /* CONFIG_IEEE80211N */
conf->driver = wpa_s->driver;
@ -91,20 +87,17 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
* Using default config settings for: conf->ht_op_mode_fixed,
* conf->ht_capab, conf->secondary_channel, conf->require_ht
*/
modes = wpa_drv_get_hw_feature_data(wpa_s, &num_modes, &flags);
if (modes) {
if (wpa_s->hw.modes) {
struct hostapd_hw_modes *mode = NULL;
int i;
for (i = 0; i < num_modes; i++) {
if (modes[i].mode == conf->hw_mode) {
mode = &modes[i];
for (i = 0; i < wpa_s->hw.num_modes; i++) {
if (wpa_s->hw.modes[i].mode == conf->hw_mode) {
mode = &wpa_s->hw.modes[i];
break;
}
}
if (mode && mode->ht_capab)
conf->ieee80211n = 1;
ieee80211_sta_free_hw_features(modes, num_modes);
modes = NULL;
}
#endif /* CONFIG_IEEE80211N */

View file

@ -355,20 +355,19 @@ static int bgscan_learn_get_params(struct bgscan_learn_data *data,
static int * bgscan_learn_get_supp_freqs(struct wpa_supplicant *wpa_s)
{
struct hostapd_hw_modes *modes;
u16 num_modes, flags;
int i, j, *freqs = NULL, *n;
size_t count = 0;
modes = wpa_drv_get_hw_feature_data(wpa_s, &num_modes, &flags);
if (!modes)
modes = wpa_s->hw.modes;
if (modes == NULL)
return NULL;
for (i = 0; i < num_modes; i++) {
for (i = 0; i < wpa_s->hw.num_modes; i++) {
for (j = 0; j < modes[i].num_channels; j++) {
if (modes[i].channels[j].flag & HOSTAPD_CHAN_DISABLED)
continue;
n = os_realloc(freqs, (count + 2) * sizeof(int));
if (!n)
if (n == NULL)
continue;
freqs = n;
@ -376,10 +375,7 @@ static int * bgscan_learn_get_supp_freqs(struct wpa_supplicant *wpa_s)
count++;
freqs[count] = 0;
}
os_free(modes[i].channels);
os_free(modes[i].rates);
}
os_free(modes);
return freqs;
}

View file

@ -2030,8 +2030,7 @@ struct p2p_oper_class_map {
static int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s,
struct p2p_channels *chan)
{
struct hostapd_hw_modes *modes, *mode;
u16 num_modes, flags;
struct hostapd_hw_modes *mode;
int cla, op;
struct p2p_oper_class_map op_class[] = {
{ HOSTAPD_MODE_IEEE80211G, 81, 1, 13, 1, BW20 },
@ -2049,8 +2048,7 @@ static int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s,
{ -1, 0, 0, 0, 0, BW20 }
};
modes = wpa_drv_get_hw_feature_data(wpa_s, &num_modes, &flags);
if (modes == NULL) {
if (wpa_s->hw.modes == NULL) {
wpa_printf(MSG_DEBUG, "P2P: Driver did not support fetching "
"of all supported channels; assume dualband "
"support");
@ -2064,7 +2062,7 @@ static int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s,
u8 ch;
struct p2p_reg_class *reg = NULL;
mode = get_mode(modes, num_modes, o->mode);
mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, o->mode);
if (mode == NULL)
continue;
for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
@ -2097,8 +2095,6 @@ static int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s,
chan->reg_classes = cla;
ieee80211_sta_free_hw_features(modes, num_modes);
return 0;
}

View file

@ -370,6 +370,22 @@ void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
}
static void free_hw_features(struct wpa_supplicant *wpa_s)
{
int i;
if (wpa_s->hw.modes == NULL)
return;
for (i = 0; i < wpa_s->hw.num_modes; i++) {
os_free(wpa_s->hw.modes[i].channels);
os_free(wpa_s->hw.modes[i].rates);
}
os_free(wpa_s->hw.modes);
wpa_s->hw.modes = NULL;
}
static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
{
bgscan_deinit(wpa_s);
@ -450,6 +466,8 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
gas_query_deinit(wpa_s->gas);
wpa_s->gas = NULL;
free_hw_features(wpa_s);
}
@ -2295,6 +2313,10 @@ next_driver:
return -1;
}
wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
&wpa_s->hw.num_modes,
&wpa_s->hw.flags);
if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
wpa_s->drv_flags = capa.flags;
wpa_s->max_scan_ssids = capa.max_scan_ssids;
@ -2759,23 +2781,6 @@ void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
}
void ieee80211_sta_free_hw_features(struct hostapd_hw_modes *hw_features,
size_t num_hw_features)
{
size_t i;
if (hw_features == NULL)
return;
for (i = 0; i < num_hw_features; i++) {
os_free(hw_features[i].channels);
os_free(hw_features[i].rates);
}
os_free(hw_features);
}
static void add_freq(int *freqs, int *num_freqs, int freq)
{
int i;

View file

@ -500,6 +500,12 @@ struct wpa_supplicant {
unsigned int network_select:1;
unsigned int auto_select:1;
#endif /* CONFIG_INTERWORKING */
struct {
struct hostapd_hw_modes *modes;
u16 num_modes;
u16 flags;
} hw;
};
@ -569,8 +575,6 @@ enum wpa_key_mgmt key_mgmt2driver(int key_mgmt);
enum wpa_cipher cipher_suite2driver(int cipher);
void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s);
void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s);
void ieee80211_sta_free_hw_features(struct hostapd_hw_modes *hw_features,
size_t num_hw_features);
void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid);
int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s);

View file

@ -1121,7 +1121,7 @@ int wpas_wps_init(struct wpa_supplicant *wpa_s)
struct wps_context *wps;
struct wps_registrar_config rcfg;
struct hostapd_hw_modes *modes;
u16 num_modes, flags, m;
u16 m;
wps = os_zalloc(sizeof(*wps));
if (wps == NULL)
@ -1155,16 +1155,15 @@ int wpas_wps_init(struct wpa_supplicant *wpa_s)
WPS_DEV_TYPE_LEN * wps->dev.num_sec_dev_types);
wps->dev.os_version = WPA_GET_BE32(wpa_s->conf->os_version);
modes = wpa_drv_get_hw_feature_data(wpa_s, &num_modes, &flags);
modes = wpa_s->hw.modes;
if (modes) {
for (m = 0; m < num_modes; m++) {
for (m = 0; m < wpa_s->hw.num_modes; m++) {
if (modes[m].mode == HOSTAPD_MODE_IEEE80211B ||
modes[m].mode == HOSTAPD_MODE_IEEE80211G)
wps->dev.rf_bands |= WPS_RF_24GHZ;
else if (modes[m].mode == HOSTAPD_MODE_IEEE80211A)
wps->dev.rf_bands |= WPS_RF_50GHZ;
}
ieee80211_sta_free_hw_features(modes, num_modes);
}
if (wps->dev.rf_bands == 0) {
/*