1 // SPDX-License-Identifier: ISC
6 enum mt7921_testmode_attr
{
14 MT7921_TM_ATTR_MAX
= NUM_MT7921_TM_ATTRS
- 1,
17 struct mt7921_tm_cmd
{
23 struct mt7921_tm_evt
{
28 static const struct nla_policy mt7921_tm_policy
[NUM_MT7921_TM_ATTRS
] = {
29 [MT7921_TM_ATTR_SET
] = NLA_POLICY_EXACT_LEN(sizeof(struct mt7921_tm_cmd
)),
30 [MT7921_TM_ATTR_QUERY
] = NLA_POLICY_EXACT_LEN(sizeof(struct mt7921_tm_cmd
)),
34 mt7921_tm_set(struct mt792x_dev
*dev
, struct mt7921_tm_cmd
*req
)
36 struct mt7921_rftest_cmd cmd
= {
37 .action
= req
->action
,
38 .param0
= cpu_to_le32(req
->param0
),
39 .param1
= cpu_to_le32(req
->param1
),
41 bool testmode
= false, normal
= false;
42 struct mt76_connac_pm
*pm
= &dev
->pm
;
43 struct mt76_phy
*phy
= &dev
->mphy
;
46 mutex_lock(&dev
->mt76
.mutex
);
48 if (req
->action
== TM_SWITCH_MODE
) {
49 if (req
->param0
== MT7921_TM_NORMAL
)
56 /* Make sure testmode running on full power mode */
58 cancel_delayed_work_sync(&pm
->ps_work
);
59 cancel_work_sync(&pm
->wake_work
);
60 __mt792x_mcu_drv_pmctrl(dev
);
62 phy
->test
.state
= MT76_TM_STATE_ON
;
65 if (!mt76_testmode_enabled(phy
))
68 ret
= mt76_mcu_send_msg(&dev
->mt76
, MCU_CE_CMD(TEST_CTRL
), &cmd
,
74 /* Switch back to the normal world */
75 phy
->test
.state
= MT76_TM_STATE_OFF
;
79 mutex_unlock(&dev
->mt76
.mutex
);
85 mt7921_tm_query(struct mt792x_dev
*dev
, struct mt7921_tm_cmd
*req
,
86 struct mt7921_tm_evt
*evt_resp
)
88 struct mt7921_rftest_cmd cmd
= {
89 .action
= req
->action
,
90 .param0
= cpu_to_le32(req
->param0
),
91 .param1
= cpu_to_le32(req
->param1
),
93 struct mt7921_rftest_evt
*evt
;
97 ret
= mt76_mcu_send_and_get_msg(&dev
->mt76
, MCU_CE_CMD(TEST_CTRL
),
98 &cmd
, sizeof(cmd
), true, &skb
);
102 evt
= (struct mt7921_rftest_evt
*)skb
->data
;
103 evt_resp
->param0
= le32_to_cpu(evt
->param0
);
104 evt_resp
->param1
= le32_to_cpu(evt
->param1
);
111 int mt7921_testmode_cmd(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
,
114 struct nlattr
*tb
[NUM_MT76_TM_ATTRS
];
115 struct mt76_phy
*mphy
= hw
->priv
;
116 struct mt792x_phy
*phy
= mphy
->priv
;
119 if (!test_bit(MT76_STATE_RUNNING
, &mphy
->state
) ||
120 !(hw
->conf
.flags
& IEEE80211_CONF_MONITOR
))
123 err
= nla_parse_deprecated(tb
, MT76_TM_ATTR_MAX
, data
, len
,
124 mt76_tm_policy
, NULL
);
128 if (tb
[MT76_TM_ATTR_DRV_DATA
]) {
129 struct nlattr
*drv_tb
[NUM_MT7921_TM_ATTRS
], *data
;
132 data
= tb
[MT76_TM_ATTR_DRV_DATA
];
133 ret
= nla_parse_nested_deprecated(drv_tb
,
135 data
, mt7921_tm_policy
,
140 data
= drv_tb
[MT7921_TM_ATTR_SET
];
142 return mt7921_tm_set(phy
->dev
, nla_data(data
));
148 int mt7921_testmode_dump(struct ieee80211_hw
*hw
, struct sk_buff
*msg
,
149 struct netlink_callback
*cb
, void *data
, int len
)
151 struct nlattr
*tb
[NUM_MT76_TM_ATTRS
];
152 struct mt76_phy
*mphy
= hw
->priv
;
153 struct mt792x_phy
*phy
= mphy
->priv
;
156 if (!test_bit(MT76_STATE_RUNNING
, &mphy
->state
) ||
157 !(hw
->conf
.flags
& IEEE80211_CONF_MONITOR
) ||
158 !mt76_testmode_enabled(mphy
))
161 if (cb
->args
[2]++ > 0)
164 err
= nla_parse_deprecated(tb
, MT76_TM_ATTR_MAX
, data
, len
,
165 mt76_tm_policy
, NULL
);
169 if (tb
[MT76_TM_ATTR_DRV_DATA
]) {
170 struct nlattr
*drv_tb
[NUM_MT7921_TM_ATTRS
], *data
;
173 data
= tb
[MT76_TM_ATTR_DRV_DATA
];
174 ret
= nla_parse_nested_deprecated(drv_tb
,
176 data
, mt7921_tm_policy
,
181 data
= drv_tb
[MT7921_TM_ATTR_QUERY
];
183 struct mt7921_tm_evt evt_resp
;
185 err
= mt7921_tm_query(phy
->dev
, nla_data(data
),
190 return nla_put(msg
, MT7921_TM_ATTR_RSP
,
191 sizeof(evt_resp
), &evt_resp
);