The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/dev/iwlwifi/mvm/debugfs.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
    2 /*
    3  * Copyright (C) 2012-2014, 2018-2021 Intel Corporation
    4  * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
    5  * Copyright (C) 2016-2017 Intel Deutschland GmbH
    6  */
    7 #include <linux/vmalloc.h>
    8 #include <linux/err.h>
    9 #include <linux/ieee80211.h>
   10 #include <linux/netdevice.h>
   11 
   12 #include "mvm.h"
   13 #include "sta.h"
   14 #include "iwl-io.h"
   15 #include "debugfs.h"
   16 #include "iwl-modparams.h"
   17 #include "fw/error-dump.h"
   18 
   19 static ssize_t iwl_dbgfs_ctdp_budget_read(struct file *file,
   20                                           char __user *user_buf,
   21                                           size_t count, loff_t *ppos)
   22 {
   23         struct iwl_mvm *mvm = file->private_data;
   24         char buf[16];
   25         int pos, budget;
   26 
   27         if (!iwl_mvm_is_ctdp_supported(mvm))
   28                 return -EOPNOTSUPP;
   29 
   30         if (!iwl_mvm_firmware_running(mvm) ||
   31             mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
   32                 return -EIO;
   33 
   34         mutex_lock(&mvm->mutex);
   35         budget = iwl_mvm_ctdp_command(mvm, CTDP_CMD_OPERATION_REPORT, 0);
   36         mutex_unlock(&mvm->mutex);
   37 
   38         if (budget < 0)
   39                 return budget;
   40 
   41         pos = scnprintf(buf, sizeof(buf), "%d\n", budget);
   42 
   43         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
   44 }
   45 
   46 static ssize_t iwl_dbgfs_stop_ctdp_write(struct iwl_mvm *mvm, char *buf,
   47                                          size_t count, loff_t *ppos)
   48 {
   49         int ret;
   50 
   51         if (!iwl_mvm_is_ctdp_supported(mvm))
   52                 return -EOPNOTSUPP;
   53 
   54         if (!iwl_mvm_firmware_running(mvm) ||
   55             mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
   56                 return -EIO;
   57 
   58         mutex_lock(&mvm->mutex);
   59         ret = iwl_mvm_ctdp_command(mvm, CTDP_CMD_OPERATION_STOP, 0);
   60         mutex_unlock(&mvm->mutex);
   61 
   62         return ret ?: count;
   63 }
   64 
   65 static ssize_t iwl_dbgfs_force_ctkill_write(struct iwl_mvm *mvm, char *buf,
   66                                             size_t count, loff_t *ppos)
   67 {
   68         if (!iwl_mvm_firmware_running(mvm) ||
   69             mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
   70                 return -EIO;
   71 
   72         iwl_mvm_enter_ctkill(mvm);
   73 
   74         return count;
   75 }
   76 
   77 static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf,
   78                                         size_t count, loff_t *ppos)
   79 {
   80         int ret;
   81         u32 flush_arg;
   82 
   83         if (!iwl_mvm_firmware_running(mvm) ||
   84             mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
   85                 return -EIO;
   86 
   87         if (kstrtou32(buf, 0, &flush_arg))
   88                 return -EINVAL;
   89 
   90         if (iwl_mvm_has_new_tx_api(mvm)) {
   91                 IWL_DEBUG_TX_QUEUES(mvm,
   92                                     "FLUSHING all tids queues on sta_id = %d\n",
   93                                     flush_arg);
   94                 mutex_lock(&mvm->mutex);
   95                 ret = iwl_mvm_flush_sta_tids(mvm, flush_arg, 0xFFFF)
   96                         ? : count;
   97                 mutex_unlock(&mvm->mutex);
   98                 return ret;
   99         }
  100 
  101         IWL_DEBUG_TX_QUEUES(mvm, "FLUSHING queues mask to flush = 0x%x\n",
  102                             flush_arg);
  103 
  104         mutex_lock(&mvm->mutex);
  105         ret =  iwl_mvm_flush_tx_path(mvm, flush_arg) ? : count;
  106         mutex_unlock(&mvm->mutex);
  107 
  108         return ret;
  109 }
  110 
  111 static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf,
  112                                          size_t count, loff_t *ppos)
  113 {
  114         struct iwl_mvm_sta *mvmsta;
  115         int sta_id, drain, ret;
  116 
  117         if (!iwl_mvm_firmware_running(mvm) ||
  118             mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
  119                 return -EIO;
  120 
  121         if (sscanf(buf, "%d %d", &sta_id, &drain) != 2)
  122                 return -EINVAL;
  123         if (sta_id < 0 || sta_id >= mvm->fw->ucode_capa.num_stations)
  124                 return -EINVAL;
  125         if (drain < 0 || drain > 1)
  126                 return -EINVAL;
  127 
  128         mutex_lock(&mvm->mutex);
  129 
  130         mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
  131 
  132         if (!mvmsta)
  133                 ret = -ENOENT;
  134         else
  135                 ret = iwl_mvm_drain_sta(mvm, mvmsta, drain) ? : count;
  136 
  137         mutex_unlock(&mvm->mutex);
  138 
  139         return ret;
  140 }
  141 
  142 static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf,
  143                                    size_t count, loff_t *ppos)
  144 {
  145         struct iwl_mvm *mvm = file->private_data;
  146         const struct fw_img *img;
  147         unsigned int ofs, len;
  148         size_t ret;
  149         u8 *ptr;
  150 
  151         if (!iwl_mvm_firmware_running(mvm))
  152                 return -EINVAL;
  153 
  154         /* default is to dump the entire data segment */
  155         img = &mvm->fw->img[mvm->fwrt.cur_fw_img];
  156         ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
  157         len = img->sec[IWL_UCODE_SECTION_DATA].len;
  158 
  159         if (mvm->dbgfs_sram_len) {
  160                 ofs = mvm->dbgfs_sram_offset;
  161                 len = mvm->dbgfs_sram_len;
  162         }
  163 
  164         ptr = kzalloc(len, GFP_KERNEL);
  165         if (!ptr)
  166                 return -ENOMEM;
  167 
  168         iwl_trans_read_mem_bytes(mvm->trans, ofs, ptr, len);
  169 
  170         ret = simple_read_from_buffer(user_buf, count, ppos, ptr, len);
  171 
  172         kfree(ptr);
  173 
  174         return ret;
  175 }
  176 
  177 static ssize_t iwl_dbgfs_sram_write(struct iwl_mvm *mvm, char *buf,
  178                                     size_t count, loff_t *ppos)
  179 {
  180         const struct fw_img *img;
  181         u32 offset, len;
  182         u32 img_offset, img_len;
  183 
  184         if (!iwl_mvm_firmware_running(mvm))
  185                 return -EINVAL;
  186 
  187         img = &mvm->fw->img[mvm->fwrt.cur_fw_img];
  188         img_offset = img->sec[IWL_UCODE_SECTION_DATA].offset;
  189         img_len = img->sec[IWL_UCODE_SECTION_DATA].len;
  190 
  191         if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
  192                 if ((offset & 0x3) || (len & 0x3))
  193                         return -EINVAL;
  194 
  195                 if (offset + len > img_offset + img_len)
  196                         return -EINVAL;
  197 
  198                 mvm->dbgfs_sram_offset = offset;
  199                 mvm->dbgfs_sram_len = len;
  200         } else {
  201                 mvm->dbgfs_sram_offset = 0;
  202                 mvm->dbgfs_sram_len = 0;
  203         }
  204 
  205         return count;
  206 }
  207 
  208 static ssize_t iwl_dbgfs_set_nic_temperature_read(struct file *file,
  209                                                   char __user *user_buf,
  210                                                   size_t count, loff_t *ppos)
  211 {
  212         struct iwl_mvm *mvm = file->private_data;
  213         char buf[16];
  214         int pos;
  215 
  216         if (!mvm->temperature_test)
  217                 pos = scnprintf(buf , sizeof(buf), "disabled\n");
  218         else
  219                 pos = scnprintf(buf , sizeof(buf), "%d\n", mvm->temperature);
  220 
  221         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  222 }
  223 
  224 /*
  225  * Set NIC Temperature
  226  * Cause the driver to ignore the actual NIC temperature reported by the FW
  227  * Enable: any value between IWL_MVM_DEBUG_SET_TEMPERATURE_MIN -
  228  * IWL_MVM_DEBUG_SET_TEMPERATURE_MAX
  229  * Disable: IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE
  230  */
  231 static ssize_t iwl_dbgfs_set_nic_temperature_write(struct iwl_mvm *mvm,
  232                                                    char *buf, size_t count,
  233                                                    loff_t *ppos)
  234 {
  235         int temperature;
  236 
  237         if (!iwl_mvm_firmware_running(mvm) && !mvm->temperature_test)
  238                 return -EIO;
  239 
  240         if (kstrtoint(buf, 10, &temperature))
  241                 return -EINVAL;
  242         /* not a legal temperature */
  243         if ((temperature > IWL_MVM_DEBUG_SET_TEMPERATURE_MAX &&
  244              temperature != IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE) ||
  245             temperature < IWL_MVM_DEBUG_SET_TEMPERATURE_MIN)
  246                 return -EINVAL;
  247 
  248         mutex_lock(&mvm->mutex);
  249         if (temperature == IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE) {
  250                 if (!mvm->temperature_test)
  251                         goto out;
  252 
  253                 mvm->temperature_test = false;
  254                 /* Since we can't read the temp while awake, just set
  255                  * it to zero until we get the next RX stats from the
  256                  * firmware.
  257                  */
  258                 mvm->temperature = 0;
  259         } else {
  260                 mvm->temperature_test = true;
  261                 mvm->temperature = temperature;
  262         }
  263         IWL_DEBUG_TEMP(mvm, "%sabling debug set temperature (temp = %d)\n",
  264                        mvm->temperature_test ? "En" : "Dis" ,
  265                        mvm->temperature);
  266         /* handle the temperature change */
  267         iwl_mvm_tt_handler(mvm);
  268 
  269 out:
  270         mutex_unlock(&mvm->mutex);
  271 
  272         return count;
  273 }
  274 
  275 static ssize_t iwl_dbgfs_nic_temp_read(struct file *file,
  276                                        char __user *user_buf,
  277                                        size_t count, loff_t *ppos)
  278 {
  279         struct iwl_mvm *mvm = file->private_data;
  280         char buf[16];
  281         int pos, ret;
  282         s32 temp;
  283 
  284         if (!iwl_mvm_firmware_running(mvm))
  285                 return -EIO;
  286 
  287         mutex_lock(&mvm->mutex);
  288         ret = iwl_mvm_get_temp(mvm, &temp);
  289         mutex_unlock(&mvm->mutex);
  290 
  291         if (ret)
  292                 return -EIO;
  293 
  294         pos = scnprintf(buf , sizeof(buf), "%d\n", temp);
  295 
  296         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  297 }
  298 
  299 #ifdef CONFIG_ACPI
  300 static ssize_t iwl_dbgfs_sar_geo_profile_read(struct file *file,
  301                                               char __user *user_buf,
  302                                               size_t count, loff_t *ppos)
  303 {
  304         struct iwl_mvm *mvm = file->private_data;
  305         char buf[256];
  306         int pos = 0;
  307         int bufsz = sizeof(buf);
  308         int tbl_idx;
  309 
  310         if (!iwl_mvm_firmware_running(mvm))
  311                 return -EIO;
  312 
  313         mutex_lock(&mvm->mutex);
  314         tbl_idx = iwl_mvm_get_sar_geo_profile(mvm);
  315         if (tbl_idx < 0) {
  316                 mutex_unlock(&mvm->mutex);
  317                 return tbl_idx;
  318         }
  319 
  320         if (!tbl_idx) {
  321                 pos = scnprintf(buf, bufsz,
  322                                 "SAR geographic profile disabled\n");
  323         } else {
  324                 pos += scnprintf(buf + pos, bufsz - pos,
  325                                  "Use geographic profile %d\n", tbl_idx);
  326                 pos += scnprintf(buf + pos, bufsz - pos,
  327                                  "2.4GHz:\n\tChain A offset: %hhu dBm\n\tChain B offset: %hhu dBm\n\tmax tx power: %hhu dBm\n",
  328                                  mvm->fwrt.geo_profiles[tbl_idx - 1].bands[0].chains[0],
  329                                  mvm->fwrt.geo_profiles[tbl_idx - 1].bands[0].chains[1],
  330                                  mvm->fwrt.geo_profiles[tbl_idx - 1].bands[0].max);
  331                 pos += scnprintf(buf + pos, bufsz - pos,
  332                                  "5.2GHz:\n\tChain A offset: %hhu dBm\n\tChain B offset: %hhu dBm\n\tmax tx power: %hhu dBm\n",
  333                                  mvm->fwrt.geo_profiles[tbl_idx - 1].bands[1].chains[0],
  334                                  mvm->fwrt.geo_profiles[tbl_idx - 1].bands[1].chains[1],
  335                                  mvm->fwrt.geo_profiles[tbl_idx - 1].bands[1].max);
  336         }
  337         mutex_unlock(&mvm->mutex);
  338 
  339         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  340 }
  341 #endif
  342 
  343 static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
  344                                        size_t count, loff_t *ppos)
  345 {
  346         struct iwl_mvm *mvm = file->private_data;
  347         struct ieee80211_sta *sta;
  348         char buf[400];
  349         int i, pos = 0, bufsz = sizeof(buf);
  350 
  351         mutex_lock(&mvm->mutex);
  352 
  353         for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) {
  354                 pos += scnprintf(buf + pos, bufsz - pos, "%.2d: ", i);
  355                 sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
  356                                                 lockdep_is_held(&mvm->mutex));
  357                 if (!sta)
  358                         pos += scnprintf(buf + pos, bufsz - pos, "N/A\n");
  359                 else if (IS_ERR(sta))
  360                         pos += scnprintf(buf + pos, bufsz - pos, "%ld\n",
  361                                          PTR_ERR(sta));
  362                 else
  363                         pos += scnprintf(buf + pos, bufsz - pos, "%pM\n",
  364                                          sta->addr);
  365         }
  366 
  367         mutex_unlock(&mvm->mutex);
  368 
  369         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  370 }
  371 
  372 static ssize_t iwl_dbgfs_rs_data_read(struct file *file, char __user *user_buf,
  373                                       size_t count, loff_t *ppos)
  374 {
  375         struct ieee80211_sta *sta = file->private_data;
  376         struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
  377         struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->lq_sta.rs_fw;
  378         struct iwl_mvm *mvm = lq_sta->pers.drv;
  379         static const size_t bufsz = 2048;
  380         char *buff;
  381         int desc = 0;
  382         ssize_t ret;
  383 
  384         buff = kmalloc(bufsz, GFP_KERNEL);
  385         if (!buff)
  386                 return -ENOMEM;
  387 
  388         mutex_lock(&mvm->mutex);
  389 
  390         desc += scnprintf(buff + desc, bufsz - desc, "sta_id %d\n",
  391                           lq_sta->pers.sta_id);
  392         desc += scnprintf(buff + desc, bufsz - desc,
  393                           "fixed rate 0x%X\n",
  394                           lq_sta->pers.dbg_fixed_rate);
  395         desc += scnprintf(buff + desc, bufsz - desc,
  396                           "A-MPDU size limit %d\n",
  397                           lq_sta->pers.dbg_agg_frame_count_lim);
  398         desc += scnprintf(buff + desc, bufsz - desc,
  399                           "valid_tx_ant %s%s\n",
  400                 (iwl_mvm_get_valid_tx_ant(mvm) & ANT_A) ? "ANT_A," : "",
  401                 (iwl_mvm_get_valid_tx_ant(mvm) & ANT_B) ? "ANT_B," : "");
  402         desc += scnprintf(buff + desc, bufsz - desc,
  403                           "last tx rate=0x%X ",
  404                           lq_sta->last_rate_n_flags);
  405 
  406         desc += rs_pretty_print_rate(buff + desc, bufsz - desc,
  407                                      lq_sta->last_rate_n_flags);
  408         if (desc < bufsz - 1)
  409                 buff[desc++] = '\n';
  410         mutex_unlock(&mvm->mutex);
  411 
  412         ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
  413         kfree(buff);
  414         return ret;
  415 }
  416 
  417 static ssize_t iwl_dbgfs_amsdu_len_write(struct ieee80211_sta *sta,
  418                                          char *buf, size_t count,
  419                                          loff_t *ppos)
  420 {
  421         struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
  422         int i;
  423         u16 amsdu_len;
  424 
  425         if (kstrtou16(buf, 0, &amsdu_len))
  426                 return -EINVAL;
  427 
  428         /* only change from debug set <-> debug unset */
  429         if (amsdu_len && mvmsta->orig_amsdu_len)
  430                 return -EBUSY;
  431 
  432         if (amsdu_len) {
  433                 mvmsta->orig_amsdu_len = sta->max_amsdu_len;
  434                 sta->max_amsdu_len = amsdu_len;
  435                 for (i = 0; i < ARRAY_SIZE(sta->max_tid_amsdu_len); i++)
  436                         sta->max_tid_amsdu_len[i] = amsdu_len;
  437         } else {
  438                 sta->max_amsdu_len = mvmsta->orig_amsdu_len;
  439                 mvmsta->orig_amsdu_len = 0;
  440         }
  441         return count;
  442 }
  443 
  444 static ssize_t iwl_dbgfs_amsdu_len_read(struct file *file,
  445                                         char __user *user_buf,
  446                                         size_t count, loff_t *ppos)
  447 {
  448         struct ieee80211_sta *sta = file->private_data;
  449         struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
  450 
  451         char buf[32];
  452         int pos;
  453 
  454         pos = scnprintf(buf, sizeof(buf), "current %d ", sta->max_amsdu_len);
  455         pos += scnprintf(buf + pos, sizeof(buf) - pos, "stored %d\n",
  456                          mvmsta->orig_amsdu_len);
  457 
  458         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  459 }
  460 
  461 static ssize_t iwl_dbgfs_disable_power_off_read(struct file *file,
  462                                                 char __user *user_buf,
  463                                                 size_t count, loff_t *ppos)
  464 {
  465         struct iwl_mvm *mvm = file->private_data;
  466         char buf[64];
  467         int bufsz = sizeof(buf);
  468         int pos = 0;
  469 
  470         pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off_d0=%d\n",
  471                          mvm->disable_power_off);
  472         pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off_d3=%d\n",
  473                          mvm->disable_power_off_d3);
  474 
  475         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  476 }
  477 
  478 static ssize_t iwl_dbgfs_disable_power_off_write(struct iwl_mvm *mvm, char *buf,
  479                                                  size_t count, loff_t *ppos)
  480 {
  481         int ret, val;
  482 
  483         if (!iwl_mvm_firmware_running(mvm))
  484                 return -EIO;
  485 
  486         if (!strncmp("disable_power_off_d0=", buf, 21)) {
  487                 if (sscanf(buf + 21, "%d", &val) != 1)
  488                         return -EINVAL;
  489                 mvm->disable_power_off = val;
  490         } else if (!strncmp("disable_power_off_d3=", buf, 21)) {
  491                 if (sscanf(buf + 21, "%d", &val) != 1)
  492                         return -EINVAL;
  493                 mvm->disable_power_off_d3 = val;
  494         } else {
  495                 return -EINVAL;
  496         }
  497 
  498         mutex_lock(&mvm->mutex);
  499         ret = iwl_mvm_power_update_device(mvm);
  500         mutex_unlock(&mvm->mutex);
  501 
  502         return ret ?: count;
  503 }
  504 
  505 static
  506 int iwl_mvm_coex_dump_mbox(struct iwl_bt_coex_profile_notif *notif, char *buf,
  507                            int pos, int bufsz)
  508 {
  509         pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw0:\n");
  510 
  511         BT_MBOX_PRINT(0, LE_SLAVE_LAT, false);
  512         BT_MBOX_PRINT(0, LE_PROF1, false);
  513         BT_MBOX_PRINT(0, LE_PROF2, false);
  514         BT_MBOX_PRINT(0, LE_PROF_OTHER, false);
  515         BT_MBOX_PRINT(0, CHL_SEQ_N, false);
  516         BT_MBOX_PRINT(0, INBAND_S, false);
  517         BT_MBOX_PRINT(0, LE_MIN_RSSI, false);
  518         BT_MBOX_PRINT(0, LE_SCAN, false);
  519         BT_MBOX_PRINT(0, LE_ADV, false);
  520         BT_MBOX_PRINT(0, LE_MAX_TX_POWER, false);
  521         BT_MBOX_PRINT(0, OPEN_CON_1, true);
  522 
  523         pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw1:\n");
  524 
  525         BT_MBOX_PRINT(1, BR_MAX_TX_POWER, false);
  526         BT_MBOX_PRINT(1, IP_SR, false);
  527         BT_MBOX_PRINT(1, LE_MSTR, false);
  528         BT_MBOX_PRINT(1, AGGR_TRFC_LD, false);
  529         BT_MBOX_PRINT(1, MSG_TYPE, false);
  530         BT_MBOX_PRINT(1, SSN, true);
  531 
  532         pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw2:\n");
  533 
  534         BT_MBOX_PRINT(2, SNIFF_ACT, false);
  535         BT_MBOX_PRINT(2, PAG, false);
  536         BT_MBOX_PRINT(2, INQUIRY, false);
  537         BT_MBOX_PRINT(2, CONN, false);
  538         BT_MBOX_PRINT(2, SNIFF_INTERVAL, false);
  539         BT_MBOX_PRINT(2, DISC, false);
  540         BT_MBOX_PRINT(2, SCO_TX_ACT, false);
  541         BT_MBOX_PRINT(2, SCO_RX_ACT, false);
  542         BT_MBOX_PRINT(2, ESCO_RE_TX, false);
  543         BT_MBOX_PRINT(2, SCO_DURATION, true);
  544 
  545         pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw3:\n");
  546 
  547         BT_MBOX_PRINT(3, SCO_STATE, false);
  548         BT_MBOX_PRINT(3, SNIFF_STATE, false);
  549         BT_MBOX_PRINT(3, A2DP_STATE, false);
  550         BT_MBOX_PRINT(3, A2DP_SRC, false);
  551         BT_MBOX_PRINT(3, ACL_STATE, false);
  552         BT_MBOX_PRINT(3, MSTR_STATE, false);
  553         BT_MBOX_PRINT(3, OBX_STATE, false);
  554         BT_MBOX_PRINT(3, OPEN_CON_2, false);
  555         BT_MBOX_PRINT(3, TRAFFIC_LOAD, false);
  556         BT_MBOX_PRINT(3, CHL_SEQN_LSB, false);
  557         BT_MBOX_PRINT(3, INBAND_P, false);
  558         BT_MBOX_PRINT(3, MSG_TYPE_2, false);
  559         BT_MBOX_PRINT(3, SSN_2, false);
  560         BT_MBOX_PRINT(3, UPDATE_REQUEST, true);
  561 
  562         return pos;
  563 }
  564 
  565 static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf,
  566                                        size_t count, loff_t *ppos)
  567 {
  568         struct iwl_mvm *mvm = file->private_data;
  569         struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif;
  570         char *buf;
  571         int ret, pos = 0, bufsz = sizeof(char) * 1024;
  572 
  573         buf = kmalloc(bufsz, GFP_KERNEL);
  574         if (!buf)
  575                 return -ENOMEM;
  576 
  577         mutex_lock(&mvm->mutex);
  578 
  579         pos += iwl_mvm_coex_dump_mbox(notif, buf, pos, bufsz);
  580 
  581         pos += scnprintf(buf + pos, bufsz - pos, "bt_ci_compliance = %d\n",
  582                          notif->bt_ci_compliance);
  583         pos += scnprintf(buf + pos, bufsz - pos, "primary_ch_lut = %d\n",
  584                          le32_to_cpu(notif->primary_ch_lut));
  585         pos += scnprintf(buf + pos, bufsz - pos, "secondary_ch_lut = %d\n",
  586                          le32_to_cpu(notif->secondary_ch_lut));
  587         pos += scnprintf(buf + pos,
  588                          bufsz - pos, "bt_activity_grading = %d\n",
  589                          le32_to_cpu(notif->bt_activity_grading));
  590         pos += scnprintf(buf + pos, bufsz - pos, "bt_rrc = %d\n",
  591                          notif->rrc_status & 0xF);
  592         pos += scnprintf(buf + pos, bufsz - pos, "bt_ttc = %d\n",
  593                          notif->ttc_status & 0xF);
  594 
  595         pos += scnprintf(buf + pos, bufsz - pos, "sync_sco = %d\n",
  596                          IWL_MVM_BT_COEX_SYNC2SCO);
  597         pos += scnprintf(buf + pos, bufsz - pos, "mplut = %d\n",
  598                          IWL_MVM_BT_COEX_MPLUT);
  599 
  600         mutex_unlock(&mvm->mutex);
  601 
  602         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  603         kfree(buf);
  604 
  605         return ret;
  606 }
  607 #undef BT_MBOX_PRINT
  608 
  609 static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf,
  610                                      size_t count, loff_t *ppos)
  611 {
  612         struct iwl_mvm *mvm = file->private_data;
  613         struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd;
  614         char buf[256];
  615         int bufsz = sizeof(buf);
  616         int pos = 0;
  617 
  618         mutex_lock(&mvm->mutex);
  619 
  620         pos += scnprintf(buf + pos, bufsz - pos, "Channel inhibition CMD\n");
  621         pos += scnprintf(buf + pos, bufsz - pos,
  622                          "\tPrimary Channel Bitmap 0x%016llx\n",
  623                          le64_to_cpu(cmd->bt_primary_ci));
  624         pos += scnprintf(buf + pos, bufsz - pos,
  625                          "\tSecondary Channel Bitmap 0x%016llx\n",
  626                          le64_to_cpu(cmd->bt_secondary_ci));
  627 
  628         mutex_unlock(&mvm->mutex);
  629 
  630         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  631 }
  632 
  633 static ssize_t
  634 iwl_dbgfs_bt_tx_prio_write(struct iwl_mvm *mvm, char *buf,
  635                            size_t count, loff_t *ppos)
  636 {
  637         u32 bt_tx_prio;
  638 
  639         if (sscanf(buf, "%u", &bt_tx_prio) != 1)
  640                 return -EINVAL;
  641         if (bt_tx_prio > 4)
  642                 return -EINVAL;
  643 
  644         mvm->bt_tx_prio = bt_tx_prio;
  645 
  646         return count;
  647 }
  648 
  649 static ssize_t
  650 iwl_dbgfs_bt_force_ant_write(struct iwl_mvm *mvm, char *buf,
  651                              size_t count, loff_t *ppos)
  652 {
  653         static const char * const modes_str[BT_FORCE_ANT_MAX] = {
  654                 [BT_FORCE_ANT_DIS] = "dis",
  655                 [BT_FORCE_ANT_AUTO] = "auto",
  656                 [BT_FORCE_ANT_BT] = "bt",
  657                 [BT_FORCE_ANT_WIFI] = "wifi",
  658         };
  659         int ret, bt_force_ant_mode;
  660 
  661         ret = match_string(modes_str, ARRAY_SIZE(modes_str), buf);
  662         if (ret < 0)
  663                 return ret;
  664 
  665         bt_force_ant_mode = ret;
  666         ret = 0;
  667         mutex_lock(&mvm->mutex);
  668         if (mvm->bt_force_ant_mode == bt_force_ant_mode)
  669                 goto out;
  670 
  671         mvm->bt_force_ant_mode = bt_force_ant_mode;
  672         IWL_DEBUG_COEX(mvm, "Force mode: %s\n",
  673                        modes_str[mvm->bt_force_ant_mode]);
  674 
  675         if (iwl_mvm_firmware_running(mvm))
  676                 ret = iwl_mvm_send_bt_init_conf(mvm);
  677         else
  678                 ret = 0;
  679 
  680 out:
  681         mutex_unlock(&mvm->mutex);
  682         return ret ?: count;
  683 }
  684 
  685 static ssize_t iwl_dbgfs_fw_ver_read(struct file *file, char __user *user_buf,
  686                                      size_t count, loff_t *ppos)
  687 {
  688         struct iwl_mvm *mvm = file->private_data;
  689         char *buff, *pos, *endpos;
  690         static const size_t bufsz = 1024;
  691         int ret;
  692 
  693         buff = kmalloc(bufsz, GFP_KERNEL);
  694         if (!buff)
  695                 return -ENOMEM;
  696 
  697         pos = buff;
  698         endpos = pos + bufsz;
  699 
  700         pos += scnprintf(pos, endpos - pos, "FW prefix: %s\n",
  701                          mvm->trans->cfg->fw_name_pre);
  702         pos += scnprintf(pos, endpos - pos, "FW: %s\n",
  703                          mvm->fwrt.fw->human_readable);
  704         pos += scnprintf(pos, endpos - pos, "Device: %s\n",
  705                          mvm->fwrt.trans->name);
  706         pos += scnprintf(pos, endpos - pos, "Bus: %s\n",
  707 #if defined(__linux__)
  708                          mvm->fwrt.dev->bus->name);
  709 #elif defined(__FreeBSD__)
  710                         "<bus>");
  711 #endif
  712 
  713         ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff);
  714         kfree(buff);
  715 
  716         return ret;
  717 }
  718 
  719 static ssize_t iwl_dbgfs_phy_integration_ver_read(struct file *file,
  720                                                   char __user *user_buf,
  721                                                   size_t count, loff_t *ppos)
  722 {
  723         struct iwl_mvm *mvm = file->private_data;
  724         char *buf;
  725         size_t bufsz;
  726         int pos;
  727         ssize_t ret;
  728 
  729         bufsz = mvm->fw->phy_integration_ver_len + 2;
  730         buf = kmalloc(bufsz, GFP_KERNEL);
  731         if (!buf)
  732                 return -ENOMEM;
  733 
  734         pos = scnprintf(buf, bufsz, "%.*s\n", mvm->fw->phy_integration_ver_len,
  735                         mvm->fw->phy_integration_ver);
  736 
  737         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  738 
  739         kfree(buf);
  740         return ret;
  741 }
  742 
  743 #define PRINT_STATS_LE32(_struct, _memb)                                \
  744                          pos += scnprintf(buf + pos, bufsz - pos,       \
  745                                           fmt_table, #_memb,            \
  746                                           le32_to_cpu(_struct->_memb))
  747 
  748 static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file,
  749                                           char __user *user_buf, size_t count,
  750                                           loff_t *ppos)
  751 {
  752         struct iwl_mvm *mvm = file->private_data;
  753         static const char *fmt_table = "\t%-30s %10u\n";
  754         static const char *fmt_header = "%-32s\n";
  755         int pos = 0;
  756         char *buf;
  757         int ret;
  758         size_t bufsz;
  759 
  760         if (iwl_mvm_has_new_rx_stats_api(mvm))
  761                 bufsz = ((sizeof(struct mvm_statistics_rx) /
  762                           sizeof(__le32)) * 43) + (4 * 33) + 1;
  763         else
  764                 /* 43 = size of each data line; 33 = size of each header */
  765                 bufsz = ((sizeof(struct mvm_statistics_rx_v3) /
  766                           sizeof(__le32)) * 43) + (4 * 33) + 1;
  767 
  768         buf = kzalloc(bufsz, GFP_KERNEL);
  769         if (!buf)
  770                 return -ENOMEM;
  771 
  772         mutex_lock(&mvm->mutex);
  773 
  774         if (iwl_mvm_firmware_running(mvm))
  775                 iwl_mvm_request_statistics(mvm, false);
  776 
  777         pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
  778                          "Statistics_Rx - OFDM");
  779         if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
  780                 struct mvm_statistics_rx_phy_v2 *ofdm = &mvm->rx_stats_v3.ofdm;
  781 
  782                 PRINT_STATS_LE32(ofdm, ina_cnt);
  783                 PRINT_STATS_LE32(ofdm, fina_cnt);
  784                 PRINT_STATS_LE32(ofdm, plcp_err);
  785                 PRINT_STATS_LE32(ofdm, crc32_err);
  786                 PRINT_STATS_LE32(ofdm, overrun_err);
  787                 PRINT_STATS_LE32(ofdm, early_overrun_err);
  788                 PRINT_STATS_LE32(ofdm, crc32_good);
  789                 PRINT_STATS_LE32(ofdm, false_alarm_cnt);
  790                 PRINT_STATS_LE32(ofdm, fina_sync_err_cnt);
  791                 PRINT_STATS_LE32(ofdm, sfd_timeout);
  792                 PRINT_STATS_LE32(ofdm, fina_timeout);
  793                 PRINT_STATS_LE32(ofdm, unresponded_rts);
  794                 PRINT_STATS_LE32(ofdm, rxe_frame_lmt_overrun);
  795                 PRINT_STATS_LE32(ofdm, sent_ack_cnt);
  796                 PRINT_STATS_LE32(ofdm, sent_cts_cnt);
  797                 PRINT_STATS_LE32(ofdm, sent_ba_rsp_cnt);
  798                 PRINT_STATS_LE32(ofdm, dsp_self_kill);
  799                 PRINT_STATS_LE32(ofdm, mh_format_err);
  800                 PRINT_STATS_LE32(ofdm, re_acq_main_rssi_sum);
  801                 PRINT_STATS_LE32(ofdm, reserved);
  802         } else {
  803                 struct mvm_statistics_rx_phy *ofdm = &mvm->rx_stats.ofdm;
  804 
  805                 PRINT_STATS_LE32(ofdm, unresponded_rts);
  806                 PRINT_STATS_LE32(ofdm, rxe_frame_lmt_overrun);
  807                 PRINT_STATS_LE32(ofdm, sent_ba_rsp_cnt);
  808                 PRINT_STATS_LE32(ofdm, dsp_self_kill);
  809                 PRINT_STATS_LE32(ofdm, reserved);
  810         }
  811 
  812         pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
  813                          "Statistics_Rx - CCK");
  814         if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
  815                 struct mvm_statistics_rx_phy_v2 *cck = &mvm->rx_stats_v3.cck;
  816 
  817                 PRINT_STATS_LE32(cck, ina_cnt);
  818                 PRINT_STATS_LE32(cck, fina_cnt);
  819                 PRINT_STATS_LE32(cck, plcp_err);
  820                 PRINT_STATS_LE32(cck, crc32_err);
  821                 PRINT_STATS_LE32(cck, overrun_err);
  822                 PRINT_STATS_LE32(cck, early_overrun_err);
  823                 PRINT_STATS_LE32(cck, crc32_good);
  824                 PRINT_STATS_LE32(cck, false_alarm_cnt);
  825                 PRINT_STATS_LE32(cck, fina_sync_err_cnt);
  826                 PRINT_STATS_LE32(cck, sfd_timeout);
  827                 PRINT_STATS_LE32(cck, fina_timeout);
  828                 PRINT_STATS_LE32(cck, unresponded_rts);
  829                 PRINT_STATS_LE32(cck, rxe_frame_lmt_overrun);
  830                 PRINT_STATS_LE32(cck, sent_ack_cnt);
  831                 PRINT_STATS_LE32(cck, sent_cts_cnt);
  832                 PRINT_STATS_LE32(cck, sent_ba_rsp_cnt);
  833                 PRINT_STATS_LE32(cck, dsp_self_kill);
  834                 PRINT_STATS_LE32(cck, mh_format_err);
  835                 PRINT_STATS_LE32(cck, re_acq_main_rssi_sum);
  836                 PRINT_STATS_LE32(cck, reserved);
  837         } else {
  838                 struct mvm_statistics_rx_phy *cck = &mvm->rx_stats.cck;
  839 
  840                 PRINT_STATS_LE32(cck, unresponded_rts);
  841                 PRINT_STATS_LE32(cck, rxe_frame_lmt_overrun);
  842                 PRINT_STATS_LE32(cck, sent_ba_rsp_cnt);
  843                 PRINT_STATS_LE32(cck, dsp_self_kill);
  844                 PRINT_STATS_LE32(cck, reserved);
  845         }
  846 
  847         pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
  848                          "Statistics_Rx - GENERAL");
  849         if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
  850                 struct mvm_statistics_rx_non_phy_v3 *general =
  851                         &mvm->rx_stats_v3.general;
  852 
  853                 PRINT_STATS_LE32(general, bogus_cts);
  854                 PRINT_STATS_LE32(general, bogus_ack);
  855                 PRINT_STATS_LE32(general, non_bssid_frames);
  856                 PRINT_STATS_LE32(general, filtered_frames);
  857                 PRINT_STATS_LE32(general, non_channel_beacons);
  858                 PRINT_STATS_LE32(general, channel_beacons);
  859                 PRINT_STATS_LE32(general, num_missed_bcon);
  860                 PRINT_STATS_LE32(general, adc_rx_saturation_time);
  861                 PRINT_STATS_LE32(general, ina_detection_search_time);
  862                 PRINT_STATS_LE32(general, beacon_silence_rssi_a);
  863                 PRINT_STATS_LE32(general, beacon_silence_rssi_b);
  864                 PRINT_STATS_LE32(general, beacon_silence_rssi_c);
  865                 PRINT_STATS_LE32(general, interference_data_flag);
  866                 PRINT_STATS_LE32(general, channel_load);
  867                 PRINT_STATS_LE32(general, dsp_false_alarms);
  868                 PRINT_STATS_LE32(general, beacon_rssi_a);
  869                 PRINT_STATS_LE32(general, beacon_rssi_b);
  870                 PRINT_STATS_LE32(general, beacon_rssi_c);
  871                 PRINT_STATS_LE32(general, beacon_energy_a);
  872                 PRINT_STATS_LE32(general, beacon_energy_b);
  873                 PRINT_STATS_LE32(general, beacon_energy_c);
  874                 PRINT_STATS_LE32(general, num_bt_kills);
  875                 PRINT_STATS_LE32(general, mac_id);
  876                 PRINT_STATS_LE32(general, directed_data_mpdu);
  877         } else {
  878                 struct mvm_statistics_rx_non_phy *general =
  879                         &mvm->rx_stats.general;
  880 
  881                 PRINT_STATS_LE32(general, bogus_cts);
  882                 PRINT_STATS_LE32(general, bogus_ack);
  883                 PRINT_STATS_LE32(general, non_channel_beacons);
  884                 PRINT_STATS_LE32(general, channel_beacons);
  885                 PRINT_STATS_LE32(general, num_missed_bcon);
  886                 PRINT_STATS_LE32(general, adc_rx_saturation_time);
  887                 PRINT_STATS_LE32(general, ina_detection_search_time);
  888                 PRINT_STATS_LE32(general, beacon_silence_rssi_a);
  889                 PRINT_STATS_LE32(general, beacon_silence_rssi_b);
  890                 PRINT_STATS_LE32(general, beacon_silence_rssi_c);
  891                 PRINT_STATS_LE32(general, interference_data_flag);
  892                 PRINT_STATS_LE32(general, channel_load);
  893                 PRINT_STATS_LE32(general, beacon_rssi_a);
  894                 PRINT_STATS_LE32(general, beacon_rssi_b);
  895                 PRINT_STATS_LE32(general, beacon_rssi_c);
  896                 PRINT_STATS_LE32(general, beacon_energy_a);
  897                 PRINT_STATS_LE32(general, beacon_energy_b);
  898                 PRINT_STATS_LE32(general, beacon_energy_c);
  899                 PRINT_STATS_LE32(general, num_bt_kills);
  900                 PRINT_STATS_LE32(general, mac_id);
  901         }
  902 
  903         pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
  904                          "Statistics_Rx - HT");
  905         if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
  906                 struct mvm_statistics_rx_ht_phy_v1 *ht =
  907                         &mvm->rx_stats_v3.ofdm_ht;
  908 
  909                 PRINT_STATS_LE32(ht, plcp_err);
  910                 PRINT_STATS_LE32(ht, overrun_err);
  911                 PRINT_STATS_LE32(ht, early_overrun_err);
  912                 PRINT_STATS_LE32(ht, crc32_good);
  913                 PRINT_STATS_LE32(ht, crc32_err);
  914                 PRINT_STATS_LE32(ht, mh_format_err);
  915                 PRINT_STATS_LE32(ht, agg_crc32_good);
  916                 PRINT_STATS_LE32(ht, agg_mpdu_cnt);
  917                 PRINT_STATS_LE32(ht, agg_cnt);
  918                 PRINT_STATS_LE32(ht, unsupport_mcs);
  919         } else {
  920                 struct mvm_statistics_rx_ht_phy *ht =
  921                         &mvm->rx_stats.ofdm_ht;
  922 
  923                 PRINT_STATS_LE32(ht, mh_format_err);
  924                 PRINT_STATS_LE32(ht, agg_mpdu_cnt);
  925                 PRINT_STATS_LE32(ht, agg_cnt);
  926                 PRINT_STATS_LE32(ht, unsupport_mcs);
  927         }
  928 
  929         mutex_unlock(&mvm->mutex);
  930 
  931         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  932         kfree(buf);
  933 
  934         return ret;
  935 }
  936 #undef PRINT_STAT_LE32
  937 
  938 static ssize_t iwl_dbgfs_frame_stats_read(struct iwl_mvm *mvm,
  939                                           char __user *user_buf, size_t count,
  940                                           loff_t *ppos,
  941                                           struct iwl_mvm_frame_stats *stats)
  942 {
  943         char *buff, *pos, *endpos;
  944         int idx, i;
  945         int ret;
  946         static const size_t bufsz = 1024;
  947 
  948         buff = kmalloc(bufsz, GFP_KERNEL);
  949         if (!buff)
  950                 return -ENOMEM;
  951 
  952         spin_lock_bh(&mvm->drv_stats_lock);
  953 
  954         pos = buff;
  955         endpos = pos + bufsz;
  956 
  957         pos += scnprintf(pos, endpos - pos,
  958                          "Legacy/HT/VHT\t:\t%d/%d/%d\n",
  959                          stats->legacy_frames,
  960                          stats->ht_frames,
  961                          stats->vht_frames);
  962         pos += scnprintf(pos, endpos - pos, "20/40/80\t:\t%d/%d/%d\n",
  963                          stats->bw_20_frames,
  964                          stats->bw_40_frames,
  965                          stats->bw_80_frames);
  966         pos += scnprintf(pos, endpos - pos, "NGI/SGI\t\t:\t%d/%d\n",
  967                          stats->ngi_frames,
  968                          stats->sgi_frames);
  969         pos += scnprintf(pos, endpos - pos, "SISO/MIMO2\t:\t%d/%d\n",
  970                          stats->siso_frames,
  971                          stats->mimo2_frames);
  972         pos += scnprintf(pos, endpos - pos, "FAIL/SCSS\t:\t%d/%d\n",
  973                          stats->fail_frames,
  974                          stats->success_frames);
  975         pos += scnprintf(pos, endpos - pos, "MPDUs agg\t:\t%d\n",
  976                          stats->agg_frames);
  977         pos += scnprintf(pos, endpos - pos, "A-MPDUs\t\t:\t%d\n",
  978                          stats->ampdu_count);
  979         pos += scnprintf(pos, endpos - pos, "Avg MPDUs/A-MPDU:\t%d\n",
  980                          stats->ampdu_count > 0 ?
  981                          (stats->agg_frames / stats->ampdu_count) : 0);
  982 
  983         pos += scnprintf(pos, endpos - pos, "Last Rates\n");
  984 
  985         idx = stats->last_frame_idx - 1;
  986         for (i = 0; i < ARRAY_SIZE(stats->last_rates); i++) {
  987                 idx = (idx + 1) % ARRAY_SIZE(stats->last_rates);
  988                 if (stats->last_rates[idx] == 0)
  989                         continue;
  990                 pos += scnprintf(pos, endpos - pos, "Rate[%d]: ",
  991                                  (int)(ARRAY_SIZE(stats->last_rates) - i));
  992                 pos += rs_pretty_print_rate_v1(pos, endpos - pos,
  993                                                stats->last_rates[idx]);
  994                 if (pos < endpos - 1)
  995                         *pos++ = '\n';
  996         }
  997         spin_unlock_bh(&mvm->drv_stats_lock);
  998 
  999         ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff);
 1000         kfree(buff);
 1001 
 1002         return ret;
 1003 }
 1004 
 1005 static ssize_t iwl_dbgfs_drv_rx_stats_read(struct file *file,
 1006                                            char __user *user_buf, size_t count,
 1007                                            loff_t *ppos)
 1008 {
 1009         struct iwl_mvm *mvm = file->private_data;
 1010 
 1011         return iwl_dbgfs_frame_stats_read(mvm, user_buf, count, ppos,
 1012                                           &mvm->drv_rx_stats);
 1013 }
 1014 
 1015 static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
 1016                                           size_t count, loff_t *ppos)
 1017 {
 1018         int __maybe_unused ret;
 1019 
 1020         if (!iwl_mvm_firmware_running(mvm))
 1021                 return -EIO;
 1022 
 1023         mutex_lock(&mvm->mutex);
 1024 
 1025         /* allow one more restart that we're provoking here */
 1026         if (mvm->fw_restart >= 0)
 1027                 mvm->fw_restart++;
 1028 
 1029         if (count == 6 && !strcmp(buf, "nolog\n")) {
 1030                 set_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, &mvm->status);
 1031                 set_bit(STATUS_SUPPRESS_CMD_ERROR_ONCE, &mvm->trans->status);
 1032         }
 1033 
 1034         /* take the return value to make compiler happy - it will fail anyway */
 1035         ret = iwl_mvm_send_cmd_pdu(mvm,
 1036                                    WIDE_ID(LONG_GROUP, REPLY_ERROR),
 1037                                    0, 0, NULL);
 1038 
 1039         mutex_unlock(&mvm->mutex);
 1040 
 1041         return count;
 1042 }
 1043 
 1044 static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf,
 1045                                       size_t count, loff_t *ppos)
 1046 {
 1047         if (!iwl_mvm_firmware_running(mvm))
 1048                 return -EIO;
 1049 
 1050         if (count == 6 && !strcmp(buf, "nolog\n"))
 1051                 set_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, &mvm->status);
 1052 
 1053         iwl_force_nmi(mvm->trans);
 1054 
 1055         return count;
 1056 }
 1057 
 1058 static ssize_t
 1059 iwl_dbgfs_scan_ant_rxchain_read(struct file *file,
 1060                                 char __user *user_buf,
 1061                                 size_t count, loff_t *ppos)
 1062 {
 1063         struct iwl_mvm *mvm = file->private_data;
 1064         int pos = 0;
 1065         char buf[32];
 1066         const size_t bufsz = sizeof(buf);
 1067 
 1068         /* print which antennas were set for the scan command by the user */
 1069         pos += scnprintf(buf + pos, bufsz - pos, "Antennas for scan: ");
 1070         if (mvm->scan_rx_ant & ANT_A)
 1071                 pos += scnprintf(buf + pos, bufsz - pos, "A");
 1072         if (mvm->scan_rx_ant & ANT_B)
 1073                 pos += scnprintf(buf + pos, bufsz - pos, "B");
 1074         pos += scnprintf(buf + pos, bufsz - pos, " (%hhx)\n", mvm->scan_rx_ant);
 1075 
 1076         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 1077 }
 1078 
 1079 static ssize_t
 1080 iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf,
 1081                                  size_t count, loff_t *ppos)
 1082 {
 1083         u8 scan_rx_ant;
 1084 
 1085         if (!iwl_mvm_firmware_running(mvm))
 1086                 return -EIO;
 1087 
 1088         if (sscanf(buf, "%hhx", &scan_rx_ant) != 1)
 1089                 return -EINVAL;
 1090         if (scan_rx_ant > ANT_ABC)
 1091                 return -EINVAL;
 1092         if (scan_rx_ant & ~(iwl_mvm_get_valid_rx_ant(mvm)))
 1093                 return -EINVAL;
 1094 
 1095         if (mvm->scan_rx_ant != scan_rx_ant) {
 1096                 mvm->scan_rx_ant = scan_rx_ant;
 1097                 if (fw_has_capa(&mvm->fw->ucode_capa,
 1098                                 IWL_UCODE_TLV_CAPA_UMAC_SCAN))
 1099                         iwl_mvm_config_scan(mvm);
 1100         }
 1101 
 1102         return count;
 1103 }
 1104 
 1105 static ssize_t iwl_dbgfs_indirection_tbl_write(struct iwl_mvm *mvm,
 1106                                                char *buf, size_t count,
 1107                                                loff_t *ppos)
 1108 {
 1109         struct iwl_rss_config_cmd cmd = {
 1110                 .flags = cpu_to_le32(IWL_RSS_ENABLE),
 1111                 .hash_mask = IWL_RSS_HASH_TYPE_IPV4_TCP |
 1112                              IWL_RSS_HASH_TYPE_IPV4_UDP |
 1113                              IWL_RSS_HASH_TYPE_IPV4_PAYLOAD |
 1114                              IWL_RSS_HASH_TYPE_IPV6_TCP |
 1115                              IWL_RSS_HASH_TYPE_IPV6_UDP |
 1116                              IWL_RSS_HASH_TYPE_IPV6_PAYLOAD,
 1117         };
 1118         int ret, i, num_repeats, nbytes = count / 2;
 1119 
 1120         ret = hex2bin(cmd.indirection_table, buf, nbytes);
 1121         if (ret)
 1122                 return ret;
 1123 
 1124         /*
 1125          * The input is the redirection table, partial or full.
 1126          * Repeat the pattern if needed.
 1127          * For example, input of 01020F will be repeated 42 times,
 1128          * indirecting RSS hash results to queues 1, 2, 15 (skipping
 1129          * queues 3 - 14).
 1130          */
 1131         num_repeats = ARRAY_SIZE(cmd.indirection_table) / nbytes;
 1132         for (i = 1; i < num_repeats; i++)
 1133                 memcpy(&cmd.indirection_table[i * nbytes],
 1134                        cmd.indirection_table, nbytes);
 1135         /* handle cut in the middle pattern for the last places */
 1136         memcpy(&cmd.indirection_table[i * nbytes], cmd.indirection_table,
 1137                ARRAY_SIZE(cmd.indirection_table) % nbytes);
 1138 
 1139         netdev_rss_key_fill(cmd.secret_key, sizeof(cmd.secret_key));
 1140 
 1141         mutex_lock(&mvm->mutex);
 1142         if (iwl_mvm_firmware_running(mvm))
 1143                 ret = iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0,
 1144                                            sizeof(cmd), &cmd);
 1145         else
 1146                 ret = 0;
 1147         mutex_unlock(&mvm->mutex);
 1148 
 1149         return ret ?: count;
 1150 }
 1151 
 1152 static ssize_t iwl_dbgfs_inject_packet_write(struct iwl_mvm *mvm,
 1153                                              char *buf, size_t count,
 1154                                              loff_t *ppos)
 1155 {
 1156         struct iwl_op_mode *opmode = container_of((void *)mvm,
 1157                                                   struct iwl_op_mode,
 1158                                                   op_mode_specific);
 1159         struct iwl_rx_cmd_buffer rxb = {
 1160                 ._rx_page_order = 0,
 1161                 .truesize = 0, /* not used */
 1162                 ._offset = 0,
 1163         };
 1164         struct iwl_rx_packet *pkt;
 1165         int bin_len = count / 2;
 1166         int ret = -EINVAL;
 1167 
 1168         if (!iwl_mvm_firmware_running(mvm))
 1169                 return -EIO;
 1170 
 1171         /* supporting only MQ RX */
 1172         if (!mvm->trans->trans_cfg->mq_rx_supported)
 1173                 return -ENOTSUPP;
 1174 
 1175         rxb._page = alloc_pages(GFP_ATOMIC, 0);
 1176         if (!rxb._page)
 1177                 return -ENOMEM;
 1178         pkt = rxb_addr(&rxb);
 1179 
 1180         ret = hex2bin(page_address(rxb._page), buf, bin_len);
 1181         if (ret)
 1182                 goto out;
 1183 
 1184         /* avoid invalid memory access and malformed packet */
 1185         if (bin_len < sizeof(*pkt) ||
 1186             bin_len != sizeof(*pkt) + iwl_rx_packet_payload_len(pkt))
 1187                 goto out;
 1188 
 1189         local_bh_disable();
 1190         iwl_mvm_rx_mq(opmode, NULL, &rxb);
 1191         local_bh_enable();
 1192         ret = 0;
 1193 
 1194 out:
 1195         iwl_free_rxb(&rxb);
 1196 
 1197         return ret ?: count;
 1198 }
 1199 
 1200 static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len)
 1201 {
 1202         struct ieee80211_vif *vif;
 1203         struct iwl_mvm_vif *mvmvif;
 1204         struct sk_buff *beacon;
 1205         struct ieee80211_tx_info *info;
 1206         struct iwl_mac_beacon_cmd beacon_cmd = {};
 1207         u8 rate;
 1208         int i;
 1209 
 1210         len /= 2;
 1211 
 1212         /* Element len should be represented by u8 */
 1213         if (len >= U8_MAX)
 1214                 return -EINVAL;
 1215 
 1216         if (!iwl_mvm_firmware_running(mvm))
 1217                 return -EIO;
 1218 
 1219         if (!iwl_mvm_has_new_tx_api(mvm) &&
 1220             !fw_has_api(&mvm->fw->ucode_capa,
 1221                         IWL_UCODE_TLV_API_NEW_BEACON_TEMPLATE))
 1222                 return -EINVAL;
 1223 
 1224         mutex_lock(&mvm->mutex);
 1225 
 1226         for (i = 0; i < NUM_MAC_INDEX_DRIVER; i++) {
 1227                 vif = iwl_mvm_rcu_dereference_vif_id(mvm, i, false);
 1228                 if (!vif)
 1229                         continue;
 1230 
 1231                 if (vif->type == NL80211_IFTYPE_AP)
 1232                         break;
 1233         }
 1234 
 1235         if (i == NUM_MAC_INDEX_DRIVER || !vif)
 1236                 goto out_err;
 1237 
 1238         mvm->hw->extra_beacon_tailroom = len;
 1239 
 1240         beacon = ieee80211_beacon_get_template(mvm->hw, vif, NULL, 0);
 1241         if (!beacon)
 1242                 goto out_err;
 1243 
 1244         if (len && hex2bin(skb_put_zero(beacon, len), bin, len)) {
 1245                 dev_kfree_skb(beacon);
 1246                 goto out_err;
 1247         }
 1248 
 1249         mvm->beacon_inject_active = true;
 1250 
 1251         mvmvif = iwl_mvm_vif_from_mac80211(vif);
 1252         info = IEEE80211_SKB_CB(beacon);
 1253         rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif);
 1254 
 1255         beacon_cmd.flags =
 1256                 cpu_to_le16(iwl_mvm_mac_ctxt_get_beacon_flags(mvm->fw, rate));
 1257         beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len);
 1258         beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id);
 1259 
 1260         iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx,
 1261                                  &beacon_cmd.tim_size,
 1262                                  beacon->data, beacon->len);
 1263 
 1264         iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd,
 1265                                          sizeof(beacon_cmd));
 1266         mutex_unlock(&mvm->mutex);
 1267 
 1268         dev_kfree_skb(beacon);
 1269 
 1270         return 0;
 1271 
 1272 out_err:
 1273         mutex_unlock(&mvm->mutex);
 1274         return -EINVAL;
 1275 }
 1276 
 1277 static ssize_t iwl_dbgfs_inject_beacon_ie_write(struct iwl_mvm *mvm,
 1278                                                 char *buf, size_t count,
 1279                                                 loff_t *ppos)
 1280 {
 1281         int ret = _iwl_dbgfs_inject_beacon_ie(mvm, buf, count);
 1282 
 1283         mvm->hw->extra_beacon_tailroom = 0;
 1284         return ret ?: count;
 1285 }
 1286 
 1287 static ssize_t iwl_dbgfs_inject_beacon_ie_restore_write(struct iwl_mvm *mvm,
 1288                                                         char *buf,
 1289                                                         size_t count,
 1290                                                         loff_t *ppos)
 1291 {
 1292         int ret = _iwl_dbgfs_inject_beacon_ie(mvm, NULL, 0);
 1293 
 1294         mvm->hw->extra_beacon_tailroom = 0;
 1295         mvm->beacon_inject_active = false;
 1296         return ret ?: count;
 1297 }
 1298 
 1299 static ssize_t iwl_dbgfs_fw_dbg_conf_read(struct file *file,
 1300                                           char __user *user_buf,
 1301                                           size_t count, loff_t *ppos)
 1302 {
 1303         struct iwl_mvm *mvm = file->private_data;
 1304         int conf;
 1305         char buf[8];
 1306         const size_t bufsz = sizeof(buf);
 1307         int pos = 0;
 1308 
 1309         mutex_lock(&mvm->mutex);
 1310         conf = mvm->fwrt.dump.conf;
 1311         mutex_unlock(&mvm->mutex);
 1312 
 1313         pos += scnprintf(buf + pos, bufsz - pos, "%d\n", conf);
 1314 
 1315         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 1316 }
 1317 
 1318 static ssize_t iwl_dbgfs_fw_dbg_conf_write(struct iwl_mvm *mvm,
 1319                                            char *buf, size_t count,
 1320                                            loff_t *ppos)
 1321 {
 1322         unsigned int conf_id;
 1323         int ret;
 1324 
 1325         if (!iwl_mvm_firmware_running(mvm))
 1326                 return -EIO;
 1327 
 1328         ret = kstrtouint(buf, 0, &conf_id);
 1329         if (ret)
 1330                 return ret;
 1331 
 1332         if (WARN_ON(conf_id >= FW_DBG_CONF_MAX))
 1333                 return -EINVAL;
 1334 
 1335         mutex_lock(&mvm->mutex);
 1336         ret = iwl_fw_start_dbg_conf(&mvm->fwrt, conf_id);
 1337         mutex_unlock(&mvm->mutex);
 1338 
 1339         return ret ?: count;
 1340 }
 1341 
 1342 static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm,
 1343                                               char *buf, size_t count,
 1344                                               loff_t *ppos)
 1345 {
 1346         if (count == 0)
 1347                 return 0;
 1348 
 1349         iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_USER_TRIGGER,
 1350                                NULL);
 1351 
 1352         iwl_fw_dbg_collect(&mvm->fwrt, FW_DBG_TRIGGER_USER, buf,
 1353                            (count - 1), NULL);
 1354 
 1355         return count;
 1356 }
 1357 
 1358 static ssize_t iwl_dbgfs_dbg_time_point_write(struct iwl_mvm *mvm,
 1359                                               char *buf, size_t count,
 1360                                               loff_t *ppos)
 1361 {
 1362         u32 timepoint;
 1363 
 1364         if (kstrtou32(buf, 0, &timepoint))
 1365                 return -EINVAL;
 1366 
 1367         if (timepoint == IWL_FW_INI_TIME_POINT_INVALID ||
 1368             timepoint >= IWL_FW_INI_TIME_POINT_NUM)
 1369                 return -EINVAL;
 1370 
 1371         iwl_dbg_tlv_time_point(&mvm->fwrt, timepoint, NULL);
 1372 
 1373         return count;
 1374 }
 1375 
 1376 #define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
 1377         _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm)
 1378 #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
 1379         _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm)
 1380 #define MVM_DEBUGFS_ADD_FILE_ALIAS(alias, name, parent, mode) do {      \
 1381                 debugfs_create_file(alias, mode, parent, mvm,           \
 1382                                     &iwl_dbgfs_##name##_ops);           \
 1383         } while (0)
 1384 #define MVM_DEBUGFS_ADD_FILE(name, parent, mode) \
 1385         MVM_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode)
 1386 
 1387 #define MVM_DEBUGFS_WRITE_STA_FILE_OPS(name, bufsz) \
 1388         _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_sta)
 1389 #define MVM_DEBUGFS_READ_WRITE_STA_FILE_OPS(name, bufsz) \
 1390         _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct ieee80211_sta)
 1391 
 1392 #define MVM_DEBUGFS_ADD_STA_FILE_ALIAS(alias, name, parent, mode) do {  \
 1393                 debugfs_create_file(alias, mode, parent, sta,           \
 1394                                     &iwl_dbgfs_##name##_ops);           \
 1395         } while (0)
 1396 #define MVM_DEBUGFS_ADD_STA_FILE(name, parent, mode) \
 1397         MVM_DEBUGFS_ADD_STA_FILE_ALIAS(#name, name, parent, mode)
 1398 
 1399 static ssize_t
 1400 iwl_dbgfs_prph_reg_read(struct file *file,
 1401                         char __user *user_buf,
 1402                         size_t count, loff_t *ppos)
 1403 {
 1404         struct iwl_mvm *mvm = file->private_data;
 1405         int pos = 0;
 1406         char buf[32];
 1407         const size_t bufsz = sizeof(buf);
 1408 
 1409         if (!mvm->dbgfs_prph_reg_addr)
 1410                 return -EINVAL;
 1411 
 1412         pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n",
 1413                 mvm->dbgfs_prph_reg_addr,
 1414                 iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr));
 1415 
 1416         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 1417 }
 1418 
 1419 static ssize_t
 1420 iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
 1421                          size_t count, loff_t *ppos)
 1422 {
 1423         u8 args;
 1424         u32 value;
 1425 
 1426         args = sscanf(buf, "%i %i", &mvm->dbgfs_prph_reg_addr, &value);
 1427         /* if we only want to set the reg address - nothing more to do */
 1428         if (args == 1)
 1429                 goto out;
 1430 
 1431         /* otherwise, make sure we have both address and value */
 1432         if (args != 2)
 1433                 return -EINVAL;
 1434 
 1435         iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value);
 1436 
 1437 out:
 1438         return count;
 1439 }
 1440 
 1441 static ssize_t
 1442 iwl_dbgfs_send_echo_cmd_write(struct iwl_mvm *mvm, char *buf,
 1443                               size_t count, loff_t *ppos)
 1444 {
 1445         int ret;
 1446 
 1447         if (!iwl_mvm_firmware_running(mvm))
 1448                 return -EIO;
 1449 
 1450         mutex_lock(&mvm->mutex);
 1451         ret = iwl_mvm_send_cmd_pdu(mvm, ECHO_CMD, 0, 0, NULL);
 1452         mutex_unlock(&mvm->mutex);
 1453 
 1454         return ret ?: count;
 1455 }
 1456 
 1457 struct iwl_mvm_sniffer_apply {
 1458         struct iwl_mvm *mvm;
 1459         u8 *bssid;
 1460         u16 aid;
 1461 };
 1462 
 1463 static bool iwl_mvm_sniffer_apply(struct iwl_notif_wait_data *notif_data,
 1464                                   struct iwl_rx_packet *pkt, void *data)
 1465 {
 1466         struct iwl_mvm_sniffer_apply *apply = data;
 1467 
 1468         apply->mvm->cur_aid = cpu_to_le16(apply->aid);
 1469         memcpy(apply->mvm->cur_bssid, apply->bssid,
 1470                sizeof(apply->mvm->cur_bssid));
 1471 
 1472         return true;
 1473 }
 1474 
 1475 static ssize_t
 1476 iwl_dbgfs_he_sniffer_params_write(struct iwl_mvm *mvm, char *buf,
 1477                                   size_t count, loff_t *ppos)
 1478 {
 1479         struct iwl_notification_wait wait;
 1480         struct iwl_he_monitor_cmd he_mon_cmd = {};
 1481         struct iwl_mvm_sniffer_apply apply = {
 1482                 .mvm = mvm,
 1483         };
 1484         u16 wait_cmds[] = {
 1485                 WIDE_ID(DATA_PATH_GROUP, HE_AIR_SNIFFER_CONFIG_CMD),
 1486         };
 1487         u32 aid;
 1488         int ret;
 1489 
 1490         if (!iwl_mvm_firmware_running(mvm))
 1491                 return -EIO;
 1492 
 1493         ret = sscanf(buf, "%x %2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx", &aid,
 1494                      &he_mon_cmd.bssid[0], &he_mon_cmd.bssid[1],
 1495                      &he_mon_cmd.bssid[2], &he_mon_cmd.bssid[3],
 1496                      &he_mon_cmd.bssid[4], &he_mon_cmd.bssid[5]);
 1497         if (ret != 7)
 1498                 return -EINVAL;
 1499 
 1500         he_mon_cmd.aid = cpu_to_le16(aid);
 1501 
 1502         apply.aid = aid;
 1503         apply.bssid = (void *)he_mon_cmd.bssid;
 1504 
 1505         mutex_lock(&mvm->mutex);
 1506 
 1507         /*
 1508          * Use the notification waiter to get our function triggered
 1509          * in sequence with other RX. This ensures that frames we get
 1510          * on the RX queue _before_ the new configuration is applied
 1511          * still have mvm->cur_aid pointing to the old AID, and that
 1512          * frames on the RX queue _after_ the firmware processed the
 1513          * new configuration (and sent the response, synchronously)
 1514          * get mvm->cur_aid correctly set to the new AID.
 1515          */
 1516         iwl_init_notification_wait(&mvm->notif_wait, &wait,
 1517                                    wait_cmds, ARRAY_SIZE(wait_cmds),
 1518                                    iwl_mvm_sniffer_apply, &apply);
 1519 
 1520         ret = iwl_mvm_send_cmd_pdu(mvm,
 1521                                    WIDE_ID(DATA_PATH_GROUP, HE_AIR_SNIFFER_CONFIG_CMD),
 1522                                    0,
 1523                                    sizeof(he_mon_cmd), &he_mon_cmd);
 1524 
 1525         /* no need to really wait, we already did anyway */
 1526         iwl_remove_notification(&mvm->notif_wait, &wait);
 1527 
 1528         mutex_unlock(&mvm->mutex);
 1529 
 1530         return ret ?: count;
 1531 }
 1532 
 1533 static ssize_t
 1534 iwl_dbgfs_he_sniffer_params_read(struct file *file, char __user *user_buf,
 1535                                  size_t count, loff_t *ppos)
 1536 {
 1537         struct iwl_mvm *mvm = file->private_data;
 1538         u8 buf[32];
 1539         int len;
 1540 
 1541         len = scnprintf(buf, sizeof(buf),
 1542                         "%d %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n",
 1543                         le16_to_cpu(mvm->cur_aid), mvm->cur_bssid[0],
 1544                         mvm->cur_bssid[1], mvm->cur_bssid[2], mvm->cur_bssid[3],
 1545                         mvm->cur_bssid[4], mvm->cur_bssid[5]);
 1546 
 1547         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 1548 }
 1549 
 1550 static ssize_t
 1551 iwl_dbgfs_uapsd_noagg_bssids_read(struct file *file, char __user *user_buf,
 1552                                   size_t count, loff_t *ppos)
 1553 {
 1554         struct iwl_mvm *mvm = file->private_data;
 1555         u8 buf[IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM * ETH_ALEN * 3 + 1];
 1556         unsigned int pos = 0;
 1557         size_t bufsz = sizeof(buf);
 1558         int i;
 1559 
 1560         mutex_lock(&mvm->mutex);
 1561 
 1562         for (i = 0; i < IWL_MVM_UAPSD_NOAGG_LIST_LEN; i++)
 1563                 pos += scnprintf(buf + pos, bufsz - pos, "%pM\n",
 1564                                  mvm->uapsd_noagg_bssids[i].addr);
 1565 
 1566         mutex_unlock(&mvm->mutex);
 1567 
 1568         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 1569 }
 1570 
 1571 static ssize_t
 1572 iwl_dbgfs_ltr_config_write(struct iwl_mvm *mvm,
 1573                            char *buf, size_t count, loff_t *ppos)
 1574 {
 1575         int ret;
 1576         struct iwl_ltr_config_cmd ltr_config = {0};
 1577 
 1578         if (!iwl_mvm_firmware_running(mvm))
 1579                 return -EIO;
 1580 
 1581         if (sscanf(buf, "%x,%x,%x,%x,%x,%x,%x",
 1582                    &ltr_config.flags,
 1583                    &ltr_config.static_long,
 1584                    &ltr_config.static_short,
 1585                    &ltr_config.ltr_cfg_values[0],
 1586                    &ltr_config.ltr_cfg_values[1],
 1587                    &ltr_config.ltr_cfg_values[2],
 1588                    &ltr_config.ltr_cfg_values[3]) != 7) {
 1589                 return -EINVAL;
 1590         }
 1591 
 1592         mutex_lock(&mvm->mutex);
 1593         ret = iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0, sizeof(ltr_config),
 1594                                    &ltr_config);
 1595         mutex_unlock(&mvm->mutex);
 1596 
 1597         if (ret)
 1598                 IWL_ERR(mvm, "failed to send ltr configuration cmd\n");
 1599 
 1600         return ret ?: count;
 1601 }
 1602 
 1603 static ssize_t iwl_dbgfs_rfi_freq_table_write(struct iwl_mvm *mvm, char *buf,
 1604                                               size_t count, loff_t *ppos)
 1605 {
 1606         int ret = 0;
 1607         u16 op_id;
 1608 
 1609         if (kstrtou16(buf, 10, &op_id))
 1610                 return -EINVAL;
 1611 
 1612         /* value zero triggers re-sending the default table to the device */
 1613         if (!op_id) {
 1614                 mutex_lock(&mvm->mutex);
 1615                 ret = iwl_rfi_send_config_cmd(mvm, NULL);
 1616                 mutex_unlock(&mvm->mutex);
 1617         } else {
 1618                 ret = -EOPNOTSUPP; /* in the future a new table will be added */
 1619         }
 1620 
 1621         return ret ?: count;
 1622 }
 1623 
 1624 /* The size computation is as follows:
 1625  * each number needs at most 3 characters, number of rows is the size of
 1626  * the table; So, need 5 chars for the "freq: " part and each tuple afterwards
 1627  * needs 6 characters for numbers and 5 for the punctuation around.
 1628  */
 1629 #define IWL_RFI_BUF_SIZE (IWL_RFI_LUT_INSTALLED_SIZE *\
 1630                                 (5 + IWL_RFI_LUT_ENTRY_CHANNELS_NUM * (6 + 5)))
 1631 
 1632 static ssize_t iwl_dbgfs_rfi_freq_table_read(struct file *file,
 1633                                              char __user *user_buf,
 1634                                              size_t count, loff_t *ppos)
 1635 {
 1636         struct iwl_mvm *mvm = file->private_data;
 1637         struct iwl_rfi_freq_table_resp_cmd *resp;
 1638         u32 status;
 1639         char buf[IWL_RFI_BUF_SIZE];
 1640         int i, j, pos = 0;
 1641 
 1642         resp = iwl_rfi_get_freq_table(mvm);
 1643         if (IS_ERR(resp))
 1644                 return PTR_ERR(resp);
 1645 
 1646         status = le32_to_cpu(resp->status);
 1647         if (status != RFI_FREQ_TABLE_OK) {
 1648                 scnprintf(buf, IWL_RFI_BUF_SIZE, "status = %d\n", status);
 1649                 goto out;
 1650         }
 1651 
 1652         for (i = 0; i < ARRAY_SIZE(resp->table); i++) {
 1653                 pos += scnprintf(buf + pos, IWL_RFI_BUF_SIZE - pos, "%d: ",
 1654                                  resp->table[i].freq);
 1655 
 1656                 for (j = 0; j < ARRAY_SIZE(resp->table[i].channels); j++)
 1657                         pos += scnprintf(buf + pos, IWL_RFI_BUF_SIZE - pos,
 1658                                          "(%d, %d) ",
 1659                                          resp->table[i].channels[j],
 1660                                          resp->table[i].bands[j]);
 1661                 pos += scnprintf(buf + pos, IWL_RFI_BUF_SIZE - pos, "\n");
 1662         }
 1663 
 1664 out:
 1665         kfree(resp);
 1666         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 1667 }
 1668 
 1669 MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64);
 1670 
 1671 /* Device wide debugfs entries */
 1672 MVM_DEBUGFS_READ_FILE_OPS(ctdp_budget);
 1673 MVM_DEBUGFS_WRITE_FILE_OPS(stop_ctdp, 8);
 1674 MVM_DEBUGFS_WRITE_FILE_OPS(force_ctkill, 8);
 1675 MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16);
 1676 MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain, 8);
 1677 MVM_DEBUGFS_WRITE_FILE_OPS(send_echo_cmd, 8);
 1678 MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram, 64);
 1679 MVM_DEBUGFS_READ_WRITE_FILE_OPS(set_nic_temperature, 64);
 1680 MVM_DEBUGFS_READ_FILE_OPS(nic_temp);
 1681 MVM_DEBUGFS_READ_FILE_OPS(stations);
 1682 MVM_DEBUGFS_READ_FILE_OPS(rs_data);
 1683 MVM_DEBUGFS_READ_FILE_OPS(bt_notif);
 1684 MVM_DEBUGFS_READ_FILE_OPS(bt_cmd);
 1685 MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off, 64);
 1686 MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats);
 1687 MVM_DEBUGFS_READ_FILE_OPS(drv_rx_stats);
 1688 MVM_DEBUGFS_READ_FILE_OPS(fw_ver);
 1689 MVM_DEBUGFS_READ_FILE_OPS(phy_integration_ver);
 1690 MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10);
 1691 MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10);
 1692 MVM_DEBUGFS_WRITE_FILE_OPS(bt_tx_prio, 10);
 1693 MVM_DEBUGFS_WRITE_FILE_OPS(bt_force_ant, 10);
 1694 MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
 1695 MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8);
 1696 MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 64);
 1697 MVM_DEBUGFS_WRITE_FILE_OPS(dbg_time_point, 64);
 1698 MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl,
 1699                            (IWL_RSS_INDIRECTION_TABLE_SIZE * 2));
 1700 MVM_DEBUGFS_WRITE_FILE_OPS(inject_packet, 512);
 1701 MVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon_ie, 512);
 1702 MVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon_ie_restore, 512);
 1703 
 1704 MVM_DEBUGFS_READ_FILE_OPS(uapsd_noagg_bssids);
 1705 
 1706 #ifdef CONFIG_ACPI
 1707 MVM_DEBUGFS_READ_FILE_OPS(sar_geo_profile);
 1708 #endif
 1709 
 1710 MVM_DEBUGFS_READ_WRITE_STA_FILE_OPS(amsdu_len, 16);
 1711 
 1712 MVM_DEBUGFS_READ_WRITE_FILE_OPS(he_sniffer_params, 32);
 1713 
 1714 MVM_DEBUGFS_WRITE_FILE_OPS(ltr_config, 512);
 1715 MVM_DEBUGFS_READ_WRITE_FILE_OPS(rfi_freq_table, 16);
 1716 
 1717 static ssize_t iwl_dbgfs_mem_read(struct file *file, char __user *user_buf,
 1718                                   size_t count, loff_t *ppos)
 1719 {
 1720         struct iwl_mvm *mvm = file->private_data;
 1721         struct iwl_dbg_mem_access_cmd cmd = {};
 1722         struct iwl_dbg_mem_access_rsp *rsp;
 1723         struct iwl_host_cmd hcmd = {
 1724                 .flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
 1725                 .data = { &cmd, },
 1726                 .len = { sizeof(cmd) },
 1727         };
 1728         size_t delta;
 1729         ssize_t ret, len;
 1730 
 1731         if (!iwl_mvm_firmware_running(mvm))
 1732                 return -EIO;
 1733 
 1734         hcmd.id = WIDE_ID(DEBUG_GROUP, *ppos >> 24 ? UMAC_RD_WR : LMAC_RD_WR);
 1735         cmd.op = cpu_to_le32(DEBUG_MEM_OP_READ);
 1736 
 1737         /* Take care of alignment of both the position and the length */
 1738         delta = *ppos & 0x3;
 1739         cmd.addr = cpu_to_le32(*ppos - delta);
 1740         cmd.len = cpu_to_le32(min(ALIGN(count + delta, 4) / 4,
 1741                                   (size_t)DEBUG_MEM_MAX_SIZE_DWORDS));
 1742 
 1743         mutex_lock(&mvm->mutex);
 1744         ret = iwl_mvm_send_cmd(mvm, &hcmd);
 1745         mutex_unlock(&mvm->mutex);
 1746 
 1747         if (ret < 0)
 1748                 return ret;
 1749 
 1750         rsp = (void *)hcmd.resp_pkt->data;
 1751         if (le32_to_cpu(rsp->status) != DEBUG_MEM_STATUS_SUCCESS) {
 1752                 ret = -ENXIO;
 1753                 goto out;
 1754         }
 1755 
 1756         len = min((size_t)le32_to_cpu(rsp->len) << 2,
 1757                   iwl_rx_packet_payload_len(hcmd.resp_pkt) - sizeof(*rsp));
 1758         len = min(len - delta, count);
 1759         if (len < 0) {
 1760                 ret = -EFAULT;
 1761                 goto out;
 1762         }
 1763 
 1764         ret = len - copy_to_user(user_buf, (u8 *)rsp->data + delta, len);
 1765         *ppos += ret;
 1766 
 1767 out:
 1768         iwl_free_resp(&hcmd);
 1769         return ret;
 1770 }
 1771 
 1772 static ssize_t iwl_dbgfs_mem_write(struct file *file,
 1773                                    const char __user *user_buf, size_t count,
 1774                                    loff_t *ppos)
 1775 {
 1776         struct iwl_mvm *mvm = file->private_data;
 1777         struct iwl_dbg_mem_access_cmd *cmd;
 1778         struct iwl_dbg_mem_access_rsp *rsp;
 1779         struct iwl_host_cmd hcmd = {};
 1780         size_t cmd_size;
 1781         size_t data_size;
 1782         u32 op, len;
 1783         ssize_t ret;
 1784 
 1785         if (!iwl_mvm_firmware_running(mvm))
 1786                 return -EIO;
 1787 
 1788         hcmd.id = WIDE_ID(DEBUG_GROUP, *ppos >> 24 ? UMAC_RD_WR : LMAC_RD_WR);
 1789 
 1790         if (*ppos & 0x3 || count < 4) {
 1791                 op = DEBUG_MEM_OP_WRITE_BYTES;
 1792                 len = min(count, (size_t)(4 - (*ppos & 0x3)));
 1793                 data_size = len;
 1794         } else {
 1795                 op = DEBUG_MEM_OP_WRITE;
 1796                 len = min(count >> 2, (size_t)DEBUG_MEM_MAX_SIZE_DWORDS);
 1797                 data_size = len << 2;
 1798         }
 1799 
 1800         cmd_size = sizeof(*cmd) + ALIGN(data_size, 4);
 1801         cmd = kzalloc(cmd_size, GFP_KERNEL);
 1802         if (!cmd)
 1803                 return -ENOMEM;
 1804 
 1805         cmd->op = cpu_to_le32(op);
 1806         cmd->len = cpu_to_le32(len);
 1807         cmd->addr = cpu_to_le32(*ppos);
 1808         if (copy_from_user((void *)cmd->data, user_buf, data_size)) {
 1809                 kfree(cmd);
 1810                 return -EFAULT;
 1811         }
 1812 
 1813         hcmd.flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
 1814         hcmd.data[0] = (void *)cmd;
 1815         hcmd.len[0] = cmd_size;
 1816 
 1817         mutex_lock(&mvm->mutex);
 1818         ret = iwl_mvm_send_cmd(mvm, &hcmd);
 1819         mutex_unlock(&mvm->mutex);
 1820 
 1821         kfree(cmd);
 1822 
 1823         if (ret < 0)
 1824                 return ret;
 1825 
 1826         rsp = (void *)hcmd.resp_pkt->data;
 1827         if (rsp->status != DEBUG_MEM_STATUS_SUCCESS) {
 1828                 ret = -ENXIO;
 1829                 goto out;
 1830         }
 1831 
 1832         ret = data_size;
 1833         *ppos += ret;
 1834 
 1835 out:
 1836         iwl_free_resp(&hcmd);
 1837         return ret;
 1838 }
 1839 
 1840 static const struct file_operations iwl_dbgfs_mem_ops = {
 1841         .read = iwl_dbgfs_mem_read,
 1842         .write = iwl_dbgfs_mem_write,
 1843         .open = simple_open,
 1844         .llseek = default_llseek,
 1845 };
 1846 
 1847 void iwl_mvm_sta_add_debugfs(struct ieee80211_hw *hw,
 1848                              struct ieee80211_vif *vif,
 1849                              struct ieee80211_sta *sta,
 1850                              struct dentry *dir)
 1851 {
 1852         struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 1853 
 1854         if (iwl_mvm_has_tlc_offload(mvm)) {
 1855                 MVM_DEBUGFS_ADD_STA_FILE(rs_data, dir, 0400);
 1856         }
 1857         MVM_DEBUGFS_ADD_STA_FILE(amsdu_len, dir, 0600);
 1858 }
 1859 
 1860 void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm)
 1861 {
 1862         struct dentry *bcast_dir __maybe_unused;
 1863 
 1864         spin_lock_init(&mvm->drv_stats_lock);
 1865 
 1866         MVM_DEBUGFS_ADD_FILE(tx_flush, mvm->debugfs_dir, 0200);
 1867         MVM_DEBUGFS_ADD_FILE(sta_drain, mvm->debugfs_dir, 0200);
 1868         MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, 0600);
 1869         MVM_DEBUGFS_ADD_FILE(set_nic_temperature, mvm->debugfs_dir, 0600);
 1870         MVM_DEBUGFS_ADD_FILE(nic_temp, mvm->debugfs_dir, 0400);
 1871         MVM_DEBUGFS_ADD_FILE(ctdp_budget, mvm->debugfs_dir, 0400);
 1872         MVM_DEBUGFS_ADD_FILE(stop_ctdp, mvm->debugfs_dir, 0200);
 1873         MVM_DEBUGFS_ADD_FILE(force_ctkill, mvm->debugfs_dir, 0200);
 1874         MVM_DEBUGFS_ADD_FILE(stations, mvm->debugfs_dir, 0400);
 1875         MVM_DEBUGFS_ADD_FILE(bt_notif, mvm->debugfs_dir, 0400);
 1876         MVM_DEBUGFS_ADD_FILE(bt_cmd, mvm->debugfs_dir, 0400);
 1877         MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir, 0600);
 1878         MVM_DEBUGFS_ADD_FILE(fw_ver, mvm->debugfs_dir, 0400);
 1879         MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, 0400);
 1880         MVM_DEBUGFS_ADD_FILE(drv_rx_stats, mvm->debugfs_dir, 0400);
 1881         MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, 0200);
 1882         MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, 0200);
 1883         MVM_DEBUGFS_ADD_FILE(bt_tx_prio, mvm->debugfs_dir, 0200);
 1884         MVM_DEBUGFS_ADD_FILE(bt_force_ant, mvm->debugfs_dir, 0200);
 1885         MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir, 0600);
 1886         MVM_DEBUGFS_ADD_FILE(prph_reg, mvm->debugfs_dir, 0600);
 1887         MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, 0600);
 1888         MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, 0200);
 1889         MVM_DEBUGFS_ADD_FILE(dbg_time_point, mvm->debugfs_dir, 0200);
 1890         MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, 0200);
 1891         MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, 0200);
 1892         MVM_DEBUGFS_ADD_FILE(inject_packet, mvm->debugfs_dir, 0200);
 1893         MVM_DEBUGFS_ADD_FILE(inject_beacon_ie, mvm->debugfs_dir, 0200);
 1894         MVM_DEBUGFS_ADD_FILE(inject_beacon_ie_restore, mvm->debugfs_dir, 0200);
 1895         MVM_DEBUGFS_ADD_FILE(rfi_freq_table, mvm->debugfs_dir, 0600);
 1896 
 1897         if (mvm->fw->phy_integration_ver)
 1898                 MVM_DEBUGFS_ADD_FILE(phy_integration_ver, mvm->debugfs_dir, 0400);
 1899 #ifdef CONFIG_ACPI
 1900         MVM_DEBUGFS_ADD_FILE(sar_geo_profile, mvm->debugfs_dir, 0400);
 1901 #endif
 1902         MVM_DEBUGFS_ADD_FILE(he_sniffer_params, mvm->debugfs_dir, 0600);
 1903 
 1904         if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SET_LTR_GEN2))
 1905                 MVM_DEBUGFS_ADD_FILE(ltr_config, mvm->debugfs_dir, 0200);
 1906 
 1907         debugfs_create_bool("enable_scan_iteration_notif", 0600,
 1908                             mvm->debugfs_dir, &mvm->scan_iter_notif_enabled);
 1909         debugfs_create_bool("drop_bcn_ap_mode", 0600, mvm->debugfs_dir,
 1910                             &mvm->drop_bcn_ap_mode);
 1911 
 1912         MVM_DEBUGFS_ADD_FILE(uapsd_noagg_bssids, mvm->debugfs_dir, S_IRUSR);
 1913 
 1914 #ifdef CONFIG_PM_SLEEP
 1915         MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, 0400);
 1916         debugfs_create_bool("d3_wake_sysassert", 0600, mvm->debugfs_dir,
 1917                             &mvm->d3_wake_sysassert);
 1918         debugfs_create_u32("last_netdetect_scans", 0400, mvm->debugfs_dir,
 1919                            &mvm->last_netdetect_scans);
 1920 #endif
 1921 
 1922         debugfs_create_u8("ps_disabled", 0400, mvm->debugfs_dir,
 1923                           &mvm->ps_disabled);
 1924         debugfs_create_blob("nvm_hw", 0400, mvm->debugfs_dir,
 1925                             &mvm->nvm_hw_blob);
 1926         debugfs_create_blob("nvm_sw", 0400, mvm->debugfs_dir,
 1927                             &mvm->nvm_sw_blob);
 1928         debugfs_create_blob("nvm_calib", 0400, mvm->debugfs_dir,
 1929                             &mvm->nvm_calib_blob);
 1930         debugfs_create_blob("nvm_prod", 0400, mvm->debugfs_dir,
 1931                             &mvm->nvm_prod_blob);
 1932         debugfs_create_blob("nvm_phy_sku", 0400, mvm->debugfs_dir,
 1933                             &mvm->nvm_phy_sku_blob);
 1934         debugfs_create_blob("nvm_reg", S_IRUSR,
 1935                             mvm->debugfs_dir, &mvm->nvm_reg_blob);
 1936 
 1937         debugfs_create_file("mem", 0600, mvm->debugfs_dir, mvm,
 1938                             &iwl_dbgfs_mem_ops);
 1939 
 1940 #if defined(__linux__)
 1941         /*
 1942          * Create a symlink with mac80211. It will be removed when mac80211
 1943          * exists (before the opmode exists which removes the target.)
 1944          */
 1945         if (!IS_ERR(mvm->debugfs_dir)) {
 1946                 char buf[100];
 1947 
 1948                 snprintf(buf, 100, "../../%pd2", mvm->debugfs_dir->d_parent);
 1949                 debugfs_create_symlink("iwlwifi", mvm->hw->wiphy->debugfsdir,
 1950                                        buf);
 1951         }
 1952 #endif
 1953 }

Cache object: b91c4c62e3f67e7a7aa6545d81307f72


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.