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