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