diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-05-19 11:19:36 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-05-22 14:05:59 -0400 |
commit | 87057825824973f29cf2f37cff1e549170b2d7e6 (patch) | |
tree | dbbb7596aeea401a1e9c9379d0948889dbde8884 | |
parent | 9cef873798dfcdc10ff40b02abf1de935ceeba85 (diff) |
wext: remove atomic requirement for wireless stats
The requirement for wireless stats to be atomic is now mostly
artificial since we hold the rtnl _and_ the dev_base_lock for
iterating the device list. Doing that is not required, just the
rtnl is sufficient (and the rtnl is required for other reasons
outlined in commit "wext: fix get_wireless_stats locking").
This will fix http://bugzilla.kernel.org/show_bug.cgi?id=13344
and make things easier for drivers.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | net/wireless/wext.c | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/net/wireless/wext.c b/net/wireless/wext.c index d3bbef70cc7c..22378daceb94 100644 --- a/net/wireless/wext.c +++ b/net/wireless/wext.c | |||
@@ -636,8 +636,10 @@ static void wireless_seq_printf_stats(struct seq_file *seq, | |||
636 | /* | 636 | /* |
637 | * Print info for /proc/net/wireless (print all entries) | 637 | * Print info for /proc/net/wireless (print all entries) |
638 | */ | 638 | */ |
639 | static int wireless_seq_show(struct seq_file *seq, void *v) | 639 | static int wireless_dev_seq_show(struct seq_file *seq, void *v) |
640 | { | 640 | { |
641 | might_sleep(); | ||
642 | |||
641 | if (v == SEQ_START_TOKEN) | 643 | if (v == SEQ_START_TOKEN) |
642 | seq_printf(seq, "Inter-| sta-| Quality | Discarded " | 644 | seq_printf(seq, "Inter-| sta-| Quality | Discarded " |
643 | "packets | Missed | WE\n" | 645 | "packets | Missed | WE\n" |
@@ -651,21 +653,41 @@ static int wireless_seq_show(struct seq_file *seq, void *v) | |||
651 | 653 | ||
652 | static void *wireless_dev_seq_start(struct seq_file *seq, loff_t *pos) | 654 | static void *wireless_dev_seq_start(struct seq_file *seq, loff_t *pos) |
653 | { | 655 | { |
656 | struct net *net = seq_file_net(seq); | ||
657 | loff_t off; | ||
658 | struct net_device *dev; | ||
659 | |||
654 | rtnl_lock(); | 660 | rtnl_lock(); |
655 | return dev_seq_start(seq, pos); | 661 | if (!*pos) |
662 | return SEQ_START_TOKEN; | ||
663 | |||
664 | off = 1; | ||
665 | for_each_netdev(net, dev) | ||
666 | if (off++ == *pos) | ||
667 | return dev; | ||
668 | return NULL; | ||
669 | } | ||
670 | |||
671 | static void *wireless_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) | ||
672 | { | ||
673 | struct net *net = seq_file_net(seq); | ||
674 | |||
675 | ++*pos; | ||
676 | |||
677 | return v == SEQ_START_TOKEN ? | ||
678 | first_net_device(net) : next_net_device(v); | ||
656 | } | 679 | } |
657 | 680 | ||
658 | static void wireless_dev_seq_stop(struct seq_file *seq, void *v) | 681 | static void wireless_dev_seq_stop(struct seq_file *seq, void *v) |
659 | { | 682 | { |
660 | dev_seq_stop(seq, v); | ||
661 | rtnl_unlock(); | 683 | rtnl_unlock(); |
662 | } | 684 | } |
663 | 685 | ||
664 | static const struct seq_operations wireless_seq_ops = { | 686 | static const struct seq_operations wireless_seq_ops = { |
665 | .start = wireless_dev_seq_start, | 687 | .start = wireless_dev_seq_start, |
666 | .next = dev_seq_next, | 688 | .next = wireless_dev_seq_next, |
667 | .stop = wireless_dev_seq_stop, | 689 | .stop = wireless_dev_seq_stop, |
668 | .show = wireless_seq_show, | 690 | .show = wireless_dev_seq_show, |
669 | }; | 691 | }; |
670 | 692 | ||
671 | static int seq_open_wireless(struct inode *inode, struct file *file) | 693 | static int seq_open_wireless(struct inode *inode, struct file *file) |