From 8903b905962c705a1dc46eed60c162b7346497f9 Mon Sep 17 00:00:00 2001
From: Lavanya Suresh <lavaks@codeaurora.org>
Date: Thu, 6 May 2021 13:31:49 +0530
Subject: [PATCH] mac80211: Add support to handle AWGN interference for 6G

On receiving AWGN interference indication, mac80211 triggers actions
to bringdown the interface and indicates the same to userspace using
existing NL80211_CMD_STOP_AP interface, so as to avoid transmission
in that channel.

Signed-off-by: Lavanya Suresh <lavaks@codeaurora.org>
---
 include/net/mac80211.h     |  7 +++++++
 net/mac80211/ieee80211_i.h |  4 ++++
 net/mac80211/iface.c       |  2 ++
 net/mac80211/util.c        | 26 ++++++++++++++++++++++++++
 4 files changed, 39 insertions(+)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index df3c728..a91a7f9 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -6245,6 +6245,13 @@ void ieee80211_radar_detected(struct ieee80211_hw *hw);
 void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success);
 
 /**
+ * ieee80211_awgn_detected - inform that awgn interference is detected
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ */
+void ieee80211_awgn_detected(struct ieee80211_vif *vif);
+
+/**
  * ieee80211_request_smps - request SM PS transition
  * @vif: &struct ieee80211_vif pointer from the add_interface callback.
  * @smps_mode: new SM PS mode
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 448e8bd..200d325 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -952,6 +952,8 @@ struct ieee80211_sub_if_data {
 	bool csa_block_tx; /* write-protected by sdata_lock and local->mtx */
 	struct cfg80211_chan_def csa_chandef;
 
+	struct work_struct awgn_detected_work;
+
 	struct work_struct color_change_finalize_work;
 
 	struct list_head assigned_chanctx_list; /* protected by chanctx_mtx */
@@ -1778,6 +1780,8 @@ int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
 void ieee80211_csa_finalize_work(struct work_struct *work);
 int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
 			     struct cfg80211_csa_settings *params);
+/* awgn interference handling */
+void ieee80211_awgn_interference_detected_work(struct work_struct *work);
 
 /* color change handling */
 void ieee80211_color_change_finalize_work(struct work_struct *work);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 1169a1c..7d441ac 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -471,6 +471,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
 	sdata_unlock(sdata);
 
 	cancel_work_sync(&sdata->csa_finalize_work);
+	cancel_work_sync(&sdata->awgn_detected_work);
 
 	cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
 
@@ -1660,6 +1661,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
 	INIT_WORK(&sdata->work, ieee80211_iface_work);
 	INIT_WORK(&sdata->recalc_smps, ieee80211_recalc_smps_work);
 	INIT_WORK(&sdata->csa_finalize_work, ieee80211_csa_finalize_work);
+	INIT_WORK(&sdata->awgn_detected_work, ieee80211_awgn_interference_detected_work);
 	INIT_WORK(&sdata->color_change_finalize_work, ieee80211_color_change_finalize_work);
 	INIT_LIST_HEAD(&sdata->assigned_chanctx_list);
 	INIT_LIST_HEAD(&sdata->reserved_chanctx_list);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index a00ed23..56f490b 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -3929,6 +3929,32 @@ u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c)
 	return ret;
 }
 
+void ieee80211_awgn_interference_detected_work(struct work_struct *work)
+{
+	struct ieee80211_sub_if_data *sdata =
+		container_of(work, struct ieee80211_sub_if_data, awgn_detected_work);
+
+	sdata_lock(sdata);
+
+	if (!ieee80211_sdata_running(sdata))
+		goto unlock;
+
+	cfg80211_stop_iface(sdata->local->hw.wiphy, &sdata->wdev,
+			    GFP_KERNEL);
+
+unlock:
+	sdata_unlock(sdata);
+}
+
+void ieee80211_awgn_detected(struct ieee80211_vif *vif)
+{
+	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+
+	ieee80211_queue_work(&sdata->local->hw,
+			     &sdata->awgn_detected_work);
+}
+EXPORT_SYMBOL(ieee80211_awgn_detected);
+
 /*
  * Returns true if smps_mode_new is strictly more restrictive than
  * smps_mode_old.
-- 
2.7.4

