Files
wlan-ap/feeds/mediatek-sdk/mac80211/patches/subsys/mtk-0034-mac80211-mtk-add-dfs-relax-flag-for-scanning-without.patch
Arif Alam 26b61bbdd9 mac80211: update patches
Signed-off-by: Arif Alam <arif.alam@netexperience.com>
2025-07-30 01:30:44 -04:00

197 lines
6.1 KiB
Diff

From d873d195bcb481b7b82be195cb17e3fc7f7ecf58 Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Wed, 11 Dec 2024 13:21:21 +0800
Subject: [PATCH] mac80211: mtk: add dfs relax flag for scanning without dfs
restrictions
Add dfs relax flag for scanning without dfs restrictions.
If user turn on the dfs relax flag by entering the following command:
echo 1 > /sys/kernel/debug/ieee80211/phyX/scan_dfs_relax
Then, allow AP/STA to scan while operating on a DFS channel.
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
---
include/net/cfg80211.h | 4 +++
net/mac80211/offchannel.c | 4 +--
net/mac80211/scan.c | 3 ++-
net/wireless/debugfs.c | 53 +++++++++++++++++++++++++++++++++++++++
net/wireless/nl80211.c | 14 ++++++++---
5 files changed, 71 insertions(+), 7 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 67b0e6c..f159340 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5047,6 +5047,8 @@ struct wiphy_iftype_akm_suites {
* @mbssid_max_ema_profile_periodicity: maximum profile periodicity supported by
* the driver. Setting this field to a non-zero value indicates that the
* driver supports enhanced multi-BSSID advertisements (EMA AP).
+ *
+ * @dfs_relax: a flag to relax the DFS restrictions during scanning
*/
struct wiphy {
struct mutex mtx;
@@ -5197,6 +5199,8 @@ struct wiphy {
u8 mbssid_max_interfaces;
u8 ema_max_profile_periodicity;
+ bool dfs_relax;
+
char priv[] __aligned(NETDEV_ALIGN);
};
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index 042b6fb..2cd8454 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -579,8 +579,8 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
}
/* if there's no need to queue, handle it immediately */
- if (list_empty(&local->roc_list) &&
- !local->scanning && !ieee80211_is_radar_required(local)) {
+ if (list_empty(&local->roc_list) && !local->scanning &&
+ (local->hw.wiphy->dfs_relax || !ieee80211_is_radar_required(local))) {
/* if not HW assist, just queue & schedule work */
if (!local->ops->remain_on_channel) {
list_add_tail(&roc->list, &local->roc_list);
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 9d53f1a..9ef5179 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -572,7 +572,8 @@ static bool __ieee80211_can_leave_ch(struct ieee80211_sub_if_data *sdata)
if (!ieee80211_is_radar_required(local))
return true;
- if (!regulatory_pre_cac_allowed(local->hw.wiphy))
+ if (!local->hw.wiphy->dfs_relax &&
+ !regulatory_pre_cac_allowed(local->hw.wiphy))
return false;
mutex_lock(&local->iflist_mtx);
diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c
index 0637ed4..9fecbef 100644
--- a/net/wireless/debugfs.c
+++ b/net/wireless/debugfs.c
@@ -388,6 +388,58 @@ dfs_available_reset(void *data, u64 val)
DEFINE_DEBUGFS_ATTRIBUTE(dfs_available_reset_ops, NULL,
dfs_available_reset, "0x%08llx\n");
+
+static ssize_t scan_dfs_relax_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct wiphy *wiphy = file->private_data;
+ char buf[16];
+
+ if (count >= sizeof(buf))
+ return -EINVAL;
+
+ if (copy_from_user(buf, user_buf, count))
+ return -EFAULT;
+
+ if (count && buf[count - 1] == '\n')
+ buf[count - 1] = '\0';
+ else
+ buf[count] = '\0';
+
+ if (kstrtobool(buf, &wiphy->dfs_relax))
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t scan_dfs_relax_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct wiphy *wiphy = file->private_data;
+ unsigned int r, offset, buf_size = PAGE_SIZE;
+ char *buf;
+
+ buf = kzalloc(buf_size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ offset = scnprintf(buf, buf_size, "dfs relax: %u\n", wiphy->dfs_relax);
+
+ r = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
+
+ kfree(buf);
+
+ return r;
+}
+
+static const struct file_operations scan_dfs_relax_ops = {
+ .write = scan_dfs_relax_write,
+ .read = scan_dfs_relax_read,
+ .open = simple_open,
+ .llseek = default_llseek,
+};
+
#define DEBUGFS_ADD(name, chmod) \
debugfs_create_file(#name, chmod, phyd, &rdev->wiphy, &name## _ops)
@@ -404,4 +456,5 @@ void cfg80211_debugfs_rdev_add(struct cfg80211_registered_device *rdev)
DEBUGFS_ADD(dfs_skip_nop, 0600);
DEBUGFS_ADD(dfs_skip_cac, 0600);
DEBUGFS_ADD(dfs_available_reset, 0600);
+ DEBUGFS_ADD(scan_dfs_relax, 0644);
}
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 4883b1f..3d22429 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -8400,13 +8400,16 @@ int nl80211_parse_random_mac(struct nlattr **attrs,
return 0;
}
-static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev)
+static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev, bool dfs_relax)
{
ASSERT_WDEV_LOCK(wdev);
if (!cfg80211_beaconing_iface_active(wdev))
return true;
+ if (dfs_relax)
+ return true;
+
if (!(wdev->chandef.chan->flags & IEEE80211_CHAN_RADAR))
return true;
@@ -8627,7 +8630,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
request->n_channels = i;
wdev_lock(wdev);
- if (!cfg80211_off_channel_oper_allowed(wdev)) {
+ if (!cfg80211_off_channel_oper_allowed(wdev, wiphy->dfs_relax)) {
struct ieee80211_channel *chan;
if (request->n_channels != 1) {
@@ -11549,8 +11552,11 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
if (err)
return err;
+ if (wdev->cac_started)
+ return -EBUSY;
+
wdev_lock(wdev);
- if (!cfg80211_off_channel_oper_allowed(wdev) &&
+ if (!cfg80211_off_channel_oper_allowed(wdev, rdev->wiphy.dfs_relax) &&
!cfg80211_chandef_identical(&wdev->chandef, &chandef)) {
compat_chandef = cfg80211_chandef_compatible(&wdev->chandef,
&chandef);
@@ -11755,7 +11761,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
wdev_lock(wdev);
- if (params.offchan && !cfg80211_off_channel_oper_allowed(wdev)) {
+ if (params.offchan && !cfg80211_off_channel_oper_allowed(wdev, false)) {
wdev_unlock(wdev);
return -EBUSY;
}
--
2.45.2