Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: ISC
0002 /*
0003  * Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
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 /* Returns true if callee consumes the skb and the skb should be discarded.
0029  * Returns false if skb is not used. Does not sleep.
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     /* Only testmode.c should be handling events from utf firmware,
0051      * otherwise all sort of problems will arise as mac80211 operations
0052      * are not initialised.
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     /* load utf firmware image */
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     /* We didn't find FW UTF API 1 ("utf.bin") does not advertise
0160      * firmware features. Do an ugly hack where we force the firmware
0161      * features to match with 10.1 branch so that wmi.c will use the
0162      * correct WMI interface.
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     /* Use the same board data file as the normal firmware uses (but
0212      * it's still "owned" by normal_mode_fw so we shouldn't free it.
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     /* start utf only when the driver is not in use  */
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         /* utf image is already downloaded, it shouldn't be */
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         /* utf firmware is not running, nothing to do */
0462         goto out;
0463     }
0464 
0465     __ath10k_tm_cmd_utf_stop(ar);
0466 
0467 out:
0468     mutex_unlock(&ar->conf_mutex);
0469 }