linux/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
<<
>>
Prefs
   1/*
   2        Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
   3        <http://rt2x00.serialmonkey.com>
   4
   5        This program is free software; you can redistribute it and/or modify
   6        it under the terms of the GNU General Public License as published by
   7        the Free Software Foundation; either version 2 of the License, or
   8        (at your option) any later version.
   9
  10        This program is distributed in the hope that it will be useful,
  11        but WITHOUT ANY WARRANTY; without even the implied warranty of
  12        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13        GNU General Public License for more details.
  14
  15        You should have received a copy of the GNU General Public License
  16        along with this program; if not, see <http://www.gnu.org/licenses/>.
  17 */
  18
  19/*
  20        Module: rt2x00lib
  21        Abstract: rt2x00 debugfs specific routines.
  22 */
  23
  24#include <linux/debugfs.h>
  25#include <linux/kernel.h>
  26#include <linux/module.h>
  27#include <linux/poll.h>
  28#include <linux/sched.h>
  29#include <linux/slab.h>
  30#include <linux/uaccess.h>
  31
  32#include "rt2x00.h"
  33#include "rt2x00lib.h"
  34#include "rt2x00dump.h"
  35
  36#define MAX_LINE_LENGTH 64
  37
  38struct rt2x00debug_crypto {
  39        unsigned long success;
  40        unsigned long icv_error;
  41        unsigned long mic_error;
  42        unsigned long key_error;
  43};
  44
  45struct rt2x00debug_intf {
  46        /*
  47         * Pointer to driver structure where
  48         * this debugfs entry belongs to.
  49         */
  50        struct rt2x00_dev *rt2x00dev;
  51
  52        /*
  53         * Reference to the rt2x00debug structure
  54         * which can be used to communicate with
  55         * the registers.
  56         */
  57        const struct rt2x00debug *debug;
  58
  59        /*
  60         * Debugfs entries for:
  61         * - driver folder
  62         *   - driver file
  63         *   - chipset file
  64         *   - device state flags file
  65         *   - device capability flags file
  66         *   - register folder
  67         *     - csr offset/value files
  68         *     - eeprom offset/value files
  69         *     - bbp offset/value files
  70         *     - rf offset/value files
  71         *     - rfcsr offset/value files
  72         *   - queue folder
  73         *     - frame dump file
  74         *     - queue stats file
  75         *     - crypto stats file
  76         */
  77        struct dentry *driver_folder;
  78        struct dentry *driver_entry;
  79        struct dentry *chipset_entry;
  80        struct dentry *dev_flags;
  81        struct dentry *cap_flags;
  82        struct dentry *register_folder;
  83        struct dentry *csr_off_entry;
  84        struct dentry *csr_val_entry;
  85        struct dentry *eeprom_off_entry;
  86        struct dentry *eeprom_val_entry;
  87        struct dentry *bbp_off_entry;
  88        struct dentry *bbp_val_entry;
  89        struct dentry *rf_off_entry;
  90        struct dentry *rf_val_entry;
  91        struct dentry *rfcsr_off_entry;
  92        struct dentry *rfcsr_val_entry;
  93        struct dentry *queue_folder;
  94        struct dentry *queue_frame_dump_entry;
  95        struct dentry *queue_stats_entry;
  96        struct dentry *crypto_stats_entry;
  97
  98        /*
  99         * The frame dump file only allows a single reader,
 100         * so we need to store the current state here.
 101         */
 102        unsigned long frame_dump_flags;
 103#define FRAME_DUMP_FILE_OPEN    1
 104
 105        /*
 106         * We queue each frame before dumping it to the user,
 107         * per read command we will pass a single skb structure
 108         * so we should be prepared to queue multiple sk buffers
 109         * before sending it to userspace.
 110         */
 111        struct sk_buff_head frame_dump_skbqueue;
 112        wait_queue_head_t frame_dump_waitqueue;
 113
 114        /*
 115         * HW crypto statistics.
 116         * All statistics are stored separately per cipher type.
 117         */
 118        struct rt2x00debug_crypto crypto_stats[CIPHER_MAX];
 119
 120        /*
 121         * Driver and chipset files will use a data buffer
 122         * that has been created in advance. This will simplify
 123         * the code since we can use the debugfs functions.
 124         */
 125        struct debugfs_blob_wrapper driver_blob;
 126        struct debugfs_blob_wrapper chipset_blob;
 127
 128        /*
 129         * Requested offset for each register type.
 130         */
 131        unsigned int offset_csr;
 132        unsigned int offset_eeprom;
 133        unsigned int offset_bbp;
 134        unsigned int offset_rf;
 135        unsigned int offset_rfcsr;
 136};
 137
 138void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,
 139                               struct rxdone_entry_desc *rxdesc)
 140{
 141        struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
 142        enum cipher cipher = rxdesc->cipher;
 143        enum rx_crypto status = rxdesc->cipher_status;
 144
 145        if (cipher == CIPHER_TKIP_NO_MIC)
 146                cipher = CIPHER_TKIP;
 147        if (cipher == CIPHER_NONE || cipher >= CIPHER_MAX)
 148                return;
 149
 150        /* Remove CIPHER_NONE index */
 151        cipher--;
 152
 153        intf->crypto_stats[cipher].success += (status == RX_CRYPTO_SUCCESS);
 154        intf->crypto_stats[cipher].icv_error += (status == RX_CRYPTO_FAIL_ICV);
 155        intf->crypto_stats[cipher].mic_error += (status == RX_CRYPTO_FAIL_MIC);
 156        intf->crypto_stats[cipher].key_error += (status == RX_CRYPTO_FAIL_KEY);
 157}
 158
 159void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
 160                            enum rt2x00_dump_type type, struct queue_entry *entry)
 161{
 162        struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
 163        struct sk_buff *skb = entry->skb;
 164        struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
 165        struct sk_buff *skbcopy;
 166        struct rt2x00dump_hdr *dump_hdr;
 167        struct timeval timestamp;
 168        u32 data_len;
 169
 170        if (likely(!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)))
 171                return;
 172
 173        do_gettimeofday(&timestamp);
 174
 175        if (skb_queue_len(&intf->frame_dump_skbqueue) > 20) {
 176                rt2x00_dbg(rt2x00dev, "txrx dump queue length exceeded\n");
 177                return;
 178        }
 179
 180        data_len = skb->len;
 181        if (skbdesc->flags & SKBDESC_DESC_IN_SKB)
 182                data_len -= skbdesc->desc_len;
 183
 184        skbcopy = alloc_skb(sizeof(*dump_hdr) + skbdesc->desc_len + data_len,
 185                            GFP_ATOMIC);
 186        if (!skbcopy) {
 187                rt2x00_dbg(rt2x00dev, "Failed to copy skb for dump\n");
 188                return;
 189        }
 190
 191        dump_hdr = (struct rt2x00dump_hdr *)skb_put(skbcopy, sizeof(*dump_hdr));
 192        dump_hdr->version = cpu_to_le32(DUMP_HEADER_VERSION);
 193        dump_hdr->header_length = cpu_to_le32(sizeof(*dump_hdr));
 194        dump_hdr->desc_length = cpu_to_le32(skbdesc->desc_len);
 195        dump_hdr->data_length = cpu_to_le32(data_len);
 196        dump_hdr->chip_rt = cpu_to_le16(rt2x00dev->chip.rt);
 197        dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf);
 198        dump_hdr->chip_rev = cpu_to_le16(rt2x00dev->chip.rev);
 199        dump_hdr->type = cpu_to_le16(type);
 200        dump_hdr->queue_index = entry->queue->qid;
 201        dump_hdr->entry_index = entry->entry_idx;
 202        dump_hdr->timestamp_sec = cpu_to_le32(timestamp.tv_sec);
 203        dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_usec);
 204
 205        if (!(skbdesc->flags & SKBDESC_DESC_IN_SKB))
 206                memcpy(skb_put(skbcopy, skbdesc->desc_len), skbdesc->desc,
 207                       skbdesc->desc_len);
 208        memcpy(skb_put(skbcopy, skb->len), skb->data, skb->len);
 209
 210        skb_queue_tail(&intf->frame_dump_skbqueue, skbcopy);
 211        wake_up_interruptible(&intf->frame_dump_waitqueue);
 212
 213        /*
 214         * Verify that the file has not been closed while we were working.
 215         */
 216        if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags))
 217                skb_queue_purge(&intf->frame_dump_skbqueue);
 218}
 219EXPORT_SYMBOL_GPL(rt2x00debug_dump_frame);
 220
 221static int rt2x00debug_file_open(struct inode *inode, struct file *file)
 222{
 223        struct rt2x00debug_intf *intf = inode->i_private;
 224
 225        file->private_data = inode->i_private;
 226
 227        if (!try_module_get(intf->debug->owner))
 228                return -EBUSY;
 229
 230        return 0;
 231}
 232
 233static int rt2x00debug_file_release(struct inode *inode, struct file *file)
 234{
 235        struct rt2x00debug_intf *intf = file->private_data;
 236
 237        module_put(intf->debug->owner);
 238
 239        return 0;
 240}
 241
 242static int rt2x00debug_open_queue_dump(struct inode *inode, struct file *file)
 243{
 244        struct rt2x00debug_intf *intf = inode->i_private;
 245        int retval;
 246
 247        retval = rt2x00debug_file_open(inode, file);
 248        if (retval)
 249                return retval;
 250
 251        if (test_and_set_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)) {
 252                rt2x00debug_file_release(inode, file);
 253                return -EBUSY;
 254        }
 255
 256        return 0;
 257}
 258
 259static int rt2x00debug_release_queue_dump(struct inode *inode, struct file *file)
 260{
 261        struct rt2x00debug_intf *intf = inode->i_private;
 262
 263        skb_queue_purge(&intf->frame_dump_skbqueue);
 264
 265        clear_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags);
 266
 267        return rt2x00debug_file_release(inode, file);
 268}
 269
 270static ssize_t rt2x00debug_read_queue_dump(struct file *file,
 271                                           char __user *buf,
 272                                           size_t length,
 273                                           loff_t *offset)
 274{
 275        struct rt2x00debug_intf *intf = file->private_data;
 276        struct sk_buff *skb;
 277        size_t status;
 278        int retval;
 279
 280        if (file->f_flags & O_NONBLOCK)
 281                return -EAGAIN;
 282
 283        retval =
 284            wait_event_interruptible(intf->frame_dump_waitqueue,
 285                                     (skb =
 286                                     skb_dequeue(&intf->frame_dump_skbqueue)));
 287        if (retval)
 288                return retval;
 289
 290        status = min_t(size_t, skb->len, length);
 291        if (copy_to_user(buf, skb->data, status)) {
 292                status = -EFAULT;
 293                goto exit;
 294        }
 295
 296        *offset += status;
 297
 298exit:
 299        kfree_skb(skb);
 300
 301        return status;
 302}
 303
 304static unsigned int rt2x00debug_poll_queue_dump(struct file *file,
 305                                                poll_table *wait)
 306{
 307        struct rt2x00debug_intf *intf = file->private_data;
 308
 309        poll_wait(file, &intf->frame_dump_waitqueue, wait);
 310
 311        if (!skb_queue_empty(&intf->frame_dump_skbqueue))
 312                return POLLOUT | POLLWRNORM;
 313
 314        return 0;
 315}
 316
 317static const struct file_operations rt2x00debug_fop_queue_dump = {
 318        .owner          = THIS_MODULE,
 319        .read           = rt2x00debug_read_queue_dump,
 320        .poll           = rt2x00debug_poll_queue_dump,
 321        .open           = rt2x00debug_open_queue_dump,
 322        .release        = rt2x00debug_release_queue_dump,
 323        .llseek         = default_llseek,
 324};
 325
 326static ssize_t rt2x00debug_read_queue_stats(struct file *file,
 327                                            char __user *buf,
 328                                            size_t length,
 329                                            loff_t *offset)
 330{
 331        struct rt2x00debug_intf *intf = file->private_data;
 332        struct data_queue *queue;
 333        unsigned long irqflags;
 334        unsigned int lines = 1 + intf->rt2x00dev->data_queues;
 335        size_t size;
 336        char *data;
 337        char *temp;
 338
 339        if (*offset)
 340                return 0;
 341
 342        data = kcalloc(lines, MAX_LINE_LENGTH, GFP_KERNEL);
 343        if (!data)
 344                return -ENOMEM;
 345
 346        temp = data +
 347            sprintf(data, "qid\tflags\t\tcount\tlimit\tlength\tindex\tdma done\tdone\n");
 348
 349        queue_for_each(intf->rt2x00dev, queue) {
 350                spin_lock_irqsave(&queue->index_lock, irqflags);
 351
 352                temp += sprintf(temp, "%d\t0x%.8x\t%d\t%d\t%d\t%d\t%d\t\t%d\n",
 353                                queue->qid, (unsigned int)queue->flags,
 354                                queue->count, queue->limit, queue->length,
 355                                queue->index[Q_INDEX],
 356                                queue->index[Q_INDEX_DMA_DONE],
 357                                queue->index[Q_INDEX_DONE]);
 358
 359                spin_unlock_irqrestore(&queue->index_lock, irqflags);
 360        }
 361
 362        size = strlen(data);
 363        size = min(size, length);
 364
 365        if (copy_to_user(buf, data, size)) {
 366                kfree(data);
 367                return -EFAULT;
 368        }
 369
 370        kfree(data);
 371
 372        *offset += size;
 373        return size;
 374}
 375
 376static const struct file_operations rt2x00debug_fop_queue_stats = {
 377        .owner          = THIS_MODULE,
 378        .read           = rt2x00debug_read_queue_stats,
 379        .open           = rt2x00debug_file_open,
 380        .release        = rt2x00debug_file_release,
 381        .llseek         = default_llseek,
 382};
 383
 384#ifdef CONFIG_RT2X00_LIB_CRYPTO
 385static ssize_t rt2x00debug_read_crypto_stats(struct file *file,
 386                                             char __user *buf,
 387                                             size_t length,
 388                                             loff_t *offset)
 389{
 390        struct rt2x00debug_intf *intf = file->private_data;
 391        static const char * const name[] = { "WEP64", "WEP128", "TKIP", "AES" };
 392        char *data;
 393        char *temp;
 394        size_t size;
 395        unsigned int i;
 396
 397        if (*offset)
 398                return 0;
 399
 400        data = kzalloc((1 + CIPHER_MAX) * MAX_LINE_LENGTH, GFP_KERNEL);
 401        if (!data)
 402                return -ENOMEM;
 403
 404        temp = data;
 405        temp += sprintf(data, "cipher\tsuccess\ticv err\tmic err\tkey err\n");
 406
 407        for (i = 0; i < CIPHER_MAX; i++) {
 408                temp += sprintf(temp, "%s\t%lu\t%lu\t%lu\t%lu\n", name[i],
 409                                intf->crypto_stats[i].success,
 410                                intf->crypto_stats[i].icv_error,
 411                                intf->crypto_stats[i].mic_error,
 412                                intf->crypto_stats[i].key_error);
 413        }
 414
 415        size = strlen(data);
 416        size = min(size, length);
 417
 418        if (copy_to_user(buf, data, size)) {
 419                kfree(data);
 420                return -EFAULT;
 421        }
 422
 423        kfree(data);
 424
 425        *offset += size;
 426        return size;
 427}
 428
 429static const struct file_operations rt2x00debug_fop_crypto_stats = {
 430        .owner          = THIS_MODULE,
 431        .read           = rt2x00debug_read_crypto_stats,
 432        .open           = rt2x00debug_file_open,
 433        .release        = rt2x00debug_file_release,
 434        .llseek         = default_llseek,
 435};
 436#endif
 437
 438#define RT2X00DEBUGFS_OPS_READ(__name, __format, __type)        \
 439static ssize_t rt2x00debug_read_##__name(struct file *file,     \
 440                                         char __user *buf,      \
 441                                         size_t length,         \
 442                                         loff_t *offset)        \
 443{                                                               \
 444        struct rt2x00debug_intf *intf = file->private_data;     \
 445        const struct rt2x00debug *debug = intf->debug;          \
 446        char line[16];                                          \
 447        size_t size;                                            \
 448        unsigned int index = intf->offset_##__name;             \
 449        __type value;                                           \
 450                                                                \
 451        if (*offset)                                            \
 452                return 0;                                       \
 453                                                                \
 454        if (index >= debug->__name.word_count)                  \
 455                return -EINVAL;                                 \
 456                                                                \
 457        index += (debug->__name.word_base /                     \
 458                  debug->__name.word_size);                     \
 459                                                                \
 460        if (debug->__name.flags & RT2X00DEBUGFS_OFFSET)         \
 461                index *= debug->__name.word_size;               \
 462                                                                \
 463        debug->__name.read(intf->rt2x00dev, index, &value);     \
 464                                                                \
 465        size = sprintf(line, __format, value);                  \
 466                                                                \
 467        if (copy_to_user(buf, line, size))                      \
 468                return -EFAULT;                                 \
 469                                                                \
 470        *offset += size;                                        \
 471        return size;                                            \
 472}
 473
 474#define RT2X00DEBUGFS_OPS_WRITE(__name, __type)                 \
 475static ssize_t rt2x00debug_write_##__name(struct file *file,    \
 476                                          const char __user *buf,\
 477                                          size_t length,        \
 478                                          loff_t *offset)       \
 479{                                                               \
 480        struct rt2x00debug_intf *intf = file->private_data;     \
 481        const struct rt2x00debug *debug = intf->debug;          \
 482        char line[17];                                          \
 483        size_t size;                                            \
 484        unsigned int index = intf->offset_##__name;             \
 485        __type value;                                           \
 486                                                                \
 487        if (*offset)                                            \
 488                return 0;                                       \
 489                                                                \
 490        if (index >= debug->__name.word_count)                  \
 491                return -EINVAL;                                 \
 492                                                                \
 493        if (length > sizeof(line))                              \
 494                return -EINVAL;                                 \
 495                                                                \
 496        if (copy_from_user(line, buf, length))                  \
 497                return -EFAULT;                                 \
 498        line[16] = 0;                                           \
 499                                                \
 500        size = strlen(line);                                    \
 501        value = simple_strtoul(line, NULL, 0);                  \
 502                                                                \
 503        index += (debug->__name.word_base /                     \
 504                  debug->__name.word_size);                     \
 505                                                                \
 506        if (debug->__name.flags & RT2X00DEBUGFS_OFFSET)         \
 507                index *= debug->__name.word_size;               \
 508                                                                \
 509        debug->__name.write(intf->rt2x00dev, index, value);     \
 510                                                                \
 511        *offset += size;                                        \
 512        return size;                                            \
 513}
 514
 515#define RT2X00DEBUGFS_OPS(__name, __format, __type)             \
 516RT2X00DEBUGFS_OPS_READ(__name, __format, __type);               \
 517RT2X00DEBUGFS_OPS_WRITE(__name, __type);                        \
 518                                                                \
 519static const struct file_operations rt2x00debug_fop_##__name = {\
 520        .owner          = THIS_MODULE,                          \
 521        .read           = rt2x00debug_read_##__name,            \
 522        .write          = rt2x00debug_write_##__name,           \
 523        .open           = rt2x00debug_file_open,                \
 524        .release        = rt2x00debug_file_release,             \
 525        .llseek         = generic_file_llseek,                  \
 526};
 527
 528RT2X00DEBUGFS_OPS(csr, "0x%.8x\n", u32);
 529RT2X00DEBUGFS_OPS(eeprom, "0x%.4x\n", u16);
 530RT2X00DEBUGFS_OPS(bbp, "0x%.2x\n", u8);
 531RT2X00DEBUGFS_OPS(rf, "0x%.8x\n", u32);
 532RT2X00DEBUGFS_OPS(rfcsr, "0x%.2x\n", u8);
 533
 534static ssize_t rt2x00debug_read_dev_flags(struct file *file,
 535                                          char __user *buf,
 536                                          size_t length,
 537                                          loff_t *offset)
 538{
 539        struct rt2x00debug_intf *intf = file->private_data;
 540        char line[16];
 541        size_t size;
 542
 543        if (*offset)
 544                return 0;
 545
 546        size = sprintf(line, "0x%.8x\n", (unsigned int)intf->rt2x00dev->flags);
 547
 548        if (copy_to_user(buf, line, size))
 549                return -EFAULT;
 550
 551        *offset += size;
 552        return size;
 553}
 554
 555static const struct file_operations rt2x00debug_fop_dev_flags = {
 556        .owner          = THIS_MODULE,
 557        .read           = rt2x00debug_read_dev_flags,
 558        .open           = rt2x00debug_file_open,
 559        .release        = rt2x00debug_file_release,
 560        .llseek         = default_llseek,
 561};
 562
 563static ssize_t rt2x00debug_read_cap_flags(struct file *file,
 564                                          char __user *buf,
 565                                          size_t length,
 566                                          loff_t *offset)
 567{
 568        struct rt2x00debug_intf *intf = file->private_data;
 569        char line[16];
 570        size_t size;
 571
 572        if (*offset)
 573                return 0;
 574
 575        size = sprintf(line, "0x%.8x\n", (unsigned int)intf->rt2x00dev->cap_flags);
 576
 577        if (copy_to_user(buf, line, size))
 578                return -EFAULT;
 579
 580        *offset += size;
 581        return size;
 582}
 583
 584static const struct file_operations rt2x00debug_fop_cap_flags = {
 585        .owner          = THIS_MODULE,
 586        .read           = rt2x00debug_read_cap_flags,
 587        .open           = rt2x00debug_file_open,
 588        .release        = rt2x00debug_file_release,
 589        .llseek         = default_llseek,
 590};
 591
 592static struct dentry *rt2x00debug_create_file_driver(const char *name,
 593                                                     struct rt2x00debug_intf
 594                                                     *intf,
 595                                                     struct debugfs_blob_wrapper
 596                                                     *blob)
 597{
 598        char *data;
 599
 600        data = kzalloc(3 * MAX_LINE_LENGTH, GFP_KERNEL);
 601        if (!data)
 602                return NULL;
 603
 604        blob->data = data;
 605        data += sprintf(data, "driver:\t%s\n", intf->rt2x00dev->ops->name);
 606        data += sprintf(data, "version:\t%s\n", DRV_VERSION);
 607        blob->size = strlen(blob->data);
 608
 609        return debugfs_create_blob(name, S_IRUSR, intf->driver_folder, blob);
 610}
 611
 612static struct dentry *rt2x00debug_create_file_chipset(const char *name,
 613                                                      struct rt2x00debug_intf
 614                                                      *intf,
 615                                                      struct
 616                                                      debugfs_blob_wrapper
 617                                                      *blob)
 618{
 619        const struct rt2x00debug *debug = intf->debug;
 620        char *data;
 621
 622        data = kzalloc(9 * MAX_LINE_LENGTH, GFP_KERNEL);
 623        if (!data)
 624                return NULL;
 625
 626        blob->data = data;
 627        data += sprintf(data, "rt chip:\t%04x\n", intf->rt2x00dev->chip.rt);
 628        data += sprintf(data, "rf chip:\t%04x\n", intf->rt2x00dev->chip.rf);
 629        data += sprintf(data, "revision:\t%04x\n", intf->rt2x00dev->chip.rev);
 630        data += sprintf(data, "\n");
 631        data += sprintf(data, "register\tbase\twords\twordsize\n");
 632#define RT2X00DEBUGFS_SPRINTF_REGISTER(__name)                  \
 633{                                                               \
 634        if (debug->__name.read)                                 \
 635                data += sprintf(data, __stringify(__name)       \
 636                                "\t%d\t%d\t%d\n",               \
 637                                debug->__name.word_base,        \
 638                                debug->__name.word_count,       \
 639                                debug->__name.word_size);       \
 640}
 641        RT2X00DEBUGFS_SPRINTF_REGISTER(csr);
 642        RT2X00DEBUGFS_SPRINTF_REGISTER(eeprom);
 643        RT2X00DEBUGFS_SPRINTF_REGISTER(bbp);
 644        RT2X00DEBUGFS_SPRINTF_REGISTER(rf);
 645        RT2X00DEBUGFS_SPRINTF_REGISTER(rfcsr);
 646#undef RT2X00DEBUGFS_SPRINTF_REGISTER
 647
 648        blob->size = strlen(blob->data);
 649
 650        return debugfs_create_blob(name, S_IRUSR, intf->driver_folder, blob);
 651}
 652
 653void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
 654{
 655        const struct rt2x00debug *debug = rt2x00dev->ops->debugfs;
 656        struct rt2x00debug_intf *intf;
 657
 658        intf = kzalloc(sizeof(struct rt2x00debug_intf), GFP_KERNEL);
 659        if (!intf) {
 660                rt2x00_err(rt2x00dev, "Failed to allocate debug handler\n");
 661                return;
 662        }
 663
 664        intf->debug = debug;
 665        intf->rt2x00dev = rt2x00dev;
 666        rt2x00dev->debugfs_intf = intf;
 667
 668        intf->driver_folder =
 669            debugfs_create_dir(intf->rt2x00dev->ops->name,
 670                               rt2x00dev->hw->wiphy->debugfsdir);
 671        if (IS_ERR(intf->driver_folder) || !intf->driver_folder)
 672                goto exit;
 673
 674        intf->driver_entry =
 675            rt2x00debug_create_file_driver("driver", intf, &intf->driver_blob);
 676        if (IS_ERR(intf->driver_entry) || !intf->driver_entry)
 677                goto exit;
 678
 679        intf->chipset_entry =
 680            rt2x00debug_create_file_chipset("chipset",
 681                                            intf, &intf->chipset_blob);
 682        if (IS_ERR(intf->chipset_entry) || !intf->chipset_entry)
 683                goto exit;
 684
 685        intf->dev_flags = debugfs_create_file("dev_flags", S_IRUSR,
 686                                              intf->driver_folder, intf,
 687                                              &rt2x00debug_fop_dev_flags);
 688        if (IS_ERR(intf->dev_flags) || !intf->dev_flags)
 689                goto exit;
 690
 691        intf->cap_flags = debugfs_create_file("cap_flags", S_IRUSR,
 692                                              intf->driver_folder, intf,
 693                                              &rt2x00debug_fop_cap_flags);
 694        if (IS_ERR(intf->cap_flags) || !intf->cap_flags)
 695                goto exit;
 696
 697        intf->register_folder =
 698            debugfs_create_dir("register", intf->driver_folder);
 699        if (IS_ERR(intf->register_folder) || !intf->register_folder)
 700                goto exit;
 701
 702#define RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(__intf, __name)                     \
 703({                                                                              \
 704        if (debug->__name.read) {                                               \
 705                (__intf)->__name##_off_entry =                                  \
 706                debugfs_create_u32(__stringify(__name) "_offset",               \
 707                                       S_IRUSR | S_IWUSR,                       \
 708                                       (__intf)->register_folder,               \
 709                                       &(__intf)->offset_##__name);             \
 710                if (IS_ERR((__intf)->__name##_off_entry)                        \
 711                                || !(__intf)->__name##_off_entry)               \
 712                        goto exit;                                              \
 713                                                                                \
 714                (__intf)->__name##_val_entry =                                  \
 715                debugfs_create_file(__stringify(__name) "_value",               \
 716                                        S_IRUSR | S_IWUSR,                      \
 717                                        (__intf)->register_folder,              \
 718                                        (__intf), &rt2x00debug_fop_##__name);   \
 719                if (IS_ERR((__intf)->__name##_val_entry)                        \
 720                                || !(__intf)->__name##_val_entry)               \
 721                        goto exit;                                              \
 722        }                                                                       \
 723})
 724
 725        RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, csr);
 726        RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, eeprom);
 727        RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, bbp);
 728        RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, rf);
 729        RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, rfcsr);
 730
 731#undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY
 732
 733        intf->queue_folder =
 734            debugfs_create_dir("queue", intf->driver_folder);
 735        if (IS_ERR(intf->queue_folder) || !intf->queue_folder)
 736                goto exit;
 737
 738        intf->queue_frame_dump_entry =
 739            debugfs_create_file("dump", S_IRUSR, intf->queue_folder,
 740                                intf, &rt2x00debug_fop_queue_dump);
 741        if (IS_ERR(intf->queue_frame_dump_entry)
 742                || !intf->queue_frame_dump_entry)
 743                goto exit;
 744
 745        skb_queue_head_init(&intf->frame_dump_skbqueue);
 746        init_waitqueue_head(&intf->frame_dump_waitqueue);
 747
 748        intf->queue_stats_entry =
 749            debugfs_create_file("queue", S_IRUSR, intf->queue_folder,
 750                                intf, &rt2x00debug_fop_queue_stats);
 751
 752#ifdef CONFIG_RT2X00_LIB_CRYPTO
 753        if (rt2x00_has_cap_hw_crypto(rt2x00dev))
 754                intf->crypto_stats_entry =
 755                    debugfs_create_file("crypto", S_IRUGO, intf->queue_folder,
 756                                        intf, &rt2x00debug_fop_crypto_stats);
 757#endif
 758
 759        return;
 760
 761exit:
 762        rt2x00debug_deregister(rt2x00dev);
 763        rt2x00_err(rt2x00dev, "Failed to register debug handler\n");
 764}
 765
 766void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
 767{
 768        struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
 769
 770        if (unlikely(!intf))
 771                return;
 772
 773        skb_queue_purge(&intf->frame_dump_skbqueue);
 774
 775#ifdef CONFIG_RT2X00_LIB_CRYPTO
 776        debugfs_remove(intf->crypto_stats_entry);
 777#endif
 778        debugfs_remove(intf->queue_stats_entry);
 779        debugfs_remove(intf->queue_frame_dump_entry);
 780        debugfs_remove(intf->queue_folder);
 781        debugfs_remove(intf->rfcsr_val_entry);
 782        debugfs_remove(intf->rfcsr_off_entry);
 783        debugfs_remove(intf->rf_val_entry);
 784        debugfs_remove(intf->rf_off_entry);
 785        debugfs_remove(intf->bbp_val_entry);
 786        debugfs_remove(intf->bbp_off_entry);
 787        debugfs_remove(intf->eeprom_val_entry);
 788        debugfs_remove(intf->eeprom_off_entry);
 789        debugfs_remove(intf->csr_val_entry);
 790        debugfs_remove(intf->csr_off_entry);
 791        debugfs_remove(intf->register_folder);
 792        debugfs_remove(intf->dev_flags);
 793        debugfs_remove(intf->cap_flags);
 794        debugfs_remove(intf->chipset_entry);
 795        debugfs_remove(intf->driver_entry);
 796        debugfs_remove(intf->driver_folder);
 797        kfree(intf->chipset_blob.data);
 798        kfree(intf->driver_blob.data);
 799        kfree(intf);
 800
 801        rt2x00dev->debugfs_intf = NULL;
 802}
 803