]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/batman-adv/bat_sysfs.c
c14ab47fc5a43efdf1db59619737cebb04a73746
[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 struct bat_attribute {
32         struct attribute attr;
33         ssize_t (*show)(struct kobject *kobj, struct attribute *attr,
34                         char *buf);
35         ssize_t (*store)(struct kobject *kobj, struct attribute *attr,
36                          char *buf, size_t count);
37 };
38
39 #define BAT_ATTR(_name, _mode, _show, _store)   \
40 struct bat_attribute bat_attr_##_name = {       \
41         .attr = {.name = __stringify(_name),    \
42                  .mode = _mode },               \
43         .show   = _show,                        \
44         .store  = _store,                       \
45 };
46
47 #define BAT_BIN_ATTR(_name, _mode, _read, _write)       \
48 struct bin_attribute bat_attr_##_name = {               \
49         .attr = { .name = __stringify(_name),           \
50                   .mode = _mode, },                     \
51         .read = _read,                                  \
52         .write = _write,                                \
53 };
54
55 static ssize_t show_aggr_ogm(struct kobject *kobj, struct attribute *attr,
56                              char *buff)
57 {
58         struct device *dev = to_dev(kobj->parent);
59         struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
60         int aggr_status = atomic_read(&bat_priv->aggregation_enabled);
61
62         return sprintf(buff, "status: %s\ncommands: enable, disable, 0, 1 \n",
63                        aggr_status == 0 ? "disabled" : "enabled");
64 }
65
66 static ssize_t store_aggr_ogm(struct kobject *kobj, struct attribute *attr,
67                               char *buff, size_t count)
68 {
69         struct device *dev = to_dev(kobj->parent);
70         struct net_device *net_dev = to_net_dev(dev);
71         struct bat_priv *bat_priv = netdev_priv(net_dev);
72         int aggr_tmp = -1;
73
74         if (((count == 2) && (buff[0] == '1')) ||
75             (strncmp(buff, "enable", 6) == 0))
76                 aggr_tmp = 1;
77
78         if (((count == 2) && (buff[0] == '0')) ||
79             (strncmp(buff, "disable", 7) == 0))
80                 aggr_tmp = 0;
81
82         if (aggr_tmp < 0) {
83                 if (buff[count - 1] == '\n')
84                         buff[count - 1] = '\0';
85
86                 printk(KERN_INFO "batman-adv:Invalid parameter for 'aggregate OGM' setting on mesh %s received: %s\n",
87                        net_dev->name, buff);
88                 return -EINVAL;
89         }
90
91         if (atomic_read(&bat_priv->aggregation_enabled) == aggr_tmp)
92                 return count;
93
94         printk(KERN_INFO "batman-adv:Changing aggregation from: %s to: %s on mesh: %s\n",
95                atomic_read(&bat_priv->aggregation_enabled) == 1 ?
96                "enabled" : "disabled", aggr_tmp == 1 ? "enabled" : "disabled",
97                net_dev->name);
98
99         atomic_set(&bat_priv->aggregation_enabled, (unsigned)aggr_tmp);
100         return count;
101 }
102
103 static ssize_t show_vis_mode(struct kobject *kobj, struct attribute *attr,
104                              char *buff)
105 {
106         struct device *dev = to_dev(kobj->parent);
107         struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
108         int vis_mode = atomic_read(&bat_priv->vis_mode);
109
110         return sprintf(buff, "status: %s\ncommands: client, server, %d, %d \n",
111                        vis_mode == VIS_TYPE_CLIENT_UPDATE ?
112                                                         "client" : "server",
113                        VIS_TYPE_SERVER_SYNC, VIS_TYPE_CLIENT_UPDATE);
114 }
115
116 static ssize_t store_vis_mode(struct kobject *kobj, struct attribute *attr,
117                               char *buff, size_t count)
118 {
119         struct device *dev = to_dev(kobj->parent);
120         struct net_device *net_dev = to_net_dev(dev);
121         struct bat_priv *bat_priv = netdev_priv(net_dev);
122         unsigned long val;
123         int ret, vis_mode_tmp = -1;
124
125         ret = strict_strtoul(buff, 10, &val);
126
127         if (((count == 2) && (!ret) && (val == VIS_TYPE_CLIENT_UPDATE)) ||
128             (strncmp(buff, "client", 6) == 0))
129                 vis_mode_tmp = VIS_TYPE_CLIENT_UPDATE;
130
131         if (((count == 2) && (!ret) && (val == VIS_TYPE_SERVER_SYNC)) ||
132             (strncmp(buff, "server", 6) == 0))
133                 vis_mode_tmp = VIS_TYPE_SERVER_SYNC;
134
135         if (vis_mode_tmp < 0) {
136                 if (buff[count - 1] == '\n')
137                         buff[count - 1] = '\0';
138
139                 printk(KERN_INFO "batman-adv:Invalid parameter for 'vis mode' setting on mesh %s received: %s\n",
140                        net_dev->name, buff);
141                 return -EINVAL;
142         }
143
144         if (atomic_read(&bat_priv->vis_mode) == vis_mode_tmp)
145                 return count;
146
147         printk(KERN_INFO "batman-adv:Changing vis mode from: %s to: %s on mesh: %s\n",
148                atomic_read(&bat_priv->vis_mode) == VIS_TYPE_CLIENT_UPDATE ?
149                "client" : "server", vis_mode_tmp == VIS_TYPE_CLIENT_UPDATE ?
150                "client" : "server", net_dev->name);
151
152         atomic_set(&bat_priv->vis_mode, (unsigned)vis_mode_tmp);
153         return count;
154 }
155
156 static BAT_ATTR(aggregate_ogm, S_IRUGO | S_IWUSR,
157                 show_aggr_ogm, store_aggr_ogm);
158 static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode);
159
160 static struct bat_attribute *mesh_attrs[] = {
161         &bat_attr_aggregate_ogm,
162         &bat_attr_vis_mode,
163         NULL,
164 };
165
166 static ssize_t transtable_local_read(struct kobject *kobj,
167                                struct bin_attribute *bin_attr,
168                                char *buff, loff_t off, size_t count)
169 {
170         struct device *dev = to_dev(kobj->parent);
171         struct net_device *net_dev = to_net_dev(dev);
172
173         return hna_local_fill_buffer_text(net_dev, buff, count, off);
174 }
175
176 static ssize_t transtable_global_read(struct kobject *kobj,
177                                struct bin_attribute *bin_attr,
178                                char *buff, loff_t off, size_t count)
179 {
180         struct device *dev = to_dev(kobj->parent);
181         struct net_device *net_dev = to_net_dev(dev);
182
183         return hna_global_fill_buffer_text(net_dev, buff, count, off);
184 }
185
186 static ssize_t originators_read(struct kobject *kobj,
187                                struct bin_attribute *bin_attr,
188                                char *buff, loff_t off, size_t count)
189 {
190         struct device *dev = to_dev(kobj->parent);
191         struct net_device *net_dev = to_net_dev(dev);
192
193         return orig_fill_buffer_text(net_dev, buff, count, off);
194 }
195
196 static ssize_t vis_data_read(struct kobject *kobj,
197                              struct bin_attribute *bin_attr,
198                              char *buff, loff_t off, size_t count)
199 {
200         struct device *dev = to_dev(kobj->parent);
201         struct net_device *net_dev = to_net_dev(dev);
202
203         return vis_fill_buffer_text(net_dev, buff, count, off);
204 }
205
206 static BAT_BIN_ATTR(transtable_local, S_IRUGO, transtable_local_read, NULL);
207 static BAT_BIN_ATTR(transtable_global, S_IRUGO, transtable_global_read, NULL);
208 static BAT_BIN_ATTR(originators, S_IRUGO, originators_read, NULL);
209 static BAT_BIN_ATTR(vis_data, S_IRUGO, vis_data_read, NULL);
210
211 static struct bin_attribute *mesh_bin_attrs[] = {
212         &bat_attr_transtable_local,
213         &bat_attr_transtable_global,
214         &bat_attr_originators,
215         &bat_attr_vis_data,
216         NULL,
217 };
218
219 int sysfs_add_meshif(struct net_device *dev)
220 {
221         struct kobject *batif_kobject = &dev->dev.kobj;
222         struct bat_priv *bat_priv = netdev_priv(dev);
223         struct bat_attribute **bat_attr;
224         struct bin_attribute **bin_attr;
225         int err;
226
227         /* FIXME: should be done in the general mesh setup
228                   routine as soon as we have it */
229         atomic_set(&bat_priv->aggregation_enabled, 1);
230         atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE);
231
232         bat_priv->mesh_obj = kobject_create_and_add(SYSFS_IF_MESH_SUBDIR,
233                                                     batif_kobject);
234         if (!bat_priv->mesh_obj) {
235                 printk(KERN_ERR "batman-adv:Can't add sysfs directory: %s/%s\n",
236                        dev->name, SYSFS_IF_MESH_SUBDIR);
237                 goto out;
238         }
239
240         for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr) {
241                 err = sysfs_create_file(bat_priv->mesh_obj,
242                                         &((*bat_attr)->attr));
243                 if (err) {
244                         printk(KERN_ERR "batman-adv:Can't add sysfs file: %s/%s/%s\n",
245                                dev->name, SYSFS_IF_MESH_SUBDIR,
246                                ((*bat_attr)->attr).name);
247                         goto rem_attr;
248                 }
249         }
250
251         for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr) {
252                 err = sysfs_create_bin_file(bat_priv->mesh_obj, (*bin_attr));
253                 if (err) {
254                         printk(KERN_ERR "batman-adv:Can't add sysfs file: %s/%s/%s\n",
255                                dev->name, SYSFS_IF_MESH_SUBDIR,
256                                ((*bin_attr)->attr).name);
257                         goto rem_bin_attr;
258                 }
259         }
260
261         return 0;
262
263 rem_bin_attr:
264         for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr)
265                 sysfs_remove_bin_file(bat_priv->mesh_obj, (*bin_attr));
266 rem_attr:
267         for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr)
268                 sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
269
270         kobject_put(bat_priv->mesh_obj);
271         bat_priv->mesh_obj = NULL;
272 out:
273         return -ENOMEM;
274 }
275
276 void sysfs_del_meshif(struct net_device *dev)
277 {
278         struct bat_priv *bat_priv = netdev_priv(dev);
279         struct bat_attribute **bat_attr;
280         struct bin_attribute **bin_attr;
281
282         for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr)
283                 sysfs_remove_bin_file(bat_priv->mesh_obj, (*bin_attr));
284
285         for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr)
286                 sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
287
288         kobject_put(bat_priv->mesh_obj);
289         bat_priv->mesh_obj = NULL;
290 }