361 lines
12 KiB
Diff
361 lines
12 KiB
Diff
From: Aditya Kumar Singh <quic_adisi@quicinc.com>
|
|
Date: Fri, 6 Sep 2024 12:14:26 +0530
|
|
Subject: [PATCH] wifi: mac80211: handle ieee80211_radar_detected() for MLO
|
|
|
|
Currently DFS works under assumption there could be only one channel
|
|
context in the hardware. Hence, drivers just calls the function
|
|
ieee80211_radar_detected() passing the hardware structure. However, with
|
|
MLO, this obviously will not work since number of channel contexts will be
|
|
more than one and hence drivers would need to pass the channel information
|
|
as well on which the radar is detected.
|
|
|
|
Also, when radar is detected in one of the links, other link's CAC should
|
|
not be cancelled.
|
|
|
|
Hence, in order to support DFS with MLO, do the following changes -
|
|
* Add channel context conf pointer as an argument to the function
|
|
ieee80211_radar_detected(). During MLO, drivers would have to pass on
|
|
which channel context conf radar is detected. Otherwise, drivers could
|
|
just pass NULL.
|
|
* ieee80211_radar_detected() will iterate over all channel contexts
|
|
present and
|
|
* if channel context conf is passed, only mark that as radar
|
|
detected
|
|
* if NULL is passed, then mark all channel contexts as radar
|
|
detected
|
|
* Then as usual, schedule the radar detected work.
|
|
* In the worker, go over all the contexts again and for all such context
|
|
which is marked with radar detected, cancel the ongoing CAC by calling
|
|
ieee80211_dfs_cac_cancel() and then notify cfg80211 via
|
|
cfg80211_radar_event().
|
|
* To cancel the CAC, pass the channel context as well where radar is
|
|
detected to ieee80211_dfs_cac_cancel(). This ensures that CAC is
|
|
canceled only on the links using the provided context, leaving other
|
|
links unaffected.
|
|
|
|
This would also help in scenarios where there is split phy 5 GHz radio,
|
|
which is capable of DFS channels in both lower and upper band. In this
|
|
case, simultaneous radars can be detected.
|
|
|
|
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
|
|
Link: https://patch.msgid.link/20240906064426.2101315-9-quic_adisi@quicinc.com
|
|
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
|
---
|
|
|
|
--- a/drivers/net/wireless/ath/ath10k/debug.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/debug.c
|
|
@@ -3,7 +3,7 @@
|
|
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
|
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
|
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
|
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
+ * Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
@@ -1774,7 +1774,7 @@ static ssize_t ath10k_write_simulate_rad
|
|
if (!arvif->is_started)
|
|
return -EINVAL;
|
|
|
|
- ieee80211_radar_detected(ar->hw);
|
|
+ ieee80211_radar_detected(ar->hw, NULL);
|
|
|
|
return count;
|
|
}
|
|
--- a/drivers/net/wireless/ath/ath10k/mac.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/mac.c
|
|
@@ -1437,7 +1437,7 @@ static void ath10k_recalc_radar_detectio
|
|
* by indicating that radar was detected.
|
|
*/
|
|
ath10k_warn(ar, "failed to start CAC: %d\n", ret);
|
|
- ieee80211_radar_detected(ar->hw);
|
|
+ ieee80211_radar_detected(ar->hw, NULL);
|
|
}
|
|
}
|
|
|
|
--- a/drivers/net/wireless/ath/ath10k/wmi.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
|
|
@@ -3990,7 +3990,7 @@ static void ath10k_radar_detected(struct
|
|
if (ar->dfs_block_radar_events)
|
|
ath10k_info(ar, "DFS Radar detected, but ignored as requested\n");
|
|
else
|
|
- ieee80211_radar_detected(ar->hw);
|
|
+ ieee80211_radar_detected(ar->hw, NULL);
|
|
}
|
|
|
|
static void ath10k_radar_confirmation_work(struct work_struct *work)
|
|
--- a/drivers/net/wireless/ath/ath11k/wmi.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
|
|
@@ -8358,7 +8358,7 @@ ath11k_wmi_pdev_dfs_radar_detected_event
|
|
if (ar->dfs_block_radar_events)
|
|
ath11k_info(ab, "DFS Radar detected, but ignored as requested\n");
|
|
else
|
|
- ieee80211_radar_detected(ar->hw);
|
|
+ ieee80211_radar_detected(ar->hw, NULL);
|
|
|
|
exit:
|
|
rcu_read_unlock();
|
|
--- a/drivers/net/wireless/ath/ath12k/wmi.c
|
|
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
|
|
@@ -6789,7 +6789,7 @@ ath12k_wmi_pdev_dfs_radar_detected_event
|
|
if (ar->dfs_block_radar_events)
|
|
ath12k_info(ab, "DFS Radar detected, but ignored as requested\n");
|
|
else
|
|
- ieee80211_radar_detected(ath12k_ar_to_hw(ar));
|
|
+ ieee80211_radar_detected(ath12k_ar_to_hw(ar), NULL);
|
|
|
|
exit:
|
|
rcu_read_unlock();
|
|
--- a/drivers/net/wireless/ath/ath9k/dfs.c
|
|
+++ b/drivers/net/wireless/ath/ath9k/dfs.c
|
|
@@ -280,7 +280,7 @@ ath9k_dfs_process_radar_pulse(struct ath
|
|
if (!pd->add_pulse(pd, pe, NULL))
|
|
return;
|
|
DFS_STAT_INC(sc, radar_detected);
|
|
- ieee80211_radar_detected(sc->hw);
|
|
+ ieee80211_radar_detected(sc->hw, NULL);
|
|
}
|
|
|
|
/*
|
|
--- a/drivers/net/wireless/ath/ath9k/dfs_debug.c
|
|
+++ b/drivers/net/wireless/ath/ath9k/dfs_debug.c
|
|
@@ -116,7 +116,7 @@ static ssize_t write_file_simulate_radar
|
|
{
|
|
struct ath_softc *sc = file->private_data;
|
|
|
|
- ieee80211_radar_detected(sc->hw);
|
|
+ ieee80211_radar_detected(sc->hw, NULL);
|
|
|
|
return count;
|
|
}
|
|
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
|
|
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
|
|
@@ -394,7 +394,7 @@ mt7615_mcu_rx_radar_detected(struct mt76
|
|
if (mt76_phy_dfs_state(mphy) < MT_DFS_STATE_CAC)
|
|
return;
|
|
|
|
- ieee80211_radar_detected(mphy->hw);
|
|
+ ieee80211_radar_detected(mphy->hw, NULL);
|
|
dev->hw_pattern++;
|
|
}
|
|
|
|
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c
|
|
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c
|
|
@@ -630,7 +630,7 @@ static void mt76x02_dfs_tasklet(struct t
|
|
radar_detected = mt76x02_dfs_check_detection(dev);
|
|
if (radar_detected) {
|
|
/* sw detector rx radar pattern */
|
|
- ieee80211_radar_detected(dev->mt76.hw);
|
|
+ ieee80211_radar_detected(dev->mt76.hw, NULL);
|
|
mt76x02_dfs_detector_reset(dev);
|
|
|
|
return;
|
|
@@ -658,7 +658,7 @@ static void mt76x02_dfs_tasklet(struct t
|
|
|
|
/* hw detector rx radar pattern */
|
|
dfs_pd->stats[i].hw_pattern++;
|
|
- ieee80211_radar_detected(dev->mt76.hw);
|
|
+ ieee80211_radar_detected(dev->mt76.hw, NULL);
|
|
mt76x02_dfs_detector_reset(dev);
|
|
|
|
return;
|
|
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
|
|
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
|
|
@@ -293,7 +293,7 @@ mt7915_mcu_rx_radar_detected(struct mt79
|
|
&dev->rdd2_chandef,
|
|
GFP_ATOMIC);
|
|
else
|
|
- ieee80211_radar_detected(mphy->hw);
|
|
+ ieee80211_radar_detected(mphy->hw, NULL);
|
|
dev->hw_pattern++;
|
|
}
|
|
|
|
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
|
|
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
|
|
@@ -371,7 +371,7 @@ mt7996_mcu_rx_radar_detected(struct mt79
|
|
&dev->rdd2_chandef,
|
|
GFP_ATOMIC);
|
|
else
|
|
- ieee80211_radar_detected(mphy->hw);
|
|
+ ieee80211_radar_detected(mphy->hw, NULL);
|
|
dev->hw_pattern++;
|
|
}
|
|
|
|
--- a/drivers/net/wireless/ti/wl18xx/event.c
|
|
+++ b/drivers/net/wireless/ti/wl18xx/event.c
|
|
@@ -142,7 +142,7 @@ int wl18xx_process_mailbox_events(struct
|
|
wl18xx_radar_type_decode(mbox->radar_type));
|
|
|
|
if (!wl->radar_debug_mode)
|
|
- ieee80211_radar_detected(wl->hw);
|
|
+ ieee80211_radar_detected(wl->hw, NULL);
|
|
}
|
|
|
|
if (vector & PERIODIC_SCAN_REPORT_EVENT_ID) {
|
|
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
|
|
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
|
|
@@ -1146,7 +1146,7 @@ static int hwsim_write_simulate_radar(vo
|
|
{
|
|
struct mac80211_hwsim_data *data = dat;
|
|
|
|
- ieee80211_radar_detected(data->hw);
|
|
+ ieee80211_radar_detected(data->hw, NULL);
|
|
|
|
return 0;
|
|
}
|
|
--- a/include/net/mac80211.h
|
|
+++ b/include/net/mac80211.h
|
|
@@ -6717,8 +6717,11 @@ void ieee80211_cqm_beacon_loss_notify(st
|
|
* ieee80211_radar_detected - inform that a radar was detected
|
|
*
|
|
* @hw: pointer as obtained from ieee80211_alloc_hw()
|
|
+ * @chanctx_conf: Channel context on which radar is detected. Mandatory to
|
|
+ * pass a valid pointer during MLO. For non-MLO %NULL can be passed
|
|
*/
|
|
-void ieee80211_radar_detected(struct ieee80211_hw *hw);
|
|
+void ieee80211_radar_detected(struct ieee80211_hw *hw,
|
|
+ struct ieee80211_chanctx_conf *chanctx_conf);
|
|
|
|
/**
|
|
* ieee80211_chswitch_done - Complete channel switch process
|
|
--- a/net/mac80211/chan.c
|
|
+++ b/net/mac80211/chan.c
|
|
@@ -681,6 +681,7 @@ ieee80211_alloc_chanctx(struct ieee80211
|
|
ctx->mode = mode;
|
|
ctx->conf.radar_enabled = false;
|
|
ctx->conf.radio_idx = radio_idx;
|
|
+ ctx->radar_detected = false;
|
|
_ieee80211_recalc_chanctx_min_def(local, ctx, NULL, false);
|
|
|
|
return ctx;
|
|
--- a/net/mac80211/ieee80211_i.h
|
|
+++ b/net/mac80211/ieee80211_i.h
|
|
@@ -895,6 +895,8 @@ struct ieee80211_chanctx {
|
|
struct ieee80211_chan_req req;
|
|
|
|
struct ieee80211_chanctx_conf conf;
|
|
+
|
|
+ bool radar_detected;
|
|
};
|
|
|
|
struct mac80211_qos_map {
|
|
@@ -2632,7 +2634,8 @@ void ieee80211_recalc_chanctx_min_def(st
|
|
bool ieee80211_is_radar_required(struct ieee80211_local *local);
|
|
|
|
void ieee80211_dfs_cac_timer_work(struct wiphy *wiphy, struct wiphy_work *work);
|
|
-void ieee80211_dfs_cac_cancel(struct ieee80211_local *local);
|
|
+void ieee80211_dfs_cac_cancel(struct ieee80211_local *local,
|
|
+ struct ieee80211_chanctx *chanctx);
|
|
void ieee80211_dfs_radar_detected_work(struct wiphy *wiphy,
|
|
struct wiphy_work *work);
|
|
int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
|
|
--- a/net/mac80211/pm.c
|
|
+++ b/net/mac80211/pm.c
|
|
@@ -32,7 +32,7 @@ int __ieee80211_suspend(struct ieee80211
|
|
|
|
ieee80211_scan_cancel(local);
|
|
|
|
- ieee80211_dfs_cac_cancel(local);
|
|
+ ieee80211_dfs_cac_cancel(local, NULL);
|
|
|
|
ieee80211_roc_purge(local, NULL);
|
|
|
|
--- a/net/mac80211/util.c
|
|
+++ b/net/mac80211/util.c
|
|
@@ -3451,11 +3451,16 @@ u64 ieee80211_calculate_rx_timestamp(str
|
|
return ts;
|
|
}
|
|
|
|
-void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
|
|
+/* Cancel CAC for the interfaces under the specified @local. If @ctx is
|
|
+ * also provided, only the interfaces using that ctx will be canceled.
|
|
+ */
|
|
+void ieee80211_dfs_cac_cancel(struct ieee80211_local *local,
|
|
+ struct ieee80211_chanctx *ctx)
|
|
{
|
|
struct ieee80211_sub_if_data *sdata;
|
|
struct cfg80211_chan_def chandef;
|
|
struct ieee80211_link_data *link;
|
|
+ struct ieee80211_chanctx_conf *chanctx_conf;
|
|
unsigned int link_id;
|
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
|
@@ -3468,6 +3473,11 @@ void ieee80211_dfs_cac_cancel(struct iee
|
|
if (!link)
|
|
continue;
|
|
|
|
+ chanctx_conf = sdata_dereference(link->conf->chanctx_conf,
|
|
+ sdata);
|
|
+ if (ctx && &ctx->conf != chanctx_conf)
|
|
+ continue;
|
|
+
|
|
wiphy_delayed_work_cancel(local->hw.wiphy,
|
|
&link->dfs_cac_timer_work);
|
|
|
|
@@ -3488,9 +3498,8 @@ void ieee80211_dfs_radar_detected_work(s
|
|
{
|
|
struct ieee80211_local *local =
|
|
container_of(work, struct ieee80211_local, radar_detected_work);
|
|
- struct cfg80211_chan_def chandef = local->hw.conf.chandef;
|
|
+ struct cfg80211_chan_def chandef;
|
|
struct ieee80211_chanctx *ctx;
|
|
- int num_chanctx = 0;
|
|
|
|
lockdep_assert_wiphy(local->hw.wiphy);
|
|
|
|
@@ -3498,25 +3507,46 @@ void ieee80211_dfs_radar_detected_work(s
|
|
if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER)
|
|
continue;
|
|
|
|
- num_chanctx++;
|
|
+ if (!ctx->radar_detected)
|
|
+ continue;
|
|
+
|
|
+ ctx->radar_detected = false;
|
|
+
|
|
chandef = ctx->conf.def;
|
|
+
|
|
+ ieee80211_dfs_cac_cancel(local, ctx);
|
|
+ cfg80211_radar_event(local->hw.wiphy, &chandef, GFP_KERNEL);
|
|
}
|
|
+}
|
|
|
|
- ieee80211_dfs_cac_cancel(local);
|
|
+static void
|
|
+ieee80211_radar_mark_chan_ctx_iterator(struct ieee80211_hw *hw,
|
|
+ struct ieee80211_chanctx_conf *chanctx_conf,
|
|
+ void *data)
|
|
+{
|
|
+ struct ieee80211_chanctx *ctx =
|
|
+ container_of(chanctx_conf, struct ieee80211_chanctx,
|
|
+ conf);
|
|
|
|
- if (num_chanctx > 1)
|
|
- /* XXX: multi-channel is not supported yet */
|
|
- WARN_ON(1);
|
|
- else
|
|
- cfg80211_radar_event(local->hw.wiphy, &chandef, GFP_KERNEL);
|
|
+ if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER)
|
|
+ return;
|
|
+
|
|
+ if (data && data != chanctx_conf)
|
|
+ return;
|
|
+
|
|
+ ctx->radar_detected = true;
|
|
}
|
|
|
|
-void ieee80211_radar_detected(struct ieee80211_hw *hw)
|
|
+void ieee80211_radar_detected(struct ieee80211_hw *hw,
|
|
+ struct ieee80211_chanctx_conf *chanctx_conf)
|
|
{
|
|
struct ieee80211_local *local = hw_to_local(hw);
|
|
|
|
trace_api_radar_detected(local);
|
|
|
|
+ ieee80211_iter_chan_contexts_atomic(hw, ieee80211_radar_mark_chan_ctx_iterator,
|
|
+ chanctx_conf);
|
|
+
|
|
wiphy_work_queue(hw->wiphy, &local->radar_detected_work);
|
|
}
|
|
EXPORT_SYMBOL(ieee80211_radar_detected);
|