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 25static 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 */ 36static 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 ret = wl_get_tallies(lp, &tallies); 50 if (ret == 0) { 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 105 read_unlock(&dev_base_lock); 106 return ret; 107} 108 109static DEVICE_ATTR(tallies, S_IRUGO, show_tallies, NULL); 110 111static struct attribute *wlags_attrs[] = { 112 &dev_attr_tallies.attr, 113 NULL 114}; 115 116static struct attribute_group wlags_group = { 117 .name = "wlags", 118 .attrs = wlags_attrs, 119}; 120 121void register_wlags_sysfs(struct net_device *net) 122{ 123 struct device *dev = &(net->dev); 124 struct wl_private *lp = wl_priv(net); 125 126 lp->sysfsCreated = sysfs_create_group(&dev->kobj, &wlags_group); 127} 128 129void unregister_wlags_sysfs(struct net_device *net) 130{ 131 struct device *dev = &(net->dev); 132 struct wl_private *lp = wl_priv(net); 133 134 if (lp->sysfsCreated) 135 sysfs_remove_group(&dev->kobj, &wlags_group); 136} 137