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