All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lorenzo Bianconi <lorenzo@kernel.org>
To: j@w1.fi
Cc: hostap@lists.infradead.org, linux-wireless@vger.kernel.org,
	nbd@nbd.name, ryder.lee@mediatek.com, evelyn.tsai@mediatek.com,
	lorenzo.bianconi@redhat.com
Subject: [PATCH 5/9] DFS: configure background radar/cac detection.
Date: Mon, 20 Dec 2021 16:48:20 +0100	[thread overview]
Message-ID: <bb37607827b240a6a702a205bd42e6d1a0b70eca.1640014128.git.lorenzo@kernel.org> (raw)
In-Reply-To: <cover.1640014128.git.lorenzo@kernel.org>

Introduce the capability to perfrom radar/CAC detection on a offchannel
radar chain available on some hw (e.g. mt7915). This feature allows
to avoid CAC downtime switching on a different channel during CAC
detection on the selected radar channel.

Tested-by: Owen Peng <owen.peng@mediatek.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 src/ap/ap_drv_ops.c          |   9 ++-
 src/ap/ap_drv_ops.h          |   3 +-
 src/ap/dfs.c                 | 129 ++++++++++++++++++++++++++++++++++-
 src/ap/hostapd.h             |  15 ++++
 src/drivers/driver.h         |   5 ++
 src/drivers/driver_nl80211.c |   5 ++
 6 files changed, 160 insertions(+), 6 deletions(-)

diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index e91773666..63791330b 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -812,7 +812,8 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
 			  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 center_segment0, int center_segment1,
+			  int radar_background)
 {
 	struct hostapd_data *hapd = iface->bss[0];
 	struct hostapd_freq_params data;
@@ -838,10 +839,14 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
 		wpa_printf(MSG_ERROR, "Can't set freq params");
 		return -1;
 	}
+	data.radar_background = radar_background;
 
 	res = hapd->driver->start_dfs_cac(hapd->drv_priv, &data);
 	if (!res) {
-		iface->cac_started = 1;
+		if (radar_background)
+			iface->radar_background.cac_started = 1;
+		else
+			iface->cac_started = 1;
 		os_get_reltime(&iface->dfs_cac_start);
 	}
 
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index 61c8f64eb..92842a1dc 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -130,7 +130,8 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
 			  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 center_segment0, int center_segment1,
+			  int radar_offchan);
 int hostapd_drv_do_acs(struct hostapd_data *hapd);
 int hostapd_drv_update_dh_ie(struct hostapd_data *hapd, const u8 *peer,
 			     u16 reason_code, const u8 *ie, size_t ielen);
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index 5ce5489b2..94ef87d87 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -870,7 +870,9 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
 
 	/* Finally start CAC */
 	hostapd_set_state(iface, HAPD_IFACE_DFS);
-	wpa_printf(MSG_DEBUG, "DFS start CAC on %d MHz", iface->freq);
+	wpa_printf(MSG_DEBUG, "DFS start CAC on %d MHz background %d",
+		   iface->freq,
+		   !!(iface->drv_flags2 & WPA_DRIVER_RADAR_BACKGROUND));
 	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START
 		"freq=%d chan=%d sec_chan=%d, width=%d, seg0=%d, seg1=%d, cac_time=%ds",
 		iface->freq,
@@ -887,13 +889,37 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
 		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));
+		hostapd_get_oper_centr_freq_seg1_idx(iface->conf),
+		!!(iface->drv_flags2 & WPA_DRIVER_RADAR_BACKGROUND));
 
 	if (res) {
 		wpa_printf(MSG_ERROR, "DFS start_dfs_cac() failed, %d", res);
 		return -1;
 	}
 
+	if (iface->drv_flags2 & WPA_DRIVER_RADAR_BACKGROUND) {
+		/* Cache background radar parameters */
+		iface->radar_background.channel = iface->conf->channel;
+		iface->radar_background.secondary_channel =
+			iface->conf->secondary_channel;
+		iface->radar_background.freq = iface->freq;
+		iface->radar_background.centr_freq_seg0_idx =
+			hostapd_get_oper_centr_freq_seg0_idx(iface->conf);
+		iface->radar_background.centr_freq_seg1_idx =
+			hostapd_get_oper_centr_freq_seg1_idx(iface->conf);
+
+		/*
+		 * Let's select a random channel for the moment
+		 * and perform CAC on dedicated radar chain
+		 */
+		res = dfs_set_valid_channel(iface, 1);
+		if (res < 0)
+			return res;
+
+		iface->radar_background.temp_ch = 1;
+		return 1;
+	}
+
 	return 0;
 }
 
@@ -915,6 +941,78 @@ int hostapd_is_dfs_chan_available(struct hostapd_iface *iface)
 }
 
 
+static struct hostapd_channel_data *
+dfs_downgrade_bandwidth(struct hostapd_iface *iface, int *secondary_channel,
+			u8 *oper_centr_freq_seg0_idx,
+			u8 *oper_centr_freq_seg1_idx, int *skip_radar);
+
+static void
+hostpad_dfs_update_background_chain(struct hostapd_iface *iface)
+{
+	struct hostapd_channel_data *channel;
+	int sec = 0, flags = 2;
+	u8 cf1 = 0, cf2 = 0;
+
+	channel = dfs_get_valid_channel(iface, &sec, &cf1, &cf2, 2);
+	if (!channel || channel->chan == iface->conf->channel)
+		channel = dfs_downgrade_bandwidth(iface, &sec, &cf1, &cf2,
+						  &flags);
+	if (!channel ||
+	    hostapd_start_dfs_cac(iface, iface->conf->hw_mode,
+				  channel->freq, channel->chan,
+				  iface->conf->ieee80211n,
+				  iface->conf->ieee80211ac,
+				  iface->conf->ieee80211ax,
+				  sec, hostapd_get_oper_chwidth(iface->conf),
+				  cf1, cf2, 1)) {
+		/*
+		 * Toggle interface state to enter DFS state
+		 * until NOP is finished.
+		 */
+		wpa_printf(MSG_ERROR, "DFS failed start CAC offchannel");
+		return;
+	}
+
+	wpa_printf(MSG_DEBUG,
+		   "%s: setting background chain to chan %d (%d MHz)",
+		   __func__, channel->chan, channel->freq);
+
+	iface->radar_background.channel = channel->chan;
+	iface->radar_background.freq = channel->freq;
+	iface->radar_background.secondary_channel = sec;
+	iface->radar_background.centr_freq_seg0_idx = cf1;
+	iface->radar_background.centr_freq_seg1_idx = cf2;
+}
+
+/* XXX: check if all channel bandwith */
+static int
+hostapd_dfs_is_background_event(struct hostapd_iface *iface, int freq)
+{
+	if (iface->radar_background.freq != freq)
+		return 0;
+
+	return 1;
+}
+
+static int
+hostapd_dfs_start_channel_switch_background(struct hostapd_iface *iface)
+{
+	iface->conf->channel = iface->radar_background.channel;
+	iface->freq = iface->radar_background.freq;
+	iface->conf->secondary_channel =
+		iface->radar_background.secondary_channel;
+	hostapd_set_oper_centr_freq_seg0_idx(iface->conf,
+			iface->radar_background.centr_freq_seg0_idx);
+	hostapd_set_oper_centr_freq_seg1_idx(iface->conf,
+			iface->radar_background.centr_freq_seg1_idx);
+
+	hostpad_dfs_update_background_chain(iface);
+	hostapd_disable_iface(iface);
+	hostapd_enable_iface(iface);
+
+	return 0;
+}
+
 int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
 			     int ht_enabled, int chan_offset, int chan_width,
 			     int cf1, int cf2)
@@ -935,6 +1033,23 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
 			set_dfs_state(iface, freq, ht_enabled, chan_offset,
 				      chan_width, cf1, cf2,
 				      HOSTAPD_CHAN_DFS_AVAILABLE);
+
+			/*
+			 * radar event from background chain for selected
+			 * channel. Perfrom CSA, move main chain to selected
+			 * channel and configure background chain to a new DFS
+			 * channel
+			 */
+			if ((iface->drv_flags2 & WPA_DRIVER_RADAR_BACKGROUND) &&
+			    hostapd_dfs_is_background_event(iface, freq)) {
+				iface->radar_background.cac_started = 0;
+				if (!iface->radar_background.temp_ch)
+					return 0;
+
+				iface->radar_background.temp_ch = 0;
+				return hostapd_dfs_start_channel_switch_background(iface);
+			}
+
 			/*
 			 * Just mark the channel available when CAC completion
 			 * event is received in enabled state. CAC result could
@@ -951,6 +1066,10 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
 				iface->cac_started = 0;
 			}
 		}
+	} else if ((iface->drv_flags2 & WPA_DRIVER_RADAR_BACKGROUND) &&
+		   hostapd_dfs_is_background_event(iface, freq)) {
+		iface->radar_background.cac_started = 0;
+		hostpad_dfs_update_background_chain(iface);
 	}
 
 	return 0;
@@ -1308,7 +1427,11 @@ int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
 		"seg1=%d cac_time=%ds",
 		freq, (freq - 5000) / 5, chan_offset, chan_width, cf1, cf2,
 		iface->dfs_cac_ms / 1000);
-	iface->cac_started = 1;
+
+	if (hostapd_dfs_is_background_event(iface, freq))
+		iface->radar_background.cac_started = 1;
+	else
+		iface->cac_started = 1;
 	os_get_reltime(&iface->dfs_cac_start);
 	return 0;
 }
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index f3ca7529a..72b6035d6 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -520,6 +520,21 @@ struct hostapd_iface {
 	int *basic_rates;
 	int freq;
 
+	/* Background radar configuration */
+	struct {
+		int channel;
+		int secondary_channel;
+		int freq;
+		int centr_freq_seg0_idx;
+		int centr_freq_seg1_idx;
+		/* Main chain is on temporary channel during
+		 * CAC detection on radar offchain.
+		 */
+		unsigned int temp_ch:1;
+		/* CAC started on radar offchain */
+		unsigned int cac_started:1;
+	} radar_background;
+
 	u16 hw_flags;
 
 	/* Number of associated Non-ERP stations (i.e., stations using 802.11b
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index fa28b03db..10dc84994 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -782,6 +782,11 @@ struct hostapd_freq_params {
 	 * for IEEE 802.11ay EDMG configuration.
 	 */
 	struct ieee80211_edmg_config edmg;
+
+	/**
+	 * radar_background - Whether radar/CAC background is requested
+	 */
+	int radar_background;
 };
 
 /**
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index aec179ac3..e8e06cf17 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -4896,6 +4896,8 @@ static int nl80211_put_freq_params(struct nl_msg *msg,
 	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);
+	wpa_printf(MSG_DEBUG, "  * radar_background=%d",
+		   freq->radar_background);
 
 	hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
 	is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
@@ -4973,6 +4975,9 @@ static int nl80211_put_freq_params(struct nl_msg *msg,
 				NL80211_CHAN_NO_HT))
 			return -ENOBUFS;
 	}
+	if (freq->radar_background)
+		nla_put_flag(msg, NL80211_ATTR_RADAR_BACKGROUND);
+
 	return 0;
 }
 
-- 
2.33.1


  parent reply	other threads:[~2021-12-20 15:48 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-20 15:48 [PATCH 0/9] introduce background radar detection support Lorenzo Bianconi
2021-12-20 15:48 ` [PATCH 1/9] Sync include/uapi/linux/nl80211.h with mac80211-next.git Lorenzo Bianconi
2022-03-03 21:58   ` Jouni Malinen
2021-12-20 15:48 ` [PATCH 2/9] DFS: introduce dfs_set_valid_channel utility routine Lorenzo Bianconi
2021-12-20 15:48 ` [PATCH 3/9] DFS: add capability select radar-only channels Lorenzo Bianconi
2021-12-20 15:48 ` [PATCH 4/9] nl80211: report background radar/cac detection capability Lorenzo Bianconi
2021-12-20 15:48 ` Lorenzo Bianconi [this message]
2021-12-20 15:48 ` [PATCH 6/9] DFS: introduce hostapd_dfs_request_channel_switch routine Lorenzo Bianconi
2022-03-03 22:54   ` Jouni Malinen
2022-03-04 11:52     ` Lorenzo Bianconi
2021-12-20 15:48 ` [PATCH 7/9] DFS: enable CSA for background radar detection Lorenzo Bianconi
2021-12-20 15:48 ` [PATCH 8/9] DFS: switch to background radar channel if available Lorenzo Bianconi
2022-03-03 22:20   ` Jouni Malinen
2022-03-04 13:46     ` Lorenzo Bianconi
2021-12-20 15:48 ` [PATCH 9/9] DFS: introduce radar_background parameter to config file Lorenzo Bianconi
2022-03-03 21:56   ` Jouni Malinen
2022-03-04 11:08     ` Lorenzo Bianconi
2022-03-03 23:19 ` [PATCH 0/9] introduce background radar detection support Jouni Malinen
2022-03-04  9:48   ` Lorenzo Bianconi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bb37607827b240a6a702a205bd42e6d1a0b70eca.1640014128.git.lorenzo@kernel.org \
    --to=lorenzo@kernel.org \
    --cc=evelyn.tsai@mediatek.com \
    --cc=hostap@lists.infradead.org \
    --cc=j@w1.fi \
    --cc=linux-wireless@vger.kernel.org \
    --cc=lorenzo.bianconi@redhat.com \
    --cc=nbd@nbd.name \
    --cc=ryder.lee@mediatek.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.