aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mediatek/mt76/testmode.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--drivers/net/wireless/mediatek/mt76/testmode.c124
1 files changed, 79 insertions, 45 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/testmode.c b/drivers/net/wireless/mediatek/mt76/testmode.c
index 581eb56dc4be..cc769645afa5 100644
--- a/drivers/net/wireless/mediatek/mt76/testmode.c
+++ b/drivers/net/wireless/mediatek/mt76/testmode.c
@@ -14,18 +14,23 @@ static const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
[MT76_TM_ATTR_TX_RATE_STBC] = { .type = NLA_U8 },
[MT76_TM_ATTR_TX_LTF] = { .type = NLA_U8 },
[MT76_TM_ATTR_TX_ANTENNA] = { .type = NLA_U8 },
+ [MT76_TM_ATTR_TX_SPE_IDX] = { .type = NLA_U8 },
[MT76_TM_ATTR_TX_POWER_CONTROL] = { .type = NLA_U8 },
[MT76_TM_ATTR_TX_POWER] = { .type = NLA_NESTED },
+ [MT76_TM_ATTR_TX_DUTY_CYCLE] = { .type = NLA_U8 },
+ [MT76_TM_ATTR_TX_IPG] = { .type = NLA_U32 },
+ [MT76_TM_ATTR_TX_TIME] = { .type = NLA_U32 },
[MT76_TM_ATTR_FREQ_OFFSET] = { .type = NLA_U32 },
};
-void mt76_testmode_tx_pending(struct mt76_dev *dev)
+void mt76_testmode_tx_pending(struct mt76_phy *phy)
{
- struct mt76_testmode_data *td = &dev->test;
+ struct mt76_testmode_data *td = &phy->test;
+ struct mt76_dev *dev = phy->dev;
struct mt76_wcid *wcid = &dev->global_wcid;
- struct mt76_phy *phy = &dev->phy;
struct sk_buff *skb = td->tx_skb;
struct mt76_queue *q;
+ u16 tx_queued_limit;
int qid;
if (!skb || !td->tx_pending)
@@ -34,9 +39,12 @@ void mt76_testmode_tx_pending(struct mt76_dev *dev)
qid = skb_get_queue_mapping(skb);
q = phy->q_tx[qid];
+ tx_queued_limit = td->tx_queued_limit ? td->tx_queued_limit : 1000;
+
spin_lock_bh(&q->lock);
- while (td->tx_pending > 0 && td->tx_queued - td->tx_done < 1000 &&
+ while (td->tx_pending > 0 &&
+ td->tx_queued - td->tx_done < tx_queued_limit &&
q->queued < q->ndesc / 2) {
int ret;
@@ -56,10 +64,9 @@ void mt76_testmode_tx_pending(struct mt76_dev *dev)
static int
-mt76_testmode_tx_init(struct mt76_dev *dev)
+mt76_testmode_tx_init(struct mt76_phy *phy)
{
- struct mt76_testmode_data *td = &dev->test;
- struct mt76_phy *phy = &dev->phy;
+ struct mt76_testmode_data *td = &phy->test;
struct ieee80211_tx_info *info;
struct ieee80211_hdr *hdr;
struct sk_buff *skb;
@@ -67,6 +74,7 @@ mt76_testmode_tx_init(struct mt76_dev *dev)
IEEE80211_FCTL_FROMDS;
struct ieee80211_tx_rate *rate;
u8 max_nss = hweight8(phy->antenna_mask);
+ bool ext_phy = phy != &phy->dev->phy;
if (td->tx_antenna_mask)
max_nss = min_t(u8, max_nss, hweight8(td->tx_antenna_mask));
@@ -88,6 +96,9 @@ mt76_testmode_tx_init(struct mt76_dev *dev)
IEEE80211_TX_CTL_NO_ACK |
IEEE80211_TX_CTL_NO_PS_BUFFER;
+ if (ext_phy)
+ info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY;
+
if (td->tx_rate_mode > MT76_TM_TX_MODE_VHT)
goto out;
@@ -166,9 +177,10 @@ out:
}
static void
-mt76_testmode_tx_start(struct mt76_dev *dev)
+mt76_testmode_tx_start(struct mt76_phy *phy)
{
- struct mt76_testmode_data *td = &dev->test;
+ struct mt76_testmode_data *td = &phy->test;
+ struct mt76_dev *dev = phy->dev;
td->tx_queued = 0;
td->tx_done = 0;
@@ -177,9 +189,10 @@ mt76_testmode_tx_start(struct mt76_dev *dev)
}
static void
-mt76_testmode_tx_stop(struct mt76_dev *dev)
+mt76_testmode_tx_stop(struct mt76_phy *phy)
{
- struct mt76_testmode_data *td = &dev->test;
+ struct mt76_testmode_data *td = &phy->test;
+ struct mt76_dev *dev = phy->dev;
mt76_worker_disable(&dev->tx_worker);
@@ -187,7 +200,8 @@ mt76_testmode_tx_stop(struct mt76_dev *dev)
mt76_worker_enable(&dev->tx_worker);
- wait_event_timeout(dev->tx_wait, td->tx_done == td->tx_queued, 10 * HZ);
+ wait_event_timeout(dev->tx_wait, td->tx_done == td->tx_queued,
+ MT76_TM_TIMEOUT * HZ);
dev_kfree_skb(td->tx_skb);
td->tx_skb = NULL;
@@ -206,9 +220,9 @@ mt76_testmode_param_present(struct mt76_testmode_data *td, u16 idx)
}
static void
-mt76_testmode_init_defaults(struct mt76_dev *dev)
+mt76_testmode_init_defaults(struct mt76_phy *phy)
{
- struct mt76_testmode_data *td = &dev->test;
+ struct mt76_testmode_data *td = &phy->test;
if (td->tx_msdu_len > 0)
return;
@@ -220,49 +234,50 @@ mt76_testmode_init_defaults(struct mt76_dev *dev)
}
static int
-__mt76_testmode_set_state(struct mt76_dev *dev, enum mt76_testmode_state state)
+__mt76_testmode_set_state(struct mt76_phy *phy, enum mt76_testmode_state state)
{
- enum mt76_testmode_state prev_state = dev->test.state;
+ enum mt76_testmode_state prev_state = phy->test.state;
+ struct mt76_dev *dev = phy->dev;
int err;
if (prev_state == MT76_TM_STATE_TX_FRAMES)
- mt76_testmode_tx_stop(dev);
+ mt76_testmode_tx_stop(phy);
if (state == MT76_TM_STATE_TX_FRAMES) {
- err = mt76_testmode_tx_init(dev);
+ err = mt76_testmode_tx_init(phy);
if (err)
return err;
}
- err = dev->test_ops->set_state(dev, state);
+ err = dev->test_ops->set_state(phy, state);
if (err) {
if (state == MT76_TM_STATE_TX_FRAMES)
- mt76_testmode_tx_stop(dev);
+ mt76_testmode_tx_stop(phy);
return err;
}
if (state == MT76_TM_STATE_TX_FRAMES)
- mt76_testmode_tx_start(dev);
+ mt76_testmode_tx_start(phy);
else if (state == MT76_TM_STATE_RX_FRAMES) {
- memset(&dev->test.rx_stats, 0, sizeof(dev->test.rx_stats));
+ memset(&phy->test.rx_stats, 0, sizeof(phy->test.rx_stats));
}
- dev->test.state = state;
+ phy->test.state = state;
return 0;
}
-int mt76_testmode_set_state(struct mt76_dev *dev, enum mt76_testmode_state state)
+int mt76_testmode_set_state(struct mt76_phy *phy, enum mt76_testmode_state state)
{
- struct mt76_testmode_data *td = &dev->test;
- struct ieee80211_hw *hw = dev->phy.hw;
+ struct mt76_testmode_data *td = &phy->test;
+ struct ieee80211_hw *hw = phy->hw;
if (state == td->state && state == MT76_TM_STATE_OFF)
return 0;
if (state > MT76_TM_STATE_OFF &&
- (!test_bit(MT76_STATE_RUNNING, &dev->phy.state) ||
+ (!test_bit(MT76_STATE_RUNNING, &phy->state) ||
!(hw->conf.flags & IEEE80211_CONF_MONITOR)))
return -ENOTCONN;
@@ -270,12 +285,12 @@ int mt76_testmode_set_state(struct mt76_dev *dev, enum mt76_testmode_state state
td->state != MT76_TM_STATE_IDLE) {
int ret;
- ret = __mt76_testmode_set_state(dev, MT76_TM_STATE_IDLE);
+ ret = __mt76_testmode_set_state(phy, MT76_TM_STATE_IDLE);
if (ret)
return ret;
}
- return __mt76_testmode_set_state(dev, state);
+ return __mt76_testmode_set_state(phy, state);
}
EXPORT_SYMBOL(mt76_testmode_set_state);
@@ -301,8 +316,9 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
{
struct mt76_phy *phy = hw->priv;
struct mt76_dev *dev = phy->dev;
- struct mt76_testmode_data *td = &dev->test;
+ struct mt76_testmode_data *td = &phy->test;
struct nlattr *tb[NUM_MT76_TM_ATTRS];
+ bool ext_phy = phy != &dev->phy;
u32 state;
int err;
int i;
@@ -320,11 +336,11 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
mutex_lock(&dev->mutex);
if (tb[MT76_TM_ATTR_RESET]) {
- mt76_testmode_set_state(dev, MT76_TM_STATE_OFF);
+ mt76_testmode_set_state(phy, MT76_TM_STATE_OFF);
memset(td, 0, sizeof(*td));
}
- mt76_testmode_init_defaults(dev);
+ mt76_testmode_init_defaults(phy);
if (tb[MT76_TM_ATTR_TX_COUNT])
td->tx_count = nla_get_u32(tb[MT76_TM_ATTR_TX_COUNT]);
@@ -350,12 +366,21 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_RATE_LDPC], &td->tx_rate_ldpc, 0, 1) ||
mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_RATE_STBC], &td->tx_rate_stbc, 0, 1) ||
mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_LTF], &td->tx_ltf, 0, 2) ||
- mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_ANTENNA], &td->tx_antenna_mask, 1,
- phy->antenna_mask) ||
+ mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_ANTENNA], &td->tx_antenna_mask,
+ 1 << (ext_phy * 2), phy->antenna_mask << (ext_phy * 2)) ||
+ mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_SPE_IDX], &td->tx_spe_idx, 0, 27) ||
+ mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_DUTY_CYCLE],
+ &td->tx_duty_cycle, 0, 99) ||
mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_POWER_CONTROL],
&td->tx_power_control, 0, 1))
goto out;
+ if (tb[MT76_TM_ATTR_TX_IPG])
+ td->tx_ipg = nla_get_u32(tb[MT76_TM_ATTR_TX_IPG]);
+
+ if (tb[MT76_TM_ATTR_TX_TIME])
+ td->tx_time = nla_get_u32(tb[MT76_TM_ATTR_TX_TIME]);
+
if (tb[MT76_TM_ATTR_FREQ_OFFSET])
td->freq_offset = nla_get_u32(tb[MT76_TM_ATTR_FREQ_OFFSET]);
@@ -382,7 +407,7 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
}
if (dev->test_ops->set_params) {
- err = dev->test_ops->set_params(dev, tb, state);
+ err = dev->test_ops->set_params(phy, tb, state);
if (err)
goto out;
}
@@ -393,7 +418,7 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
err = 0;
if (tb[MT76_TM_ATTR_STATE])
- err = mt76_testmode_set_state(dev, state);
+ err = mt76_testmode_set_state(phy, state);
out:
mutex_unlock(&dev->mutex);
@@ -403,9 +428,10 @@ out:
EXPORT_SYMBOL(mt76_testmode_cmd);
static int
-mt76_testmode_dump_stats(struct mt76_dev *dev, struct sk_buff *msg)
+mt76_testmode_dump_stats(struct mt76_phy *phy, struct sk_buff *msg)
{
- struct mt76_testmode_data *td = &dev->test;
+ struct mt76_testmode_data *td = &phy->test;
+ struct mt76_dev *dev = phy->dev;
u64 rx_packets = 0;
u64 rx_fcs_error = 0;
int i;
@@ -425,7 +451,7 @@ mt76_testmode_dump_stats(struct mt76_dev *dev, struct sk_buff *msg)
return -EMSGSIZE;
if (dev->test_ops->dump_stats)
- return dev->test_ops->dump_stats(dev, msg);
+ return dev->test_ops->dump_stats(phy, msg);
return 0;
}
@@ -435,7 +461,7 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
{
struct mt76_phy *phy = hw->priv;
struct mt76_dev *dev = phy->dev;
- struct mt76_testmode_data *td = &dev->test;
+ struct mt76_testmode_data *td = &phy->test;
struct nlattr *tb[NUM_MT76_TM_ATTRS] = {};
int err = 0;
void *a;
@@ -461,22 +487,22 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
a = nla_nest_start(msg, MT76_TM_ATTR_STATS);
if (a) {
- err = mt76_testmode_dump_stats(dev, msg);
+ err = mt76_testmode_dump_stats(phy, msg);
nla_nest_end(msg, a);
}
goto out;
}
- mt76_testmode_init_defaults(dev);
+ mt76_testmode_init_defaults(phy);
err = -EMSGSIZE;
if (nla_put_u32(msg, MT76_TM_ATTR_STATE, td->state))
goto out;
- if (td->mtd_name &&
- (nla_put_string(msg, MT76_TM_ATTR_MTD_PART, td->mtd_name) ||
- nla_put_u32(msg, MT76_TM_ATTR_MTD_OFFSET, td->mtd_offset)))
+ if (dev->test_mtd.name &&
+ (nla_put_string(msg, MT76_TM_ATTR_MTD_PART, dev->test_mtd.name) ||
+ nla_put_u32(msg, MT76_TM_ATTR_MTD_OFFSET, dev->test_mtd.offset)))
goto out;
if (nla_put_u32(msg, MT76_TM_ATTR_TX_COUNT, td->tx_count) ||
@@ -491,6 +517,14 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
nla_put_u8(msg, MT76_TM_ATTR_TX_LTF, td->tx_ltf)) ||
(mt76_testmode_param_present(td, MT76_TM_ATTR_TX_ANTENNA) &&
nla_put_u8(msg, MT76_TM_ATTR_TX_ANTENNA, td->tx_antenna_mask)) ||
+ (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_SPE_IDX) &&
+ nla_put_u8(msg, MT76_TM_ATTR_TX_SPE_IDX, td->tx_spe_idx)) ||
+ (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_DUTY_CYCLE) &&
+ nla_put_u8(msg, MT76_TM_ATTR_TX_DUTY_CYCLE, td->tx_duty_cycle)) ||
+ (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_IPG) &&
+ nla_put_u32(msg, MT76_TM_ATTR_TX_IPG, td->tx_ipg)) ||
+ (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_TIME) &&
+ nla_put_u32(msg, MT76_TM_ATTR_TX_TIME, td->tx_time)) ||
(mt76_testmode_param_present(td, MT76_TM_ATTR_TX_POWER_CONTROL) &&
nla_put_u8(msg, MT76_TM_ATTR_TX_POWER_CONTROL, td->tx_power_control)) ||
(mt76_testmode_param_present(td, MT76_TM_ATTR_FREQ_OFFSET) &&