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 | |
| 45 | read_lock(&dev_base_lock); |
| 46 | if (dev_isalive(dev)) { |
| 47 | wl_lock(lp, &flags); |
| 48 | |
| 49 | if ((ret = wl_get_tallies(lp, &tallies)) == 0) { |
| 50 | wl_unlock(lp, &flags); |
| 51 | ret = snprintf(buf, PAGE_SIZE, |
| 52 | "TxUnicastFrames: %u\n" |
| 53 | "TxMulticastFrames: %u\n" |
| 54 | "TxFragments: %u\n" |
| 55 | "TxUnicastOctets: %u\n" |
| 56 | "TxMulticastOctets: %u\n" |
| 57 | "TxDeferredTransmissions: %u\n" |
| 58 | "TxSingleRetryFrames: %u\n" |
| 59 | "TxMultipleRetryFrames: %u\n" |
| 60 | "TxRetryLimitExceeded: %u\n" |
| 61 | "TxDiscards: %u\n" |
| 62 | "RxUnicastFrames: %u\n" |
| 63 | "RxMulticastFrames: %u\n" |
| 64 | "RxFragments: %u\n" |
| 65 | "RxUnicastOctets: %u\n" |
| 66 | "RxMulticastOctets: %u\n" |
| 67 | "RxFCSErrors: %u\n" |
| 68 | "RxDiscardsNoBuffer: %u\n" |
| 69 | "TxDiscardsWrongSA: %u\n" |
| 70 | "RxWEPUndecryptable: %u\n" |
| 71 | "RxMsgInMsgFragments: %u\n" |
| 72 | "RxMsgInBadMsgFragments: %u\n" |
| 73 | "RxDiscardsWEPICVError: %u\n" |
| 74 | "RxDiscardsWEPExcluded: %u\n" |
| 75 | , |
| 76 | (unsigned int)tallies.TxUnicastFrames, |
| 77 | (unsigned int)tallies.TxMulticastFrames, |
| 78 | (unsigned int)tallies.TxFragments, |
| 79 | (unsigned int)tallies.TxUnicastOctets, |
| 80 | (unsigned int)tallies.TxMulticastOctets, |
| 81 | (unsigned int)tallies.TxDeferredTransmissions, |
| 82 | (unsigned int)tallies.TxSingleRetryFrames, |
| 83 | (unsigned int)tallies.TxMultipleRetryFrames, |
| 84 | (unsigned int)tallies.TxRetryLimitExceeded, |
| 85 | (unsigned int)tallies.TxDiscards, |
| 86 | (unsigned int)tallies.RxUnicastFrames, |
| 87 | (unsigned int)tallies.RxMulticastFrames, |
| 88 | (unsigned int)tallies.RxFragments, |
| 89 | (unsigned int)tallies.RxUnicastOctets, |
| 90 | (unsigned int)tallies.RxMulticastOctets, |
| 91 | (unsigned int)tallies.RxFCSErrors, |
| 92 | (unsigned int)tallies.RxDiscardsNoBuffer, |
| 93 | (unsigned int)tallies.TxDiscardsWrongSA, |
| 94 | (unsigned int)tallies.RxWEPUndecryptable, |
| 95 | (unsigned int)tallies.RxMsgInMsgFragments, |
| 96 | (unsigned int)tallies.RxMsgInBadMsgFragments, |
| 97 | (unsigned int)tallies.RxDiscardsWEPICVError, |
| 98 | (unsigned int)tallies.RxDiscardsWEPExcluded); |
| 99 | } else { |
| 100 | wl_unlock( lp, &flags ); |
| 101 | } |
| 102 | } |
| 103 | |
| 104 | read_unlock(&dev_base_lock); |
| 105 | return ret; |
| 106 | } |
| 107 | |
| 108 | static DEVICE_ATTR(tallies, S_IRUGO, show_tallies, NULL); |
| 109 | |
| 110 | static struct attribute *wlags_attrs[] = { |
| 111 | &dev_attr_tallies.attr, |
| 112 | NULL |
| 113 | }; |
| 114 | |
| 115 | static struct attribute_group wlags_group = { |
| 116 | .name = "wlags", |
| 117 | .attrs = wlags_attrs, |
| 118 | }; |
| 119 | |
| 120 | void register_wlags_sysfs(struct net_device *net) |
| 121 | { |
| 122 | struct device *dev = &(net->dev); |
| 123 | struct wl_private *lp = wl_priv(net); |
| 124 | |
| 125 | lp->sysfsCreated = sysfs_create_group(&dev->kobj, &wlags_group); |
| 126 | } |
| 127 | |
| 128 | void unregister_wlags_sysfs(struct net_device *net) |
| 129 | { |
| 130 | struct device *dev = &(net->dev); |
| 131 | struct wl_private *lp = wl_priv(net); |
| 132 | |
| 133 | if (lp->sysfsCreated) |
| 134 | sysfs_remove_group(&dev->kobj, &wlags_group); |
| 135 | } |