Henk de Groot | 68c0bdf | 2009-09-27 11:12:52 +0200 | [diff] [blame] | 1 | /* |
| 2 | * ex: sw=4 |
| 3 | */ |
| 4 | |
| 5 | #include <linux/kernel.h> |
| 6 | #include <linux/netdevice.h> |
| 7 | #include <linux/if_arp.h> |
| 8 | #include <net/sock.h> |
| 9 | #include <linux/rtnetlink.h> |
| 10 | #include <linux/wireless.h> |
| 11 | #include <net/iw_handler.h> |
| 12 | #include <linux/sysfs.h> |
| 13 | |
| 14 | #include <debug.h> |
| 15 | #include <hcf.h> |
| 16 | #include <hcfdef.h> |
| 17 | |
| 18 | #include <wl_if.h> |
| 19 | #include <wl_internal.h> |
| 20 | #include <wl_util.h> |
| 21 | #include <wl_main.h> |
| 22 | #include <wl_wext.h> |
| 23 | #include <wl_priv.h> |
| 24 | |
| 25 | static inline int dev_isalive(const struct net_device *dev) |
| 26 | { |
| 27 | return dev->reg_state == NETREG_REGISTERED; |
| 28 | } |
| 29 | |
| 30 | /* |
| 31 | * empirically even if tallies are defined as 32 bits entities, only |
| 32 | * high 16 bits are relevant; low half is always zero. It means tallies |
| 33 | * are pretty much useless for traffic counting but at least give overview |
| 34 | * about where error come from |
| 35 | */ |
| 36 | static ssize_t show_tallies(struct device *d, struct device_attribute *attr, |
| 37 | char *buf) |
| 38 | { |
| 39 | struct net_device *dev = to_net_dev(d); |
| 40 | struct wl_private *lp = wl_priv(dev); |
| 41 | unsigned long flags; |
| 42 | CFG_HERMES_TALLIES_STRCT tallies; |
| 43 | ssize_t ret = -EINVAL; |
| 44 | |
Eric Dumazet | 8892384 | 2010-10-29 15:19:27 +0200 | [diff] [blame] | 45 | rcu_read_lock(); |
Henk de Groot | 68c0bdf | 2009-09-27 11:12:52 +0200 | [diff] [blame] | 46 | if (dev_isalive(dev)) { |
| 47 | wl_lock(lp, &flags); |
| 48 | |
Joe Perches | 491dbc8 | 2010-03-24 22:17:07 -0700 | [diff] [blame] | 49 | ret = wl_get_tallies(lp, &tallies); |
| 50 | if (ret == 0) { |
Henk de Groot | 68c0bdf | 2009-09-27 11:12:52 +0200 | [diff] [blame] | 51 | wl_unlock(lp, &flags); |
| 52 | ret = snprintf(buf, PAGE_SIZE, |
| 53 | "TxUnicastFrames: %u\n" |
| 54 | "TxMulticastFrames: %u\n" |
| 55 | "TxFragments: %u\n" |
| 56 | "TxUnicastOctets: %u\n" |
| 57 | "TxMulticastOctets: %u\n" |
| 58 | "TxDeferredTransmissions: %u\n" |
| 59 | "TxSingleRetryFrames: %u\n" |
| 60 | "TxMultipleRetryFrames: %u\n" |
| 61 | "TxRetryLimitExceeded: %u\n" |
| 62 | "TxDiscards: %u\n" |
| 63 | "RxUnicastFrames: %u\n" |
| 64 | "RxMulticastFrames: %u\n" |
| 65 | "RxFragments: %u\n" |
| 66 | "RxUnicastOctets: %u\n" |
| 67 | "RxMulticastOctets: %u\n" |
| 68 | "RxFCSErrors: %u\n" |
| 69 | "RxDiscardsNoBuffer: %u\n" |
| 70 | "TxDiscardsWrongSA: %u\n" |
| 71 | "RxWEPUndecryptable: %u\n" |
| 72 | "RxMsgInMsgFragments: %u\n" |
| 73 | "RxMsgInBadMsgFragments: %u\n" |
| 74 | "RxDiscardsWEPICVError: %u\n" |
| 75 | "RxDiscardsWEPExcluded: %u\n" |
| 76 | , |
| 77 | (unsigned int)tallies.TxUnicastFrames, |
| 78 | (unsigned int)tallies.TxMulticastFrames, |
| 79 | (unsigned int)tallies.TxFragments, |
| 80 | (unsigned int)tallies.TxUnicastOctets, |
| 81 | (unsigned int)tallies.TxMulticastOctets, |
| 82 | (unsigned int)tallies.TxDeferredTransmissions, |
| 83 | (unsigned int)tallies.TxSingleRetryFrames, |
| 84 | (unsigned int)tallies.TxMultipleRetryFrames, |
| 85 | (unsigned int)tallies.TxRetryLimitExceeded, |
| 86 | (unsigned int)tallies.TxDiscards, |
| 87 | (unsigned int)tallies.RxUnicastFrames, |
| 88 | (unsigned int)tallies.RxMulticastFrames, |
| 89 | (unsigned int)tallies.RxFragments, |
| 90 | (unsigned int)tallies.RxUnicastOctets, |
| 91 | (unsigned int)tallies.RxMulticastOctets, |
| 92 | (unsigned int)tallies.RxFCSErrors, |
| 93 | (unsigned int)tallies.RxDiscardsNoBuffer, |
| 94 | (unsigned int)tallies.TxDiscardsWrongSA, |
| 95 | (unsigned int)tallies.RxWEPUndecryptable, |
| 96 | (unsigned int)tallies.RxMsgInMsgFragments, |
| 97 | (unsigned int)tallies.RxMsgInBadMsgFragments, |
| 98 | (unsigned int)tallies.RxDiscardsWEPICVError, |
| 99 | (unsigned int)tallies.RxDiscardsWEPExcluded); |
| 100 | } else { |
| 101 | wl_unlock( lp, &flags ); |
| 102 | } |
| 103 | } |
| 104 | |
Eric Dumazet | 8892384 | 2010-10-29 15:19:27 +0200 | [diff] [blame] | 105 | rcu_read_unlock(); |
Henk de Groot | 68c0bdf | 2009-09-27 11:12:52 +0200 | [diff] [blame] | 106 | return ret; |
| 107 | } |
| 108 | |
| 109 | static DEVICE_ATTR(tallies, S_IRUGO, show_tallies, NULL); |
| 110 | |
| 111 | static struct attribute *wlags_attrs[] = { |
| 112 | &dev_attr_tallies.attr, |
| 113 | NULL |
| 114 | }; |
| 115 | |
| 116 | static struct attribute_group wlags_group = { |
| 117 | .name = "wlags", |
| 118 | .attrs = wlags_attrs, |
| 119 | }; |
| 120 | |
| 121 | void register_wlags_sysfs(struct net_device *net) |
| 122 | { |
David Kilroy | 1ca6167 | 2011-10-09 12:11:31 +0100 | [diff] [blame] | 123 | struct device *dev = &(net->dev); |
| 124 | struct wl_private *lp = wl_priv(net); |
| 125 | int err; |
| 126 | err = sysfs_create_group(&dev->kobj, &wlags_group); |
| 127 | if (!err) |
| 128 | lp->sysfsCreated = true; |
Henk de Groot | 68c0bdf | 2009-09-27 11:12:52 +0200 | [diff] [blame] | 129 | } |
| 130 | |
| 131 | void unregister_wlags_sysfs(struct net_device *net) |
| 132 | { |
David Kilroy | 1ca6167 | 2011-10-09 12:11:31 +0100 | [diff] [blame] | 133 | struct device *dev = &(net->dev); |
| 134 | struct wl_private *lp = wl_priv(net); |
Henk de Groot | 68c0bdf | 2009-09-27 11:12:52 +0200 | [diff] [blame] | 135 | |
David Kilroy | 1ca6167 | 2011-10-09 12:11:31 +0100 | [diff] [blame] | 136 | if (lp->sysfsCreated) |
| 137 | sysfs_remove_group(&dev->kobj, &wlags_group); |
Henk de Groot | 68c0bdf | 2009-09-27 11:12:52 +0200 | [diff] [blame] | 138 | } |