2 * WUSB Wire Adapter: WLP interface
5 * Copyright (C) 2005-2006 Intel Corporation
6 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
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.
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.
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
26 #include <linux/netdevice.h>
27 #include <linux/etherdevice.h>
28 #include <linux/device.h>
30 #include "i1480u-wlp.h"
35 * @dev: Class device from the net_device; assumed refcnted.
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.
40 ssize_t
uwb_phy_rate_show(const struct wlp_options
*options
, char *buf
)
42 return sprintf(buf
, "%u\n",
43 wlp_tx_hdr_phy_rate(&options
->def_tx_hdr
));
45 EXPORT_SYMBOL_GPL(uwb_phy_rate_show
);
48 ssize_t
uwb_phy_rate_store(struct wlp_options
*options
,
49 const char *buf
, size_t size
)
54 result
= sscanf(buf
, "%u\n", &rate
);
60 if (rate
>= UWB_PHY_RATE_INVALID
)
62 wlp_tx_hdr_set_phy_rate(&options
->def_tx_hdr
, rate
);
65 return result
< 0 ? result
: size
;
67 EXPORT_SYMBOL_GPL(uwb_phy_rate_store
);
70 ssize_t
uwb_rts_cts_show(const struct wlp_options
*options
, char *buf
)
72 return sprintf(buf
, "%u\n",
73 wlp_tx_hdr_rts_cts(&options
->def_tx_hdr
));
75 EXPORT_SYMBOL_GPL(uwb_rts_cts_show
);
78 ssize_t
uwb_rts_cts_store(struct wlp_options
*options
,
79 const char *buf
, size_t size
)
84 result
= sscanf(buf
, "%u\n", &value
);
90 wlp_tx_hdr_set_rts_cts(&options
->def_tx_hdr
, !!value
);
93 return result
< 0 ? result
: size
;
95 EXPORT_SYMBOL_GPL(uwb_rts_cts_store
);
98 ssize_t
uwb_ack_policy_show(const struct wlp_options
*options
, char *buf
)
100 return sprintf(buf
, "%u\n",
101 wlp_tx_hdr_ack_policy(&options
->def_tx_hdr
));
103 EXPORT_SYMBOL_GPL(uwb_ack_policy_show
);
106 ssize_t
uwb_ack_policy_store(struct wlp_options
*options
,
107 const char *buf
, size_t size
)
112 result
= sscanf(buf
, "%u\n", &value
);
113 if (result
!= 1 || value
> UWB_ACK_B_REQ
) {
117 wlp_tx_hdr_set_ack_policy(&options
->def_tx_hdr
, value
);
120 return result
< 0 ? result
: size
;
122 EXPORT_SYMBOL_GPL(uwb_ack_policy_store
);
126 * Show the PCA base priority.
128 * We can access without locking, as the value is (for now) orthogonal
131 ssize_t
uwb_pca_base_priority_show(const struct wlp_options
*options
,
134 return sprintf(buf
, "%u\n",
135 options
->pca_base_priority
);
137 EXPORT_SYMBOL_GPL(uwb_pca_base_priority_show
);
141 * Set the PCA base priority.
143 * We can access without locking, as the value is (for now) orthogonal
146 ssize_t
uwb_pca_base_priority_store(struct wlp_options
*options
,
147 const char *buf
, size_t size
)
149 ssize_t result
= -EINVAL
;
150 u8 pca_base_priority
;
152 result
= sscanf(buf
, "%hhu\n", &pca_base_priority
);
158 if (pca_base_priority
>= 8)
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
);
166 return result
< 0 ? result
: size
;
168 EXPORT_SYMBOL_GPL(uwb_pca_base_priority_store
);
171 * Show current inflight values
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.
177 static ssize_t
wlp_tx_inflight_show(struct i1480u_tx_inflight
*inflight
,
181 unsigned long sec_elapsed
= (jiffies
- inflight
->restart_ts
)/HZ
;
182 unsigned long restart_count
= atomic_read(&inflight
->restart_count
);
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);
198 ssize_t
wlp_tx_inflight_store(struct i1480u_tx_inflight
*inflight
,
199 const char *buf
, size_t size
)
201 unsigned long in_threshold
, in_max
;
203 result
= sscanf(buf
, "%lu %lu", &in_threshold
, &in_max
);
206 if (in_max
<= in_threshold
)
208 inflight
->max
= in_max
;
209 inflight
->threshold
= in_threshold
;
213 * Glue (or function adaptors) for accesing info on sysfs
215 * [we need this indirection because the PCI driver does almost the
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
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).
230 #define i1480u_SHOW(name, fn, param) \
231 static ssize_t i1480u_show_##name(struct device *dev, \
232 struct device_attribute *attr,\
235 struct i1480u *i1480u = netdev_priv(to_net_dev(dev)); \
236 return fn(&i1480u->param, buf); \
239 #define i1480u_STORE(name, fn, param) \
240 static ssize_t i1480u_store_##name(struct device *dev, \
241 struct device_attribute *attr,\
242 const char *buf, size_t size)\
244 struct i1480u *i1480u = netdev_priv(to_net_dev(dev)); \
245 return fn(&i1480u->param, buf, size); \
248 #define i1480u_ATTR(name, perm) static DEVICE_ATTR(name, perm, \
252 #define i1480u_ATTR_SHOW(name) static DEVICE_ATTR(name, \
254 i1480u_show_##name, NULL)
256 #define i1480u_ATTR_NAME(a) (dev_attr_##a)
262 i1480u_SHOW(uwb_phy_rate
, uwb_phy_rate_show
, options
);
263 i1480u_STORE(uwb_phy_rate
, uwb_phy_rate_store
, options
);
264 i1480u_ATTR(uwb_phy_rate
, S_IRUGO
| S_IWUSR
);
266 i1480u_SHOW(uwb_rts_cts
, uwb_rts_cts_show
, options
);
267 i1480u_STORE(uwb_rts_cts
, uwb_rts_cts_store
, options
);
268 i1480u_ATTR(uwb_rts_cts
, S_IRUGO
| S_IWUSR
);
270 i1480u_SHOW(uwb_ack_policy
, uwb_ack_policy_show
, options
);
271 i1480u_STORE(uwb_ack_policy
, uwb_ack_policy_store
, options
);
272 i1480u_ATTR(uwb_ack_policy
, S_IRUGO
| S_IWUSR
);
274 i1480u_SHOW(uwb_pca_base_priority
, uwb_pca_base_priority_show
, options
);
275 i1480u_STORE(uwb_pca_base_priority
, uwb_pca_base_priority_store
, options
);
276 i1480u_ATTR(uwb_pca_base_priority
, S_IRUGO
| S_IWUSR
);
278 i1480u_SHOW(wlp_eda
, wlp_eda_show
, wlp
);
279 i1480u_STORE(wlp_eda
, wlp_eda_store
, wlp
);
280 i1480u_ATTR(wlp_eda
, S_IRUGO
| S_IWUSR
);
282 i1480u_SHOW(wlp_uuid
, wlp_uuid_show
, wlp
);
283 i1480u_STORE(wlp_uuid
, wlp_uuid_store
, wlp
);
284 i1480u_ATTR(wlp_uuid
, S_IRUGO
| S_IWUSR
);
286 i1480u_SHOW(wlp_dev_name
, wlp_dev_name_show
, wlp
);
287 i1480u_STORE(wlp_dev_name
, wlp_dev_name_store
, wlp
);
288 i1480u_ATTR(wlp_dev_name
, S_IRUGO
| S_IWUSR
);
290 i1480u_SHOW(wlp_dev_manufacturer
, wlp_dev_manufacturer_show
, wlp
);
291 i1480u_STORE(wlp_dev_manufacturer
, wlp_dev_manufacturer_store
, wlp
);
292 i1480u_ATTR(wlp_dev_manufacturer
, S_IRUGO
| S_IWUSR
);
294 i1480u_SHOW(wlp_dev_model_name
, wlp_dev_model_name_show
, wlp
);
295 i1480u_STORE(wlp_dev_model_name
, wlp_dev_model_name_store
, wlp
);
296 i1480u_ATTR(wlp_dev_model_name
, S_IRUGO
| S_IWUSR
);
298 i1480u_SHOW(wlp_dev_model_nr
, wlp_dev_model_nr_show
, wlp
);
299 i1480u_STORE(wlp_dev_model_nr
, wlp_dev_model_nr_store
, wlp
);
300 i1480u_ATTR(wlp_dev_model_nr
, S_IRUGO
| S_IWUSR
);
302 i1480u_SHOW(wlp_dev_serial
, wlp_dev_serial_show
, wlp
);
303 i1480u_STORE(wlp_dev_serial
, wlp_dev_serial_store
, wlp
);
304 i1480u_ATTR(wlp_dev_serial
, S_IRUGO
| S_IWUSR
);
306 i1480u_SHOW(wlp_dev_prim_category
, wlp_dev_prim_category_show
, wlp
);
307 i1480u_STORE(wlp_dev_prim_category
, wlp_dev_prim_category_store
, wlp
);
308 i1480u_ATTR(wlp_dev_prim_category
, S_IRUGO
| S_IWUSR
);
310 i1480u_SHOW(wlp_dev_prim_OUI
, wlp_dev_prim_OUI_show
, wlp
);
311 i1480u_STORE(wlp_dev_prim_OUI
, wlp_dev_prim_OUI_store
, wlp
);
312 i1480u_ATTR(wlp_dev_prim_OUI
, S_IRUGO
| S_IWUSR
);
314 i1480u_SHOW(wlp_dev_prim_OUI_sub
, wlp_dev_prim_OUI_sub_show
, wlp
);
315 i1480u_STORE(wlp_dev_prim_OUI_sub
, wlp_dev_prim_OUI_sub_store
, wlp
);
316 i1480u_ATTR(wlp_dev_prim_OUI_sub
, S_IRUGO
| S_IWUSR
);
318 i1480u_SHOW(wlp_dev_prim_subcat
, wlp_dev_prim_subcat_show
, wlp
);
319 i1480u_STORE(wlp_dev_prim_subcat
, wlp_dev_prim_subcat_store
, wlp
);
320 i1480u_ATTR(wlp_dev_prim_subcat
, S_IRUGO
| S_IWUSR
);
322 i1480u_SHOW(wlp_neighborhood
, wlp_neighborhood_show
, wlp
);
323 i1480u_ATTR_SHOW(wlp_neighborhood
);
325 i1480u_SHOW(wss_activate
, wlp_wss_activate_show
, wlp
.wss
);
326 i1480u_STORE(wss_activate
, wlp_wss_activate_store
, wlp
.wss
);
327 i1480u_ATTR(wss_activate
, S_IRUGO
| S_IWUSR
);
330 * Show the (min, max, avg) Line Quality Estimate (LQE, in dB) as over
331 * the last 256 received WLP frames (ECMA-368 13.3).
333 * [the -7dB that have to be substracted from the LQI to make the LQE
334 * are already taken into account].
336 i1480u_SHOW(wlp_lqe
, stats_show
, lqe_stats
);
337 i1480u_STORE(wlp_lqe
, stats_store
, lqe_stats
);
338 i1480u_ATTR(wlp_lqe
, S_IRUGO
| S_IWUSR
);
341 * Show the Receive Signal Strength Indicator averaged over all the
342 * received WLP frames (ECMA-368 13.3). Still is not clear what
343 * this value is, but is kind of a percentage of the signal strength
346 i1480u_SHOW(wlp_rssi
, stats_show
, rssi_stats
);
347 i1480u_STORE(wlp_rssi
, stats_store
, rssi_stats
);
348 i1480u_ATTR(wlp_rssi
, S_IRUGO
| S_IWUSR
);
351 * We maintain a basic flow control counter. "count" how many TX URBs are
352 * outstanding. Only allow "max"
353 * TX URBs to be outstanding. If this value is reached the queue will be
354 * stopped. The queue will be restarted when there are
355 * "threshold" URBs outstanding.
357 i1480u_SHOW(wlp_tx_inflight
, wlp_tx_inflight_show
, tx_inflight
);
358 i1480u_STORE(wlp_tx_inflight
, wlp_tx_inflight_store
, tx_inflight
);
359 i1480u_ATTR(wlp_tx_inflight
, S_IRUGO
| S_IWUSR
);
361 static struct attribute
*i1480u_attrs
[] = {
362 &i1480u_ATTR_NAME(uwb_phy_rate
).attr
,
363 &i1480u_ATTR_NAME(uwb_rts_cts
).attr
,
364 &i1480u_ATTR_NAME(uwb_ack_policy
).attr
,
365 &i1480u_ATTR_NAME(uwb_pca_base_priority
).attr
,
366 &i1480u_ATTR_NAME(wlp_lqe
).attr
,
367 &i1480u_ATTR_NAME(wlp_rssi
).attr
,
368 &i1480u_ATTR_NAME(wlp_eda
).attr
,
369 &i1480u_ATTR_NAME(wlp_uuid
).attr
,
370 &i1480u_ATTR_NAME(wlp_dev_name
).attr
,
371 &i1480u_ATTR_NAME(wlp_dev_manufacturer
).attr
,
372 &i1480u_ATTR_NAME(wlp_dev_model_name
).attr
,
373 &i1480u_ATTR_NAME(wlp_dev_model_nr
).attr
,
374 &i1480u_ATTR_NAME(wlp_dev_serial
).attr
,
375 &i1480u_ATTR_NAME(wlp_dev_prim_category
).attr
,
376 &i1480u_ATTR_NAME(wlp_dev_prim_OUI
).attr
,
377 &i1480u_ATTR_NAME(wlp_dev_prim_OUI_sub
).attr
,
378 &i1480u_ATTR_NAME(wlp_dev_prim_subcat
).attr
,
379 &i1480u_ATTR_NAME(wlp_neighborhood
).attr
,
380 &i1480u_ATTR_NAME(wss_activate
).attr
,
381 &i1480u_ATTR_NAME(wlp_tx_inflight
).attr
,
385 static struct attribute_group i1480u_attr_group
= {
386 .name
= NULL
, /* we want them in the same directory */
387 .attrs
= i1480u_attrs
,
390 int i1480u_sysfs_setup(struct i1480u
*i1480u
)
393 struct device
*dev
= &i1480u
->usb_iface
->dev
;
394 result
= sysfs_create_group(&i1480u
->net_dev
->dev
.kobj
,
397 dev_err(dev
, "cannot initialize sysfs attributes: %d\n",
403 void i1480u_sysfs_release(struct i1480u
*i1480u
)
405 sysfs_remove_group(&i1480u
->net_dev
->dev
.kobj
,