]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/batman-adv/bat_sysfs.c
Input: wacom - fix runtime PM related deadlock
[net-next-2.6.git] / drivers / staging / batman-adv / bat_sysfs.c
1 /*
2  * Copyright (C) 2010 B.A.T.M.A.N. contributors:
3  *
4  * Marek Lindner
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of version 2 of the GNU General Public
8  * License as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301, USA
19  *
20  */
21
22 #include "main.h"
23 #include "bat_sysfs.h"
24 #include "translation-table.h"
25 #include "originator.h"
26 #include "hard-interface.h"
27 #include "vis.h"
28
29 #define to_dev(obj)     container_of(obj, struct device, kobj)
30
31 #define BAT_ATTR(_name, _mode, _show, _store)   \
32 struct bat_attribute bat_attr_##_name = {       \
33         .attr = {.name = __stringify(_name),    \
34                  .mode = _mode },               \
35         .show   = _show,                        \
36         .store  = _store,                       \
37 };
38
39 static ssize_t show_aggr_ogms(struct kobject *kobj, struct attribute *attr,
40                              char *buff)
41 {
42         struct device *dev = to_dev(kobj->parent);
43         struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
44         int aggr_status = atomic_read(&bat_priv->aggregation_enabled);
45
46         return sprintf(buff, "%s\n",
47                        aggr_status == 0 ? "disabled" : "enabled");
48 }
49
50 static ssize_t store_aggr_ogms(struct kobject *kobj, struct attribute *attr,
51                               char *buff, size_t count)
52 {
53         struct device *dev = to_dev(kobj->parent);
54         struct net_device *net_dev = to_net_dev(dev);
55         struct bat_priv *bat_priv = netdev_priv(net_dev);
56         int aggr_tmp = -1;
57
58         if (((count == 2) && (buff[0] == '1')) ||
59             (strncmp(buff, "enable", 6) == 0))
60                 aggr_tmp = 1;
61
62         if (((count == 2) && (buff[0] == '0')) ||
63             (strncmp(buff, "disable", 7) == 0))
64                 aggr_tmp = 0;
65
66         if (aggr_tmp < 0) {
67                 if (buff[count - 1] == '\n')
68                         buff[count - 1] = '\0';
69
70                 bat_info(net_dev,
71                          "Invalid parameter for 'aggregate OGM' setting"
72                          "received: %s\n", buff);
73                 return -EINVAL;
74         }
75
76         if (atomic_read(&bat_priv->aggregation_enabled) == aggr_tmp)
77                 return count;
78
79         bat_info(net_dev, "Changing aggregation from: %s to: %s\n",
80                  atomic_read(&bat_priv->aggregation_enabled) == 1 ?
81                  "enabled" : "disabled", aggr_tmp == 1 ? "enabled" :
82                  "disabled");
83
84         atomic_set(&bat_priv->aggregation_enabled, (unsigned)aggr_tmp);
85         return count;
86 }
87
88 static ssize_t show_bond(struct kobject *kobj, struct attribute *attr,
89                              char *buff)
90 {
91         struct device *dev = to_dev(kobj->parent);
92         struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
93         int bond_status = atomic_read(&bat_priv->bonding_enabled);
94
95         return sprintf(buff, "%s\n",
96                        bond_status == 0 ? "disabled" : "enabled");
97 }
98
99 static ssize_t store_bond(struct kobject *kobj, struct attribute *attr,
100                           char *buff, size_t count)
101 {
102         struct device *dev = to_dev(kobj->parent);
103         struct net_device *net_dev = to_net_dev(dev);
104         struct bat_priv *bat_priv = netdev_priv(net_dev);
105         int bonding_enabled_tmp = -1;
106
107         if (((count == 2) && (buff[0] == '1')) ||
108             (strncmp(buff, "enable", 6) == 0))
109                 bonding_enabled_tmp = 1;
110
111         if (((count == 2) && (buff[0] == '0')) ||
112             (strncmp(buff, "disable", 7) == 0))
113                 bonding_enabled_tmp = 0;
114
115         if (bonding_enabled_tmp < 0) {
116                 if (buff[count - 1] == '\n')
117                         buff[count - 1] = '\0';
118
119                 bat_err(net_dev,
120                         "Invalid parameter for 'bonding' setting received: "
121                         "%s\n", buff);
122                 return -EINVAL;
123         }
124
125         if (atomic_read(&bat_priv->bonding_enabled) == bonding_enabled_tmp)
126                 return count;
127
128         bat_info(net_dev, "Changing bonding from: %s to: %s\n",
129                  atomic_read(&bat_priv->bonding_enabled) == 1 ?
130                  "enabled" : "disabled",
131                  bonding_enabled_tmp == 1 ? "enabled" : "disabled");
132
133         atomic_set(&bat_priv->bonding_enabled, (unsigned)bonding_enabled_tmp);
134         return count;
135 }
136
137 static ssize_t show_vis_mode(struct kobject *kobj, struct attribute *attr,
138                              char *buff)
139 {
140         struct device *dev = to_dev(kobj->parent);
141         struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
142         int vis_mode = atomic_read(&bat_priv->vis_mode);
143
144         return sprintf(buff, "%s\n",
145                        vis_mode == VIS_TYPE_CLIENT_UPDATE ?
146                                                         "client" : "server");
147 }
148
149 static ssize_t store_vis_mode(struct kobject *kobj, struct attribute *attr,
150                               char *buff, size_t count)
151 {
152         struct device *dev = to_dev(kobj->parent);
153         struct net_device *net_dev = to_net_dev(dev);
154         struct bat_priv *bat_priv = netdev_priv(net_dev);
155         unsigned long val;
156         int ret, vis_mode_tmp = -1;
157
158         ret = strict_strtoul(buff, 10, &val);
159
160         if (((count == 2) && (!ret) && (val == VIS_TYPE_CLIENT_UPDATE)) ||
161             (strncmp(buff, "client", 6) == 0) ||
162             (strncmp(buff, "off", 3) == 0))
163                 vis_mode_tmp = VIS_TYPE_CLIENT_UPDATE;
164
165         if (((count == 2) && (!ret) && (val == VIS_TYPE_SERVER_SYNC)) ||
166             (strncmp(buff, "server", 6) == 0))
167                 vis_mode_tmp = VIS_TYPE_SERVER_SYNC;
168
169         if (vis_mode_tmp < 0) {
170                 if (buff[count - 1] == '\n')
171                         buff[count - 1] = '\0';
172
173                 bat_info(net_dev,
174                          "Invalid parameter for 'vis mode' setting received: "
175                          "%s\n", buff);
176                 return -EINVAL;
177         }
178
179         if (atomic_read(&bat_priv->vis_mode) == vis_mode_tmp)
180                 return count;
181
182         bat_info(net_dev, "Changing vis mode from: %s to: %s\n",
183                  atomic_read(&bat_priv->vis_mode) == VIS_TYPE_CLIENT_UPDATE ?
184                  "client" : "server", vis_mode_tmp == VIS_TYPE_CLIENT_UPDATE ?
185                  "client" : "server");
186
187         atomic_set(&bat_priv->vis_mode, (unsigned)vis_mode_tmp);
188         return count;
189 }
190
191 static ssize_t show_orig_interval(struct kobject *kobj, struct attribute *attr,
192                                  char *buff)
193 {
194         struct device *dev = to_dev(kobj->parent);
195         struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
196
197         return sprintf(buff, "%i\n",
198                        atomic_read(&bat_priv->orig_interval));
199 }
200
201 static ssize_t store_orig_interval(struct kobject *kobj, struct attribute *attr,
202                                   char *buff, size_t count)
203 {
204         struct device *dev = to_dev(kobj->parent);
205         struct net_device *net_dev = to_net_dev(dev);
206         struct bat_priv *bat_priv = netdev_priv(net_dev);
207         unsigned long orig_interval_tmp;
208         int ret;
209
210         ret = strict_strtoul(buff, 10, &orig_interval_tmp);
211         if (ret) {
212                 bat_info(net_dev, "Invalid parameter for 'orig_interval' "
213                          "setting received: %s\n", buff);
214                 return -EINVAL;
215         }
216
217         if (orig_interval_tmp < JITTER * 2) {
218                 bat_info(net_dev, "New originator interval too small: %li "
219                          "(min: %i)\n", orig_interval_tmp, JITTER * 2);
220                 return -EINVAL;
221         }
222
223         if (atomic_read(&bat_priv->orig_interval) == orig_interval_tmp)
224                 return count;
225
226         bat_info(net_dev, "Changing originator interval from: %i to: %li\n",
227                  atomic_read(&bat_priv->orig_interval),
228                  orig_interval_tmp);
229
230         atomic_set(&bat_priv->orig_interval, orig_interval_tmp);
231         return count;
232 }
233
234 #ifdef CONFIG_BATMAN_ADV_DEBUG
235 static ssize_t show_log_level(struct kobject *kobj, struct attribute *attr,
236                              char *buff)
237 {
238         struct device *dev = to_dev(kobj->parent);
239         struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
240         int log_level = atomic_read(&bat_priv->log_level);
241
242         return sprintf(buff, "%d\n", log_level);
243 }
244
245 static ssize_t store_log_level(struct kobject *kobj, struct attribute *attr,
246                               char *buff, size_t count)
247 {
248         struct device *dev = to_dev(kobj->parent);
249         struct net_device *net_dev = to_net_dev(dev);
250         struct bat_priv *bat_priv = netdev_priv(net_dev);
251         unsigned long log_level_tmp;
252         int ret;
253
254         ret = strict_strtoul(buff, 10, &log_level_tmp);
255         if (ret) {
256                 bat_info(net_dev, "Invalid parameter for 'log_level' "
257                          "setting received: %s\n", buff);
258                 return -EINVAL;
259         }
260
261         if (log_level_tmp > 3) {
262                 bat_info(net_dev, "New log level too big: %li "
263                          "(max: %i)\n", log_level_tmp, 3);
264                 return -EINVAL;
265         }
266
267         if (atomic_read(&bat_priv->log_level) == log_level_tmp)
268                 return count;
269
270         atomic_set(&bat_priv->log_level, (unsigned)log_level_tmp);
271         return count;
272 }
273 #endif
274
275 static BAT_ATTR(aggregated_ogms, S_IRUGO | S_IWUSR,
276                 show_aggr_ogms, store_aggr_ogms);
277 static BAT_ATTR(bonding, S_IRUGO | S_IWUSR, show_bond, store_bond);
278 static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode);
279 static BAT_ATTR(orig_interval, S_IRUGO | S_IWUSR,
280                 show_orig_interval, store_orig_interval);
281 #ifdef CONFIG_BATMAN_ADV_DEBUG
282 static BAT_ATTR(log_level, S_IRUGO | S_IWUSR, show_log_level, store_log_level);
283 #endif
284
285 static struct bat_attribute *mesh_attrs[] = {
286         &bat_attr_aggregated_ogms,
287         &bat_attr_bonding,
288         &bat_attr_vis_mode,
289         &bat_attr_orig_interval,
290 #ifdef CONFIG_BATMAN_ADV_DEBUG
291         &bat_attr_log_level,
292 #endif
293         NULL,
294 };
295
296 int sysfs_add_meshif(struct net_device *dev)
297 {
298         struct kobject *batif_kobject = &dev->dev.kobj;
299         struct bat_priv *bat_priv = netdev_priv(dev);
300         struct bat_attribute **bat_attr;
301         int err;
302
303         /* FIXME: should be done in the general mesh setup
304                   routine as soon as we have it */
305         atomic_set(&bat_priv->aggregation_enabled, 1);
306         atomic_set(&bat_priv->bonding_enabled, 0);
307         atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE);
308         atomic_set(&bat_priv->orig_interval, 1000);
309         atomic_set(&bat_priv->log_level, 0);
310
311         bat_priv->primary_if = NULL;
312         bat_priv->num_ifaces = 0;
313
314         bat_priv->mesh_obj = kobject_create_and_add(SYSFS_IF_MESH_SUBDIR,
315                                                     batif_kobject);
316         if (!bat_priv->mesh_obj) {
317                 bat_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
318                         SYSFS_IF_MESH_SUBDIR);
319                 goto out;
320         }
321
322         for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr) {
323                 err = sysfs_create_file(bat_priv->mesh_obj,
324                                         &((*bat_attr)->attr));
325                 if (err) {
326                         bat_err(dev, "Can't add sysfs file: %s/%s/%s\n",
327                                 dev->name, SYSFS_IF_MESH_SUBDIR,
328                                 ((*bat_attr)->attr).name);
329                         goto rem_attr;
330                 }
331         }
332
333         return 0;
334
335 rem_attr:
336         for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr)
337                 sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
338
339         kobject_put(bat_priv->mesh_obj);
340         bat_priv->mesh_obj = NULL;
341 out:
342         return -ENOMEM;
343 }
344
345 void sysfs_del_meshif(struct net_device *dev)
346 {
347         struct bat_priv *bat_priv = netdev_priv(dev);
348         struct bat_attribute **bat_attr;
349
350         for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr)
351                 sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
352
353         kobject_put(bat_priv->mesh_obj);
354         bat_priv->mesh_obj = NULL;
355 }
356
357 static ssize_t show_mesh_iface(struct kobject *kobj, struct attribute *attr,
358                                char *buff)
359 {
360         struct device *dev = to_dev(kobj->parent);
361         struct net_device *net_dev = to_net_dev(dev);
362         struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
363
364         if (!batman_if)
365                 return 0;
366
367         return sprintf(buff, "%s\n",
368                        batman_if->if_status == IF_NOT_IN_USE ?
369                                                         "none" : "bat0");
370 }
371
372 static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr,
373                                 char *buff, size_t count)
374 {
375         struct device *dev = to_dev(kobj->parent);
376         struct net_device *net_dev = to_net_dev(dev);
377         struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
378         int status_tmp = -1;
379
380         if (!batman_if)
381                 return count;
382
383         if (strncmp(buff, "none", 4) == 0)
384                 status_tmp = IF_NOT_IN_USE;
385
386         if (strncmp(buff, "bat0", 4) == 0)
387                 status_tmp = IF_I_WANT_YOU;
388
389         if (status_tmp < 0) {
390                 if (buff[count - 1] == '\n')
391                         buff[count - 1] = '\0';
392
393                 pr_err("Invalid parameter for 'mesh_iface' setting received: "
394                        "%s\n", buff);
395                 return -EINVAL;
396         }
397
398         if ((batman_if->if_status == status_tmp) ||
399             ((status_tmp == IF_I_WANT_YOU) &&
400              (batman_if->if_status != IF_NOT_IN_USE)))
401                 return count;
402
403         if (status_tmp == IF_I_WANT_YOU)
404                 status_tmp = hardif_enable_interface(batman_if);
405         else
406                 hardif_disable_interface(batman_if);
407
408         return (status_tmp < 0 ? status_tmp : count);
409 }
410
411 static ssize_t show_iface_status(struct kobject *kobj, struct attribute *attr,
412                                  char *buff)
413 {
414         struct device *dev = to_dev(kobj->parent);
415         struct net_device *net_dev = to_net_dev(dev);
416         struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
417
418         if (!batman_if)
419                 return 0;
420
421         switch (batman_if->if_status) {
422         case IF_TO_BE_REMOVED:
423                 return sprintf(buff, "disabling\n");
424         case IF_INACTIVE:
425                 return sprintf(buff, "inactive\n");
426         case IF_ACTIVE:
427                 return sprintf(buff, "active\n");
428         case IF_TO_BE_ACTIVATED:
429                 return sprintf(buff, "enabling\n");
430         case IF_NOT_IN_USE:
431         default:
432                 return sprintf(buff, "not in use\n");
433         }
434 }
435
436 static BAT_ATTR(mesh_iface, S_IRUGO | S_IWUSR,
437                 show_mesh_iface, store_mesh_iface);
438 static BAT_ATTR(iface_status, S_IRUGO, show_iface_status, NULL);
439
440 static struct bat_attribute *batman_attrs[] = {
441         &bat_attr_mesh_iface,
442         &bat_attr_iface_status,
443         NULL,
444 };
445
446 int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev)
447 {
448         struct kobject *hardif_kobject = &dev->dev.kobj;
449         struct bat_attribute **bat_attr;
450         int err;
451
452         *hardif_obj = kobject_create_and_add(SYSFS_IF_BAT_SUBDIR,
453                                                     hardif_kobject);
454
455         if (!*hardif_obj) {
456                 bat_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
457                         SYSFS_IF_BAT_SUBDIR);
458                 goto out;
459         }
460
461         for (bat_attr = batman_attrs; *bat_attr; ++bat_attr) {
462                 err = sysfs_create_file(*hardif_obj, &((*bat_attr)->attr));
463                 if (err) {
464                         bat_err(dev, "Can't add sysfs file: %s/%s/%s\n",
465                                 dev->name, SYSFS_IF_BAT_SUBDIR,
466                                 ((*bat_attr)->attr).name);
467                         goto rem_attr;
468                 }
469         }
470
471         return 0;
472
473 rem_attr:
474         for (bat_attr = batman_attrs; *bat_attr; ++bat_attr)
475                 sysfs_remove_file(*hardif_obj, &((*bat_attr)->attr));
476 out:
477         return -ENOMEM;
478 }
479
480 void sysfs_del_hardif(struct kobject **hardif_obj)
481 {
482         kobject_put(*hardif_obj);
483         *hardif_obj = NULL;
484 }