diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-05-19 17:19:36 +0200 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-05-22 14:05:59 -0400 |
commit | 87057825824973f29cf2f37cff1e549170b2d7e6 (patch) | |
tree | dbbb7596aeea401a1e9c9379d0948889dbde8884 /net | |
parent | 9cef873798dfcdc10ff40b02abf1de935ceeba85 (diff) | |
download | linux-3.10-87057825824973f29cf2f37cff1e549170b2d7e6.tar.gz linux-3.10-87057825824973f29cf2f37cff1e549170b2d7e6.tar.bz2 linux-3.10-87057825824973f29cf2f37cff1e549170b2d7e6.zip |
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>
Diffstat (limited to 'net')
-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 d3bbef70cc7..22378daceb9 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, /* * Print info for /proc/net/wireless (print all entries) */ -static int wireless_seq_show(struct seq_file *seq, void *v) +static int wireless_dev_seq_show(struct seq_file *seq, void *v) { + might_sleep(); + if (v == SEQ_START_TOKEN) seq_printf(seq, "Inter-| sta-| Quality | Discarded " "packets | Missed | WE\n" @@ -651,21 +653,41 @@ static int wireless_seq_show(struct seq_file *seq, void *v) static void *wireless_dev_seq_start(struct seq_file *seq, loff_t *pos) { + struct net *net = seq_file_net(seq); + loff_t off; + struct net_device *dev; + rtnl_lock(); - return dev_seq_start(seq, pos); + if (!*pos) + return SEQ_START_TOKEN; + + off = 1; + for_each_netdev(net, dev) + if (off++ == *pos) + return dev; + return NULL; +} + +static void *wireless_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct net *net = seq_file_net(seq); + + ++*pos; + + return v == SEQ_START_TOKEN ? + first_net_device(net) : next_net_device(v); } static void wireless_dev_seq_stop(struct seq_file *seq, void *v) { - dev_seq_stop(seq, v); rtnl_unlock(); } static const struct seq_operations wireless_seq_ops = { .start = wireless_dev_seq_start, - .next = dev_seq_next, + .next = wireless_dev_seq_next, .stop = wireless_dev_seq_stop, - .show = wireless_seq_show, + .show = wireless_dev_seq_show, }; static int seq_open_wireless(struct inode *inode, struct file *file) |