]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
wifi: mt76: mt7996: fix the behavior of radar detection
authorStanleyYP Wang <StanleyYP.Wang@mediatek.com>
Mon, 15 Dec 2025 06:37:23 +0000 (14:37 +0800)
committerFelix Fietkau <nbd@nbd.name>
Mon, 23 Mar 2026 09:14:42 +0000 (09:14 +0000)
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>
drivers/net/wireless/mediatek/mt76/mt7996/mac.c
drivers/net/wireless/mediatek/mt76/mt7996/main.c
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h

index 84cbf36b493c5000796be0fc529b9ae2ca40884d..2765ac7285b40b6ffa96d766325b2712f97e3139 100644 (file)
@@ -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)
index 4b73fefcee8e88bdb329a75719c320c5df965585..fac50dbceae7645a766ee51220c6b029c46ce5bc 100644 (file)
@@ -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);
@@ -954,6 +955,24 @@ mt7996_channel_switch_beacon(struct ieee80211_hw *hw,
        mutex_unlock(&dev->mt76.mutex);
 }
 
+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,
@@ -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,
index c059ddbf1e423e55cb56b545dce381f9e64cddb2..6294704f78813886a5068fc8fa636d4392e5a6c9 100644 (file)
@@ -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 {
index fc8b09e76f013cf06517fe5ba906eb7a5558d339..5b3597ca79be92b0535769bf7e58a02cd9d4cae9 100644 (file)
@@ -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 {
index 7a884311800ea8cfc0e302b2a140a4072ce18b69..d31864f973cceb5649ac4b7357bcac79eb01d0d9 100644 (file)
@@ -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);