[][MAC80211][core][Add DFS status show, cac and nop skip command]
[Description]
Add DFS status show, cac/nop skip command via debugfs in cfg80211
[Release-log]
N/A
Change-Id: I693b54c3d74ef932a7ba1ef864d24ab237b49dee
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/6590829
Build: srv_hbgsm110
diff --git a/autobuild_mac80211_release/package/kernel/mac80211/patches/subsys/914-cfg80211-implement-DFS-status-show-cac-and-nop-skip-command.patch b/autobuild_mac80211_release/package/kernel/mac80211/patches/subsys/914-cfg80211-implement-DFS-status-show-cac-and-nop-skip-command.patch
new file mode 100644
index 0000000..2aaf114
--- /dev/null
+++ b/autobuild_mac80211_release/package/kernel/mac80211/patches/subsys/914-cfg80211-implement-DFS-status-show-cac-and-nop-skip-command.patch
@@ -0,0 +1,256 @@
+From eca521242b94855825f085d1bca67a5958420baa Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Thu, 22 Sep 2022 14:27:41 +0800
+Subject: [PATCH] cfg80211: implement DFS status show, cac and nop skip command
+ via debugfs
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ net/wireless/debugfs.c | 228 +++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 221 insertions(+), 7 deletions(-)
+
+diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c
+index aab4346..19c3091 100644
+--- a/net/wireless/debugfs.c
++++ b/net/wireless/debugfs.c
+@@ -95,16 +95,230 @@ static const struct file_operations ht40allow_map_ops = {
+ .llseek = default_llseek,
+ };
+
+-#define DEBUGFS_ADD(name) \
+- debugfs_create_file(#name, 0444, phyd, &rdev->wiphy, &name## _ops)
++static int dfs_print_chan(struct ieee80211_channel *chan, int remain_time,
++ char *buf, int buf_size, int offset)
++{
++ if (WARN_ON(offset > buf_size))
++ return 0;
++
++ if (chan->dfs_state == NL80211_DFS_UNAVAILABLE) {
++ offset += scnprintf(buf + offset, buf_size - offset,
++ " Channel = %d, DFS_state = Unavailable",
++ chan->hw_value);
++ if (remain_time > 0)
++ offset += scnprintf(buf + offset, buf_size - offset,
++ ", Non-occupancy Remain Time = %d [sec]\n",
++ remain_time);
++ else
++ offset += scnprintf(buf + offset, buf_size - offset,
++ ", Changing state...\n");
++ } else if (chan->dfs_state == NL80211_DFS_USABLE) {
++ offset += scnprintf(buf + offset, buf_size - offset,
++ " Channel = %d, DFS_state = Usable",
++ chan->hw_value);
++ if (remain_time > 0)
++ offset += scnprintf(buf + offset, buf_size - offset,
++ ", CAC Remain Time = %d [sec]\n",
++ remain_time);
++ else
++ offset += scnprintf(buf + offset, buf_size - offset,
++ "\n");
++ } else if (chan->dfs_state == NL80211_DFS_AVAILABLE) {
++ offset += scnprintf(buf + offset, buf_size - offset,
++ " Channel = %d, DFS_state = Available\n",
++ chan->hw_value);
++ } else {
++ offset += scnprintf(buf + offset, buf_size - offset,
++ " Channel = %d, DFS_state = Unknown\n",
++ chan->hw_value);
++ }
++
++ return offset;
++}
++
++static int dfs_status_read_wdev(struct wiphy *wiphy, struct wireless_dev *wdev, char *buf,
++ unsigned int buf_size, unsigned int offset)
++{
++ struct cfg80211_chan_def *chandef;
++ enum nl80211_band band;
++ struct ieee80211_supported_band *sband;
++ struct ieee80211_channel *chan;
++ unsigned long jiffies_passed;
++ int i, remain_time = 0;
++
++ offset += scnprintf(buf + offset, buf_size - offset, "DFS Channel:\n");
++
++ for (band = 0; band < NUM_NL80211_BANDS; band++) {
++ sband = wiphy->bands[band];
++ if (!sband)
++ continue;
++ for (i = 0; i < sband->n_channels; i++) {
++ chan = &sband->channels[i];
++
++ if (!(chan->flags & IEEE80211_CHAN_RADAR))
++ continue;
++
++ if (chan->dfs_state == NL80211_DFS_UNAVAILABLE) {
++ jiffies_passed = jiffies - chan->dfs_state_entered;
++ remain_time = (IEEE80211_DFS_MIN_NOP_TIME_MS -
++ jiffies_to_msecs(jiffies_passed));
++ if (remain_time > IEEE80211_DFS_MIN_NOP_TIME_MS)
++ remain_time = 0;
++ } else if (chan->dfs_state == NL80211_DFS_USABLE) {
++ chandef = &wdev->chandef;
++ if (wdev->cac_started && cfg80211_is_sub_chan(chandef, chan)) {
++ jiffies_passed = jiffies - wdev->cac_start_time;
++ remain_time = (wdev->cac_time_ms -
++ jiffies_to_msecs(jiffies_passed));
++ }
++ if (remain_time > wdev->cac_time_ms)
++ remain_time = 0;
++ }
++ offset = dfs_print_chan(chan, remain_time / 1000, buf, buf_size, offset);
++ remain_time = 0;
++ }
++ }
++
++ return offset;
++}
++
++static ssize_t dfs_status_read(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct wiphy *wiphy = file->private_data;
++ struct wireless_dev *wdev;
++ char *buf;
++ unsigned int offset = 0, buf_size = PAGE_SIZE, r;
++ const char * const iftype_str[] = {
++ [NL80211_IFTYPE_UNSPECIFIED] = "unspecified",
++ [NL80211_IFTYPE_ADHOC] = "adhoc",
++ [NL80211_IFTYPE_STATION] = "station",
++ [NL80211_IFTYPE_AP] = "ap",
++ [NL80211_IFTYPE_AP_VLAN] = "ap vlan",
++ [NL80211_IFTYPE_WDS] = "wds",
++ [NL80211_IFTYPE_MONITOR] = "monitor",
++ [NL80211_IFTYPE_MESH_POINT] = "mesh point",
++ [NL80211_IFTYPE_P2P_CLIENT] = "p2p client",
++ [NL80211_IFTYPE_P2P_GO] = "p2p go",
++ [NL80211_IFTYPE_P2P_DEVICE] = "p2p device",
++ [NL80211_IFTYPE_OCB] = "ocb",
++ [NL80211_IFTYPE_NAN] = "nan",
++ };
++
++ buf = kzalloc(buf_size, GFP_KERNEL);
++ if (!buf)
++ return -ENOMEM;
++
++ list_for_each_entry(wdev, &wiphy->wdev_list, list) {
++ offset += scnprintf(buf + offset, buf_size - offset,
++ "wdev 0x%x\n"
++ "interface type %s\n",
++ wdev->identifier, iftype_str[wdev->iftype]);
++ offset = dfs_status_read_wdev(wiphy, wdev, buf, buf_size, offset);
++ }
++
++ r = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
++
++ kfree(buf);
++
++ return r;
++}
++
++static const struct file_operations dfs_status_ops = {
++ .read = dfs_status_read,
++ .open = simple_open,
++ .llseek = default_llseek,
++};
++
++static int
++dfs_nop_skip(void *data, u64 val)
++{
++ struct wiphy *wiphy = data;
++ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
++ bool en = !!val;
++ enum nl80211_band band;
++ struct ieee80211_supported_band *sband;
++ struct ieee80211_channel *chan;
++ u32 nop_time = IEEE80211_DFS_MIN_NOP_TIME_MS;
++ int i;
++
++ if (!en)
++ return 0;
++
++ for (band = 0; band < NUM_NL80211_BANDS; band++) {
++ sband = wiphy->bands[band];
++ if (!sband)
++ continue;
++ for (i = 0; i < sband->n_channels; i++) {
++ chan = &sband->channels[i];
++
++ if (!(chan->flags & IEEE80211_CHAN_RADAR))
++ continue;
++
++ if (chan->dfs_state == NL80211_DFS_UNAVAILABLE) {
++ // Let current jiffies > dfs_state_entered_jiffies + NOP time
++ chan->dfs_state_entered = jiffies -
++ msecs_to_jiffies(nop_time + 1);
++ }
++ }
++ }
++
++ cfg80211_sched_dfs_chan_update(rdev);
++
++ return 0;
++}
++
++DEFINE_DEBUGFS_ATTRIBUTE(dfs_skip_nop_ops, NULL,
++ dfs_nop_skip, "0x%08llx\n");
++
++static int
++dfs_cac_skip(void *data, u64 val)
++{
++ struct wiphy *wiphy = data;
++ struct wireless_dev *wdev;
++ struct cfg80211_chan_def *chandef;
++ bool en = !!val;
++ struct ieee80211_channel *chan;
++
++ if (!en)
++ return 0;
++
++ list_for_each_entry(wdev, &wiphy->wdev_list, list) {
++ chandef = &wdev->chandef;
++ if (chandef->chan) {
++ chan = chandef->chan;
++ if (!(chan->flags & IEEE80211_CHAN_RADAR))
++ continue;
++
++ if (chan->dfs_state == NL80211_DFS_USABLE && wdev->cac_started) {
++ // Let current jiffies > dfs_state_entered_jiffies + CAC time
++ wdev->cac_start_time = jiffies -
++ msecs_to_jiffies(wdev->cac_time_ms + 1);
++ cfg80211_cac_event(wdev->netdev, chandef,
++ NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
++ }
++ }
++ }
++
++ return 0;
++}
++
++DEFINE_DEBUGFS_ATTRIBUTE(dfs_skip_cac_ops, NULL,
++ dfs_cac_skip, "0x%08llx\n");
++
++#define DEBUGFS_ADD(name, chmod) \
++ debugfs_create_file(#name, chmod, phyd, &rdev->wiphy, &name## _ops)
+
+ void cfg80211_debugfs_rdev_add(struct cfg80211_registered_device *rdev)
+ {
+ struct dentry *phyd = rdev->wiphy.debugfsdir;
+
+- DEBUGFS_ADD(rts_threshold);
+- DEBUGFS_ADD(fragmentation_threshold);
+- DEBUGFS_ADD(short_retry_limit);
+- DEBUGFS_ADD(long_retry_limit);
+- DEBUGFS_ADD(ht40allow_map);
++ DEBUGFS_ADD(rts_threshold, 0444);
++ DEBUGFS_ADD(fragmentation_threshold, 0444);
++ DEBUGFS_ADD(short_retry_limit, 0444);
++ DEBUGFS_ADD(long_retry_limit, 0444);
++ DEBUGFS_ADD(ht40allow_map, 0444);
++ DEBUGFS_ADD(dfs_status, 0444);
++ DEBUGFS_ADD(dfs_skip_nop, 0600);
++ DEBUGFS_ADD(dfs_skip_cac, 0600);
+ }
+--
+2.18.0
+