[PATCH 2/6] S1G: Add support for freq_khz

Bassem Dawood bassem at morsemicro.com
Tue Oct 31 22:34:27 PDT 2023


This commit adds support for specifying a frequency in khz. The predominate use
case is S1G. Many S1G channels are centered on frequencies which a
MHz value does not support. Additional freq_khz parameters have been added as
required to the key structures that maintain the operating parameters of a hostapd
AP. These freq_khz params have been added to key functions alongside the traditional freq
parameter as an alternative.

Because this commit has introduced an alternative parameter that is used instead of the
traditional freq param we needed to introduce logic that would support this change.
We opted for logic that checks if freq_khz is set, and if so, uses that parameter
going forward, otherwise if freq_khz is not set, freq is used as per the existing use case.
This approach prevents regression for existing code.

The kernel maintains frequencies by using a combination of freq and freq_offset parameters.
This patch includes a number of changes to support this concept.
---
 hostapd/Makefile                   |  5 +++
 src/ap/ap_drv_ops.c                | 20 ++++++++----
 src/ap/ap_drv_ops.h                | 11 ++++---
 src/ap/beacon.c                    |  3 +-
 src/ap/dfs.c                       | 13 ++++++--
 src/ap/drv_callbacks.c             | 10 +++---
 src/ap/hostapd.c                   | 24 ++++++++++----
 src/ap/hostapd.h                   |  5 +--
 src/ap/hw_features.c               | 51 +++++++++++++++++++-----------
 src/ap/hw_features.h               |  2 +-
 src/common/defs.h                  |  6 ++++
 src/common/hw_features_common.c    | 30 ++++++++++++------
 src/common/hw_features_common.h    | 16 ++++++----
 src/common/ieee802_11_common.c     | 13 ++++++++
 src/common/ieee802_11_common.h     |  2 ++
 src/drivers/driver.h               | 17 ++++++++++
 src/drivers/driver_nl80211.c       | 23 +++++++++++++-
 src/drivers/driver_nl80211_capa.c  |  7 +++-
 src/drivers/driver_nl80211_event.c | 18 ++++++++---
 wpa_supplicant/ap.c                | 11 ++++---
 wpa_supplicant/config_ssid.h       |  5 +++
 wpa_supplicant/events.c            |  1 +
 wpa_supplicant/mesh.c              |  3 +-
 wpa_supplicant/wpa_supplicant.c    |  6 ++--
 24 files changed, 225 insertions(+), 77 deletions(-)

diff --git a/hostapd/Makefile b/hostapd/Makefile
index 51702439c..ab317bab0 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -351,6 +351,11 @@ CFLAGS += -DCONFIG_IEEE80211AX
 OBJS += ../src/ap/ieee802_11_he.o
 endif
 
+ifdef CONFIG_IEEE80211AH
+CFLAGS += -DCONFIG_IEEE80211AH
+OBJS += ../src/ap/ieee802_11_s1g.o
+endif
+
 ifdef CONFIG_MBO
 CFLAGS += -DCONFIG_MBO
 OBJS += ../src/ap/mbo_ap.o
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index 8f9cc5b36..dddc351df 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -571,18 +571,22 @@ 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 edmg, u8 edmg_channel,
+		     int freq, int freq_khz, int channel,
+		     int edmg, u8 edmg_channel,
 		     int ht_enabled, int vht_enabled,
 		     int he_enabled, bool eht_enabled,
+		     int s1g_enabled,
 		     int sec_channel_offset, int oper_chwidth,
 		     int center_segment0, int center_segment1)
 {
 	struct hostapd_freq_params data;
 	struct hostapd_hw_modes *cmode = hapd->iface->current_mode;
 
-	if (hostapd_set_freq_params(&data, mode, freq, channel, edmg,
+	if (hostapd_set_freq_params(&data, mode, freq, freq_khz,
+				    channel, edmg,
 				    edmg_channel, ht_enabled,
-				    vht_enabled, he_enabled, eht_enabled,
+				    vht_enabled, he_enabled,
+				    eht_enabled, s1g_enabled,
 				    sec_channel_offset, oper_chwidth,
 				    center_segment0, center_segment1,
 				    cmode ? cmode->vht_capab : 0,
@@ -879,8 +883,9 @@ 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 he_enabled, bool eht_enabled,
+			  int channel, int ht_enabled,
+			  int vht_enabled, int he_enabled,
+			  bool eht_enabled, int s1g_enabled,
 			  int sec_channel_offset, int oper_chwidth,
 			  int center_segment0, int center_segment1,
 			  bool radar_background)
@@ -899,9 +904,10 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
 		return -1;
 	}
 
-	if (hostapd_set_freq_params(&data, mode, freq, channel, 0, 0,
+	if (hostapd_set_freq_params(&data, mode, freq, 0, channel, 0, 0,
 				    ht_enabled,
-				    vht_enabled, he_enabled, eht_enabled,
+				    vht_enabled, he_enabled,
+				    eht_enabled, s1g_enabled,
 				    sec_channel_offset,
 				    oper_chwidth, center_segment0,
 				    center_segment1,
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index 331b0eaf4..28123c4f3 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -65,9 +65,11 @@ int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
 		       const u8 *addr, int idx, int link_id, u8 *seq);
 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 edmg, u8 edmg_channel,
+		     int freq, int freq_khz,
+		     int channel, int edmg, u8 edmg_channel,
 		     int ht_enabled, int vht_enabled, int he_enabled,
-		     bool eht_enabled, int sec_channel_offset, int oper_chwidth,
+		     bool eht_enabled, int s1g_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);
@@ -129,8 +131,9 @@ 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 he_enabled, bool eht_enabled,
+			  int channel, int ht_enabled,
+			  int vht_enabled, int he_enabled,
+			  bool eht_enabled, int s1g_enabled,
 			  int sec_channel_offset, int oper_chwidth,
 			  int center_segment0, int center_segment1,
 			  bool radar_background);
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 1d3b96ac7..b8431e4a9 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -2213,10 +2213,11 @@ static int __ieee802_11_set_beacon(struct hostapd_data *hapd)
 
 	if (cmode &&
 	    hostapd_set_freq_params(&freq, iconf->hw_mode, iface->freq,
+				    iface->freq_khz,
 				    iconf->channel, iconf->enable_edmg,
 				    iconf->edmg_channel, iconf->ieee80211n,
 				    iconf->ieee80211ac, iconf->ieee80211ax,
-				    iconf->ieee80211be,
+				    iconf->ieee80211be, iconf->ieee80211ah,
 				    iconf->secondary_channel,
 				    hostapd_get_oper_chwidth(iconf),
 				    hostapd_get_oper_centr_freq_seg0_idx(iconf),
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index 414e546cf..8d79e7452 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -831,6 +831,9 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
 	if (is_6ghz_freq(iface->freq))
 		return 1;
 
+	if (is_s1g_freq(iface->freq_khz))
+		return 1;
+
 	if (!iface->current_mode) {
 		/*
 		 * This can happen with drivers that do not provide mode
@@ -903,7 +906,7 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
 		iface, iface->conf->hw_mode, iface->freq, iface->conf->channel,
 		iface->conf->ieee80211n, iface->conf->ieee80211ac,
 		iface->conf->ieee80211ax, iface->conf->ieee80211be,
-		iface->conf->secondary_channel,
+		iface->conf->ieee80211ah, iface->conf->secondary_channel,
 		hostapd_get_oper_chwidth(iface->conf),
 		hostapd_get_oper_centr_freq_seg0_idx(iface->conf),
 		hostapd_get_oper_centr_freq_seg1_idx(iface->conf),
@@ -960,6 +963,7 @@ int hostapd_is_dfs_chan_available(struct hostapd_iface *iface)
 
 static int hostapd_dfs_request_channel_switch(struct hostapd_iface *iface,
 					      int channel, int freq,
+					      int freq_khz,
 					      int secondary_channel,
 					      u8 current_vht_oper_chwidth,
 					      u8 oper_centr_freq_seg0_idx,
@@ -989,13 +993,14 @@ static int hostapd_dfs_request_channel_switch(struct hostapd_iface *iface,
 #endif /* CONFIG_MESH */
 	err = hostapd_set_freq_params(&csa_settings.freq_params,
 				      iface->conf->hw_mode,
-				      freq, channel,
+				      freq, freq_khz, channel,
 				      iface->conf->enable_edmg,
 				      iface->conf->edmg_channel,
 				      iface->conf->ieee80211n,
 				      iface->conf->ieee80211ac,
 				      iface->conf->ieee80211ax,
 				      iface->conf->ieee80211be,
+				      iface->conf->ieee80211ah,
 				      secondary_channel,
 				      new_vht_oper_chwidth,
 				      oper_centr_freq_seg0_idx,
@@ -1076,6 +1081,7 @@ static void hostpad_dfs_update_background_chain(struct hostapd_iface *iface)
 				  iface->conf->ieee80211ac,
 				  iface->conf->ieee80211ax,
 				  iface->conf->ieee80211be,
+				  iface->conf->ieee80211ah,
 				  sec, hostapd_get_oper_chwidth(iface->conf),
 				  oper_centr_freq_seg0_idx,
 				  oper_centr_freq_seg1_idx, true)) {
@@ -1122,7 +1128,7 @@ hostapd_dfs_start_channel_switch_background(struct hostapd_iface *iface)
 	hostpad_dfs_update_background_chain(iface);
 
 	return hostapd_dfs_request_channel_switch(
-		iface, iface->conf->channel, iface->freq,
+		iface, iface->conf->channel, iface->freq, 0,
 		iface->conf->secondary_channel, current_vht_oper_chwidth,
 		hostapd_get_oper_centr_freq_seg0_idx(iface->conf),
 		hostapd_get_oper_centr_freq_seg1_idx(iface->conf));
@@ -1414,6 +1420,7 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
 
 	return hostapd_dfs_request_channel_switch(iface, channel->chan,
 						  channel->freq,
+						  channel->freq_khz,
 						  secondary_channel,
 						  current_vht_oper_chwidth,
 						  oper_centr_freq_seg0_idx,
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 0516213f4..65cf1ecd0 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -1025,8 +1025,8 @@ void hostapd_event_sta_opmode_changed(struct hostapd_data *hapd, const u8 *addr,
 }
 
 
-void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
-			     int offset, int width, int cf1, int cf2,
+void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int freq_khz,
+			     int ht, int offset, int width, int cf1, int cf2,
 			     u16 punct_bitmap, int finished)
 {
 #ifdef NEED_AP_MLME
@@ -1056,7 +1056,7 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
 	is_dfs0 = hostapd_is_dfs_required(hapd->iface);
 	hapd->iface->freq = freq;
 
-	channel = hostapd_hw_get_channel(hapd, freq);
+	channel = hostapd_hw_get_channel(hapd, freq, freq_khz);
 	if (!channel) {
 		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
 			       HOSTAPD_LEVEL_WARNING,
@@ -1285,6 +1285,7 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd,
 				if (hapd->iface->freq > 0 &&
 				    !hw_get_chan(mode->mode,
 						 hapd->iface->freq,
+						 hapd->iface->freq_khz,
 						 hapd->iface->hw_features,
 						 hapd->iface->num_hw_features))
 					continue;
@@ -1309,7 +1310,7 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd,
 		goto out;
 	}
 	pri_chan = hw_get_channel_freq(hapd->iface->current_mode->mode,
-				       acs_res->pri_freq, NULL,
+				       acs_res->pri_freq, 0, NULL,
 				       hapd->iface->hw_features,
 				       hapd->iface->num_hw_features);
 	if (!pri_chan) {
@@ -2350,6 +2351,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
 		if (!data)
 			break;
 		hostapd_event_ch_switch(hapd, data->ch_switch.freq,
+					data->ch_switch.freq_khz,
 					data->ch_switch.ht_enabled,
 					data->ch_switch.ch_offset,
 					data->ch_switch.ch_width,
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index f949a431f..992dba3c1 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -1671,8 +1671,8 @@ static int hostapd_no_ir_channel_list_updated(struct hostapd_iface *iface,
 		mode = &iface->hw_features[i];
 
 		if (mode->mode == iface->conf->hw_mode) {
-			if (iface->freq > 0 &&
-			    !hw_mode_get_channel(mode, iface->freq, NULL)) {
+			if ((iface->freq > 0  || iface->freq_khz > 0) &&
+			    !hw_mode_get_channel(mode, iface->freq, iface->freq_khz, NULL)) {
 				mode = NULL;
 				continue;
 			}
@@ -1698,7 +1698,8 @@ static int hostapd_no_ir_channel_list_updated(struct hostapd_iface *iface,
 			struct hostapd_channel_data *chan;
 
 			chan = hw_get_channel_freq(iface->current_mode->mode,
-						   iface->freq, NULL,
+						   iface->freq,
+						   iface->freq_khz, NULL,
 						   iface->hw_features,
 						   iface->num_hw_features);
 
@@ -1733,7 +1734,8 @@ static int hostapd_no_ir_channel_list_updated(struct hostapd_iface *iface,
 			struct hostapd_channel_data *chan;
 
 			chan = hw_get_channel_freq(iface->current_mode->mode,
-						   iface->freq, NULL,
+						   iface->freq,
+						   iface->freq_khz, NULL,
 						   iface->hw_features,
 						   iface->num_hw_features);
 			if (!chan) {
@@ -1874,6 +1876,10 @@ static int configured_fixed_chan_to_freq(struct hostapd_iface *iface)
 {
 	int freq, i, j;
 
+	if (iface->conf->ieee80211ah) {
+		return 0;
+	}
+
 	if (!iface->conf->channel)
 		return 0;
 	if (iface->conf->op_class) {
@@ -2333,7 +2339,8 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
 #endif /* CONFIG_MESH */
 
 		if (!delay_apply_cfg &&
-		    hostapd_set_freq(hapd, hapd->iconf->hw_mode, iface->freq,
+		    hostapd_set_freq(hapd, hapd->iconf->hw_mode,
+				     iface->freq, iface->freq_khz,
 				     hapd->iconf->channel,
 				     hapd->iconf->enable_edmg,
 				     hapd->iconf->edmg_channel,
@@ -2341,6 +2348,7 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
 				     hapd->iconf->ieee80211ac,
 				     hapd->iconf->ieee80211ax,
 				     hapd->iconf->ieee80211be,
+				     hapd->iconf->ieee80211ah,
 				     hapd->iconf->secondary_channel,
 				     hostapd_get_oper_chwidth(hapd->iconf),
 				     hostapd_get_oper_centr_freq_seg0_idx(
@@ -3776,7 +3784,7 @@ static int hostapd_change_config_freq(struct hostapd_data *hapd,
 
 	if (!params->channel) {
 		/* check if the new channel is supported by hw */
-		params->channel = hostapd_hw_get_channel(hapd, params->freq);
+		params->channel = hostapd_hw_get_channel(hapd, params->freq, 0);
 	}
 
 	channel = params->channel;
@@ -3790,10 +3798,12 @@ static int hostapd_change_config_freq(struct hostapd_data *hapd,
 	if (old_params &&
 	    hostapd_set_freq_params(old_params, conf->hw_mode,
 				    hostapd_hw_get_freq(hapd, conf->channel),
+				    0,
 				    conf->channel, conf->enable_edmg,
 				    conf->edmg_channel, conf->ieee80211n,
 				    conf->ieee80211ac, conf->ieee80211ax,
-				    conf->ieee80211be, conf->secondary_channel,
+				    conf->ieee80211be, conf->ieee80211ah,
+				    conf->secondary_channel,
 				    hostapd_get_oper_chwidth(conf),
 				    hostapd_get_oper_centr_freq_seg0_idx(conf),
 				    hostapd_get_oper_centr_freq_seg1_idx(conf),
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 2994b2788..b8f328b9d 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -561,6 +561,7 @@ struct hostapd_iface {
 	struct hostapd_rate_data *current_rates;
 	int *basic_rates;
 	int freq;
+	int freq_khz;
 
 	/* Background radar configuration */
 	struct {
@@ -739,8 +740,8 @@ void hostapd_event_connect_failed_reason(struct hostapd_data *hapd,
 int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
 			 const u8 *bssid, const u8 *ie, size_t ie_len,
 			 int ssi_signal);
-void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
-			     int offset, int width, int cf1, int cf2,
+void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int freq_khz,
+			     int ht, int offset, int width, int cf1, int cf2,
 			     u16 punct_bitmap, int finished);
 struct survey_results;
 void hostapd_event_get_survey(struct hostapd_iface *iface,
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index 9edbb5ae2..963c3d45b 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -264,11 +264,11 @@ static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface)
 	if (!iface->current_mode)
 		return 0;
 
-	p_chan = hw_get_channel_freq(iface->current_mode->mode, pri_freq, NULL,
+	p_chan = hw_get_channel_freq(iface->current_mode->mode, pri_freq, 0, NULL,
 				     iface->hw_features,
 				     iface->num_hw_features);
 
-	s_chan = hw_get_channel_freq(iface->current_mode->mode, sec_freq, NULL,
+	s_chan = hw_get_channel_freq(iface->current_mode->mode, sec_freq, 0, NULL,
 				     iface->hw_features,
 				     iface->num_hw_features);
 
@@ -303,10 +303,10 @@ static int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface,
 
 	if (!iface->current_mode)
 		return 0;
-	pri_chan = hw_get_channel_freq(iface->current_mode->mode, pri_freq,
+	pri_chan = hw_get_channel_freq(iface->current_mode->mode, pri_freq, 0,
 				       NULL, iface->hw_features,
 				       iface->num_hw_features);
-	sec_chan = hw_get_channel_freq(iface->current_mode->mode, sec_freq,
+	sec_chan = hw_get_channel_freq(iface->current_mode->mode, sec_freq, 0,
 				       NULL, iface->hw_features,
 				       iface->num_hw_features);
 
@@ -829,15 +829,16 @@ int hostapd_check_he_6ghz_capab(struct hostapd_iface *iface)
  * -1 = not currently usable due to 6 GHz NO-IR
  */
 static int hostapd_is_usable_chan(struct hostapd_iface *iface,
-				  int frequency, int primary)
+				  int frequency, int frequency_khz, int primary)
 {
 	struct hostapd_channel_data *chan;
 
 	if (!iface->current_mode)
 		return 0;
 
-	chan = hw_get_channel_freq(iface->current_mode->mode, frequency, NULL,
-				   iface->hw_features, iface->num_hw_features);
+	chan = hw_get_channel_freq(iface->current_mode->mode, frequency,
+				   frequency_khz, NULL, iface->hw_features,
+				   iface->num_hw_features);
 	if (!chan)
 		return 0;
 
@@ -847,7 +848,8 @@ static int hostapd_is_usable_chan(struct hostapd_iface *iface,
 
 	wpa_printf(MSG_INFO,
 		   "Frequency %d (%s) not allowed for AP mode, flags: 0x%x%s%s",
-		   frequency, primary ? "primary" : "secondary",
+		   frequency_khz ? frequency_khz : frequency,
+		   primary ? "primary" : "secondary",
 		   chan->flag,
 		   chan->flag & HOSTAPD_CHAN_NO_IR ? " NO-IR" : "",
 		   chan->flag & HOSTAPD_CHAN_RADAR ? " RADAR" : "");
@@ -874,7 +876,8 @@ static int hostapd_is_usable_edmg(struct hostapd_iface *iface)
 	if (!iface->current_mode)
 		return 0;
 	pri_chan = hw_get_channel_freq(iface->current_mode->mode,
-				       iface->freq, NULL,
+				       iface->freq,
+				       iface->freq_khz, NULL,
 				       iface->hw_features,
 				       iface->num_hw_features);
 	if (!pri_chan)
@@ -904,7 +907,7 @@ static int hostapd_is_usable_edmg(struct hostapd_iface *iface)
 		if (num_of_enabled > 4)
 			return 0;
 
-		err = hostapd_is_usable_chan(iface, freq, 1);
+		err = hostapd_is_usable_chan(iface, freq, 0, 1);
 		if (err <= 0)
 			return err;
 
@@ -1005,8 +1008,10 @@ static int hostapd_is_usable_chans(struct hostapd_iface *iface)
 
 	if (!iface->current_mode)
 		return 0;
+
 	pri_chan = hw_get_channel_freq(iface->current_mode->mode,
-				       iface->freq, NULL,
+				       iface->freq,
+				       iface->freq_khz, NULL,
 				       iface->hw_features,
 				       iface->num_hw_features);
 	if (!pri_chan) {
@@ -1014,11 +1019,17 @@ static int hostapd_is_usable_chans(struct hostapd_iface *iface)
 		return 0;
 	}
 
-	err = hostapd_is_usable_chan(iface, pri_chan->freq, 1);
+	err = hostapd_is_usable_chan(iface, pri_chan->freq,
+				     pri_chan->freq_khz,
+				     pri_chan->freq_khz ? 0 : 1);
 	if (err <= 0) {
 		wpa_printf(MSG_ERROR, "Primary frequency not allowed");
 		return err;
 	}
+
+	if (iface->conf->ieee80211ah)
+		return 1;
+
 	err = hostapd_is_usable_edmg(iface);
 	if (err <= 0)
 		return err;
@@ -1030,7 +1041,7 @@ static int hostapd_is_usable_chans(struct hostapd_iface *iface)
 		return 1;
 
 	err = hostapd_is_usable_chan(iface, iface->freq +
-				     iface->conf->secondary_channel * 20, 0);
+				     iface->conf->secondary_channel * 20, 0, 0);
 	if (err > 0) {
 		if (iface->conf->secondary_channel == 1 &&
 		    (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P))
@@ -1044,14 +1055,14 @@ static int hostapd_is_usable_chans(struct hostapd_iface *iface)
 
 	/* Both HT40+ and HT40- are set, pick a valid secondary channel */
 	secondary_freq = iface->freq + 20;
-	err = hostapd_is_usable_chan(iface, secondary_freq, 0);
+	err = hostapd_is_usable_chan(iface, secondary_freq, 0, 0);
 	if (err > 0 && (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P)) {
 		iface->conf->secondary_channel = 1;
 		return 1;
 	}
 
 	secondary_freq = iface->freq - 20;
-	err = hostapd_is_usable_chan(iface, secondary_freq, 0);
+	err = hostapd_is_usable_chan(iface, secondary_freq, 0, 0);
 	if (err > 0 && (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40M)) {
 		iface->conf->secondary_channel = -1;
 		return 1;
@@ -1066,7 +1077,8 @@ static bool skip_mode(struct hostapd_iface *iface,
 {
 	int chan;
 
-	if (iface->freq > 0 && !hw_mode_get_channel(mode, iface->freq, &chan))
+	if ((iface->freq > 0 || iface->freq_khz > 0) &&
+	    !hw_mode_get_channel(mode, iface->freq, iface->freq_khz, &chan))
 		return true;
 
 	if (is_6ghz_op_class(iface->conf->op_class) && iface->freq == 0 &&
@@ -1120,7 +1132,7 @@ int hostapd_determine_mode(struct hostapd_iface *iface)
 static enum hostapd_chan_status
 hostapd_check_chans(struct hostapd_iface *iface)
 {
-	if (iface->freq) {
+	if (iface->freq || iface->freq_khz) {
 		int err;
 
 		hostapd_determine_mode(iface);
@@ -1338,13 +1350,14 @@ int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan)
 }
 
 
-int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq)
+int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq, int freq_khz)
 {
 	int i, channel;
 	struct hostapd_hw_modes *mode;
 
 	if (hapd->iface->current_mode) {
 		channel = hw_get_chan(hapd->iface->current_mode->mode, freq,
+				      freq_khz,
 				      hapd->iface->hw_features,
 				      hapd->iface->num_hw_features);
 		if (channel)
@@ -1357,7 +1370,7 @@ int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq)
 		return 0;
 	for (i = 0; i < hapd->iface->num_hw_features; i++) {
 		mode = &hapd->iface->hw_features[i];
-		channel = hw_get_chan(mode->mode, freq,
+		channel = hw_get_chan(mode->mode, freq, freq_khz,
 				      hapd->iface->hw_features,
 				      hapd->iface->num_hw_features);
 		if (channel)
diff --git a/src/ap/hw_features.h b/src/ap/hw_features.h
index c682c6d20..3d452a21e 100644
--- a/src/ap/hw_features.h
+++ b/src/ap/hw_features.h
@@ -20,7 +20,7 @@ int hostapd_acs_completed(struct hostapd_iface *iface, int err);
 int hostapd_select_hw_mode(struct hostapd_iface *iface);
 const char * hostapd_hw_mode_txt(int mode);
 int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan);
-int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq);
+int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq, int freq_khz);
 int hostapd_check_ht_capab(struct hostapd_iface *iface);
 int hostapd_check_edmg_capab(struct hostapd_iface *iface);
 int hostapd_check_he_6ghz_capab(struct hostapd_iface *iface);
diff --git a/src/common/defs.h b/src/common/defs.h
index c0c6dbe84..697a2d478 100644
--- a/src/common/defs.h
+++ b/src/common/defs.h
@@ -519,6 +519,12 @@ enum frame_encryption {
 	FRAME_ENCRYPTED = 1
 };
 
+#define MHZ_TO_KHZ(x) ((x) * 1000)
+#define KHZ_TO_MHZ(x) ((x) / 1000)
+#define KHZ_TO_S1G_OFFSET(x) ((x) % 1000)
+/* If x (freq_khz) is 0 then print "MHz" else print "kHz" */
+#define KHZ_PRINT_FREQ_UNITS(x) (x) == 0 ? "MHz" : "kHz"
+
 #define MAX_NUM_MLD_LINKS 15
 
 enum sae_pwe {
diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c
index 57b5a8e23..58f0dcc4e 100644
--- a/src/common/hw_features_common.c
+++ b/src/common/hw_features_common.c
@@ -41,14 +41,17 @@ struct hostapd_channel_data * hw_get_channel_chan(struct hostapd_hw_modes *mode,
 
 
 struct hostapd_channel_data *
-hw_mode_get_channel(struct hostapd_hw_modes *mode, int freq, int *chan)
+hw_mode_get_channel(struct hostapd_hw_modes *mode, int freq,
+		    int freq_khz, int *chan)
 {
 	int i;
 
 	for (i = 0; i < mode->num_channels; i++) {
 		struct hostapd_channel_data *ch = &mode->channels[i];
-
-		if (ch->freq == freq) {
+		if (freq_khz && (ch->freq_khz == freq_khz)) {
+			return ch;
+		}
+		if (freq && (ch->freq == freq)) {
 			if (chan)
 				*chan = ch->chan;
 			return ch;
@@ -60,8 +63,9 @@ hw_mode_get_channel(struct hostapd_hw_modes *mode, int freq, int *chan)
 
 
 struct hostapd_channel_data *
-hw_get_channel_freq(enum hostapd_hw_mode mode, int freq, int *chan,
-		    struct hostapd_hw_modes *hw_features, int num_hw_features)
+hw_get_channel_freq(enum hostapd_hw_mode mode, int freq, int freq_khz,
+		    int *chan, struct hostapd_hw_modes *hw_features,
+		    int num_hw_features)
 {
 	struct hostapd_channel_data *chan_data;
 	int i;
@@ -78,7 +82,8 @@ hw_get_channel_freq(enum hostapd_hw_mode mode, int freq, int *chan,
 		if (curr_mode->mode != mode)
 			continue;
 
-		chan_data = hw_mode_get_channel(curr_mode, freq, chan);
+		chan_data = hw_mode_get_channel(curr_mode, freq,
+						freq_khz, chan);
 		if (chan_data)
 			return chan_data;
 	}
@@ -97,12 +102,13 @@ int hw_get_freq(struct hostapd_hw_modes *mode, int chan)
 }
 
 
-int hw_get_chan(enum hostapd_hw_mode mode, int freq,
+int hw_get_chan(enum hostapd_hw_mode mode, int freq, int freq_khz,
 		struct hostapd_hw_modes *hw_features, int num_hw_features)
 {
 	int chan;
 
-	hw_get_channel_freq(mode, freq, &chan, hw_features, num_hw_features);
+	hw_get_channel_freq(mode, freq, freq_khz, &chan, hw_features,
+			    num_hw_features);
 
 	return chan;
 }
@@ -383,10 +389,12 @@ 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 enable_edmg,
+			    int freq, int freq_khz,
+			    int channel, int enable_edmg,
 			    u8 edmg_channel, int ht_enabled,
 			    int vht_enabled, int he_enabled,
-			    bool eht_enabled, int sec_channel_offset,
+			    bool eht_enabled, int s1g_enabled,
+			    int sec_channel_offset,
 			    enum oper_chan_width oper_chwidth,
 			    int center_segment0,
 			    int center_segment1, u32 vht_caps,
@@ -400,11 +408,13 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
 	os_memset(data, 0, sizeof(*data));
 	data->mode = mode;
 	data->freq = freq;
+	data->freq_khz = freq_khz;
 	data->channel = channel;
 	data->ht_enabled = ht_enabled;
 	data->vht_enabled = vht_enabled;
 	data->he_enabled = he_enabled;
 	data->eht_enabled = eht_enabled;
+	data->s1g_enabled = s1g_enabled;
 	data->sec_channel_offset = sec_channel_offset;
 	data->center_freq1 = freq + sec_channel_offset * 10;
 	data->center_freq2 = 0;
diff --git a/src/common/hw_features_common.h b/src/common/hw_features_common.h
index 82e028238..c876e5d0c 100644
--- a/src/common/hw_features_common.h
+++ b/src/common/hw_features_common.h
@@ -15,14 +15,16 @@
 struct hostapd_channel_data * hw_get_channel_chan(struct hostapd_hw_modes *mode,
 						  int chan, int *freq);
 struct hostapd_channel_data *
-hw_mode_get_channel(struct hostapd_hw_modes *mode, int freq, int *chan);
+hw_mode_get_channel(struct hostapd_hw_modes *mode, int freq,
+		    int freq_khz, int *chan);
 
 struct hostapd_channel_data *
-hw_get_channel_freq(enum hostapd_hw_mode mode, int freq, int *chan,
-		    struct hostapd_hw_modes *hw_features, int num_hw_features);
+hw_get_channel_freq(enum hostapd_hw_mode mode, int freq, int freq_khz,
+		    int *chan, struct hostapd_hw_modes *hw_features,
+		    int num_hw_features);
 
 int hw_get_freq(struct hostapd_hw_modes *mode, int chan);
-int hw_get_chan(enum hostapd_hw_mode mode, int freq,
+int hw_get_chan(enum hostapd_hw_mode mode, int freq, int freq_khz,
 		struct hostapd_hw_modes *hw_features, int num_hw_features);
 
 int allowed_ht40_channel_pair(enum hostapd_hw_mode mode,
@@ -37,10 +39,12 @@ int check_40mhz_2g4(struct hostapd_hw_modes *mode,
 		    int sec_chan);
 int hostapd_set_freq_params(struct hostapd_freq_params *data,
 			    enum hostapd_hw_mode mode,
-			    int freq, int channel, int edmg, u8 edmg_channel,
+			    int freq, int freq_khz,
+			    int channel, int edmg, u8 edmg_channel,
 			    int ht_enabled,
 			    int vht_enabled, int he_enabled,
-			    bool eht_enabled, int sec_channel_offset,
+			    bool eht_enabled, int s1g_enabled,
+			    int sec_channel_offset,
 			    enum oper_chan_width oper_chwidth,
 			    int center_segment0,
 			    int center_segment1, u32 vht_caps,
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index 21c3ed701..becc23a7d 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -1381,6 +1381,10 @@ ieee80211_freq_to_channel_ext(unsigned int freq, int sec_channel,
 
 	/* TODO: more operating classes */
 
+	if (is_s1g_freq(MHZ_TO_KHZ(freq))) {
+		return HOSTAPD_MODE_IEEE80211A;
+	}
+
 	if (sec_channel > 1 || sec_channel < -1)
 		return NUM_HOSTAPD_MODES;
 
@@ -2834,6 +2838,15 @@ int get_6ghz_sec_channel(int channel)
 }
 
 
+bool is_s1g_freq(int freq_khz)
+{
+	if (freq_khz < 1000000 && freq_khz > 0)
+		return true;
+
+	return false;
+}
+
+
 int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
 				    size_t nei_rep_len)
 {
diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
index f8cede008..72b04ab8b 100644
--- a/src/common/ieee802_11_common.h
+++ b/src/common/ieee802_11_common.h
@@ -283,6 +283,8 @@ bool is_6ghz_op_class(u8 op_class);
 bool is_6ghz_psc_frequency(int freq);
 int get_6ghz_sec_channel(int channel);
 
+bool is_s1g_freq(int freq_khz);
+
 int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
 				    size_t nei_rep_len);
 
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index dbe2ad5e4..543e97aff 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -119,6 +119,11 @@ struct hostapd_channel_data {
 	 */
 	int freq;
 
+	/**
+	 * freq_khz - Frequency in kHz
+	 */
+	int freq_khz;
+
 	/**
 	 * flag - Channel flags (HOSTAPD_CHAN_*)
 	 */
@@ -778,6 +783,11 @@ struct hostapd_freq_params {
 	 */
 	int freq;
 
+	/**
+	 * freq_khz - Primary channel center frequency in kHz
+	 */
+	int freq_khz;
+
 	/**
 	 * channel - Channel number
 	 */
@@ -807,6 +817,11 @@ struct hostapd_freq_params {
 	 */
 	int he_enabled;
 
+	/**
+	 * s1g_enabled - Whether S1G is enabled
+	 */
+	int s1g_enabled;
+
 	/**
 	 * center_freq1 - Segment 0 center frequency in MHz
 	 *
@@ -6446,6 +6461,7 @@ union wpa_event_data {
 	 */
 	struct ch_switch {
 		int freq;
+		int freq_khz;
 		int ht_enabled;
 		int ch_offset;
 		enum chan_width ch_width;
@@ -6548,6 +6564,7 @@ union wpa_event_data {
 	 */
 	struct acs_selected_channels {
 		unsigned int pri_freq;
+                unsigned int pri_freq_khz;
 		unsigned int sec_freq;
 		u8 edmg_channel;
 		u8 vht_seg0_center_ch;
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 9bd6a58e0..cee08571a 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -4862,7 +4862,20 @@ static int nl80211_put_freq_params(struct nl_msg *msg,
 	u8 channel;
 
 	wpa_printf(MSG_DEBUG, "  * freq=%d", freq->freq);
-	if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq->freq))
+	if (is_s1g_freq(freq->freq_khz)) {
+		if (nla_put_u32(msg,
+				NL80211_ATTR_WIPHY_FREQ,
+				KHZ_TO_MHZ(freq->freq_khz)))
+		return -ENOBUFS;
+	} else {
+		if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq->freq))
+			return -ENOBUFS;
+	}
+
+	wpa_printf(MSG_DEBUG, "  * freq_offset=%d",
+		   KHZ_TO_S1G_OFFSET(freq->freq_khz));
+	if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
+			KHZ_TO_S1G_OFFSET(freq->freq_khz)))
 		return -ENOBUFS;
 
 	wpa_printf(MSG_DEBUG, "  * eht_enabled=%d", freq->eht_enabled);
@@ -5027,6 +5040,14 @@ static int wpa_driver_nl80211_set_ap(void *priv,
 	    nla_put(msg, NL80211_ATTR_SSID, params->ssid_len, params->ssid))
 		goto fail;
 
+	if (is_s1g_freq(params->freq->freq_khz)) {
+		if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
+				KHZ_TO_MHZ(params->freq->freq_khz)) ||
+			nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
+				    KHZ_TO_S1G_OFFSET(params->freq->freq_khz)))
+			goto fail;
+	}
+
 	if (params->mld_ap) {
 		wpa_printf(MSG_DEBUG, "nl80211: link_id=%u",
 			   params->mld_link_id);
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index 5e6406885..fb6fd3c83 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -1652,6 +1652,8 @@ static void phy_info_freq(struct hostapd_hw_modes *mode,
 
 	os_memset(chan, 0, sizeof(*chan));
 	chan->freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
+	chan->freq_khz = MHZ_TO_KHZ(chan->freq) +
+		nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_OFFSET]);
 	chan->flag = 0;
 	chan->allowed_bw = ~0;
 	chan->dfs_cac_ms = 0;
@@ -2134,7 +2136,10 @@ wpa_driver_nl80211_postprocess_modes(struct hostapd_hw_modes *modes,
 	for (m = 0; m < *num_modes; m++) {
 		if (!modes[m].num_channels)
 			continue;
-		if (modes[m].channels[0].freq < 2000) {
+		if (modes[m].channels[0].freq_khz < 1000000 &&
+			modes[m].channels[0].freq_khz > 0){
+			modes[m].mode = HOSTAPD_MODE_IEEE80211A;
+		} else if (modes[m].channels[0].freq < 2000) {
 			modes[m].num_channels = 0;
 			continue;
 		} else if (modes[m].channels[0].freq < 4000) {
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index 9d39703e0..129b43903 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -1198,7 +1198,8 @@ static int calculate_chan_offset(int width, int freq, int cf1, int cf2)
 
 static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
 				 struct nlattr *ifindex, struct nlattr *link,
-				 struct nlattr *freq, struct nlattr *type,
+				 struct nlattr *freq, struct nlattr *freq_off,
+				 struct nlattr *type,
 				 struct nlattr *bw, struct nlattr *cf1,
 				 struct nlattr *cf2,
 				 struct nlattr *punct_bitmap,
@@ -1255,6 +1256,8 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
 
 	os_memset(&data, 0, sizeof(data));
 	data.ch_switch.freq = nla_get_u32(freq);
+	data.ch_switch.freq_khz = MHZ_TO_KHZ(data.ch_switch.freq) +
+		nla_get_u32(freq_off);
 	data.ch_switch.ht_enabled = ht_enabled;
 	data.ch_switch.ch_offset = chan_offset;
 	if (punct_bitmap)
@@ -1631,7 +1634,8 @@ nl80211_get_mld_link_by_freq(struct i802_bss *bss, unsigned int freq)
 static void mlme_event(struct i802_bss *bss,
 		       enum nl80211_commands cmd, struct nlattr *frame,
 		       struct nlattr *addr, struct nlattr *timed_out,
-		       struct nlattr *freq, struct nlattr *ack,
+		       struct nlattr *freq, struct nlattr *freq_offset,
+		       struct nlattr *ack,
 		       struct nlattr *cookie, struct nlattr *sig,
 		       struct nlattr *wmm, struct nlattr *req_ie,
 		       struct nlattr *link)
@@ -3878,7 +3882,9 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
 	case NL80211_CMD_UNPROT_DISASSOCIATE:
 		mlme_event(bss, cmd, tb[NL80211_ATTR_FRAME],
 			   tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],
-			   tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],
+			   tb[NL80211_ATTR_WIPHY_FREQ],
+			   tb[NL80211_ATTR_WIPHY_FREQ_OFFSET],
+			   tb[NL80211_ATTR_ACK],
 			   tb[NL80211_ATTR_COOKIE],
 			   tb[NL80211_ATTR_RX_SIGNAL_DBM],
 			   tb[NL80211_ATTR_STA_WME],
@@ -3907,6 +3913,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
 				     tb[NL80211_ATTR_IFINDEX],
 				     tb[NL80211_ATTR_MLO_LINK_ID],
 				     tb[NL80211_ATTR_WIPHY_FREQ],
+				     tb[NL80211_ATTR_WIPHY_FREQ_OFFSET],
 				     tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
 				     tb[NL80211_ATTR_CHANNEL_WIDTH],
 				     tb[NL80211_ATTR_CENTER_FREQ1],
@@ -3919,6 +3926,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
 				     tb[NL80211_ATTR_IFINDEX],
 				     tb[NL80211_ATTR_MLO_LINK_ID],
 				     tb[NL80211_ATTR_WIPHY_FREQ],
+				     tb[NL80211_ATTR_WIPHY_FREQ_OFFSET],
 				     tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
 				     tb[NL80211_ATTR_CHANNEL_WIDTH],
 				     tb[NL80211_ATTR_CENTER_FREQ1],
@@ -4108,7 +4116,9 @@ int process_bss_event(struct nl_msg *msg, void *arg)
 	case NL80211_CMD_FRAME_TX_STATUS:
 		mlme_event(bss, gnlh->cmd, tb[NL80211_ATTR_FRAME],
 			   tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],
-			   tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],
+			   tb[NL80211_ATTR_WIPHY_FREQ],
+			   tb[NL80211_ATTR_WIPHY_FREQ_OFFSET],
+			   tb[NL80211_ATTR_ACK],
 			   tb[NL80211_ATTR_COOKIE],
 			   tb[NL80211_ATTR_RX_SIGNAL_DBM],
 			   tb[NL80211_ATTR_STA_WME], NULL,
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index ff7c75644..10c2ece9e 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -1838,8 +1838,8 @@ int ap_ctrl_iface_chanswitch(struct wpa_supplicant *wpa_s, const char *pos)
 #endif /* CONFIG_CTRL_IFACE */
 
 
-void wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht,
-		       int offset, int width, int cf1, int cf2,
+void wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int freq_khz,
+		       int ht, int offset, int width, int cf1, int cf2,
 		       u16 punct_bitmap, int finished)
 {
 	struct hostapd_iface *iface = wpa_s->ap_iface;
@@ -1849,9 +1849,12 @@ void wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht,
 	if (!iface)
 		return;
 	wpa_s->assoc_freq = freq;
-	if (wpa_s->current_ssid)
+	wpa_s->assoc_freq_khz = freq_khz;
+	if (wpa_s->current_ssid) {
 		wpa_s->current_ssid->frequency = freq;
-	hostapd_event_ch_switch(iface->bss[0], freq, ht,
+		wpa_s->current_ssid->frequency_khz = freq_khz;
+	}
+	hostapd_event_ch_switch(iface->bss[0], freq, freq_khz, ht,
 				offset, width, cf1, cf2, punct_bitmap,
 				finished);
 }
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index ff045380e..7ee8d1d1a 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -524,6 +524,11 @@ struct wpa_ssid {
 	 */
 	int frequency;
 
+	/**
+	 * frequency_khz - Channel frequency in kilohertz (kHz)
+	 */
+	int frequency_khz;
+
 	/**
 	 * enable_edmg - Enable EDMG feature in STA/AP mode
 	 *
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index f205b91d5..2b3ff03c0 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -5739,6 +5739,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
 		    wpa_s->current_ssid->mode ==
 		    WPAS_MODE_P2P_GROUP_FORMATION) {
 			wpas_ap_ch_switch(wpa_s, data->ch_switch.freq,
+					  data->ch_switch.freq_khz,
 					  data->ch_switch.ht_enabled,
 					  data->ch_switch.ch_offset,
 					  data->ch_switch.ch_width,
diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c
index 486fc6a09..35b9a2202 100644
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -219,13 +219,14 @@ static int wpas_mesh_update_freq_params(struct wpa_supplicant *wpa_s)
 		    &params->freq,
 		    ifmsh->conf->hw_mode,
 		    ifmsh->freq,
+		    ifmsh->freq_khz,
 		    ifmsh->conf->channel,
 		    ifmsh->conf->enable_edmg,
 		    ifmsh->conf->edmg_channel,
 		    ifmsh->conf->ieee80211n,
 		    ifmsh->conf->ieee80211ac,
 		    ifmsh->conf->ieee80211ax,
-		    ifmsh->conf->ieee80211be,
+		    ifmsh->conf->ieee80211ah,
 		    ifmsh->conf->secondary_channel,
 		    hostapd_get_oper_chwidth(ifmsh->conf),
 		    hostapd_get_oper_centr_freq_seg0_idx(ifmsh->conf),
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index ba68e8198..e2c78926a 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -2997,10 +2997,11 @@ static bool ibss_mesh_select_80_160mhz(struct wpa_supplicant *wpa_s,
 
 skip_80mhz:
 	if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
+				    freq->freq_khz,
 				    freq->channel, ssid->enable_edmg,
 				    ssid->edmg_channel, freq->ht_enabled,
 				    freq->vht_enabled, freq->he_enabled,
-				    freq->eht_enabled,
+				    freq->eht_enabled, freq->s1g_enabled,
 				    freq->sec_channel_offset,
 				    chwidth, seg0, seg1, vht_caps,
 				    &mode->he_capab[ieee80211_mode],
@@ -3027,6 +3028,7 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
 	bool is_6ghz;
 
 	freq->freq = ssid->frequency;
+	freq->freq_khz = ssid->frequency_khz;
 
 	if (ssid->mode == WPAS_MODE_IBSS && !ssid->fixed_freq) {
 		struct wpa_bss *bss = ibss_find_existing_bss(wpa_s, ssid);
@@ -3043,7 +3045,7 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
 	hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
 	for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
 		if (wpa_s->hw.modes[i].mode == hw_mode &&
-		    hw_mode_get_channel(&wpa_s->hw.modes[i], freq->freq,
+		    hw_mode_get_channel(&wpa_s->hw.modes[i], freq->freq, freq->freq_khz,
 					NULL) != NULL) {
 			mode = &wpa_s->hw.modes[i];
 			break;
-- 
2.25.1




More information about the Hostap mailing list