linux/net/mac80211/debugfs.c
<<
>>
Prefs
   1/*
   2 * mac80211 debugfs for wireless PHYs
   3 *
   4 * Copyright 2007       Johannes Berg <johannes@sipsolutions.net>
   5 *
   6 * GPLv2
   7 *
   8 */
   9
  10#include <linux/debugfs.h>
  11#include <linux/rtnetlink.h>
  12#include "ieee80211_i.h"
  13#include "rate.h"
  14#include "debugfs.h"
  15
  16int mac80211_open_file_generic(struct inode *inode, struct file *file)
  17{
  18        file->private_data = inode->i_private;
  19        return 0;
  20}
  21
  22#define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...)              \
  23static ssize_t name## _read(struct file *file, char __user *userbuf,    \
  24                            size_t count, loff_t *ppos)                 \
  25{                                                                       \
  26        struct ieee80211_local *local = file->private_data;             \
  27        char buf[buflen];                                               \
  28        int res;                                                        \
  29                                                                        \
  30        res = scnprintf(buf, buflen, fmt "\n", ##value);                \
  31        return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
  32}                                                                       \
  33                                                                        \
  34static const struct file_operations name## _ops = {                     \
  35        .read = name## _read,                                           \
  36        .open = mac80211_open_file_generic,                             \
  37};
  38
  39#define DEBUGFS_ADD(name)                                               \
  40        local->debugfs.name = debugfs_create_file(#name, 0400, phyd,    \
  41                                                  local, &name## _ops);
  42
  43#define DEBUGFS_ADD_MODE(name, mode)                                    \
  44        local->debugfs.name = debugfs_create_file(#name, mode, phyd,    \
  45                                                  local, &name## _ops);
  46
  47#define DEBUGFS_DEL(name)                                               \
  48        debugfs_remove(local->debugfs.name);                            \
  49        local->debugfs.name = NULL;
  50
  51
  52DEBUGFS_READONLY_FILE(frequency, 20, "%d",
  53                      local->hw.conf.channel->center_freq);
  54DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d",
  55                      local->rts_threshold);
  56DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d",
  57                      local->fragmentation_threshold);
  58DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d",
  59                      local->hw.conf.short_frame_max_tx_count);
  60DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d",
  61                      local->hw.conf.long_frame_max_tx_count);
  62DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d",
  63                      local->total_ps_buffered);
  64DEBUGFS_READONLY_FILE(wep_iv, 20, "%#08x",
  65                      local->wep_iv & 0xffffff);
  66DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s",
  67                      local->rate_ctrl ? local->rate_ctrl->ops->name : "<unset>");
  68
  69static ssize_t tsf_read(struct file *file, char __user *user_buf,
  70                             size_t count, loff_t *ppos)
  71{
  72        struct ieee80211_local *local = file->private_data;
  73        u64 tsf = 0;
  74        char buf[100];
  75
  76        if (local->ops->get_tsf)
  77                tsf = local->ops->get_tsf(local_to_hw(local));
  78
  79        snprintf(buf, sizeof(buf), "0x%016llx\n", (unsigned long long) tsf);
  80
  81        return simple_read_from_buffer(user_buf, count, ppos, buf, 19);
  82}
  83
  84static ssize_t tsf_write(struct file *file,
  85                         const char __user *user_buf,
  86                         size_t count, loff_t *ppos)
  87{
  88        struct ieee80211_local *local = file->private_data;
  89        unsigned long long tsf;
  90        char buf[100];
  91        size_t len;
  92
  93        len = min(count, sizeof(buf) - 1);
  94        if (copy_from_user(buf, user_buf, len))
  95                return -EFAULT;
  96        buf[len] = '\0';
  97
  98        if (strncmp(buf, "reset", 5) == 0) {
  99                if (local->ops->reset_tsf) {
 100                        local->ops->reset_tsf(local_to_hw(local));
 101                        printk(KERN_INFO "%s: debugfs reset TSF\n", wiphy_name(local->hw.wiphy));
 102                }
 103        } else {
 104                tsf = simple_strtoul(buf, NULL, 0);
 105                if (local->ops->set_tsf) {
 106                        local->ops->set_tsf(local_to_hw(local), tsf);
 107                        printk(KERN_INFO "%s: debugfs set TSF to %#018llx\n", wiphy_name(local->hw.wiphy), tsf);
 108                }
 109        }
 110
 111        return count;
 112}
 113
 114static const struct file_operations tsf_ops = {
 115        .read = tsf_read,
 116        .write = tsf_write,
 117        .open = mac80211_open_file_generic
 118};
 119
 120static ssize_t reset_write(struct file *file, const char __user *user_buf,
 121                           size_t count, loff_t *ppos)
 122{
 123        struct ieee80211_local *local = file->private_data;
 124
 125        rtnl_lock();
 126        __ieee80211_suspend(&local->hw);
 127        __ieee80211_resume(&local->hw);
 128        rtnl_unlock();
 129
 130        return count;
 131}
 132
 133static const struct file_operations reset_ops = {
 134        .write = reset_write,
 135        .open = mac80211_open_file_generic,
 136};
 137
 138/* statistics stuff */
 139
 140#define DEBUGFS_STATS_FILE(name, buflen, fmt, value...)                 \
 141        DEBUGFS_READONLY_FILE(stats_ ##name, buflen, fmt, ##value)
 142
 143static ssize_t format_devstat_counter(struct ieee80211_local *local,
 144        char __user *userbuf,
 145        size_t count, loff_t *ppos,
 146        int (*printvalue)(struct ieee80211_low_level_stats *stats, char *buf,
 147                          int buflen))
 148{
 149        struct ieee80211_low_level_stats stats;
 150        char buf[20];
 151        int res;
 152
 153        if (!local->ops->get_stats)
 154                return -EOPNOTSUPP;
 155
 156        rtnl_lock();
 157        res = local->ops->get_stats(local_to_hw(local), &stats);
 158        rtnl_unlock();
 159        if (!res)
 160                res = printvalue(&stats, buf, sizeof(buf));
 161        return simple_read_from_buffer(userbuf, count, ppos, buf, res);
 162}
 163
 164#define DEBUGFS_DEVSTATS_FILE(name)                                     \
 165static int print_devstats_##name(struct ieee80211_low_level_stats *stats,\
 166                                 char *buf, int buflen)                 \
 167{                                                                       \
 168        return scnprintf(buf, buflen, "%u\n", stats->name);             \
 169}                                                                       \
 170static ssize_t stats_ ##name## _read(struct file *file,                 \
 171                                     char __user *userbuf,              \
 172                                     size_t count, loff_t *ppos)        \
 173{                                                                       \
 174        return format_devstat_counter(file->private_data,               \
 175                                      userbuf,                          \
 176                                      count,                            \
 177                                      ppos,                             \
 178                                      print_devstats_##name);           \
 179}                                                                       \
 180                                                                        \
 181static const struct file_operations stats_ ##name## _ops = {            \
 182        .read = stats_ ##name## _read,                                  \
 183        .open = mac80211_open_file_generic,                             \
 184};
 185
 186#define DEBUGFS_STATS_ADD(name)                                         \
 187        local->debugfs.stats.name = debugfs_create_file(#name, 0400, statsd,\
 188                local, &stats_ ##name## _ops);
 189
 190#define DEBUGFS_STATS_DEL(name)                                         \
 191        debugfs_remove(local->debugfs.stats.name);                      \
 192        local->debugfs.stats.name = NULL;
 193
 194DEBUGFS_STATS_FILE(transmitted_fragment_count, 20, "%u",
 195                   local->dot11TransmittedFragmentCount);
 196DEBUGFS_STATS_FILE(multicast_transmitted_frame_count, 20, "%u",
 197                   local->dot11MulticastTransmittedFrameCount);
 198DEBUGFS_STATS_FILE(failed_count, 20, "%u",
 199                   local->dot11FailedCount);
 200DEBUGFS_STATS_FILE(retry_count, 20, "%u",
 201                   local->dot11RetryCount);
 202DEBUGFS_STATS_FILE(multiple_retry_count, 20, "%u",
 203                   local->dot11MultipleRetryCount);
 204DEBUGFS_STATS_FILE(frame_duplicate_count, 20, "%u",
 205                   local->dot11FrameDuplicateCount);
 206DEBUGFS_STATS_FILE(received_fragment_count, 20, "%u",
 207                   local->dot11ReceivedFragmentCount);
 208DEBUGFS_STATS_FILE(multicast_received_frame_count, 20, "%u",
 209                   local->dot11MulticastReceivedFrameCount);
 210DEBUGFS_STATS_FILE(transmitted_frame_count, 20, "%u",
 211                   local->dot11TransmittedFrameCount);
 212#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
 213DEBUGFS_STATS_FILE(tx_handlers_drop, 20, "%u",
 214                   local->tx_handlers_drop);
 215DEBUGFS_STATS_FILE(tx_handlers_queued, 20, "%u",
 216                   local->tx_handlers_queued);
 217DEBUGFS_STATS_FILE(tx_handlers_drop_unencrypted, 20, "%u",
 218                   local->tx_handlers_drop_unencrypted);
 219DEBUGFS_STATS_FILE(tx_handlers_drop_fragment, 20, "%u",
 220                   local->tx_handlers_drop_fragment);
 221DEBUGFS_STATS_FILE(tx_handlers_drop_wep, 20, "%u",
 222                   local->tx_handlers_drop_wep);
 223DEBUGFS_STATS_FILE(tx_handlers_drop_not_assoc, 20, "%u",
 224                   local->tx_handlers_drop_not_assoc);
 225DEBUGFS_STATS_FILE(tx_handlers_drop_unauth_port, 20, "%u",
 226                   local->tx_handlers_drop_unauth_port);
 227DEBUGFS_STATS_FILE(rx_handlers_drop, 20, "%u",
 228                   local->rx_handlers_drop);
 229DEBUGFS_STATS_FILE(rx_handlers_queued, 20, "%u",
 230                   local->rx_handlers_queued);
 231DEBUGFS_STATS_FILE(rx_handlers_drop_nullfunc, 20, "%u",
 232                   local->rx_handlers_drop_nullfunc);
 233DEBUGFS_STATS_FILE(rx_handlers_drop_defrag, 20, "%u",
 234                   local->rx_handlers_drop_defrag);
 235DEBUGFS_STATS_FILE(rx_handlers_drop_short, 20, "%u",
 236                   local->rx_handlers_drop_short);
 237DEBUGFS_STATS_FILE(rx_handlers_drop_passive_scan, 20, "%u",
 238                   local->rx_handlers_drop_passive_scan);
 239DEBUGFS_STATS_FILE(tx_expand_skb_head, 20, "%u",
 240                   local->tx_expand_skb_head);
 241DEBUGFS_STATS_FILE(tx_expand_skb_head_cloned, 20, "%u",
 242                   local->tx_expand_skb_head_cloned);
 243DEBUGFS_STATS_FILE(rx_expand_skb_head, 20, "%u",
 244                   local->rx_expand_skb_head);
 245DEBUGFS_STATS_FILE(rx_expand_skb_head2, 20, "%u",
 246                   local->rx_expand_skb_head2);
 247DEBUGFS_STATS_FILE(rx_handlers_fragments, 20, "%u",
 248                   local->rx_handlers_fragments);
 249DEBUGFS_STATS_FILE(tx_status_drop, 20, "%u",
 250                   local->tx_status_drop);
 251
 252#endif
 253
 254DEBUGFS_DEVSTATS_FILE(dot11ACKFailureCount);
 255DEBUGFS_DEVSTATS_FILE(dot11RTSFailureCount);
 256DEBUGFS_DEVSTATS_FILE(dot11FCSErrorCount);
 257DEBUGFS_DEVSTATS_FILE(dot11RTSSuccessCount);
 258
 259
 260void debugfs_hw_add(struct ieee80211_local *local)
 261{
 262        struct dentry *phyd = local->hw.wiphy->debugfsdir;
 263        struct dentry *statsd;
 264
 265        if (!phyd)
 266                return;
 267
 268        local->debugfs.stations = debugfs_create_dir("stations", phyd);
 269        local->debugfs.keys = debugfs_create_dir("keys", phyd);
 270
 271        DEBUGFS_ADD(frequency);
 272        DEBUGFS_ADD(rts_threshold);
 273        DEBUGFS_ADD(fragmentation_threshold);
 274        DEBUGFS_ADD(short_retry_limit);
 275        DEBUGFS_ADD(long_retry_limit);
 276        DEBUGFS_ADD(total_ps_buffered);
 277        DEBUGFS_ADD(wep_iv);
 278        DEBUGFS_ADD(tsf);
 279        DEBUGFS_ADD_MODE(reset, 0200);
 280
 281        statsd = debugfs_create_dir("statistics", phyd);
 282        local->debugfs.statistics = statsd;
 283
 284        /* if the dir failed, don't put all the other things into the root! */
 285        if (!statsd)
 286                return;
 287
 288        DEBUGFS_STATS_ADD(transmitted_fragment_count);
 289        DEBUGFS_STATS_ADD(multicast_transmitted_frame_count);
 290        DEBUGFS_STATS_ADD(failed_count);
 291        DEBUGFS_STATS_ADD(retry_count);
 292        DEBUGFS_STATS_ADD(multiple_retry_count);
 293        DEBUGFS_STATS_ADD(frame_duplicate_count);
 294        DEBUGFS_STATS_ADD(received_fragment_count);
 295        DEBUGFS_STATS_ADD(multicast_received_frame_count);
 296        DEBUGFS_STATS_ADD(transmitted_frame_count);
 297#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
 298        DEBUGFS_STATS_ADD(tx_handlers_drop);
 299        DEBUGFS_STATS_ADD(tx_handlers_queued);
 300        DEBUGFS_STATS_ADD(tx_handlers_drop_unencrypted);
 301        DEBUGFS_STATS_ADD(tx_handlers_drop_fragment);
 302        DEBUGFS_STATS_ADD(tx_handlers_drop_wep);
 303        DEBUGFS_STATS_ADD(tx_handlers_drop_not_assoc);
 304        DEBUGFS_STATS_ADD(tx_handlers_drop_unauth_port);
 305        DEBUGFS_STATS_ADD(rx_handlers_drop);
 306        DEBUGFS_STATS_ADD(rx_handlers_queued);
 307        DEBUGFS_STATS_ADD(rx_handlers_drop_nullfunc);
 308        DEBUGFS_STATS_ADD(rx_handlers_drop_defrag);
 309        DEBUGFS_STATS_ADD(rx_handlers_drop_short);
 310        DEBUGFS_STATS_ADD(rx_handlers_drop_passive_scan);
 311        DEBUGFS_STATS_ADD(tx_expand_skb_head);
 312        DEBUGFS_STATS_ADD(tx_expand_skb_head_cloned);
 313        DEBUGFS_STATS_ADD(rx_expand_skb_head);
 314        DEBUGFS_STATS_ADD(rx_expand_skb_head2);
 315        DEBUGFS_STATS_ADD(rx_handlers_fragments);
 316        DEBUGFS_STATS_ADD(tx_status_drop);
 317#endif
 318        DEBUGFS_STATS_ADD(dot11ACKFailureCount);
 319        DEBUGFS_STATS_ADD(dot11RTSFailureCount);
 320        DEBUGFS_STATS_ADD(dot11FCSErrorCount);
 321        DEBUGFS_STATS_ADD(dot11RTSSuccessCount);
 322}
 323
 324void debugfs_hw_del(struct ieee80211_local *local)
 325{
 326        DEBUGFS_DEL(frequency);
 327        DEBUGFS_DEL(rts_threshold);
 328        DEBUGFS_DEL(fragmentation_threshold);
 329        DEBUGFS_DEL(short_retry_limit);
 330        DEBUGFS_DEL(long_retry_limit);
 331        DEBUGFS_DEL(total_ps_buffered);
 332        DEBUGFS_DEL(wep_iv);
 333        DEBUGFS_DEL(tsf);
 334        DEBUGFS_DEL(reset);
 335
 336        DEBUGFS_STATS_DEL(transmitted_fragment_count);
 337        DEBUGFS_STATS_DEL(multicast_transmitted_frame_count);
 338        DEBUGFS_STATS_DEL(failed_count);
 339        DEBUGFS_STATS_DEL(retry_count);
 340        DEBUGFS_STATS_DEL(multiple_retry_count);
 341        DEBUGFS_STATS_DEL(frame_duplicate_count);
 342        DEBUGFS_STATS_DEL(received_fragment_count);
 343        DEBUGFS_STATS_DEL(multicast_received_frame_count);
 344        DEBUGFS_STATS_DEL(transmitted_frame_count);
 345        DEBUGFS_STATS_DEL(num_scans);
 346#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
 347        DEBUGFS_STATS_DEL(tx_handlers_drop);
 348        DEBUGFS_STATS_DEL(tx_handlers_queued);
 349        DEBUGFS_STATS_DEL(tx_handlers_drop_unencrypted);
 350        DEBUGFS_STATS_DEL(tx_handlers_drop_fragment);
 351        DEBUGFS_STATS_DEL(tx_handlers_drop_wep);
 352        DEBUGFS_STATS_DEL(tx_handlers_drop_not_assoc);
 353        DEBUGFS_STATS_DEL(tx_handlers_drop_unauth_port);
 354        DEBUGFS_STATS_DEL(rx_handlers_drop);
 355        DEBUGFS_STATS_DEL(rx_handlers_queued);
 356        DEBUGFS_STATS_DEL(rx_handlers_drop_nullfunc);
 357        DEBUGFS_STATS_DEL(rx_handlers_drop_defrag);
 358        DEBUGFS_STATS_DEL(rx_handlers_drop_short);
 359        DEBUGFS_STATS_DEL(rx_handlers_drop_passive_scan);
 360        DEBUGFS_STATS_DEL(tx_expand_skb_head);
 361        DEBUGFS_STATS_DEL(tx_expand_skb_head_cloned);
 362        DEBUGFS_STATS_DEL(rx_expand_skb_head);
 363        DEBUGFS_STATS_DEL(rx_expand_skb_head2);
 364        DEBUGFS_STATS_DEL(rx_handlers_fragments);
 365        DEBUGFS_STATS_DEL(tx_status_drop);
 366#endif
 367        DEBUGFS_STATS_DEL(dot11ACKFailureCount);
 368        DEBUGFS_STATS_DEL(dot11RTSFailureCount);
 369        DEBUGFS_STATS_DEL(dot11FCSErrorCount);
 370        DEBUGFS_STATS_DEL(dot11RTSSuccessCount);
 371
 372        debugfs_remove(local->debugfs.statistics);
 373        local->debugfs.statistics = NULL;
 374        debugfs_remove(local->debugfs.stations);
 375        local->debugfs.stations = NULL;
 376        debugfs_remove(local->debugfs.keys);
 377        local->debugfs.keys = NULL;
 378}
 379