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         *     - rfcsr offset/value files
  74         *   - queue folder
  75         *     - frame dump file
  76         *     - queue stats file
  77         *     - crypto stats file
  78         */
  79        struct dentry *driver_folder;
  80        struct dentry *driver_entry;
  81        struct dentry *chipset_entry;
  82        struct dentry *dev_flags;
  83        struct dentry *cap_flags;
  84        struct dentry *register_folder;
  85        struct dentry *csr_off_entry;
  86        struct dentry *csr_val_entry;
  87        struct dentry *eeprom_off_entry;
  88        struct dentry *eeprom_val_entry;
  89        struct dentry *bbp_off_entry;
  90        struct dentry *bbp_val_entry;
  91        struct dentry *rf_off_entry;
  92        struct dentry *rf_val_entry;
  93        struct dentry *rfcsr_off_entry;
  94        struct dentry *rfcsr_val_entry;
  95        struct dentry *queue_folder;
  96        struct dentry *queue_frame_dump_entry;
  97        struct dentry *queue_stats_entry;
  98        struct dentry *crypto_stats_entry;
  99
 100        /*
 101         * The frame dump file only allows a single reader,
 102         * so we need to store the current state here.
 103         */
 104        unsigned long frame_dump_flags;
 105#define FRAME_DUMP_FILE_OPEN    1
 106
 107        /*
 108         * We queue each frame before dumping it to the user,
 109         * per read command we will pass a single skb structure
 110         * so we should be prepared to queue multiple sk buffers
 111         * before sending it to userspace.
 112         */
 113        struct sk_buff_head frame_dump_skbqueue;
 114        wait_queue_head_t frame_dump_waitqueue;
 115
 116        /*
 117         * HW crypto statistics.
 118         * All statistics are stored separately per cipher type.
 119         */
 120        struct rt2x00debug_crypto crypto_stats[CIPHER_MAX];
 121
 122        /*
 123         * Driver and chipset files will use a data buffer
 124         * that has been created in advance. This will simplify
 125         * the code since we can use the debugfs functions.
 126         */
 127        struct debugfs_blob_wrapper driver_blob;
 128        struct debugfs_blob_wrapper chipset_blob;
 129
 130        /*
 131         * Requested offset for each register type.
 132         */
 133        unsigned int offset_csr;
 134        unsigned int offset_eeprom;
 135        unsigned int offset_bbp;
 136        unsigned int offset_rf;
 137        unsigned int offset_rfcsr;
 138};
 139
 140void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,
 141                               struct rxdone_entry_desc *rxdesc)
 142{
 143        struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
 144        enum cipher cipher = rxdesc->cipher;
 145        enum rx_crypto status = rxdesc->cipher_status;
 146
 147        if (cipher == CIPHER_TKIP_NO_MIC)
 148                cipher = CIPHER_TKIP;
 149        if (cipher == CIPHER_NONE || cipher >= CIPHER_MAX)
 150                return;
 151
 152        /* Remove CIPHER_NONE index */
 153        cipher--;
 154
 155        intf->crypto_stats[cipher].success += (status == RX_CRYPTO_SUCCESS);
 156        intf->crypto_stats[cipher].icv_error += (status == RX_CRYPTO_FAIL_ICV);
 157        intf->crypto_stats[cipher].mic_error += (status == RX_CRYPTO_FAIL_MIC);
 158        intf->crypto_stats[cipher].key_error += (status == RX_CRYPTO_FAIL_KEY);
 159}
 160
 161void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
 162                            enum rt2x00_dump_type type, struct sk_buff *skb)
 163{
 164        struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
 165        struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
 166        struct sk_buff *skbcopy;
 167        struct rt2x00dump_hdr *dump_hdr;
 168        struct timeval timestamp;
 169        u32 data_len;
 170
 171        if (likely(!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)))
 172                return;
 173
 174        do_gettimeofday(&timestamp);
 175
 176        if (skb_queue_len(&intf->frame_dump_skbqueue) > 20) {
 177                rt2x00_dbg(rt2x00dev, "txrx dump queue length exceeded\n");
 178                return;
 179        }
 180
 181        data_len = skb->len;
 182        if (skbdesc->flags & SKBDESC_DESC_IN_SKB)
 183                data_len -= skbdesc->desc_len;
 184
 185        skbcopy = alloc_skb(sizeof(*dump_hdr) + skbdesc->desc_len + data_len,
 186                            GFP_ATOMIC);
 187        if (!skbcopy) {
 188                rt2x00_dbg(rt2x00dev, "Failed to copy skb for dump\n");
 189                return;
 190        }
 191
 192        dump_hdr = (struct rt2x00dump_hdr *)skb_put(skbcopy, sizeof(*dump_hdr));
 193        dump_hdr->version = cpu_to_le32(DUMP_HEADER_VERSION);
 194        dump_hdr->header_length = cpu_to_le32(sizeof(*dump_hdr));
 195        dump_hdr->desc_length = cpu_to_le32(skbdesc->desc_len);
 196        dump_hdr->data_length = cpu_to_le32(data_len);
 197        dump_hdr->chip_rt = cpu_to_le16(rt2x00dev->chip.rt);
 198        dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf);
 199        dump_hdr->chip_rev = cpu_to_le16(rt2x00dev->chip.rev);
 200        dump_hdr->type = cpu_to_le16(type);
 201        dump_hdr->queue_index = skbdesc->entry->queue->qid;
 202        dump_hdr->entry_index = skbdesc->entry->entry_idx;
 203        dump_hdr->timestamp_sec = cpu_to_le32(timestamp.tv_sec);
 204        dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_usec);
 205
 206        if (!(skbdesc->flags & SKBDESC_DESC_IN_SKB))
 207                memcpy(skb_put(skbcopy, skbdesc->desc_len), skbdesc->desc,
 208                       skbdesc->desc_len);
 209        memcpy(skb_put(skbcopy, skb->len), skb->data, skb->len);
 210
 211        skb_queue_tail(&intf->frame_dump_skbqueue, skbcopy);
 212        wake_up_interruptible(&intf->frame_dump_waitqueue);
 213
 214        /*
 215         * Verify that the file has not been closed while we were working.
 216         */
 217        if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags))
 218                skb_queue_purge(&intf->frame_dump_skbqueue);
 219}
 220EXPORT_SYMBOL_GPL(rt2x00debug_dump_frame);
 221
 222static int rt2x00debug_file_open(struct inode *inode, struct file *file)
 223{
 224        struct rt2x00debug_intf *intf = inode->i_private;
 225
 226        file->private_data = inode->i_private;
 227
 228        if (!try_module_get(intf->debug->owner))
 229                return -EBUSY;
 230
 231        return 0;
 232}
 233
 234static int rt2x00debug_file_release(struct inode *inode, struct file *file)
 235{
 236        struct rt2x00debug_intf *intf = file->private_data;
 237
 238        module_put(intf->debug->owner);
 239
 240        return 0;
 241}
 242
 243static int rt2x00debug_open_queue_dump(struct inode *inode, struct file *file)
 244{
 245        struct rt2x00debug_intf *intf = inode->i_private;
 246        int retval;
 247
 248        retval = rt2x00debug_file_open(inode, file);
 249        if (retval)
 250                return retval;
 251
 252        if (test_and_set_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)) {
 253                rt2x00debug_file_release(inode, file);
 254                return -EBUSY;
 255        }
 256
 257        return 0;
 258}
 259
 260static int rt2x00debug_release_queue_dump(struct inode *inode, struct file *file)
 261{
 262        struct rt2x00debug_intf *intf = inode->i_private;
 263
 264        skb_queue_purge(&intf->frame_dump_skbqueue);
 265
 266        clear_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags);
 267
 268        return rt2x00debug_file_release(inode, file);
 269}
 270
 271static ssize_t rt2x00debug_read_queue_dump(struct file *file,
 272                                           char __user *buf,
 273                                           size_t length,
 274                                           loff_t *offset)
 275{
 276        struct rt2x00debug_intf *intf = file->private_data;
 277        struct sk_buff *skb;
 278        size_t status;
 279        int retval;
 280
 281        if (file->f_flags & O_NONBLOCK)
 282                return -EAGAIN;
 283
 284        retval =
 285            wait_event_interruptible(intf->frame_dump_waitqueue,
 286                                     (skb =
 287                                     skb_dequeue(&intf->frame_dump_skbqueue)));
 288        if (retval)
 289                return retval;
 290
 291        status = min((size_t)skb->len, length);
 292        if (copy_to_user(buf, skb->data, status)) {
 293                status = -EFAULT;
 294                goto exit;
 295        }
 296
 297        *offset += status;
 298
 299exit:
 300        kfree_skb(skb);
 301
 302        return status;
 303}
 304
 305static unsigned int rt2x00debug_poll_queue_dump(struct file *file,
 306                                                poll_table *wait)
 307{
 308        struct rt2x00debug_intf *intf = file->private_data;
 309
 310        poll_wait(file, &intf->frame_dump_waitqueue, wait);
 311
 312        if (!skb_queue_empty(&intf->frame_dump_skbqueue))
 313                return POLLOUT | POLLWRNORM;
 314
 315        return 0;
 316}
 317
 318static const struct file_operations rt2x00debug_fop_queue_dump = {
 319        .owner          = THIS_MODULE,
 320        .read           = rt2x00debug_read_queue_dump,
 321        .poll           = rt2x00debug_poll_queue_dump,
 322        .open           = rt2x00debug_open_queue_dump,
 323        .release        = rt2x00debug_release_queue_dump,
 324        .llseek         = default_llseek,
 325};
 326
 327static ssize_t rt2x00debug_read_queue_stats(struct file *file,
 328                                            char __user *buf,
 329                                            size_t length,
 330                                            loff_t *offset)
 331{
 332        struct rt2x00debug_intf *intf = file->private_data;
 333        struct data_queue *queue;
 334        unsigned long irqflags;
 335        unsigned int lines = 1 + intf->rt2x00dev->data_queues;
 336        size_t size;
 337        char *data;
 338        char *temp;
 339
 340        if (*offset)
 341                return 0;
 342
 343        data = kcalloc(lines, MAX_LINE_LENGTH, GFP_KERNEL);
 344        if (!data)
 345                return -ENOMEM;
 346
 347        temp = data +
 348            sprintf(data, "qid\tflags\t\tcount\tlimit\tlength\tindex\tdma done\tdone\n");
 349
 350        queue_for_each(intf->rt2x00dev, queue) {
 351                spin_lock_irqsave(&queue->index_lock, irqflags);
 352
 353                temp += sprintf(temp, "%d\t0x%.8x\t%d\t%d\t%d\t%d\t%d\t\t%d\n",
 354                                queue->qid, (unsigned int)queue->flags,
 355                                queue->count, queue->limit, queue->length,
 356                                queue->index[Q_INDEX],
 357                                queue->index[Q_INDEX_DMA_DONE],
 358                                queue->index[Q_INDEX_DONE]);
 359
 360                spin_unlock_irqrestore(&queue->index_lock, irqflags);
 361        }
 362
 363        size = strlen(data);
 364        size = min(size, length);
 365
 366        if (copy_to_user(buf, data, size)) {
 367                kfree(data);
 368                return -EFAULT;
 369        }
 370
 371        kfree(data);
 372
 373        *offset += size;
 374        return size;
 375}
 376
 377static const struct file_operations rt2x00debug_fop_queue_stats = {
 378        .owner          = THIS_MODULE,
 379        .read           = rt2x00debug_read_queue_stats,
 380        .open           = rt2x00debug_file_open,
 381        .release        = rt2x00debug_file_release,
 382        .llseek         = default_llseek,
 383};
 384
 385#ifdef CONFIG_RT2X00_LIB_CRYPTO
 386static ssize_t rt2x00debug_read_crypto_stats(struct file *file,
 387                                             char __user *buf,
 388                                             size_t length,
 389                                             loff_t *offset)
 390{
 391        struct rt2x00debug_intf *intf = file->private_data;
 392        static const char * const name[] = { "WEP64", "WEP128", "TKIP", "AES" };
 393        char *data;
 394        char *temp;
 395        size_t size;
 396        unsigned int i;
 397
 398        if (*offset)
 399                return 0;
 400
 401        data = kzalloc((1 + CIPHER_MAX) * MAX_LINE_LENGTH, GFP_KERNEL);
 402        if (!data)
 403                return -ENOMEM;
 404
 405        temp = data;
 406        temp += sprintf(data, "cipher\tsuccess\ticv err\tmic err\tkey err\n");
 407
 408        for (i = 0; i < CIPHER_MAX; i++) {
 409                temp += sprintf(temp, "%s\t%lu\t%lu\t%lu\t%lu\n", name[i],
 410                                intf->crypto_stats[i].success,
 411                                intf->crypto_stats[i].icv_error,
 412                                intf->crypto_stats[i].mic_error,
 413                                intf->crypto_stats[i].key_error);
 414        }
 415
 416        size = strlen(data);
 417        size = min(size, length);
 418
 419        if (copy_to_user(buf, data, size)) {
 420                kfree(data);
 421                return -EFAULT;
 422        }
 423
 424        kfree(data);
 425
 426        *offset += size;
 427        return size;
 428}
 429
 430static const struct file_operations rt2x00debug_fop_crypto_stats = {
 431        .owner          = THIS_MODULE,
 432        .read           = rt2x00debug_read_crypto_stats,
 433        .open           = rt2x00debug_file_open,
 434        .release        = rt2x00debug_file_release,
 435        .llseek         = default_llseek,
 436};
 437#endif
 438
 439#define RT2X00DEBUGFS_OPS_READ(__name, __format, __type)        \
 440static ssize_t rt2x00debug_read_##__name(struct file *file,     \
 441                                         char __user *buf,      \
 442                                         size_t length,         \
 443                                         loff_t *offset)        \
 444{                                                               \
 445        struct rt2x00debug_intf *intf = file->private_data;     \
 446        const struct rt2x00debug *debug = intf->debug;          \
 447        char line[16];                                          \
 448        size_t size;                                            \
 449        unsigned int index = intf->offset_##__name;             \
 450        __type value;                                           \
 451                                                                \
 452        if (*offset)                                            \
 453                return 0;                                       \
 454                                                                \
 455        if (index >= debug->__name.word_count)                  \
 456                return -EINVAL;                                 \
 457                                                                \
 458        index += (debug->__name.word_base /                     \
 459                  debug->__name.word_size);                     \
 460                                                                \
 461        if (debug->__name.flags & RT2X00DEBUGFS_OFFSET)         \
 462                index *= debug->__name.word_size;               \
 463                                                                \
 464        debug->__name.read(intf->rt2x00dev, index, &value);     \
 465                                                                \
 466        size = sprintf(line, __format, value);                  \
 467                                                                \
 468        if (copy_to_user(buf, line, size))                      \
 469                return -EFAULT;                                 \
 470                                                                \
 471        *offset += size;                                        \
 472        return size;                                            \
 473}
 474
 475#define RT2X00DEBUGFS_OPS_WRITE(__name, __type)                 \
 476static ssize_t rt2x00debug_write_##__name(struct file *file,    \
 477                                          const char __user *buf,\
 478                                          size_t length,        \
 479                                          loff_t *offset)       \
 480{                                                               \
 481        struct rt2x00debug_intf *intf = file->private_data;     \
 482        const struct rt2x00debug *debug = intf->debug;          \
 483        char line[16];                                          \
 484        size_t size;                                            \
 485        unsigned int index = intf->offset_##__name;             \
 486        __type value;                                           \
 487                                                                \
 488        if (*offset)                                            \
 489                return 0;                                       \
 490                                                                \
 491        if (index >= debug->__name.word_count)                  \
 492                return -EINVAL;                                 \
 493                                                                \
 494        if (length > sizeof(line))                              \
 495                return -EINVAL;                                 \
 496                                                                \
 497        if (copy_from_user(line, buf, length))                  \
 498                return -EFAULT;                                 \
 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 (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags))
 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