diff options
author | Ivo van Doorn <ivdoorn@gmail.com> | 2008-02-10 16:50:28 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-02-29 15:37:20 -0500 |
commit | 68598d294b6bc1ecc418359994234cb43f4635ad (patch) | |
tree | 90504409cad902a6d935be5b03f8947e699c2808 | |
parent | e44df9296a8ab9d9160e230d68a1b01015c94e93 (diff) |
rt2x00: Add queue statistics to debugfs
Rename "frame" folder to "queue" folder,
add extra file to this folder which contains
statistics about all hardware queues. This will
help debugging and spotting problems in the
queue indexing system.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00debug.c | 90 |
1 files changed, 76 insertions, 14 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index 4e048ac0a684..21af11a97334 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c | |||
@@ -33,7 +33,7 @@ | |||
33 | #include "rt2x00lib.h" | 33 | #include "rt2x00lib.h" |
34 | #include "rt2x00dump.h" | 34 | #include "rt2x00dump.h" |
35 | 35 | ||
36 | #define PRINT_LINE_LEN_MAX 32 | 36 | #define MAX_LINE_LENGTH 64 |
37 | 37 | ||
38 | struct rt2x00debug_intf { | 38 | struct rt2x00debug_intf { |
39 | /* | 39 | /* |
@@ -60,8 +60,9 @@ struct rt2x00debug_intf { | |||
60 | * - eeprom offset/value files | 60 | * - eeprom offset/value files |
61 | * - bbp offset/value files | 61 | * - bbp offset/value files |
62 | * - rf offset/value files | 62 | * - rf offset/value files |
63 | * - frame dump folder | 63 | * - queue folder |
64 | * - frame dump file | 64 | * - frame dump file |
65 | * - queue stats file | ||
65 | */ | 66 | */ |
66 | struct dentry *driver_folder; | 67 | struct dentry *driver_folder; |
67 | struct dentry *driver_entry; | 68 | struct dentry *driver_entry; |
@@ -76,8 +77,9 @@ struct rt2x00debug_intf { | |||
76 | struct dentry *bbp_val_entry; | 77 | struct dentry *bbp_val_entry; |
77 | struct dentry *rf_off_entry; | 78 | struct dentry *rf_off_entry; |
78 | struct dentry *rf_val_entry; | 79 | struct dentry *rf_val_entry; |
79 | struct dentry *frame_folder; | 80 | struct dentry *queue_folder; |
80 | struct dentry *frame_dump_entry; | 81 | struct dentry *queue_frame_dump_entry; |
82 | struct dentry *queue_stats_entry; | ||
81 | 83 | ||
82 | /* | 84 | /* |
83 | * The frame dump file only allows a single reader, | 85 | * The frame dump file only allows a single reader, |
@@ -269,6 +271,61 @@ static const struct file_operations rt2x00debug_fop_queue_dump = { | |||
269 | .release = rt2x00debug_release_queue_dump, | 271 | .release = rt2x00debug_release_queue_dump, |
270 | }; | 272 | }; |
271 | 273 | ||
274 | static ssize_t rt2x00debug_read_queue_stats(struct file *file, | ||
275 | char __user *buf, | ||
276 | size_t length, | ||
277 | loff_t *offset) | ||
278 | { | ||
279 | struct rt2x00debug_intf *intf = file->private_data; | ||
280 | struct data_queue *queue; | ||
281 | unsigned int lines = 1 + intf->rt2x00dev->data_queues; | ||
282 | size_t size; | ||
283 | char *data; | ||
284 | char *temp; | ||
285 | |||
286 | if (*offset) | ||
287 | return 0; | ||
288 | |||
289 | data = kzalloc(lines * MAX_LINE_LENGTH, GFP_KERNEL); | ||
290 | if (!data) | ||
291 | return -ENOMEM; | ||
292 | |||
293 | temp = data + | ||
294 | sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdone\tcrypto\n"); | ||
295 | |||
296 | queue_for_each(intf->rt2x00dev, queue) { | ||
297 | spin_lock(&queue->lock); | ||
298 | |||
299 | temp += sprintf(temp, "%d\t%d\t%d\t%d\t%d\t%d\t%d\n", queue->qid, | ||
300 | queue->count, queue->limit, queue->length, | ||
301 | queue->index[Q_INDEX], | ||
302 | queue->index[Q_INDEX_DONE], | ||
303 | queue->index[Q_INDEX_CRYPTO]); | ||
304 | |||
305 | spin_unlock(&queue->lock); | ||
306 | } | ||
307 | |||
308 | size = strlen(data); | ||
309 | size = min(size, length); | ||
310 | |||
311 | if (copy_to_user(buf, data, size)) { | ||
312 | kfree(data); | ||
313 | return -EFAULT; | ||
314 | } | ||
315 | |||
316 | kfree(data); | ||
317 | |||
318 | *offset += size; | ||
319 | return size; | ||
320 | } | ||
321 | |||
322 | static const struct file_operations rt2x00debug_fop_queue_stats = { | ||
323 | .owner = THIS_MODULE, | ||
324 | .read = rt2x00debug_read_queue_stats, | ||
325 | .open = rt2x00debug_file_open, | ||
326 | .release = rt2x00debug_file_release, | ||
327 | }; | ||
328 | |||
272 | #define RT2X00DEBUGFS_OPS_READ(__name, __format, __type) \ | 329 | #define RT2X00DEBUGFS_OPS_READ(__name, __format, __type) \ |
273 | static ssize_t rt2x00debug_read_##__name(struct file *file, \ | 330 | static ssize_t rt2x00debug_read_##__name(struct file *file, \ |
274 | char __user *buf, \ | 331 | char __user *buf, \ |
@@ -386,7 +443,7 @@ static struct dentry *rt2x00debug_create_file_driver(const char *name, | |||
386 | { | 443 | { |
387 | char *data; | 444 | char *data; |
388 | 445 | ||
389 | data = kzalloc(3 * PRINT_LINE_LEN_MAX, GFP_KERNEL); | 446 | data = kzalloc(3 * MAX_LINE_LENGTH, GFP_KERNEL); |
390 | if (!data) | 447 | if (!data) |
391 | return NULL; | 448 | return NULL; |
392 | 449 | ||
@@ -409,7 +466,7 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name, | |||
409 | const struct rt2x00debug *debug = intf->debug; | 466 | const struct rt2x00debug *debug = intf->debug; |
410 | char *data; | 467 | char *data; |
411 | 468 | ||
412 | data = kzalloc(8 * PRINT_LINE_LEN_MAX, GFP_KERNEL); | 469 | data = kzalloc(8 * MAX_LINE_LENGTH, GFP_KERNEL); |
413 | if (!data) | 470 | if (!data) |
414 | return NULL; | 471 | return NULL; |
415 | 472 | ||
@@ -496,20 +553,24 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) | |||
496 | 553 | ||
497 | #undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY | 554 | #undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY |
498 | 555 | ||
499 | intf->frame_folder = | 556 | intf->queue_folder = |
500 | debugfs_create_dir("frame", intf->driver_folder); | 557 | debugfs_create_dir("queue", intf->driver_folder); |
501 | if (IS_ERR(intf->frame_folder)) | 558 | if (IS_ERR(intf->queue_folder)) |
502 | goto exit; | 559 | goto exit; |
503 | 560 | ||
504 | intf->frame_dump_entry = | 561 | intf->queue_frame_dump_entry = |
505 | debugfs_create_file("dump", S_IRUGO, intf->frame_folder, | 562 | debugfs_create_file("dump", S_IRUGO, intf->queue_folder, |
506 | intf, &rt2x00debug_fop_queue_dump); | 563 | intf, &rt2x00debug_fop_queue_dump); |
507 | if (IS_ERR(intf->frame_dump_entry)) | 564 | if (IS_ERR(intf->queue_frame_dump_entry)) |
508 | goto exit; | 565 | goto exit; |
509 | 566 | ||
510 | skb_queue_head_init(&intf->frame_dump_skbqueue); | 567 | skb_queue_head_init(&intf->frame_dump_skbqueue); |
511 | init_waitqueue_head(&intf->frame_dump_waitqueue); | 568 | init_waitqueue_head(&intf->frame_dump_waitqueue); |
512 | 569 | ||
570 | intf->queue_stats_entry = | ||
571 | debugfs_create_file("queue", S_IRUGO, intf->queue_folder, | ||
572 | intf, &rt2x00debug_fop_queue_stats); | ||
573 | |||
513 | return; | 574 | return; |
514 | 575 | ||
515 | exit: | 576 | exit: |
@@ -528,8 +589,9 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev) | |||
528 | 589 | ||
529 | skb_queue_purge(&intf->frame_dump_skbqueue); | 590 | skb_queue_purge(&intf->frame_dump_skbqueue); |
530 | 591 | ||
531 | debugfs_remove(intf->frame_dump_entry); | 592 | debugfs_remove(intf->queue_stats_entry); |
532 | debugfs_remove(intf->frame_folder); | 593 | debugfs_remove(intf->queue_frame_dump_entry); |
594 | debugfs_remove(intf->queue_folder); | ||
533 | debugfs_remove(intf->rf_val_entry); | 595 | debugfs_remove(intf->rf_val_entry); |
534 | debugfs_remove(intf->rf_off_entry); | 596 | debugfs_remove(intf->rf_off_entry); |
535 | debugfs_remove(intf->bbp_val_entry); | 597 | debugfs_remove(intf->bbp_val_entry); |