nl80211: Fix mode settings with split wiphy dump

When the wiphy information is split, there's no guarantee that the
channels are processed before the bitrates; in fact, with the current
kernel it happens the other way around. Therefore, the mode information
isn't set up correctly and there's no 11g mode.

Fix this by doing the 11b/11g determination as part of the
postprocessing.

Signed-hostap: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Johannes Berg 2013-03-19 02:01:46 +02:00 committed by Jouni Malinen
parent 09491b7392
commit c30a4ab045

View file

@ -5082,21 +5082,19 @@ static void phy_info_freq(struct hostapd_hw_modes *mode,
struct hostapd_channel_data *chan, struct hostapd_channel_data *chan,
struct nlattr *tb_freq[]) struct nlattr *tb_freq[])
{ {
enum hostapd_hw_mode m;
chan->freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]); chan->freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
chan->flag = 0; chan->flag = 0;
/* mode is not set */ if (chan->freq < 4000)
if (mode->mode >= NUM_HOSTAPD_MODES) { m = HOSTAPD_MODE_IEEE80211B;
/* crude heuristic */ else if (chan->freq > 50000)
if (chan->freq < 4000) m = HOSTAPD_MODE_IEEE80211AD;
mode->mode = HOSTAPD_MODE_IEEE80211B; else
else if (chan->freq > 50000) m = HOSTAPD_MODE_IEEE80211A;
mode->mode = HOSTAPD_MODE_IEEE80211AD;
else
mode->mode = HOSTAPD_MODE_IEEE80211A;
}
switch (mode->mode) { switch (m) {
case HOSTAPD_MODE_IEEE80211AD: case HOSTAPD_MODE_IEEE80211AD:
chan->chan = (chan->freq - 56160) / 2160; chan->chan = (chan->freq - 56160) / 2160;
break; break;
@ -5220,12 +5218,6 @@ static int phy_info_rates(struct hostapd_hw_modes *mode, struct nlattr *tb)
continue; continue;
mode->rates[idx] = nla_get_u32( mode->rates[idx] = nla_get_u32(
tb_rate[NL80211_BITRATE_ATTR_RATE]); tb_rate[NL80211_BITRATE_ATTR_RATE]);
/* crude heuristic */
if (mode->mode == HOSTAPD_MODE_IEEE80211B &&
mode->rates[idx] > 200)
mode->mode = HOSTAPD_MODE_IEEE80211G;
idx++; idx++;
} }
@ -5303,12 +5295,31 @@ static int phy_info_handler(struct nl_msg *msg, void *arg)
static struct hostapd_hw_modes * static struct hostapd_hw_modes *
wpa_driver_nl80211_add_11b(struct hostapd_hw_modes *modes, u16 *num_modes) wpa_driver_nl80211_postprocess_modes(struct hostapd_hw_modes *modes,
u16 *num_modes)
{ {
u16 m; u16 m;
struct hostapd_hw_modes *mode11g = NULL, *nmodes, *mode; struct hostapd_hw_modes *mode11g = NULL, *nmodes, *mode;
int i, mode11g_idx = -1; int i, mode11g_idx = -1;
/* heuristic to set up modes */
for (m = 0; m < *num_modes; m++) {
if (!modes[m].num_channels)
continue;
if (modes[m].channels[0].freq < 4000) {
modes[m].mode = HOSTAPD_MODE_IEEE80211B;
for (i = 0; i < modes[m].num_rates; i++) {
if (modes[m].rates[i] > 200) {
modes[m].mode = HOSTAPD_MODE_IEEE80211G;
break;
}
}
} else if (modes[m].channels[0].freq > 50000)
modes[m].mode = HOSTAPD_MODE_IEEE80211AD;
else
modes[m].mode = HOSTAPD_MODE_IEEE80211A;
}
/* If only 802.11g mode is included, use it to construct matching /* If only 802.11g mode is included, use it to construct matching
* 802.11b mode data. */ * 802.11b mode data. */
@ -5554,7 +5565,8 @@ wpa_driver_nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags)
if (send_and_recv_msgs(drv, msg, phy_info_handler, &result) == 0) { if (send_and_recv_msgs(drv, msg, phy_info_handler, &result) == 0) {
nl80211_set_ht40_flags(drv, &result); nl80211_set_ht40_flags(drv, &result);
return wpa_driver_nl80211_add_11b(result.modes, num_modes); return wpa_driver_nl80211_postprocess_modes(result.modes,
num_modes);
} }
msg = NULL; msg = NULL;
nla_put_failure: nla_put_failure: