diff options
author | Eliad Peller <eliad@wizery.com> | 2011-05-15 04:10:30 -0400 |
---|---|---|
committer | Luciano Coelho <coelho@ti.com> | 2011-06-27 03:15:50 -0400 |
commit | c84368e01a00f449d97e8a59e1b0c24dcf70a8b3 (patch) | |
tree | 94e76522214288a5ca6f932e53740ee5bda6a343 /drivers/net | |
parent | 77ddaa108f727b5ef3be004b952d2c3d3ffc48e5 (diff) |
wl12xx: add rx_streaming debugfs entry
Allow control over rx_streaming interval and operation mode
(always/only on coex) via debugfs.
e.g.
echo 100 > /debug/ieee80211/phy0/wl12xx/rx_streaming/interval
echo 1 > /debug/ieee80211/phy0/wl12xx/rx_streaming/always
Signed-off-by: Eliad Peller <eliad@wizery.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/wl12xx/debugfs.c | 136 |
1 files changed, 135 insertions, 1 deletions
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index f1f8df9b6cd7..c3f19463474d 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c | |||
@@ -71,6 +71,14 @@ static const struct file_operations name## _ops = { \ | |||
71 | if (!entry || IS_ERR(entry)) \ | 71 | if (!entry || IS_ERR(entry)) \ |
72 | goto err; \ | 72 | goto err; \ |
73 | 73 | ||
74 | #define DEBUGFS_ADD_PREFIX(prefix, name, parent) \ | ||
75 | do { \ | ||
76 | entry = debugfs_create_file(#name, 0400, parent, \ | ||
77 | wl, &prefix## _## name## _ops); \ | ||
78 | if (!entry || IS_ERR(entry)) \ | ||
79 | goto err; \ | ||
80 | } while (0); | ||
81 | |||
74 | #define DEBUGFS_FWSTATS_FILE(sub, name, fmt) \ | 82 | #define DEBUGFS_FWSTATS_FILE(sub, name, fmt) \ |
75 | static ssize_t sub## _ ##name## _read(struct file *file, \ | 83 | static ssize_t sub## _ ##name## _read(struct file *file, \ |
76 | char __user *userbuf, \ | 84 | char __user *userbuf, \ |
@@ -527,11 +535,129 @@ static const struct file_operations beacon_interval_ops = { | |||
527 | .llseek = default_llseek, | 535 | .llseek = default_llseek, |
528 | }; | 536 | }; |
529 | 537 | ||
538 | static ssize_t rx_streaming_interval_write(struct file *file, | ||
539 | const char __user *user_buf, | ||
540 | size_t count, loff_t *ppos) | ||
541 | { | ||
542 | struct wl1271 *wl = file->private_data; | ||
543 | char buf[10]; | ||
544 | size_t len; | ||
545 | unsigned long value; | ||
546 | int ret; | ||
547 | |||
548 | len = min(count, sizeof(buf) - 1); | ||
549 | if (copy_from_user(buf, user_buf, len)) | ||
550 | return -EFAULT; | ||
551 | buf[len] = '\0'; | ||
552 | |||
553 | ret = kstrtoul(buf, 0, &value); | ||
554 | if (ret < 0) { | ||
555 | wl1271_warning("illegal value in rx_streaming_interval!"); | ||
556 | return -EINVAL; | ||
557 | } | ||
558 | |||
559 | /* valid values: 0, 10-100 */ | ||
560 | if (value && (value < 10 || value > 100)) { | ||
561 | wl1271_warning("value is not in range!"); | ||
562 | return -ERANGE; | ||
563 | } | ||
564 | |||
565 | mutex_lock(&wl->mutex); | ||
566 | |||
567 | wl->conf.rx_streaming.interval = value; | ||
568 | |||
569 | ret = wl1271_ps_elp_wakeup(wl); | ||
570 | if (ret < 0) | ||
571 | goto out; | ||
572 | |||
573 | wl1271_recalc_rx_streaming(wl); | ||
574 | |||
575 | wl1271_ps_elp_sleep(wl); | ||
576 | out: | ||
577 | mutex_unlock(&wl->mutex); | ||
578 | return count; | ||
579 | } | ||
580 | |||
581 | static ssize_t rx_streaming_interval_read(struct file *file, | ||
582 | char __user *userbuf, | ||
583 | size_t count, loff_t *ppos) | ||
584 | { | ||
585 | struct wl1271 *wl = file->private_data; | ||
586 | return wl1271_format_buffer(userbuf, count, ppos, | ||
587 | "%d\n", wl->conf.rx_streaming.interval); | ||
588 | } | ||
589 | |||
590 | static const struct file_operations rx_streaming_interval_ops = { | ||
591 | .read = rx_streaming_interval_read, | ||
592 | .write = rx_streaming_interval_write, | ||
593 | .open = wl1271_open_file_generic, | ||
594 | .llseek = default_llseek, | ||
595 | }; | ||
596 | |||
597 | static ssize_t rx_streaming_always_write(struct file *file, | ||
598 | const char __user *user_buf, | ||
599 | size_t count, loff_t *ppos) | ||
600 | { | ||
601 | struct wl1271 *wl = file->private_data; | ||
602 | char buf[10]; | ||
603 | size_t len; | ||
604 | unsigned long value; | ||
605 | int ret; | ||
606 | |||
607 | len = min(count, sizeof(buf) - 1); | ||
608 | if (copy_from_user(buf, user_buf, len)) | ||
609 | return -EFAULT; | ||
610 | buf[len] = '\0'; | ||
611 | |||
612 | ret = kstrtoul(buf, 0, &value); | ||
613 | if (ret < 0) { | ||
614 | wl1271_warning("illegal value in rx_streaming_write!"); | ||
615 | return -EINVAL; | ||
616 | } | ||
617 | |||
618 | /* valid values: 0, 10-100 */ | ||
619 | if (!(value == 0 || value == 1)) { | ||
620 | wl1271_warning("value is not in valid!"); | ||
621 | return -EINVAL; | ||
622 | } | ||
623 | |||
624 | mutex_lock(&wl->mutex); | ||
625 | |||
626 | wl->conf.rx_streaming.always = value; | ||
627 | |||
628 | ret = wl1271_ps_elp_wakeup(wl); | ||
629 | if (ret < 0) | ||
630 | goto out; | ||
631 | |||
632 | wl1271_recalc_rx_streaming(wl); | ||
633 | |||
634 | wl1271_ps_elp_sleep(wl); | ||
635 | out: | ||
636 | mutex_unlock(&wl->mutex); | ||
637 | return count; | ||
638 | } | ||
639 | |||
640 | static ssize_t rx_streaming_always_read(struct file *file, | ||
641 | char __user *userbuf, | ||
642 | size_t count, loff_t *ppos) | ||
643 | { | ||
644 | struct wl1271 *wl = file->private_data; | ||
645 | return wl1271_format_buffer(userbuf, count, ppos, | ||
646 | "%d\n", wl->conf.rx_streaming.always); | ||
647 | } | ||
648 | |||
649 | static const struct file_operations rx_streaming_always_ops = { | ||
650 | .read = rx_streaming_always_read, | ||
651 | .write = rx_streaming_always_write, | ||
652 | .open = wl1271_open_file_generic, | ||
653 | .llseek = default_llseek, | ||
654 | }; | ||
655 | |||
530 | static int wl1271_debugfs_add_files(struct wl1271 *wl, | 656 | static int wl1271_debugfs_add_files(struct wl1271 *wl, |
531 | struct dentry *rootdir) | 657 | struct dentry *rootdir) |
532 | { | 658 | { |
533 | int ret = 0; | 659 | int ret = 0; |
534 | struct dentry *entry, *stats; | 660 | struct dentry *entry, *stats, *streaming; |
535 | 661 | ||
536 | stats = debugfs_create_dir("fw-statistics", rootdir); | 662 | stats = debugfs_create_dir("fw-statistics", rootdir); |
537 | if (!stats || IS_ERR(stats)) { | 663 | if (!stats || IS_ERR(stats)) { |
@@ -640,6 +766,14 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl, | |||
640 | DEBUGFS_ADD(dtim_interval, rootdir); | 766 | DEBUGFS_ADD(dtim_interval, rootdir); |
641 | DEBUGFS_ADD(beacon_interval, rootdir); | 767 | DEBUGFS_ADD(beacon_interval, rootdir); |
642 | 768 | ||
769 | streaming = debugfs_create_dir("rx_streaming", rootdir); | ||
770 | if (!streaming || IS_ERR(streaming)) | ||
771 | goto err; | ||
772 | |||
773 | DEBUGFS_ADD_PREFIX(rx_streaming, interval, streaming); | ||
774 | DEBUGFS_ADD_PREFIX(rx_streaming, always, streaming); | ||
775 | |||
776 | |||
643 | return 0; | 777 | return 0; |
644 | 778 | ||
645 | err: | 779 | err: |