blob: e6f30ed6490a9eb7090e995623bf0065b8414968 [file] [log] [blame]
From 1b8fc72bfd653ce3ef422e86617b1821948f4805 Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Mon, 20 Mar 2023 16:08:30 +0800
Subject: [PATCH 048/104] mtk: hostapd: Fix ZWDFS issue in BW 160
When background radar is enabled and bandwidth is set to 160, AP will
fail to startup due to the lack of non-DFS channel.
Under this circumstance, AP should perform CAC itself, and the background
chain could also perform CAC simultaneously.
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
---
src/ap/dfs.c | 98 ++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 79 insertions(+), 19 deletions(-)
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index 3e036441b..f5794753e 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -69,15 +69,22 @@ static int dfs_get_used_n_chans(struct hostapd_iface *iface, int *seg1)
static int dfs_channel_available(struct hostapd_channel_data *chan,
enum dfs_channel_type type)
{
+ int dfs_status = chan->flag & HOSTAPD_CHAN_DFS_MASK;
+
+ if (chan->flag & HOSTAPD_CHAN_DISABLED)
+ return -1;
+
if (type == DFS_NO_CAC_YET) {
/* Select only radar channel where CAC has not been
* performed yet
*/
- if ((chan->flag & HOSTAPD_CHAN_RADAR) &&
- (chan->flag & HOSTAPD_CHAN_DFS_MASK) ==
- HOSTAPD_CHAN_DFS_USABLE)
+ if (!(chan->flag & HOSTAPD_CHAN_RADAR))
+ return 0;
+
+ if (dfs_status == HOSTAPD_CHAN_DFS_USABLE)
return 1;
- return 0;
+
+ return -1;
}
/*
@@ -86,16 +93,14 @@ static int dfs_channel_available(struct hostapd_channel_data *chan,
* channel for CSA, unless they are available for immediate use.
*/
if (type == DFS_AVAILABLE && (chan->flag & HOSTAPD_CHAN_RADAR) &&
- ((chan->flag & HOSTAPD_CHAN_DFS_MASK) !=
- HOSTAPD_CHAN_DFS_AVAILABLE))
- return 0;
+ (dfs_status != HOSTAPD_CHAN_DFS_AVAILABLE))
+ return -1;
- if (chan->flag & HOSTAPD_CHAN_DISABLED)
- return 0;
if ((chan->flag & HOSTAPD_CHAN_RADAR) &&
- ((chan->flag & HOSTAPD_CHAN_DFS_MASK) ==
- HOSTAPD_CHAN_DFS_UNAVAILABLE))
- return 0;
+ ((dfs_status == HOSTAPD_CHAN_DFS_UNAVAILABLE) ||
+ (dfs_status == HOSTAPD_CHAN_DFS_UNKNOWN)))
+ return -1;
+
return 1;
}
@@ -167,7 +172,7 @@ static int dfs_chan_range_available(struct hostapd_hw_modes *mode,
enum dfs_channel_type type)
{
struct hostapd_channel_data *first_chan, *chan;
- int i;
+ int i, available = 0, ret = 0;
u32 bw = num_chan_to_bw(num_chans);
if (first_chan_idx + num_chans > mode->num_channels) {
@@ -203,14 +208,17 @@ static int dfs_chan_range_available(struct hostapd_hw_modes *mode,
return 0;
}
- if (!dfs_channel_available(chan, type)) {
+ ret = dfs_channel_available(chan, type);
+ if (ret < 0) {
wpa_printf(MSG_DEBUG, "DFS: channel not available %d",
first_chan->freq + i * 20);
return 0;
}
+
+ available |= ret;
}
- return 1;
+ return available;
}
@@ -838,8 +846,12 @@ static unsigned int dfs_get_cac_time(struct hostapd_iface *iface,
*/
int hostapd_handle_dfs(struct hostapd_iface *iface)
{
+ struct hostapd_channel_data *channel;
int res, n_chans, n_chans1, start_chan_idx, start_chan_idx1;
- int skip_radar = 0;
+ int sec = 0, skip_radar = 0;
+ u8 cf1 = 0, cf2 = 0;
+ bool use_radar_background = dfs_use_radar_background(iface);
+ enum dfs_channel_type channel_type = DFS_NO_CAC_YET;
if (is_6ghz_freq(iface->freq))
return 1;
@@ -902,7 +914,7 @@ 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%s", iface->freq,
- dfs_use_radar_background(iface) ? " (background)" : "");
+ use_radar_background ? " (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,
@@ -912,6 +924,16 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
hostapd_get_oper_centr_freq_seg1_idx(iface->conf),
iface->dfs_cac_ms / 1000);
+ if (use_radar_background) {
+ channel = dfs_get_valid_channel(iface, &sec, &cf1, &cf2, DFS_AVAILABLE);
+ /*
+ * AP cannot get any random available channel.
+ * Let AP and dedicated radar chain both perform CAC.
+ */
+ if (!channel)
+ use_radar_background = false;
+ }
+
res = hostapd_start_dfs_cac(
iface, iface->conf->hw_mode, iface->freq, iface->conf->channel,
iface->conf->ieee80211n, iface->conf->ieee80211ac,
@@ -920,14 +942,14 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
hostapd_get_oper_chwidth(iface->conf),
hostapd_get_oper_centr_freq_seg0_idx(iface->conf),
hostapd_get_oper_centr_freq_seg1_idx(iface->conf),
- dfs_use_radar_background(iface));
+ use_radar_background);
if (res) {
wpa_printf(MSG_ERROR, "DFS start_dfs_cac() failed, %d", res);
return -1;
}
- if (dfs_use_radar_background(iface)) {
+ if (use_radar_background) {
/* Cache background radar parameters. */
iface->radar_background.channel = iface->conf->channel;
iface->radar_background.secondary_channel =
@@ -948,6 +970,35 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
iface->radar_background.temp_ch = 1;
return 1;
+ } else if (dfs_use_radar_background(iface)) {
+ if (iface->dfs_domain == HOSTAPD_DFS_REGION_ETSI)
+ channel_type = DFS_ANY_CHANNEL;
+
+ channel = dfs_get_valid_channel(iface, &sec, &cf1, &cf2, channel_type);
+
+ if (!channel ||
+ (channel->chan == iface->conf->channel &&
+ cf1 == hostapd_get_oper_centr_freq_seg0_idx(iface->conf) &&
+ cf2 == hostapd_get_oper_centr_freq_seg1_idx(iface->conf))) {
+ wpa_printf(MSG_ERROR, "Background radar could not get valid channel\n");
+ iface->radar_background.channel = -1;
+ return 0;
+ }
+
+ hostapd_start_dfs_cac(iface, iface->conf->hw_mode,
+ channel->freq, channel->chan,
+ iface->conf->ieee80211n,
+ iface->conf->ieee80211ac,
+ iface->conf->ieee80211ax,
+ iface->conf->ieee80211be,
+ sec, hostapd_get_oper_chwidth(iface->conf),
+ cf1, cf2, true);
+
+ 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;
}
return 0;
@@ -1204,6 +1255,15 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
hostapd_setup_interface_complete(iface, 0);
iface->cac_started = 0;
}
+
+ /*
+ * When background radar is enabled but the CAC completion
+ * is not received from the background chain.
+ * Then, reset radar background chain.
+ */
+ if (dfs_use_radar_background(iface) &&
+ iface->radar_background.channel == -1)
+ hostapd_dfs_update_background_chain(iface);
}
} else if (hostapd_dfs_is_background_event(iface, freq)) {
iface->radar_background.cac_started = 0;
--
2.39.2