root/net/mac80211/debugfs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mac80211_format_buffer
  2. aqm_read
  3. aqm_write
  4. force_tx_status_read
  5. force_tx_status_write
  6. reset_write
  7. hwflags_read
  8. misc_read
  9. queues_read
  10. format_devstat_counter
  11. debugfs_hw_add

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * mac80211 debugfs for wireless PHYs
   4  *
   5  * Copyright 2007       Johannes Berg <johannes@sipsolutions.net>
   6  * Copyright 2013-2014  Intel Mobile Communications GmbH
   7  * Copyright (C) 2018 - 2019 Intel Corporation
   8  */
   9 
  10 #include <linux/debugfs.h>
  11 #include <linux/rtnetlink.h>
  12 #include <linux/vmalloc.h>
  13 #include "ieee80211_i.h"
  14 #include "driver-ops.h"
  15 #include "rate.h"
  16 #include "debugfs.h"
  17 
  18 #define DEBUGFS_FORMAT_BUFFER_SIZE 100
  19 
  20 int mac80211_format_buffer(char __user *userbuf, size_t count,
  21                                   loff_t *ppos, char *fmt, ...)
  22 {
  23         va_list args;
  24         char buf[DEBUGFS_FORMAT_BUFFER_SIZE];
  25         int res;
  26 
  27         va_start(args, fmt);
  28         res = vscnprintf(buf, sizeof(buf), fmt, args);
  29         va_end(args);
  30 
  31         return simple_read_from_buffer(userbuf, count, ppos, buf, res);
  32 }
  33 
  34 #define DEBUGFS_READONLY_FILE_FN(name, fmt, value...)                   \
  35 static ssize_t name## _read(struct file *file, char __user *userbuf,    \
  36                             size_t count, loff_t *ppos)                 \
  37 {                                                                       \
  38         struct ieee80211_local *local = file->private_data;             \
  39                                                                         \
  40         return mac80211_format_buffer(userbuf, count, ppos,             \
  41                                       fmt "\n", ##value);               \
  42 }
  43 
  44 #define DEBUGFS_READONLY_FILE_OPS(name)                 \
  45 static const struct file_operations name## _ops = {                     \
  46         .read = name## _read,                                           \
  47         .open = simple_open,                                            \
  48         .llseek = generic_file_llseek,                                  \
  49 };
  50 
  51 #define DEBUGFS_READONLY_FILE(name, fmt, value...)              \
  52         DEBUGFS_READONLY_FILE_FN(name, fmt, value)              \
  53         DEBUGFS_READONLY_FILE_OPS(name)
  54 
  55 #define DEBUGFS_ADD(name)                                               \
  56         debugfs_create_file(#name, 0400, phyd, local, &name## _ops);
  57 
  58 #define DEBUGFS_ADD_MODE(name, mode)                                    \
  59         debugfs_create_file(#name, mode, phyd, local, &name## _ops);
  60 
  61 
  62 DEBUGFS_READONLY_FILE(user_power, "%d",
  63                       local->user_power_level);
  64 DEBUGFS_READONLY_FILE(power, "%d",
  65                       local->hw.conf.power_level);
  66 DEBUGFS_READONLY_FILE(total_ps_buffered, "%d",
  67                       local->total_ps_buffered);
  68 DEBUGFS_READONLY_FILE(wep_iv, "%#08x",
  69                       local->wep_iv & 0xffffff);
  70 DEBUGFS_READONLY_FILE(rate_ctrl_alg, "%s",
  71         local->rate_ctrl ? local->rate_ctrl->ops->name : "hw/driver");
  72 
  73 static ssize_t aqm_read(struct file *file,
  74                         char __user *user_buf,
  75                         size_t count,
  76                         loff_t *ppos)
  77 {
  78         struct ieee80211_local *local = file->private_data;
  79         struct fq *fq = &local->fq;
  80         char buf[200];
  81         int len = 0;
  82 
  83         spin_lock_bh(&local->fq.lock);
  84         rcu_read_lock();
  85 
  86         len = scnprintf(buf, sizeof(buf),
  87                         "access name value\n"
  88                         "R fq_flows_cnt %u\n"
  89                         "R fq_backlog %u\n"
  90                         "R fq_overlimit %u\n"
  91                         "R fq_overmemory %u\n"
  92                         "R fq_collisions %u\n"
  93                         "R fq_memory_usage %u\n"
  94                         "RW fq_memory_limit %u\n"
  95                         "RW fq_limit %u\n"
  96                         "RW fq_quantum %u\n",
  97                         fq->flows_cnt,
  98                         fq->backlog,
  99                         fq->overmemory,
 100                         fq->overlimit,
 101                         fq->collisions,
 102                         fq->memory_usage,
 103                         fq->memory_limit,
 104                         fq->limit,
 105                         fq->quantum);
 106 
 107         rcu_read_unlock();
 108         spin_unlock_bh(&local->fq.lock);
 109 
 110         return simple_read_from_buffer(user_buf, count, ppos,
 111                                        buf, len);
 112 }
 113 
 114 static ssize_t aqm_write(struct file *file,
 115                          const char __user *user_buf,
 116                          size_t count,
 117                          loff_t *ppos)
 118 {
 119         struct ieee80211_local *local = file->private_data;
 120         char buf[100];
 121         size_t len;
 122 
 123         if (count > sizeof(buf))
 124                 return -EINVAL;
 125 
 126         if (copy_from_user(buf, user_buf, count))
 127                 return -EFAULT;
 128 
 129         buf[sizeof(buf) - 1] = '\0';
 130         len = strlen(buf);
 131         if (len > 0 && buf[len-1] == '\n')
 132                 buf[len-1] = 0;
 133 
 134         if (sscanf(buf, "fq_limit %u", &local->fq.limit) == 1)
 135                 return count;
 136         else if (sscanf(buf, "fq_memory_limit %u", &local->fq.memory_limit) == 1)
 137                 return count;
 138         else if (sscanf(buf, "fq_quantum %u", &local->fq.quantum) == 1)
 139                 return count;
 140 
 141         return -EINVAL;
 142 }
 143 
 144 static const struct file_operations aqm_ops = {
 145         .write = aqm_write,
 146         .read = aqm_read,
 147         .open = simple_open,
 148         .llseek = default_llseek,
 149 };
 150 
 151 static ssize_t force_tx_status_read(struct file *file,
 152                                     char __user *user_buf,
 153                                     size_t count,
 154                                     loff_t *ppos)
 155 {
 156         struct ieee80211_local *local = file->private_data;
 157         char buf[3];
 158         int len = 0;
 159 
 160         len = scnprintf(buf, sizeof(buf), "%d\n", (int)local->force_tx_status);
 161 
 162         return simple_read_from_buffer(user_buf, count, ppos,
 163                                        buf, len);
 164 }
 165 
 166 static ssize_t force_tx_status_write(struct file *file,
 167                                      const char __user *user_buf,
 168                                      size_t count,
 169                                      loff_t *ppos)
 170 {
 171         struct ieee80211_local *local = file->private_data;
 172         char buf[3];
 173         size_t len;
 174 
 175         if (count > sizeof(buf))
 176                 return -EINVAL;
 177 
 178         if (copy_from_user(buf, user_buf, count))
 179                 return -EFAULT;
 180 
 181         buf[sizeof(buf) - 1] = '\0';
 182         len = strlen(buf);
 183         if (len > 0 && buf[len - 1] == '\n')
 184                 buf[len - 1] = 0;
 185 
 186         if (buf[0] == '0' && buf[1] == '\0')
 187                 local->force_tx_status = 0;
 188         else if (buf[0] == '1' && buf[1] == '\0')
 189                 local->force_tx_status = 1;
 190         else
 191                 return -EINVAL;
 192 
 193         return count;
 194 }
 195 
 196 static const struct file_operations force_tx_status_ops = {
 197         .write = force_tx_status_write,
 198         .read = force_tx_status_read,
 199         .open = simple_open,
 200         .llseek = default_llseek,
 201 };
 202 
 203 #ifdef CONFIG_PM
 204 static ssize_t reset_write(struct file *file, const char __user *user_buf,
 205                            size_t count, loff_t *ppos)
 206 {
 207         struct ieee80211_local *local = file->private_data;
 208 
 209         rtnl_lock();
 210         __ieee80211_suspend(&local->hw, NULL);
 211         __ieee80211_resume(&local->hw);
 212         rtnl_unlock();
 213 
 214         return count;
 215 }
 216 
 217 static const struct file_operations reset_ops = {
 218         .write = reset_write,
 219         .open = simple_open,
 220         .llseek = noop_llseek,
 221 };
 222 #endif
 223 
 224 static const char *hw_flag_names[] = {
 225 #define FLAG(F) [IEEE80211_HW_##F] = #F
 226         FLAG(HAS_RATE_CONTROL),
 227         FLAG(RX_INCLUDES_FCS),
 228         FLAG(HOST_BROADCAST_PS_BUFFERING),
 229         FLAG(SIGNAL_UNSPEC),
 230         FLAG(SIGNAL_DBM),
 231         FLAG(NEED_DTIM_BEFORE_ASSOC),
 232         FLAG(SPECTRUM_MGMT),
 233         FLAG(AMPDU_AGGREGATION),
 234         FLAG(SUPPORTS_PS),
 235         FLAG(PS_NULLFUNC_STACK),
 236         FLAG(SUPPORTS_DYNAMIC_PS),
 237         FLAG(MFP_CAPABLE),
 238         FLAG(WANT_MONITOR_VIF),
 239         FLAG(NO_AUTO_VIF),
 240         FLAG(SW_CRYPTO_CONTROL),
 241         FLAG(SUPPORT_FAST_XMIT),
 242         FLAG(REPORTS_TX_ACK_STATUS),
 243         FLAG(CONNECTION_MONITOR),
 244         FLAG(QUEUE_CONTROL),
 245         FLAG(SUPPORTS_PER_STA_GTK),
 246         FLAG(AP_LINK_PS),
 247         FLAG(TX_AMPDU_SETUP_IN_HW),
 248         FLAG(SUPPORTS_RC_TABLE),
 249         FLAG(P2P_DEV_ADDR_FOR_INTF),
 250         FLAG(TIMING_BEACON_ONLY),
 251         FLAG(SUPPORTS_HT_CCK_RATES),
 252         FLAG(CHANCTX_STA_CSA),
 253         FLAG(SUPPORTS_CLONED_SKBS),
 254         FLAG(SINGLE_SCAN_ON_ALL_BANDS),
 255         FLAG(TDLS_WIDER_BW),
 256         FLAG(SUPPORTS_AMSDU_IN_AMPDU),
 257         FLAG(BEACON_TX_STATUS),
 258         FLAG(NEEDS_UNIQUE_STA_ADDR),
 259         FLAG(SUPPORTS_REORDERING_BUFFER),
 260         FLAG(USES_RSS),
 261         FLAG(TX_AMSDU),
 262         FLAG(TX_FRAG_LIST),
 263         FLAG(REPORTS_LOW_ACK),
 264         FLAG(SUPPORTS_TX_FRAG),
 265         FLAG(SUPPORTS_TDLS_BUFFER_STA),
 266         FLAG(DEAUTH_NEED_MGD_TX_PREP),
 267         FLAG(DOESNT_SUPPORT_QOS_NDP),
 268         FLAG(BUFF_MMPDU_TXQ),
 269         FLAG(SUPPORTS_VHT_EXT_NSS_BW),
 270         FLAG(STA_MMPDU_TXQ),
 271         FLAG(TX_STATUS_NO_AMPDU_LEN),
 272         FLAG(SUPPORTS_MULTI_BSSID),
 273         FLAG(SUPPORTS_ONLY_HE_MULTI_BSSID),
 274         FLAG(AMPDU_KEYBORDER_SUPPORT),
 275 #undef FLAG
 276 };
 277 
 278 static ssize_t hwflags_read(struct file *file, char __user *user_buf,
 279                             size_t count, loff_t *ppos)
 280 {
 281         struct ieee80211_local *local = file->private_data;
 282         size_t bufsz = 30 * NUM_IEEE80211_HW_FLAGS;
 283         char *buf = kzalloc(bufsz, GFP_KERNEL);
 284         char *pos = buf, *end = buf + bufsz - 1;
 285         ssize_t rv;
 286         int i;
 287 
 288         if (!buf)
 289                 return -ENOMEM;
 290 
 291         /* fail compilation if somebody adds or removes
 292          * a flag without updating the name array above
 293          */
 294         BUILD_BUG_ON(ARRAY_SIZE(hw_flag_names) != NUM_IEEE80211_HW_FLAGS);
 295 
 296         for (i = 0; i < NUM_IEEE80211_HW_FLAGS; i++) {
 297                 if (test_bit(i, local->hw.flags))
 298                         pos += scnprintf(pos, end - pos, "%s\n",
 299                                          hw_flag_names[i]);
 300         }
 301 
 302         rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
 303         kfree(buf);
 304         return rv;
 305 }
 306 
 307 static ssize_t misc_read(struct file *file, char __user *user_buf,
 308                          size_t count, loff_t *ppos)
 309 {
 310         struct ieee80211_local *local = file->private_data;
 311         /* Max len of each line is 16 characters, plus 9 for 'pending:\n' */
 312         size_t bufsz = IEEE80211_MAX_QUEUES * 16 + 9;
 313         char *buf;
 314         char *pos, *end;
 315         ssize_t rv;
 316         int i;
 317         int ln;
 318 
 319         buf = kzalloc(bufsz, GFP_KERNEL);
 320         if (!buf)
 321                 return -ENOMEM;
 322 
 323         pos = buf;
 324         end = buf + bufsz - 1;
 325 
 326         pos += scnprintf(pos, end - pos, "pending:\n");
 327 
 328         for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
 329                 ln = skb_queue_len(&local->pending[i]);
 330                 pos += scnprintf(pos, end - pos, "[%i] %d\n",
 331                                  i, ln);
 332         }
 333 
 334         rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
 335         kfree(buf);
 336         return rv;
 337 }
 338 
 339 static ssize_t queues_read(struct file *file, char __user *user_buf,
 340                            size_t count, loff_t *ppos)
 341 {
 342         struct ieee80211_local *local = file->private_data;
 343         unsigned long flags;
 344         char buf[IEEE80211_MAX_QUEUES * 20];
 345         int q, res = 0;
 346 
 347         spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
 348         for (q = 0; q < local->hw.queues; q++)
 349                 res += sprintf(buf + res, "%02d: %#.8lx/%d\n", q,
 350                                 local->queue_stop_reasons[q],
 351                                 skb_queue_len(&local->pending[q]));
 352         spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
 353 
 354         return simple_read_from_buffer(user_buf, count, ppos, buf, res);
 355 }
 356 
 357 DEBUGFS_READONLY_FILE_OPS(hwflags);
 358 DEBUGFS_READONLY_FILE_OPS(queues);
 359 DEBUGFS_READONLY_FILE_OPS(misc);
 360 
 361 /* statistics stuff */
 362 
 363 static ssize_t format_devstat_counter(struct ieee80211_local *local,
 364         char __user *userbuf,
 365         size_t count, loff_t *ppos,
 366         int (*printvalue)(struct ieee80211_low_level_stats *stats, char *buf,
 367                           int buflen))
 368 {
 369         struct ieee80211_low_level_stats stats;
 370         char buf[20];
 371         int res;
 372 
 373         rtnl_lock();
 374         res = drv_get_stats(local, &stats);
 375         rtnl_unlock();
 376         if (res)
 377                 return res;
 378         res = printvalue(&stats, buf, sizeof(buf));
 379         return simple_read_from_buffer(userbuf, count, ppos, buf, res);
 380 }
 381 
 382 #define DEBUGFS_DEVSTATS_FILE(name)                                     \
 383 static int print_devstats_##name(struct ieee80211_low_level_stats *stats,\
 384                                  char *buf, int buflen)                 \
 385 {                                                                       \
 386         return scnprintf(buf, buflen, "%u\n", stats->name);             \
 387 }                                                                       \
 388 static ssize_t stats_ ##name## _read(struct file *file,                 \
 389                                      char __user *userbuf,              \
 390                                      size_t count, loff_t *ppos)        \
 391 {                                                                       \
 392         return format_devstat_counter(file->private_data,               \
 393                                       userbuf,                          \
 394                                       count,                            \
 395                                       ppos,                             \
 396                                       print_devstats_##name);           \
 397 }                                                                       \
 398                                                                         \
 399 static const struct file_operations stats_ ##name## _ops = {            \
 400         .read = stats_ ##name## _read,                                  \
 401         .open = simple_open,                                            \
 402         .llseek = generic_file_llseek,                                  \
 403 };
 404 
 405 #define DEBUGFS_STATS_ADD(name)                                 \
 406         debugfs_create_u32(#name, 0400, statsd, &local->name);
 407 #define DEBUGFS_DEVSTATS_ADD(name)                                      \
 408         debugfs_create_file(#name, 0400, statsd, local, &stats_ ##name## _ops);
 409 
 410 DEBUGFS_DEVSTATS_FILE(dot11ACKFailureCount);
 411 DEBUGFS_DEVSTATS_FILE(dot11RTSFailureCount);
 412 DEBUGFS_DEVSTATS_FILE(dot11FCSErrorCount);
 413 DEBUGFS_DEVSTATS_FILE(dot11RTSSuccessCount);
 414 
 415 void debugfs_hw_add(struct ieee80211_local *local)
 416 {
 417         struct dentry *phyd = local->hw.wiphy->debugfsdir;
 418         struct dentry *statsd;
 419 
 420         if (!phyd)
 421                 return;
 422 
 423         local->debugfs.keys = debugfs_create_dir("keys", phyd);
 424 
 425         DEBUGFS_ADD(total_ps_buffered);
 426         DEBUGFS_ADD(wep_iv);
 427         DEBUGFS_ADD(rate_ctrl_alg);
 428         DEBUGFS_ADD(queues);
 429         DEBUGFS_ADD(misc);
 430 #ifdef CONFIG_PM
 431         DEBUGFS_ADD_MODE(reset, 0200);
 432 #endif
 433         DEBUGFS_ADD(hwflags);
 434         DEBUGFS_ADD(user_power);
 435         DEBUGFS_ADD(power);
 436         DEBUGFS_ADD_MODE(force_tx_status, 0600);
 437 
 438         if (local->ops->wake_tx_queue)
 439                 DEBUGFS_ADD_MODE(aqm, 0600);
 440 
 441         debugfs_create_u16("airtime_flags", 0600,
 442                            phyd, &local->airtime_flags);
 443 
 444         statsd = debugfs_create_dir("statistics", phyd);
 445 
 446         /* if the dir failed, don't put all the other things into the root! */
 447         if (!statsd)
 448                 return;
 449 
 450 #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
 451         DEBUGFS_STATS_ADD(dot11TransmittedFragmentCount);
 452         DEBUGFS_STATS_ADD(dot11MulticastTransmittedFrameCount);
 453         DEBUGFS_STATS_ADD(dot11FailedCount);
 454         DEBUGFS_STATS_ADD(dot11RetryCount);
 455         DEBUGFS_STATS_ADD(dot11MultipleRetryCount);
 456         DEBUGFS_STATS_ADD(dot11FrameDuplicateCount);
 457         DEBUGFS_STATS_ADD(dot11ReceivedFragmentCount);
 458         DEBUGFS_STATS_ADD(dot11MulticastReceivedFrameCount);
 459         DEBUGFS_STATS_ADD(dot11TransmittedFrameCount);
 460         DEBUGFS_STATS_ADD(tx_handlers_drop);
 461         DEBUGFS_STATS_ADD(tx_handlers_queued);
 462         DEBUGFS_STATS_ADD(tx_handlers_drop_wep);
 463         DEBUGFS_STATS_ADD(tx_handlers_drop_not_assoc);
 464         DEBUGFS_STATS_ADD(tx_handlers_drop_unauth_port);
 465         DEBUGFS_STATS_ADD(rx_handlers_drop);
 466         DEBUGFS_STATS_ADD(rx_handlers_queued);
 467         DEBUGFS_STATS_ADD(rx_handlers_drop_nullfunc);
 468         DEBUGFS_STATS_ADD(rx_handlers_drop_defrag);
 469         DEBUGFS_STATS_ADD(tx_expand_skb_head);
 470         DEBUGFS_STATS_ADD(tx_expand_skb_head_cloned);
 471         DEBUGFS_STATS_ADD(rx_expand_skb_head_defrag);
 472         DEBUGFS_STATS_ADD(rx_handlers_fragments);
 473         DEBUGFS_STATS_ADD(tx_status_drop);
 474 #endif
 475         DEBUGFS_DEVSTATS_ADD(dot11ACKFailureCount);
 476         DEBUGFS_DEVSTATS_ADD(dot11RTSFailureCount);
 477         DEBUGFS_DEVSTATS_ADD(dot11FCSErrorCount);
 478         DEBUGFS_DEVSTATS_ADD(dot11RTSSuccessCount);
 479 }

/* [<][>][^][v][top][bottom][index][help] */