d49addeb0adc940aa33d68e4c0197408584112c1
[firefly-linux-kernel-4.4.55.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         bat_info(net_dev, "Changing log level from: %i to: %li\n",
271                  atomic_read(&bat_priv->log_level),
272                  log_level_tmp);
273
274         atomic_set(&bat_priv->log_level, (unsigned)log_level_tmp);
275         return count;
276 }
277 #endif
278
279 static BAT_ATTR(aggregated_ogms, S_IRUGO | S_IWUSR,
280                 show_aggr_ogms, store_aggr_ogms);
281 static BAT_ATTR(bonding, S_IRUGO | S_IWUSR, show_bond, store_bond);
282 static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode);
283 static BAT_ATTR(orig_interval, S_IRUGO | S_IWUSR,
284                 show_orig_interval, store_orig_interval);
285 #ifdef CONFIG_BATMAN_ADV_DEBUG
286 static BAT_ATTR(log_level, S_IRUGO | S_IWUSR, show_log_level, store_log_level);
287 #endif
288
289 static struct bat_attribute *mesh_attrs[] = {
290         &bat_attr_aggregated_ogms,
291         &bat_attr_bonding,
292         &bat_attr_vis_mode,
293         &bat_attr_orig_interval,
294 #ifdef CONFIG_BATMAN_ADV_DEBUG
295         &bat_attr_log_level,
296 #endif
297         NULL,
298 };
299
300 int sysfs_add_meshif(struct net_device *dev)
301 {
302         struct kobject *batif_kobject = &dev->dev.kobj;
303         struct bat_priv *bat_priv = netdev_priv(dev);
304         struct bat_attribute **bat_attr;
305         int err;
306
307         /* FIXME: should be done in the general mesh setup
308                   routine as soon as we have it */
309         atomic_set(&bat_priv->aggregation_enabled, 1);
310         atomic_set(&bat_priv->bonding_enabled, 0);
311         atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE);
312         atomic_set(&bat_priv->orig_interval, 1000);
313         atomic_set(&bat_priv->log_level, 0);
314         atomic_set(&bat_priv->bcast_queue_left, BCAST_QUEUE_LEN);
315         atomic_set(&bat_priv->batman_queue_left, BATMAN_QUEUE_LEN);
316
317         bat_priv->primary_if = NULL;
318         bat_priv->num_ifaces = 0;
319
320         bat_priv->mesh_obj = kobject_create_and_add(SYSFS_IF_MESH_SUBDIR,
321                                                     batif_kobject);
322         if (!bat_priv->mesh_obj) {
323                 bat_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
324                         SYSFS_IF_MESH_SUBDIR);
325                 goto out;
326         }
327
328         for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr) {
329                 err = sysfs_create_file(bat_priv->mesh_obj,
330                                         &((*bat_attr)->attr));
331                 if (err) {
332                         bat_err(dev, "Can't add sysfs file: %s/%s/%s\n",
333                                 dev->name, SYSFS_IF_MESH_SUBDIR,
334                                 ((*bat_attr)->attr).name);
335                         goto rem_attr;
336                 }
337         }
338
339         return 0;
340
341 rem_attr:
342         for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr)
343                 sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
344
345         kobject_put(bat_priv->mesh_obj);
346         bat_priv->mesh_obj = NULL;
347 out:
348         return -ENOMEM;
349 }
350
351 void sysfs_del_meshif(struct net_device *dev)
352 {
353         struct bat_priv *bat_priv = netdev_priv(dev);
354         struct bat_attribute **bat_attr;
355
356         for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr)
357                 sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
358
359         kobject_put(bat_priv->mesh_obj);
360         bat_priv->mesh_obj = NULL;
361 }
362
363 static ssize_t show_mesh_iface(struct kobject *kobj, struct attribute *attr,
364                                char *buff)
365 {
366         struct device *dev = to_dev(kobj->parent);
367         struct net_device *net_dev = to_net_dev(dev);
368         struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
369
370         if (!batman_if)
371                 return 0;
372
373         return sprintf(buff, "%s\n",
374                        batman_if->if_status == IF_NOT_IN_USE ?
375                                                         "none" : "bat0");
376 }
377
378 static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr,
379                                 char *buff, size_t count)
380 {
381         struct device *dev = to_dev(kobj->parent);
382         struct net_device *net_dev = to_net_dev(dev);
383         struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
384         int status_tmp = -1;
385
386         if (!batman_if)
387                 return count;
388
389         if (strncmp(buff, "none", 4) == 0)
390                 status_tmp = IF_NOT_IN_USE;
391
392         if (strncmp(buff, "bat0", 4) == 0)
393                 status_tmp = IF_I_WANT_YOU;
394
395         if (status_tmp < 0) {
396                 if (buff[count - 1] == '\n')
397                         buff[count - 1] = '\0';
398
399                 pr_err("Invalid parameter for 'mesh_iface' setting received: "
400                        "%s\n", buff);
401                 return -EINVAL;
402         }
403
404         if ((batman_if->if_status == status_tmp) ||
405             ((status_tmp == IF_I_WANT_YOU) &&
406              (batman_if->if_status != IF_NOT_IN_USE)))
407                 return count;
408
409         if (status_tmp == IF_I_WANT_YOU)
410                 status_tmp = hardif_enable_interface(batman_if);
411         else
412                 hardif_disable_interface(batman_if);
413
414         return (status_tmp < 0 ? status_tmp : count);
415 }
416
417 static ssize_t show_iface_status(struct kobject *kobj, struct attribute *attr,
418                                  char *buff)
419 {
420         struct device *dev = to_dev(kobj->parent);
421         struct net_device *net_dev = to_net_dev(dev);
422         struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
423
424         if (!batman_if)
425                 return 0;
426
427         switch (batman_if->if_status) {
428         case IF_TO_BE_REMOVED:
429                 return sprintf(buff, "disabling\n");
430         case IF_INACTIVE:
431                 return sprintf(buff, "inactive\n");
432         case IF_ACTIVE:
433                 return sprintf(buff, "active\n");
434         case IF_TO_BE_ACTIVATED:
435                 return sprintf(buff, "enabling\n");
436         case IF_NOT_IN_USE:
437         default:
438                 return sprintf(buff, "not in use\n");
439         }
440 }
441
442 static BAT_ATTR(mesh_iface, S_IRUGO | S_IWUSR,
443                 show_mesh_iface, store_mesh_iface);
444 static BAT_ATTR(iface_status, S_IRUGO, show_iface_status, NULL);
445
446 static struct bat_attribute *batman_attrs[] = {
447         &bat_attr_mesh_iface,
448         &bat_attr_iface_status,
449         NULL,
450 };
451
452 int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev)
453 {
454         struct kobject *hardif_kobject = &dev->dev.kobj;
455         struct bat_attribute **bat_attr;
456         int err;
457
458         *hardif_obj = kobject_create_and_add(SYSFS_IF_BAT_SUBDIR,
459                                                     hardif_kobject);
460
461         if (!*hardif_obj) {
462                 bat_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
463                         SYSFS_IF_BAT_SUBDIR);
464                 goto out;
465         }
466
467         for (bat_attr = batman_attrs; *bat_attr; ++bat_attr) {
468                 err = sysfs_create_file(*hardif_obj, &((*bat_attr)->attr));
469                 if (err) {
470                         bat_err(dev, "Can't add sysfs file: %s/%s/%s\n",
471                                 dev->name, SYSFS_IF_BAT_SUBDIR,
472                                 ((*bat_attr)->attr).name);
473                         goto rem_attr;
474                 }
475         }
476
477         return 0;
478
479 rem_attr:
480         for (bat_attr = batman_attrs; *bat_attr; ++bat_attr)
481                 sysfs_remove_file(*hardif_obj, &((*bat_attr)->attr));
482 out:
483         return -ENOMEM;
484 }
485
486 void sysfs_del_hardif(struct kobject **hardif_obj)
487 {
488         kobject_put(*hardif_obj);
489         *hardif_obj = NULL;
490 }