Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
0002 /*
0003  * Copyright (C) 2012-2014, 2018-2021 Intel Corporation
0004  * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
0005  * Copyright (C) 2016-2017 Intel Deutschland GmbH
0006  */
0007 #include <linux/vmalloc.h>
0008 #include <linux/err.h>
0009 #include <linux/ieee80211.h>
0010 #include <linux/netdevice.h>
0011 
0012 #include "mvm.h"
0013 #include "sta.h"
0014 #include "iwl-io.h"
0015 #include "debugfs.h"
0016 #include "iwl-modparams.h"
0017 #include "fw/error-dump.h"
0018 
0019 static ssize_t iwl_dbgfs_ctdp_budget_read(struct file *file,
0020                       char __user *user_buf,
0021                       size_t count, loff_t *ppos)
0022 {
0023     struct iwl_mvm *mvm = file->private_data;
0024     char buf[16];
0025     int pos, budget;
0026 
0027     if (!iwl_mvm_is_ctdp_supported(mvm))
0028         return -EOPNOTSUPP;
0029 
0030     if (!iwl_mvm_firmware_running(mvm) ||
0031         mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
0032         return -EIO;
0033 
0034     mutex_lock(&mvm->mutex);
0035     budget = iwl_mvm_ctdp_command(mvm, CTDP_CMD_OPERATION_REPORT, 0);
0036     mutex_unlock(&mvm->mutex);
0037 
0038     if (budget < 0)
0039         return budget;
0040 
0041     pos = scnprintf(buf, sizeof(buf), "%d\n", budget);
0042 
0043     return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
0044 }
0045 
0046 static ssize_t iwl_dbgfs_stop_ctdp_write(struct iwl_mvm *mvm, char *buf,
0047                      size_t count, loff_t *ppos)
0048 {
0049     int ret;
0050 
0051     if (!iwl_mvm_is_ctdp_supported(mvm))
0052         return -EOPNOTSUPP;
0053 
0054     if (!iwl_mvm_firmware_running(mvm) ||
0055         mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
0056         return -EIO;
0057 
0058     mutex_lock(&mvm->mutex);
0059     ret = iwl_mvm_ctdp_command(mvm, CTDP_CMD_OPERATION_STOP, 0);
0060     mutex_unlock(&mvm->mutex);
0061 
0062     return ret ?: count;
0063 }
0064 
0065 static ssize_t iwl_dbgfs_force_ctkill_write(struct iwl_mvm *mvm, char *buf,
0066                         size_t count, loff_t *ppos)
0067 {
0068     if (!iwl_mvm_firmware_running(mvm) ||
0069         mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
0070         return -EIO;
0071 
0072     iwl_mvm_enter_ctkill(mvm);
0073 
0074     return count;
0075 }
0076 
0077 static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf,
0078                     size_t count, loff_t *ppos)
0079 {
0080     int ret;
0081     u32 flush_arg;
0082 
0083     if (!iwl_mvm_firmware_running(mvm) ||
0084         mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
0085         return -EIO;
0086 
0087     if (kstrtou32(buf, 0, &flush_arg))
0088         return -EINVAL;
0089 
0090     if (iwl_mvm_has_new_tx_api(mvm)) {
0091         IWL_DEBUG_TX_QUEUES(mvm,
0092                     "FLUSHING all tids queues on sta_id = %d\n",
0093                     flush_arg);
0094         mutex_lock(&mvm->mutex);
0095         ret = iwl_mvm_flush_sta_tids(mvm, flush_arg, 0xFFFF)
0096             ? : count;
0097         mutex_unlock(&mvm->mutex);
0098         return ret;
0099     }
0100 
0101     IWL_DEBUG_TX_QUEUES(mvm, "FLUSHING queues mask to flush = 0x%x\n",
0102                 flush_arg);
0103 
0104     mutex_lock(&mvm->mutex);
0105     ret =  iwl_mvm_flush_tx_path(mvm, flush_arg) ? : count;
0106     mutex_unlock(&mvm->mutex);
0107 
0108     return ret;
0109 }
0110 
0111 static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf,
0112                      size_t count, loff_t *ppos)
0113 {
0114     struct iwl_mvm_sta *mvmsta;
0115     int sta_id, drain, ret;
0116 
0117     if (!iwl_mvm_firmware_running(mvm) ||
0118         mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
0119         return -EIO;
0120 
0121     if (sscanf(buf, "%d %d", &sta_id, &drain) != 2)
0122         return -EINVAL;
0123     if (sta_id < 0 || sta_id >= mvm->fw->ucode_capa.num_stations)
0124         return -EINVAL;
0125     if (drain < 0 || drain > 1)
0126         return -EINVAL;
0127 
0128     mutex_lock(&mvm->mutex);
0129 
0130     mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
0131 
0132     if (!mvmsta)
0133         ret = -ENOENT;
0134     else
0135         ret = iwl_mvm_drain_sta(mvm, mvmsta, drain) ? : count;
0136 
0137     mutex_unlock(&mvm->mutex);
0138 
0139     return ret;
0140 }
0141 
0142 static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf,
0143                    size_t count, loff_t *ppos)
0144 {
0145     struct iwl_mvm *mvm = file->private_data;
0146     const struct fw_img *img;
0147     unsigned int ofs, len;
0148     size_t ret;
0149     u8 *ptr;
0150 
0151     if (!iwl_mvm_firmware_running(mvm))
0152         return -EINVAL;
0153 
0154     /* default is to dump the entire data segment */
0155     img = &mvm->fw->img[mvm->fwrt.cur_fw_img];
0156     ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
0157     len = img->sec[IWL_UCODE_SECTION_DATA].len;
0158 
0159     if (mvm->dbgfs_sram_len) {
0160         ofs = mvm->dbgfs_sram_offset;
0161         len = mvm->dbgfs_sram_len;
0162     }
0163 
0164     ptr = kzalloc(len, GFP_KERNEL);
0165     if (!ptr)
0166         return -ENOMEM;
0167 
0168     iwl_trans_read_mem_bytes(mvm->trans, ofs, ptr, len);
0169 
0170     ret = simple_read_from_buffer(user_buf, count, ppos, ptr, len);
0171 
0172     kfree(ptr);
0173 
0174     return ret;
0175 }
0176 
0177 static ssize_t iwl_dbgfs_sram_write(struct iwl_mvm *mvm, char *buf,
0178                     size_t count, loff_t *ppos)
0179 {
0180     const struct fw_img *img;
0181     u32 offset, len;
0182     u32 img_offset, img_len;
0183 
0184     if (!iwl_mvm_firmware_running(mvm))
0185         return -EINVAL;
0186 
0187     img = &mvm->fw->img[mvm->fwrt.cur_fw_img];
0188     img_offset = img->sec[IWL_UCODE_SECTION_DATA].offset;
0189     img_len = img->sec[IWL_UCODE_SECTION_DATA].len;
0190 
0191     if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
0192         if ((offset & 0x3) || (len & 0x3))
0193             return -EINVAL;
0194 
0195         if (offset + len > img_offset + img_len)
0196             return -EINVAL;
0197 
0198         mvm->dbgfs_sram_offset = offset;
0199         mvm->dbgfs_sram_len = len;
0200     } else {
0201         mvm->dbgfs_sram_offset = 0;
0202         mvm->dbgfs_sram_len = 0;
0203     }
0204 
0205     return count;
0206 }
0207 
0208 static ssize_t iwl_dbgfs_set_nic_temperature_read(struct file *file,
0209                           char __user *user_buf,
0210                           size_t count, loff_t *ppos)
0211 {
0212     struct iwl_mvm *mvm = file->private_data;
0213     char buf[16];
0214     int pos;
0215 
0216     if (!mvm->temperature_test)
0217         pos = scnprintf(buf , sizeof(buf), "disabled\n");
0218     else
0219         pos = scnprintf(buf , sizeof(buf), "%d\n", mvm->temperature);
0220 
0221     return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
0222 }
0223 
0224 /*
0225  * Set NIC Temperature
0226  * Cause the driver to ignore the actual NIC temperature reported by the FW
0227  * Enable: any value between IWL_MVM_DEBUG_SET_TEMPERATURE_MIN -
0228  * IWL_MVM_DEBUG_SET_TEMPERATURE_MAX
0229  * Disable: IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE
0230  */
0231 static ssize_t iwl_dbgfs_set_nic_temperature_write(struct iwl_mvm *mvm,
0232                            char *buf, size_t count,
0233                            loff_t *ppos)
0234 {
0235     int temperature;
0236 
0237     if (!iwl_mvm_firmware_running(mvm) && !mvm->temperature_test)
0238         return -EIO;
0239 
0240     if (kstrtoint(buf, 10, &temperature))
0241         return -EINVAL;
0242     /* not a legal temperature */
0243     if ((temperature > IWL_MVM_DEBUG_SET_TEMPERATURE_MAX &&
0244          temperature != IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE) ||
0245         temperature < IWL_MVM_DEBUG_SET_TEMPERATURE_MIN)
0246         return -EINVAL;
0247 
0248     mutex_lock(&mvm->mutex);
0249     if (temperature == IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE) {
0250         if (!mvm->temperature_test)
0251             goto out;
0252 
0253         mvm->temperature_test = false;
0254         /* Since we can't read the temp while awake, just set
0255          * it to zero until we get the next RX stats from the
0256          * firmware.
0257          */
0258         mvm->temperature = 0;
0259     } else {
0260         mvm->temperature_test = true;
0261         mvm->temperature = temperature;
0262     }
0263     IWL_DEBUG_TEMP(mvm, "%sabling debug set temperature (temp = %d)\n",
0264                mvm->temperature_test ? "En" : "Dis" ,
0265                mvm->temperature);
0266     /* handle the temperature change */
0267     iwl_mvm_tt_handler(mvm);
0268 
0269 out:
0270     mutex_unlock(&mvm->mutex);
0271 
0272     return count;
0273 }
0274 
0275 static ssize_t iwl_dbgfs_nic_temp_read(struct file *file,
0276                        char __user *user_buf,
0277                        size_t count, loff_t *ppos)
0278 {
0279     struct iwl_mvm *mvm = file->private_data;
0280     char buf[16];
0281     int pos, ret;
0282     s32 temp;
0283 
0284     if (!iwl_mvm_firmware_running(mvm))
0285         return -EIO;
0286 
0287     mutex_lock(&mvm->mutex);
0288     ret = iwl_mvm_get_temp(mvm, &temp);
0289     mutex_unlock(&mvm->mutex);
0290 
0291     if (ret)
0292         return -EIO;
0293 
0294     pos = scnprintf(buf , sizeof(buf), "%d\n", temp);
0295 
0296     return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
0297 }
0298 
0299 #ifdef CONFIG_ACPI
0300 static ssize_t iwl_dbgfs_sar_geo_profile_read(struct file *file,
0301                           char __user *user_buf,
0302                           size_t count, loff_t *ppos)
0303 {
0304     struct iwl_mvm *mvm = file->private_data;
0305     char buf[256];
0306     int pos = 0;
0307     int bufsz = sizeof(buf);
0308     int tbl_idx;
0309 
0310     if (!iwl_mvm_firmware_running(mvm))
0311         return -EIO;
0312 
0313     mutex_lock(&mvm->mutex);
0314     tbl_idx = iwl_mvm_get_sar_geo_profile(mvm);
0315     if (tbl_idx < 0) {
0316         mutex_unlock(&mvm->mutex);
0317         return tbl_idx;
0318     }
0319 
0320     if (!tbl_idx) {
0321         pos = scnprintf(buf, bufsz,
0322                 "SAR geographic profile disabled\n");
0323     } else {
0324         pos += scnprintf(buf + pos, bufsz - pos,
0325                  "Use geographic profile %d\n", tbl_idx);
0326         pos += scnprintf(buf + pos, bufsz - pos,
0327                  "2.4GHz:\n\tChain A offset: %hhu dBm\n\tChain B offset: %hhu dBm\n\tmax tx power: %hhu dBm\n",
0328                  mvm->fwrt.geo_profiles[tbl_idx - 1].bands[0].chains[0],
0329                  mvm->fwrt.geo_profiles[tbl_idx - 1].bands[0].chains[1],
0330                  mvm->fwrt.geo_profiles[tbl_idx - 1].bands[0].max);
0331         pos += scnprintf(buf + pos, bufsz - pos,
0332                  "5.2GHz:\n\tChain A offset: %hhu dBm\n\tChain B offset: %hhu dBm\n\tmax tx power: %hhu dBm\n",
0333                  mvm->fwrt.geo_profiles[tbl_idx - 1].bands[1].chains[0],
0334                  mvm->fwrt.geo_profiles[tbl_idx - 1].bands[1].chains[1],
0335                  mvm->fwrt.geo_profiles[tbl_idx - 1].bands[1].max);
0336     }
0337     mutex_unlock(&mvm->mutex);
0338 
0339     return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
0340 }
0341 #endif
0342 
0343 static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
0344                        size_t count, loff_t *ppos)
0345 {
0346     struct iwl_mvm *mvm = file->private_data;
0347     struct ieee80211_sta *sta;
0348     char buf[400];
0349     int i, pos = 0, bufsz = sizeof(buf);
0350 
0351     mutex_lock(&mvm->mutex);
0352 
0353     for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) {
0354         pos += scnprintf(buf + pos, bufsz - pos, "%.2d: ", i);
0355         sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
0356                         lockdep_is_held(&mvm->mutex));
0357         if (!sta)
0358             pos += scnprintf(buf + pos, bufsz - pos, "N/A\n");
0359         else if (IS_ERR(sta))
0360             pos += scnprintf(buf + pos, bufsz - pos, "%ld\n",
0361                      PTR_ERR(sta));
0362         else
0363             pos += scnprintf(buf + pos, bufsz - pos, "%pM\n",
0364                      sta->addr);
0365     }
0366 
0367     mutex_unlock(&mvm->mutex);
0368 
0369     return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
0370 }
0371 
0372 static ssize_t iwl_dbgfs_rs_data_read(struct file *file, char __user *user_buf,
0373                       size_t count, loff_t *ppos)
0374 {
0375     struct ieee80211_sta *sta = file->private_data;
0376     struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
0377     struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->lq_sta.rs_fw;
0378     struct iwl_mvm *mvm = lq_sta->pers.drv;
0379     static const size_t bufsz = 2048;
0380     char *buff;
0381     int desc = 0;
0382     ssize_t ret;
0383 
0384     buff = kmalloc(bufsz, GFP_KERNEL);
0385     if (!buff)
0386         return -ENOMEM;
0387 
0388     mutex_lock(&mvm->mutex);
0389 
0390     desc += scnprintf(buff + desc, bufsz - desc, "sta_id %d\n",
0391               lq_sta->pers.sta_id);
0392     desc += scnprintf(buff + desc, bufsz - desc,
0393               "fixed rate 0x%X\n",
0394               lq_sta->pers.dbg_fixed_rate);
0395     desc += scnprintf(buff + desc, bufsz - desc,
0396               "A-MPDU size limit %d\n",
0397               lq_sta->pers.dbg_agg_frame_count_lim);
0398     desc += scnprintf(buff + desc, bufsz - desc,
0399               "valid_tx_ant %s%s\n",
0400         (iwl_mvm_get_valid_tx_ant(mvm) & ANT_A) ? "ANT_A," : "",
0401         (iwl_mvm_get_valid_tx_ant(mvm) & ANT_B) ? "ANT_B," : "");
0402     desc += scnprintf(buff + desc, bufsz - desc,
0403               "last tx rate=0x%X ",
0404               lq_sta->last_rate_n_flags);
0405 
0406     desc += rs_pretty_print_rate(buff + desc, bufsz - desc,
0407                      lq_sta->last_rate_n_flags);
0408     if (desc < bufsz - 1)
0409         buff[desc++] = '\n';
0410     mutex_unlock(&mvm->mutex);
0411 
0412     ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
0413     kfree(buff);
0414     return ret;
0415 }
0416 
0417 static ssize_t iwl_dbgfs_amsdu_len_write(struct ieee80211_sta *sta,
0418                      char *buf, size_t count,
0419                      loff_t *ppos)
0420 {
0421     struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
0422     int i;
0423     u16 amsdu_len;
0424 
0425     if (kstrtou16(buf, 0, &amsdu_len))
0426         return -EINVAL;
0427 
0428     /* only change from debug set <-> debug unset */
0429     if (amsdu_len && mvmsta->orig_amsdu_len)
0430         return -EBUSY;
0431 
0432     if (amsdu_len) {
0433         mvmsta->orig_amsdu_len = sta->max_amsdu_len;
0434         sta->max_amsdu_len = amsdu_len;
0435         for (i = 0; i < ARRAY_SIZE(sta->max_tid_amsdu_len); i++)
0436             sta->max_tid_amsdu_len[i] = amsdu_len;
0437     } else {
0438         sta->max_amsdu_len = mvmsta->orig_amsdu_len;
0439         mvmsta->orig_amsdu_len = 0;
0440     }
0441     return count;
0442 }
0443 
0444 static ssize_t iwl_dbgfs_amsdu_len_read(struct file *file,
0445                     char __user *user_buf,
0446                     size_t count, loff_t *ppos)
0447 {
0448     struct ieee80211_sta *sta = file->private_data;
0449     struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
0450 
0451     char buf[32];
0452     int pos;
0453 
0454     pos = scnprintf(buf, sizeof(buf), "current %d ", sta->max_amsdu_len);
0455     pos += scnprintf(buf + pos, sizeof(buf) - pos, "stored %d\n",
0456              mvmsta->orig_amsdu_len);
0457 
0458     return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
0459 }
0460 
0461 static ssize_t iwl_dbgfs_disable_power_off_read(struct file *file,
0462                         char __user *user_buf,
0463                         size_t count, loff_t *ppos)
0464 {
0465     struct iwl_mvm *mvm = file->private_data;
0466     char buf[64];
0467     int bufsz = sizeof(buf);
0468     int pos = 0;
0469 
0470     pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off_d0=%d\n",
0471              mvm->disable_power_off);
0472     pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off_d3=%d\n",
0473              mvm->disable_power_off_d3);
0474 
0475     return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
0476 }
0477 
0478 static ssize_t iwl_dbgfs_disable_power_off_write(struct iwl_mvm *mvm, char *buf,
0479                          size_t count, loff_t *ppos)
0480 {
0481     int ret, val;
0482 
0483     if (!iwl_mvm_firmware_running(mvm))
0484         return -EIO;
0485 
0486     if (!strncmp("disable_power_off_d0=", buf, 21)) {
0487         if (sscanf(buf + 21, "%d", &val) != 1)
0488             return -EINVAL;
0489         mvm->disable_power_off = val;
0490     } else if (!strncmp("disable_power_off_d3=", buf, 21)) {
0491         if (sscanf(buf + 21, "%d", &val) != 1)
0492             return -EINVAL;
0493         mvm->disable_power_off_d3 = val;
0494     } else {
0495         return -EINVAL;
0496     }
0497 
0498     mutex_lock(&mvm->mutex);
0499     ret = iwl_mvm_power_update_device(mvm);
0500     mutex_unlock(&mvm->mutex);
0501 
0502     return ret ?: count;
0503 }
0504 
0505 static
0506 int iwl_mvm_coex_dump_mbox(struct iwl_bt_coex_profile_notif *notif, char *buf,
0507                int pos, int bufsz)
0508 {
0509     pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw0:\n");
0510 
0511     BT_MBOX_PRINT(0, LE_SLAVE_LAT, false);
0512     BT_MBOX_PRINT(0, LE_PROF1, false);
0513     BT_MBOX_PRINT(0, LE_PROF2, false);
0514     BT_MBOX_PRINT(0, LE_PROF_OTHER, false);
0515     BT_MBOX_PRINT(0, CHL_SEQ_N, false);
0516     BT_MBOX_PRINT(0, INBAND_S, false);
0517     BT_MBOX_PRINT(0, LE_MIN_RSSI, false);
0518     BT_MBOX_PRINT(0, LE_SCAN, false);
0519     BT_MBOX_PRINT(0, LE_ADV, false);
0520     BT_MBOX_PRINT(0, LE_MAX_TX_POWER, false);
0521     BT_MBOX_PRINT(0, OPEN_CON_1, true);
0522 
0523     pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw1:\n");
0524 
0525     BT_MBOX_PRINT(1, BR_MAX_TX_POWER, false);
0526     BT_MBOX_PRINT(1, IP_SR, false);
0527     BT_MBOX_PRINT(1, LE_MSTR, false);
0528     BT_MBOX_PRINT(1, AGGR_TRFC_LD, false);
0529     BT_MBOX_PRINT(1, MSG_TYPE, false);
0530     BT_MBOX_PRINT(1, SSN, true);
0531 
0532     pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw2:\n");
0533 
0534     BT_MBOX_PRINT(2, SNIFF_ACT, false);
0535     BT_MBOX_PRINT(2, PAG, false);
0536     BT_MBOX_PRINT(2, INQUIRY, false);
0537     BT_MBOX_PRINT(2, CONN, false);
0538     BT_MBOX_PRINT(2, SNIFF_INTERVAL, false);
0539     BT_MBOX_PRINT(2, DISC, false);
0540     BT_MBOX_PRINT(2, SCO_TX_ACT, false);
0541     BT_MBOX_PRINT(2, SCO_RX_ACT, false);
0542     BT_MBOX_PRINT(2, ESCO_RE_TX, false);
0543     BT_MBOX_PRINT(2, SCO_DURATION, true);
0544 
0545     pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw3:\n");
0546 
0547     BT_MBOX_PRINT(3, SCO_STATE, false);
0548     BT_MBOX_PRINT(3, SNIFF_STATE, false);
0549     BT_MBOX_PRINT(3, A2DP_STATE, false);
0550     BT_MBOX_PRINT(3, A2DP_SRC, false);
0551     BT_MBOX_PRINT(3, ACL_STATE, false);
0552     BT_MBOX_PRINT(3, MSTR_STATE, false);
0553     BT_MBOX_PRINT(3, OBX_STATE, false);
0554     BT_MBOX_PRINT(3, OPEN_CON_2, false);
0555     BT_MBOX_PRINT(3, TRAFFIC_LOAD, false);
0556     BT_MBOX_PRINT(3, CHL_SEQN_LSB, false);
0557     BT_MBOX_PRINT(3, INBAND_P, false);
0558     BT_MBOX_PRINT(3, MSG_TYPE_2, false);
0559     BT_MBOX_PRINT(3, SSN_2, false);
0560     BT_MBOX_PRINT(3, UPDATE_REQUEST, true);
0561 
0562     return pos;
0563 }
0564 
0565 static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf,
0566                        size_t count, loff_t *ppos)
0567 {
0568     struct iwl_mvm *mvm = file->private_data;
0569     struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif;
0570     char *buf;
0571     int ret, pos = 0, bufsz = sizeof(char) * 1024;
0572 
0573     buf = kmalloc(bufsz, GFP_KERNEL);
0574     if (!buf)
0575         return -ENOMEM;
0576 
0577     mutex_lock(&mvm->mutex);
0578 
0579     pos += iwl_mvm_coex_dump_mbox(notif, buf, pos, bufsz);
0580 
0581     pos += scnprintf(buf + pos, bufsz - pos, "bt_ci_compliance = %d\n",
0582              notif->bt_ci_compliance);
0583     pos += scnprintf(buf + pos, bufsz - pos, "primary_ch_lut = %d\n",
0584              le32_to_cpu(notif->primary_ch_lut));
0585     pos += scnprintf(buf + pos, bufsz - pos, "secondary_ch_lut = %d\n",
0586              le32_to_cpu(notif->secondary_ch_lut));
0587     pos += scnprintf(buf + pos,
0588              bufsz - pos, "bt_activity_grading = %d\n",
0589              le32_to_cpu(notif->bt_activity_grading));
0590     pos += scnprintf(buf + pos, bufsz - pos, "bt_rrc = %d\n",
0591              notif->rrc_status & 0xF);
0592     pos += scnprintf(buf + pos, bufsz - pos, "bt_ttc = %d\n",
0593              notif->ttc_status & 0xF);
0594 
0595     pos += scnprintf(buf + pos, bufsz - pos, "sync_sco = %d\n",
0596              IWL_MVM_BT_COEX_SYNC2SCO);
0597     pos += scnprintf(buf + pos, bufsz - pos, "mplut = %d\n",
0598              IWL_MVM_BT_COEX_MPLUT);
0599 
0600     mutex_unlock(&mvm->mutex);
0601 
0602     ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
0603     kfree(buf);
0604 
0605     return ret;
0606 }
0607 #undef BT_MBOX_PRINT
0608 
0609 static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf,
0610                      size_t count, loff_t *ppos)
0611 {
0612     struct iwl_mvm *mvm = file->private_data;
0613     struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd;
0614     char buf[256];
0615     int bufsz = sizeof(buf);
0616     int pos = 0;
0617 
0618     mutex_lock(&mvm->mutex);
0619 
0620     pos += scnprintf(buf + pos, bufsz - pos, "Channel inhibition CMD\n");
0621     pos += scnprintf(buf + pos, bufsz - pos,
0622              "\tPrimary Channel Bitmap 0x%016llx\n",
0623              le64_to_cpu(cmd->bt_primary_ci));
0624     pos += scnprintf(buf + pos, bufsz - pos,
0625              "\tSecondary Channel Bitmap 0x%016llx\n",
0626              le64_to_cpu(cmd->bt_secondary_ci));
0627 
0628     mutex_unlock(&mvm->mutex);
0629 
0630     return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
0631 }
0632 
0633 static ssize_t
0634 iwl_dbgfs_bt_tx_prio_write(struct iwl_mvm *mvm, char *buf,
0635                size_t count, loff_t *ppos)
0636 {
0637     u32 bt_tx_prio;
0638 
0639     if (sscanf(buf, "%u", &bt_tx_prio) != 1)
0640         return -EINVAL;
0641     if (bt_tx_prio > 4)
0642         return -EINVAL;
0643 
0644     mvm->bt_tx_prio = bt_tx_prio;
0645 
0646     return count;
0647 }
0648 
0649 static ssize_t
0650 iwl_dbgfs_bt_force_ant_write(struct iwl_mvm *mvm, char *buf,
0651                  size_t count, loff_t *ppos)
0652 {
0653     static const char * const modes_str[BT_FORCE_ANT_MAX] = {
0654         [BT_FORCE_ANT_DIS] = "dis",
0655         [BT_FORCE_ANT_AUTO] = "auto",
0656         [BT_FORCE_ANT_BT] = "bt",
0657         [BT_FORCE_ANT_WIFI] = "wifi",
0658     };
0659     int ret, bt_force_ant_mode;
0660 
0661     ret = match_string(modes_str, ARRAY_SIZE(modes_str), buf);
0662     if (ret < 0)
0663         return ret;
0664 
0665     bt_force_ant_mode = ret;
0666     ret = 0;
0667     mutex_lock(&mvm->mutex);
0668     if (mvm->bt_force_ant_mode == bt_force_ant_mode)
0669         goto out;
0670 
0671     mvm->bt_force_ant_mode = bt_force_ant_mode;
0672     IWL_DEBUG_COEX(mvm, "Force mode: %s\n",
0673                modes_str[mvm->bt_force_ant_mode]);
0674 
0675     if (iwl_mvm_firmware_running(mvm))
0676         ret = iwl_mvm_send_bt_init_conf(mvm);
0677     else
0678         ret = 0;
0679 
0680 out:
0681     mutex_unlock(&mvm->mutex);
0682     return ret ?: count;
0683 }
0684 
0685 static ssize_t iwl_dbgfs_fw_ver_read(struct file *file, char __user *user_buf,
0686                      size_t count, loff_t *ppos)
0687 {
0688     struct iwl_mvm *mvm = file->private_data;
0689     char *buff, *pos, *endpos;
0690     static const size_t bufsz = 1024;
0691     int ret;
0692 
0693     buff = kmalloc(bufsz, GFP_KERNEL);
0694     if (!buff)
0695         return -ENOMEM;
0696 
0697     pos = buff;
0698     endpos = pos + bufsz;
0699 
0700     pos += scnprintf(pos, endpos - pos, "FW prefix: %s\n",
0701              mvm->trans->cfg->fw_name_pre);
0702     pos += scnprintf(pos, endpos - pos, "FW: %s\n",
0703              mvm->fwrt.fw->human_readable);
0704     pos += scnprintf(pos, endpos - pos, "Device: %s\n",
0705              mvm->fwrt.trans->name);
0706     pos += scnprintf(pos, endpos - pos, "Bus: %s\n",
0707              mvm->fwrt.dev->bus->name);
0708 
0709     ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff);
0710     kfree(buff);
0711 
0712     return ret;
0713 }
0714 
0715 static ssize_t iwl_dbgfs_phy_integration_ver_read(struct file *file,
0716                           char __user *user_buf,
0717                           size_t count, loff_t *ppos)
0718 {
0719     struct iwl_mvm *mvm = file->private_data;
0720     char *buf;
0721     size_t bufsz;
0722     int pos;
0723     ssize_t ret;
0724 
0725     bufsz = mvm->fw->phy_integration_ver_len + 2;
0726     buf = kmalloc(bufsz, GFP_KERNEL);
0727     if (!buf)
0728         return -ENOMEM;
0729 
0730     pos = scnprintf(buf, bufsz, "%.*s\n", mvm->fw->phy_integration_ver_len,
0731             mvm->fw->phy_integration_ver);
0732 
0733     ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
0734 
0735     kfree(buf);
0736     return ret;
0737 }
0738 
0739 #define PRINT_STATS_LE32(_struct, _memb)                \
0740              pos += scnprintf(buf + pos, bufsz - pos,   \
0741                       fmt_table, #_memb,        \
0742                       le32_to_cpu(_struct->_memb))
0743 
0744 static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file,
0745                       char __user *user_buf, size_t count,
0746                       loff_t *ppos)
0747 {
0748     struct iwl_mvm *mvm = file->private_data;
0749     static const char *fmt_table = "\t%-30s %10u\n";
0750     static const char *fmt_header = "%-32s\n";
0751     int pos = 0;
0752     char *buf;
0753     int ret;
0754     size_t bufsz;
0755 
0756     if (iwl_mvm_has_new_rx_stats_api(mvm))
0757         bufsz = ((sizeof(struct mvm_statistics_rx) /
0758               sizeof(__le32)) * 43) + (4 * 33) + 1;
0759     else
0760         /* 43 = size of each data line; 33 = size of each header */
0761         bufsz = ((sizeof(struct mvm_statistics_rx_v3) /
0762               sizeof(__le32)) * 43) + (4 * 33) + 1;
0763 
0764     buf = kzalloc(bufsz, GFP_KERNEL);
0765     if (!buf)
0766         return -ENOMEM;
0767 
0768     mutex_lock(&mvm->mutex);
0769 
0770     if (iwl_mvm_firmware_running(mvm))
0771         iwl_mvm_request_statistics(mvm, false);
0772 
0773     pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
0774              "Statistics_Rx - OFDM");
0775     if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
0776         struct mvm_statistics_rx_phy_v2 *ofdm = &mvm->rx_stats_v3.ofdm;
0777 
0778         PRINT_STATS_LE32(ofdm, ina_cnt);
0779         PRINT_STATS_LE32(ofdm, fina_cnt);
0780         PRINT_STATS_LE32(ofdm, plcp_err);
0781         PRINT_STATS_LE32(ofdm, crc32_err);
0782         PRINT_STATS_LE32(ofdm, overrun_err);
0783         PRINT_STATS_LE32(ofdm, early_overrun_err);
0784         PRINT_STATS_LE32(ofdm, crc32_good);
0785         PRINT_STATS_LE32(ofdm, false_alarm_cnt);
0786         PRINT_STATS_LE32(ofdm, fina_sync_err_cnt);
0787         PRINT_STATS_LE32(ofdm, sfd_timeout);
0788         PRINT_STATS_LE32(ofdm, fina_timeout);
0789         PRINT_STATS_LE32(ofdm, unresponded_rts);
0790         PRINT_STATS_LE32(ofdm, rxe_frame_lmt_overrun);
0791         PRINT_STATS_LE32(ofdm, sent_ack_cnt);
0792         PRINT_STATS_LE32(ofdm, sent_cts_cnt);
0793         PRINT_STATS_LE32(ofdm, sent_ba_rsp_cnt);
0794         PRINT_STATS_LE32(ofdm, dsp_self_kill);
0795         PRINT_STATS_LE32(ofdm, mh_format_err);
0796         PRINT_STATS_LE32(ofdm, re_acq_main_rssi_sum);
0797         PRINT_STATS_LE32(ofdm, reserved);
0798     } else {
0799         struct mvm_statistics_rx_phy *ofdm = &mvm->rx_stats.ofdm;
0800 
0801         PRINT_STATS_LE32(ofdm, unresponded_rts);
0802         PRINT_STATS_LE32(ofdm, rxe_frame_lmt_overrun);
0803         PRINT_STATS_LE32(ofdm, sent_ba_rsp_cnt);
0804         PRINT_STATS_LE32(ofdm, dsp_self_kill);
0805         PRINT_STATS_LE32(ofdm, reserved);
0806     }
0807 
0808     pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
0809              "Statistics_Rx - CCK");
0810     if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
0811         struct mvm_statistics_rx_phy_v2 *cck = &mvm->rx_stats_v3.cck;
0812 
0813         PRINT_STATS_LE32(cck, ina_cnt);
0814         PRINT_STATS_LE32(cck, fina_cnt);
0815         PRINT_STATS_LE32(cck, plcp_err);
0816         PRINT_STATS_LE32(cck, crc32_err);
0817         PRINT_STATS_LE32(cck, overrun_err);
0818         PRINT_STATS_LE32(cck, early_overrun_err);
0819         PRINT_STATS_LE32(cck, crc32_good);
0820         PRINT_STATS_LE32(cck, false_alarm_cnt);
0821         PRINT_STATS_LE32(cck, fina_sync_err_cnt);
0822         PRINT_STATS_LE32(cck, sfd_timeout);
0823         PRINT_STATS_LE32(cck, fina_timeout);
0824         PRINT_STATS_LE32(cck, unresponded_rts);
0825         PRINT_STATS_LE32(cck, rxe_frame_lmt_overrun);
0826         PRINT_STATS_LE32(cck, sent_ack_cnt);
0827         PRINT_STATS_LE32(cck, sent_cts_cnt);
0828         PRINT_STATS_LE32(cck, sent_ba_rsp_cnt);
0829         PRINT_STATS_LE32(cck, dsp_self_kill);
0830         PRINT_STATS_LE32(cck, mh_format_err);
0831         PRINT_STATS_LE32(cck, re_acq_main_rssi_sum);
0832         PRINT_STATS_LE32(cck, reserved);
0833     } else {
0834         struct mvm_statistics_rx_phy *cck = &mvm->rx_stats.cck;
0835 
0836         PRINT_STATS_LE32(cck, unresponded_rts);
0837         PRINT_STATS_LE32(cck, rxe_frame_lmt_overrun);
0838         PRINT_STATS_LE32(cck, sent_ba_rsp_cnt);
0839         PRINT_STATS_LE32(cck, dsp_self_kill);
0840         PRINT_STATS_LE32(cck, reserved);
0841     }
0842 
0843     pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
0844              "Statistics_Rx - GENERAL");
0845     if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
0846         struct mvm_statistics_rx_non_phy_v3 *general =
0847             &mvm->rx_stats_v3.general;
0848 
0849         PRINT_STATS_LE32(general, bogus_cts);
0850         PRINT_STATS_LE32(general, bogus_ack);
0851         PRINT_STATS_LE32(general, non_bssid_frames);
0852         PRINT_STATS_LE32(general, filtered_frames);
0853         PRINT_STATS_LE32(general, non_channel_beacons);
0854         PRINT_STATS_LE32(general, channel_beacons);
0855         PRINT_STATS_LE32(general, num_missed_bcon);
0856         PRINT_STATS_LE32(general, adc_rx_saturation_time);
0857         PRINT_STATS_LE32(general, ina_detection_search_time);
0858         PRINT_STATS_LE32(general, beacon_silence_rssi_a);
0859         PRINT_STATS_LE32(general, beacon_silence_rssi_b);
0860         PRINT_STATS_LE32(general, beacon_silence_rssi_c);
0861         PRINT_STATS_LE32(general, interference_data_flag);
0862         PRINT_STATS_LE32(general, channel_load);
0863         PRINT_STATS_LE32(general, dsp_false_alarms);
0864         PRINT_STATS_LE32(general, beacon_rssi_a);
0865         PRINT_STATS_LE32(general, beacon_rssi_b);
0866         PRINT_STATS_LE32(general, beacon_rssi_c);
0867         PRINT_STATS_LE32(general, beacon_energy_a);
0868         PRINT_STATS_LE32(general, beacon_energy_b);
0869         PRINT_STATS_LE32(general, beacon_energy_c);
0870         PRINT_STATS_LE32(general, num_bt_kills);
0871         PRINT_STATS_LE32(general, mac_id);
0872         PRINT_STATS_LE32(general, directed_data_mpdu);
0873     } else {
0874         struct mvm_statistics_rx_non_phy *general =
0875             &mvm->rx_stats.general;
0876 
0877         PRINT_STATS_LE32(general, bogus_cts);
0878         PRINT_STATS_LE32(general, bogus_ack);
0879         PRINT_STATS_LE32(general, non_channel_beacons);
0880         PRINT_STATS_LE32(general, channel_beacons);
0881         PRINT_STATS_LE32(general, num_missed_bcon);
0882         PRINT_STATS_LE32(general, adc_rx_saturation_time);
0883         PRINT_STATS_LE32(general, ina_detection_search_time);
0884         PRINT_STATS_LE32(general, beacon_silence_rssi_a);
0885         PRINT_STATS_LE32(general, beacon_silence_rssi_b);
0886         PRINT_STATS_LE32(general, beacon_silence_rssi_c);
0887         PRINT_STATS_LE32(general, interference_data_flag);
0888         PRINT_STATS_LE32(general, channel_load);
0889         PRINT_STATS_LE32(general, beacon_rssi_a);
0890         PRINT_STATS_LE32(general, beacon_rssi_b);
0891         PRINT_STATS_LE32(general, beacon_rssi_c);
0892         PRINT_STATS_LE32(general, beacon_energy_a);
0893         PRINT_STATS_LE32(general, beacon_energy_b);
0894         PRINT_STATS_LE32(general, beacon_energy_c);
0895         PRINT_STATS_LE32(general, num_bt_kills);
0896         PRINT_STATS_LE32(general, mac_id);
0897     }
0898 
0899     pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
0900              "Statistics_Rx - HT");
0901     if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
0902         struct mvm_statistics_rx_ht_phy_v1 *ht =
0903             &mvm->rx_stats_v3.ofdm_ht;
0904 
0905         PRINT_STATS_LE32(ht, plcp_err);
0906         PRINT_STATS_LE32(ht, overrun_err);
0907         PRINT_STATS_LE32(ht, early_overrun_err);
0908         PRINT_STATS_LE32(ht, crc32_good);
0909         PRINT_STATS_LE32(ht, crc32_err);
0910         PRINT_STATS_LE32(ht, mh_format_err);
0911         PRINT_STATS_LE32(ht, agg_crc32_good);
0912         PRINT_STATS_LE32(ht, agg_mpdu_cnt);
0913         PRINT_STATS_LE32(ht, agg_cnt);
0914         PRINT_STATS_LE32(ht, unsupport_mcs);
0915     } else {
0916         struct mvm_statistics_rx_ht_phy *ht =
0917             &mvm->rx_stats.ofdm_ht;
0918 
0919         PRINT_STATS_LE32(ht, mh_format_err);
0920         PRINT_STATS_LE32(ht, agg_mpdu_cnt);
0921         PRINT_STATS_LE32(ht, agg_cnt);
0922         PRINT_STATS_LE32(ht, unsupport_mcs);
0923     }
0924 
0925     mutex_unlock(&mvm->mutex);
0926 
0927     ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
0928     kfree(buf);
0929 
0930     return ret;
0931 }
0932 #undef PRINT_STAT_LE32
0933 
0934 static ssize_t iwl_dbgfs_frame_stats_read(struct iwl_mvm *mvm,
0935                       char __user *user_buf, size_t count,
0936                       loff_t *ppos,
0937                       struct iwl_mvm_frame_stats *stats)
0938 {
0939     char *buff, *pos, *endpos;
0940     int idx, i;
0941     int ret;
0942     static const size_t bufsz = 1024;
0943 
0944     buff = kmalloc(bufsz, GFP_KERNEL);
0945     if (!buff)
0946         return -ENOMEM;
0947 
0948     spin_lock_bh(&mvm->drv_stats_lock);
0949 
0950     pos = buff;
0951     endpos = pos + bufsz;
0952 
0953     pos += scnprintf(pos, endpos - pos,
0954              "Legacy/HT/VHT\t:\t%d/%d/%d\n",
0955              stats->legacy_frames,
0956              stats->ht_frames,
0957              stats->vht_frames);
0958     pos += scnprintf(pos, endpos - pos, "20/40/80\t:\t%d/%d/%d\n",
0959              stats->bw_20_frames,
0960              stats->bw_40_frames,
0961              stats->bw_80_frames);
0962     pos += scnprintf(pos, endpos - pos, "NGI/SGI\t\t:\t%d/%d\n",
0963              stats->ngi_frames,
0964              stats->sgi_frames);
0965     pos += scnprintf(pos, endpos - pos, "SISO/MIMO2\t:\t%d/%d\n",
0966              stats->siso_frames,
0967              stats->mimo2_frames);
0968     pos += scnprintf(pos, endpos - pos, "FAIL/SCSS\t:\t%d/%d\n",
0969              stats->fail_frames,
0970              stats->success_frames);
0971     pos += scnprintf(pos, endpos - pos, "MPDUs agg\t:\t%d\n",
0972              stats->agg_frames);
0973     pos += scnprintf(pos, endpos - pos, "A-MPDUs\t\t:\t%d\n",
0974              stats->ampdu_count);
0975     pos += scnprintf(pos, endpos - pos, "Avg MPDUs/A-MPDU:\t%d\n",
0976              stats->ampdu_count > 0 ?
0977              (stats->agg_frames / stats->ampdu_count) : 0);
0978 
0979     pos += scnprintf(pos, endpos - pos, "Last Rates\n");
0980 
0981     idx = stats->last_frame_idx - 1;
0982     for (i = 0; i < ARRAY_SIZE(stats->last_rates); i++) {
0983         idx = (idx + 1) % ARRAY_SIZE(stats->last_rates);
0984         if (stats->last_rates[idx] == 0)
0985             continue;
0986         pos += scnprintf(pos, endpos - pos, "Rate[%d]: ",
0987                  (int)(ARRAY_SIZE(stats->last_rates) - i));
0988         pos += rs_pretty_print_rate_v1(pos, endpos - pos,
0989                            stats->last_rates[idx]);
0990         if (pos < endpos - 1)
0991             *pos++ = '\n';
0992     }
0993     spin_unlock_bh(&mvm->drv_stats_lock);
0994 
0995     ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff);
0996     kfree(buff);
0997 
0998     return ret;
0999 }
1000 
1001 static ssize_t iwl_dbgfs_drv_rx_stats_read(struct file *file,
1002                        char __user *user_buf, size_t count,
1003                        loff_t *ppos)
1004 {
1005     struct iwl_mvm *mvm = file->private_data;
1006 
1007     return iwl_dbgfs_frame_stats_read(mvm, user_buf, count, ppos,
1008                       &mvm->drv_rx_stats);
1009 }
1010 
1011 static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
1012                       size_t count, loff_t *ppos)
1013 {
1014     int __maybe_unused ret;
1015 
1016     if (!iwl_mvm_firmware_running(mvm))
1017         return -EIO;
1018 
1019     mutex_lock(&mvm->mutex);
1020 
1021     /* allow one more restart that we're provoking here */
1022     if (mvm->fw_restart >= 0)
1023         mvm->fw_restart++;
1024 
1025     if (count == 6 && !strcmp(buf, "nolog\n")) {
1026         set_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, &mvm->status);
1027         set_bit(STATUS_SUPPRESS_CMD_ERROR_ONCE, &mvm->trans->status);
1028     }
1029 
1030     /* take the return value to make compiler happy - it will fail anyway */
1031     ret = iwl_mvm_send_cmd_pdu(mvm,
1032                    WIDE_ID(LONG_GROUP, REPLY_ERROR),
1033                    0, 0, NULL);
1034 
1035     mutex_unlock(&mvm->mutex);
1036 
1037     return count;
1038 }
1039 
1040 static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf,
1041                       size_t count, loff_t *ppos)
1042 {
1043     if (!iwl_mvm_firmware_running(mvm))
1044         return -EIO;
1045 
1046     if (count == 6 && !strcmp(buf, "nolog\n"))
1047         set_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, &mvm->status);
1048 
1049     iwl_force_nmi(mvm->trans);
1050 
1051     return count;
1052 }
1053 
1054 static ssize_t
1055 iwl_dbgfs_scan_ant_rxchain_read(struct file *file,
1056                 char __user *user_buf,
1057                 size_t count, loff_t *ppos)
1058 {
1059     struct iwl_mvm *mvm = file->private_data;
1060     int pos = 0;
1061     char buf[32];
1062     const size_t bufsz = sizeof(buf);
1063 
1064     /* print which antennas were set for the scan command by the user */
1065     pos += scnprintf(buf + pos, bufsz - pos, "Antennas for scan: ");
1066     if (mvm->scan_rx_ant & ANT_A)
1067         pos += scnprintf(buf + pos, bufsz - pos, "A");
1068     if (mvm->scan_rx_ant & ANT_B)
1069         pos += scnprintf(buf + pos, bufsz - pos, "B");
1070     pos += scnprintf(buf + pos, bufsz - pos, " (%hhx)\n", mvm->scan_rx_ant);
1071 
1072     return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1073 }
1074 
1075 static ssize_t
1076 iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf,
1077                  size_t count, loff_t *ppos)
1078 {
1079     u8 scan_rx_ant;
1080 
1081     if (!iwl_mvm_firmware_running(mvm))
1082         return -EIO;
1083 
1084     if (sscanf(buf, "%hhx", &scan_rx_ant) != 1)
1085         return -EINVAL;
1086     if (scan_rx_ant > ANT_ABC)
1087         return -EINVAL;
1088     if (scan_rx_ant & ~(iwl_mvm_get_valid_rx_ant(mvm)))
1089         return -EINVAL;
1090 
1091     if (mvm->scan_rx_ant != scan_rx_ant) {
1092         mvm->scan_rx_ant = scan_rx_ant;
1093         if (fw_has_capa(&mvm->fw->ucode_capa,
1094                 IWL_UCODE_TLV_CAPA_UMAC_SCAN))
1095             iwl_mvm_config_scan(mvm);
1096     }
1097 
1098     return count;
1099 }
1100 
1101 static ssize_t iwl_dbgfs_indirection_tbl_write(struct iwl_mvm *mvm,
1102                            char *buf, size_t count,
1103                            loff_t *ppos)
1104 {
1105     struct iwl_rss_config_cmd cmd = {
1106         .flags = cpu_to_le32(IWL_RSS_ENABLE),
1107         .hash_mask = IWL_RSS_HASH_TYPE_IPV4_TCP |
1108                  IWL_RSS_HASH_TYPE_IPV4_UDP |
1109                  IWL_RSS_HASH_TYPE_IPV4_PAYLOAD |
1110                  IWL_RSS_HASH_TYPE_IPV6_TCP |
1111                  IWL_RSS_HASH_TYPE_IPV6_UDP |
1112                  IWL_RSS_HASH_TYPE_IPV6_PAYLOAD,
1113     };
1114     int ret, i, num_repeats, nbytes = count / 2;
1115 
1116     ret = hex2bin(cmd.indirection_table, buf, nbytes);
1117     if (ret)
1118         return ret;
1119 
1120     /*
1121      * The input is the redirection table, partial or full.
1122      * Repeat the pattern if needed.
1123      * For example, input of 01020F will be repeated 42 times,
1124      * indirecting RSS hash results to queues 1, 2, 15 (skipping
1125      * queues 3 - 14).
1126      */
1127     num_repeats = ARRAY_SIZE(cmd.indirection_table) / nbytes;
1128     for (i = 1; i < num_repeats; i++)
1129         memcpy(&cmd.indirection_table[i * nbytes],
1130                cmd.indirection_table, nbytes);
1131     /* handle cut in the middle pattern for the last places */
1132     memcpy(&cmd.indirection_table[i * nbytes], cmd.indirection_table,
1133            ARRAY_SIZE(cmd.indirection_table) % nbytes);
1134 
1135     netdev_rss_key_fill(cmd.secret_key, sizeof(cmd.secret_key));
1136 
1137     mutex_lock(&mvm->mutex);
1138     if (iwl_mvm_firmware_running(mvm))
1139         ret = iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0,
1140                        sizeof(cmd), &cmd);
1141     else
1142         ret = 0;
1143     mutex_unlock(&mvm->mutex);
1144 
1145     return ret ?: count;
1146 }
1147 
1148 static ssize_t iwl_dbgfs_inject_packet_write(struct iwl_mvm *mvm,
1149                          char *buf, size_t count,
1150                          loff_t *ppos)
1151 {
1152     struct iwl_op_mode *opmode = container_of((void *)mvm,
1153                           struct iwl_op_mode,
1154                           op_mode_specific);
1155     struct iwl_rx_cmd_buffer rxb = {
1156         ._rx_page_order = 0,
1157         .truesize = 0, /* not used */
1158         ._offset = 0,
1159     };
1160     struct iwl_rx_packet *pkt;
1161     int bin_len = count / 2;
1162     int ret = -EINVAL;
1163 
1164     if (!iwl_mvm_firmware_running(mvm))
1165         return -EIO;
1166 
1167     /* supporting only MQ RX */
1168     if (!mvm->trans->trans_cfg->mq_rx_supported)
1169         return -ENOTSUPP;
1170 
1171     rxb._page = alloc_pages(GFP_ATOMIC, 0);
1172     if (!rxb._page)
1173         return -ENOMEM;
1174     pkt = rxb_addr(&rxb);
1175 
1176     ret = hex2bin(page_address(rxb._page), buf, bin_len);
1177     if (ret)
1178         goto out;
1179 
1180     /* avoid invalid memory access and malformed packet */
1181     if (bin_len < sizeof(*pkt) ||
1182         bin_len != sizeof(*pkt) + iwl_rx_packet_payload_len(pkt))
1183         goto out;
1184 
1185     local_bh_disable();
1186     iwl_mvm_rx_mq(opmode, NULL, &rxb);
1187     local_bh_enable();
1188     ret = 0;
1189 
1190 out:
1191     iwl_free_rxb(&rxb);
1192 
1193     return ret ?: count;
1194 }
1195 
1196 static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len)
1197 {
1198     struct ieee80211_vif *vif;
1199     struct iwl_mvm_vif *mvmvif;
1200     struct sk_buff *beacon;
1201     struct ieee80211_tx_info *info;
1202     struct iwl_mac_beacon_cmd beacon_cmd = {};
1203     u8 rate;
1204     int i;
1205 
1206     len /= 2;
1207 
1208     /* Element len should be represented by u8 */
1209     if (len >= U8_MAX)
1210         return -EINVAL;
1211 
1212     if (!iwl_mvm_firmware_running(mvm))
1213         return -EIO;
1214 
1215     if (!iwl_mvm_has_new_tx_api(mvm) &&
1216         !fw_has_api(&mvm->fw->ucode_capa,
1217             IWL_UCODE_TLV_API_NEW_BEACON_TEMPLATE))
1218         return -EINVAL;
1219 
1220     mutex_lock(&mvm->mutex);
1221 
1222     for (i = 0; i < NUM_MAC_INDEX_DRIVER; i++) {
1223         vif = iwl_mvm_rcu_dereference_vif_id(mvm, i, false);
1224         if (!vif)
1225             continue;
1226 
1227         if (vif->type == NL80211_IFTYPE_AP)
1228             break;
1229     }
1230 
1231     if (i == NUM_MAC_INDEX_DRIVER || !vif)
1232         goto out_err;
1233 
1234     mvm->hw->extra_beacon_tailroom = len;
1235 
1236     beacon = ieee80211_beacon_get_template(mvm->hw, vif, NULL, 0);
1237     if (!beacon)
1238         goto out_err;
1239 
1240     if (len && hex2bin(skb_put_zero(beacon, len), bin, len)) {
1241         dev_kfree_skb(beacon);
1242         goto out_err;
1243     }
1244 
1245     mvm->beacon_inject_active = true;
1246 
1247     mvmvif = iwl_mvm_vif_from_mac80211(vif);
1248     info = IEEE80211_SKB_CB(beacon);
1249     rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif);
1250 
1251     beacon_cmd.flags =
1252         cpu_to_le16(iwl_mvm_mac_ctxt_get_beacon_flags(mvm->fw, rate));
1253     beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len);
1254     beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id);
1255 
1256     iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx,
1257                  &beacon_cmd.tim_size,
1258                  beacon->data, beacon->len);
1259 
1260     iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd,
1261                      sizeof(beacon_cmd));
1262     mutex_unlock(&mvm->mutex);
1263 
1264     dev_kfree_skb(beacon);
1265 
1266     return 0;
1267 
1268 out_err:
1269     mutex_unlock(&mvm->mutex);
1270     return -EINVAL;
1271 }
1272 
1273 static ssize_t iwl_dbgfs_inject_beacon_ie_write(struct iwl_mvm *mvm,
1274                         char *buf, size_t count,
1275                         loff_t *ppos)
1276 {
1277     int ret = _iwl_dbgfs_inject_beacon_ie(mvm, buf, count);
1278 
1279     mvm->hw->extra_beacon_tailroom = 0;
1280     return ret ?: count;
1281 }
1282 
1283 static ssize_t iwl_dbgfs_inject_beacon_ie_restore_write(struct iwl_mvm *mvm,
1284                             char *buf,
1285                             size_t count,
1286                             loff_t *ppos)
1287 {
1288     int ret = _iwl_dbgfs_inject_beacon_ie(mvm, NULL, 0);
1289 
1290     mvm->hw->extra_beacon_tailroom = 0;
1291     mvm->beacon_inject_active = false;
1292     return ret ?: count;
1293 }
1294 
1295 static ssize_t iwl_dbgfs_fw_dbg_conf_read(struct file *file,
1296                       char __user *user_buf,
1297                       size_t count, loff_t *ppos)
1298 {
1299     struct iwl_mvm *mvm = file->private_data;
1300     int conf;
1301     char buf[8];
1302     const size_t bufsz = sizeof(buf);
1303     int pos = 0;
1304 
1305     mutex_lock(&mvm->mutex);
1306     conf = mvm->fwrt.dump.conf;
1307     mutex_unlock(&mvm->mutex);
1308 
1309     pos += scnprintf(buf + pos, bufsz - pos, "%d\n", conf);
1310 
1311     return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1312 }
1313 
1314 static ssize_t iwl_dbgfs_fw_dbg_conf_write(struct iwl_mvm *mvm,
1315                        char *buf, size_t count,
1316                        loff_t *ppos)
1317 {
1318     unsigned int conf_id;
1319     int ret;
1320 
1321     if (!iwl_mvm_firmware_running(mvm))
1322         return -EIO;
1323 
1324     ret = kstrtouint(buf, 0, &conf_id);
1325     if (ret)
1326         return ret;
1327 
1328     if (WARN_ON(conf_id >= FW_DBG_CONF_MAX))
1329         return -EINVAL;
1330 
1331     mutex_lock(&mvm->mutex);
1332     ret = iwl_fw_start_dbg_conf(&mvm->fwrt, conf_id);
1333     mutex_unlock(&mvm->mutex);
1334 
1335     return ret ?: count;
1336 }
1337 
1338 static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm,
1339                           char *buf, size_t count,
1340                           loff_t *ppos)
1341 {
1342     if (count == 0)
1343         return 0;
1344 
1345     iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_USER_TRIGGER,
1346                    NULL);
1347 
1348     iwl_fw_dbg_collect(&mvm->fwrt, FW_DBG_TRIGGER_USER, buf,
1349                (count - 1), NULL);
1350 
1351     return count;
1352 }
1353 
1354 static ssize_t iwl_dbgfs_dbg_time_point_write(struct iwl_mvm *mvm,
1355                           char *buf, size_t count,
1356                           loff_t *ppos)
1357 {
1358     u32 timepoint;
1359 
1360     if (kstrtou32(buf, 0, &timepoint))
1361         return -EINVAL;
1362 
1363     if (timepoint == IWL_FW_INI_TIME_POINT_INVALID ||
1364         timepoint >= IWL_FW_INI_TIME_POINT_NUM)
1365         return -EINVAL;
1366 
1367     iwl_dbg_tlv_time_point(&mvm->fwrt, timepoint, NULL);
1368 
1369     return count;
1370 }
1371 
1372 #define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
1373     _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm)
1374 #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
1375     _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm)
1376 #define MVM_DEBUGFS_ADD_FILE_ALIAS(alias, name, parent, mode) do {  \
1377         debugfs_create_file(alias, mode, parent, mvm,       \
1378                     &iwl_dbgfs_##name##_ops);       \
1379     } while (0)
1380 #define MVM_DEBUGFS_ADD_FILE(name, parent, mode) \
1381     MVM_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode)
1382 
1383 #define MVM_DEBUGFS_WRITE_STA_FILE_OPS(name, bufsz) \
1384     _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_sta)
1385 #define MVM_DEBUGFS_READ_WRITE_STA_FILE_OPS(name, bufsz) \
1386     _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct ieee80211_sta)
1387 
1388 #define MVM_DEBUGFS_ADD_STA_FILE_ALIAS(alias, name, parent, mode) do {  \
1389         debugfs_create_file(alias, mode, parent, sta,       \
1390                     &iwl_dbgfs_##name##_ops);       \
1391     } while (0)
1392 #define MVM_DEBUGFS_ADD_STA_FILE(name, parent, mode) \
1393     MVM_DEBUGFS_ADD_STA_FILE_ALIAS(#name, name, parent, mode)
1394 
1395 static ssize_t
1396 iwl_dbgfs_prph_reg_read(struct file *file,
1397             char __user *user_buf,
1398             size_t count, loff_t *ppos)
1399 {
1400     struct iwl_mvm *mvm = file->private_data;
1401     int pos = 0;
1402     char buf[32];
1403     const size_t bufsz = sizeof(buf);
1404 
1405     if (!mvm->dbgfs_prph_reg_addr)
1406         return -EINVAL;
1407 
1408     pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n",
1409         mvm->dbgfs_prph_reg_addr,
1410         iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr));
1411 
1412     return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1413 }
1414 
1415 static ssize_t
1416 iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
1417              size_t count, loff_t *ppos)
1418 {
1419     u8 args;
1420     u32 value;
1421 
1422     args = sscanf(buf, "%i %i", &mvm->dbgfs_prph_reg_addr, &value);
1423     /* if we only want to set the reg address - nothing more to do */
1424     if (args == 1)
1425         goto out;
1426 
1427     /* otherwise, make sure we have both address and value */
1428     if (args != 2)
1429         return -EINVAL;
1430 
1431     iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value);
1432 
1433 out:
1434     return count;
1435 }
1436 
1437 static ssize_t
1438 iwl_dbgfs_send_echo_cmd_write(struct iwl_mvm *mvm, char *buf,
1439                   size_t count, loff_t *ppos)
1440 {
1441     int ret;
1442 
1443     if (!iwl_mvm_firmware_running(mvm))
1444         return -EIO;
1445 
1446     mutex_lock(&mvm->mutex);
1447     ret = iwl_mvm_send_cmd_pdu(mvm, ECHO_CMD, 0, 0, NULL);
1448     mutex_unlock(&mvm->mutex);
1449 
1450     return ret ?: count;
1451 }
1452 
1453 struct iwl_mvm_sniffer_apply {
1454     struct iwl_mvm *mvm;
1455     u8 *bssid;
1456     u16 aid;
1457 };
1458 
1459 static bool iwl_mvm_sniffer_apply(struct iwl_notif_wait_data *notif_data,
1460                   struct iwl_rx_packet *pkt, void *data)
1461 {
1462     struct iwl_mvm_sniffer_apply *apply = data;
1463 
1464     apply->mvm->cur_aid = cpu_to_le16(apply->aid);
1465     memcpy(apply->mvm->cur_bssid, apply->bssid,
1466            sizeof(apply->mvm->cur_bssid));
1467 
1468     return true;
1469 }
1470 
1471 static ssize_t
1472 iwl_dbgfs_he_sniffer_params_write(struct iwl_mvm *mvm, char *buf,
1473                   size_t count, loff_t *ppos)
1474 {
1475     struct iwl_notification_wait wait;
1476     struct iwl_he_monitor_cmd he_mon_cmd = {};
1477     struct iwl_mvm_sniffer_apply apply = {
1478         .mvm = mvm,
1479     };
1480     u16 wait_cmds[] = {
1481         WIDE_ID(DATA_PATH_GROUP, HE_AIR_SNIFFER_CONFIG_CMD),
1482     };
1483     u32 aid;
1484     int ret;
1485 
1486     if (!iwl_mvm_firmware_running(mvm))
1487         return -EIO;
1488 
1489     ret = sscanf(buf, "%x %2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx", &aid,
1490              &he_mon_cmd.bssid[0], &he_mon_cmd.bssid[1],
1491              &he_mon_cmd.bssid[2], &he_mon_cmd.bssid[3],
1492              &he_mon_cmd.bssid[4], &he_mon_cmd.bssid[5]);
1493     if (ret != 7)
1494         return -EINVAL;
1495 
1496     he_mon_cmd.aid = cpu_to_le16(aid);
1497 
1498     apply.aid = aid;
1499     apply.bssid = (void *)he_mon_cmd.bssid;
1500 
1501     mutex_lock(&mvm->mutex);
1502 
1503     /*
1504      * Use the notification waiter to get our function triggered
1505      * in sequence with other RX. This ensures that frames we get
1506      * on the RX queue _before_ the new configuration is applied
1507      * still have mvm->cur_aid pointing to the old AID, and that
1508      * frames on the RX queue _after_ the firmware processed the
1509      * new configuration (and sent the response, synchronously)
1510      * get mvm->cur_aid correctly set to the new AID.
1511      */
1512     iwl_init_notification_wait(&mvm->notif_wait, &wait,
1513                    wait_cmds, ARRAY_SIZE(wait_cmds),
1514                    iwl_mvm_sniffer_apply, &apply);
1515 
1516     ret = iwl_mvm_send_cmd_pdu(mvm,
1517                    WIDE_ID(DATA_PATH_GROUP, HE_AIR_SNIFFER_CONFIG_CMD),
1518                    0,
1519                    sizeof(he_mon_cmd), &he_mon_cmd);
1520 
1521     /* no need to really wait, we already did anyway */
1522     iwl_remove_notification(&mvm->notif_wait, &wait);
1523 
1524     mutex_unlock(&mvm->mutex);
1525 
1526     return ret ?: count;
1527 }
1528 
1529 static ssize_t
1530 iwl_dbgfs_he_sniffer_params_read(struct file *file, char __user *user_buf,
1531                  size_t count, loff_t *ppos)
1532 {
1533     struct iwl_mvm *mvm = file->private_data;
1534     u8 buf[32];
1535     int len;
1536 
1537     len = scnprintf(buf, sizeof(buf),
1538             "%d %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n",
1539             le16_to_cpu(mvm->cur_aid), mvm->cur_bssid[0],
1540             mvm->cur_bssid[1], mvm->cur_bssid[2], mvm->cur_bssid[3],
1541             mvm->cur_bssid[4], mvm->cur_bssid[5]);
1542 
1543     return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1544 }
1545 
1546 static ssize_t
1547 iwl_dbgfs_uapsd_noagg_bssids_read(struct file *file, char __user *user_buf,
1548                   size_t count, loff_t *ppos)
1549 {
1550     struct iwl_mvm *mvm = file->private_data;
1551     u8 buf[IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM * ETH_ALEN * 3 + 1];
1552     unsigned int pos = 0;
1553     size_t bufsz = sizeof(buf);
1554     int i;
1555 
1556     mutex_lock(&mvm->mutex);
1557 
1558     for (i = 0; i < IWL_MVM_UAPSD_NOAGG_LIST_LEN; i++)
1559         pos += scnprintf(buf + pos, bufsz - pos, "%pM\n",
1560                  mvm->uapsd_noagg_bssids[i].addr);
1561 
1562     mutex_unlock(&mvm->mutex);
1563 
1564     return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1565 }
1566 
1567 static ssize_t
1568 iwl_dbgfs_ltr_config_write(struct iwl_mvm *mvm,
1569                char *buf, size_t count, loff_t *ppos)
1570 {
1571     int ret;
1572     struct iwl_ltr_config_cmd ltr_config = {0};
1573 
1574     if (!iwl_mvm_firmware_running(mvm))
1575         return -EIO;
1576 
1577     if (sscanf(buf, "%x,%x,%x,%x,%x,%x,%x",
1578            &ltr_config.flags,
1579            &ltr_config.static_long,
1580            &ltr_config.static_short,
1581            &ltr_config.ltr_cfg_values[0],
1582            &ltr_config.ltr_cfg_values[1],
1583            &ltr_config.ltr_cfg_values[2],
1584            &ltr_config.ltr_cfg_values[3]) != 7) {
1585         return -EINVAL;
1586     }
1587 
1588     mutex_lock(&mvm->mutex);
1589     ret = iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0, sizeof(ltr_config),
1590                    &ltr_config);
1591     mutex_unlock(&mvm->mutex);
1592 
1593     if (ret)
1594         IWL_ERR(mvm, "failed to send ltr configuration cmd\n");
1595 
1596     return ret ?: count;
1597 }
1598 
1599 static ssize_t iwl_dbgfs_rfi_freq_table_write(struct iwl_mvm *mvm, char *buf,
1600                           size_t count, loff_t *ppos)
1601 {
1602     int ret = 0;
1603     u16 op_id;
1604 
1605     if (kstrtou16(buf, 10, &op_id))
1606         return -EINVAL;
1607 
1608     /* value zero triggers re-sending the default table to the device */
1609     if (!op_id) {
1610         mutex_lock(&mvm->mutex);
1611         ret = iwl_rfi_send_config_cmd(mvm, NULL);
1612         mutex_unlock(&mvm->mutex);
1613     } else {
1614         ret = -EOPNOTSUPP; /* in the future a new table will be added */
1615     }
1616 
1617     return ret ?: count;
1618 }
1619 
1620 /* The size computation is as follows:
1621  * each number needs at most 3 characters, number of rows is the size of
1622  * the table; So, need 5 chars for the "freq: " part and each tuple afterwards
1623  * needs 6 characters for numbers and 5 for the punctuation around.
1624  */
1625 #define IWL_RFI_BUF_SIZE (IWL_RFI_LUT_INSTALLED_SIZE *\
1626                 (5 + IWL_RFI_LUT_ENTRY_CHANNELS_NUM * (6 + 5)))
1627 
1628 static ssize_t iwl_dbgfs_rfi_freq_table_read(struct file *file,
1629                          char __user *user_buf,
1630                          size_t count, loff_t *ppos)
1631 {
1632     struct iwl_mvm *mvm = file->private_data;
1633     struct iwl_rfi_freq_table_resp_cmd *resp;
1634     u32 status;
1635     char buf[IWL_RFI_BUF_SIZE];
1636     int i, j, pos = 0;
1637 
1638     resp = iwl_rfi_get_freq_table(mvm);
1639     if (IS_ERR(resp))
1640         return PTR_ERR(resp);
1641 
1642     status = le32_to_cpu(resp->status);
1643     if (status != RFI_FREQ_TABLE_OK) {
1644         scnprintf(buf, IWL_RFI_BUF_SIZE, "status = %d\n", status);
1645         goto out;
1646     }
1647 
1648     for (i = 0; i < ARRAY_SIZE(resp->table); i++) {
1649         pos += scnprintf(buf + pos, IWL_RFI_BUF_SIZE - pos, "%d: ",
1650                  resp->table[i].freq);
1651 
1652         for (j = 0; j < ARRAY_SIZE(resp->table[i].channels); j++)
1653             pos += scnprintf(buf + pos, IWL_RFI_BUF_SIZE - pos,
1654                      "(%d, %d) ",
1655                      resp->table[i].channels[j],
1656                      resp->table[i].bands[j]);
1657         pos += scnprintf(buf + pos, IWL_RFI_BUF_SIZE - pos, "\n");
1658     }
1659 
1660 out:
1661     kfree(resp);
1662     return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1663 }
1664 
1665 MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64);
1666 
1667 /* Device wide debugfs entries */
1668 MVM_DEBUGFS_READ_FILE_OPS(ctdp_budget);
1669 MVM_DEBUGFS_WRITE_FILE_OPS(stop_ctdp, 8);
1670 MVM_DEBUGFS_WRITE_FILE_OPS(force_ctkill, 8);
1671 MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16);
1672 MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain, 8);
1673 MVM_DEBUGFS_WRITE_FILE_OPS(send_echo_cmd, 8);
1674 MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram, 64);
1675 MVM_DEBUGFS_READ_WRITE_FILE_OPS(set_nic_temperature, 64);
1676 MVM_DEBUGFS_READ_FILE_OPS(nic_temp);
1677 MVM_DEBUGFS_READ_FILE_OPS(stations);
1678 MVM_DEBUGFS_READ_FILE_OPS(rs_data);
1679 MVM_DEBUGFS_READ_FILE_OPS(bt_notif);
1680 MVM_DEBUGFS_READ_FILE_OPS(bt_cmd);
1681 MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off, 64);
1682 MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats);
1683 MVM_DEBUGFS_READ_FILE_OPS(drv_rx_stats);
1684 MVM_DEBUGFS_READ_FILE_OPS(fw_ver);
1685 MVM_DEBUGFS_READ_FILE_OPS(phy_integration_ver);
1686 MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10);
1687 MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10);
1688 MVM_DEBUGFS_WRITE_FILE_OPS(bt_tx_prio, 10);
1689 MVM_DEBUGFS_WRITE_FILE_OPS(bt_force_ant, 10);
1690 MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
1691 MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8);
1692 MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 64);
1693 MVM_DEBUGFS_WRITE_FILE_OPS(dbg_time_point, 64);
1694 MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl,
1695                (IWL_RSS_INDIRECTION_TABLE_SIZE * 2));
1696 MVM_DEBUGFS_WRITE_FILE_OPS(inject_packet, 512);
1697 MVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon_ie, 512);
1698 MVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon_ie_restore, 512);
1699 
1700 MVM_DEBUGFS_READ_FILE_OPS(uapsd_noagg_bssids);
1701 
1702 #ifdef CONFIG_ACPI
1703 MVM_DEBUGFS_READ_FILE_OPS(sar_geo_profile);
1704 #endif
1705 
1706 MVM_DEBUGFS_READ_WRITE_STA_FILE_OPS(amsdu_len, 16);
1707 
1708 MVM_DEBUGFS_READ_WRITE_FILE_OPS(he_sniffer_params, 32);
1709 
1710 MVM_DEBUGFS_WRITE_FILE_OPS(ltr_config, 512);
1711 MVM_DEBUGFS_READ_WRITE_FILE_OPS(rfi_freq_table, 16);
1712 
1713 static ssize_t iwl_dbgfs_mem_read(struct file *file, char __user *user_buf,
1714                   size_t count, loff_t *ppos)
1715 {
1716     struct iwl_mvm *mvm = file->private_data;
1717     struct iwl_dbg_mem_access_cmd cmd = {};
1718     struct iwl_dbg_mem_access_rsp *rsp;
1719     struct iwl_host_cmd hcmd = {
1720         .flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
1721         .data = { &cmd, },
1722         .len = { sizeof(cmd) },
1723     };
1724     size_t delta;
1725     ssize_t ret, len;
1726 
1727     if (!iwl_mvm_firmware_running(mvm))
1728         return -EIO;
1729 
1730     hcmd.id = WIDE_ID(DEBUG_GROUP, *ppos >> 24 ? UMAC_RD_WR : LMAC_RD_WR);
1731     cmd.op = cpu_to_le32(DEBUG_MEM_OP_READ);
1732 
1733     /* Take care of alignment of both the position and the length */
1734     delta = *ppos & 0x3;
1735     cmd.addr = cpu_to_le32(*ppos - delta);
1736     cmd.len = cpu_to_le32(min(ALIGN(count + delta, 4) / 4,
1737                   (size_t)DEBUG_MEM_MAX_SIZE_DWORDS));
1738 
1739     mutex_lock(&mvm->mutex);
1740     ret = iwl_mvm_send_cmd(mvm, &hcmd);
1741     mutex_unlock(&mvm->mutex);
1742 
1743     if (ret < 0)
1744         return ret;
1745 
1746     rsp = (void *)hcmd.resp_pkt->data;
1747     if (le32_to_cpu(rsp->status) != DEBUG_MEM_STATUS_SUCCESS) {
1748         ret = -ENXIO;
1749         goto out;
1750     }
1751 
1752     len = min((size_t)le32_to_cpu(rsp->len) << 2,
1753           iwl_rx_packet_payload_len(hcmd.resp_pkt) - sizeof(*rsp));
1754     len = min(len - delta, count);
1755     if (len < 0) {
1756         ret = -EFAULT;
1757         goto out;
1758     }
1759 
1760     ret = len - copy_to_user(user_buf, (u8 *)rsp->data + delta, len);
1761     *ppos += ret;
1762 
1763 out:
1764     iwl_free_resp(&hcmd);
1765     return ret;
1766 }
1767 
1768 static ssize_t iwl_dbgfs_mem_write(struct file *file,
1769                    const char __user *user_buf, size_t count,
1770                    loff_t *ppos)
1771 {
1772     struct iwl_mvm *mvm = file->private_data;
1773     struct iwl_dbg_mem_access_cmd *cmd;
1774     struct iwl_dbg_mem_access_rsp *rsp;
1775     struct iwl_host_cmd hcmd = {};
1776     size_t cmd_size;
1777     size_t data_size;
1778     u32 op, len;
1779     ssize_t ret;
1780 
1781     if (!iwl_mvm_firmware_running(mvm))
1782         return -EIO;
1783 
1784     hcmd.id = WIDE_ID(DEBUG_GROUP, *ppos >> 24 ? UMAC_RD_WR : LMAC_RD_WR);
1785 
1786     if (*ppos & 0x3 || count < 4) {
1787         op = DEBUG_MEM_OP_WRITE_BYTES;
1788         len = min(count, (size_t)(4 - (*ppos & 0x3)));
1789         data_size = len;
1790     } else {
1791         op = DEBUG_MEM_OP_WRITE;
1792         len = min(count >> 2, (size_t)DEBUG_MEM_MAX_SIZE_DWORDS);
1793         data_size = len << 2;
1794     }
1795 
1796     cmd_size = sizeof(*cmd) + ALIGN(data_size, 4);
1797     cmd = kzalloc(cmd_size, GFP_KERNEL);
1798     if (!cmd)
1799         return -ENOMEM;
1800 
1801     cmd->op = cpu_to_le32(op);
1802     cmd->len = cpu_to_le32(len);
1803     cmd->addr = cpu_to_le32(*ppos);
1804     if (copy_from_user((void *)cmd->data, user_buf, data_size)) {
1805         kfree(cmd);
1806         return -EFAULT;
1807     }
1808 
1809     hcmd.flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
1810     hcmd.data[0] = (void *)cmd;
1811     hcmd.len[0] = cmd_size;
1812 
1813     mutex_lock(&mvm->mutex);
1814     ret = iwl_mvm_send_cmd(mvm, &hcmd);
1815     mutex_unlock(&mvm->mutex);
1816 
1817     kfree(cmd);
1818 
1819     if (ret < 0)
1820         return ret;
1821 
1822     rsp = (void *)hcmd.resp_pkt->data;
1823     if (rsp->status != DEBUG_MEM_STATUS_SUCCESS) {
1824         ret = -ENXIO;
1825         goto out;
1826     }
1827 
1828     ret = data_size;
1829     *ppos += ret;
1830 
1831 out:
1832     iwl_free_resp(&hcmd);
1833     return ret;
1834 }
1835 
1836 static const struct file_operations iwl_dbgfs_mem_ops = {
1837     .read = iwl_dbgfs_mem_read,
1838     .write = iwl_dbgfs_mem_write,
1839     .open = simple_open,
1840     .llseek = default_llseek,
1841 };
1842 
1843 void iwl_mvm_sta_add_debugfs(struct ieee80211_hw *hw,
1844                  struct ieee80211_vif *vif,
1845                  struct ieee80211_sta *sta,
1846                  struct dentry *dir)
1847 {
1848     struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1849 
1850     if (iwl_mvm_has_tlc_offload(mvm)) {
1851         MVM_DEBUGFS_ADD_STA_FILE(rs_data, dir, 0400);
1852     }
1853     MVM_DEBUGFS_ADD_STA_FILE(amsdu_len, dir, 0600);
1854 }
1855 
1856 void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm)
1857 {
1858     struct dentry *bcast_dir __maybe_unused;
1859 
1860     spin_lock_init(&mvm->drv_stats_lock);
1861 
1862     MVM_DEBUGFS_ADD_FILE(tx_flush, mvm->debugfs_dir, 0200);
1863     MVM_DEBUGFS_ADD_FILE(sta_drain, mvm->debugfs_dir, 0200);
1864     MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, 0600);
1865     MVM_DEBUGFS_ADD_FILE(set_nic_temperature, mvm->debugfs_dir, 0600);
1866     MVM_DEBUGFS_ADD_FILE(nic_temp, mvm->debugfs_dir, 0400);
1867     MVM_DEBUGFS_ADD_FILE(ctdp_budget, mvm->debugfs_dir, 0400);
1868     MVM_DEBUGFS_ADD_FILE(stop_ctdp, mvm->debugfs_dir, 0200);
1869     MVM_DEBUGFS_ADD_FILE(force_ctkill, mvm->debugfs_dir, 0200);
1870     MVM_DEBUGFS_ADD_FILE(stations, mvm->debugfs_dir, 0400);
1871     MVM_DEBUGFS_ADD_FILE(bt_notif, mvm->debugfs_dir, 0400);
1872     MVM_DEBUGFS_ADD_FILE(bt_cmd, mvm->debugfs_dir, 0400);
1873     MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir, 0600);
1874     MVM_DEBUGFS_ADD_FILE(fw_ver, mvm->debugfs_dir, 0400);
1875     MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, 0400);
1876     MVM_DEBUGFS_ADD_FILE(drv_rx_stats, mvm->debugfs_dir, 0400);
1877     MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, 0200);
1878     MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, 0200);
1879     MVM_DEBUGFS_ADD_FILE(bt_tx_prio, mvm->debugfs_dir, 0200);
1880     MVM_DEBUGFS_ADD_FILE(bt_force_ant, mvm->debugfs_dir, 0200);
1881     MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir, 0600);
1882     MVM_DEBUGFS_ADD_FILE(prph_reg, mvm->debugfs_dir, 0600);
1883     MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, 0600);
1884     MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, 0200);
1885     MVM_DEBUGFS_ADD_FILE(dbg_time_point, mvm->debugfs_dir, 0200);
1886     MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, 0200);
1887     MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, 0200);
1888     MVM_DEBUGFS_ADD_FILE(inject_packet, mvm->debugfs_dir, 0200);
1889     MVM_DEBUGFS_ADD_FILE(inject_beacon_ie, mvm->debugfs_dir, 0200);
1890     MVM_DEBUGFS_ADD_FILE(inject_beacon_ie_restore, mvm->debugfs_dir, 0200);
1891     MVM_DEBUGFS_ADD_FILE(rfi_freq_table, mvm->debugfs_dir, 0600);
1892 
1893     if (mvm->fw->phy_integration_ver)
1894         MVM_DEBUGFS_ADD_FILE(phy_integration_ver, mvm->debugfs_dir, 0400);
1895 #ifdef CONFIG_ACPI
1896     MVM_DEBUGFS_ADD_FILE(sar_geo_profile, mvm->debugfs_dir, 0400);
1897 #endif
1898     MVM_DEBUGFS_ADD_FILE(he_sniffer_params, mvm->debugfs_dir, 0600);
1899 
1900     if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SET_LTR_GEN2))
1901         MVM_DEBUGFS_ADD_FILE(ltr_config, mvm->debugfs_dir, 0200);
1902 
1903     debugfs_create_bool("enable_scan_iteration_notif", 0600,
1904                 mvm->debugfs_dir, &mvm->scan_iter_notif_enabled);
1905     debugfs_create_bool("drop_bcn_ap_mode", 0600, mvm->debugfs_dir,
1906                 &mvm->drop_bcn_ap_mode);
1907 
1908     MVM_DEBUGFS_ADD_FILE(uapsd_noagg_bssids, mvm->debugfs_dir, S_IRUSR);
1909 
1910 #ifdef CONFIG_PM_SLEEP
1911     MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, 0400);
1912     debugfs_create_bool("d3_wake_sysassert", 0600, mvm->debugfs_dir,
1913                 &mvm->d3_wake_sysassert);
1914     debugfs_create_u32("last_netdetect_scans", 0400, mvm->debugfs_dir,
1915                &mvm->last_netdetect_scans);
1916 #endif
1917 
1918     debugfs_create_u8("ps_disabled", 0400, mvm->debugfs_dir,
1919               &mvm->ps_disabled);
1920     debugfs_create_blob("nvm_hw", 0400, mvm->debugfs_dir,
1921                 &mvm->nvm_hw_blob);
1922     debugfs_create_blob("nvm_sw", 0400, mvm->debugfs_dir,
1923                 &mvm->nvm_sw_blob);
1924     debugfs_create_blob("nvm_calib", 0400, mvm->debugfs_dir,
1925                 &mvm->nvm_calib_blob);
1926     debugfs_create_blob("nvm_prod", 0400, mvm->debugfs_dir,
1927                 &mvm->nvm_prod_blob);
1928     debugfs_create_blob("nvm_phy_sku", 0400, mvm->debugfs_dir,
1929                 &mvm->nvm_phy_sku_blob);
1930     debugfs_create_blob("nvm_reg", S_IRUSR,
1931                 mvm->debugfs_dir, &mvm->nvm_reg_blob);
1932 
1933     debugfs_create_file("mem", 0600, mvm->debugfs_dir, mvm,
1934                 &iwl_dbgfs_mem_ops);
1935 
1936     /*
1937      * Create a symlink with mac80211. It will be removed when mac80211
1938      * exists (before the opmode exists which removes the target.)
1939      */
1940     if (!IS_ERR(mvm->debugfs_dir)) {
1941         char buf[100];
1942 
1943         snprintf(buf, 100, "../../%pd2", mvm->debugfs_dir->d_parent);
1944         debugfs_create_symlink("iwlwifi", mvm->hw->wiphy->debugfsdir,
1945                        buf);
1946     }
1947 }