blob: 627f8c8dee57ddbc7044c581c894757f707960fc [file] [log] [blame]
From 9fa953a895c969b3f7a33c35e1e810b4695a2ca3 Mon Sep 17 00:00:00 2001
From: Chin-Yen Lee <timlee@realtek.com>
Date: Thu, 22 Jul 2021 18:09:17 +0800
Subject: [PATCH] CHROMIUM: rtw88: replace RADAR flag with NO_IR for dfs
channel
Currently mac80211 don't allow active scan on DFS channels, it limits
connecting hidden AP on DFS channel. We take advantage of beacon hint
in cfg80211, by replacing IEEE80211_CHAN_RADAR of channel flags with
IEEE80211_CHAN_NO_IR, to allow active scan in channels where beacon is
found. Another, to avoid keeping active scan when radar signal suddenly
exists, restore IEEE80211_CHAN_NO_IR if the interval of two scans exceeds
set time.
Signed-off-by: Chin-Yen Lee <timlee@realtek.com>
BUG=b:190353955
TEST=suite:wifi_matfunc;
DFS channel Test
a) check no probe request is sent if no AP exists
b) check probe request is sent after power on one AP;
power off AP, check no probe req is sent after 10s
c) connect to AP with hidden SSID
d) disconnect AP and repeat step a,b,c
Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Abhishek Kumar <kuabhs@chromium.org>
[kuabhs: Extend the TEST section with additional test details]
Change-Id: Ia02fa35ae1f589a6bdf60a2834359a4152c645aa
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/3074386
Reviewed-by: Matthew Wang <matthewmwang@chromium.org>
Commit-Queue: Matthew Wang <matthewmwang@chromium.org>
[rebase515(groeck): Context conflicts]
Signed-off-by: Guenter Roeck <groeck@google.com>
Change-Id: I3760b55af57a2c7bdae8611dcb608d39cb6e320d
---
drivers/net/wireless/realtek/rtw88/mac80211.c | 1 +
drivers/net/wireless/realtek/rtw88/main.c | 81 +++++++++++++++++++
drivers/net/wireless/realtek/rtw88/main.h | 10 +++
drivers/net/wireless/realtek/rtw88/regd.c | 2 +
4 files changed, 94 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c
--- a/drivers/net/wireless/realtek/rtw88/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw88/mac80211.c
@@ -605,6 +605,7 @@ static void rtw_ops_sw_scan_start(struct ieee80211_hw *hw,
mutex_lock(&rtwdev->mutex);
rtw_core_scan_start(rtwdev, rtwvif, mac_addr, false);
+ rtw_restore_no_ir_flag(rtwdev);
mutex_unlock(&rtwdev->mutex);
}
diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -510,6 +510,87 @@ int rtw_dump_reg(struct rtw_dev *rtwdev, const u32 addr, const u32 size)
}
EXPORT_SYMBOL(rtw_dump_reg);
+void rtw_replace_radar_flag_with_no_ir(struct ieee80211_hw *hw)
+{
+ struct wiphy *wiphy = hw->wiphy;
+ struct rtw_dev *rtwdev = hw->priv;
+ struct ieee80211_channel *ch;
+ struct ieee80211_supported_band *sband;
+ int i;
+
+ if (!wiphy || !wiphy->bands[NL80211_BAND_5GHZ])
+ return;
+
+ /* Currently mac80211 just don't allow active scan on DFS channels
+ * because DFS master support is not yet implemented for client devices.
+ * This behavior will make client impossible to connect to hidden AP
+ * on DFS channels. To practice the feature, a common way is to dismiss
+ * the limit for a period of time after hearing beacon in DFS channels.
+ * So we take advantage of beacon hint in cfg80211, by replacing
+ * IEEE80211_CHAN_RADAR of channel flags with IEEE80211_CHAN_NO_IR.
+ */
+ sband = wiphy->bands[NL80211_BAND_5GHZ];
+ mutex_lock(&rtwdev->dfs_mutex);
+ rtwdev->dfs_channel_map = 0;
+ for (i = 0; i < sband->n_channels; i++) {
+ ch = &sband->channels[i];
+ if (ch->flags & IEEE80211_CHAN_DISABLED)
+ continue;
+ if (ch->flags & IEEE80211_CHAN_RADAR) {
+ rtw_dbg(rtwdev, RTW_DBG_REGD,
+ "set channel(%d) RADAR flags to NO_IR",
+ ch->hw_value);
+ ch->beacon_found = false;
+ ch->flags |= IEEE80211_CHAN_NO_IR;
+ ch->flags &= ~IEEE80211_CHAN_RADAR;
+ rtwdev->dfs_channel_map |= BIT(i);
+ }
+ }
+ rtwdev->dfs_last_update = jiffies;
+ mutex_unlock(&rtwdev->dfs_mutex);
+}
+
+void rtw_restore_no_ir_flag(struct rtw_dev *rtwdev)
+{
+ struct ieee80211_hw *hw = rtwdev->hw;
+ struct wiphy *wiphy = hw->wiphy;
+ struct ieee80211_channel *ch;
+ struct ieee80211_supported_band *sband;
+ int i;
+
+ if (!wiphy || !wiphy->bands[NL80211_BAND_5GHZ])
+ return;
+
+ if (!rtwdev->dfs_channel_map)
+ return;
+
+ mutex_lock(&rtwdev->dfs_mutex);
+ /* Based on the design of beacon hint, active scan is always allowed
+ * after beacon is probed in current channel. But we need to avoid it
+ * once radar signal exits. So restore IEEE80211_CHAN_NO_IR when
+ * the interval of two scans is longer than 10s, to keep monitoring
+ * if no beacon is found, maybe due to radar signal.
+ */
+ if (time_after(rtwdev->dfs_last_update + RTW_DFS_TIMEOUT, jiffies)) {
+ mutex_unlock(&rtwdev->dfs_mutex);
+ return;
+ }
+
+ sband = wiphy->bands[NL80211_BAND_5GHZ];
+ for (i = 0; i < sband->n_channels; i++) {
+ ch = &sband->channels[i];
+ if (rtwdev->dfs_channel_map & BIT(i)) {
+ ch->beacon_found = false;
+ ch->flags |= IEEE80211_CHAN_NO_IR;
+ rtw_dbg(rtwdev, RTW_DBG_REGD,
+ "restore NO_IR flag for channel(%d)\n",
+ ch->hw_value);
+ }
+ }
+ rtwdev->dfs_last_update = jiffies;
+ mutex_unlock(&rtwdev->dfs_mutex);
+}
+
void rtw_vif_assoc_changed(struct rtw_vif *rtwvif,
struct ieee80211_bss_conf *conf)
{
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -31,6 +31,11 @@
#define RTW_WATCH_DOG_DELAY_TIME round_jiffies_relative(HZ * 2)
+/* AP need to stop beaconing after hearing radar signal in 10s.
+ * So design 10s to restore NO_IR flag referenced by beacon hint.
+ */
+#define RTW_DFS_TIMEOUT msecs_to_jiffies(10000)
+
#define RFREG_MASK 0xfffff
#define INV_RF_DATA 0xffffffff
#define TX_PAGE_SIZE_SHIFT 7
@@ -2002,6 +2007,11 @@ struct rtw_dev {
bool need_rfk;
struct completion fw_scan_density;
+ /* protects dfs channel context */
+ struct mutex dfs_mutex;
+ u32 dfs_channel_map;
+ unsigned long dfs_last_update;
+
/* hci related data, must be last */
u8 priv[] __aligned(sizeof(void *));
};
diff --git a/drivers/net/wireless/realtek/rtw88/regd.c b/drivers/net/wireless/realtek/rtw88/regd.c
--- a/drivers/net/wireless/realtek/rtw88/regd.c
+++ b/drivers/net/wireless/realtek/rtw88/regd.c
@@ -465,6 +465,8 @@ void rtw_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request)
struct rtw_regd next_regd = {0};
bool hdl;
+ rtw_replace_radar_flag_with_no_ir(hw);
+
hdl = rtw_regd_state_hdl(rtwdev, &next_regd, request);
if (!hdl) {
rtw_dbg(rtwdev, RTW_DBG_REGD,
--
2.35.0.rc0.227.g00780c9af4-goog