root/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rt2x00debug_update_crypto
  2. rt2x00debug_dump_frame
  3. rt2x00debug_file_open
  4. rt2x00debug_file_release
  5. rt2x00debug_open_queue_dump
  6. rt2x00debug_release_queue_dump
  7. rt2x00debug_read_queue_dump
  8. rt2x00debug_poll_queue_dump
  9. rt2x00debug_read_queue_stats
  10. rt2x00debug_read_crypto_stats
  11. rt2x00debug_read_dev_flags
  12. rt2x00debug_read_cap_flags
  13. rt2x00debug_write_restart_hw
  14. rt2x00debug_create_file_driver
  15. rt2x00debug_create_file_chipset
  16. rt2x00debug_register
  17. rt2x00debug_deregister

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

/* [<][>][^][v][top][bottom][index][help] */