[PATCH v13 2/5] hostapd: Support 80/160/320 MHz widths in hostapd_is_usable_chans
Allen Ye
allen.ye at mediatek.com
Mon Aug 3 23:34:34 PDT 2026
Add hostapd_is_usable_chan_seg() to check all constituent 20 MHz
sub-channels for a given bandwidth segment. The channel count is derived
from oper_chwidth (4 for 80 MHz, 8 for 160 MHz, 16 for 320 MHz), and
the start frequency is computed from the center frequency index. For
80+80 MHz, both seg0 and seg1 are checked independently.
hostapd_is_usable_chans() dispatches to hostapd_is_usable_chan_seg() for
5 GHz/6 GHz non-HT modes with a valid center frequency. The condition
intentionally excludes 2.4 GHz (mode != IEEE80211A) and HT-only
configurations (oper_chwidth == CONF_OPER_CHWIDTH_USE_HT), as well as
the 80+80 ACS case where the center frequency has not yet been filled in
by acs_adjust_center_freq(). These cases fall through to the existing
20/40 MHz path.
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>
Reviewed-by: Money Wang <money.wang at mediatek.com>
Signed-off-by: Allen Ye <allen.ye at mediatek.com>
---
src/ap/hw_features.c | 94 ++++++++++++++++++++++++++++++++++++++++----
src/ap/hw_features.h | 6 +++
2 files changed, 93 insertions(+), 7 deletions(-)
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index 30edac214..01a693828 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -1083,16 +1083,83 @@ static bool hostapd_is_usable_punct_bitmap(struct hostapd_iface *iface)
}
+static int hostapd_is_usable_chan_seg(struct hostapd_iface *iface)
+{
+ int central, oper_chwidth, err;
+ int start_chan, start_freq, chan_num, i;
+
+ oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
+ central = hostapd_get_oper_centr_freq_seg0_idx(iface->conf);
+
+ 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;
+ }
+ start_chan = central - chan_num * 2 + 2;
+ start_freq = hw_get_freq(iface->current_mode, start_chan);
+
+ if (!start_freq) {
+ wpa_printf(MSG_ERROR, "frequency not present");
+ return 0;
+ }
+
+ for (i = 0; i < chan_num; i++) {
+ int freq = start_freq + i * 20;
+
+ err = hostapd_is_usable_chan(iface, freq, freq == iface->freq);
+ 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);
+
+ if (!start_freq) {
+ wpa_printf(MSG_ERROR, "frequency not present");
+ return 0;
+ }
+
+ for (i = 0; i < chan_num; i++) {
+ int freq = start_freq + i * 20;
+
+ err = hostapd_is_usable_chan(iface, freq, freq == iface->freq);
+ if (err <= 0) {
+ wpa_printf(MSG_ERROR, "frequency %d is not allowed",
+ freq);
+ return err;
+ }
+ }
+ return 1;
+}
+
+
/* Returns:
* 1 = usable
* 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, new_sec, bw_flag;
struct hostapd_channel_data *pri_chan;
- int err, err2;
+ int err, err2, central, oper_chwidth;
if (!iface->current_mode)
return 0;
@@ -1105,11 +1172,6 @@ static int hostapd_is_usable_chans(struct hostapd_iface *iface)
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;
@@ -1117,6 +1179,24 @@ static int hostapd_is_usable_chans(struct hostapd_iface *iface)
if (!hostapd_is_usable_punct_bitmap(iface))
return 0;
+ oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
+
+ /*
+ * The central channel is not filled in acs_adjust_center_freq() after
+ * ACS of 80p80. In the case we only check the primary 40 MHz.
+ */
+ central = hostapd_get_oper_centr_freq_seg0_idx(iface->conf);
+
+ if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
+ oper_chwidth != CONF_OPER_CHWIDTH_USE_HT && central)
+ return hostapd_is_usable_chan_seg(iface);
+
+ err = hostapd_is_usable_chan(iface, pri_chan->freq, 1);
+ if (err <= 0) {
+ wpa_printf(MSG_ERROR, "Primary frequency not allowed");
+ return err;
+ }
+
if (!iface->conf->secondary_channel)
return 1;
diff --git a/src/ap/hw_features.h b/src/ap/hw_features.h
index 6f945cc77..4993e68af 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,11 @@ 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.45.2
More information about the Hostap
mailing list