0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/debugfs.h>
0014 #include <linux/kernel.h>
0015 #include <linux/module.h>
0016 #include <linux/poll.h>
0017 #include <linux/sched.h>
0018 #include <linux/slab.h>
0019 #include <linux/uaccess.h>
0020
0021 #include "rt2x00.h"
0022 #include "rt2x00lib.h"
0023 #include "rt2x00dump.h"
0024
0025 #define MAX_LINE_LENGTH 64
0026
0027 struct rt2x00debug_crypto {
0028 unsigned long success;
0029 unsigned long icv_error;
0030 unsigned long mic_error;
0031 unsigned long key_error;
0032 };
0033
0034 struct rt2x00debug_intf {
0035
0036
0037
0038
0039 struct rt2x00_dev *rt2x00dev;
0040
0041
0042
0043
0044
0045
0046 const struct rt2x00debug *debug;
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067 struct dentry *driver_folder;
0068
0069
0070
0071
0072
0073 unsigned long frame_dump_flags;
0074 #define FRAME_DUMP_FILE_OPEN 1
0075
0076
0077
0078
0079
0080
0081
0082 struct sk_buff_head frame_dump_skbqueue;
0083 wait_queue_head_t frame_dump_waitqueue;
0084
0085
0086
0087
0088
0089 struct rt2x00debug_crypto crypto_stats[CIPHER_MAX];
0090
0091
0092
0093
0094
0095
0096 struct debugfs_blob_wrapper driver_blob;
0097 struct debugfs_blob_wrapper chipset_blob;
0098
0099
0100
0101
0102 unsigned int offset_csr;
0103 unsigned int offset_eeprom;
0104 unsigned int offset_bbp;
0105 unsigned int offset_rf;
0106 unsigned int offset_rfcsr;
0107 };
0108
0109 void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,
0110 struct rxdone_entry_desc *rxdesc)
0111 {
0112 struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
0113 enum cipher cipher = rxdesc->cipher;
0114 enum rx_crypto status = rxdesc->cipher_status;
0115
0116 if (cipher == CIPHER_TKIP_NO_MIC)
0117 cipher = CIPHER_TKIP;
0118 if (cipher == CIPHER_NONE || cipher >= CIPHER_MAX)
0119 return;
0120
0121
0122 cipher--;
0123
0124 intf->crypto_stats[cipher].success += (status == RX_CRYPTO_SUCCESS);
0125 intf->crypto_stats[cipher].icv_error += (status == RX_CRYPTO_FAIL_ICV);
0126 intf->crypto_stats[cipher].mic_error += (status == RX_CRYPTO_FAIL_MIC);
0127 intf->crypto_stats[cipher].key_error += (status == RX_CRYPTO_FAIL_KEY);
0128 }
0129
0130 void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
0131 enum rt2x00_dump_type type, struct queue_entry *entry)
0132 {
0133 struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
0134 struct sk_buff *skb = entry->skb;
0135 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
0136 struct sk_buff *skbcopy;
0137 struct rt2x00dump_hdr *dump_hdr;
0138 struct timespec64 timestamp;
0139 u32 data_len;
0140
0141 if (likely(!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)))
0142 return;
0143
0144 ktime_get_ts64(×tamp);
0145
0146 if (skb_queue_len(&intf->frame_dump_skbqueue) > 20) {
0147 rt2x00_dbg(rt2x00dev, "txrx dump queue length exceeded\n");
0148 return;
0149 }
0150
0151 data_len = skb->len;
0152 if (skbdesc->flags & SKBDESC_DESC_IN_SKB)
0153 data_len -= skbdesc->desc_len;
0154
0155 skbcopy = alloc_skb(sizeof(*dump_hdr) + skbdesc->desc_len + data_len,
0156 GFP_ATOMIC);
0157 if (!skbcopy) {
0158 rt2x00_dbg(rt2x00dev, "Failed to copy skb for dump\n");
0159 return;
0160 }
0161
0162 dump_hdr = skb_put(skbcopy, sizeof(*dump_hdr));
0163 dump_hdr->version = cpu_to_le32(DUMP_HEADER_VERSION);
0164 dump_hdr->header_length = cpu_to_le32(sizeof(*dump_hdr));
0165 dump_hdr->desc_length = cpu_to_le32(skbdesc->desc_len);
0166 dump_hdr->data_length = cpu_to_le32(data_len);
0167 dump_hdr->chip_rt = cpu_to_le16(rt2x00dev->chip.rt);
0168 dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf);
0169 dump_hdr->chip_rev = cpu_to_le16(rt2x00dev->chip.rev);
0170 dump_hdr->type = cpu_to_le16(type);
0171 dump_hdr->queue_index = entry->queue->qid;
0172 dump_hdr->entry_index = entry->entry_idx;
0173 dump_hdr->timestamp_sec = cpu_to_le32(timestamp.tv_sec);
0174 dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_nsec /
0175 NSEC_PER_USEC);
0176
0177 if (!(skbdesc->flags & SKBDESC_DESC_IN_SKB))
0178 skb_put_data(skbcopy, skbdesc->desc, skbdesc->desc_len);
0179 skb_put_data(skbcopy, skb->data, skb->len);
0180
0181 skb_queue_tail(&intf->frame_dump_skbqueue, skbcopy);
0182 wake_up_interruptible(&intf->frame_dump_waitqueue);
0183
0184
0185
0186
0187 if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags))
0188 skb_queue_purge(&intf->frame_dump_skbqueue);
0189 }
0190 EXPORT_SYMBOL_GPL(rt2x00debug_dump_frame);
0191
0192 static int rt2x00debug_file_open(struct inode *inode, struct file *file)
0193 {
0194 struct rt2x00debug_intf *intf = inode->i_private;
0195
0196 file->private_data = inode->i_private;
0197
0198 if (!try_module_get(intf->debug->owner))
0199 return -EBUSY;
0200
0201 return 0;
0202 }
0203
0204 static int rt2x00debug_file_release(struct inode *inode, struct file *file)
0205 {
0206 struct rt2x00debug_intf *intf = file->private_data;
0207
0208 module_put(intf->debug->owner);
0209
0210 return 0;
0211 }
0212
0213 static int rt2x00debug_open_queue_dump(struct inode *inode, struct file *file)
0214 {
0215 struct rt2x00debug_intf *intf = inode->i_private;
0216 int retval;
0217
0218 retval = rt2x00debug_file_open(inode, file);
0219 if (retval)
0220 return retval;
0221
0222 if (test_and_set_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)) {
0223 rt2x00debug_file_release(inode, file);
0224 return -EBUSY;
0225 }
0226
0227 return 0;
0228 }
0229
0230 static int rt2x00debug_release_queue_dump(struct inode *inode, struct file *file)
0231 {
0232 struct rt2x00debug_intf *intf = inode->i_private;
0233
0234 skb_queue_purge(&intf->frame_dump_skbqueue);
0235
0236 clear_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags);
0237
0238 return rt2x00debug_file_release(inode, file);
0239 }
0240
0241 static ssize_t rt2x00debug_read_queue_dump(struct file *file,
0242 char __user *buf,
0243 size_t length,
0244 loff_t *offset)
0245 {
0246 struct rt2x00debug_intf *intf = file->private_data;
0247 struct sk_buff *skb;
0248 size_t status;
0249 int retval;
0250
0251 if (file->f_flags & O_NONBLOCK)
0252 return -EAGAIN;
0253
0254 retval =
0255 wait_event_interruptible(intf->frame_dump_waitqueue,
0256 (skb =
0257 skb_dequeue(&intf->frame_dump_skbqueue)));
0258 if (retval)
0259 return retval;
0260
0261 status = min_t(size_t, skb->len, length);
0262 if (copy_to_user(buf, skb->data, status)) {
0263 status = -EFAULT;
0264 goto exit;
0265 }
0266
0267 *offset += status;
0268
0269 exit:
0270 kfree_skb(skb);
0271
0272 return status;
0273 }
0274
0275 static __poll_t rt2x00debug_poll_queue_dump(struct file *file,
0276 poll_table *wait)
0277 {
0278 struct rt2x00debug_intf *intf = file->private_data;
0279
0280 poll_wait(file, &intf->frame_dump_waitqueue, wait);
0281
0282 if (!skb_queue_empty(&intf->frame_dump_skbqueue))
0283 return EPOLLOUT | EPOLLWRNORM;
0284
0285 return 0;
0286 }
0287
0288 static const struct file_operations rt2x00debug_fop_queue_dump = {
0289 .owner = THIS_MODULE,
0290 .read = rt2x00debug_read_queue_dump,
0291 .poll = rt2x00debug_poll_queue_dump,
0292 .open = rt2x00debug_open_queue_dump,
0293 .release = rt2x00debug_release_queue_dump,
0294 .llseek = default_llseek,
0295 };
0296
0297 static ssize_t rt2x00debug_read_queue_stats(struct file *file,
0298 char __user *buf,
0299 size_t length,
0300 loff_t *offset)
0301 {
0302 struct rt2x00debug_intf *intf = file->private_data;
0303 struct data_queue *queue;
0304 unsigned long irqflags;
0305 unsigned int lines = 1 + intf->rt2x00dev->data_queues;
0306 size_t size;
0307 char *data;
0308 char *temp;
0309
0310 if (*offset)
0311 return 0;
0312
0313 data = kcalloc(lines, MAX_LINE_LENGTH, GFP_KERNEL);
0314 if (!data)
0315 return -ENOMEM;
0316
0317 temp = data +
0318 sprintf(data, "qid\tflags\t\tcount\tlimit\tlength\tindex\tdma done\tdone\n");
0319
0320 queue_for_each(intf->rt2x00dev, queue) {
0321 spin_lock_irqsave(&queue->index_lock, irqflags);
0322
0323 temp += sprintf(temp, "%d\t0x%.8x\t%d\t%d\t%d\t%d\t%d\t\t%d\n",
0324 queue->qid, (unsigned int)queue->flags,
0325 queue->count, queue->limit, queue->length,
0326 queue->index[Q_INDEX],
0327 queue->index[Q_INDEX_DMA_DONE],
0328 queue->index[Q_INDEX_DONE]);
0329
0330 spin_unlock_irqrestore(&queue->index_lock, irqflags);
0331 }
0332
0333 size = strlen(data);
0334 size = min(size, length);
0335
0336 if (copy_to_user(buf, data, size)) {
0337 kfree(data);
0338 return -EFAULT;
0339 }
0340
0341 kfree(data);
0342
0343 *offset += size;
0344 return size;
0345 }
0346
0347 static const struct file_operations rt2x00debug_fop_queue_stats = {
0348 .owner = THIS_MODULE,
0349 .read = rt2x00debug_read_queue_stats,
0350 .open = rt2x00debug_file_open,
0351 .release = rt2x00debug_file_release,
0352 .llseek = default_llseek,
0353 };
0354
0355 #ifdef CONFIG_RT2X00_LIB_CRYPTO
0356 static ssize_t rt2x00debug_read_crypto_stats(struct file *file,
0357 char __user *buf,
0358 size_t length,
0359 loff_t *offset)
0360 {
0361 struct rt2x00debug_intf *intf = file->private_data;
0362 static const char * const name[] = { "WEP64", "WEP128", "TKIP", "AES" };
0363 char *data;
0364 char *temp;
0365 size_t size;
0366 unsigned int i;
0367
0368 if (*offset)
0369 return 0;
0370
0371 data = kcalloc(1 + CIPHER_MAX, MAX_LINE_LENGTH, GFP_KERNEL);
0372 if (!data)
0373 return -ENOMEM;
0374
0375 temp = data;
0376 temp += sprintf(data, "cipher\tsuccess\ticv err\tmic err\tkey err\n");
0377
0378 for (i = 0; i < CIPHER_MAX; i++) {
0379 temp += sprintf(temp, "%s\t%lu\t%lu\t%lu\t%lu\n", name[i],
0380 intf->crypto_stats[i].success,
0381 intf->crypto_stats[i].icv_error,
0382 intf->crypto_stats[i].mic_error,
0383 intf->crypto_stats[i].key_error);
0384 }
0385
0386 size = strlen(data);
0387 size = min(size, length);
0388
0389 if (copy_to_user(buf, data, size)) {
0390 kfree(data);
0391 return -EFAULT;
0392 }
0393
0394 kfree(data);
0395
0396 *offset += size;
0397 return size;
0398 }
0399
0400 static const struct file_operations rt2x00debug_fop_crypto_stats = {
0401 .owner = THIS_MODULE,
0402 .read = rt2x00debug_read_crypto_stats,
0403 .open = rt2x00debug_file_open,
0404 .release = rt2x00debug_file_release,
0405 .llseek = default_llseek,
0406 };
0407 #endif
0408
0409 #define RT2X00DEBUGFS_OPS_READ(__name, __format, __type) \
0410 static ssize_t rt2x00debug_read_##__name(struct file *file, \
0411 char __user *buf, \
0412 size_t length, \
0413 loff_t *offset) \
0414 { \
0415 struct rt2x00debug_intf *intf = file->private_data; \
0416 const struct rt2x00debug *debug = intf->debug; \
0417 char line[16]; \
0418 size_t size; \
0419 unsigned int index = intf->offset_##__name; \
0420 __type value; \
0421 \
0422 if (*offset) \
0423 return 0; \
0424 \
0425 if (index >= debug->__name.word_count) \
0426 return -EINVAL; \
0427 \
0428 index += (debug->__name.word_base / \
0429 debug->__name.word_size); \
0430 \
0431 if (debug->__name.flags & RT2X00DEBUGFS_OFFSET) \
0432 index *= debug->__name.word_size; \
0433 \
0434 value = debug->__name.read(intf->rt2x00dev, index); \
0435 \
0436 size = sprintf(line, __format, value); \
0437 \
0438 return simple_read_from_buffer(buf, length, offset, line, size); \
0439 }
0440
0441 #define RT2X00DEBUGFS_OPS_WRITE(__name, __type) \
0442 static ssize_t rt2x00debug_write_##__name(struct file *file, \
0443 const char __user *buf,\
0444 size_t length, \
0445 loff_t *offset) \
0446 { \
0447 struct rt2x00debug_intf *intf = file->private_data; \
0448 const struct rt2x00debug *debug = intf->debug; \
0449 char line[17]; \
0450 size_t size; \
0451 unsigned int index = intf->offset_##__name; \
0452 __type value; \
0453 \
0454 if (*offset) \
0455 return 0; \
0456 \
0457 if (index >= debug->__name.word_count) \
0458 return -EINVAL; \
0459 \
0460 if (length > sizeof(line)) \
0461 return -EINVAL; \
0462 \
0463 if (copy_from_user(line, buf, length)) \
0464 return -EFAULT; \
0465 line[16] = 0; \
0466 \
0467 size = strlen(line); \
0468 value = simple_strtoul(line, NULL, 0); \
0469 \
0470 index += (debug->__name.word_base / \
0471 debug->__name.word_size); \
0472 \
0473 if (debug->__name.flags & RT2X00DEBUGFS_OFFSET) \
0474 index *= debug->__name.word_size; \
0475 \
0476 debug->__name.write(intf->rt2x00dev, index, value); \
0477 \
0478 *offset += size; \
0479 return size; \
0480 }
0481
0482 #define RT2X00DEBUGFS_OPS(__name, __format, __type) \
0483 RT2X00DEBUGFS_OPS_READ(__name, __format, __type); \
0484 RT2X00DEBUGFS_OPS_WRITE(__name, __type); \
0485 \
0486 static const struct file_operations rt2x00debug_fop_##__name = {\
0487 .owner = THIS_MODULE, \
0488 .read = rt2x00debug_read_##__name, \
0489 .write = rt2x00debug_write_##__name, \
0490 .open = rt2x00debug_file_open, \
0491 .release = rt2x00debug_file_release, \
0492 .llseek = generic_file_llseek, \
0493 };
0494
0495 RT2X00DEBUGFS_OPS(csr, "0x%.8x\n", u32);
0496 RT2X00DEBUGFS_OPS(eeprom, "0x%.4x\n", u16);
0497 RT2X00DEBUGFS_OPS(bbp, "0x%.2x\n", u8);
0498 RT2X00DEBUGFS_OPS(rf, "0x%.8x\n", u32);
0499 RT2X00DEBUGFS_OPS(rfcsr, "0x%.2x\n", u8);
0500
0501 static ssize_t rt2x00debug_read_dev_flags(struct file *file,
0502 char __user *buf,
0503 size_t length,
0504 loff_t *offset)
0505 {
0506 struct rt2x00debug_intf *intf = file->private_data;
0507 char line[16];
0508 size_t size;
0509
0510 if (*offset)
0511 return 0;
0512
0513 size = sprintf(line, "0x%.8x\n", (unsigned int)intf->rt2x00dev->flags);
0514
0515 return simple_read_from_buffer(buf, length, offset, line, size);
0516 }
0517
0518 static const struct file_operations rt2x00debug_fop_dev_flags = {
0519 .owner = THIS_MODULE,
0520 .read = rt2x00debug_read_dev_flags,
0521 .open = rt2x00debug_file_open,
0522 .release = rt2x00debug_file_release,
0523 .llseek = default_llseek,
0524 };
0525
0526 static ssize_t rt2x00debug_read_cap_flags(struct file *file,
0527 char __user *buf,
0528 size_t length,
0529 loff_t *offset)
0530 {
0531 struct rt2x00debug_intf *intf = file->private_data;
0532 char line[16];
0533 size_t size;
0534
0535 if (*offset)
0536 return 0;
0537
0538 size = sprintf(line, "0x%.8x\n", (unsigned int)intf->rt2x00dev->cap_flags);
0539
0540 return simple_read_from_buffer(buf, length, offset, line, size);
0541 }
0542
0543 static const struct file_operations rt2x00debug_fop_cap_flags = {
0544 .owner = THIS_MODULE,
0545 .read = rt2x00debug_read_cap_flags,
0546 .open = rt2x00debug_file_open,
0547 .release = rt2x00debug_file_release,
0548 .llseek = default_llseek,
0549 };
0550
0551 static ssize_t rt2x00debug_write_restart_hw(struct file *file,
0552 const char __user *buf,
0553 size_t length,
0554 loff_t *offset)
0555 {
0556 struct rt2x00debug_intf *intf = file->private_data;
0557 struct rt2x00_dev *rt2x00dev = intf->rt2x00dev;
0558 static unsigned long last_reset = INITIAL_JIFFIES;
0559
0560 if (!rt2x00_has_cap_restart_hw(rt2x00dev))
0561 return -EOPNOTSUPP;
0562
0563 if (time_before(jiffies, last_reset + msecs_to_jiffies(2000)))
0564 return -EBUSY;
0565
0566 last_reset = jiffies;
0567
0568 ieee80211_restart_hw(rt2x00dev->hw);
0569 return length;
0570 }
0571
0572 static const struct file_operations rt2x00debug_restart_hw = {
0573 .owner = THIS_MODULE,
0574 .write = rt2x00debug_write_restart_hw,
0575 .open = simple_open,
0576 .llseek = generic_file_llseek,
0577 };
0578
0579 static void rt2x00debug_create_file_driver(const char *name,
0580 struct rt2x00debug_intf *intf,
0581 struct debugfs_blob_wrapper *blob)
0582 {
0583 char *data;
0584
0585 data = kzalloc(3 * MAX_LINE_LENGTH, GFP_KERNEL);
0586 if (!data)
0587 return;
0588
0589 blob->data = data;
0590 data += sprintf(data, "driver:\t%s\n", intf->rt2x00dev->ops->name);
0591 data += sprintf(data, "version:\t%s\n", DRV_VERSION);
0592 blob->size = strlen(blob->data);
0593
0594 debugfs_create_blob(name, 0400, intf->driver_folder, blob);
0595 }
0596
0597 static void rt2x00debug_create_file_chipset(const char *name,
0598 struct rt2x00debug_intf *intf,
0599 struct debugfs_blob_wrapper *blob)
0600 {
0601 const struct rt2x00debug *debug = intf->debug;
0602 char *data;
0603
0604 data = kzalloc(9 * MAX_LINE_LENGTH, GFP_KERNEL);
0605 if (!data)
0606 return;
0607
0608 blob->data = data;
0609 data += sprintf(data, "rt chip:\t%04x\n", intf->rt2x00dev->chip.rt);
0610 data += sprintf(data, "rf chip:\t%04x\n", intf->rt2x00dev->chip.rf);
0611 data += sprintf(data, "revision:\t%04x\n", intf->rt2x00dev->chip.rev);
0612 data += sprintf(data, "\n");
0613 data += sprintf(data, "register\tbase\twords\twordsize\n");
0614 #define RT2X00DEBUGFS_SPRINTF_REGISTER(__name) \
0615 { \
0616 if (debug->__name.read) \
0617 data += sprintf(data, __stringify(__name) \
0618 "\t%d\t%d\t%d\n", \
0619 debug->__name.word_base, \
0620 debug->__name.word_count, \
0621 debug->__name.word_size); \
0622 }
0623 RT2X00DEBUGFS_SPRINTF_REGISTER(csr);
0624 RT2X00DEBUGFS_SPRINTF_REGISTER(eeprom);
0625 RT2X00DEBUGFS_SPRINTF_REGISTER(bbp);
0626 RT2X00DEBUGFS_SPRINTF_REGISTER(rf);
0627 RT2X00DEBUGFS_SPRINTF_REGISTER(rfcsr);
0628 #undef RT2X00DEBUGFS_SPRINTF_REGISTER
0629
0630 blob->size = strlen(blob->data);
0631
0632 debugfs_create_blob(name, 0400, intf->driver_folder, blob);
0633 }
0634
0635 void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
0636 {
0637 const struct rt2x00debug *debug = rt2x00dev->ops->debugfs;
0638 struct rt2x00debug_intf *intf;
0639 struct dentry *queue_folder;
0640 struct dentry *register_folder;
0641
0642 intf = kzalloc(sizeof(struct rt2x00debug_intf), GFP_KERNEL);
0643 if (!intf) {
0644 rt2x00_err(rt2x00dev, "Failed to allocate debug handler\n");
0645 return;
0646 }
0647
0648 intf->debug = debug;
0649 intf->rt2x00dev = rt2x00dev;
0650 rt2x00dev->debugfs_intf = intf;
0651
0652 intf->driver_folder =
0653 debugfs_create_dir(intf->rt2x00dev->ops->name,
0654 rt2x00dev->hw->wiphy->debugfsdir);
0655
0656 rt2x00debug_create_file_driver("driver", intf, &intf->driver_blob);
0657 rt2x00debug_create_file_chipset("chipset", intf, &intf->chipset_blob);
0658 debugfs_create_file("dev_flags", 0400, intf->driver_folder, intf,
0659 &rt2x00debug_fop_dev_flags);
0660 debugfs_create_file("cap_flags", 0400, intf->driver_folder, intf,
0661 &rt2x00debug_fop_cap_flags);
0662 debugfs_create_file("restart_hw", 0200, intf->driver_folder, intf,
0663 &rt2x00debug_restart_hw);
0664
0665 register_folder = debugfs_create_dir("register", intf->driver_folder);
0666
0667 #define RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(__intf, __name) \
0668 ({ \
0669 if (debug->__name.read) { \
0670 debugfs_create_u32(__stringify(__name) "_offset", 0600, \
0671 register_folder, \
0672 &(__intf)->offset_##__name); \
0673 \
0674 debugfs_create_file(__stringify(__name) "_value", 0600, \
0675 register_folder, (__intf), \
0676 &rt2x00debug_fop_##__name); \
0677 } \
0678 })
0679
0680 RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, csr);
0681 RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, eeprom);
0682 RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, bbp);
0683 RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, rf);
0684 RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, rfcsr);
0685
0686 #undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY
0687
0688 queue_folder = debugfs_create_dir("queue", intf->driver_folder);
0689
0690 debugfs_create_file("dump", 0400, queue_folder, intf,
0691 &rt2x00debug_fop_queue_dump);
0692
0693 skb_queue_head_init(&intf->frame_dump_skbqueue);
0694 init_waitqueue_head(&intf->frame_dump_waitqueue);
0695
0696 debugfs_create_file("queue", 0400, queue_folder, intf,
0697 &rt2x00debug_fop_queue_stats);
0698
0699 #ifdef CONFIG_RT2X00_LIB_CRYPTO
0700 if (rt2x00_has_cap_hw_crypto(rt2x00dev))
0701 debugfs_create_file("crypto", 0444, queue_folder, intf,
0702 &rt2x00debug_fop_crypto_stats);
0703 #endif
0704
0705 return;
0706 }
0707
0708 void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
0709 {
0710 struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
0711
0712 if (unlikely(!intf))
0713 return;
0714
0715 skb_queue_purge(&intf->frame_dump_skbqueue);
0716
0717 debugfs_remove_recursive(intf->driver_folder);
0718 kfree(intf->chipset_blob.data);
0719 kfree(intf->driver_blob.data);
0720 kfree(intf);
0721
0722 rt2x00dev->debugfs_intf = NULL;
0723 }