diff mbox

[RFC,8/8] ibss/mesh: enable HT40 if supported

Message ID 1420717716-27070-8-git-send-email-janusz.dziedzic@tieto.com
State Accepted
Headers show

Commit Message

Janusz.Dziedzic@tieto.com Jan. 8, 2015, 11:48 a.m. UTC
Setup HT40+/HT40- if supported by driver.

Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
---
 wpa_supplicant/wpa_supplicant.c | 102 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 101 insertions(+), 1 deletion(-)

Comments

Jouni Malinen Jan. 10, 2015, 4:01 p.m. UTC | #1
On Thu, Jan 08, 2015 at 12:48:36PM +0100, Janusz Dziedzic wrote:
> Setup HT40+/HT40- if supported by driver.

Thanks, applied with some fixes.
diff mbox

Patch

diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 1f29bb9..27a40bd 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -33,6 +33,7 @@ 
 #include "rsn_supp/pmksa_cache.h"
 #include "common/wpa_ctrl.h"
 #include "common/ieee802_11_defs.h"
+#include "common/hw_features_common.h"
 #include "p2p/p2p.h"
 #include "blacklist.h"
 #include "wpas_glue.h"
@@ -1599,8 +1600,11 @@  static void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s, const struct wpa_
 {
 	enum hostapd_hw_mode hw_mode;
 	struct hostapd_hw_modes *mode = NULL;
+	int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157, 184, 192 };
+	struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
+	struct wpa_scan_results *scan_res;
+	int i, chan_idx, ht40 = -1, res;
 	u8 channel;
-	int i;
 
 	freq->freq = ssid->frequency;
 
@@ -1622,6 +1626,102 @@  static void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s, const struct wpa_
 
 	freq->ht_enabled = ht_supported(mode);
 
+	if (!freq->ht_enabled)
+		return;
+
+	/* Setup higher BW only for 5GHz */
+	if (mode->mode != HOSTAPD_MODE_IEEE80211A)
+		return;
+
+	scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
+	if (scan_res == NULL)
+		return;
+
+	for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
+		pri_chan = &mode->channels[chan_idx];
+		if (pri_chan->chan == channel)
+			break;
+	}
+
+	if (chan_idx == mode->num_channels)
+		return;
+
+	/* Check primary channel flags */
+	if (pri_chan->flag & HOSTAPD_CHAN_DISABLED)
+		return;
+
+	if (pri_chan->flag & HOSTAPD_CHAN_NO_IR)
+		return;
+
+	/* Check/setup HT40+/HT40- */
+	for (i = 0; i < ARRAY_SIZE(ht40plus); i++) {
+		if (ht40plus[i] == channel) {
+			ht40 = 1;
+			break;
+		}
+	}
+
+	/* Find secondary channel */
+	for (i = 0; i < mode->num_channels; i++) {
+		sec_chan = &mode->channels[i];
+		if (sec_chan->chan == channel + ht40 * 4)
+			break;
+	}
+
+	if (sec_chan->chan != pri_chan->chan + ht40 * 4)
+		return;
+
+	/* Check secondary channel flags */
+	if (sec_chan->flag & HOSTAPD_CHAN_DISABLED)
+		return;
+
+	if (sec_chan->flag & HOSTAPD_CHAN_NO_IR)
+		return;
+
+	freq->channel = pri_chan->chan;
+
+	switch (ht40) {
+	case -1:
+		if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
+			return;
+		freq->sec_channel_offset = -1;
+		break;
+	case 1:
+		if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
+			return;
+		freq->sec_channel_offset = 1;
+		break;
+	default:
+		break;
+	}
+
+	if (freq->sec_channel_offset) {
+		res = check_40mhz_5g(mode, scan_res, pri_chan->chan, sec_chan->chan);
+		switch (res) {
+		case 0:
+			/* Back to HT20 */
+			freq->sec_channel_offset = 0;
+			break;
+		case 1:
+			/* Configuration allowed */
+			break;
+		case 2:
+			/* Switch pri/sec channels */
+			freq->freq = hw_get_freq(mode, sec_chan->chan);
+			freq->sec_channel_offset = freq->sec_channel_offset * (-1);
+			freq->channel = sec_chan->chan;
+			break;
+		default:
+			freq->sec_channel_offset = 0;
+			break;
+		}
+	}
+
+	wpa_scan_results_free(scan_res);
+
+	wpa_printf(MSG_DEBUG, "ibss mesh setup freq channel %d, sec_channel_offset %d",
+		   freq->channel, freq->sec_channel_offset);
+
 	return;
 }