[][MAC80211][mt76][zero wait dfs]

[Description]
Add zero wait DFS for mt76

[Release-log]

Change-Id: I6b764d414b9af056940bd91d69dc4fd500973c2d
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/5342190
diff --git a/openwrt_patches-21.02/403-master-mt76-zero-wait-dfs.patch b/openwrt_patches-21.02/403-master-mt76-zero-wait-dfs.patch
new file mode 100644
index 0000000..600210d
--- /dev/null
+++ b/openwrt_patches-21.02/403-master-mt76-zero-wait-dfs.patch
@@ -0,0 +1,375 @@
+diff --git a/package/kernel/mt76/patches/1005-mt76-zero-wait-dfs.patch b/package/kernel/mt76/patches/1005-mt76-zero-wait-dfs.patch
+new file mode 100644
+index 0000000..68883e4
+--- /dev/null
++++ b/package/kernel/mt76/patches/1005-mt76-zero-wait-dfs.patch
+@@ -0,0 +1,369 @@
++diff --git a/mt7915/debugfs.c b/mt7915/debugfs.c
++index 3a0ec43..2ce6973 100644
++--- a/mt7915/debugfs.c
+++++ b/mt7915/debugfs.c
++@@ -75,12 +75,62 @@ mt7915_radar_trigger(void *data, u64 val)
++ {
++ 	struct mt7915_dev *dev = data;
++ 
++-	return mt7915_mcu_rdd_cmd(dev, RDD_RADAR_EMULATE, 1, 0, 0);
+++	if (val > MT_RX_SEL2)
+++		return -EINVAL;
+++
+++	return mt7915_mcu_rdd_cmd(dev, RDD_RADAR_EMULATE, val, 0, 0);
++ }
++ 
++ DEFINE_DEBUGFS_ATTRIBUTE(fops_radar_trigger, NULL,
++ 			 mt7915_radar_trigger, "%lld\n");
++ 
+++static int
+++mt7915_rdd_monitor(struct seq_file *s, void *data)
+++{
+++	struct mt7915_dev *dev = dev_get_drvdata(s->private);
+++	struct cfg80211_chan_def *chandef = &dev->rdd2_chandef;
+++	const char *bw;
+++	int ret = 0;
+++
+++	mutex_lock(&dev->mt76.mutex);
+++
+++	if (!cfg80211_chandef_valid(chandef)) {
+++		ret = -EINVAL;
+++		goto out;
+++	}
+++
+++	if (!dev->rdd2_phy) {
+++		seq_printf(s, "not running\n");
+++		goto out;
+++	}
+++
+++	switch (chandef->width) {
+++	case NL80211_CHAN_WIDTH_40:
+++		bw = "40";
+++		break;
+++	case NL80211_CHAN_WIDTH_80:
+++		bw = "80";
+++		break;
+++	case NL80211_CHAN_WIDTH_160:
+++		bw = "160";
+++		break;
+++	case NL80211_CHAN_WIDTH_80P80:
+++		bw = "80P80";
+++		break;
+++	default:
+++		bw = "20";
+++		break;
+++	}
+++
+++	seq_printf(s, "channel %d (%d MHz) width %s MHz center1: %d MHz\n",
+++		   chandef->chan->hw_value, chandef->chan->center_freq,
+++		   bw, chandef->center_freq1);
+++out:
+++	mutex_unlock(&dev->mt76.mutex);
+++
+++	return ret;
+++}
+++
++ static int
++ mt7915_fw_debug_wm_set(void *data, u64 val)
++ {
++@@ -552,6 +602,8 @@ int mt7915_init_debugfs(struct mt7915_phy *phy)
++ 				   &dev->hw_pattern);
++ 		debugfs_create_file("radar_trigger", 0200, dir, dev,
++ 				    &fops_radar_trigger);
+++		debugfs_create_devm_seqfile(dev->mt76.dev, "rdd_monitor", dir,
+++					    mt7915_rdd_monitor);
++ 	}
++ 
++ #ifdef MTK_DEBUG
++diff --git a/mt7915/init.c b/mt7915/init.c
++index e32cefc..6767702 100644
++--- a/mt7915/init.c
+++++ b/mt7915/init.c
++@@ -294,6 +294,9 @@ mt7915_regd_notifier(struct wiphy *wiphy,
++ 	memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2));
++ 	dev->mt76.region = request->dfs_region;
++ 
+++	if (dev->mt76.region == NL80211_DFS_UNSET)
+++		mt7915_mcu_rdd_offchan_enable(phy, NULL);
+++
++ 	mt7915_init_txpower(dev, &mphy->sband_2g.sband);
++ 	mt7915_init_txpower(dev, &mphy->sband_5g.sband);
++ 
++@@ -307,6 +310,7 @@ static void
++ mt7915_init_wiphy(struct ieee80211_hw *hw)
++ {
++ 	struct mt7915_phy *phy = mt7915_hw_phy(hw);
+++	struct mt76_dev *mdev = &phy->dev->mt76;
++ 	struct wiphy *wiphy = hw->wiphy;
++ 
++ 	hw->queues = 4;
++@@ -334,6 +338,12 @@ mt7915_init_wiphy(struct ieee80211_hw *hw)
++ 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
++ 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE);
++ 
+++	if (!mdev->dev->of_node ||
+++	    !of_property_read_bool(mdev->dev->of_node,
+++				   "mediatek,disable-radar-offchan"))
+++		wiphy_ext_feature_set(wiphy,
+++				      NL80211_EXT_FEATURE_RADAR_OFFCHAN);
+++
++ 	ieee80211_hw_set(hw, HAS_RATE_CONTROL);
++ 	ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD);
++ 	ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
++diff --git a/mt7915/main.c b/mt7915/main.c
++index 31efe2c..c9dba1f 100644
++--- a/mt7915/main.c
+++++ b/mt7915/main.c
++@@ -1312,6 +1312,55 @@ mt7915_twt_teardown_request(struct ieee80211_hw *hw,
++ 	mutex_unlock(&dev->mt76.mutex);
++ }
++ 
+++static int
+++mt7915_set_radar_offchan(struct ieee80211_hw *hw,
+++			 struct cfg80211_chan_def *chandef)
+++{
+++	struct mt7915_phy *phy = mt7915_hw_phy(hw);
+++	struct mt7915_dev *dev = phy->dev;
+++	int ret = -EINVAL;
+++	bool running;
+++
+++	mutex_lock(&dev->mt76.mutex);
+++
+++	if (dev->mt76.region == NL80211_DFS_UNSET)
+++		goto out;
+++
+++	if (dev->rdd2_phy && dev->rdd2_phy != phy) {
+++		/* rdd2 is already locked */
+++		ret = -EBUSY;
+++		goto out;
+++	}
+++
+++	/* rdd2 already configured on a radar channel */
+++	running = dev->rdd2_phy &&
+++		  cfg80211_chandef_valid(&dev->rdd2_chandef) &&
+++		  !!(dev->rdd2_chandef.chan->flags & IEEE80211_CHAN_RADAR);
+++
+++	if (!chandef || running ||
+++	    !(chandef->chan->flags & IEEE80211_CHAN_RADAR)) {
+++		ret = mt7915_mcu_rdd_offchan_enable(phy, NULL);
+++		if (ret)
+++			goto out;
+++
+++		if (!running)
+++			goto update_phy;
+++	}
+++
+++	ret = mt7915_mcu_rdd_offchan_enable(phy, chandef);
+++	if (ret)
+++		goto out;
+++
+++update_phy:
+++	dev->rdd2_phy = chandef ? phy : NULL;
+++	if (chandef)
+++		dev->rdd2_chandef = *chandef;
+++out:
+++	mutex_unlock(&dev->mt76.mutex);
+++
+++	return ret;
+++}
+++
++ const struct ieee80211_ops mt7915_ops = {
++ 	.tx = mt7915_tx,
++ 	.start = mt7915_start,
++@@ -1357,4 +1406,5 @@ const struct ieee80211_ops mt7915_ops = {
++ #ifdef CONFIG_MAC80211_DEBUGFS
++ 	.sta_add_debugfs = mt7915_sta_add_debugfs,
++ #endif
+++	.set_radar_offchan = mt7915_set_radar_offchan,
++ };
++diff --git a/mt7915/mcu.c b/mt7915/mcu.c
++index a5fb821..b361f68 100644
++--- a/mt7915/mcu.c
+++++ b/mt7915/mcu.c
++@@ -487,7 +487,12 @@ mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb)
++ 	if (r->band_idx && dev->mt76.phy2)
++ 		mphy = dev->mt76.phy2;
++ 
++-	ieee80211_radar_detected(mphy->hw);
+++	if (r->band_idx == MT_RX_SEL2)
+++		cfg80211_offchan_radar_event(mphy->hw->wiphy,
+++					     &dev->rdd2_chandef,
+++					     GFP_ATOMIC);
+++	else
+++		ieee80211_radar_detected(mphy->hw);
++ 	dev->hw_pattern++;
++ }
++ 
++@@ -3409,6 +3414,97 @@ int mt7915_mcu_set_radar_th(struct mt7915_dev *dev, int index,
++ 				 sizeof(req), true);
++ }
++ 
+++static int
+++mt7915_mcu_offchan_chain_ctrl(struct mt7915_phy *phy,
+++			      struct cfg80211_chan_def *chandef,
+++			      int cmd)
+++{
+++	struct mt7915_dev *dev = phy->dev;
+++	struct mt76_phy *mphy = phy->mt76;
+++	struct ieee80211_channel *chan = mphy->chandef.chan;
+++	int freq = mphy->chandef.center_freq1;
+++	struct mt7915_mcu_offchan_chain_ctrl req = {
+++		.monitor_scan_type = 2, /* simple rx */
+++	};
+++
+++	if (!chandef && cmd != CH_SWITCH_BACKGROUND_SCAN_STOP)
+++		return -EINVAL;
+++
+++	if (!cfg80211_chandef_valid(&mphy->chandef))
+++		return -EINVAL;
+++
+++	switch (cmd) {
+++	case CH_SWITCH_BACKGROUND_SCAN_START: {
+++		req.chan = chan->hw_value;
+++		req.central_chan = ieee80211_frequency_to_channel(freq);
+++		req.bw = mt7915_mcu_chan_bw(&mphy->chandef);
+++		req.monitor_chan = chandef->chan->hw_value;
+++		req.monitor_central_chan =
+++			ieee80211_frequency_to_channel(chandef->center_freq1);
+++		req.monitor_bw = mt7915_mcu_chan_bw(chandef);
+++		req.band_idx = phy != &dev->phy;
+++		req.scan_mode = 1;
+++		break;
+++	}
+++	case CH_SWITCH_BACKGROUND_SCAN_RUNNING:
+++		req.monitor_chan = chandef->chan->hw_value;
+++		req.monitor_central_chan =
+++			ieee80211_frequency_to_channel(chandef->center_freq1);
+++		req.band_idx = phy != &dev->phy;
+++		req.scan_mode = 2;
+++		break;
+++	case CH_SWITCH_BACKGROUND_SCAN_STOP:
+++		req.chan = chan->hw_value;
+++		req.central_chan = ieee80211_frequency_to_channel(freq);
+++		req.bw = mt7915_mcu_chan_bw(&mphy->chandef);
+++		req.tx_stream = hweight8(mphy->antenna_mask);
+++		req.rx_stream = mphy->antenna_mask;
+++		break;
+++	default:
+++		return -EINVAL;
+++	}
+++	req.band = chandef ? chandef->chan->band == NL80211_BAND_5GHZ : 1;
+++
+++	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(OFFCH_SCAN_CTRL),
+++				 &req, sizeof(req), false);
+++}
+++
+++int mt7915_mcu_rdd_offchan_enable(struct mt7915_phy *phy,
+++				  struct cfg80211_chan_def *chandef)
+++{
+++	struct mt7915_dev *dev = phy->dev;
+++	int err, region;
+++
+++	if (!chandef) { /* disable offchain */
+++		err = mt7915_mcu_rdd_cmd(dev, RDD_STOP, MT_RX_SEL2, 0, 0);
+++		if (err)
+++			return err;
+++
+++		return mt7915_mcu_offchan_chain_ctrl(phy, NULL,
+++				CH_SWITCH_BACKGROUND_SCAN_STOP);
+++	}
+++
+++	err = mt7915_mcu_offchan_chain_ctrl(phy, chandef,
+++					    CH_SWITCH_BACKGROUND_SCAN_START);
+++	if (err)
+++		return err;
+++
+++	switch (dev->mt76.region) {
+++	case NL80211_DFS_ETSI:
+++		region = 0;
+++		break;
+++	case NL80211_DFS_JP:
+++		region = 2;
+++		break;
+++	case NL80211_DFS_FCC:
+++	default:
+++		region = 1;
+++		break;
+++	}
+++
+++	return mt7915_mcu_rdd_cmd(dev, RDD_START, MT_RX_SEL2, 0, region);
+++}
+++
++ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)
++ {
++ 	struct mt7915_dev *dev = phy->dev;
++diff --git a/mt7915/mcu.h b/mt7915/mcu.h
++index 2f856ae..64bea9a 100644
++--- a/mt7915/mcu.h
+++++ b/mt7915/mcu.h
++@@ -153,6 +153,29 @@ struct mt7915_mcu_rdd_report {
++ 	} hw_pulse[32];
++ } __packed;
++ 
+++struct mt7915_mcu_offchan_chain_ctrl {
+++	u8 chan;		/* primary channel */
+++	u8 central_chan;	/* central channel */
+++	u8 bw;
+++	u8 tx_stream;
+++	u8 rx_stream;
+++
+++	u8 monitor_chan;	/* monitor channel */
+++	u8 monitor_central_chan;/* monitor central channel */
+++	u8 monitor_bw;
+++	u8 monitor_tx_stream;
+++	u8 monitor_rx_stream;
+++
+++	u8 scan_mode;		/* 0: ScanStop
+++				 * 1: ScanStart
+++				 * 2: ScanRunning
+++				 */
+++	u8 band_idx;		/* DBDC */
+++	u8 monitor_scan_type;
+++	u8 band;		/* 0: 2.4GHz, 1: 5GHz */
+++	u8 rsv[2];
+++} __packed;
+++
++ struct mt7915_mcu_eeprom {
++ 	u8 buffer_mode;
++ 	u8 format;
++@@ -286,6 +309,7 @@ enum {
++ 	MCU_EXT_CMD_SCS_CTRL = 0x82,
++ 	MCU_EXT_CMD_TWT_AGRT_UPDATE = 0x94,
++ 	MCU_EXT_CMD_FW_DBG_CTRL = 0x95,
+++	MCU_EXT_CMD_OFFCH_SCAN_CTRL = 0x9a,
++ 	MCU_EXT_CMD_SET_RDD_TH = 0x9d,
++ 	MCU_EXT_CMD_MURU_CTRL = 0x9f,
++ 	MCU_EXT_CMD_SET_SPR = 0xa8,
++diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
++index 27dcd3f..f3449eb 100644
++--- a/mt7915/mt7915.h
+++++ b/mt7915/mt7915.h
++@@ -298,6 +298,10 @@ struct mt7915_dev {
++ 	struct tasklet_struct irq_tasklet;
++ 	struct mt7915_phy phy;
++ 
+++	/* monitor rx chain configured channel */
+++	struct cfg80211_chan_def rdd2_chandef;
+++	struct mt7915_phy *rdd2_phy;
+++
++ 	u16 chainmask;
++ 	u32 hif_idx;
++ 
++@@ -379,6 +383,7 @@ enum {
++ enum {
++ 	MT_RX_SEL0,
++ 	MT_RX_SEL1,
+++	MT_RX_SEL2, /* monitor chain */
++ };
++ 
++ enum mt7915_rdd_cmd {
++@@ -516,6 +521,8 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,
++ 			   struct ieee80211_sta *sta, struct rate_info *rate);
++ int mt7915_mcu_rdd_cmd(struct mt7915_dev *dev, enum mt7915_rdd_cmd cmd,
++ 		       u8 index, u8 rx_sel, u8 val);
+++int mt7915_mcu_rdd_offchan_enable(struct mt7915_phy *phy,
+++				  struct cfg80211_chan_def *chandef);
++ int mt7915_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3);
++ int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl);
++ int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level);
++