[PATCH mt76 2/7] wifi: mt76: mt7996: fix the behavior of radar detection

Lorenzo Bianconi lorenzo at kernel.org
Tue Dec 9 03:19:52 PST 2025


On Nov 25, Shayne Chen wrote:
> From: StanleyYP Wang <StanleyYP.Wang at mediatek.com>
> 
> 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 at mediatek.com>
> Signed-off-by: Shayne Chen <shayne.chen at mediatek.com>
> Signed-off-by: StanleyYP Wang <StanleyYP.Wang at mediatek.com>
> ---
>  .../net/wireless/mediatek/mt76/mt7996/mac.c   |  8 +---
>  .../net/wireless/mediatek/mt76/mt7996/main.c  | 20 ++++++++
>  .../net/wireless/mediatek/mt76/mt7996/mcu.c   | 46 ++++++++++++++++---
>  .../net/wireless/mediatek/mt76/mt7996/mcu.h   |  1 +
>  .../wireless/mediatek/mt76/mt7996/mt7996.h    |  2 +
>  5 files changed, 65 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> index 2560e2f46e89..ce85d8f1bde6 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> @@ -2973,7 +2973,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:
> @@ -2988,11 +2988,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 9b4bfb071292..18c6cdaae20b 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);
> @@ -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,
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> index 7be03bbf34d4..c18c809ac77a 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
> @@ -4610,6 +4618,32 @@ 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,
> +	};
> +
> +	if (!phy->rdd_tx_paused)
> +		return 0;
> +
> +	phy->rdd_tx_paused = false;

should you check the return value of mt76_mcu_send_msg() before setting
rdd_tx_paused to false here?

Regards,
Lorenzo

> +
> +	return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(BAND_CONFIG),
> +				 &req, sizeof(req), true);
> +}
> +
>  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);
> -- 
> 2.51.0
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mediatek/attachments/20251209/ee4fe11d/attachment.sig>


More information about the Linux-mediatek mailing list