[PATCH v8 2/5] hostapd: Update hostapd_is_usable_chans for {160,320}MHz chan width

Lorenzo Bianconi lorenzo at kernel.org
Thu Nov 28 00:08:32 PST 2024


From: Allen Ye <allen.ye at mediatek.com>

Update hostapd_is_usable_chans utility routine logic to take into
account 160MHz and 320MHz channel width.
This is a preliminary patch to introduce AFC support.

Tested-by: Felix Fietkau <nbd at nbd.name>
Tested-by: Krishna Chaitanya <chaitanya.mgit at gmail.com>
Signed-off-by: Allen Ye <allen.ye at mediatek.com>
---
 src/ap/hw_features.c | 110 +++++++++++++++++++++++++++----------------
 src/ap/hw_features.h |   7 +++
 2 files changed, 76 insertions(+), 41 deletions(-)

diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index cef38173e..7e0b2af1d 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -1019,28 +1019,14 @@ static bool hostapd_is_usable_punct_bitmap(struct hostapd_iface *iface)
  * 0 = not usable
  * -1 = not currently usable due to 6 GHz NO-IR
  */
-static int hostapd_is_usable_chans(struct hostapd_iface *iface)
+int hostapd_is_usable_chans(struct hostapd_iface *iface)
 {
-	int secondary_freq;
-	struct hostapd_channel_data *pri_chan;
-	int err, err2;
+	int err, central, oper_chwidth;
+	int start_chan, start_freq, chan_num, i;
 
 	if (!iface->current_mode)
 		return 0;
-	pri_chan = hw_get_channel_freq(iface->current_mode->mode,
-				       iface->freq, NULL,
-				       iface->hw_features,
-				       iface->num_hw_features);
-	if (!pri_chan) {
-		wpa_printf(MSG_ERROR, "Primary frequency not present");
-		return 0;
-	}
 
-	err = hostapd_is_usable_chan(iface, pri_chan->freq, 1);
-	if (err <= 0) {
-		wpa_printf(MSG_ERROR, "Primary frequency not allowed");
-		return err;
-	}
 	err = hostapd_is_usable_edmg(iface);
 	if (err <= 0)
 		return err;
@@ -1048,38 +1034,80 @@ static int hostapd_is_usable_chans(struct hostapd_iface *iface)
 	if (!hostapd_is_usable_punct_bitmap(iface))
 		return 0;
 
-	if (!iface->conf->secondary_channel)
-		return 1;
+	oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
+	if (oper_chwidth == CONF_OPER_CHWIDTH_USE_HT) {
+		int chan = hw_get_chan(iface->current_mode->mode, iface->freq,
+				       iface->hw_features, iface->num_hw_features);
+		if (!chan) {
+			wpa_printf(MSG_ERROR, "Primary channel not present");
+			return 0;
+		}
 
-	err = hostapd_is_usable_chan(iface, iface->freq +
-				     iface->conf->secondary_channel * 20, 0);
-	if (err > 0) {
-		if (iface->conf->secondary_channel == 1 &&
-		    (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P))
-			return 1;
-		if (iface->conf->secondary_channel == -1 &&
-		    (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40M))
-			return 1;
+		switch (iface->conf->secondary_channel) {
+			case 1:
+				start_chan = chan;
+				chan_num = 2;
+				break;
+			case -1:
+				start_chan = chan - 4;
+				chan_num = 2;
+				break;
+			default:
+				start_chan = chan;
+				chan_num = 1;
+		}
+	} else {
+		switch (oper_chwidth) {
+			case CONF_OPER_CHWIDTH_80MHZ:
+			case CONF_OPER_CHWIDTH_80P80MHZ:
+				chan_num = 4;
+				break;
+			case CONF_OPER_CHWIDTH_160MHZ:
+				chan_num = 8;
+				break;
+			case CONF_OPER_CHWIDTH_320MHZ:
+				chan_num = 16;
+				break;
+			default:
+				return 0;
+		}
+		central = hostapd_get_oper_centr_freq_seg0_idx(iface->conf);
+		start_chan = central - chan_num * 2 + 2;
 	}
-	if (!iface->conf->ht40_plus_minus_allowed)
-		return err;
+	start_freq = hw_get_freq(iface->current_mode, start_chan);
 
-	/* Both HT40+ and HT40- are set, pick a valid secondary channel */
-	secondary_freq = iface->freq + 20;
-	err2 = hostapd_is_usable_chan(iface, secondary_freq, 0);
-	if (err2 > 0 && (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P)) {
-		iface->conf->secondary_channel = 1;
-		return 1;
+	if (!start_freq) {
+		wpa_printf(MSG_ERROR, "frequency not present");
+		return 0;
 	}
 
-	secondary_freq = iface->freq - 20;
-	err2 = hostapd_is_usable_chan(iface, secondary_freq, 0);
-	if (err2 > 0 && (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40M)) {
-		iface->conf->secondary_channel = -1;
+	for (i = 0; i < chan_num; i++) {
+		int freq = start_freq + i * 20;
+
+		err = hostapd_is_usable_chan(iface, freq, 0);
+		if (err <= 0) {
+			wpa_printf(MSG_ERROR, "frequency %d is not allowed", freq);
+			return err;
+		}
+	}
+
+	if (oper_chwidth != CONF_OPER_CHWIDTH_80P80MHZ)
 		return 1;
+
+	central = hostapd_get_oper_centr_freq_seg1_idx(iface->conf);
+	start_chan = central - chan_num * 2 + 2;
+	start_freq = hw_get_freq(iface->current_mode, start_chan);
+	for (i = 0; i < chan_num; i++) {
+		int freq = start_freq + i * 20;
+
+		err = hostapd_is_usable_chan(iface, freq, 0);
+		if (err <= 0) {
+			wpa_printf(MSG_ERROR, "frequency %d is not allowed", freq);
+			return err;
+		}
 	}
 
-	return err;
+	return 1;
 }
 
 
diff --git a/src/ap/hw_features.h b/src/ap/hw_features.h
index 73663d0af..d4953e8ba 100644
--- a/src/ap/hw_features.h
+++ b/src/ap/hw_features.h
@@ -32,6 +32,7 @@ int hostapd_hw_skip_mode(struct hostapd_iface *iface,
 int hostapd_determine_mode(struct hostapd_iface *iface);
 void hostapd_free_multi_hw_info(struct hostapd_multi_hw_info *multi_hw_info);
 int hostapd_set_current_hw_info(struct hostapd_iface *iface, int oper_freq);
+int hostapd_is_usable_chans(struct hostapd_iface *iface);
 #else /* NEED_AP_MLME */
 static inline void
 hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
@@ -115,6 +116,12 @@ static inline int hostapd_set_current_hw_info(struct hostapd_iface *iface,
 {
 	return 0;
 }
+
+static inline int hostapd_is_usable_chans(struct hostapd_iface *iface)
+{
+	return 1;
+}
+
 #endif /* NEED_AP_MLME */
 
 #endif /* HW_FEATURES_H */
-- 
2.47.0




More information about the Hostap mailing list