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