0001
0002
0003
0004
0005
0006 #include "testmode.h"
0007
0008 #include <net/netlink.h>
0009 #include <linux/firmware.h>
0010
0011 #include "debug.h"
0012 #include "wmi.h"
0013 #include "hif.h"
0014 #include "hw.h"
0015 #include "core.h"
0016
0017 #include "testmode_i.h"
0018
0019 static const struct nla_policy ath10k_tm_policy[ATH10K_TM_ATTR_MAX + 1] = {
0020 [ATH10K_TM_ATTR_CMD] = { .type = NLA_U32 },
0021 [ATH10K_TM_ATTR_DATA] = { .type = NLA_BINARY,
0022 .len = ATH10K_TM_DATA_MAX_LEN },
0023 [ATH10K_TM_ATTR_WMI_CMDID] = { .type = NLA_U32 },
0024 [ATH10K_TM_ATTR_VERSION_MAJOR] = { .type = NLA_U32 },
0025 [ATH10K_TM_ATTR_VERSION_MINOR] = { .type = NLA_U32 },
0026 };
0027
0028
0029
0030
0031 bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id, struct sk_buff *skb)
0032 {
0033 struct sk_buff *nl_skb;
0034 bool consumed;
0035 int ret;
0036
0037 ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
0038 "testmode event wmi cmd_id %d skb %pK skb->len %d\n",
0039 cmd_id, skb, skb->len);
0040
0041 ath10k_dbg_dump(ar, ATH10K_DBG_TESTMODE, NULL, "", skb->data, skb->len);
0042
0043 spin_lock_bh(&ar->data_lock);
0044
0045 if (!ar->testmode.utf_monitor) {
0046 consumed = false;
0047 goto out;
0048 }
0049
0050
0051
0052
0053
0054 consumed = true;
0055
0056 nl_skb = cfg80211_testmode_alloc_event_skb(ar->hw->wiphy,
0057 2 * sizeof(u32) + skb->len,
0058 GFP_ATOMIC);
0059 if (!nl_skb) {
0060 ath10k_warn(ar,
0061 "failed to allocate skb for testmode wmi event\n");
0062 goto out;
0063 }
0064
0065 ret = nla_put_u32(nl_skb, ATH10K_TM_ATTR_CMD, ATH10K_TM_CMD_WMI);
0066 if (ret) {
0067 ath10k_warn(ar,
0068 "failed to put testmode wmi event cmd attribute: %d\n",
0069 ret);
0070 kfree_skb(nl_skb);
0071 goto out;
0072 }
0073
0074 ret = nla_put_u32(nl_skb, ATH10K_TM_ATTR_WMI_CMDID, cmd_id);
0075 if (ret) {
0076 ath10k_warn(ar,
0077 "failed to put testmode wmi event cmd_id: %d\n",
0078 ret);
0079 kfree_skb(nl_skb);
0080 goto out;
0081 }
0082
0083 ret = nla_put(nl_skb, ATH10K_TM_ATTR_DATA, skb->len, skb->data);
0084 if (ret) {
0085 ath10k_warn(ar,
0086 "failed to copy skb to testmode wmi event: %d\n",
0087 ret);
0088 kfree_skb(nl_skb);
0089 goto out;
0090 }
0091
0092 cfg80211_testmode_event(nl_skb, GFP_ATOMIC);
0093
0094 out:
0095 spin_unlock_bh(&ar->data_lock);
0096
0097 return consumed;
0098 }
0099
0100 static int ath10k_tm_cmd_get_version(struct ath10k *ar, struct nlattr *tb[])
0101 {
0102 struct sk_buff *skb;
0103 int ret;
0104
0105 ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
0106 "testmode cmd get version_major %d version_minor %d\n",
0107 ATH10K_TESTMODE_VERSION_MAJOR,
0108 ATH10K_TESTMODE_VERSION_MINOR);
0109
0110 skb = cfg80211_testmode_alloc_reply_skb(ar->hw->wiphy,
0111 nla_total_size(sizeof(u32)));
0112 if (!skb)
0113 return -ENOMEM;
0114
0115 ret = nla_put_u32(skb, ATH10K_TM_ATTR_VERSION_MAJOR,
0116 ATH10K_TESTMODE_VERSION_MAJOR);
0117 if (ret) {
0118 kfree_skb(skb);
0119 return ret;
0120 }
0121
0122 ret = nla_put_u32(skb, ATH10K_TM_ATTR_VERSION_MINOR,
0123 ATH10K_TESTMODE_VERSION_MINOR);
0124 if (ret) {
0125 kfree_skb(skb);
0126 return ret;
0127 }
0128
0129 ret = nla_put_u32(skb, ATH10K_TM_ATTR_WMI_OP_VERSION,
0130 ar->normal_mode_fw.fw_file.wmi_op_version);
0131 if (ret) {
0132 kfree_skb(skb);
0133 return ret;
0134 }
0135
0136 return cfg80211_testmode_reply(skb);
0137 }
0138
0139 static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar,
0140 struct ath10k_fw_file *fw_file)
0141 {
0142 char filename[100];
0143 int ret;
0144
0145 snprintf(filename, sizeof(filename), "%s/%s",
0146 ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE);
0147
0148
0149 ret = firmware_request_nowarn(&fw_file->firmware, filename, ar->dev);
0150 ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode fw request '%s': %d\n",
0151 filename, ret);
0152
0153 if (ret) {
0154 ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n",
0155 filename, ret);
0156 return ret;
0157 }
0158
0159
0160
0161
0162
0163
0164
0165 fw_file->wmi_op_version = ATH10K_FW_WMI_OP_VERSION_10_1;
0166 fw_file->htt_op_version = ATH10K_FW_HTT_OP_VERSION_10_1;
0167 fw_file->firmware_data = fw_file->firmware->data;
0168 fw_file->firmware_len = fw_file->firmware->size;
0169
0170 return 0;
0171 }
0172
0173 static int ath10k_tm_fetch_firmware(struct ath10k *ar)
0174 {
0175 struct ath10k_fw_components *utf_mode_fw;
0176 int ret;
0177 char fw_name[100];
0178 int fw_api2 = 2;
0179
0180 switch (ar->hif.bus) {
0181 case ATH10K_BUS_SDIO:
0182 case ATH10K_BUS_USB:
0183 scnprintf(fw_name, sizeof(fw_name), "%s-%s-%d.bin",
0184 ATH10K_FW_UTF_FILE_BASE, ath10k_bus_str(ar->hif.bus),
0185 fw_api2);
0186 break;
0187 default:
0188 scnprintf(fw_name, sizeof(fw_name), "%s-%d.bin",
0189 ATH10K_FW_UTF_FILE_BASE, fw_api2);
0190 break;
0191 }
0192
0193 ret = ath10k_core_fetch_firmware_api_n(ar, fw_name,
0194 &ar->testmode.utf_mode_fw.fw_file);
0195 if (ret == 0) {
0196 ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using fw utf api 2");
0197 goto out;
0198 }
0199
0200 ret = ath10k_tm_fetch_utf_firmware_api_1(ar, &ar->testmode.utf_mode_fw.fw_file);
0201 if (ret) {
0202 ath10k_err(ar, "failed to fetch utf firmware binary: %d", ret);
0203 return ret;
0204 }
0205
0206 ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using utf api 1");
0207
0208 out:
0209 utf_mode_fw = &ar->testmode.utf_mode_fw;
0210
0211
0212
0213
0214 utf_mode_fw->board_data = ar->normal_mode_fw.board_data;
0215 utf_mode_fw->board_len = ar->normal_mode_fw.board_len;
0216
0217 if (!utf_mode_fw->fw_file.otp_data) {
0218 ath10k_info(ar, "utf.bin didn't contain otp binary, taking it from the normal mode firmware");
0219 utf_mode_fw->fw_file.otp_data = ar->normal_mode_fw.fw_file.otp_data;
0220 utf_mode_fw->fw_file.otp_len = ar->normal_mode_fw.fw_file.otp_len;
0221 }
0222
0223 return 0;
0224 }
0225
0226 static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
0227 {
0228 const char *ver;
0229 int ret;
0230
0231 ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf start\n");
0232
0233 mutex_lock(&ar->conf_mutex);
0234
0235 if (ar->state == ATH10K_STATE_UTF) {
0236 ret = -EALREADY;
0237 goto err;
0238 }
0239
0240
0241 if (ar->state != ATH10K_STATE_OFF) {
0242 ret = -EBUSY;
0243 goto err;
0244 }
0245
0246 if (WARN_ON(ar->testmode.utf_mode_fw.fw_file.firmware != NULL)) {
0247
0248 ret = -EEXIST;
0249 goto err;
0250 }
0251
0252 ret = ath10k_tm_fetch_firmware(ar);
0253 if (ret) {
0254 ath10k_err(ar, "failed to fetch UTF firmware: %d", ret);
0255 goto err;
0256 }
0257
0258 if (ar->testmode.utf_mode_fw.fw_file.codeswap_data &&
0259 ar->testmode.utf_mode_fw.fw_file.codeswap_len) {
0260 ret = ath10k_swap_code_seg_init(ar,
0261 &ar->testmode.utf_mode_fw.fw_file);
0262 if (ret) {
0263 ath10k_warn(ar,
0264 "failed to init utf code swap segment: %d\n",
0265 ret);
0266 goto err_release_utf_mode_fw;
0267 }
0268 }
0269
0270 spin_lock_bh(&ar->data_lock);
0271 ar->testmode.utf_monitor = true;
0272 spin_unlock_bh(&ar->data_lock);
0273
0274 ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode wmi version %d\n",
0275 ar->testmode.utf_mode_fw.fw_file.wmi_op_version);
0276
0277 ret = ath10k_hif_power_up(ar, ATH10K_FIRMWARE_MODE_UTF);
0278 if (ret) {
0279 ath10k_err(ar, "failed to power up hif (testmode): %d\n", ret);
0280 ar->state = ATH10K_STATE_OFF;
0281 goto err_release_utf_mode_fw;
0282 }
0283
0284 ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_UTF,
0285 &ar->testmode.utf_mode_fw);
0286 if (ret) {
0287 ath10k_err(ar, "failed to start core (testmode): %d\n", ret);
0288 ar->state = ATH10K_STATE_OFF;
0289 goto err_power_down;
0290 }
0291
0292 ar->state = ATH10K_STATE_UTF;
0293
0294 if (strlen(ar->testmode.utf_mode_fw.fw_file.fw_version) > 0)
0295 ver = ar->testmode.utf_mode_fw.fw_file.fw_version;
0296 else
0297 ver = "API 1";
0298
0299 ath10k_info(ar, "UTF firmware %s started\n", ver);
0300
0301 mutex_unlock(&ar->conf_mutex);
0302
0303 return 0;
0304
0305 err_power_down:
0306 ath10k_hif_power_down(ar);
0307
0308 err_release_utf_mode_fw:
0309 if (ar->testmode.utf_mode_fw.fw_file.codeswap_data &&
0310 ar->testmode.utf_mode_fw.fw_file.codeswap_len)
0311 ath10k_swap_code_seg_release(ar,
0312 &ar->testmode.utf_mode_fw.fw_file);
0313
0314 release_firmware(ar->testmode.utf_mode_fw.fw_file.firmware);
0315 ar->testmode.utf_mode_fw.fw_file.firmware = NULL;
0316
0317 err:
0318 mutex_unlock(&ar->conf_mutex);
0319
0320 return ret;
0321 }
0322
0323 static void __ath10k_tm_cmd_utf_stop(struct ath10k *ar)
0324 {
0325 lockdep_assert_held(&ar->conf_mutex);
0326
0327 ath10k_core_stop(ar);
0328 ath10k_hif_power_down(ar);
0329
0330 spin_lock_bh(&ar->data_lock);
0331
0332 ar->testmode.utf_monitor = false;
0333
0334 spin_unlock_bh(&ar->data_lock);
0335
0336 if (ar->testmode.utf_mode_fw.fw_file.codeswap_data &&
0337 ar->testmode.utf_mode_fw.fw_file.codeswap_len)
0338 ath10k_swap_code_seg_release(ar,
0339 &ar->testmode.utf_mode_fw.fw_file);
0340
0341 release_firmware(ar->testmode.utf_mode_fw.fw_file.firmware);
0342 ar->testmode.utf_mode_fw.fw_file.firmware = NULL;
0343
0344 ar->state = ATH10K_STATE_OFF;
0345 }
0346
0347 static int ath10k_tm_cmd_utf_stop(struct ath10k *ar, struct nlattr *tb[])
0348 {
0349 int ret;
0350
0351 ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf stop\n");
0352
0353 mutex_lock(&ar->conf_mutex);
0354
0355 if (ar->state != ATH10K_STATE_UTF) {
0356 ret = -ENETDOWN;
0357 goto out;
0358 }
0359
0360 __ath10k_tm_cmd_utf_stop(ar);
0361
0362 ret = 0;
0363
0364 ath10k_info(ar, "UTF firmware stopped\n");
0365
0366 out:
0367 mutex_unlock(&ar->conf_mutex);
0368 return ret;
0369 }
0370
0371 static int ath10k_tm_cmd_wmi(struct ath10k *ar, struct nlattr *tb[])
0372 {
0373 struct sk_buff *skb;
0374 int ret, buf_len;
0375 u32 cmd_id;
0376 void *buf;
0377
0378 mutex_lock(&ar->conf_mutex);
0379
0380 if (ar->state != ATH10K_STATE_UTF) {
0381 ret = -ENETDOWN;
0382 goto out;
0383 }
0384
0385 if (!tb[ATH10K_TM_ATTR_DATA]) {
0386 ret = -EINVAL;
0387 goto out;
0388 }
0389
0390 if (!tb[ATH10K_TM_ATTR_WMI_CMDID]) {
0391 ret = -EINVAL;
0392 goto out;
0393 }
0394
0395 buf = nla_data(tb[ATH10K_TM_ATTR_DATA]);
0396 buf_len = nla_len(tb[ATH10K_TM_ATTR_DATA]);
0397 cmd_id = nla_get_u32(tb[ATH10K_TM_ATTR_WMI_CMDID]);
0398
0399 ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
0400 "testmode cmd wmi cmd_id %d buf %pK buf_len %d\n",
0401 cmd_id, buf, buf_len);
0402
0403 ath10k_dbg_dump(ar, ATH10K_DBG_TESTMODE, NULL, "", buf, buf_len);
0404
0405 skb = ath10k_wmi_alloc_skb(ar, buf_len);
0406 if (!skb) {
0407 ret = -ENOMEM;
0408 goto out;
0409 }
0410
0411 memcpy(skb->data, buf, buf_len);
0412
0413 ret = ath10k_wmi_cmd_send(ar, skb, cmd_id);
0414 if (ret) {
0415 ath10k_warn(ar, "failed to transmit wmi command (testmode): %d\n",
0416 ret);
0417 goto out;
0418 }
0419
0420 ret = 0;
0421
0422 out:
0423 mutex_unlock(&ar->conf_mutex);
0424 return ret;
0425 }
0426
0427 int ath10k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
0428 void *data, int len)
0429 {
0430 struct ath10k *ar = hw->priv;
0431 struct nlattr *tb[ATH10K_TM_ATTR_MAX + 1];
0432 int ret;
0433
0434 ret = nla_parse_deprecated(tb, ATH10K_TM_ATTR_MAX, data, len,
0435 ath10k_tm_policy, NULL);
0436 if (ret)
0437 return ret;
0438
0439 if (!tb[ATH10K_TM_ATTR_CMD])
0440 return -EINVAL;
0441
0442 switch (nla_get_u32(tb[ATH10K_TM_ATTR_CMD])) {
0443 case ATH10K_TM_CMD_GET_VERSION:
0444 return ath10k_tm_cmd_get_version(ar, tb);
0445 case ATH10K_TM_CMD_UTF_START:
0446 return ath10k_tm_cmd_utf_start(ar, tb);
0447 case ATH10K_TM_CMD_UTF_STOP:
0448 return ath10k_tm_cmd_utf_stop(ar, tb);
0449 case ATH10K_TM_CMD_WMI:
0450 return ath10k_tm_cmd_wmi(ar, tb);
0451 default:
0452 return -EOPNOTSUPP;
0453 }
0454 }
0455
0456 void ath10k_testmode_destroy(struct ath10k *ar)
0457 {
0458 mutex_lock(&ar->conf_mutex);
0459
0460 if (ar->state != ATH10K_STATE_UTF) {
0461
0462 goto out;
0463 }
0464
0465 __ath10k_tm_cmd_utf_stop(ar);
0466
0467 out:
0468 mutex_unlock(&ar->conf_mutex);
0469 }