2021-01-05 12:54:32

by Shayne Chen

[permalink] [raw]
Subject: [PATCH 1/4] mt76: testmode: add a new state for continuous tx

Support to set a special tx state in testmode: continuous tx,
which is used for sending tx without time gap.
Note that continuous tx mode doesn't send real packets, instead, it's
pure phy signal, and the waveform can be observed by instrument.

Signed-off-by: Shayne Chen <[email protected]>
---
drivers/net/wireless/mediatek/mt76/testmode.h | 2 ++
1 file changed, 2 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/testmode.h b/drivers/net/wireless/mediatek/mt76/testmode.h
index e4849946f180..6db8109a0945 100644
--- a/drivers/net/wireless/mediatek/mt76/testmode.h
+++ b/drivers/net/wireless/mediatek/mt76/testmode.h
@@ -140,12 +140,14 @@ enum mt76_testmode_rx_attr {
* @MT76_TM_STATE_IDLE: test mode enabled, but idle
* @MT76_TM_STATE_TX_FRAMES: send a fixed number of test frames
* @MT76_TM_STATE_RX_FRAMES: receive packets and keep statistics
+ * @MT76_TM_STATE_TX_CONT: waveform tx without time gap
*/
enum mt76_testmode_state {
MT76_TM_STATE_OFF,
MT76_TM_STATE_IDLE,
MT76_TM_STATE_TX_FRAMES,
MT76_TM_STATE_RX_FRAMES,
+ MT76_TM_STATE_TX_CONT,

/* keep last */
NUM_MT76_TM_STATES,
--
2.29.2


2021-01-05 12:54:33

by Shayne Chen

[permalink] [raw]
Subject: [PATCH 3/4] mt76: mt7915: add support for continuous tx in testmode

Implement continuous tx state for MT7915 NIC testmode.

Signed-off-by: Shayne Chen <[email protected]>
---
.../net/wireless/mediatek/mt76/mt7915/mcu.c | 3 +-
.../net/wireless/mediatek/mt76/mt7915/mcu.h | 1 +
.../wireless/mediatek/mt76/mt7915/testmode.c | 160 ++++++++++++++++--
.../wireless/mediatek/mt76/mt7915/testmode.h | 40 +++++
4 files changed, 192 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
index 9f78e4ec14c9..abf8ba2308ba 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
@@ -3208,7 +3208,8 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)
#ifdef CONFIG_NL80211_TESTMODE
if (phy->mt76->test.tx_antenna_mask &&
(phy->mt76->test.state == MT76_TM_STATE_TX_FRAMES ||
- phy->mt76->test.state == MT76_TM_STATE_RX_FRAMES)) {
+ phy->mt76->test.state == MT76_TM_STATE_RX_FRAMES ||
+ phy->mt76->test.state == MT76_TM_STATE_TX_CONT)) {
req.tx_streams_num = fls(phy->mt76->test.tx_antenna_mask);
req.rx_streams = phy->mt76->test.tx_antenna_mask;

diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
index 163b6f330e67..95ac3c418808 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
@@ -240,6 +240,7 @@ enum {

enum {
MCU_EXT_CMD_EFUSE_ACCESS = 0x01,
+ MCU_EXT_CMD_RF_TEST = 0x04,
MCU_EXT_CMD_PM_STATE_CTRL = 0x07,
MCU_EXT_CMD_CHANNEL_SWITCH = 0x08,
MCU_EXT_CMD_FW_LOG_2_HOST = 0x13,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c
index e5af42c70e12..68b170308c4a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c
@@ -409,6 +409,16 @@ mt7915_tm_init(struct mt7915_phy *phy, bool en)
mt7915_mcu_add_bss_info(phy, phy->monitor_vif, en);
}

+static void
+mt7915_tm_update_channel(struct mt7915_phy *phy)
+{
+ mutex_unlock(&phy->dev->mt76.mutex);
+ mt7915_set_channel(phy);
+ mutex_lock(&phy->dev->mt76.mutex);
+
+ mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH);
+}
+
static void
mt7915_tm_set_tx_frames(struct mt7915_phy *phy, bool en)
{
@@ -425,11 +435,7 @@ mt7915_tm_set_tx_frames(struct mt7915_phy *phy, bool en)
mt7915_tm_clean_hwq(phy, dev->mt76.global_wcid.idx);

if (en) {
- mutex_unlock(&dev->mt76.mutex);
- mt7915_set_channel(phy);
- mutex_lock(&dev->mt76.mutex);
-
- mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH);
+ mt7915_tm_update_channel(phy);

if (td->tx_spe_idx) {
phy->test.spe_idx = td->tx_spe_idx;
@@ -469,15 +475,144 @@ static void
mt7915_tm_set_rx_frames(struct mt7915_phy *phy, bool en)
{
struct mt7915_dev *dev = phy->dev;
- if (en) {
- mutex_unlock(&dev->mt76.mutex);
- mt7915_set_channel(phy);
- mutex_lock(&dev->mt76.mutex);
+ if (en)
+ mt7915_tm_update_channel(phy);
+
+ mt7915_tm_set_trx(phy, TM_MAC_RX_RXV, en);
+}
+
+static int
+mt7915_tm_rf_switch_mode(struct mt7915_dev *dev, u32 oper)
+{
+ struct mt7915_tm_rf_test req = {
+ .op.op_mode = cpu_to_le32(oper),
+ };
+
+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RF_TEST, &req,
+ sizeof(req), true);
+}
+
+static int
+mt7915_tm_set_tx_cont(struct mt7915_phy *phy, bool en)
+{
+#define TX_CONT_START 0x05
+#define TX_CONT_STOP 0x06
+ struct mt7915_dev *dev = phy->dev;
+ struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
+ int freq1 = ieee80211_frequency_to_channel(chandef->center_freq1);
+ struct mt76_testmode_data *td = &phy->mt76->test;
+ u32 func_idx = en ? TX_CONT_START : TX_CONT_STOP;
+ u8 rate_idx = td->tx_rate_idx, mode;
+ u16 rateval;
+ struct mt7915_tm_rf_test req = {
+ .action = 1,
+ .icap_len = 120,
+ .op.rf.func_idx = cpu_to_le32(func_idx),
+ };
+ struct tm_tx_cont *tx_cont = &req.op.rf.param.tx_cont;
+
+ tx_cont->control_ch = chandef->chan->hw_value;
+ tx_cont->center_ch = freq1;
+ tx_cont->tx_ant = td->tx_antenna_mask;
+ tx_cont->band = phy != &dev->phy;
+
+ switch (chandef->width) {
+ case NL80211_CHAN_WIDTH_40:
+ tx_cont->bw = CMD_CBW_40MHZ;
+ break;
+ case NL80211_CHAN_WIDTH_80:
+ tx_cont->bw = CMD_CBW_80MHZ;
+ break;
+ case NL80211_CHAN_WIDTH_80P80:
+ tx_cont->bw = CMD_CBW_8080MHZ;
+ break;
+ case NL80211_CHAN_WIDTH_160:
+ tx_cont->bw = CMD_CBW_160MHZ;
+ break;
+ case NL80211_CHAN_WIDTH_5:
+ tx_cont->bw = CMD_CBW_5MHZ;
+ break;
+ case NL80211_CHAN_WIDTH_10:
+ tx_cont->bw = CMD_CBW_10MHZ;
+ break;
+ case NL80211_CHAN_WIDTH_20:
+ tx_cont->bw = CMD_CBW_20MHZ;
+ break;
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ tx_cont->bw = CMD_CBW_20MHZ;
+ break;
+ default:
+ break;
+ }

- mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH);
+ if (!en) {
+ req.op.rf.param.func_data = cpu_to_le32(phy != &dev->phy);
+ goto out;
}

- mt7915_tm_set_trx(phy, TM_MAC_RX_RXV, en);
+ if (td->tx_rate_mode <= MT76_TM_TX_MODE_OFDM) {
+ struct ieee80211_supported_band *sband;
+ u8 idx = rate_idx;
+
+ if (chandef->chan->band == NL80211_BAND_5GHZ)
+ sband = &phy->mt76->sband_5g.sband;
+ else
+ sband = &phy->mt76->sband_2g.sband;
+
+ if (td->tx_rate_mode == MT76_TM_TX_MODE_OFDM)
+ idx += 4;
+ rate_idx = sband->bitrates[idx].hw_value & 0xff;
+ }
+
+ switch (td->tx_rate_mode) {
+ case MT76_TM_TX_MODE_CCK:
+ mode = MT_PHY_TYPE_CCK;
+ break;
+ case MT76_TM_TX_MODE_OFDM:
+ mode = MT_PHY_TYPE_OFDM;
+ break;
+ case MT76_TM_TX_MODE_HT:
+ mode = MT_PHY_TYPE_HT;
+ break;
+ case MT76_TM_TX_MODE_VHT:
+ mode = MT_PHY_TYPE_VHT;
+ break;
+ case MT76_TM_TX_MODE_HE_SU:
+ mode = MT_PHY_TYPE_HE_SU;
+ break;
+ case MT76_TM_TX_MODE_HE_EXT_SU:
+ mode = MT_PHY_TYPE_HE_EXT_SU;
+ break;
+ case MT76_TM_TX_MODE_HE_TB:
+ mode = MT_PHY_TYPE_HE_TB;
+ break;
+ case MT76_TM_TX_MODE_HE_MU:
+ mode = MT_PHY_TYPE_HE_MU;
+ break;
+ default:
+ break;
+ }
+
+ rateval = mode << 6 | rate_idx;
+ tx_cont->rateval = cpu_to_le16(rateval);
+
+out:
+ if (!en) {
+ int ret;
+
+ ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RF_TEST, &req,
+ sizeof(req), true);
+ if (ret)
+ return ret;
+
+ return mt7915_tm_rf_switch_mode(dev, RF_OPER_NORMAL);
+ }
+
+ mt7915_tm_rf_switch_mode(dev, RF_OPER_RF_TEST);
+ mt7915_tm_update_channel(phy);
+
+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RF_TEST, &req,
+ sizeof(req), true);
}

static void
@@ -507,6 +642,9 @@ mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
else if (prev_state == MT76_TM_STATE_RX_FRAMES ||
state == MT76_TM_STATE_RX_FRAMES)
mt7915_tm_set_rx_frames(phy, state == MT76_TM_STATE_RX_FRAMES);
+ else if (prev_state == MT76_TM_STATE_TX_CONT ||
+ state == MT76_TM_STATE_TX_CONT)
+ mt7915_tm_set_tx_cont(phy, state == MT76_TM_STATE_TX_CONT);
else if (prev_state == MT76_TM_STATE_OFF ||
state == MT76_TM_STATE_OFF)
mt7915_tm_init(phy, !(state == MT76_TM_STATE_OFF));
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/testmode.h b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.h
index da92cad0aa9b..8f8533ef9859 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/testmode.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.h
@@ -56,4 +56,44 @@ enum {
TM_MAC_RX_RXV,
};

+struct tm_tx_cont {
+ u8 control_ch;
+ u8 center_ch;
+ u8 bw;
+ u8 tx_ant;
+ __le16 rateval;
+ u8 band;
+ u8 txfd_mode;
+};
+
+struct mt7915_tm_rf_test {
+ u8 action;
+ u8 icap_len;
+ u8 _rsv[2];
+ union {
+ __le32 op_mode;
+ __le32 freq;
+
+ struct {
+ __le32 func_idx;
+ union {
+ __le32 func_data;
+ __le32 cal_dump;
+
+ struct tm_tx_cont tx_cont;
+
+ u8 _pad[80];
+ } param;
+ } rf;
+ } op;
+} __packed;
+
+enum {
+ RF_OPER_NORMAL,
+ RF_OPER_RF_TEST,
+ RF_OPER_ICAP,
+ RF_OPER_ICAP_OVERLAP,
+ RF_OPER_WIFI_SPECTRUM,
+};
+
#endif
--
2.29.2

2021-01-05 12:56:04

by Shayne Chen

[permalink] [raw]
Subject: [PATCH 2/4] mt76: mt7915: rework set state part in testmode

This is a preliminary patch to simplify setting state in mt7915
testmode, for adding the new continuous tx state.

Signed-off-by: Shayne Chen <[email protected]>
---
.../wireless/mediatek/mt76/mt7915/testmode.c | 22 +++++++++----------
1 file changed, 10 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c
index 6f6e02038c6d..e5af42c70e12 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c
@@ -395,9 +395,8 @@ mt7915_tm_reg_backup_restore(struct mt7915_phy *phy)
}

static void
-mt7915_tm_init(struct mt7915_phy *phy)
+mt7915_tm_init(struct mt7915_phy *phy, bool en)
{
- bool en = !(phy->mt76->test.state == MT76_TM_STATE_OFF);
struct mt7915_dev *dev = phy->dev;

if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
@@ -502,16 +501,15 @@ mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)

mphy->test.state = state;

- if (prev_state == MT76_TM_STATE_TX_FRAMES)
- mt7915_tm_set_tx_frames(phy, false);
- else if (state == MT76_TM_STATE_TX_FRAMES)
- mt7915_tm_set_tx_frames(phy, true);
- else if (prev_state == MT76_TM_STATE_RX_FRAMES)
- mt7915_tm_set_rx_frames(phy, false);
- else if (state == MT76_TM_STATE_RX_FRAMES)
- mt7915_tm_set_rx_frames(phy, true);
- else if (prev_state == MT76_TM_STATE_OFF || state == MT76_TM_STATE_OFF)
- mt7915_tm_init(phy);
+ if (prev_state == MT76_TM_STATE_TX_FRAMES ||
+ state == MT76_TM_STATE_TX_FRAMES)
+ mt7915_tm_set_tx_frames(phy, state == MT76_TM_STATE_TX_FRAMES);
+ else if (prev_state == MT76_TM_STATE_RX_FRAMES ||
+ state == MT76_TM_STATE_RX_FRAMES)
+ mt7915_tm_set_rx_frames(phy, state == MT76_TM_STATE_RX_FRAMES);
+ else if (prev_state == MT76_TM_STATE_OFF ||
+ state == MT76_TM_STATE_OFF)
+ mt7915_tm_init(phy, !(state == MT76_TM_STATE_OFF));

if ((state == MT76_TM_STATE_IDLE &&
prev_state == MT76_TM_STATE_OFF) ||
--
2.29.2

2021-01-14 10:25:46

by Felix Fietkau

[permalink] [raw]
Subject: Re: [PATCH 3/4] mt76: mt7915: add support for continuous tx in testmode

On 2021-01-05 12:30, Shayne Chen wrote:
> Implement continuous tx state for MT7915 NIC testmode.
>
> Signed-off-by: Shayne Chen <[email protected]>
> ---
> .../net/wireless/mediatek/mt76/mt7915/mcu.c | 3 +-
> .../net/wireless/mediatek/mt76/mt7915/mcu.h | 1 +
> .../wireless/mediatek/mt76/mt7915/testmode.c | 160 ++++++++++++++++--
> .../wireless/mediatek/mt76/mt7915/testmode.h | 40 +++++
> 4 files changed, 192 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c
> index e5af42c70e12..68b170308c4a 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c
> @@ -469,15 +475,144 @@ static void
> mt7915_tm_set_rx_frames(struct mt7915_phy *phy, bool en)
> {
> struct mt7915_dev *dev = phy->dev;
> - if (en) {
> - mutex_unlock(&dev->mt76.mutex);
> - mt7915_set_channel(phy);
> - mutex_lock(&dev->mt76.mutex);
> + if (en)
> + mt7915_tm_update_channel(phy);
> +
> + mt7915_tm_set_trx(phy, TM_MAC_RX_RXV, en);
This leaves dev as an unused variable. I'll fix it up locally.

- Felix