a1d8ca6ac93514ecbd0ffec158c98a9f71207fcc
[linux-2.6.git] / drivers / uwb / i1480 / i1480u-wlp / sysfs.c
1 /*
2  * WUSB Wire Adapter: WLP interface
3  * Sysfs interfaces
4  *
5  * Copyright (C) 2005-2006 Intel Corporation
6  * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License version
10  * 2 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20  * 02110-1301, USA.
21  *
22  *
23  * FIXME: docs
24  */
25
26 #include <linux/netdevice.h>
27 #include <linux/etherdevice.h>
28 #include <linux/uwb/debug.h>
29 #include <linux/device.h>
30 #include "i1480u-wlp.h"
31
32
33 /**
34  *
35  * @dev: Class device from the net_device; assumed refcnted.
36  *
37  * Yes, I don't lock--we assume it is refcounted and I am getting a
38  * single byte value that is kind of atomic to read.
39  */
40 ssize_t uwb_phy_rate_show(const struct wlp_options *options, char *buf)
41 {
42         return sprintf(buf, "%u\n",
43                        wlp_tx_hdr_phy_rate(&options->def_tx_hdr));
44 }
45 EXPORT_SYMBOL_GPL(uwb_phy_rate_show);
46
47
48 ssize_t uwb_phy_rate_store(struct wlp_options *options,
49                            const char *buf, size_t size)
50 {
51         ssize_t result;
52         unsigned rate;
53
54         result = sscanf(buf, "%u\n", &rate);
55         if (result != 1) {
56                 result = -EINVAL;
57                 goto out;
58         }
59         result = -EINVAL;
60         if (rate >= UWB_PHY_RATE_INVALID)
61                 goto out;
62         wlp_tx_hdr_set_phy_rate(&options->def_tx_hdr, rate);
63         result = 0;
64 out:
65         return result < 0 ? result : size;
66 }
67 EXPORT_SYMBOL_GPL(uwb_phy_rate_store);
68
69
70 ssize_t uwb_rts_cts_show(const struct wlp_options *options, char *buf)
71 {
72         return sprintf(buf, "%u\n",
73                        wlp_tx_hdr_rts_cts(&options->def_tx_hdr));
74 }
75 EXPORT_SYMBOL_GPL(uwb_rts_cts_show);
76
77
78 ssize_t uwb_rts_cts_store(struct wlp_options *options,
79                           const char *buf, size_t size)
80 {
81         ssize_t result;
82         unsigned value;
83
84         result = sscanf(buf, "%u\n", &value);
85         if (result != 1) {
86                 result = -EINVAL;
87                 goto out;
88         }
89         result = -EINVAL;
90         wlp_tx_hdr_set_rts_cts(&options->def_tx_hdr, !!value);
91         result = 0;
92 out:
93         return result < 0 ? result : size;
94 }
95 EXPORT_SYMBOL_GPL(uwb_rts_cts_store);
96
97
98 ssize_t uwb_ack_policy_show(const struct wlp_options *options, char *buf)
99 {
100         return sprintf(buf, "%u\n",
101                        wlp_tx_hdr_ack_policy(&options->def_tx_hdr));
102 }
103 EXPORT_SYMBOL_GPL(uwb_ack_policy_show);
104
105
106 ssize_t uwb_ack_policy_store(struct wlp_options *options,
107                              const char *buf, size_t size)
108 {
109         ssize_t result;
110         unsigned value;
111
112         result = sscanf(buf, "%u\n", &value);
113         if (result != 1 || value > UWB_ACK_B_REQ) {
114                 result = -EINVAL;
115                 goto out;
116         }
117         wlp_tx_hdr_set_ack_policy(&options->def_tx_hdr, value);
118         result = 0;
119 out:
120         return result < 0 ? result : size;
121 }
122 EXPORT_SYMBOL_GPL(uwb_ack_policy_store);
123
124
125 /**
126  * Show the PCA base priority.
127  *
128  * We can access without locking, as the value is (for now) orthogonal
129  * to other values.
130  */
131 ssize_t uwb_pca_base_priority_show(const struct wlp_options *options,
132                                    char *buf)
133 {
134         return sprintf(buf, "%u\n",
135                        options->pca_base_priority);
136 }
137 EXPORT_SYMBOL_GPL(uwb_pca_base_priority_show);
138
139
140 /**
141  * Set the PCA base priority.
142  *
143  * We can access without locking, as the value is (for now) orthogonal
144  * to other values.
145  */
146 ssize_t uwb_pca_base_priority_store(struct wlp_options *options,
147                                     const char *buf, size_t size)
148 {
149         ssize_t result = -EINVAL;
150         u8 pca_base_priority;
151
152         result = sscanf(buf, "%hhu\n", &pca_base_priority);
153         if (result != 1) {
154                 result = -EINVAL;
155                 goto out;
156         }
157         result = -EINVAL;
158         if (pca_base_priority >= 8)
159                 goto out;
160         options->pca_base_priority = pca_base_priority;
161         /* Update TX header if we are currently using PCA. */
162         if (result >= 0 && (wlp_tx_hdr_delivery_id_type(&options->def_tx_hdr) & WLP_DRP) == 0)
163                 wlp_tx_hdr_set_delivery_id_type(&options->def_tx_hdr, options->pca_base_priority);
164         result = 0;
165 out:
166         return result < 0 ? result : size;
167 }
168 EXPORT_SYMBOL_GPL(uwb_pca_base_priority_store);
169
170 /**
171  * Show current inflight values
172  *
173  * Will print the current MAX and THRESHOLD values for the basic flow
174  * control. In addition it will report how many times the TX queue needed
175  * to be restarted since the last time this query was made.
176  */
177 static ssize_t wlp_tx_inflight_show(struct i1480u_tx_inflight *inflight,
178                                     char *buf)
179 {
180         ssize_t result;
181         unsigned long sec_elapsed = (jiffies - inflight->restart_ts)/HZ;
182         unsigned long restart_count = atomic_read(&inflight->restart_count);
183
184         result = scnprintf(buf, PAGE_SIZE, "%lu %lu %d %lu %lu %lu\n"
185                            "#read: threshold max inflight_count restarts "
186                            "seconds restarts/sec\n"
187                            "#write: threshold max\n",
188                            inflight->threshold, inflight->max,
189                            atomic_read(&inflight->count),
190                            restart_count, sec_elapsed,
191                            sec_elapsed == 0 ? 0 : restart_count/sec_elapsed);
192         inflight->restart_ts = jiffies;
193         atomic_set(&inflight->restart_count, 0);
194         return result;
195 }
196
197 static
198 ssize_t wlp_tx_inflight_store(struct i1480u_tx_inflight *inflight,
199                                 const char *buf, size_t size)
200 {
201         unsigned long in_threshold, in_max;
202         ssize_t result;
203         result = sscanf(buf, "%lu %lu", &in_threshold, &in_max);
204         if (result != 2)
205                 return -EINVAL;
206         if (in_max <= in_threshold)
207                 return -EINVAL;
208         inflight->max = in_max;
209         inflight->threshold = in_threshold;
210         return size;
211 }
212 /*
213  * Glue (or function adaptors) for accesing info on sysfs
214  *
215  * [we need this indirection because the PCI driver does almost the
216  * same]
217  *
218  * Linux 2.6.21 changed how 'struct netdevice' does attributes (from
219  * having a 'struct class_dev' to having a 'struct device'). That is
220  * quite of a pain.
221  *
222  * So we try to abstract that here. i1480u_SHOW() and i1480u_STORE()
223  * create adaptors for extracting the 'struct i1480u' from a 'struct
224  * dev' and calling a function for doing a sysfs operation (as we have
225  * them factorized already). i1480u_ATTR creates the attribute file
226  * (CLASS_DEVICE_ATTR or DEVICE_ATTR) and i1480u_ATTR_NAME produces a
227  * class_device_attr_NAME or device_attr_NAME (for group registration).
228  */
229 #include <linux/version.h>
230
231 #define i1480u_SHOW(name, fn, param)                            \
232 static ssize_t i1480u_show_##name(struct device *dev,           \
233                                   struct device_attribute *attr,\
234                                   char *buf)                    \
235 {                                                               \
236         struct i1480u *i1480u = netdev_priv(to_net_dev(dev));   \
237         return fn(&i1480u->param, buf);                         \
238 }
239
240 #define i1480u_STORE(name, fn, param)                           \
241 static ssize_t i1480u_store_##name(struct device *dev,          \
242                                    struct device_attribute *attr,\
243                                    const char *buf, size_t size)\
244 {                                                               \
245         struct i1480u *i1480u = netdev_priv(to_net_dev(dev));   \
246         return fn(&i1480u->param, buf, size);                   \
247 }
248
249 #define i1480u_ATTR(name, perm) static DEVICE_ATTR(name, perm,  \
250                                              i1480u_show_##name,\
251                                              i1480u_store_##name)
252
253 #define i1480u_ATTR_SHOW(name) static DEVICE_ATTR(name,         \
254                                         S_IRUGO,                \
255                                         i1480u_show_##name, NULL)
256
257 #define i1480u_ATTR_NAME(a) (dev_attr_##a)
258
259
260 /*
261  * Sysfs adaptors
262  */
263 i1480u_SHOW(uwb_phy_rate, uwb_phy_rate_show, options);
264 i1480u_STORE(uwb_phy_rate, uwb_phy_rate_store, options);
265 i1480u_ATTR(uwb_phy_rate, S_IRUGO | S_IWUSR);
266
267 i1480u_SHOW(uwb_rts_cts, uwb_rts_cts_show, options);
268 i1480u_STORE(uwb_rts_cts, uwb_rts_cts_store, options);
269 i1480u_ATTR(uwb_rts_cts, S_IRUGO | S_IWUSR);
270
271 i1480u_SHOW(uwb_ack_policy, uwb_ack_policy_show, options);
272 i1480u_STORE(uwb_ack_policy, uwb_ack_policy_store, options);
273 i1480u_ATTR(uwb_ack_policy, S_IRUGO | S_IWUSR);
274
275 i1480u_SHOW(uwb_pca_base_priority, uwb_pca_base_priority_show, options);
276 i1480u_STORE(uwb_pca_base_priority, uwb_pca_base_priority_store, options);
277 i1480u_ATTR(uwb_pca_base_priority, S_IRUGO | S_IWUSR);
278
279 i1480u_SHOW(wlp_eda, wlp_eda_show, wlp);
280 i1480u_STORE(wlp_eda, wlp_eda_store, wlp);
281 i1480u_ATTR(wlp_eda, S_IRUGO | S_IWUSR);
282
283 i1480u_SHOW(wlp_uuid, wlp_uuid_show, wlp);
284 i1480u_STORE(wlp_uuid, wlp_uuid_store, wlp);
285 i1480u_ATTR(wlp_uuid, S_IRUGO | S_IWUSR);
286
287 i1480u_SHOW(wlp_dev_name, wlp_dev_name_show, wlp);
288 i1480u_STORE(wlp_dev_name, wlp_dev_name_store, wlp);
289 i1480u_ATTR(wlp_dev_name, S_IRUGO | S_IWUSR);
290
291 i1480u_SHOW(wlp_dev_manufacturer, wlp_dev_manufacturer_show, wlp);
292 i1480u_STORE(wlp_dev_manufacturer, wlp_dev_manufacturer_store, wlp);
293 i1480u_ATTR(wlp_dev_manufacturer, S_IRUGO | S_IWUSR);
294
295 i1480u_SHOW(wlp_dev_model_name, wlp_dev_model_name_show, wlp);
296 i1480u_STORE(wlp_dev_model_name, wlp_dev_model_name_store, wlp);
297 i1480u_ATTR(wlp_dev_model_name, S_IRUGO | S_IWUSR);
298
299 i1480u_SHOW(wlp_dev_model_nr, wlp_dev_model_nr_show, wlp);
300 i1480u_STORE(wlp_dev_model_nr, wlp_dev_model_nr_store, wlp);
301 i1480u_ATTR(wlp_dev_model_nr, S_IRUGO | S_IWUSR);
302
303 i1480u_SHOW(wlp_dev_serial, wlp_dev_serial_show, wlp);
304 i1480u_STORE(wlp_dev_serial, wlp_dev_serial_store, wlp);
305 i1480u_ATTR(wlp_dev_serial, S_IRUGO | S_IWUSR);
306
307 i1480u_SHOW(wlp_dev_prim_category, wlp_dev_prim_category_show, wlp);
308 i1480u_STORE(wlp_dev_prim_category, wlp_dev_prim_category_store, wlp);
309 i1480u_ATTR(wlp_dev_prim_category, S_IRUGO | S_IWUSR);
310
311 i1480u_SHOW(wlp_dev_prim_OUI, wlp_dev_prim_OUI_show, wlp);
312 i1480u_STORE(wlp_dev_prim_OUI, wlp_dev_prim_OUI_store, wlp);
313 i1480u_ATTR(wlp_dev_prim_OUI, S_IRUGO | S_IWUSR);
314
315 i1480u_SHOW(wlp_dev_prim_OUI_sub, wlp_dev_prim_OUI_sub_show, wlp);
316 i1480u_STORE(wlp_dev_prim_OUI_sub, wlp_dev_prim_OUI_sub_store, wlp);
317 i1480u_ATTR(wlp_dev_prim_OUI_sub, S_IRUGO | S_IWUSR);
318
319 i1480u_SHOW(wlp_dev_prim_subcat, wlp_dev_prim_subcat_show, wlp);
320 i1480u_STORE(wlp_dev_prim_subcat, wlp_dev_prim_subcat_store, wlp);
321 i1480u_ATTR(wlp_dev_prim_subcat, S_IRUGO | S_IWUSR);
322
323 i1480u_SHOW(wlp_neighborhood, wlp_neighborhood_show, wlp);
324 i1480u_ATTR_SHOW(wlp_neighborhood);
325
326 i1480u_SHOW(wss_activate, wlp_wss_activate_show, wlp.wss);
327 i1480u_STORE(wss_activate, wlp_wss_activate_store, wlp.wss);
328 i1480u_ATTR(wss_activate, S_IRUGO | S_IWUSR);
329
330 /*
331  * Show the (min, max, avg) Line Quality Estimate (LQE, in dB) as over
332  * the last 256 received WLP frames (ECMA-368 13.3).
333  *
334  * [the -7dB that have to be substracted from the LQI to make the LQE
335  * are already taken into account].
336  */
337 i1480u_SHOW(wlp_lqe, stats_show, lqe_stats);
338 i1480u_STORE(wlp_lqe, stats_store, lqe_stats);
339 i1480u_ATTR(wlp_lqe, S_IRUGO | S_IWUSR);
340
341 /*
342  * Show the Receive Signal Strength Indicator averaged over all the
343  * received WLP frames (ECMA-368 13.3). Still is not clear what
344  * this value is, but is kind of a percentage of the signal strength
345  * at the antenna.
346  */
347 i1480u_SHOW(wlp_rssi, stats_show, rssi_stats);
348 i1480u_STORE(wlp_rssi, stats_store, rssi_stats);
349 i1480u_ATTR(wlp_rssi, S_IRUGO | S_IWUSR);
350
351 /**
352  * We maintain a basic flow control counter. "count" how many TX URBs are
353  * outstanding. Only allow "max"
354  * TX URBs to be outstanding. If this value is reached the queue will be
355  * stopped. The queue will be restarted when there are
356  * "threshold" URBs outstanding.
357  */
358 i1480u_SHOW(wlp_tx_inflight, wlp_tx_inflight_show, tx_inflight);
359 i1480u_STORE(wlp_tx_inflight, wlp_tx_inflight_store, tx_inflight);
360 i1480u_ATTR(wlp_tx_inflight, S_IRUGO | S_IWUSR);
361
362 static struct attribute *i1480u_attrs[] = {
363         &i1480u_ATTR_NAME(uwb_phy_rate).attr,
364         &i1480u_ATTR_NAME(uwb_rts_cts).attr,
365         &i1480u_ATTR_NAME(uwb_ack_policy).attr,
366         &i1480u_ATTR_NAME(uwb_pca_base_priority).attr,
367         &i1480u_ATTR_NAME(wlp_lqe).attr,
368         &i1480u_ATTR_NAME(wlp_rssi).attr,
369         &i1480u_ATTR_NAME(wlp_eda).attr,
370         &i1480u_ATTR_NAME(wlp_uuid).attr,
371         &i1480u_ATTR_NAME(wlp_dev_name).attr,
372         &i1480u_ATTR_NAME(wlp_dev_manufacturer).attr,
373         &i1480u_ATTR_NAME(wlp_dev_model_name).attr,
374         &i1480u_ATTR_NAME(wlp_dev_model_nr).attr,
375         &i1480u_ATTR_NAME(wlp_dev_serial).attr,
376         &i1480u_ATTR_NAME(wlp_dev_prim_category).attr,
377         &i1480u_ATTR_NAME(wlp_dev_prim_OUI).attr,
378         &i1480u_ATTR_NAME(wlp_dev_prim_OUI_sub).attr,
379         &i1480u_ATTR_NAME(wlp_dev_prim_subcat).attr,
380         &i1480u_ATTR_NAME(wlp_neighborhood).attr,
381         &i1480u_ATTR_NAME(wss_activate).attr,
382         &i1480u_ATTR_NAME(wlp_tx_inflight).attr,
383         NULL,
384 };
385
386 static struct attribute_group i1480u_attr_group = {
387         .name = NULL,   /* we want them in the same directory */
388         .attrs = i1480u_attrs,
389 };
390
391 int i1480u_sysfs_setup(struct i1480u *i1480u)
392 {
393         int result;
394         struct device *dev = &i1480u->usb_iface->dev;
395         result = sysfs_create_group(&i1480u->net_dev->dev.kobj,
396                                     &i1480u_attr_group);
397         if (result < 0)
398                 dev_err(dev, "cannot initialize sysfs attributes: %d\n",
399                         result);
400         return result;
401 }
402
403
404 void i1480u_sysfs_release(struct i1480u *i1480u)
405 {
406         sysfs_remove_group(&i1480u->net_dev->dev.kobj,
407                            &i1480u_attr_group);
408 }