2021-09-28 15:15:55

by Lorenzo Bianconi

[permalink] [raw]
Subject: [RFC 4/7] mt76: mt7915: introduce mt7915_set_offchan_chain routine

Introduce mt7915_dfs_set_rdd_monitor and mt7915_mcu_set_offchan_ctrl
routines to configure rx dfs dedicated chain.
This is a preliminary patch to add zero-wait dfs support performing CAC
detection on rdd2.

Signed-off-by: Lorenzo Bianconi <[email protected]>
---
.../net/wireless/mediatek/mt76/mt7915/init.c | 2 +
.../net/wireless/mediatek/mt76/mt7915/mac.c | 35 +++++++++++++
.../net/wireless/mediatek/mt76/mt7915/main.c | 32 ++++++++++++
.../net/wireless/mediatek/mt76/mt7915/mcu.c | 52 +++++++++++++++++++
.../net/wireless/mediatek/mt76/mt7915/mcu.h | 24 +++++++++
.../wireless/mediatek/mt76/mt7915/mt7915.h | 8 +++
6 files changed, 153 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
index 8c42a1668013..ba4d644fe846 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
@@ -296,6 +296,8 @@ mt7915_regd_notifier(struct wiphy *wiphy,
mt7915_init_txpower(dev, &mphy->sband_2g.sband);
mt7915_init_txpower(dev, &mphy->sband_5g.sband);

+ mt7915_dfs_set_rdd_monitor(phy, dev->mt76.region != NL80211_DFS_UNSET);
+
if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR))
return;

diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
index 899d2e228c1f..a2f94bedf9a1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
@@ -2316,3 +2316,38 @@ void mt7915_mac_twt_teardown_flow(struct mt7915_dev *dev,
dev->twt.table_mask &= ~BIT(flow->table_id);
dev->twt.n_agrt--;
}
+
+int mt7915_dfs_set_rdd_monitor(struct mt7915_phy *phy, bool enable)
+{
+ struct mt7915_dev *dev = phy->dev;
+ int err, region;
+
+ if (!enable || dev->mt76.region == NL80211_DFS_UNSET) {
+ err = mt7915_mcu_rdd_cmd(dev, RDD_STOP, MT_RX_SEL2, 0, 0);
+ if (err)
+ return err;
+
+ return mt7915_mcu_set_offchan_ctrl(phy,
+ CH_SWITCH_BACKGROUND_SCAN_STOP);
+ }
+
+ err = mt7915_mcu_set_offchan_ctrl(phy,
+ 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);
+}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
index ce1c68cf061a..406517bfbfc2 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
@@ -1085,6 +1085,37 @@ mt7915_twt_teardown_request(struct ieee80211_hw *hw,
mutex_unlock(&dev->mt76.mutex);
}

+static int
+mt7915_set_offchan_chain(struct ieee80211_hw *hw,
+ struct cfg80211_chan_def *chandef)
+{
+ struct mt7915_phy *phy = mt7915_hw_phy(hw);
+ struct cfg80211_chan_def *off_chandef;
+ struct mt7915_dev *dev = phy->dev;
+ bool running;
+
+ off_chandef = &dev->offchan_chain.chandef;
+ if (cfg80211_chandef_identical(chandef, off_chandef))
+ return 0;
+
+ if (cfg80211_chandef_identical(&phy->mt76->chandef, off_chandef))
+ return 0;
+
+ running = off_chandef->chan &&
+ !!(off_chandef->chan->flags & IEEE80211_CHAN_RADAR);
+ *off_chandef = *chandef;
+
+ if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR) || running) {
+ int ret;
+
+ ret = mt7915_dfs_set_rdd_monitor(phy, false);
+ if (ret || !running)
+ return ret;
+ }
+
+ return mt7915_dfs_set_rdd_monitor(phy, true);
+}
+
const struct ieee80211_ops mt7915_ops = {
.tx = mt7915_tx,
.start = mt7915_start,
@@ -1127,4 +1158,5 @@ const struct ieee80211_ops mt7915_ops = {
#ifdef CONFIG_MAC80211_DEBUGFS
.sta_add_debugfs = mt7915_sta_add_debugfs,
#endif
+ .set_offchan_chain = mt7915_set_offchan_chain,
};
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
index df3a9dc1ca35..6249be262825 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
@@ -3204,6 +3204,58 @@ int mt7915_mcu_set_radar_th(struct mt7915_dev *dev, int index,
sizeof(req), true);
}

+int mt7915_mcu_set_offchan_ctrl(struct mt7915_phy *phy, int cmd)
+{
+ struct mt7915_dev *dev = phy->dev;
+ struct mt76_phy *mphy = phy->mt76;
+ struct ieee80211_channel *chan = mphy->chandef.chan;
+ struct cfg80211_chan_def *off_chandef = &dev->offchan_chain.chandef;
+ struct ieee80211_channel *off_chan = off_chandef->chan;
+ int offchan_freq = off_chandef->center_freq1;
+ int freq = mphy->chandef.center_freq1;
+ struct mt7915_mcu_offchan_ctrl req = {
+ .monitor_scan_type = 2, /* simple rx */
+ };
+
+ if (!off_chan)
+ 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 = off_chan->hw_value;
+ req.monitor_central_chan =
+ ieee80211_frequency_to_channel(offchan_freq);
+ req.monitor_bw = mt7915_mcu_chan_bw(off_chandef);
+ req.band_idx = phy != &dev->phy;
+ req.scan_mode = 1;
+ break;
+ }
+ case CH_SWITCH_BACKGROUND_SCAN_RUNNING:
+ req.monitor_chan = off_chan->hw_value;
+ req.monitor_central_chan =
+ ieee80211_frequency_to_channel(offchan_freq);
+ 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 = off_chan->band == NL80211_BAND_5GHZ;
+
+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(OFFCH_SCAN_CTRL),
+ &req, sizeof(req), false);
+}
+
int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)
{
struct mt7915_dev *dev = phy->dev;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
index 0bd66c5136e9..8e0b219de8bc 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
@@ -152,6 +152,29 @@ struct mt7915_mcu_rdd_report {
} hw_pulse[32];
} __packed;

+struct mt7915_mcu_offchan_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;
@@ -279,6 +302,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/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
index 0cd09767455a..65017a4347b9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
@@ -191,6 +191,11 @@ struct mt7915_dev {
struct tasklet_struct irq_tasklet;
struct mt7915_phy phy;

+ /* monitor rx chain configured channel */
+ struct {
+ struct cfg80211_chan_def chandef;
+ } offchan_chain;
+
u16 chainmask;
u32 hif_idx;

@@ -251,6 +256,7 @@ enum {
enum {
MT_RX_SEL0,
MT_RX_SEL1,
+ MT_RX_SEL2, /* monitor chain */
};

enum mt7915_rdd_cmd {
@@ -389,6 +395,7 @@ 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_set_offchan_ctrl(struct mt7915_phy *phy, int cmd);
int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 ctrl);
int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level);
void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb);
@@ -455,6 +462,7 @@ void mt7915_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps);
void mt7915_stats_work(struct work_struct *work);
int mt76_dfs_start_rdd(struct mt7915_dev *dev, bool force);
int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy);
+int mt7915_dfs_set_rdd_monitor(struct mt7915_phy *phy, bool enable);
void mt7915_set_stream_he_caps(struct mt7915_phy *phy);
void mt7915_set_stream_vht_txbf_caps(struct mt7915_phy *phy);
void mt7915_update_channel(struct mt76_phy *mphy);
--
2.31.1