mirror of
https://github.com/outbackdingo/wlan-ap.git
synced 2026-01-27 10:20:52 +00:00
ath11k: backport awgn mitigation in 6GHz
Signed-off-by: Arif Alam <arif.alam@netexperience.com>
This commit is contained in:
@@ -21,10 +21,8 @@ Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
|
||||
drivers/net/wireless/ath/ath11k/wmi.c | 49 ++++++++++++-
|
||||
6 files changed, 229 insertions(+), 95 deletions(-)
|
||||
|
||||
Index: backports-20210222_001-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/core.c
|
||||
===================================================================
|
||||
--- backports-20210222_001-4.4.60-b157d2276.orig/drivers/net/wireless/ath/ath11k/core.c
|
||||
+++ backports-20210222_001-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/core.c
|
||||
--- a/drivers/net/wireless/ath/ath11k/core.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/core.c
|
||||
@@ -425,6 +425,55 @@ static const struct ath11k_num_vdevs_pee
|
||||
},
|
||||
};
|
||||
@@ -81,10 +79,8 @@ Index: backports-20210222_001-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/c
|
||||
int ath11k_core_suspend(struct ath11k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
Index: backports-20210222_001-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/core.h
|
||||
===================================================================
|
||||
--- backports-20210222_001-4.4.60-b157d2276.orig/drivers/net/wireless/ath/ath11k/core.h
|
||||
+++ backports-20210222_001-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/core.h
|
||||
--- a/drivers/net/wireless/ath/ath11k/core.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/core.h
|
||||
@@ -527,8 +527,6 @@ struct ath11k_debug {
|
||||
struct ath11k_dbg_htt_stats htt_stats;
|
||||
u32 extd_tx_stats;
|
||||
@@ -94,10 +90,10 @@ Index: backports-20210222_001-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/c
|
||||
u32 extd_rx_stats;
|
||||
u32 pktlog_filter;
|
||||
u32 pktlog_mode;
|
||||
@@ -759,6 +757,11 @@ struct ath11k {
|
||||
u8 cfr_enabled;
|
||||
bool ani_enabled;
|
||||
enum wmi_phy_mode cfr_phymode;
|
||||
@@ -764,6 +762,11 @@ struct ath11k {
|
||||
struct cfg80211_chan_def awgn_chandef;
|
||||
u32 chan_bw_interference_bitmap;
|
||||
bool awgn_intf_handling_in_prog;
|
||||
+
|
||||
+ /* fw pdev_stats can be requested by get_txpower mac ops too */
|
||||
+ struct list_head fw_stats_pdevs;
|
||||
@@ -106,7 +102,7 @@ Index: backports-20210222_001-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/c
|
||||
};
|
||||
|
||||
struct ath11k_band_cap {
|
||||
@@ -1188,6 +1191,12 @@ enum ath11k_fw_recovery_option {
|
||||
@@ -1193,6 +1196,12 @@ enum ath11k_fw_recovery_option {
|
||||
ATH11K_FW_RECOVERY_ENABLE_SSR_ONLY,
|
||||
};
|
||||
|
||||
@@ -119,10 +115,8 @@ Index: backports-20210222_001-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/c
|
||||
extern const struct ce_pipe_config ath11k_target_ce_config_wlan_ipq8074[];
|
||||
extern const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_ipq8074[];
|
||||
extern const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_ipq6018[];
|
||||
Index: backports-20210222_001-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/debugfs.c
|
||||
===================================================================
|
||||
--- backports-20210222_001-4.4.60-b157d2276.orig/drivers/net/wireless/ath/ath11k/debugfs.c
|
||||
+++ backports-20210222_001-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/debugfs.c
|
||||
--- a/drivers/net/wireless/ath/ath11k/debugfs.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/debugfs.c
|
||||
@@ -650,86 +650,29 @@ void ath11k_debug_aggr_size_config_init(
|
||||
&fops_amsdu_aggr_size);
|
||||
}
|
||||
@@ -313,10 +307,8 @@ Index: backports-20210222_001-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/d
|
||||
}
|
||||
|
||||
static ssize_t ath11k_write_pktlog_filter(struct file *file,
|
||||
Index: backports-20210222_001-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/debugfs.h
|
||||
===================================================================
|
||||
--- backports-20210222_001-4.4.60-b157d2276.orig/drivers/net/wireless/ath/ath11k/debugfs.h
|
||||
+++ backports-20210222_001-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/debugfs.h
|
||||
--- a/drivers/net/wireless/ath/ath11k/debugfs.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/debugfs.h
|
||||
@@ -231,7 +231,7 @@ int ath11k_debugfs_pdev_create(struct at
|
||||
void ath11k_debugfs_pdev_destroy(struct ath11k_base *ab);
|
||||
int ath11k_debugfs_register(struct ath11k *ar);
|
||||
@@ -337,11 +329,9 @@ Index: backports-20210222_001-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/d
|
||||
{
|
||||
}
|
||||
|
||||
Index: backports-20210222_001-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/mac.c
|
||||
===================================================================
|
||||
--- backports-20210222_001-4.4.60-b157d2276.orig/drivers/net/wireless/ath/ath11k/mac.c
|
||||
+++ backports-20210222_001-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/mac.c
|
||||
@@ -8850,6 +8850,96 @@ out:
|
||||
--- a/drivers/net/wireless/ath/ath11k/mac.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/mac.c
|
||||
@@ -8969,6 +8969,96 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -438,7 +428,7 @@ Index: backports-20210222_001-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/m
|
||||
static const struct ieee80211_ops ath11k_ops = {
|
||||
.tx = ath11k_mac_op_tx,
|
||||
.start = ath11k_mac_op_start,
|
||||
@@ -8892,6 +8982,7 @@ static const struct ieee80211_ops ath11k
|
||||
@@ -9011,6 +9101,7 @@ static const struct ieee80211_ops ath11k
|
||||
#ifdef CPTCFG_MAC80211_MESH
|
||||
.config_mesh_offload_path = ath11k_mac_op_config_mesh_offload_path,
|
||||
#endif
|
||||
@@ -446,7 +436,7 @@ Index: backports-20210222_001-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/m
|
||||
};
|
||||
|
||||
static void ath11k_mac_update_ch_list(struct ath11k *ar,
|
||||
@@ -9562,6 +9653,8 @@ int ath11k_mac_allocate(struct ath11k_ba
|
||||
@@ -9681,6 +9772,8 @@ int ath11k_mac_allocate(struct ath11k_ba
|
||||
ar->monitor_vdev_id = -1;
|
||||
ar->monitor_vdev_created = false;
|
||||
ar->monitor_started = false;
|
||||
@@ -455,10 +445,8 @@ Index: backports-20210222_001-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/m
|
||||
}
|
||||
|
||||
return 0;
|
||||
Index: backports-20210222_001-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/wmi.c
|
||||
===================================================================
|
||||
--- backports-20210222_001-4.4.60-b157d2276.orig/drivers/net/wireless/ath/ath11k/wmi.c
|
||||
+++ backports-20210222_001-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/wmi.c
|
||||
--- a/drivers/net/wireless/ath/ath11k/wmi.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
|
||||
@@ -7063,7 +7063,7 @@ void ath11k_wmi_fw_stats_fill(struct ath
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
|
||||
@@ -5,7 +5,8 @@ Subject: [PATCH] ath11k: Add support to handle AWGN interference for 6G
|
||||
|
||||
When AWGN interference is detected in any 6G channel, FW indicates it to
|
||||
host using WMI_DCS_INTERFERENCE_EVENT. Added support to parse new wmi
|
||||
event to get AWGN interference info and indicate to mac80211.
|
||||
event to get AWGN interference info, validate the AWGN detected channel
|
||||
and interference bitmap and indicate to mac80211.
|
||||
|
||||
AWGN interference detection support in FW will be advertised in wmi service
|
||||
ready event, based on which host can decide to handle and process interference
|
||||
@@ -26,7 +27,7 @@ Signed-off-by: Lavanya Suresh <lavaks@codeaurora.org>
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/debugfs.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/debugfs.c
|
||||
@@ -2161,6 +2161,35 @@ static const struct file_operations fops
|
||||
@@ -2165,6 +2165,35 @@ static const struct file_operations fops
|
||||
.open = simple_open
|
||||
};
|
||||
|
||||
@@ -62,7 +63,7 @@ Signed-off-by: Lavanya Suresh <lavaks@codeaurora.org>
|
||||
static ssize_t ath11k_write_btcoex(struct file *file,
|
||||
const char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
@@ -3765,6 +3794,12 @@ int ath11k_debugfs_register(struct ath11
|
||||
@@ -4136,6 +4165,12 @@ int ath11k_debugfs_register(struct ath11
|
||||
&ar->dfs_block_radar_events);
|
||||
}
|
||||
|
||||
@@ -77,7 +78,7 @@ Signed-off-by: Lavanya Suresh <lavaks@codeaurora.org>
|
||||
&fops_enable_m3_dump);
|
||||
--- a/drivers/net/wireless/ath/ath11k/wmi.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
|
||||
@@ -8419,6 +8419,143 @@ exit:
|
||||
@@ -8531,6 +8531,209 @@ exit:
|
||||
kfree(tb);
|
||||
}
|
||||
|
||||
@@ -96,6 +97,7 @@ Signed-off-by: Lavanya Suresh <lavaks@codeaurora.org>
|
||||
+ "AWGN Info: channel width: %d, chan freq: %d, center_freq0: %d, center_freq1: %d, bw_intf_bitmap: %d\n",
|
||||
+ awgn_info->channel_width, awgn_info->chan_freq, awgn_info->center_freq0, awgn_info->center_freq1,
|
||||
+ awgn_info->chan_bw_interference_bitmap);
|
||||
+ memcpy(data, awgn_info, sizeof(*awgn_info));
|
||||
+ break;
|
||||
+ default:
|
||||
+ ath11k_warn(ab,
|
||||
@@ -139,12 +141,72 @@ Signed-off-by: Lavanya Suresh <lavaks@codeaurora.org>
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+bool ath11k_wmi_validate_dcs_awgn_info(struct ath11k *ar, struct wmi_dcs_awgn_info *awgn_info)
|
||||
+{
|
||||
+ spin_lock_bh(&ar->data_lock);
|
||||
+
|
||||
+ if (!ar->rx_channel) {
|
||||
+ spin_unlock_bh(&ar->data_lock);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (awgn_info->chan_freq != ar->rx_channel->center_freq) {
|
||||
+ spin_unlock_bh(&ar->data_lock);
|
||||
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
|
||||
+ "dcs interference event received with wrong channel %d",awgn_info->chan_freq);
|
||||
+ return false;
|
||||
+ }
|
||||
+ spin_unlock_bh(&ar->data_lock);
|
||||
+
|
||||
+ switch (awgn_info->channel_width) {
|
||||
+ case WMI_HOST_CHAN_WIDTH_20:
|
||||
+ if (awgn_info->chan_bw_interference_bitmap > WMI_DCS_SEG_PRI20) {
|
||||
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
|
||||
+ "dcs interference event received with wrong chan width bmap %d for 20MHz",
|
||||
+ awgn_info->chan_bw_interference_bitmap);
|
||||
+ return false;
|
||||
+ }
|
||||
+ break;
|
||||
+ case WMI_HOST_CHAN_WIDTH_40:
|
||||
+ if (awgn_info->chan_bw_interference_bitmap > WMI_DCS_SEG_SEC20) {
|
||||
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
|
||||
+ "dcs interference event received with wrong chan width bmap %d for 40MHz",
|
||||
+ awgn_info->chan_bw_interference_bitmap);
|
||||
+ return false;
|
||||
+ }
|
||||
+ break;
|
||||
+ case WMI_HOST_CHAN_WIDTH_80:
|
||||
+ if (awgn_info->chan_bw_interference_bitmap > WMI_DCS_SEG_SEC40) {
|
||||
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
|
||||
+ "dcs interference event received with wrong chan width bmap %d for 80MHz",
|
||||
+ awgn_info->chan_bw_interference_bitmap);
|
||||
+ return false;
|
||||
+ }
|
||||
+ break;
|
||||
+ case WMI_HOST_CHAN_WIDTH_160:
|
||||
+ case WMI_HOST_CHAN_WIDTH_80P80:
|
||||
+ if (awgn_info->chan_bw_interference_bitmap > WMI_DCS_SEG_SEC80) {
|
||||
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
|
||||
+ "dcs interference event received with wrong chan width bmap %d for 80P80/160MHz",
|
||||
+ awgn_info->chan_bw_interference_bitmap);
|
||||
+ return false;
|
||||
+ }
|
||||
+ break;
|
||||
+ default:
|
||||
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
|
||||
+ "dcs interference event received with unknown channel width %d",
|
||||
+ awgn_info->channel_width);
|
||||
+ return false;
|
||||
+ }
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+ath11k_wmi_dcs_awgn_interference_event(struct ath11k_base *ab,
|
||||
+ struct sk_buff *skb)
|
||||
+{
|
||||
+ const struct wmi_dcs_interference_ev *dcs_intf_ev;
|
||||
+ struct wmi_dcs_awgn_info *awgn_info;
|
||||
+ struct wmi_dcs_awgn_info awgn_info = {};
|
||||
+ struct ath11k *ar;
|
||||
+ struct ath11k_vif *arvif;
|
||||
+ const struct wmi_tlv *tlv;
|
||||
@@ -186,7 +248,7 @@ Signed-off-by: Lavanya Suresh <lavaks@codeaurora.org>
|
||||
+
|
||||
+ ret = ath11k_wmi_tlv_iter(ab, skb->data, skb->len,
|
||||
+ ath11k_wmi_dcs_awgn_event_parser,
|
||||
+ awgn_info);
|
||||
+ &awgn_info);
|
||||
+ if (ret) {
|
||||
+ ath11k_warn(ab, "failed to parse awgn tlv %d\n", ret);
|
||||
+ return;
|
||||
@@ -205,6 +267,11 @@ Signed-off-by: Lavanya Suresh <lavaks@codeaurora.org>
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ if (!ath11k_wmi_validate_dcs_awgn_info(ar, &awgn_info)) {
|
||||
+ ath11k_warn(ab, "Invalid DCS AWGN TLV - Skipping event");
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ ath11k_info(ab, "Interface(pdev %d) will be disabled because of AWGN interference\n",
|
||||
+ dcs_intf_ev->pdev_id);
|
||||
+
|
||||
@@ -221,7 +288,7 @@ Signed-off-by: Lavanya Suresh <lavaks@codeaurora.org>
|
||||
static void ath11k_wmi_tm_event_segmented(struct ath11k_base *ab, u32 cmd_id,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
@@ -9566,6 +9703,9 @@ static void ath11k_wmi_tlv_op_rx(struct
|
||||
@@ -9678,6 +9881,9 @@ static void ath11k_wmi_tlv_op_rx(struct
|
||||
case WMI_WOW_WAKEUP_HOST_EVENTID:
|
||||
ath11k_wmi_event_wow_wakeup_host(ab, skb);
|
||||
break;
|
||||
@@ -231,7 +298,7 @@ Signed-off-by: Lavanya Suresh <lavaks@codeaurora.org>
|
||||
case WMI_PDEV_GET_TPC_STATS_EVENTID:
|
||||
ath11k_process_tpc_stats(ab, skb);
|
||||
break;
|
||||
@@ -9728,6 +9868,42 @@ int ath11k_wmi_simulate_radar(struct ath
|
||||
@@ -9846,6 +10052,42 @@ int ath11k_wmi_simulate_radar(struct ath
|
||||
return ath11k_wmi_send_unit_test_cmd(ar, wmi_ut, dfs_args);
|
||||
}
|
||||
|
||||
@@ -276,7 +343,7 @@ Signed-off-by: Lavanya Suresh <lavaks@codeaurora.org>
|
||||
u32 m3_args[WMI_M3_MAX_TEST_ARGS];
|
||||
--- a/drivers/net/wireless/ath/ath11k/wmi.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
|
||||
@@ -1903,6 +1903,7 @@ enum wmi_tlv_tag {
|
||||
@@ -1909,6 +1909,7 @@ enum wmi_tlv_tag {
|
||||
WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT,
|
||||
|
||||
WMI_CTRL_PATH_CAL_STATS = 0x3BC,
|
||||
@@ -284,7 +351,7 @@ Signed-off-by: Lavanya Suresh <lavaks@codeaurora.org>
|
||||
|
||||
WMI_TAG_MAX
|
||||
};
|
||||
@@ -2175,6 +2176,7 @@ enum wmi_tlv_service {
|
||||
@@ -2181,6 +2182,7 @@ enum wmi_tlv_service {
|
||||
WMI_TLV_SERVICE_PASSIVE_SCAN_START_TIME_ENHANCE = 263,
|
||||
WMI_TLV_SERVICE_QOS_NULL_FRAME_TX_OVER_WMI = 264,
|
||||
WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281,
|
||||
@@ -292,7 +359,7 @@ Signed-off-by: Lavanya Suresh <lavaks@codeaurora.org>
|
||||
|
||||
WMI_MAX_EXT2_SERVICE
|
||||
};
|
||||
@@ -4216,6 +4218,17 @@ struct wmi_dfs_unit_test_arg {
|
||||
@@ -4264,6 +4266,17 @@ struct wmi_dfs_unit_test_arg {
|
||||
u32 radar_param;
|
||||
};
|
||||
|
||||
@@ -310,7 +377,7 @@ Signed-off-by: Lavanya Suresh <lavaks@codeaurora.org>
|
||||
#define WMI_M3_UNIT_TEST_MODULE 0x22
|
||||
#define WMI_M3_UNIT_TEST_TOKEN 0
|
||||
|
||||
@@ -4843,6 +4856,21 @@ struct wmi_pdev_radar_ev {
|
||||
@@ -4891,6 +4904,42 @@ struct wmi_pdev_radar_ev {
|
||||
s32 sidx;
|
||||
} __packed;
|
||||
|
||||
@@ -328,11 +395,32 @@ Signed-off-by: Lavanya Suresh <lavaks@codeaurora.org>
|
||||
+ u32 interference_type;
|
||||
+ u32 pdev_id;
|
||||
+} __packed;
|
||||
+
|
||||
+enum wmi_host_channel_width {
|
||||
+ WMI_HOST_CHAN_WIDTH_20 = 0,
|
||||
+ WMI_HOST_CHAN_WIDTH_40 = 1,
|
||||
+ WMI_HOST_CHAN_WIDTH_80 = 2,
|
||||
+ WMI_HOST_CHAN_WIDTH_160 = 3,
|
||||
+ WMI_HOST_CHAN_WIDTH_80P80 = 4,
|
||||
+};
|
||||
+
|
||||
+enum wmi_dcs_interference_chan_segment {
|
||||
+ WMI_DCS_SEG_PRI20 = 0x1,
|
||||
+ WMI_DCS_SEG_SEC20 = 0x2,
|
||||
+ WMI_DCS_SEG_SEC40_LOWER = 0x4,
|
||||
+ WMI_DCS_SEG_SEC40_UPPER = 0x8,
|
||||
+ WMI_DCS_SEG_SEC40 = 0xC,
|
||||
+ WMI_DCS_SEG_SEC80_LOWER = 0x10,
|
||||
+ WMI_DCS_SEG_SEC80_LOWER_UPPER = 0x20,
|
||||
+ WMI_DCS_SEG_SEC80_UPPER_LOWER = 0x40,
|
||||
+ WMI_DCS_SEG_SEC80_UPPER = 0x80,
|
||||
+ WMI_DCS_SEG_SEC80 = 0xF0,
|
||||
+};
|
||||
+
|
||||
struct wmi_pdev_temperature_event {
|
||||
/* temperature value in Celcius degree */
|
||||
s32 temp;
|
||||
@@ -6636,6 +6664,7 @@ void ath11k_wmi_fw_stats_fill(struct ath
|
||||
@@ -6686,6 +6735,7 @@ void ath11k_wmi_fw_stats_fill(struct ath
|
||||
struct ath11k_fw_stats *fw_stats, u32 stats_id,
|
||||
char *buf);
|
||||
int ath11k_wmi_simulate_radar(struct ath11k *ar);
|
||||
|
||||
@@ -0,0 +1,388 @@
|
||||
From 53f2c10cf048d3420bff7db90cb3bafaf6f7ac57 Mon Sep 17 00:00:00 2001
|
||||
From: Hari Chandrakanthan <quic_haric@quicinc.com>
|
||||
Date: Wed, 1 Dec 2021 12:19:02 +0530
|
||||
Subject: [PATCH] ath11k : Add support for awgn mitigation in 6Ghz
|
||||
|
||||
AWGN - Additive white Gaussian Noise
|
||||
|
||||
support to simulate awgn event with channel bw
|
||||
interference bitmap is added.
|
||||
|
||||
channel bw interference bitmap holds the interference information
|
||||
on primary and secondary channels.
|
||||
|
||||
Eg: For 80Mhz operating bandwidth, the chan bw interference
|
||||
bitmap can be as follows.
|
||||
|
||||
segment chan_bw_interference_bitmap
|
||||
0 0x01
|
||||
1 0x02
|
||||
2 0x04
|
||||
3 0x08
|
||||
|
||||
segment 0 - primary 20Mhz
|
||||
segment 1 - secondary 20Mhz
|
||||
segment 2 - secondary 40Mhz lower
|
||||
segment 3 - secondary 40Mhz upper
|
||||
|
||||
support to update rx_channel is added
|
||||
|
||||
Signed-off-by: Hari Chandrakanthan <quic_haric@quicinc.com>
|
||||
---
|
||||
drivers/net/wireless/ath/ath11k/core.h | 4 ++
|
||||
drivers/net/wireless/ath/ath11k/debugfs.c | 6 +-
|
||||
drivers/net/wireless/ath/ath11k/mac.c | 116 +++++++++++++++++++++++++++++-
|
||||
drivers/net/wireless/ath/ath11k/mac.h | 3 +
|
||||
drivers/net/wireless/ath/ath11k/wmi.c | 33 ++++++---
|
||||
drivers/net/wireless/ath/ath11k/wmi.h | 2 +-
|
||||
6 files changed, 151 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/core.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/core.h
|
||||
@@ -689,6 +689,7 @@ struct ath11k {
|
||||
int max_num_peers;
|
||||
u32 num_started_vdevs;
|
||||
u32 num_created_vdevs;
|
||||
+ u32 num_mesh_vdevs;
|
||||
unsigned long long allocated_vdev_map;
|
||||
|
||||
struct idr txmgmt_idr;
|
||||
@@ -759,6 +760,10 @@ struct ath11k {
|
||||
u8 cfr_enabled;
|
||||
bool ani_enabled;
|
||||
enum wmi_phy_mode cfr_phymode;
|
||||
+
|
||||
+ struct cfg80211_chan_def awgn_chandef;
|
||||
+ u32 chan_bw_interference_bitmap;
|
||||
+ bool awgn_intf_handling_in_prog;
|
||||
};
|
||||
|
||||
struct ath11k_band_cap {
|
||||
--- a/drivers/net/wireless/ath/ath11k/debugfs.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/debugfs.c
|
||||
@@ -2273,6 +2273,7 @@ static ssize_t ath11k_write_simulate_awg
|
||||
{
|
||||
struct ath11k *ar = file->private_data;
|
||||
int ret;
|
||||
+ u32 chan_bw_interference_bitmap;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
if (ar->state != ATH11K_STATE_ON) {
|
||||
@@ -2280,7 +2281,10 @@ static ssize_t ath11k_write_simulate_awg
|
||||
goto exit;
|
||||
}
|
||||
|
||||
- ret = ath11k_wmi_simulate_awgn(ar);
|
||||
+ if (kstrtou32_from_user(user_buf, count, 0, &chan_bw_interference_bitmap))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ ret = ath11k_wmi_simulate_awgn(ar, chan_bw_interference_bitmap);
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/mac.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/mac.c
|
||||
@@ -886,7 +886,7 @@ void ath11k_mac_peer_cleanup_all(struct
|
||||
ar->num_stations = 0;
|
||||
}
|
||||
|
||||
-static void
|
||||
+void
|
||||
ath11k_mac_get_any_chandef_iter(struct ieee80211_hw *hw,
|
||||
struct ieee80211_chanctx_conf *conf,
|
||||
void *data)
|
||||
@@ -6453,6 +6453,11 @@ static int ath11k_mac_op_start(struct ie
|
||||
ar->num_peers = 0;
|
||||
ar->allocated_vdev_map = 0;
|
||||
|
||||
+ spin_lock_bh(&ar->data_lock);
|
||||
+ ar->awgn_intf_handling_in_prog = false;
|
||||
+ ar->num_mesh_vdevs = 0;
|
||||
+ spin_unlock_bh(&ar->data_lock);
|
||||
+
|
||||
/* Configure monitor status ring with default rx_filter to get rx status
|
||||
* such as rssi, rx_duration.
|
||||
*/
|
||||
@@ -6529,6 +6534,10 @@ static void ath11k_mac_op_stop(struct ie
|
||||
synchronize_rcu();
|
||||
|
||||
atomic_set(&ar->num_pending_mgmt_tx, 0);
|
||||
+
|
||||
+ spin_lock_bh(&ar->data_lock);
|
||||
+ ar->awgn_intf_handling_in_prog = false;
|
||||
+ spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -6662,6 +6671,10 @@ static int ath11k_mac_vdev_delete(struct
|
||||
ar->ab->free_vdev_map |= 1LL << (arvif->vdev_id);
|
||||
ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id);
|
||||
ar->num_created_vdevs--;
|
||||
+ spin_lock_bh(&ar->data_lock);
|
||||
+ if (vif->type == NL80211_IFTYPE_MESH_POINT)
|
||||
+ ar->num_mesh_vdevs--;
|
||||
+ spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %pM deleted, vdev_id %d\n",
|
||||
vif->addr, arvif->vdev_id);
|
||||
@@ -6813,6 +6826,8 @@ static int ath11k_mac_op_add_interface(s
|
||||
ab->free_vdev_map &= ~(1LL << arvif->vdev_id);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
+ if (vif->type == NL80211_IFTYPE_MESH_POINT)
|
||||
+ ar->num_mesh_vdevs++;
|
||||
list_add(&arvif->list, &ar->arvifs);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
@@ -7475,6 +7490,75 @@ ath11k_mac_change_chanctx_fill_iter(void
|
||||
arg->next_vif++;
|
||||
}
|
||||
|
||||
+static void ath11k_mac_num_chanctxs_iter(struct ieee80211_hw *hw,
|
||||
+ struct ieee80211_chanctx_conf *conf,
|
||||
+ void *data)
|
||||
+{
|
||||
+ int *num = data;
|
||||
+
|
||||
+ (*num)++;
|
||||
+}
|
||||
+
|
||||
+static int ath11k_mac_num_chanctxs(struct ath11k *ar)
|
||||
+{
|
||||
+ int num = 0;
|
||||
+
|
||||
+ ieee80211_iter_chan_contexts_atomic(ar->hw,
|
||||
+ ath11k_mac_num_chanctxs_iter,
|
||||
+ &num);
|
||||
+
|
||||
+ return num;
|
||||
+}
|
||||
+
|
||||
+static void ath11k_mac_update_rx_channel(struct ath11k *ar,
|
||||
+ struct ieee80211_chanctx_conf *ctx,
|
||||
+ struct ieee80211_vif_chanctx_switch *vifs,
|
||||
+ int n_vifs)
|
||||
+{
|
||||
+ struct cfg80211_chan_def *def = NULL;
|
||||
+
|
||||
+ /* Both locks are required because ar->rx_channel is modified. This
|
||||
+ * allows readers to hold either lock.
|
||||
+ */
|
||||
+ lockdep_assert_held(&ar->conf_mutex);
|
||||
+ lockdep_assert_held(&ar->data_lock);
|
||||
+
|
||||
+ WARN_ON(ctx && vifs);
|
||||
+ WARN_ON(vifs && !n_vifs);
|
||||
+
|
||||
+ /* FIXME: Sort of an optimization and a workaround. Peers and vifs are
|
||||
+ * on a linked list now. Doing a lookup peer -> vif -> chanctx for each
|
||||
+ * ppdu on Rx may reduce performance on low-end systems. It should be
|
||||
+ * possible to make tables/hashmaps to speed the lookup up (be vary of
|
||||
+ * cpu data cache lines though regarding sizes) but to keep the initial
|
||||
+ * implementation simple and less intrusive fallback to the slow lookup
|
||||
+ * only for multi-channel cases. Single-channel cases will remain to
|
||||
+ * use the old channel derival and thus performance should not be
|
||||
+ * affected much.
|
||||
+ */
|
||||
+ rcu_read_lock();
|
||||
+ if (!ctx && ath11k_mac_num_chanctxs(ar) == 1) {
|
||||
+ ieee80211_iter_chan_contexts_atomic(ar->hw,
|
||||
+ ath11k_mac_get_any_chandef_iter,
|
||||
+ &def);
|
||||
+ if (vifs)
|
||||
+ def = &vifs[0].new_ctx->def;
|
||||
+
|
||||
+ ar->rx_channel = def->chan;
|
||||
+ } else if ((ctx && ath11k_mac_num_chanctxs(ar) == 0) ||
|
||||
+ (ctx && (ar->state == ATH11K_STATE_RESTARTED))) {
|
||||
+ /* During driver restart due to firmware assert, since mac80211
|
||||
+ * already has valid channel context for given radio, channel
|
||||
+ * context iteration return num_chanctx > 0. So fix rx_channel
|
||||
+ * when restart is in progress.
|
||||
+ */
|
||||
+ ar->rx_channel = ctx->def.chan;
|
||||
+ } else {
|
||||
+ ar->rx_channel = NULL;
|
||||
+ }
|
||||
+ rcu_read_unlock();
|
||||
+}
|
||||
+
|
||||
static void
|
||||
ath11k_mac_update_vif_chan(struct ath11k *ar,
|
||||
struct ieee80211_vif_chanctx_switch *vifs,
|
||||
@@ -7482,6 +7566,7 @@ ath11k_mac_update_vif_chan(struct ath11k
|
||||
{
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct ath11k_vif *arvif;
|
||||
+ struct cfg80211_chan_def *chandef = NULL;
|
||||
int ret;
|
||||
int i;
|
||||
bool monitor_vif = false;
|
||||
@@ -7520,11 +7605,13 @@ ath11k_mac_update_vif_chan(struct ath11k
|
||||
}
|
||||
}
|
||||
|
||||
+ chandef = &vifs[0].new_ctx->def;
|
||||
+
|
||||
/* All relevant vdevs are downed and associated channel resources
|
||||
* should be available for the channel switch now.
|
||||
*/
|
||||
|
||||
- /* TODO: Update ar->rx_channel */
|
||||
+ ath11k_mac_update_rx_channel(ar, NULL, vifs, n_vifs);
|
||||
|
||||
for (i = 0; i < n_vifs; i++) {
|
||||
struct vdev_up_params params = {0};
|
||||
@@ -7572,6 +7659,38 @@ ath11k_mac_update_vif_chan(struct ath11k
|
||||
if (!ath11k_mac_monitor_stop(ar))
|
||||
ath11k_mac_monitor_start(ar);
|
||||
}
|
||||
+
|
||||
+ spin_lock_bh(&ar->data_lock);
|
||||
+ if (ar->awgn_intf_handling_in_prog && chandef) {
|
||||
+ if (!ar->chan_bw_interference_bitmap ||
|
||||
+ (ar->chan_bw_interference_bitmap & WMI_DCS_SEG_PRI20)) {
|
||||
+ if (ar->awgn_chandef.chan->center_freq !=
|
||||
+ chandef->chan->center_freq) {
|
||||
+ ar->awgn_intf_handling_in_prog = false;
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_MAC,
|
||||
+ "AWGN : channel switch completed\n");
|
||||
+ } else {
|
||||
+ ath11k_warn(ab, "AWGN : channel switch is not done, freq : %d\n",
|
||||
+ ar->awgn_chandef.chan->center_freq);
|
||||
+ }
|
||||
+ } else {
|
||||
+ if ((ar->awgn_chandef.chan->center_freq ==
|
||||
+ chandef->chan->center_freq) &&
|
||||
+ (ar->awgn_chandef.width != chandef->width)) {
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_MAC,
|
||||
+ "AWGN : BW reduction is complete\n");
|
||||
+ ar->awgn_intf_handling_in_prog = false;
|
||||
+ } else {
|
||||
+ ath11k_warn(ab, "AWGN : awgn_freq : %d chan_freq %d"
|
||||
+ " awgn_width %d chan_width %d\n",
|
||||
+ ar->awgn_chandef.chan->center_freq,
|
||||
+ chandef->chan->center_freq,
|
||||
+ ar->awgn_chandef.width,
|
||||
+ chandef->width);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
--- a/drivers/net/wireless/ath/ath11k/mac.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/mac.h
|
||||
@@ -167,4 +167,7 @@ void ath11k_mac_bcn_tx_event(struct ath1
|
||||
void ath11k_mac_handle_beacon(struct ath11k *ar, struct sk_buff *skb);
|
||||
void ath11k_mac_handle_beacon_miss(struct ath11k *ar, u32 vdev_id);
|
||||
bool ath11k_mac_sta_level_info(struct ath11k_vif *arvif, struct ieee80211_sta *sta);
|
||||
+void ath11k_mac_get_any_chandef_iter(struct ieee80211_hw *hw,
|
||||
+ struct ieee80211_chanctx_conf *conf,
|
||||
+ void *data);
|
||||
#endif
|
||||
--- a/drivers/net/wireless/ath/ath11k/wmi.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
|
||||
@@ -8685,8 +8685,8 @@ ath11k_wmi_dcs_awgn_interference_event(s
|
||||
{
|
||||
const struct wmi_dcs_interference_ev *dcs_intf_ev;
|
||||
struct wmi_dcs_awgn_info awgn_info = {};
|
||||
+ struct cfg80211_chan_def *chandef = NULL;
|
||||
struct ath11k *ar;
|
||||
- struct ath11k_vif *arvif;
|
||||
const struct wmi_tlv *tlv;
|
||||
u16 tlv_tag;
|
||||
u8 *ptr;
|
||||
@@ -8745,20 +8745,35 @@ ath11k_wmi_dcs_awgn_interference_event(s
|
||||
goto exit;
|
||||
}
|
||||
|
||||
+ if (ar->awgn_intf_handling_in_prog)
|
||||
+ goto exit;
|
||||
+
|
||||
if (!ath11k_wmi_validate_dcs_awgn_info(ar, &awgn_info)) {
|
||||
ath11k_warn(ab, "Invalid DCS AWGN TLV - Skipping event");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
- ath11k_info(ab, "Interface(pdev %d) will be disabled because of AWGN interference\n",
|
||||
+ ath11k_info(ab, "Interface(pdev %d) : AWGN interference detected\n",
|
||||
dcs_intf_ev->pdev_id);
|
||||
|
||||
- list_for_each_entry(arvif, &ar->arvifs, list) {
|
||||
- if (arvif->is_started && arvif->vdev_type == WMI_VDEV_TYPE_AP) {
|
||||
- ieee80211_awgn_detected(arvif->vif);
|
||||
- }
|
||||
+ ieee80211_iter_chan_contexts_atomic(ar->hw, ath11k_mac_get_any_chandef_iter,
|
||||
+ &chandef);
|
||||
+ if (!chandef) {
|
||||
+ ath11k_warn(ab, "chandef is not available\n");
|
||||
+ goto exit;
|
||||
}
|
||||
+ ar->awgn_chandef = *chandef;
|
||||
+
|
||||
+ ieee80211_awgn_detected(ar->hw, awgn_info.chan_bw_interference_bitmap);
|
||||
+
|
||||
+ spin_lock_bh(&ar->data_lock);
|
||||
+ /* Incase of mesh intf presence, dont set in prog as there will be no
|
||||
+ Channel/BW change happening. */
|
||||
+ ar->awgn_intf_handling_in_prog = (ar->num_mesh_vdevs ? false : true);
|
||||
+ ar->chan_bw_interference_bitmap = awgn_info.chan_bw_interference_bitmap;
|
||||
+ spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "AWGN : Interference handling started\n");
|
||||
exit:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
@@ -10080,7 +10095,7 @@ int ath11k_wmi_simulate_radar(struct ath
|
||||
}
|
||||
|
||||
|
||||
-int ath11k_wmi_simulate_awgn(struct ath11k *ar)
|
||||
+int ath11k_wmi_simulate_awgn(struct ath11k *ar, u32 chan_bw_interference_bitmap)
|
||||
{
|
||||
struct ath11k_vif *arvif;
|
||||
u32 awgn_args[WMI_AWGN_MAX_TEST_ARGS];
|
||||
@@ -10103,14 +10118,16 @@ int ath11k_wmi_simulate_awgn(struct ath1
|
||||
return -EINVAL;
|
||||
|
||||
awgn_args[WMI_AWGN_TEST_AWGN_INT] = WMI_UNIT_TEST_AWGN_INTF_TYPE;
|
||||
- awgn_args[WMI_AWGN_TEST_BITMAP] = WMI_UNIT_TEST_AWGN_PRIMARY_20;
|
||||
+ awgn_args[WMI_AWGN_TEST_BITMAP] = chan_bw_interference_bitmap;
|
||||
|
||||
wmi_ut.vdev_id = arvif->vdev_id;
|
||||
wmi_ut.module_id = WMI_AWGN_UNIT_TEST_MODULE;
|
||||
wmi_ut.num_args = WMI_AWGN_MAX_TEST_ARGS;
|
||||
wmi_ut.diag_token = WMI_AWGN_UNIT_TEST_TOKEN;
|
||||
|
||||
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "Triggering AWGN Simulation\n");
|
||||
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
|
||||
+ "Triggering AWGN Simulation, interference bitmap : 0x%x\n",
|
||||
+ chan_bw_interference_bitmap);
|
||||
|
||||
return ath11k_wmi_send_unit_test_cmd(ar, wmi_ut, awgn_args);
|
||||
}
|
||||
--- a/drivers/net/wireless/ath/ath11k/wmi.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
|
||||
@@ -6744,7 +6744,7 @@ void ath11k_wmi_fw_stats_fill(struct ath
|
||||
struct ath11k_fw_stats *fw_stats, u32 stats_id,
|
||||
char *buf);
|
||||
int ath11k_wmi_simulate_radar(struct ath11k *ar);
|
||||
-int ath11k_wmi_simulate_awgn(struct ath11k *ar);
|
||||
+int ath11k_wmi_simulate_awgn(struct ath11k *ar, u32 chan_bw_interference_bitmap);
|
||||
int ath11k_wmi_send_twt_enable_cmd(struct ath11k *ar, u32 pdev_id);
|
||||
int ath11k_wmi_send_twt_disable_cmd(struct ath11k *ar, u32 pdev_id);
|
||||
int ath11k_wmi_send_twt_add_dialog_cmd(struct ath11k *ar,
|
||||
--- a/drivers/net/wireless/ath/ath11k/core.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/core.c
|
||||
@@ -1264,6 +1264,9 @@ void ath11k_core_halt(struct ath11k *ar)
|
||||
|
||||
ar->num_created_vdevs = 0;
|
||||
ar->allocated_vdev_map = 0;
|
||||
+ spin_lock_bh(&ar->data_lock);
|
||||
+ ar->num_mesh_vdevs = 0;
|
||||
+ spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
ath11k_mac_scan_finish(ar);
|
||||
ath11k_mac_peer_cleanup_all(ar);
|
||||
@@ -0,0 +1,356 @@
|
||||
From 1634cf729a978d025cfe726ef0d1796af6cdea36 Mon Sep 17 00:00:00 2001
|
||||
From: Hari Chandrakanthan <quic_haric@quicinc.com>
|
||||
Date: Wed, 1 Dec 2021 12:21:06 +0530
|
||||
Subject: [PATCH] mac80211 : add support to awgn detection and mitigation in
|
||||
6Ghz
|
||||
|
||||
when awgn interference is detected on operating channel,
|
||||
AP is supposed to stop transmitting in that channel.
|
||||
AP can reduce it's operating bandwidth or
|
||||
completely move to another channel based on the
|
||||
interference segment.
|
||||
|
||||
support to send nl event upon detecting awgn in 6Ghz is added
|
||||
|
||||
When awgn wmi event is detected by the driver, driver notifies mac80211
|
||||
with the channel interference bitmap and mac80211 sends the operating
|
||||
channel info and the channel interference bitmap to userspace through
|
||||
NL80211_CMD_AWGN_DETECT cmd and NL80211_ATTR_AWGN_INTERFERENCE_BITMAP
|
||||
attribute. If the interference is on the primary channel, the userspace
|
||||
tool completely switches to a new channel or it reduces bandwidth on the
|
||||
same operating channel.
|
||||
|
||||
Signed-off-by: Hari Chandrakanthan <quic_haric@quicinc.com>
|
||||
---
|
||||
include/net/cfg80211.h | 13 ++++++++++
|
||||
include/net/mac80211.h | 5 ++--
|
||||
include/uapi/linux/nl80211.h | 10 ++++++++
|
||||
net/mac80211/ieee80211_i.h | 5 ++--
|
||||
net/mac80211/iface.c | 3 ---
|
||||
net/mac80211/main.c | 4 +++
|
||||
net/mac80211/util.c | 61 +++++++++++++++++++++++++-------------------
|
||||
net/wireless/mlme.c | 9 +++++++
|
||||
net/wireless/nl80211.c | 37 +++++++++++++++++++++++++++
|
||||
net/wireless/nl80211.h | 5 ++++
|
||||
10 files changed, 119 insertions(+), 33 deletions(-)
|
||||
|
||||
--- a/include/net/cfg80211.h
|
||||
+++ b/include/net/cfg80211.h
|
||||
@@ -7576,6 +7576,19 @@ void cfg80211_radar_event(struct wiphy *
|
||||
struct cfg80211_chan_def *chandef, gfp_t gfp);
|
||||
|
||||
/**
|
||||
+ * cfg80211_awgn_event - awgn detection event
|
||||
+ * @wiphy: the wiphy
|
||||
+ * @chandef: chandef for the current channel
|
||||
+ * @gfp: context flags
|
||||
+ * @chan_bw_interference_bitmap: channel bandwidth interference bitmap
|
||||
+ *
|
||||
+ * This function is called when Additive white Gaussian noise (AWGN)
|
||||
+ * is detected on the current channel.
|
||||
+ */
|
||||
+void cfg80211_awgn_event(struct wiphy *wiphy, struct cfg80211_chan_def *chandef,
|
||||
+ gfp_t gfp, u32 chan_bw_interference_bitmap);
|
||||
+
|
||||
+/**
|
||||
* cfg80211_sta_opmode_change_notify - STA's ht/vht operation mode change event
|
||||
* @dev: network device
|
||||
* @mac: MAC address of a station which opmode got modified
|
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -6256,9 +6256,10 @@ void ieee80211_chswitch_done(struct ieee
|
||||
/**
|
||||
* ieee80211_awgn_detected - inform that awgn interference is detected
|
||||
*
|
||||
- * @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
+ * @hw: pointer as obtained from ieee80211_alloc_hw()
|
||||
+ * @chan_bw_interference_bitmap : awgn interference bitmap
|
||||
*/
|
||||
-void ieee80211_awgn_detected(struct ieee80211_vif *vif);
|
||||
+void ieee80211_awgn_detected(struct ieee80211_hw *hw, u32 chan_bw_interference_bitmap);
|
||||
|
||||
/**
|
||||
* ieee80211_request_smps - request SM PS transition
|
||||
--- a/include/uapi/linux/nl80211.h
|
||||
+++ b/include/uapi/linux/nl80211.h
|
||||
@@ -1209,6 +1209,11 @@
|
||||
* @NL80211_CMD_COLOR_CHANGE_ANNOUNCEMENT_COMPLETED: Notify userland that the color change
|
||||
* has completed
|
||||
*
|
||||
+ *
|
||||
+ * @NL80211_CMD_AWGN_DETECT: Once AWGN interference is detected on the operating
|
||||
+ * channel, userspace is notified with the interference bitmap using
|
||||
+ * %NL80211_ATTR_AWGN_INTERFERENCE_BITMAP
|
||||
+
|
||||
* @NL80211_CMD_MAX: highest used command number
|
||||
* @__NL80211_CMD_AFTER_LAST: internal use
|
||||
*/
|
||||
@@ -1453,6 +1458,7 @@ enum nl80211_commands {
|
||||
NL80211_CMD_COLOR_CHANGE_ANNOUNCEMENT_ABORTED,
|
||||
NL80211_CMD_COLOR_CHANGE_ANNOUNCEMENT_COMPLETED,
|
||||
|
||||
+ NL80211_CMD_AWGN_DETECT,
|
||||
/* add new commands above here */
|
||||
|
||||
/* used to define NL80211_CMD_MAX below */
|
||||
@@ -2639,6 +2645,8 @@ enum nl80211_commands {
|
||||
* @NL80211_ATTR_BEACON_TX_MODE: used to configure the beacon tx mode as
|
||||
* staggered mode = 1 or burst mode = 2 in %NL80211_CMD_START_AP or
|
||||
* %NL80211_CMD_JOIN_MESH from user-space.
|
||||
+ * @NL80211_ATTR_AWGN_INTERFERENCE_BITMAP: u32 attribute specifying the
|
||||
+ * interference bitmap of operating bandwidth for %NL80211_CMD_AWGN_DETECT
|
||||
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
|
||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||
@@ -3154,6 +3162,8 @@ enum nl80211_attrs {
|
||||
|
||||
NL80211_ATTR_BEACON_TX_MODE,
|
||||
|
||||
+ NL80211_ATTR_AWGN_INTERFERENCE_BITMAP,
|
||||
+
|
||||
/* add attributes here, update the policy in nl80211.c */
|
||||
|
||||
__NL80211_ATTR_AFTER_LAST,
|
||||
--- a/net/mac80211/ieee80211_i.h
|
||||
+++ b/net/mac80211/ieee80211_i.h
|
||||
@@ -952,8 +952,6 @@ 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 */
|
||||
@@ -1461,6 +1459,8 @@ struct ieee80211_local {
|
||||
struct sk_buff_head skb_queue_tdls_chsw;
|
||||
|
||||
struct mac80211_memory_stats memory_stats;
|
||||
+ struct work_struct awgn_detected_work;
|
||||
+ u32 chan_bw_interference_bitmap;
|
||||
};
|
||||
|
||||
static inline struct ieee80211_sub_if_data *
|
||||
@@ -2298,6 +2298,7 @@ void ieee80211_dfs_cac_timer(unsigned lo
|
||||
void ieee80211_dfs_cac_timer_work(struct work_struct *work);
|
||||
void ieee80211_dfs_cac_cancel(struct ieee80211_local *local);
|
||||
void ieee80211_dfs_radar_detected_work(struct work_struct *work);
|
||||
+void ieee80211_awgn_detected_work(struct work_struct *work);
|
||||
int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
|
||||
struct cfg80211_csa_settings *csa_settings);
|
||||
|
||||
--- a/net/mac80211/iface.c
|
||||
+++ b/net/mac80211/iface.c
|
||||
@@ -474,8 +474,6 @@ static void ieee80211_do_stop(struct iee
|
||||
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);
|
||||
|
||||
if (sdata->wdev.cac_started) {
|
||||
@@ -1672,7 +1670,6 @@ static void ieee80211_setup_sdata(struct
|
||||
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);
|
||||
--- a/net/mac80211/main.c
|
||||
+++ b/net/mac80211/main.c
|
||||
@@ -272,6 +272,7 @@ static void ieee80211_restart_work(struc
|
||||
"%s called with hardware scan in progress\n", __func__);
|
||||
|
||||
flush_work(&local->radar_detected_work);
|
||||
+ flush_work(&local->awgn_detected_work);
|
||||
/* we might do interface manipulations, so need both */
|
||||
rtnl_lock();
|
||||
wiphy_lock(local->hw.wiphy);
|
||||
@@ -721,6 +722,8 @@ struct ieee80211_hw *ieee80211_alloc_hw_
|
||||
|
||||
INIT_WORK(&local->radar_detected_work,
|
||||
ieee80211_dfs_radar_detected_work);
|
||||
+ INIT_WORK(&local->awgn_detected_work,
|
||||
+ ieee80211_awgn_detected_work);
|
||||
|
||||
INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter);
|
||||
local->smps_mode = IEEE80211_SMPS_OFF;
|
||||
@@ -1388,6 +1391,7 @@ void ieee80211_unregister_hw(struct ieee
|
||||
cancel_work_sync(&local->tdls_chsw_work);
|
||||
flush_work(&local->sched_scan_stopped_work);
|
||||
flush_work(&local->radar_detected_work);
|
||||
+ flush_work(&local->awgn_detected_work);
|
||||
|
||||
ieee80211_clear_tx_pending(local);
|
||||
rate_control_deinitialize(local);
|
||||
--- a/net/mac80211/util.c
|
||||
+++ b/net/mac80211/util.c
|
||||
@@ -3833,6 +3833,32 @@ void ieee80211_dfs_cac_cancel(struct iee
|
||||
mutex_unlock(&local->mtx);
|
||||
}
|
||||
|
||||
+void ieee80211_awgn_detected_work(struct work_struct *work)
|
||||
+{
|
||||
+ struct ieee80211_local *local =
|
||||
+ container_of(work, struct ieee80211_local, awgn_detected_work);
|
||||
+ struct cfg80211_chan_def chandef = local->hw.conf.chandef;
|
||||
+ struct ieee80211_chanctx *ctx;
|
||||
+ int num_chanctx = 0;
|
||||
+
|
||||
+ mutex_lock(&local->chanctx_mtx);
|
||||
+ list_for_each_entry(ctx, &local->chanctx_list, list) {
|
||||
+ if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER)
|
||||
+ continue;
|
||||
+
|
||||
+ num_chanctx++;
|
||||
+ chandef = ctx->conf.def;
|
||||
+ }
|
||||
+ mutex_unlock(&local->chanctx_mtx);
|
||||
+
|
||||
+ if (num_chanctx > 1)
|
||||
+ /* XXX: multi-channel is not supported yet */
|
||||
+ WARN_ON_ONCE(1);
|
||||
+ else
|
||||
+ cfg80211_awgn_event(local->hw.wiphy, &chandef, GFP_KERNEL,
|
||||
+ local->chan_bw_interference_bitmap);
|
||||
+}
|
||||
+
|
||||
void ieee80211_dfs_radar_detected_work(struct work_struct *work)
|
||||
{
|
||||
struct ieee80211_local *local =
|
||||
@@ -3872,6 +3898,15 @@ void ieee80211_radar_detected(struct iee
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_radar_detected);
|
||||
|
||||
+void ieee80211_awgn_detected(struct ieee80211_hw *hw, u32 chan_bw_interference_bitmap)
|
||||
+{
|
||||
+ struct ieee80211_local *local = hw_to_local(hw);
|
||||
+
|
||||
+ local->chan_bw_interference_bitmap = chan_bw_interference_bitmap;
|
||||
+ schedule_work(&local->awgn_detected_work);
|
||||
+}
|
||||
+EXPORT_SYMBOL(ieee80211_awgn_detected);
|
||||
+
|
||||
u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c)
|
||||
{
|
||||
u32 ret;
|
||||
@@ -3937,32 +3972,6 @@ u32 ieee80211_chandef_downgrade(struct 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.
|
||||
--- a/net/wireless/mlme.c
|
||||
+++ b/net/wireless/mlme.c
|
||||
@@ -926,6 +926,15 @@ void cfg80211_radar_event(struct wiphy *
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_radar_event);
|
||||
|
||||
+void cfg80211_awgn_event(struct wiphy *wiphy, struct cfg80211_chan_def *chandef,
|
||||
+ gfp_t gfp, u32 chan_bw_interference_bitmap)
|
||||
+{
|
||||
+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
||||
+
|
||||
+ nl80211_awgn_notify(rdev, chandef, NULL, gfp, chan_bw_interference_bitmap);
|
||||
+}
|
||||
+EXPORT_SYMBOL(cfg80211_awgn_event);
|
||||
+
|
||||
void cfg80211_cac_event(struct net_device *netdev,
|
||||
const struct cfg80211_chan_def *chandef,
|
||||
enum nl80211_radar_event event, gfp_t gfp)
|
||||
--- a/net/wireless/nl80211.c
|
||||
+++ b/net/wireless/nl80211.c
|
||||
@@ -798,6 +798,7 @@ static const struct nla_policy nl80211_p
|
||||
[NL80211_ATTR_COLOR_CHANGE_ANNOUNCEMENT_IES] = NLA_POLICY_NESTED(nl80211_policy),
|
||||
[NL80211_ATTR_RNR_OFFSETS] = NLA_POLICY_NESTED(nl80211_rnr_ies_policy),
|
||||
[NL80211_ATTR_BEACON_TX_MODE] = NLA_POLICY_RANGE(NLA_U32, 1, 2),
|
||||
+ [NL80211_ATTR_AWGN_INTERFERENCE_BITMAP] = { .type = NLA_U32 },
|
||||
|
||||
};
|
||||
|
||||
@@ -17683,6 +17684,42 @@ void cfg80211_ch_switch_notify(struct ne
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_ch_switch_notify);
|
||||
|
||||
+void nl80211_awgn_notify(struct cfg80211_registered_device *rdev,
|
||||
+ struct cfg80211_chan_def *chandef,
|
||||
+ struct net_device *netdev,
|
||||
+ gfp_t gfp, u32 chan_bw_interference_bitmap)
|
||||
+{
|
||||
+ struct sk_buff *msg;
|
||||
+ void *hdr;
|
||||
+ int ret;
|
||||
+
|
||||
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
|
||||
+ if (!msg)
|
||||
+ return;
|
||||
+
|
||||
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_AWGN_DETECT);
|
||||
+ if (!hdr) {
|
||||
+ nlmsg_free(msg);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (nl80211_send_chandef(msg, chandef))
|
||||
+ goto nla_put_failure;
|
||||
+
|
||||
+ if (nla_put_u32(msg, NL80211_ATTR_AWGN_INTERFERENCE_BITMAP,
|
||||
+ chan_bw_interference_bitmap))
|
||||
+ goto nla_put_failure;
|
||||
+
|
||||
+ genlmsg_end(msg, hdr);
|
||||
+
|
||||
+ ret = genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
|
||||
+ NL80211_MCGRP_MLME, gfp);
|
||||
+ return;
|
||||
+
|
||||
+nla_put_failure:
|
||||
+ nlmsg_free(msg);
|
||||
+}
|
||||
+
|
||||
void cfg80211_ch_switch_started_notify(struct net_device *dev,
|
||||
struct cfg80211_chan_def *chandef,
|
||||
u8 count, bool quiet)
|
||||
--- a/net/wireless/nl80211.h
|
||||
+++ b/net/wireless/nl80211.h
|
||||
@@ -120,6 +120,11 @@ nl80211_radar_notify(struct cfg80211_reg
|
||||
enum nl80211_radar_event event,
|
||||
struct net_device *netdev, gfp_t gfp);
|
||||
|
||||
+void nl80211_awgn_notify(struct cfg80211_registered_device *rdev,
|
||||
+ struct cfg80211_chan_def *chandef,
|
||||
+ struct net_device *netdev,
|
||||
+ gfp_t gfp, u32 chan_bw_interference_bitmap);
|
||||
+
|
||||
void nl80211_send_ap_stopped(struct wireless_dev *wdev);
|
||||
|
||||
void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev);
|
||||
Reference in New Issue
Block a user