[][MAC80211][core][Add sta-assisted DFS state update mechanism in eagle]
[Description]
Add sta-assisted DFS state update mechanism in eagle for the needs of
autotest.
[Release-log]
N/A
Change-Id: I7d8af40a401f596e7ade6e39d0204593422a4d3d
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/7615400
diff --git a/autobuild_mac80211_release/package/kernel/mac80211_dev/patches/subsys/mtk-0016-mac80211-mtk-add-sta-assisted-DFS-state-update-mecha.patch b/autobuild_mac80211_release/package/kernel/mac80211_dev/patches/subsys/mtk-0016-mac80211-mtk-add-sta-assisted-DFS-state-update-mecha.patch
new file mode 100644
index 0000000..f14111c
--- /dev/null
+++ b/autobuild_mac80211_release/package/kernel/mac80211_dev/patches/subsys/mtk-0016-mac80211-mtk-add-sta-assisted-DFS-state-update-mecha.patch
@@ -0,0 +1,180 @@
+From e545285e24de95d0d620bb7e9c97abba39e363b9 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 14:25:24 +0800
+Subject: [PATCH] mac80211: mtk: add sta-assisted DFS state update mechanism
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ include/net/cfg80211.h | 14 +++++++++
+ include/uapi/linux/nl80211.h | 6 ++++
+ net/mac80211/mlme.c | 12 ++++++++
+ net/wireless/chan.c | 60 ++++++++++++++++++++++++++++++++++++
+ 4 files changed, 92 insertions(+)
+
+diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
+index 84564bd..06d1567 100644
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -8180,6 +8180,20 @@ void cfg80211_cac_event(struct net_device *netdev,
+ const struct cfg80211_chan_def *chandef,
+ enum nl80211_radar_event event, gfp_t gfp);
+
++/**
++ * cfg80211_sta_update_dfs_state - Update channel's DFS state during STA channel switch,
++ * association, and disassociation
++ * @wdev: the wireless device
++ * @bss_chandef: the current BSS channel definition
++ * @csa_chandef: the CSA channel definition
++ * @associated: whether STA is during association or disassociation process
++ *
++ */
++void cfg80211_sta_update_dfs_state(struct wireless_dev *wdev,
++ const struct cfg80211_chan_def *bss_chandef,
++ const struct cfg80211_chan_def *csa_chandef,
++ bool associated);
++
+ /**
+ * cfg80211_background_cac_abort - Channel Availability Check offchan abort event
+ * @wiphy: the wiphy
+diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
+index bd26a06..e453d64 100644
+--- a/include/uapi/linux/nl80211.h
++++ b/include/uapi/linux/nl80211.h
+@@ -6565,6 +6565,10 @@ enum nl80211_smps_mode {
+ * applicable for ETSI dfs domain where pre-CAC is valid for ever.
+ * @NL80211_RADAR_CAC_STARTED: Channel Availability Check has been started,
+ * should be generated by HW if NL80211_EXT_FEATURE_DFS_OFFLOAD is enabled.
++ * @NL80211_RADAR_STA_CAC_SKIPPED: STA set the DFS state to available
++ * when receiving CSA/assoc resp
++ * @NL80211_RADAR_STA_CAC_EXPIRED: STA set the DFS state to usable
++ * when STA is disconnected or leaving the channel
+ */
+ enum nl80211_radar_event {
+ NL80211_RADAR_DETECTED,
+@@ -6573,6 +6577,8 @@ enum nl80211_radar_event {
+ NL80211_RADAR_NOP_FINISHED,
+ NL80211_RADAR_PRE_CAC_EXPIRED,
+ NL80211_RADAR_CAC_STARTED,
++ NL80211_RADAR_STA_CAC_SKIPPED,
++ NL80211_RADAR_STA_CAC_EXPIRED,
+ };
+
+ /**
+diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
+index 72d153f..5a3dd31 100644
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -1987,6 +1987,11 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
+ IEEE80211_QUEUE_STOP_REASON_CSA);
+ mutex_unlock(&local->mtx);
+
++ cfg80211_sta_update_dfs_state(&sdata->wdev,
++ &sdata->vif.bss_conf.chandef,
++ &link->csa_chandef,
++ sdata->vif.cfg.assoc);
++
+ cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chandef, 0,
+ csa_ie.count, csa_ie.mode, 0);
+
+@@ -3072,6 +3077,10 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
+ sizeof(sdata->vif.bss_conf.tx_pwr_env));
+
+ ieee80211_vif_set_links(sdata, 0);
++
++ cfg80211_sta_update_dfs_state(&sdata->wdev,
++ &sdata->vif.bss_conf.chandef,
++ NULL, sdata->vif.cfg.assoc);
+ }
+
+ static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
+@@ -5276,6 +5285,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
+ event.u.mlme.status = MLME_SUCCESS;
+ drv_event_callback(sdata->local, sdata, &event);
+ sdata_info(sdata, "associated\n");
++ cfg80211_sta_update_dfs_state(&sdata->wdev,
++ &sdata->vif.bss_conf.chandef,
++ NULL, sdata->vif.cfg.assoc);
+
+ info.success = 1;
+ }
+diff --git a/net/wireless/chan.c b/net/wireless/chan.c
+index fef0ba5..13276bc 100644
+--- a/net/wireless/chan.c
++++ b/net/wireless/chan.c
+@@ -14,6 +14,7 @@
+ #include <net/cfg80211.h>
+ #include "core.h"
+ #include "rdev-ops.h"
++#include "nl80211.h"
+
+ static bool cfg80211_valid_60g_freq(u32 freq)
+ {
+@@ -1436,6 +1437,65 @@ bool cfg80211_any_usable_channels(struct wiphy *wiphy,
+ }
+ EXPORT_SYMBOL(cfg80211_any_usable_channels);
+
++static void cfg80211_sta_radar_notify(struct wiphy *wiphy,
++ const struct cfg80211_chan_def *chandef,
++ enum nl80211_radar_event event)
++{
++ struct wireless_dev *wdev;
++
++ list_for_each_entry(wdev, &wiphy->wdev_list, list) {
++ if (cfg80211_chandef_dfs_required(wiphy, chandef, wdev->iftype) > 0) {
++ nl80211_radar_notify(wiphy_to_rdev(wiphy), chandef,
++ event, wdev->netdev, GFP_KERNEL);
++ return;
++ }
++ }
++}
++
++void cfg80211_sta_update_dfs_state(struct wireless_dev *wdev,
++ const struct cfg80211_chan_def *bss_chandef,
++ const struct cfg80211_chan_def *csa_chandef,
++ bool associated)
++{
++ bool csa_active = !!csa_chandef;
++ enum nl80211_dfs_state dfs_state = NL80211_DFS_USABLE;
++ enum nl80211_radar_event event = NL80211_RADAR_STA_CAC_EXPIRED;
++
++ if (!bss_chandef)
++ return;
++
++ /* assume csa channel is cac completed */
++ if (csa_active &&
++ (cfg80211_chandef_dfs_usable(wdev->wiphy, csa_chandef) ||
++ cfg80211_chandef_dfs_available(wdev->wiphy, csa_chandef))) {
++ cfg80211_set_dfs_state(wdev->wiphy, csa_chandef, NL80211_DFS_AVAILABLE);
++ cfg80211_sta_radar_notify(wdev->wiphy, csa_chandef,
++ NL80211_RADAR_STA_CAC_SKIPPED);
++ netdev_info(wdev->netdev, "Set CSA channel's DFS state to available\n");
++ }
++
++ /* avoid updating the dfs state during nop */
++ if (!cfg80211_chandef_dfs_usable(wdev->wiphy, bss_chandef) &&
++ !cfg80211_chandef_dfs_available(wdev->wiphy, bss_chandef))
++ return;
++
++ if (associated && !csa_active) {
++ dfs_state = NL80211_DFS_AVAILABLE;
++ event = NL80211_RADAR_STA_CAC_SKIPPED;
++ }
++
++ cfg80211_set_dfs_state(wdev->wiphy, bss_chandef, dfs_state);
++ cfg80211_sta_radar_notify(wdev->wiphy, bss_chandef, event);
++
++ if (csa_active)
++ netdev_info(wdev->netdev, "Set origin channel's DFS state to usable\n");
++ else
++ netdev_info(wdev->netdev, "Set BSS channel's DFS state to %s due to %s\n",
++ (dfs_state == NL80211_DFS_USABLE) ? "usable" : "available",
++ associated ? "association" : "disassociation");
++}
++EXPORT_SYMBOL(cfg80211_sta_update_dfs_state);
++
+ struct cfg80211_chan_def *wdev_chandef(struct wireless_dev *wdev,
+ unsigned int link_id)
+ {
+--
+2.18.0
+