[PATCH V3 6/8] HE: add HE to support to channel management

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Verify if the chwidth/mode is supported by the HW by checking the
capabilities.

Signed-off-by: Shashidhar Lakkavalli <slakkavalli@xxxxxxxxx>
Signed-off-by: John Crispin <john@xxxxxxxxxxx>
---
 src/ap/acs.c                    |  6 +--
 src/ap/ap_drv_ops.c             | 17 ++++----
 src/ap/ap_drv_ops.h             |  4 +-
 src/ap/beacon.c                 |  5 ++-
 src/ap/dfs.c                    | 13 +++---
 src/ap/drv_callbacks.c          |  3 +-
 src/ap/hostapd.c                | 12 ++++--
 src/ap/hw_features.c            | 15 ++++++-
 src/ap/neighbor_db.c            |  9 +++--
 src/common/hw_features_common.c | 87 +++++++++++++++++++++++++++++++++++------
 src/common/hw_features_common.h |  5 ++-
 src/common/ieee802_11_defs.h    |  9 +++++
 src/drivers/driver.h            |  5 +++
 src/drivers/driver_nl80211.c    | 11 +++---
 wpa_supplicant/wpa_supplicant.c |  4 +-
 15 files changed, 153 insertions(+), 52 deletions(-)

diff --git a/src/ap/acs.c b/src/ap/acs.c
index 4414ad6a3..9f1378195 100644
--- a/src/ap/acs.c
+++ b/src/ap/acs.c
@@ -594,7 +594,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
 	    iface->conf->secondary_channel)
 		n_chans = 2;
 
-	if (iface->conf->ieee80211ac) {
+	if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) {
 		switch (hostapd_get_oper_chwidth(iface->conf)) {
 		case CHANWIDTH_80MHZ:
 			n_chans = 4;
@@ -607,7 +607,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
 
 	bw = num_chan_to_bw(n_chans);
 
-	/* TODO: VHT80+80. Update acs_adjust_center_freq() too. */
+	/* TODO: VHT/HE80+80. Update acs_adjust_center_freq() too. */
 
 	wpa_printf(MSG_DEBUG,
 		   "ACS: Survey analysis for selected bandwidth %d MHz", bw);
@@ -647,7 +647,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
 		}
 
 		if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
-		    iface->conf->ieee80211ac) {
+		    (iface->conf->ieee80211ac || iface->conf->ieee80211ax)) {
 			if (hostapd_get_oper_chwidth(iface->conf) ==
 			    CHANWIDTH_80MHZ &&
 			    !acs_usable_vht80_chan(chan)) {
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index 7a8d160d8..a58e23076 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -542,18 +542,19 @@ int hostapd_flush(struct hostapd_data *hapd)
 
 
 int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
-		     int freq, int channel, int ht_enabled, int vht_enabled,
+		     int freq, int channel, int ht_enabled, int vht_enabled, int he_enabled,
 		     int sec_channel_offset, int oper_chwidth,
 		     int center_segment0, int center_segment1)
 {
 	struct hostapd_freq_params data;
 
 	if (hostapd_set_freq_params(&data, mode, freq, channel, ht_enabled,
-				    vht_enabled, sec_channel_offset,
+				    vht_enabled, he_enabled, sec_channel_offset,
 				    oper_chwidth,
 				    center_segment0, center_segment1,
 				    hapd->iface->current_mode ?
-				    hapd->iface->current_mode->vht_capab : 0))
+				    hapd->iface->current_mode->vht_capab : 0,
+				    &hapd->iface->current_mode->he_capab))
 		return -1;
 
 	if (hapd->driver == NULL)
@@ -780,7 +781,7 @@ int hostapd_drv_send_action_addr3_ap(struct hostapd_data *hapd,
 
 int hostapd_start_dfs_cac(struct hostapd_iface *iface,
 			  enum hostapd_hw_mode mode, int freq,
-			  int channel, int ht_enabled, int vht_enabled,
+			  int channel, int ht_enabled, int vht_enabled, int he_enabled,
 			  int sec_channel_offset, int oper_chwidth,
 			  int center_segment0, int center_segment1)
 {
@@ -798,10 +799,11 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
 	}
 
 	if (hostapd_set_freq_params(&data, mode, freq, channel, ht_enabled,
-				    vht_enabled, sec_channel_offset,
+				    vht_enabled, he_enabled, sec_channel_offset,
 				    oper_chwidth, center_segment0,
 				    center_segment1,
-				    iface->current_mode->vht_capab)) {
+				    iface->current_mode->vht_capab,
+				    &iface->current_mode->he_capab)) {
 		wpa_printf(MSG_ERROR, "Can't set freq params");
 		return -1;
 	}
@@ -927,7 +929,8 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd)
 
 	/* Note: VHT20 is defined by combination of ht_capab & oper_chwidth
 	 */
-	if (hapd->iface->conf->ieee80211ac && params.ht40_enabled) {
+	if ((hapd->iface->conf->ieee80211ax || hapd->iface->conf->ieee80211ac)
+	     && params.ht40_enabled) {
 		u8 oper_chwidth = hostapd_get_oper_chwidth(hapd->iface->conf);
 
 		if (oper_chwidth == CHANWIDTH_80MHZ)
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index 33cfbc721..d4481fd81 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -65,7 +65,7 @@ int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
 int hostapd_flush(struct hostapd_data *hapd);
 int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
 		     int freq, int channel, int ht_enabled, int vht_enabled,
-		     int sec_channel_offset, int oper_chwidth,
+		     int he_enabled, int sec_channel_offset, int oper_chwidth,
 		     int center_segment0, int center_segment1);
 int hostapd_set_rts(struct hostapd_data *hapd, int rts);
 int hostapd_set_frag(struct hostapd_data *hapd, int frag);
@@ -125,7 +125,7 @@ int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr,
 		      u8 *tspec_ie, size_t tspec_ielen);
 int hostapd_start_dfs_cac(struct hostapd_iface *iface,
 			  enum hostapd_hw_mode mode, int freq,
-			  int channel, int ht_enabled, int vht_enabled,
+			  int channel, int ht_enabled, int vht_enabled, int he_enabled,
 			  int sec_channel_offset, int oper_chwidth,
 			  int center_segment0, int center_segment1);
 int hostapd_drv_do_acs(struct hostapd_data *hapd);
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index ef5bce36c..d1e5ff853 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -1424,12 +1424,13 @@ int ieee802_11_set_beacon(struct hostapd_data *hapd)
 	if (iface->current_mode &&
 	    hostapd_set_freq_params(&freq, iconf->hw_mode, iface->freq,
 				    iconf->channel, iconf->ieee80211n,
-				    iconf->ieee80211ac,
+				    iconf->ieee80211ac, iconf->ieee80211ax,
 				    iconf->secondary_channel,
 				    hostapd_get_oper_chwidth(iconf),
 				    hostapd_get_oper_centr_freq_seg0_idx(iconf),
 				    hostapd_get_oper_centr_freq_seg1_idx(iconf),
-				    iface->current_mode->vht_capab) == 0)
+				    iface->current_mode->vht_capab,
+				    &iface->current_mode->he_capab) == 0)
 		params.freq = &freq;
 
 	res = hostapd_drv_set_ap(hapd, &params);
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index 5e1cbb980..55cf53e2e 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -28,7 +28,7 @@ static int dfs_get_used_n_chans(struct hostapd_iface *iface, int *seg1)
 	if (iface->conf->ieee80211n && iface->conf->secondary_channel)
 		n_chans = 2;
 
-	if (iface->conf->ieee80211ac) {
+	if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) {
 		switch (hostapd_get_oper_chwidth(iface->conf)) {
 		case CHANWIDTH_USE_HT:
 			break;
@@ -238,7 +238,7 @@ static void dfs_adjust_center_freq(struct hostapd_iface *iface,
 				   u8 *oper_centr_freq_seg0_idx,
 				   u8 *oper_centr_freq_seg1_idx)
 {
-	if (!iface->conf->ieee80211ac)
+	if (!iface->conf->ieee80211ac && !iface->conf->ieee80211ax)
 		return;
 
 	if (!chan)
@@ -288,8 +288,8 @@ static int dfs_get_start_chan_idx(struct hostapd_iface *iface, int *seg1_start)
 	if (iface->conf->ieee80211n && iface->conf->secondary_channel == -1)
 		channel_no -= 4;
 
-	/* VHT */
-	if (iface->conf->ieee80211ac) {
+	/* VHT/HE */
+	if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) {
 		switch (hostapd_get_oper_chwidth(iface->conf)) {
 		case CHANWIDTH_USE_HT:
 			break;
@@ -746,6 +746,7 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
 				    iface->conf->channel,
 				    iface->conf->ieee80211n,
 				    iface->conf->ieee80211ac,
+				    iface->conf->ieee80211ax,
 				    iface->conf->secondary_channel,
 				    hostapd_get_oper_chwidth(iface->conf),
 				    hostapd_get_oper_centr_freq_seg0_idx(iface->conf),
@@ -958,11 +959,13 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
 				      channel->chan,
 				      iface->conf->ieee80211n,
 				      iface->conf->ieee80211ac,
+				      iface->conf->ieee80211ax,
 				      secondary_channel,
 				      hostapd_get_oper_chwidth(iface->conf),
 				      oper_centr_freq_seg0_idx,
 				      oper_centr_freq_seg1_idx,
-				      iface->current_mode->vht_capab);
+				      iface->current_mode->vht_capab,
+				      &iface->current_mode->he_capab);
 
 	if (err) {
 		wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params");
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index f53750a88..1db48024d 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -953,7 +953,7 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd,
 		goto out;
 	}
 
-	if (hapd->iface->conf->ieee80211ac) {
+	if (hapd->iface->conf->ieee80211ac || hapd->iface->conf->ieee80211ax) {
 		/* set defaults for backwards compatibility */
 		hostapd_set_oper_centr_freq_seg0_idx(hapd->iconf, 0);
 		hostapd_set_oper_centr_freq_seg0_idx(hapd->iconf, 0);
@@ -965,7 +965,6 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd,
 			if (acs_res->vht_seg1_center_ch == 0) {
 				hostapd_set_oper_centr_freq_seg0_idx(hapd->iconf, acs_res->vht_seg0_center_ch);
 				hostapd_set_oper_chwidth(hapd->iconf, CHANWIDTH_160MHZ);
-					CHANWIDTH_160MHZ;
 			} else {
 				hostapd_set_oper_centr_freq_seg0_idx(hapd->iconf, acs_res->vht_seg0_center_ch);
 				hostapd_set_oper_centr_freq_seg0_idx(hapd->iconf, acs_res->vht_seg1_center_ch);
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 1c21ca9ff..5b0b7f03f 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -1861,6 +1861,7 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
 				     hapd->iconf->channel,
 				     hapd->iconf->ieee80211n,
 				     hapd->iconf->ieee80211ac,
+				     hapd->iconf->ieee80211ax,
 				     hapd->iconf->secondary_channel,
 				     hostapd_get_oper_chwidth(hapd->iconf),
 				     hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf),
@@ -3205,12 +3206,13 @@ static int hostapd_change_config_freq(struct hostapd_data *hapd,
 	    hostapd_set_freq_params(old_params, conf->hw_mode,
 				    hostapd_hw_get_freq(hapd, conf->channel),
 				    conf->channel, conf->ieee80211n,
-				    conf->ieee80211ac,
+				    conf->ieee80211ac, conf->ieee80211ax,
 				    conf->secondary_channel,
 				    hostapd_get_oper_chwidth(conf),
 				    hostapd_get_oper_centr_freq_seg0_idx(conf),
 				    hostapd_get_oper_centr_freq_seg1_idx(conf),
-				    conf->vht_capab))
+				    conf->vht_capab,
+				    &hapd->iface->current_mode->he_capab))
 		return -1;
 
 	switch (params->bandwidth) {
@@ -3282,10 +3284,11 @@ static int hostapd_fill_csa_settings(struct hostapd_data *hapd,
 		    &hapd->iface->cs_oper_class,
 		    &chan) == NUM_HOSTAPD_MODES) {
 		wpa_printf(MSG_DEBUG,
-			   "invalid frequency for channel switch (freq=%d, sec_channel_offset=%d, vht_enabled=%d)",
+			   "invalid frequency for channel switch (freq=%d, sec_channel_offset=%d, vht_enabled=%d, he_enabled=%d)",
 			   settings->freq_params.freq,
 			   settings->freq_params.sec_channel_offset,
-			   settings->freq_params.vht_enabled);
+			   settings->freq_params.vht_enabled,
+			   settings->freq_params.he_enabled);
 		return -1;
 	}
 
@@ -3423,6 +3426,7 @@ hostapd_switch_channel_fallback(struct hostapd_iface *iface,
 	hostapd_set_oper_chwidth(iface->conf, bw);
 	iface->conf->ieee80211n = freq_params->ht_enabled;
 	iface->conf->ieee80211ac = freq_params->vht_enabled;
+	iface->conf->ieee80211ax = freq_params->he_enabled;
 
 	/*
 	 * cs_params must not be cleared earlier because the freq_params
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index 015f29808..27c863a65 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -654,6 +654,13 @@ static int ieee80211ac_supported_vht_capab(struct hostapd_iface *iface)
 }
 #endif /* CONFIG_IEEE80211AC */
 
+#ifdef CONFIG_IEEE80211AX
+static int ieee80211ax_supported_he_capab(struct hostapd_iface *iface)
+{
+	return 1;
+}
+#endif /* CONFIG_IEEE80211AC */
+
 #endif /* CONFIG_IEEE80211N */
 
 
@@ -674,6 +681,11 @@ int hostapd_check_ht_capab(struct hostapd_iface *iface)
 
 	if (!ieee80211n_supported_ht_capab(iface))
 		return -1;
+#ifdef CONFIG_IEEE80211AX
+	if (iface->conf->ieee80211ax &&
+	    !ieee80211ax_supported_he_capab(iface))
+		return -1;
+#endif /* CONFIG_IEEE80211AX */
 #ifdef CONFIG_IEEE80211AC
 	if (iface->conf->ieee80211ac &&
 	    !ieee80211ac_supported_vht_capab(iface))
@@ -862,12 +874,13 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
 		return -1;
 
 	if ((iface->conf->hw_mode == HOSTAPD_MODE_IEEE80211G ||
-	     iface->conf->ieee80211n || iface->conf->ieee80211ac) &&
+	     iface->conf->ieee80211n || iface->conf->ieee80211ac || iface->conf->ieee80211ax) &&
 	    iface->conf->channel == 14) {
 		wpa_printf(MSG_INFO, "Disable OFDM/HT/VHT on channel 14");
 		iface->conf->hw_mode = HOSTAPD_MODE_IEEE80211B;
 		iface->conf->ieee80211n = 0;
 		iface->conf->ieee80211ac = 0;
+		iface->conf->ieee80211ax = 0;
 	}
 
 	iface->current_mode = NULL;
diff --git a/src/ap/neighbor_db.c b/src/ap/neighbor_db.c
index 82aa99e87..c1aa3163f 100644
--- a/src/ap/neighbor_db.c
+++ b/src/ap/neighbor_db.c
@@ -140,15 +140,15 @@ void hostapd_free_neighbor_db(struct hostapd_data *hapd)
 
 #ifdef NEED_AP_MLME
 static enum nr_chan_width hostapd_get_nr_chan_width(struct hostapd_data *hapd,
-						    int ht, int vht)
+						    int ht, int vht, int he)
 {
 	u8 oper_chwidth = hostapd_get_oper_chwidth(hapd->iconf);
 
-	if (!ht && !vht)
+	if (!ht && !vht && !he)
 		return NR_CHAN_WIDTH_20;
 	if (!hapd->iconf->secondary_channel)
 		return NR_CHAN_WIDTH_20;
-	if (!vht || oper_chwidth == CHANWIDTH_USE_HT)
+	if ((!vht && !he) || oper_chwidth == CHANWIDTH_USE_HT)
 		return NR_CHAN_WIDTH_40;
 	if (oper_chwidth == CHANWIDTH_80MHZ)
 		return NR_CHAN_WIDTH_80;
@@ -167,6 +167,7 @@ void hostapd_neighbor_set_own_report(struct hostapd_data *hapd)
 	u16 capab = hostapd_own_capab_info(hapd);
 	int ht = hapd->iconf->ieee80211n && !hapd->conf->disable_11n;
 	int vht = hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac;
+	int he = hapd->iconf->ieee80211ax;
 	struct wpa_ssid_value ssid;
 	u8 channel, op_class;
 	u8 center_freq1_idx = 0, center_freq2_idx = 0;
@@ -212,7 +213,7 @@ void hostapd_neighbor_set_own_report(struct hostapd_data *hapd)
 					  &op_class, &channel) ==
 	    NUM_HOSTAPD_MODES)
 		return;
-	width = hostapd_get_nr_chan_width(hapd, ht, vht);
+	width = hostapd_get_nr_chan_width(hapd, ht, vht, he);
 	if (vht) {
 		center_freq1_idx = hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf);
 		if (width == NR_CHAN_WIDTH_80P80)
diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c
index aa430f2e2..c18d99daa 100644
--- a/src/common/hw_features_common.c
+++ b/src/common/hw_features_common.c
@@ -358,12 +358,25 @@ int check_40mhz_2g4(struct hostapd_hw_modes *mode,
 }
 
 
+int hostapd_set_freq_chwidth(struct hostapd_freq_params *data,
+			     enum hostapd_hw_mode mode,
+			     int freq, int channel, int ht_enabled,
+			     int sec_channel_offset,
+			     int oper_chwidth, int center_segment0,
+			     int center_segment1, u32 vht_caps)
+{
+
+	return 0;
+}
+
+
 int hostapd_set_freq_params(struct hostapd_freq_params *data,
 			    enum hostapd_hw_mode mode,
 			    int freq, int channel, int ht_enabled,
-			    int vht_enabled, int sec_channel_offset,
+			    int vht_enabled, int he_enabled, int sec_channel_offset,
 			    int oper_chwidth, int center_segment0,
-			    int center_segment1, u32 vht_caps)
+			    int center_segment1, u32 vht_caps,
+			    struct he_capabilities *he_cap)
 {
 	os_memset(data, 0, sizeof(*data));
 	data->mode = mode;
@@ -371,18 +384,50 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
 	data->channel = channel;
 	data->ht_enabled = ht_enabled;
 	data->vht_enabled = vht_enabled;
+	data->he_enabled = he_enabled;
 	data->sec_channel_offset = sec_channel_offset;
 	data->center_freq1 = freq + sec_channel_offset * 10;
 	data->center_freq2 = 0;
 	data->bandwidth = sec_channel_offset ? 40 : 20;
 
-	if (data->vht_enabled) switch (oper_chwidth) {
+	if (data->he_enabled) switch (oper_chwidth) {
 	case CHANWIDTH_USE_HT:
-		if (center_segment1 ||
-		    (center_segment0 != 0 &&
-		     5000 + center_segment0 * 5 != data->center_freq1 &&
-		     2407 + center_segment0 * 5 != data->center_freq1))
+		if (mode < HOSTAPD_MODE_IEEE80211A) {
+			if (!(he_cap->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
+			      HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G)) {
+				wpa_printf(MSG_ERROR,
+					   "40 channel width is not supported!");
+				return -1;
+			}
+			break;
+		}
+		/* fall through */
+	case CHANWIDTH_80MHZ:
+		if (!(he_cap->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
+		      HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G)) {
+			wpa_printf(MSG_ERROR,
+				   "40/80 channel width is not supported!");
+			return -1;
+		}
+		break;
+	case CHANWIDTH_80P80MHZ:
+		if (!(he_cap->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
+		      HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G)) {
+			wpa_printf(MSG_ERROR,
+				   "80+80 channel width is not supported!");
 			return -1;
+		}
+		break;
+	case CHANWIDTH_160MHZ:
+		if (!(he_cap->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
+		      HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G)) {
+			wpa_printf(MSG_ERROR,
+				   "160 channel width is not supported!");
+			return -1;
+		}
+		break;
+	} else if (data->vht_enabled) switch (oper_chwidth) {
+	case CHANWIDTH_USE_HT:
 		break;
 	case CHANWIDTH_80P80MHZ:
 		if (!(vht_caps & VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)) {
@@ -390,6 +435,28 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
 				   "80+80 channel width is not supported!");
 			return -1;
 		}
+		/* fall through */
+	case CHANWIDTH_80MHZ:
+		break;
+	case CHANWIDTH_160MHZ:
+		if (!(vht_caps & (VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
+				  VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))) {
+			wpa_printf(MSG_ERROR,
+				   "160MHZ channel width is not supported!");
+			return -1;
+		}
+		break;
+	}
+
+	switch (oper_chwidth) {
+	case CHANWIDTH_USE_HT:
+		if (center_segment1 ||
+		    (center_segment0 != 0 &&
+		     5000 + center_segment0 * 5 != data->center_freq1 &&
+		     2407 + center_segment0 * 5 != data->center_freq1))
+			return -1;
+		break;
+	case CHANWIDTH_80P80MHZ:
 		if (center_segment1 == center_segment0 + 4 ||
 		    center_segment1 == center_segment0 - 4)
 			return -1;
@@ -434,12 +501,6 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
 		break;
 	case CHANWIDTH_160MHZ:
 		data->bandwidth = 160;
-		if (!(vht_caps & (VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
-				  VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))) {
-			wpa_printf(MSG_ERROR,
-				   "160MHZ channel width is not supported!");
-			return -1;
-		}
 		if (center_segment1)
 			return -1;
 		if (!sec_channel_offset)
diff --git a/src/common/hw_features_common.h b/src/common/hw_features_common.h
index d3efe77f2..119319311 100644
--- a/src/common/hw_features_common.h
+++ b/src/common/hw_features_common.h
@@ -32,9 +32,10 @@ int check_40mhz_2g4(struct hostapd_hw_modes *mode,
 int hostapd_set_freq_params(struct hostapd_freq_params *data,
 			    enum hostapd_hw_mode mode,
 			    int freq, int channel, int ht_enabled,
-			    int vht_enabled, int sec_channel_offset,
+			    int vht_enabled, int he_enabled, int sec_channel_offset,
 			    int oper_chwidth, int center_segment0,
-			    int center_segment1, u32 vht_caps);
+			    int center_segment1, u32 vht_caps,
+			    struct he_capabilities *he_caps);
 void set_disable_ht40(struct ieee80211_ht_capabilities *htcaps,
 		      int disabled);
 int ieee80211ac_cap_check(u32 hw, u32 conf);
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index f5f43d1b0..ed6a9132e 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -2138,6 +2138,15 @@ struct ieee80211_spatial_reuse {
 } STRUCT_PACKED;
 
 /* HE Capabilities Information defines */
+
+#define HE_PHYCAP_CHANNEL_WIDTH_SET_IDX			0
+#define HE_PHYCAP_CHANNEL_WIDTH_MASK			((u8) (BIT(1) | BIT(2) | \
+							      BIT(3) | BIT(4)))
+#define HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G         ((u8) BIT(1))
+#define HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G	((u8) BIT(2))
+#define HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G	((u8) BIT(3))
+#define HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G	((u8) BIT(4))
+
 #define HE_PHYCAP_SU_BEAMFORMER_CAPAB_IDX	3
 #define HE_PHYCAP_SU_BEAMFORMER_CAPAB		((u8) BIT(7))
 #define HE_PHYCAP_SU_BEAMFORMEE_CAPAB_IDX	4
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 376e65c4d..20f583900 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -701,6 +701,11 @@ struct hostapd_freq_params {
 	int vht_enabled;
 
 	/**
+	 * he_enabled - Whether HE is enabled
+	 */
+	int he_enabled;
+
+	/**
 	 * center_freq1 - Segment 0 center frequency in MHz
 	 *
 	 * Valid for both HT and VHT.
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 94c77b470..640d205c2 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -4352,10 +4352,11 @@ static int nl80211_put_freq_params(struct nl_msg *msg,
 	if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq->freq))
 		return -ENOBUFS;
 
+	wpa_printf(MSG_DEBUG, "  * he_enabled=%d", freq->he_enabled);
 	wpa_printf(MSG_DEBUG, "  * vht_enabled=%d", freq->vht_enabled);
 	wpa_printf(MSG_DEBUG, "  * ht_enabled=%d", freq->ht_enabled);
 
-	if (freq->vht_enabled) {
+	if (freq->vht_enabled || freq->he_enabled) {
 		enum nl80211_chan_width cw;
 
 		wpa_printf(MSG_DEBUG, "  * bandwidth=%d", freq->bandwidth);
@@ -4430,8 +4431,8 @@ static int nl80211_set_channel(struct i802_bss *bss,
 	int ret;
 
 	wpa_printf(MSG_DEBUG,
-		   "nl80211: Set freq %d (ht_enabled=%d, vht_enabled=%d, bandwidth=%d MHz, cf1=%d MHz, cf2=%d MHz)",
-		   freq->freq, freq->ht_enabled, freq->vht_enabled,
+		   "nl80211: Set freq %d (ht_enabled=%d, vht_enabled=%d, he_enabled=%d, bandwidth=%d MHz, cf1=%d MHz, cf2=%d MHz)",
+		   freq->freq, freq->ht_enabled, freq->vht_enabled, freq->he_enabled,
 		   freq->bandwidth, freq->center_freq1, freq->center_freq2);
 
 	msg = nl80211_drv_msg(drv, 0, set_chan ? NL80211_CMD_SET_CHANNEL :
@@ -8382,8 +8383,8 @@ static int nl80211_start_radar_detection(void *priv,
 	struct nl_msg *msg;
 	int ret;
 
-	wpa_printf(MSG_DEBUG, "nl80211: Start radar detection (CAC) %d MHz (ht_enabled=%d, vht_enabled=%d, bandwidth=%d MHz, cf1=%d MHz, cf2=%d MHz)",
-		   freq->freq, freq->ht_enabled, freq->vht_enabled,
+	wpa_printf(MSG_DEBUG, "nl80211: Start radar detection (CAC) %d MHz (ht_enabled=%d, vht_enabled=%d, he_enabled=%d, bandwidth=%d MHz, cf1=%d MHz, cf2=%d MHz)",
+		   freq->freq, freq->ht_enabled, freq->vht_enabled, freq->he_enabled,
 		   freq->bandwidth, freq->center_freq1, freq->center_freq2);
 
 	if (!(drv->capa.flags & WPA_DRIVER_FLAGS_RADAR)) {
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index ee612303f..2da082a9e 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -2406,9 +2406,9 @@ skip_ht40:
 
 	if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
 				    freq->channel, freq->ht_enabled,
-				    vht_freq.vht_enabled,
+				    vht_freq.vht_enabled, 0,
 				    freq->sec_channel_offset,
-				    chwidth, seg0, seg1, vht_caps) != 0)
+				    chwidth, seg0, seg1, vht_caps, NULL) != 0)
 		return;
 
 	*freq = vht_freq;
-- 
2.11.0


_______________________________________________
Hostap mailing list
Hostap@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/hostap



[Index of Archives]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux