diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00debug.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00debug.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index 6bee1d611bbf..5cf4c859e39d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c | |||
@@ -35,6 +35,13 @@ | |||
35 | 35 | ||
36 | #define MAX_LINE_LENGTH 64 | 36 | #define MAX_LINE_LENGTH 64 |
37 | 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 | |||
38 | struct rt2x00debug_intf { | 45 | struct rt2x00debug_intf { |
39 | /* | 46 | /* |
40 | * Pointer to driver structure where | 47 | * Pointer to driver structure where |
@@ -63,6 +70,7 @@ struct rt2x00debug_intf { | |||
63 | * - queue folder | 70 | * - queue folder |
64 | * - frame dump file | 71 | * - frame dump file |
65 | * - queue stats file | 72 | * - queue stats file |
73 | * - crypto stats file | ||
66 | */ | 74 | */ |
67 | struct dentry *driver_folder; | 75 | struct dentry *driver_folder; |
68 | struct dentry *driver_entry; | 76 | struct dentry *driver_entry; |
@@ -80,6 +88,7 @@ struct rt2x00debug_intf { | |||
80 | struct dentry *queue_folder; | 88 | struct dentry *queue_folder; |
81 | struct dentry *queue_frame_dump_entry; | 89 | struct dentry *queue_frame_dump_entry; |
82 | struct dentry *queue_stats_entry; | 90 | struct dentry *queue_stats_entry; |
91 | struct dentry *crypto_stats_entry; | ||
83 | 92 | ||
84 | /* | 93 | /* |
85 | * The frame dump file only allows a single reader, | 94 | * The frame dump file only allows a single reader, |
@@ -98,6 +107,12 @@ struct rt2x00debug_intf { | |||
98 | wait_queue_head_t frame_dump_waitqueue; | 107 | wait_queue_head_t frame_dump_waitqueue; |
99 | 108 | ||
100 | /* | 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 | /* | ||
101 | * Driver and chipset files will use a data buffer | 116 | * Driver and chipset files will use a data buffer |
102 | * that has been created in advance. This will simplify | 117 | * that has been created in advance. This will simplify |
103 | * the code since we can use the debugfs functions. | 118 | * the code since we can use the debugfs functions. |
@@ -114,6 +129,25 @@ struct rt2x00debug_intf { | |||
114 | unsigned int offset_rf; | 129 | unsigned int offset_rf; |
115 | }; | 130 | }; |
116 | 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 | |||
117 | void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, | 151 | void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, |
118 | enum rt2x00_dump_type type, struct sk_buff *skb) | 152 | enum rt2x00_dump_type type, struct sk_buff *skb) |
119 | { | 153 | { |
@@ -327,6 +361,59 @@ static const struct file_operations rt2x00debug_fop_queue_stats = { | |||
327 | .release = rt2x00debug_file_release, | 361 | .release = rt2x00debug_file_release, |
328 | }; | 362 | }; |
329 | 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 | |||
330 | #define RT2X00DEBUGFS_OPS_READ(__name, __format, __type) \ | 417 | #define RT2X00DEBUGFS_OPS_READ(__name, __format, __type) \ |
331 | static ssize_t rt2x00debug_read_##__name(struct file *file, \ | 418 | static ssize_t rt2x00debug_read_##__name(struct file *file, \ |
332 | char __user *buf, \ | 419 | char __user *buf, \ |
@@ -569,6 +656,13 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) | |||
569 | debugfs_create_file("queue", S_IRUSR, intf->queue_folder, | 656 | debugfs_create_file("queue", S_IRUSR, intf->queue_folder, |
570 | intf, &rt2x00debug_fop_queue_stats); | 657 | intf, &rt2x00debug_fop_queue_stats); |
571 | 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 | |||
572 | return; | 666 | return; |
573 | 667 | ||
574 | exit: | 668 | exit: |
@@ -587,6 +681,9 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev) | |||
587 | 681 | ||
588 | skb_queue_purge(&intf->frame_dump_skbqueue); | 682 | skb_queue_purge(&intf->frame_dump_skbqueue); |
589 | 683 | ||
684 | #ifdef CONFIG_RT2X00_LIB_CRYPTO | ||
685 | debugfs_remove(intf->crypto_stats_entry); | ||
686 | #endif | ||
590 | debugfs_remove(intf->queue_stats_entry); | 687 | debugfs_remove(intf->queue_stats_entry); |
591 | debugfs_remove(intf->queue_frame_dump_entry); | 688 | debugfs_remove(intf->queue_frame_dump_entry); |
592 | debugfs_remove(intf->queue_folder); | 689 | debugfs_remove(intf->queue_folder); |