[PATCH] driver_nl80211: fix mode settings

Johannes Berg johannes at sipsolutions.net
Mon Mar 18 17:20:57 EDT 2013


From: Johannes Berg <johannes.berg at intel.com>

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 at intel.com>
---
 src/drivers/driver_nl80211.c | 50 +++++++++++++++++++++++++++-----------------
 1 file changed, 31 insertions(+), 19 deletions(-)

diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 4cf4e41..b31196c 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -5113,21 +5113,19 @@ static void phy_info_freq(struct hostapd_hw_modes *mode,
 			  struct hostapd_channel_data *chan,
 			  struct nlattr *tb_freq[])
 {
+	enum hostapd_hw_mode m;
+
 	chan->freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
 	chan->flag = 0;
 
-	/* mode is not set */
-	if (mode->mode >= NUM_HOSTAPD_MODES) {
-		/* crude heuristic */
-		if (chan->freq < 4000)
-			mode->mode = HOSTAPD_MODE_IEEE80211B;
-		else if (chan->freq > 50000)
-			mode->mode = HOSTAPD_MODE_IEEE80211AD;
-		else
-			mode->mode = HOSTAPD_MODE_IEEE80211A;
-	}
+	if (chan->freq < 4000)
+		m = HOSTAPD_MODE_IEEE80211B;
+	else if (chan->freq > 50000)
+		m = HOSTAPD_MODE_IEEE80211AD;
+	else
+		m = HOSTAPD_MODE_IEEE80211A;
 
-	switch (mode->mode) {
+	switch (m) {
 	case HOSTAPD_MODE_IEEE80211AD:
 		chan->chan = (chan->freq - 56160) / 2160;
 		break;
@@ -5251,12 +5249,6 @@ static int phy_info_rates(struct hostapd_hw_modes *mode, struct nlattr *tb)
 			continue;
 		mode->rates[idx] = nla_get_u32(
 			tb_rate[NL80211_BITRATE_ATTR_RATE]);
-
-		/* crude heuristic */
-		if (mode->mode == HOSTAPD_MODE_IEEE80211B &&
-		    mode->rates[idx] > 200)
-			mode->mode = HOSTAPD_MODE_IEEE80211G;
-
 		idx++;
 	}
 
@@ -5334,12 +5326,31 @@ static int phy_info_handler(struct nl_msg *msg, void *arg)
 
 
 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;
 	struct hostapd_hw_modes *mode11g = NULL, *nmodes, *mode;
 	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
 	 * 802.11b mode data. */
 
@@ -5585,7 +5596,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) {
 		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;
  nla_put_failure:
-- 
1.8.0



More information about the HostAP mailing list