Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * mac80211 debugfs for wireless PHYs
0004  *
0005  * Copyright 2007   Johannes Berg <johannes@sipsolutions.net>
0006  * Copyright 2013-2014  Intel Mobile Communications GmbH
0007  * Copyright (C) 2018 - 2019, 2021-2022 Intel Corporation
0008  */
0009 
0010 #include <linux/debugfs.h>
0011 #include <linux/rtnetlink.h>
0012 #include <linux/vmalloc.h>
0013 #include "ieee80211_i.h"
0014 #include "driver-ops.h"
0015 #include "rate.h"
0016 #include "debugfs.h"
0017 
0018 #define DEBUGFS_FORMAT_BUFFER_SIZE 100
0019 
0020 int mac80211_format_buffer(char __user *userbuf, size_t count,
0021                   loff_t *ppos, char *fmt, ...)
0022 {
0023     va_list args;
0024     char buf[DEBUGFS_FORMAT_BUFFER_SIZE];
0025     int res;
0026 
0027     va_start(args, fmt);
0028     res = vscnprintf(buf, sizeof(buf), fmt, args);
0029     va_end(args);
0030 
0031     return simple_read_from_buffer(userbuf, count, ppos, buf, res);
0032 }
0033 
0034 #define DEBUGFS_READONLY_FILE_FN(name, fmt, value...)           \
0035 static ssize_t name## _read(struct file *file, char __user *userbuf,    \
0036                 size_t count, loff_t *ppos)         \
0037 {                                   \
0038     struct ieee80211_local *local = file->private_data;     \
0039                                     \
0040     return mac80211_format_buffer(userbuf, count, ppos,         \
0041                       fmt "\n", ##value);       \
0042 }
0043 
0044 #define DEBUGFS_READONLY_FILE_OPS(name)         \
0045 static const struct file_operations name## _ops = {         \
0046     .read = name## _read,                       \
0047     .open = simple_open,                        \
0048     .llseek = generic_file_llseek,                  \
0049 };
0050 
0051 #define DEBUGFS_READONLY_FILE(name, fmt, value...)      \
0052     DEBUGFS_READONLY_FILE_FN(name, fmt, value)      \
0053     DEBUGFS_READONLY_FILE_OPS(name)
0054 
0055 #define DEBUGFS_ADD(name)                       \
0056     debugfs_create_file(#name, 0400, phyd, local, &name## _ops)
0057 
0058 #define DEBUGFS_ADD_MODE(name, mode)                    \
0059     debugfs_create_file(#name, mode, phyd, local, &name## _ops);
0060 
0061 
0062 DEBUGFS_READONLY_FILE(hw_conf, "%x",
0063               local->hw.conf.flags);
0064 DEBUGFS_READONLY_FILE(user_power, "%d",
0065               local->user_power_level);
0066 DEBUGFS_READONLY_FILE(power, "%d",
0067               local->hw.conf.power_level);
0068 DEBUGFS_READONLY_FILE(total_ps_buffered, "%d",
0069               local->total_ps_buffered);
0070 DEBUGFS_READONLY_FILE(wep_iv, "%#08x",
0071               local->wep_iv & 0xffffff);
0072 DEBUGFS_READONLY_FILE(rate_ctrl_alg, "%s",
0073     local->rate_ctrl ? local->rate_ctrl->ops->name : "hw/driver");
0074 
0075 static ssize_t aqm_read(struct file *file,
0076             char __user *user_buf,
0077             size_t count,
0078             loff_t *ppos)
0079 {
0080     struct ieee80211_local *local = file->private_data;
0081     struct fq *fq = &local->fq;
0082     char buf[200];
0083     int len = 0;
0084 
0085     spin_lock_bh(&local->fq.lock);
0086     rcu_read_lock();
0087 
0088     len = scnprintf(buf, sizeof(buf),
0089             "access name value\n"
0090             "R fq_flows_cnt %u\n"
0091             "R fq_backlog %u\n"
0092             "R fq_overlimit %u\n"
0093             "R fq_overmemory %u\n"
0094             "R fq_collisions %u\n"
0095             "R fq_memory_usage %u\n"
0096             "RW fq_memory_limit %u\n"
0097             "RW fq_limit %u\n"
0098             "RW fq_quantum %u\n",
0099             fq->flows_cnt,
0100             fq->backlog,
0101             fq->overmemory,
0102             fq->overlimit,
0103             fq->collisions,
0104             fq->memory_usage,
0105             fq->memory_limit,
0106             fq->limit,
0107             fq->quantum);
0108 
0109     rcu_read_unlock();
0110     spin_unlock_bh(&local->fq.lock);
0111 
0112     return simple_read_from_buffer(user_buf, count, ppos,
0113                        buf, len);
0114 }
0115 
0116 static ssize_t aqm_write(struct file *file,
0117              const char __user *user_buf,
0118              size_t count,
0119              loff_t *ppos)
0120 {
0121     struct ieee80211_local *local = file->private_data;
0122     char buf[100];
0123 
0124     if (count >= sizeof(buf))
0125         return -EINVAL;
0126 
0127     if (copy_from_user(buf, user_buf, count))
0128         return -EFAULT;
0129 
0130     if (count && buf[count - 1] == '\n')
0131         buf[count - 1] = '\0';
0132     else
0133         buf[count] = '\0';
0134 
0135     if (sscanf(buf, "fq_limit %u", &local->fq.limit) == 1)
0136         return count;
0137     else if (sscanf(buf, "fq_memory_limit %u", &local->fq.memory_limit) == 1)
0138         return count;
0139     else if (sscanf(buf, "fq_quantum %u", &local->fq.quantum) == 1)
0140         return count;
0141 
0142     return -EINVAL;
0143 }
0144 
0145 static const struct file_operations aqm_ops = {
0146     .write = aqm_write,
0147     .read = aqm_read,
0148     .open = simple_open,
0149     .llseek = default_llseek,
0150 };
0151 
0152 static ssize_t airtime_flags_read(struct file *file,
0153                   char __user *user_buf,
0154                   size_t count, loff_t *ppos)
0155 {
0156     struct ieee80211_local *local = file->private_data;
0157     char buf[128] = {}, *pos, *end;
0158 
0159     pos = buf;
0160     end = pos + sizeof(buf) - 1;
0161 
0162     if (local->airtime_flags & AIRTIME_USE_TX)
0163         pos += scnprintf(pos, end - pos, "AIRTIME_TX\t(%lx)\n",
0164                  AIRTIME_USE_TX);
0165     if (local->airtime_flags & AIRTIME_USE_RX)
0166         pos += scnprintf(pos, end - pos, "AIRTIME_RX\t(%lx)\n",
0167                  AIRTIME_USE_RX);
0168 
0169     return simple_read_from_buffer(user_buf, count, ppos, buf,
0170                        strlen(buf));
0171 }
0172 
0173 static ssize_t airtime_flags_write(struct file *file,
0174                    const char __user *user_buf,
0175                    size_t count, loff_t *ppos)
0176 {
0177     struct ieee80211_local *local = file->private_data;
0178     char buf[16];
0179 
0180     if (count >= sizeof(buf))
0181         return -EINVAL;
0182 
0183     if (copy_from_user(buf, user_buf, count))
0184         return -EFAULT;
0185 
0186     if (count && buf[count - 1] == '\n')
0187         buf[count - 1] = '\0';
0188     else
0189         buf[count] = '\0';
0190 
0191     if (kstrtou16(buf, 0, &local->airtime_flags))
0192         return -EINVAL;
0193 
0194     return count;
0195 }
0196 
0197 static const struct file_operations airtime_flags_ops = {
0198     .write = airtime_flags_write,
0199     .read = airtime_flags_read,
0200     .open = simple_open,
0201     .llseek = default_llseek,
0202 };
0203 
0204 static ssize_t aql_pending_read(struct file *file,
0205                 char __user *user_buf,
0206                 size_t count, loff_t *ppos)
0207 {
0208     struct ieee80211_local *local = file->private_data;
0209     char buf[400];
0210     int len = 0;
0211 
0212     len = scnprintf(buf, sizeof(buf),
0213             "AC     AQL pending\n"
0214             "VO     %u us\n"
0215             "VI     %u us\n"
0216             "BE     %u us\n"
0217             "BK     %u us\n"
0218             "total  %u us\n",
0219             atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_VO]),
0220             atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_VI]),
0221             atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_BE]),
0222             atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_BK]),
0223             atomic_read(&local->aql_total_pending_airtime));
0224     return simple_read_from_buffer(user_buf, count, ppos,
0225                        buf, len);
0226 }
0227 
0228 static const struct file_operations aql_pending_ops = {
0229     .read = aql_pending_read,
0230     .open = simple_open,
0231     .llseek = default_llseek,
0232 };
0233 
0234 static ssize_t aql_txq_limit_read(struct file *file,
0235                   char __user *user_buf,
0236                   size_t count,
0237                   loff_t *ppos)
0238 {
0239     struct ieee80211_local *local = file->private_data;
0240     char buf[400];
0241     int len = 0;
0242 
0243     len = scnprintf(buf, sizeof(buf),
0244             "AC AQL limit low   AQL limit high\n"
0245             "VO %u      %u\n"
0246             "VI %u      %u\n"
0247             "BE %u      %u\n"
0248             "BK %u      %u\n",
0249             local->aql_txq_limit_low[IEEE80211_AC_VO],
0250             local->aql_txq_limit_high[IEEE80211_AC_VO],
0251             local->aql_txq_limit_low[IEEE80211_AC_VI],
0252             local->aql_txq_limit_high[IEEE80211_AC_VI],
0253             local->aql_txq_limit_low[IEEE80211_AC_BE],
0254             local->aql_txq_limit_high[IEEE80211_AC_BE],
0255             local->aql_txq_limit_low[IEEE80211_AC_BK],
0256             local->aql_txq_limit_high[IEEE80211_AC_BK]);
0257     return simple_read_from_buffer(user_buf, count, ppos,
0258                        buf, len);
0259 }
0260 
0261 static ssize_t aql_txq_limit_write(struct file *file,
0262                    const char __user *user_buf,
0263                    size_t count,
0264                    loff_t *ppos)
0265 {
0266     struct ieee80211_local *local = file->private_data;
0267     char buf[100];
0268     u32 ac, q_limit_low, q_limit_high, q_limit_low_old, q_limit_high_old;
0269     struct sta_info *sta;
0270 
0271     if (count >= sizeof(buf))
0272         return -EINVAL;
0273 
0274     if (copy_from_user(buf, user_buf, count))
0275         return -EFAULT;
0276 
0277     if (count && buf[count - 1] == '\n')
0278         buf[count - 1] = '\0';
0279     else
0280         buf[count] = '\0';
0281 
0282     if (sscanf(buf, "%u %u %u", &ac, &q_limit_low, &q_limit_high) != 3)
0283         return -EINVAL;
0284 
0285     if (ac >= IEEE80211_NUM_ACS)
0286         return -EINVAL;
0287 
0288     q_limit_low_old = local->aql_txq_limit_low[ac];
0289     q_limit_high_old = local->aql_txq_limit_high[ac];
0290 
0291     local->aql_txq_limit_low[ac] = q_limit_low;
0292     local->aql_txq_limit_high[ac] = q_limit_high;
0293 
0294     mutex_lock(&local->sta_mtx);
0295     list_for_each_entry(sta, &local->sta_list, list) {
0296         /* If a sta has customized queue limits, keep it */
0297         if (sta->airtime[ac].aql_limit_low == q_limit_low_old &&
0298             sta->airtime[ac].aql_limit_high == q_limit_high_old) {
0299             sta->airtime[ac].aql_limit_low = q_limit_low;
0300             sta->airtime[ac].aql_limit_high = q_limit_high;
0301         }
0302     }
0303     mutex_unlock(&local->sta_mtx);
0304     return count;
0305 }
0306 
0307 static const struct file_operations aql_txq_limit_ops = {
0308     .write = aql_txq_limit_write,
0309     .read = aql_txq_limit_read,
0310     .open = simple_open,
0311     .llseek = default_llseek,
0312 };
0313 
0314 static ssize_t aql_enable_read(struct file *file, char __user *user_buf,
0315                    size_t count, loff_t *ppos)
0316 {
0317     char buf[3];
0318     int len;
0319 
0320     len = scnprintf(buf, sizeof(buf), "%d\n",
0321             !static_key_false(&aql_disable.key));
0322 
0323     return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0324 }
0325 
0326 static ssize_t aql_enable_write(struct file *file, const char __user *user_buf,
0327                 size_t count, loff_t *ppos)
0328 {
0329     bool aql_disabled = static_key_false(&aql_disable.key);
0330     char buf[3];
0331     size_t len;
0332 
0333     if (count > sizeof(buf))
0334         return -EINVAL;
0335 
0336     if (copy_from_user(buf, user_buf, count))
0337         return -EFAULT;
0338 
0339     buf[sizeof(buf) - 1] = '\0';
0340     len = strlen(buf);
0341     if (len > 0 && buf[len - 1] == '\n')
0342         buf[len - 1] = 0;
0343 
0344     if (buf[0] == '0' && buf[1] == '\0') {
0345         if (!aql_disabled)
0346             static_branch_inc(&aql_disable);
0347     } else if (buf[0] == '1' && buf[1] == '\0') {
0348         if (aql_disabled)
0349             static_branch_dec(&aql_disable);
0350     } else {
0351         return -EINVAL;
0352     }
0353 
0354     return count;
0355 }
0356 
0357 static const struct file_operations aql_enable_ops = {
0358     .write = aql_enable_write,
0359     .read = aql_enable_read,
0360     .open = simple_open,
0361     .llseek = default_llseek,
0362 };
0363 
0364 static ssize_t force_tx_status_read(struct file *file,
0365                     char __user *user_buf,
0366                     size_t count,
0367                     loff_t *ppos)
0368 {
0369     struct ieee80211_local *local = file->private_data;
0370     char buf[3];
0371     int len = 0;
0372 
0373     len = scnprintf(buf, sizeof(buf), "%d\n", (int)local->force_tx_status);
0374 
0375     return simple_read_from_buffer(user_buf, count, ppos,
0376                        buf, len);
0377 }
0378 
0379 static ssize_t force_tx_status_write(struct file *file,
0380                      const char __user *user_buf,
0381                      size_t count,
0382                      loff_t *ppos)
0383 {
0384     struct ieee80211_local *local = file->private_data;
0385     char buf[3];
0386 
0387     if (count >= sizeof(buf))
0388         return -EINVAL;
0389 
0390     if (copy_from_user(buf, user_buf, count))
0391         return -EFAULT;
0392 
0393     if (count && buf[count - 1] == '\n')
0394         buf[count - 1] = '\0';
0395     else
0396         buf[count] = '\0';
0397 
0398     if (buf[0] == '0' && buf[1] == '\0')
0399         local->force_tx_status = 0;
0400     else if (buf[0] == '1' && buf[1] == '\0')
0401         local->force_tx_status = 1;
0402     else
0403         return -EINVAL;
0404 
0405     return count;
0406 }
0407 
0408 static const struct file_operations force_tx_status_ops = {
0409     .write = force_tx_status_write,
0410     .read = force_tx_status_read,
0411     .open = simple_open,
0412     .llseek = default_llseek,
0413 };
0414 
0415 #ifdef CONFIG_PM
0416 static ssize_t reset_write(struct file *file, const char __user *user_buf,
0417                size_t count, loff_t *ppos)
0418 {
0419     struct ieee80211_local *local = file->private_data;
0420     int ret;
0421 
0422     rtnl_lock();
0423     wiphy_lock(local->hw.wiphy);
0424     __ieee80211_suspend(&local->hw, NULL);
0425     ret = __ieee80211_resume(&local->hw);
0426     wiphy_unlock(local->hw.wiphy);
0427 
0428     if (ret)
0429         cfg80211_shutdown_all_interfaces(local->hw.wiphy);
0430 
0431     rtnl_unlock();
0432 
0433     return count;
0434 }
0435 
0436 static const struct file_operations reset_ops = {
0437     .write = reset_write,
0438     .open = simple_open,
0439     .llseek = noop_llseek,
0440 };
0441 #endif
0442 
0443 static const char *hw_flag_names[] = {
0444 #define FLAG(F) [IEEE80211_HW_##F] = #F
0445     FLAG(HAS_RATE_CONTROL),
0446     FLAG(RX_INCLUDES_FCS),
0447     FLAG(HOST_BROADCAST_PS_BUFFERING),
0448     FLAG(SIGNAL_UNSPEC),
0449     FLAG(SIGNAL_DBM),
0450     FLAG(NEED_DTIM_BEFORE_ASSOC),
0451     FLAG(SPECTRUM_MGMT),
0452     FLAG(AMPDU_AGGREGATION),
0453     FLAG(SUPPORTS_PS),
0454     FLAG(PS_NULLFUNC_STACK),
0455     FLAG(SUPPORTS_DYNAMIC_PS),
0456     FLAG(MFP_CAPABLE),
0457     FLAG(WANT_MONITOR_VIF),
0458     FLAG(NO_AUTO_VIF),
0459     FLAG(SW_CRYPTO_CONTROL),
0460     FLAG(SUPPORT_FAST_XMIT),
0461     FLAG(REPORTS_TX_ACK_STATUS),
0462     FLAG(CONNECTION_MONITOR),
0463     FLAG(QUEUE_CONTROL),
0464     FLAG(SUPPORTS_PER_STA_GTK),
0465     FLAG(AP_LINK_PS),
0466     FLAG(TX_AMPDU_SETUP_IN_HW),
0467     FLAG(SUPPORTS_RC_TABLE),
0468     FLAG(P2P_DEV_ADDR_FOR_INTF),
0469     FLAG(TIMING_BEACON_ONLY),
0470     FLAG(SUPPORTS_HT_CCK_RATES),
0471     FLAG(CHANCTX_STA_CSA),
0472     FLAG(SUPPORTS_CLONED_SKBS),
0473     FLAG(SINGLE_SCAN_ON_ALL_BANDS),
0474     FLAG(TDLS_WIDER_BW),
0475     FLAG(SUPPORTS_AMSDU_IN_AMPDU),
0476     FLAG(BEACON_TX_STATUS),
0477     FLAG(NEEDS_UNIQUE_STA_ADDR),
0478     FLAG(SUPPORTS_REORDERING_BUFFER),
0479     FLAG(USES_RSS),
0480     FLAG(TX_AMSDU),
0481     FLAG(TX_FRAG_LIST),
0482     FLAG(REPORTS_LOW_ACK),
0483     FLAG(SUPPORTS_TX_FRAG),
0484     FLAG(SUPPORTS_TDLS_BUFFER_STA),
0485     FLAG(DEAUTH_NEED_MGD_TX_PREP),
0486     FLAG(DOESNT_SUPPORT_QOS_NDP),
0487     FLAG(BUFF_MMPDU_TXQ),
0488     FLAG(SUPPORTS_VHT_EXT_NSS_BW),
0489     FLAG(STA_MMPDU_TXQ),
0490     FLAG(TX_STATUS_NO_AMPDU_LEN),
0491     FLAG(SUPPORTS_MULTI_BSSID),
0492     FLAG(SUPPORTS_ONLY_HE_MULTI_BSSID),
0493     FLAG(AMPDU_KEYBORDER_SUPPORT),
0494     FLAG(SUPPORTS_TX_ENCAP_OFFLOAD),
0495     FLAG(SUPPORTS_RX_DECAP_OFFLOAD),
0496     FLAG(SUPPORTS_CONC_MON_RX_DECAP),
0497     FLAG(DETECTS_COLOR_COLLISION),
0498     FLAG(MLO_MCAST_MULTI_LINK_TX),
0499 #undef FLAG
0500 };
0501 
0502 static ssize_t hwflags_read(struct file *file, char __user *user_buf,
0503                 size_t count, loff_t *ppos)
0504 {
0505     struct ieee80211_local *local = file->private_data;
0506     size_t bufsz = 30 * NUM_IEEE80211_HW_FLAGS;
0507     char *buf = kzalloc(bufsz, GFP_KERNEL);
0508     char *pos = buf, *end = buf + bufsz - 1;
0509     ssize_t rv;
0510     int i;
0511 
0512     if (!buf)
0513         return -ENOMEM;
0514 
0515     /* fail compilation if somebody adds or removes
0516      * a flag without updating the name array above
0517      */
0518     BUILD_BUG_ON(ARRAY_SIZE(hw_flag_names) != NUM_IEEE80211_HW_FLAGS);
0519 
0520     for (i = 0; i < NUM_IEEE80211_HW_FLAGS; i++) {
0521         if (test_bit(i, local->hw.flags))
0522             pos += scnprintf(pos, end - pos, "%s\n",
0523                      hw_flag_names[i]);
0524     }
0525 
0526     rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
0527     kfree(buf);
0528     return rv;
0529 }
0530 
0531 static ssize_t misc_read(struct file *file, char __user *user_buf,
0532              size_t count, loff_t *ppos)
0533 {
0534     struct ieee80211_local *local = file->private_data;
0535     /* Max len of each line is 16 characters, plus 9 for 'pending:\n' */
0536     size_t bufsz = IEEE80211_MAX_QUEUES * 16 + 9;
0537     char *buf;
0538     char *pos, *end;
0539     ssize_t rv;
0540     int i;
0541     int ln;
0542 
0543     buf = kzalloc(bufsz, GFP_KERNEL);
0544     if (!buf)
0545         return -ENOMEM;
0546 
0547     pos = buf;
0548     end = buf + bufsz - 1;
0549 
0550     pos += scnprintf(pos, end - pos, "pending:\n");
0551 
0552     for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
0553         ln = skb_queue_len(&local->pending[i]);
0554         pos += scnprintf(pos, end - pos, "[%i] %d\n",
0555                  i, ln);
0556     }
0557 
0558     rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
0559     kfree(buf);
0560     return rv;
0561 }
0562 
0563 static ssize_t queues_read(struct file *file, char __user *user_buf,
0564                size_t count, loff_t *ppos)
0565 {
0566     struct ieee80211_local *local = file->private_data;
0567     unsigned long flags;
0568     char buf[IEEE80211_MAX_QUEUES * 20];
0569     int q, res = 0;
0570 
0571     spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
0572     for (q = 0; q < local->hw.queues; q++)
0573         res += sprintf(buf + res, "%02d: %#.8lx/%d\n", q,
0574                 local->queue_stop_reasons[q],
0575                 skb_queue_len(&local->pending[q]));
0576     spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
0577 
0578     return simple_read_from_buffer(user_buf, count, ppos, buf, res);
0579 }
0580 
0581 DEBUGFS_READONLY_FILE_OPS(hwflags);
0582 DEBUGFS_READONLY_FILE_OPS(queues);
0583 DEBUGFS_READONLY_FILE_OPS(misc);
0584 
0585 /* statistics stuff */
0586 
0587 static ssize_t format_devstat_counter(struct ieee80211_local *local,
0588     char __user *userbuf,
0589     size_t count, loff_t *ppos,
0590     int (*printvalue)(struct ieee80211_low_level_stats *stats, char *buf,
0591               int buflen))
0592 {
0593     struct ieee80211_low_level_stats stats;
0594     char buf[20];
0595     int res;
0596 
0597     rtnl_lock();
0598     res = drv_get_stats(local, &stats);
0599     rtnl_unlock();
0600     if (res)
0601         return res;
0602     res = printvalue(&stats, buf, sizeof(buf));
0603     return simple_read_from_buffer(userbuf, count, ppos, buf, res);
0604 }
0605 
0606 #define DEBUGFS_DEVSTATS_FILE(name)                 \
0607 static int print_devstats_##name(struct ieee80211_low_level_stats *stats,\
0608                  char *buf, int buflen)         \
0609 {                                   \
0610     return scnprintf(buf, buflen, "%u\n", stats->name);     \
0611 }                                   \
0612 static ssize_t stats_ ##name## _read(struct file *file,         \
0613                      char __user *userbuf,      \
0614                      size_t count, loff_t *ppos)    \
0615 {                                   \
0616     return format_devstat_counter(file->private_data,       \
0617                       userbuf,              \
0618                       count,                \
0619                       ppos,             \
0620                       print_devstats_##name);       \
0621 }                                   \
0622                                     \
0623 static const struct file_operations stats_ ##name## _ops = {        \
0624     .read = stats_ ##name## _read,                  \
0625     .open = simple_open,                        \
0626     .llseek = generic_file_llseek,                  \
0627 };
0628 
0629 #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
0630 #define DEBUGFS_STATS_ADD(name)                 \
0631     debugfs_create_u32(#name, 0400, statsd, &local->name);
0632 #endif
0633 #define DEBUGFS_DEVSTATS_ADD(name)                  \
0634     debugfs_create_file(#name, 0400, statsd, local, &stats_ ##name## _ops);
0635 
0636 DEBUGFS_DEVSTATS_FILE(dot11ACKFailureCount);
0637 DEBUGFS_DEVSTATS_FILE(dot11RTSFailureCount);
0638 DEBUGFS_DEVSTATS_FILE(dot11FCSErrorCount);
0639 DEBUGFS_DEVSTATS_FILE(dot11RTSSuccessCount);
0640 
0641 void debugfs_hw_add(struct ieee80211_local *local)
0642 {
0643     struct dentry *phyd = local->hw.wiphy->debugfsdir;
0644     struct dentry *statsd;
0645 
0646     if (!phyd)
0647         return;
0648 
0649     local->debugfs.keys = debugfs_create_dir("keys", phyd);
0650 
0651     DEBUGFS_ADD(total_ps_buffered);
0652     DEBUGFS_ADD(wep_iv);
0653     DEBUGFS_ADD(rate_ctrl_alg);
0654     DEBUGFS_ADD(queues);
0655     DEBUGFS_ADD(misc);
0656 #ifdef CONFIG_PM
0657     DEBUGFS_ADD_MODE(reset, 0200);
0658 #endif
0659     DEBUGFS_ADD(hwflags);
0660     DEBUGFS_ADD(user_power);
0661     DEBUGFS_ADD(power);
0662     DEBUGFS_ADD(hw_conf);
0663     DEBUGFS_ADD_MODE(force_tx_status, 0600);
0664     DEBUGFS_ADD_MODE(aql_enable, 0600);
0665     DEBUGFS_ADD(aql_pending);
0666 
0667     if (local->ops->wake_tx_queue)
0668         DEBUGFS_ADD_MODE(aqm, 0600);
0669 
0670     DEBUGFS_ADD_MODE(airtime_flags, 0600);
0671 
0672     DEBUGFS_ADD(aql_txq_limit);
0673     debugfs_create_u32("aql_threshold", 0600,
0674                phyd, &local->aql_threshold);
0675 
0676     statsd = debugfs_create_dir("statistics", phyd);
0677 
0678     /* if the dir failed, don't put all the other things into the root! */
0679     if (!statsd)
0680         return;
0681 
0682 #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
0683     DEBUGFS_STATS_ADD(dot11TransmittedFragmentCount);
0684     DEBUGFS_STATS_ADD(dot11MulticastTransmittedFrameCount);
0685     DEBUGFS_STATS_ADD(dot11FailedCount);
0686     DEBUGFS_STATS_ADD(dot11RetryCount);
0687     DEBUGFS_STATS_ADD(dot11MultipleRetryCount);
0688     DEBUGFS_STATS_ADD(dot11FrameDuplicateCount);
0689     DEBUGFS_STATS_ADD(dot11ReceivedFragmentCount);
0690     DEBUGFS_STATS_ADD(dot11MulticastReceivedFrameCount);
0691     DEBUGFS_STATS_ADD(dot11TransmittedFrameCount);
0692     DEBUGFS_STATS_ADD(tx_handlers_drop);
0693     DEBUGFS_STATS_ADD(tx_handlers_queued);
0694     DEBUGFS_STATS_ADD(tx_handlers_drop_wep);
0695     DEBUGFS_STATS_ADD(tx_handlers_drop_not_assoc);
0696     DEBUGFS_STATS_ADD(tx_handlers_drop_unauth_port);
0697     DEBUGFS_STATS_ADD(rx_handlers_drop);
0698     DEBUGFS_STATS_ADD(rx_handlers_queued);
0699     DEBUGFS_STATS_ADD(rx_handlers_drop_nullfunc);
0700     DEBUGFS_STATS_ADD(rx_handlers_drop_defrag);
0701     DEBUGFS_STATS_ADD(tx_expand_skb_head);
0702     DEBUGFS_STATS_ADD(tx_expand_skb_head_cloned);
0703     DEBUGFS_STATS_ADD(rx_expand_skb_head_defrag);
0704     DEBUGFS_STATS_ADD(rx_handlers_fragments);
0705     DEBUGFS_STATS_ADD(tx_status_drop);
0706 #endif
0707     DEBUGFS_DEVSTATS_ADD(dot11ACKFailureCount);
0708     DEBUGFS_DEVSTATS_ADD(dot11RTSFailureCount);
0709     DEBUGFS_DEVSTATS_ADD(dot11FCSErrorCount);
0710     DEBUGFS_DEVSTATS_ADD(dot11RTSSuccessCount);
0711 }