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