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 
dev_isalive(const struct net_device * dev)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  */
show_tallies(struct device * d,struct device_attribute * attr,char * buf)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     rcu_read_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     rcu_read_unlock();
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 
register_wlags_sysfs(struct net_device * net)121 void register_wlags_sysfs(struct net_device *net)
122 {
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;
129 }
130 
unregister_wlags_sysfs(struct net_device * net)131 void unregister_wlags_sysfs(struct net_device *net)
132 {
133 	struct device *dev = &(net->dev);
134 	struct wl_private *lp = wl_priv(net);
135 
136 	if (lp->sysfsCreated)
137 		sysfs_remove_group(&dev->kobj, &wlags_group);
138 }
139