Merge branch 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[pandora-kernel.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_frag(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 frag_status = atomic_read(&bat_priv->frag_enabled);
143
144         return sprintf(buff, "%s\n",
145                        frag_status == 0 ? "disabled" : "enabled");
146 }
147
148 static ssize_t store_frag(struct kobject *kobj, struct attribute *attr,
149                           char *buff, size_t count)
150 {
151         struct device *dev = to_dev(kobj->parent);
152         struct net_device *net_dev = to_net_dev(dev);
153         struct bat_priv *bat_priv = netdev_priv(net_dev);
154         int frag_enabled_tmp = -1;
155
156         if (((count == 2) && (buff[0] == '1')) ||
157             (strncmp(buff, "enable", 6) == 0))
158                 frag_enabled_tmp = 1;
159
160         if (((count == 2) && (buff[0] == '0')) ||
161             (strncmp(buff, "disable", 7) == 0))
162                 frag_enabled_tmp = 0;
163
164         if (frag_enabled_tmp < 0) {
165                 if (buff[count - 1] == '\n')
166                         buff[count - 1] = '\0';
167
168                 bat_err(net_dev,
169                         "Invalid parameter for 'fragmentation' setting on mesh"
170                         "received: %s\n", buff);
171                 return -EINVAL;
172         }
173
174         if (atomic_read(&bat_priv->frag_enabled) == frag_enabled_tmp)
175                 return count;
176
177         bat_info(net_dev, "Changing fragmentation from: %s to: %s\n",
178                  atomic_read(&bat_priv->frag_enabled) == 1 ?
179                  "enabled" : "disabled",
180                  frag_enabled_tmp == 1 ? "enabled" : "disabled");
181
182         atomic_set(&bat_priv->frag_enabled, (unsigned)frag_enabled_tmp);
183         update_min_mtu(net_dev);
184         return count;
185 }
186
187 static ssize_t show_vis_mode(struct kobject *kobj, struct attribute *attr,
188                              char *buff)
189 {
190         struct device *dev = to_dev(kobj->parent);
191         struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
192         int vis_mode = atomic_read(&bat_priv->vis_mode);
193
194         return sprintf(buff, "%s\n",
195                        vis_mode == VIS_TYPE_CLIENT_UPDATE ?
196                                                         "client" : "server");
197 }
198
199 static ssize_t store_vis_mode(struct kobject *kobj, struct attribute *attr,
200                               char *buff, size_t count)
201 {
202         struct device *dev = to_dev(kobj->parent);
203         struct net_device *net_dev = to_net_dev(dev);
204         struct bat_priv *bat_priv = netdev_priv(net_dev);
205         unsigned long val;
206         int ret, vis_mode_tmp = -1;
207
208         ret = strict_strtoul(buff, 10, &val);
209
210         if (((count == 2) && (!ret) && (val == VIS_TYPE_CLIENT_UPDATE)) ||
211             (strncmp(buff, "client", 6) == 0) ||
212             (strncmp(buff, "off", 3) == 0))
213                 vis_mode_tmp = VIS_TYPE_CLIENT_UPDATE;
214
215         if (((count == 2) && (!ret) && (val == VIS_TYPE_SERVER_SYNC)) ||
216             (strncmp(buff, "server", 6) == 0))
217                 vis_mode_tmp = VIS_TYPE_SERVER_SYNC;
218
219         if (vis_mode_tmp < 0) {
220                 if (buff[count - 1] == '\n')
221                         buff[count - 1] = '\0';
222
223                 bat_info(net_dev,
224                          "Invalid parameter for 'vis mode' setting received: "
225                          "%s\n", buff);
226                 return -EINVAL;
227         }
228
229         if (atomic_read(&bat_priv->vis_mode) == vis_mode_tmp)
230                 return count;
231
232         bat_info(net_dev, "Changing vis mode from: %s to: %s\n",
233                  atomic_read(&bat_priv->vis_mode) == VIS_TYPE_CLIENT_UPDATE ?
234                  "client" : "server", vis_mode_tmp == VIS_TYPE_CLIENT_UPDATE ?
235                  "client" : "server");
236
237         atomic_set(&bat_priv->vis_mode, (unsigned)vis_mode_tmp);
238         return count;
239 }
240
241 static ssize_t show_orig_interval(struct kobject *kobj, struct attribute *attr,
242                                  char *buff)
243 {
244         struct device *dev = to_dev(kobj->parent);
245         struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
246
247         return sprintf(buff, "%i\n",
248                        atomic_read(&bat_priv->orig_interval));
249 }
250
251 static ssize_t store_orig_interval(struct kobject *kobj, struct attribute *attr,
252                                   char *buff, size_t count)
253 {
254         struct device *dev = to_dev(kobj->parent);
255         struct net_device *net_dev = to_net_dev(dev);
256         struct bat_priv *bat_priv = netdev_priv(net_dev);
257         unsigned long orig_interval_tmp;
258         int ret;
259
260         ret = strict_strtoul(buff, 10, &orig_interval_tmp);
261         if (ret) {
262                 bat_info(net_dev, "Invalid parameter for 'orig_interval' "
263                          "setting received: %s\n", buff);
264                 return -EINVAL;
265         }
266
267         if (orig_interval_tmp < JITTER * 2) {
268                 bat_info(net_dev, "New originator interval too small: %li "
269                          "(min: %i)\n", orig_interval_tmp, JITTER * 2);
270                 return -EINVAL;
271         }
272
273         if (atomic_read(&bat_priv->orig_interval) == orig_interval_tmp)
274                 return count;
275
276         bat_info(net_dev, "Changing originator interval from: %i to: %li\n",
277                  atomic_read(&bat_priv->orig_interval),
278                  orig_interval_tmp);
279
280         atomic_set(&bat_priv->orig_interval, orig_interval_tmp);
281         return count;
282 }
283
284 #ifdef CONFIG_BATMAN_ADV_DEBUG
285 static ssize_t show_log_level(struct kobject *kobj, struct attribute *attr,
286                              char *buff)
287 {
288         struct device *dev = to_dev(kobj->parent);
289         struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
290         int log_level = atomic_read(&bat_priv->log_level);
291
292         return sprintf(buff, "%d\n", log_level);
293 }
294
295 static ssize_t store_log_level(struct kobject *kobj, struct attribute *attr,
296                               char *buff, size_t count)
297 {
298         struct device *dev = to_dev(kobj->parent);
299         struct net_device *net_dev = to_net_dev(dev);
300         struct bat_priv *bat_priv = netdev_priv(net_dev);
301         unsigned long log_level_tmp;
302         int ret;
303
304         ret = strict_strtoul(buff, 10, &log_level_tmp);
305         if (ret) {
306                 bat_info(net_dev, "Invalid parameter for 'log_level' "
307                          "setting received: %s\n", buff);
308                 return -EINVAL;
309         }
310
311         if (log_level_tmp > 3) {
312                 bat_info(net_dev, "New log level too big: %li "
313                          "(max: %i)\n", log_level_tmp, 3);
314                 return -EINVAL;
315         }
316
317         if (atomic_read(&bat_priv->log_level) == log_level_tmp)
318                 return count;
319
320         bat_info(net_dev, "Changing log level from: %i to: %li\n",
321                  atomic_read(&bat_priv->log_level),
322                  log_level_tmp);
323
324         atomic_set(&bat_priv->log_level, (unsigned)log_level_tmp);
325         return count;
326 }
327 #endif
328
329 static BAT_ATTR(aggregated_ogms, S_IRUGO | S_IWUSR,
330                 show_aggr_ogms, store_aggr_ogms);
331 static BAT_ATTR(bonding, S_IRUGO | S_IWUSR, show_bond, store_bond);
332 static BAT_ATTR(fragmentation, S_IRUGO | S_IWUSR, show_frag, store_frag);
333 static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode);
334 static BAT_ATTR(orig_interval, S_IRUGO | S_IWUSR,
335                 show_orig_interval, store_orig_interval);
336 #ifdef CONFIG_BATMAN_ADV_DEBUG
337 static BAT_ATTR(log_level, S_IRUGO | S_IWUSR, show_log_level, store_log_level);
338 #endif
339
340 static struct bat_attribute *mesh_attrs[] = {
341         &bat_attr_aggregated_ogms,
342         &bat_attr_bonding,
343         &bat_attr_fragmentation,
344         &bat_attr_vis_mode,
345         &bat_attr_orig_interval,
346 #ifdef CONFIG_BATMAN_ADV_DEBUG
347         &bat_attr_log_level,
348 #endif
349         NULL,
350 };
351
352 int sysfs_add_meshif(struct net_device *dev)
353 {
354         struct kobject *batif_kobject = &dev->dev.kobj;
355         struct bat_priv *bat_priv = netdev_priv(dev);
356         struct bat_attribute **bat_attr;
357         int err;
358
359         bat_priv->mesh_obj = kobject_create_and_add(SYSFS_IF_MESH_SUBDIR,
360                                                     batif_kobject);
361         if (!bat_priv->mesh_obj) {
362                 bat_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
363                         SYSFS_IF_MESH_SUBDIR);
364                 goto out;
365         }
366
367         for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr) {
368                 err = sysfs_create_file(bat_priv->mesh_obj,
369                                         &((*bat_attr)->attr));
370                 if (err) {
371                         bat_err(dev, "Can't add sysfs file: %s/%s/%s\n",
372                                 dev->name, SYSFS_IF_MESH_SUBDIR,
373                                 ((*bat_attr)->attr).name);
374                         goto rem_attr;
375                 }
376         }
377
378         return 0;
379
380 rem_attr:
381         for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr)
382                 sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
383
384         kobject_put(bat_priv->mesh_obj);
385         bat_priv->mesh_obj = NULL;
386 out:
387         return -ENOMEM;
388 }
389
390 void sysfs_del_meshif(struct net_device *dev)
391 {
392         struct bat_priv *bat_priv = netdev_priv(dev);
393         struct bat_attribute **bat_attr;
394
395         for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr)
396                 sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
397
398         kobject_put(bat_priv->mesh_obj);
399         bat_priv->mesh_obj = NULL;
400 }
401
402 static ssize_t show_mesh_iface(struct kobject *kobj, struct attribute *attr,
403                                char *buff)
404 {
405         struct device *dev = to_dev(kobj->parent);
406         struct net_device *net_dev = to_net_dev(dev);
407         struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
408         ssize_t length;
409
410         if (!batman_if)
411                 return 0;
412
413         length = sprintf(buff, "%s\n", batman_if->if_status == IF_NOT_IN_USE ?
414                          "none" : batman_if->soft_iface->name);
415
416         hardif_put(batman_if);
417
418         return length;
419 }
420
421 static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr,
422                                 char *buff, size_t count)
423 {
424         struct device *dev = to_dev(kobj->parent);
425         struct net_device *net_dev = to_net_dev(dev);
426         struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
427         int status_tmp = -1;
428         int ret;
429
430         if (!batman_if)
431                 return count;
432
433         if (buff[count - 1] == '\n')
434                 buff[count - 1] = '\0';
435
436         if (strlen(buff) >= IFNAMSIZ) {
437                 pr_err("Invalid parameter for 'mesh_iface' setting received: "
438                        "interface name too long '%s'\n", buff);
439                 hardif_put(batman_if);
440                 return -EINVAL;
441         }
442
443         if (strncmp(buff, "none", 4) == 0)
444                 status_tmp = IF_NOT_IN_USE;
445         else
446                 status_tmp = IF_I_WANT_YOU;
447
448         if ((batman_if->if_status == status_tmp) || ((batman_if->soft_iface) &&
449             (strncmp(batman_if->soft_iface->name, buff, IFNAMSIZ) == 0))) {
450                 hardif_put(batman_if);
451                 return count;
452         }
453
454         if (status_tmp == IF_NOT_IN_USE) {
455                 rtnl_lock();
456                 hardif_disable_interface(batman_if);
457                 rtnl_unlock();
458                 hardif_put(batman_if);
459                 return count;
460         }
461
462         /* if the interface already is in use */
463         if (batman_if->if_status != IF_NOT_IN_USE) {
464                 rtnl_lock();
465                 hardif_disable_interface(batman_if);
466                 rtnl_unlock();
467         }
468
469         ret = hardif_enable_interface(batman_if, buff);
470         hardif_put(batman_if);
471
472         return ret;
473 }
474
475 static ssize_t show_iface_status(struct kobject *kobj, struct attribute *attr,
476                                  char *buff)
477 {
478         struct device *dev = to_dev(kobj->parent);
479         struct net_device *net_dev = to_net_dev(dev);
480         struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
481         ssize_t length;
482
483         if (!batman_if)
484                 return 0;
485
486         switch (batman_if->if_status) {
487         case IF_TO_BE_REMOVED:
488                 length = sprintf(buff, "disabling\n");
489                 break;
490         case IF_INACTIVE:
491                 length = sprintf(buff, "inactive\n");
492                 break;
493         case IF_ACTIVE:
494                 length = sprintf(buff, "active\n");
495                 break;
496         case IF_TO_BE_ACTIVATED:
497                 length = sprintf(buff, "enabling\n");
498                 break;
499         case IF_NOT_IN_USE:
500         default:
501                 length = sprintf(buff, "not in use\n");
502                 break;
503         }
504
505         hardif_put(batman_if);
506
507         return length;
508 }
509
510 static BAT_ATTR(mesh_iface, S_IRUGO | S_IWUSR,
511                 show_mesh_iface, store_mesh_iface);
512 static BAT_ATTR(iface_status, S_IRUGO, show_iface_status, NULL);
513
514 static struct bat_attribute *batman_attrs[] = {
515         &bat_attr_mesh_iface,
516         &bat_attr_iface_status,
517         NULL,
518 };
519
520 int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev)
521 {
522         struct kobject *hardif_kobject = &dev->dev.kobj;
523         struct bat_attribute **bat_attr;
524         int err;
525
526         *hardif_obj = kobject_create_and_add(SYSFS_IF_BAT_SUBDIR,
527                                                     hardif_kobject);
528
529         if (!*hardif_obj) {
530                 bat_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
531                         SYSFS_IF_BAT_SUBDIR);
532                 goto out;
533         }
534
535         for (bat_attr = batman_attrs; *bat_attr; ++bat_attr) {
536                 err = sysfs_create_file(*hardif_obj, &((*bat_attr)->attr));
537                 if (err) {
538                         bat_err(dev, "Can't add sysfs file: %s/%s/%s\n",
539                                 dev->name, SYSFS_IF_BAT_SUBDIR,
540                                 ((*bat_attr)->attr).name);
541                         goto rem_attr;
542                 }
543         }
544
545         return 0;
546
547 rem_attr:
548         for (bat_attr = batman_attrs; *bat_attr; ++bat_attr)
549                 sysfs_remove_file(*hardif_obj, &((*bat_attr)->attr));
550 out:
551         return -ENOMEM;
552 }
553
554 void sysfs_del_hardif(struct kobject **hardif_obj)
555 {
556         kobject_put(*hardif_obj);
557         *hardif_obj = NULL;
558 }