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