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