Path: blob/main/sys/contrib/dev/mediatek/mt76/mt7921/testmode.c
48525 views
// SPDX-License-Identifier: ISC12#include "mt7921.h"3#include "mcu.h"45enum mt7921_testmode_attr {6MT7921_TM_ATTR_UNSPEC,7MT7921_TM_ATTR_SET,8MT7921_TM_ATTR_QUERY,9MT7921_TM_ATTR_RSP,1011/* keep last */12NUM_MT7921_TM_ATTRS,13MT7921_TM_ATTR_MAX = NUM_MT7921_TM_ATTRS - 1,14};1516struct mt7921_tm_cmd {17u8 action;18u32 param0;19u32 param1;20};2122struct mt7921_tm_evt {23u32 param0;24u32 param1;25};2627static const struct nla_policy mt7921_tm_policy[NUM_MT7921_TM_ATTRS] = {28[MT7921_TM_ATTR_SET] = NLA_POLICY_EXACT_LEN(sizeof(struct mt7921_tm_cmd)),29[MT7921_TM_ATTR_QUERY] = NLA_POLICY_EXACT_LEN(sizeof(struct mt7921_tm_cmd)),30};3132static int33mt7921_tm_set(struct mt792x_dev *dev, struct mt7921_tm_cmd *req)34{35struct mt7921_rftest_cmd cmd = {36.action = req->action,37.param0 = cpu_to_le32(req->param0),38.param1 = cpu_to_le32(req->param1),39};40bool testmode = false, normal = false;41struct mt76_connac_pm *pm = &dev->pm;42struct mt76_phy *phy = &dev->mphy;43int ret = -ENOTCONN;4445mutex_lock(&dev->mt76.mutex);4647if (req->action == TM_SWITCH_MODE) {48if (req->param0 == MT7921_TM_NORMAL)49normal = true;50else51testmode = true;52}5354if (testmode) {55/* Make sure testmode running on full power mode */56pm->enable = false;57cancel_delayed_work_sync(&pm->ps_work);58cancel_work_sync(&pm->wake_work);59__mt792x_mcu_drv_pmctrl(dev);6061phy->test.state = MT76_TM_STATE_ON;62}6364if (!mt76_testmode_enabled(phy))65goto out;6667ret = mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(TEST_CTRL), &cmd,68sizeof(cmd), false);69if (ret)70goto out;7172if (normal) {73/* Switch back to the normal world */74phy->test.state = MT76_TM_STATE_OFF;75pm->enable = true;76}77out:78mutex_unlock(&dev->mt76.mutex);7980return ret;81}8283static int84mt7921_tm_query(struct mt792x_dev *dev, struct mt7921_tm_cmd *req,85struct mt7921_tm_evt *evt_resp)86{87struct mt7921_rftest_cmd cmd = {88.action = req->action,89.param0 = cpu_to_le32(req->param0),90.param1 = cpu_to_le32(req->param1),91};92struct mt7921_rftest_evt *evt;93struct sk_buff *skb;94int ret;9596ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_CE_CMD(TEST_CTRL),97&cmd, sizeof(cmd), true, &skb);98if (ret)99goto out;100101evt = (struct mt7921_rftest_evt *)skb->data;102evt_resp->param0 = le32_to_cpu(evt->param0);103evt_resp->param1 = le32_to_cpu(evt->param1);104out:105dev_kfree_skb(skb);106107return ret;108}109110int mt7921_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,111void *data, int len)112{113struct nlattr *tb[NUM_MT76_TM_ATTRS];114struct mt76_phy *mphy = hw->priv;115struct mt792x_phy *phy = mphy->priv;116int err;117118if (!test_bit(MT76_STATE_RUNNING, &mphy->state) ||119!(hw->conf.flags & IEEE80211_CONF_MONITOR))120return -ENOTCONN;121122err = nla_parse_deprecated(tb, MT76_TM_ATTR_MAX, data, len,123mt76_tm_policy, NULL);124if (err)125return err;126127if (tb[MT76_TM_ATTR_DRV_DATA]) {128struct nlattr *drv_tb[NUM_MT7921_TM_ATTRS], *data;129int ret;130131data = tb[MT76_TM_ATTR_DRV_DATA];132ret = nla_parse_nested_deprecated(drv_tb,133MT7921_TM_ATTR_MAX,134data, mt7921_tm_policy,135NULL);136if (ret)137return ret;138139data = drv_tb[MT7921_TM_ATTR_SET];140if (data)141return mt7921_tm_set(phy->dev, nla_data(data));142}143144return -EINVAL;145}146147int mt7921_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,148struct netlink_callback *cb, void *data, int len)149{150struct nlattr *tb[NUM_MT76_TM_ATTRS];151struct mt76_phy *mphy = hw->priv;152struct mt792x_phy *phy = mphy->priv;153int err;154155if (!test_bit(MT76_STATE_RUNNING, &mphy->state) ||156!(hw->conf.flags & IEEE80211_CONF_MONITOR) ||157!mt76_testmode_enabled(mphy))158return -ENOTCONN;159160if (cb->args[2]++ > 0)161return -ENOENT;162163err = nla_parse_deprecated(tb, MT76_TM_ATTR_MAX, data, len,164mt76_tm_policy, NULL);165if (err)166return err;167168if (tb[MT76_TM_ATTR_DRV_DATA]) {169struct nlattr *drv_tb[NUM_MT7921_TM_ATTRS], *data;170int ret;171172data = tb[MT76_TM_ATTR_DRV_DATA];173ret = nla_parse_nested_deprecated(drv_tb,174MT7921_TM_ATTR_MAX,175data, mt7921_tm_policy,176NULL);177if (ret)178return ret;179180data = drv_tb[MT7921_TM_ATTR_QUERY];181if (data) {182struct mt7921_tm_evt evt_resp;183184err = mt7921_tm_query(phy->dev, nla_data(data),185&evt_resp);186if (err)187return err;188189return nla_put(msg, MT7921_TM_ATTR_RSP,190sizeof(evt_resp), &evt_resp);191}192}193194return -EINVAL;195}196197198