summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
authorStanleyYP Wang <StanleyYP.Wang@mediatek.com>2025-12-15 14:37:23 +0800
committerFelix Fietkau <nbd@nbd.name>2026-03-23 09:14:42 +0000
commit45a09251d610f3b8a1fb02039146e42f1f4efe90 (patch)
treee087d9c353d550eb4e270a1245c80e2c8d18819e /drivers/net
parent20743b0b64d91927d1a9346341f3ecdc527c8776 (diff)
wifi: mt76: mt7996: fix the behavior of radar detection
RDD_DET_MODE is a firmware command intended for testing and does not pause TX after radar detection, so remove it from the normal flow; instead, use the MAC_ENABLE_CTRL firmware command to resume TX after the radar-triggered channel switch completes. Fixes: 1529e335f93d ("wifi: mt76: mt7996: rework radar HWRDD idx") Co-developed-by: Shayne Chen <shayne.chen@mediatek.com> Signed-off-by: Shayne Chen <shayne.chen@mediatek.com> Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com> Link: https://patch.msgid.link/20251215063728.3013365-2-shayne.chen@mediatek.com Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/mac.c8
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/main.c20
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/mcu.c49
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/mcu.h1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h2
5 files changed, 68 insertions, 12 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 84cbf36b493c..2765ac7285b4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -2974,7 +2974,7 @@ static void mt7996_dfs_stop_radar_detector(struct mt7996_phy *phy)
static int mt7996_dfs_start_rdd(struct mt7996_dev *dev, int rdd_idx)
{
- int err, region;
+ int region;
switch (dev->mt76.region) {
case NL80211_DFS_ETSI:
@@ -2989,11 +2989,7 @@ static int mt7996_dfs_start_rdd(struct mt7996_dev *dev, int rdd_idx)
break;
}
- err = mt7996_mcu_rdd_cmd(dev, RDD_START, rdd_idx, region);
- if (err < 0)
- return err;
-
- return mt7996_mcu_rdd_cmd(dev, RDD_DET_MODE, rdd_idx, 1);
+ return mt7996_mcu_rdd_cmd(dev, RDD_START, rdd_idx, region);
}
static int mt7996_dfs_start_radar_detector(struct mt7996_phy *phy)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 4b73fefcee8e..fac50dbceae7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -79,6 +79,7 @@ static void mt7996_stop_phy(struct mt7996_phy *phy)
mutex_lock(&dev->mt76.mutex);
+ mt7996_mcu_rdd_resume_tx(phy);
mt7996_mcu_set_radio_en(phy, false);
clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);
@@ -955,6 +956,24 @@ mt7996_channel_switch_beacon(struct ieee80211_hw *hw,
}
static int
+mt7996_post_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf)
+{
+ struct cfg80211_chan_def *chandef = &link_conf->chanreq.oper;
+ struct mt7996_dev *dev = mt7996_hw_dev(hw);
+ struct mt7996_phy *phy = mt7996_band_phy(dev, chandef->chan->band);
+ int ret;
+
+ mutex_lock(&dev->mt76.mutex);
+
+ ret = mt7996_mcu_rdd_resume_tx(phy);
+
+ mutex_unlock(&dev->mt76.mutex);
+
+ return ret;
+}
+
+static int
mt7996_mac_sta_init_link(struct mt7996_dev *dev,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_link_sta *link_sta,
@@ -2327,6 +2346,7 @@ const struct ieee80211_ops mt7996_ops = {
.release_buffered_frames = mt76_release_buffered_frames,
.get_txpower = mt7996_get_txpower,
.channel_switch_beacon = mt7996_channel_switch_beacon,
+ .post_channel_switch = mt7996_post_channel_switch,
.get_stats = mt7996_get_stats,
.get_et_sset_count = mt7996_get_et_sset_count,
.get_et_stats = mt7996_get_et_stats,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index c059ddbf1e42..6294704f7881 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -520,24 +520,32 @@ mt7996_mcu_rx_radar_detected(struct mt7996_dev *dev, struct sk_buff *skb)
break;
case MT_RDD_IDX_BACKGROUND:
if (!dev->rdd2_phy)
- return;
+ goto err;
mphy = dev->rdd2_phy->mt76;
break;
default:
- dev_err(dev->mt76.dev, "Unknown RDD idx %d\n", r->rdd_idx);
- return;
+ goto err;
}
if (!mphy)
- return;
+ goto err;
- if (r->rdd_idx == MT_RDD_IDX_BACKGROUND)
+ if (r->rdd_idx == MT_RDD_IDX_BACKGROUND) {
cfg80211_background_radar_event(mphy->hw->wiphy,
&dev->rdd2_chandef,
GFP_ATOMIC);
- else
+ } else {
+ struct mt7996_phy *phy = mphy->priv;
+
+ phy->rdd_tx_paused = true;
ieee80211_radar_detected(mphy->hw, NULL);
+ }
dev->hw_pattern++;
+
+ return;
+
+err:
+ dev_err(dev->mt76.dev, "Invalid RDD idx %d\n", r->rdd_idx);
}
static void
@@ -4612,6 +4620,35 @@ int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable)
&req, sizeof(req), true);
}
+int mt7996_mcu_rdd_resume_tx(struct mt7996_phy *phy)
+{
+ struct {
+ u8 band_idx;
+ u8 _rsv[3];
+
+ __le16 tag;
+ __le16 len;
+ u8 mac_enable;
+ u8 _rsv2[3];
+ } __packed req = {
+ .band_idx = phy->mt76->band_idx,
+ .tag = cpu_to_le16(UNI_BAND_CONFIG_MAC_ENABLE_CTRL),
+ .len = cpu_to_le16(sizeof(req) - 4),
+ .mac_enable = 2,
+ };
+ int ret;
+
+ if (!phy->rdd_tx_paused)
+ return 0;
+
+ ret = mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(BAND_CONFIG),
+ &req, sizeof(req), true);
+ if (!ret)
+ phy->rdd_tx_paused = false;
+
+ return ret;
+}
+
int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 rdd_idx, u8 val)
{
struct {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
index fc8b09e76f01..5b3597ca79be 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
@@ -835,6 +835,7 @@ enum {
enum {
UNI_BAND_CONFIG_RADIO_ENABLE,
UNI_BAND_CONFIG_RTS_THRESHOLD = 0x08,
+ UNI_BAND_CONFIG_MAC_ENABLE_CTRL = 0x0c,
};
enum {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 7a884311800e..d31864f973cc 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -377,6 +377,7 @@ struct mt7996_phy {
bool has_aux_rx;
bool counter_reset;
+ bool rdd_tx_paused;
};
struct mt7996_dev {
@@ -726,6 +727,7 @@ int mt7996_mcu_get_temperature(struct mt7996_phy *phy);
int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state);
int mt7996_mcu_set_thermal_protect(struct mt7996_phy *phy, bool enable);
int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy);
+int mt7996_mcu_rdd_resume_tx(struct mt7996_phy *phy);
int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 rdd_idx, u8 val);
int mt7996_mcu_rdd_background_enable(struct mt7996_phy *phy,
struct cfg80211_chan_def *chandef);