swconfig: cleanup of kernel drivers and interface
[openwrt.git] / target / linux / generic / files / drivers / net / phy / swconfig.c
1 /*
2  * swconfig.c: Switch configuration API
3  *
4  * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  */
16
17 #include <linux/types.h>
18 #include <linux/module.h>
19 #include <linux/init.h>
20 #include <linux/list.h>
21 #include <linux/if.h>
22 #include <linux/if_ether.h>
23 #include <linux/capability.h>
24 #include <linux/skbuff.h>
25 #include <linux/switch.h>
26
27 //#define DEBUG 1
28 #ifdef DEBUG
29 #define DPRINTF(format, ...) printk("%s: " format, __func__, ##__VA_ARGS__)
30 #else
31 #define DPRINTF(...) do {} while(0)
32 #endif
33
34 MODULE_AUTHOR("Felix Fietkau <nbd@openwrt.org>");
35 MODULE_LICENSE("GPL");
36
37 static int swdev_id = 0;
38 static struct list_head swdevs;
39 static spinlock_t swdevs_lock = SPIN_LOCK_UNLOCKED;
40 struct swconfig_callback;
41
42 struct swconfig_callback
43 {
44         struct sk_buff *msg;
45         struct genlmsghdr *hdr;
46         struct genl_info *info;
47         int cmd;
48
49         /* callback for filling in the message data */
50         int (*fill)(struct swconfig_callback *cb, void *arg);
51
52         /* callback for closing the message before sending it */
53         int (*close)(struct swconfig_callback *cb, void *arg);
54
55         struct nlattr *nest[4];
56         int args[4];
57 };
58
59 /* defaults */
60
61 static int
62 swconfig_get_vlan_ports(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
63 {
64         int ret;
65         if (val->port_vlan >= dev->vlans)
66                 return -EINVAL;
67
68         if (!dev->ops->get_vlan_ports)
69                 return -EOPNOTSUPP;
70
71         ret = dev->ops->get_vlan_ports(dev, val);
72         return ret;
73 }
74
75 static int
76 swconfig_set_vlan_ports(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
77 {
78         struct switch_port *ports = val->value.ports;
79         const struct switch_dev_ops *ops = dev->ops;
80         int i;
81
82         if (val->port_vlan >= dev->vlans)
83                 return -EINVAL;
84
85         /* validate ports */
86         if (val->len > dev->ports)
87                 return -EINVAL;
88
89         if (!ops->set_vlan_ports)
90                 return -EOPNOTSUPP;
91
92         for (i = 0; i < val->len; i++) {
93                 if (ports[i].id >= dev->ports)
94                         return -EINVAL;
95
96                 if (ops->set_port_pvid &&
97                     !(ports[i].flags & (1 << SWITCH_PORT_FLAG_TAGGED)))
98                         ops->set_port_pvid(dev, ports[i].id, val->port_vlan);
99         }
100
101         return ops->set_vlan_ports(dev, val);
102 }
103
104 static int
105 swconfig_set_pvid(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
106 {
107         if (val->port_vlan >= dev->ports)
108                 return -EINVAL;
109
110         if (!dev->ops->set_port_pvid)
111                 return -EOPNOTSUPP;
112
113         return dev->ops->set_port_pvid(dev, val->port_vlan, val->value.i);
114 }
115
116 static int
117 swconfig_get_pvid(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
118 {
119         if (val->port_vlan >= dev->ports)
120                 return -EINVAL;
121
122         if (!dev->ops->get_port_pvid)
123                 return -EOPNOTSUPP;
124
125         return dev->ops->get_port_pvid(dev, val->port_vlan, &val->value.i);
126 }
127
128 static int
129 swconfig_apply_config(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
130 {
131         /* don't complain if not supported by the switch driver */
132         if (!dev->ops->apply_config)
133                 return 0;
134
135         return dev->ops->apply_config(dev);
136 }
137
138 static int
139 swconfig_reset_switch(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
140 {
141         /* don't complain if not supported by the switch driver */
142         if (!dev->ops->reset_switch)
143                 return 0;
144
145         return dev->ops->reset_switch(dev);
146 }
147
148 enum global_defaults {
149         GLOBAL_APPLY,
150         GLOBAL_RESET,
151 };
152
153 enum vlan_defaults {
154         VLAN_PORTS,
155 };
156
157 enum port_defaults {
158         PORT_PVID,
159 };
160
161 static struct switch_attr default_global[] = {
162         [GLOBAL_APPLY] = {
163                 .type = SWITCH_TYPE_NOVAL,
164                 .name = "apply",
165                 .description = "Activate changes in the hardware",
166                 .set = swconfig_apply_config,
167         },
168         [GLOBAL_RESET] = {
169                 .type = SWITCH_TYPE_NOVAL,
170                 .name = "reset",
171                 .description = "Reset the switch",
172                 .set = swconfig_reset_switch,
173         }
174 };
175
176 static struct switch_attr default_port[] = {
177         [PORT_PVID] = {
178                 .type = SWITCH_TYPE_INT,
179                 .name = "pvid",
180                 .description = "Primary VLAN ID",
181                 .set = swconfig_set_pvid,
182                 .get = swconfig_get_pvid,
183         }
184 };
185
186 static struct switch_attr default_vlan[] = {
187         [VLAN_PORTS] = {
188                 .type = SWITCH_TYPE_PORTS,
189                 .name = "ports",
190                 .description = "VLAN port mapping",
191                 .set = swconfig_set_vlan_ports,
192                 .get = swconfig_get_vlan_ports,
193         },
194 };
195
196
197 static void swconfig_defaults_init(struct switch_dev *dev)
198 {
199         const struct switch_dev_ops *ops = dev->ops;
200
201         dev->def_global = 0;
202         dev->def_vlan = 0;
203         dev->def_port = 0;
204
205         if (ops->get_vlan_ports || ops->set_vlan_ports)
206                 set_bit(VLAN_PORTS, &dev->def_vlan);
207
208         if (ops->get_port_pvid || ops->set_port_pvid)
209                 set_bit(PORT_PVID, &dev->def_port);
210
211         /* always present, can be no-op */
212         set_bit(GLOBAL_APPLY, &dev->def_global);
213         set_bit(GLOBAL_RESET, &dev->def_global);
214 }
215
216
217 static struct genl_family switch_fam = {
218         .id = GENL_ID_GENERATE,
219         .name = "switch",
220         .hdrsize = 0,
221         .version = 1,
222         .maxattr = SWITCH_ATTR_MAX,
223 };
224
225 static const struct nla_policy switch_policy[SWITCH_ATTR_MAX+1] = {
226         [SWITCH_ATTR_ID] = { .type = NLA_U32 },
227         [SWITCH_ATTR_OP_ID] = { .type = NLA_U32 },
228         [SWITCH_ATTR_OP_PORT] = { .type = NLA_U32 },
229         [SWITCH_ATTR_OP_VLAN] = { .type = NLA_U32 },
230         [SWITCH_ATTR_OP_VALUE_INT] = { .type = NLA_U32 },
231         [SWITCH_ATTR_OP_VALUE_STR] = { .type = NLA_NUL_STRING },
232         [SWITCH_ATTR_OP_VALUE_PORTS] = { .type = NLA_NESTED },
233         [SWITCH_ATTR_TYPE] = { .type = NLA_U32 },
234 };
235
236 static const struct nla_policy port_policy[SWITCH_PORT_ATTR_MAX+1] = {
237         [SWITCH_PORT_ID] = { .type = NLA_U32 },
238         [SWITCH_PORT_FLAG_TAGGED] = { .type = NLA_FLAG },
239 };
240
241 static inline void
242 swconfig_lock(void)
243 {
244         spin_lock(&swdevs_lock);
245 }
246
247 static inline void
248 swconfig_unlock(void)
249 {
250         spin_unlock(&swdevs_lock);
251 }
252
253 static struct switch_dev *
254 swconfig_get_dev(struct genl_info *info)
255 {
256         struct switch_dev *dev = NULL;
257         struct switch_dev *p;
258         int id;
259
260         if (!info->attrs[SWITCH_ATTR_ID])
261                 goto done;
262
263         id = nla_get_u32(info->attrs[SWITCH_ATTR_ID]);
264         swconfig_lock();
265         list_for_each_entry(p, &swdevs, dev_list) {
266                 if (id != p->id)
267                         continue;
268
269                 dev = p;
270                 break;
271         }
272         if (dev)
273                 spin_lock(&dev->lock);
274         else
275                 DPRINTF("device %d not found\n", id);
276         swconfig_unlock();
277 done:
278         return dev;
279 }
280
281 static inline void
282 swconfig_put_dev(struct switch_dev *dev)
283 {
284         spin_unlock(&dev->lock);
285 }
286
287 static int
288 swconfig_dump_attr(struct swconfig_callback *cb, void *arg)
289 {
290         struct switch_attr *op = arg;
291         struct genl_info *info = cb->info;
292         struct sk_buff *msg = cb->msg;
293         int id = cb->args[0];
294         void *hdr;
295
296         hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, &switch_fam,
297                         NLM_F_MULTI, SWITCH_CMD_NEW_ATTR);
298         if (IS_ERR(hdr))
299                 return -1;
300
301         NLA_PUT_U32(msg, SWITCH_ATTR_OP_ID, id);
302         NLA_PUT_U32(msg, SWITCH_ATTR_OP_TYPE, op->type);
303         NLA_PUT_STRING(msg, SWITCH_ATTR_OP_NAME, op->name);
304         if (op->description)
305                 NLA_PUT_STRING(msg, SWITCH_ATTR_OP_DESCRIPTION,
306                         op->description);
307
308         return genlmsg_end(msg, hdr);
309 nla_put_failure:
310         genlmsg_cancel(msg, hdr);
311         return -EMSGSIZE;
312 }
313
314 /* spread multipart messages across multiple message buffers */
315 static int
316 swconfig_send_multipart(struct swconfig_callback *cb, void *arg)
317 {
318         struct genl_info *info = cb->info;
319         int restart = 0;
320         int err;
321
322         do {
323                 if (!cb->msg) {
324                         cb->msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
325                         if (cb->msg == NULL)
326                                 goto error;
327                 }
328
329                 if (!(cb->fill(cb, arg) < 0))
330                         break;
331
332                 /* fill failed, check if this was already the second attempt */
333                 if (restart)
334                         goto error;
335
336                 /* try again in a new message, send the current one */
337                 restart = 1;
338                 if (cb->close) {
339                         if (cb->close(cb, arg) < 0)
340                                 goto error;
341                 }
342                 err = genlmsg_reply(cb->msg, info);
343                 cb->msg = NULL;
344                 if (err < 0)
345                         goto error;
346
347         } while (restart);
348
349         return 0;
350
351 error:
352         if (cb->msg)
353                 nlmsg_free(cb->msg);
354         return -1;
355 }
356
357 static int
358 swconfig_list_attrs(struct sk_buff *skb, struct genl_info *info)
359 {
360         struct genlmsghdr *hdr = nlmsg_data(info->nlhdr);
361         const struct switch_attrlist *alist;
362         struct switch_dev *dev;
363         struct swconfig_callback cb;
364         int err = -EINVAL;
365         int i;
366
367         /* defaults */
368         struct switch_attr *def_list;
369         unsigned long *def_active;
370         int n_def;
371
372         dev = swconfig_get_dev(info);
373         if (!dev)
374                 return -EINVAL;
375
376         switch(hdr->cmd) {
377         case SWITCH_CMD_LIST_GLOBAL:
378                 alist = &dev->ops->attr_global;
379                 def_list = default_global;
380                 def_active = &dev->def_global;
381                 n_def = ARRAY_SIZE(default_global);
382                 break;
383         case SWITCH_CMD_LIST_VLAN:
384                 alist = &dev->ops->attr_vlan;
385                 def_list = default_vlan;
386                 def_active = &dev->def_vlan;
387                 n_def = ARRAY_SIZE(default_vlan);
388                 break;
389         case SWITCH_CMD_LIST_PORT:
390                 alist = &dev->ops->attr_port;
391                 def_list = default_port;
392                 def_active = &dev->def_port;
393                 n_def = ARRAY_SIZE(default_port);
394                 break;
395         default:
396                 WARN_ON(1);
397                 goto out;
398         }
399
400         memset(&cb, 0, sizeof(cb));
401         cb.info = info;
402         cb.fill = swconfig_dump_attr;
403         for (i = 0; i < alist->n_attr; i++) {
404                 if (alist->attr[i].disabled)
405                         continue;
406                 cb.args[0] = i;
407                 err = swconfig_send_multipart(&cb, (void *) &alist->attr[i]);
408                 if (err < 0)
409                         goto error;
410         }
411
412         /* defaults */
413         for (i = 0; i < n_def; i++) {
414                 if (!test_bit(i, def_active))
415                         continue;
416                 cb.args[0] = SWITCH_ATTR_DEFAULTS_OFFSET + i;
417                 err = swconfig_send_multipart(&cb, (void *) &def_list[i]);
418                 if (err < 0)
419                         goto error;
420         }
421         swconfig_put_dev(dev);
422
423         if (!cb.msg)
424                 return 0;
425
426         return genlmsg_reply(cb.msg, info);
427
428 error:
429         if (cb.msg)
430                 nlmsg_free(cb.msg);
431 out:
432         swconfig_put_dev(dev);
433         return err;
434 }
435
436 static const struct switch_attr *
437 swconfig_lookup_attr(struct switch_dev *dev, struct genl_info *info,
438                 struct switch_val *val)
439 {
440         struct genlmsghdr *hdr = nlmsg_data(info->nlhdr);
441         const struct switch_attrlist *alist;
442         const struct switch_attr *attr = NULL;
443         int attr_id;
444
445         /* defaults */
446         struct switch_attr *def_list;
447         unsigned long *def_active;
448         int n_def;
449
450         if (!info->attrs[SWITCH_ATTR_OP_ID])
451                 goto done;
452
453         switch(hdr->cmd) {
454         case SWITCH_CMD_SET_GLOBAL:
455         case SWITCH_CMD_GET_GLOBAL:
456                 alist = &dev->ops->attr_global;
457                 def_list = default_global;
458                 def_active = &dev->def_global;
459                 n_def = ARRAY_SIZE(default_global);
460                 break;
461         case SWITCH_CMD_SET_VLAN:
462         case SWITCH_CMD_GET_VLAN:
463                 alist = &dev->ops->attr_vlan;
464                 def_list = default_vlan;
465                 def_active = &dev->def_vlan;
466                 n_def = ARRAY_SIZE(default_vlan);
467                 if (!info->attrs[SWITCH_ATTR_OP_VLAN])
468                         goto done;
469                 val->port_vlan = nla_get_u32(info->attrs[SWITCH_ATTR_OP_VLAN]);
470                 if (val->port_vlan >= dev->vlans)
471                         goto done;
472                 break;
473         case SWITCH_CMD_SET_PORT:
474         case SWITCH_CMD_GET_PORT:
475                 alist = &dev->ops->attr_port;
476                 def_list = default_port;
477                 def_active = &dev->def_port;
478                 n_def = ARRAY_SIZE(default_port);
479                 if (!info->attrs[SWITCH_ATTR_OP_PORT])
480                         goto done;
481                 val->port_vlan = nla_get_u32(info->attrs[SWITCH_ATTR_OP_PORT]);
482                 if (val->port_vlan >= dev->ports)
483                         goto done;
484                 break;
485         default:
486                 WARN_ON(1);
487                 goto done;
488         }
489
490         if (!alist)
491                 goto done;
492
493         attr_id = nla_get_u32(info->attrs[SWITCH_ATTR_OP_ID]);
494         if (attr_id >= SWITCH_ATTR_DEFAULTS_OFFSET) {
495                 attr_id -= SWITCH_ATTR_DEFAULTS_OFFSET;
496                 if (attr_id >= n_def)
497                         goto done;
498                 if (!test_bit(attr_id, def_active))
499                         goto done;
500                 attr = &def_list[attr_id];
501         } else {
502                 if (attr_id >= alist->n_attr)
503                         goto done;
504                 attr = &alist->attr[attr_id];
505         }
506
507         if (attr->disabled)
508                 attr = NULL;
509
510 done:
511         if (!attr)
512                 DPRINTF("attribute lookup failed\n");
513         val->attr = attr;
514         return attr;
515 }
516
517 static int
518 swconfig_parse_ports(struct sk_buff *msg, struct nlattr *head,
519                 struct switch_val *val, int max)
520 {
521         struct nlattr *nla;
522         int rem;
523
524         val->len = 0;
525         nla_for_each_nested(nla, head, rem) {
526                 struct nlattr *tb[SWITCH_PORT_ATTR_MAX+1];
527                 struct switch_port *port = &val->value.ports[val->len];
528
529                 if (val->len >= max)
530                         return -EINVAL;
531
532                 if (nla_parse_nested(tb, SWITCH_PORT_ATTR_MAX, nla,
533                                 port_policy))
534                         return -EINVAL;
535
536                 if (!tb[SWITCH_PORT_ID])
537                         return -EINVAL;
538
539                 port->id = nla_get_u32(tb[SWITCH_PORT_ID]);
540                 if (tb[SWITCH_PORT_FLAG_TAGGED])
541                         port->flags |= (1 << SWITCH_PORT_FLAG_TAGGED);
542                 val->len++;
543         }
544
545         return 0;
546 }
547
548 static int
549 swconfig_set_attr(struct sk_buff *skb, struct genl_info *info)
550 {
551         const struct switch_attr *attr;
552         struct switch_dev *dev;
553         struct switch_val val;
554         int err = -EINVAL;
555
556         dev = swconfig_get_dev(info);
557         if (!dev)
558                 return -EINVAL;
559
560         memset(&val, 0, sizeof(val));
561         attr = swconfig_lookup_attr(dev, info, &val);
562         if (!attr || !attr->set)
563                 goto error;
564
565         val.attr = attr;
566         switch(attr->type) {
567         case SWITCH_TYPE_NOVAL:
568                 break;
569         case SWITCH_TYPE_INT:
570                 if (!info->attrs[SWITCH_ATTR_OP_VALUE_INT])
571                         goto error;
572                 val.value.i =
573                         nla_get_u32(info->attrs[SWITCH_ATTR_OP_VALUE_INT]);
574                 break;
575         case SWITCH_TYPE_STRING:
576                 if (!info->attrs[SWITCH_ATTR_OP_VALUE_STR])
577                         goto error;
578                 val.value.s =
579                         nla_data(info->attrs[SWITCH_ATTR_OP_VALUE_STR]);
580                 break;
581         case SWITCH_TYPE_PORTS:
582                 val.value.ports = dev->portbuf;
583                 memset(dev->portbuf, 0,
584                         sizeof(struct switch_port) * dev->ports);
585
586                 /* TODO: implement multipart? */
587                 if (info->attrs[SWITCH_ATTR_OP_VALUE_PORTS]) {
588                         err = swconfig_parse_ports(skb,
589                                 info->attrs[SWITCH_ATTR_OP_VALUE_PORTS], &val, dev->ports);
590                         if (err < 0)
591                                 goto error;
592                 } else {
593                         val.len = 0;
594                         err = 0;
595                 }
596                 break;
597         default:
598                 goto error;
599         }
600
601         err = attr->set(dev, attr, &val);
602 error:
603         swconfig_put_dev(dev);
604         return err;
605 }
606
607 static int
608 swconfig_close_portlist(struct swconfig_callback *cb, void *arg)
609 {
610         if (cb->nest[0])
611                 nla_nest_end(cb->msg, cb->nest[0]);
612         return 0;
613 }
614
615 static int
616 swconfig_send_port(struct swconfig_callback *cb, void *arg)
617 {
618         const struct switch_port *port = arg;
619         struct nlattr *p = NULL;
620
621         if (!cb->nest[0]) {
622                 cb->nest[0] = nla_nest_start(cb->msg, cb->cmd);
623                 if (!cb->nest[0])
624                         return -1;
625         }
626
627         p = nla_nest_start(cb->msg, SWITCH_ATTR_PORT);
628         if (!p)
629                 goto error;
630
631         NLA_PUT_U32(cb->msg, SWITCH_PORT_ID, port->id);
632         if (port->flags & (1 << SWITCH_PORT_FLAG_TAGGED))
633                 NLA_PUT_FLAG(cb->msg, SWITCH_PORT_FLAG_TAGGED);
634
635         nla_nest_end(cb->msg, p);
636         return 0;
637
638 nla_put_failure:
639                 nla_nest_cancel(cb->msg, p);
640 error:
641         nla_nest_cancel(cb->msg, cb->nest[0]);
642         return -1;
643 }
644
645 static int
646 swconfig_send_ports(struct sk_buff **msg, struct genl_info *info, int attr,
647                 const struct switch_val *val)
648 {
649         struct swconfig_callback cb;
650         int err = 0;
651         int i;
652
653         if (!val->value.ports)
654                 return -EINVAL;
655
656         memset(&cb, 0, sizeof(cb));
657         cb.cmd = attr;
658         cb.msg = *msg;
659         cb.info = info;
660         cb.fill = swconfig_send_port;
661         cb.close = swconfig_close_portlist;
662
663         cb.nest[0] = nla_nest_start(cb.msg, cb.cmd);
664         for (i = 0; i < val->len; i++) {
665                 err = swconfig_send_multipart(&cb, &val->value.ports[i]);
666                 if (err)
667                         goto done;
668         }
669         err = val->len;
670         swconfig_close_portlist(&cb, NULL);
671         *msg = cb.msg;
672
673 done:
674         return err;
675 }
676
677 static int
678 swconfig_get_attr(struct sk_buff *skb, struct genl_info *info)
679 {
680         struct genlmsghdr *hdr = nlmsg_data(info->nlhdr);
681         const struct switch_attr *attr;
682         struct switch_dev *dev;
683         struct sk_buff *msg = NULL;
684         struct switch_val val;
685         int err = -EINVAL;
686         int cmd = hdr->cmd;
687
688         dev = swconfig_get_dev(info);
689         if (!dev)
690                 return -EINVAL;
691
692         memset(&val, 0, sizeof(val));
693         attr = swconfig_lookup_attr(dev, info, &val);
694         if (!attr || !attr->get)
695                 goto error;
696
697         if (attr->type == SWITCH_TYPE_PORTS) {
698                 val.value.ports = dev->portbuf;
699                 memset(dev->portbuf, 0,
700                         sizeof(struct switch_port) * dev->ports);
701         }
702
703         err = attr->get(dev, attr, &val);
704         if (err)
705                 goto error;
706
707         msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
708         if (!msg)
709                 goto error;
710
711         hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, &switch_fam,
712                         0, cmd);
713         if (IS_ERR(hdr))
714                 goto nla_put_failure;
715
716         switch(attr->type) {
717         case SWITCH_TYPE_INT:
718                 NLA_PUT_U32(msg, SWITCH_ATTR_OP_VALUE_INT, val.value.i);
719                 break;
720         case SWITCH_TYPE_STRING:
721                 NLA_PUT_STRING(msg, SWITCH_ATTR_OP_VALUE_STR, val.value.s);
722                 break;
723         case SWITCH_TYPE_PORTS:
724                 err = swconfig_send_ports(&msg, info,
725                                 SWITCH_ATTR_OP_VALUE_PORTS, &val);
726                 if (err < 0)
727                         goto nla_put_failure;
728                 break;
729         default:
730                 DPRINTF("invalid type in attribute\n");
731                 err = -EINVAL;
732                 goto error;
733         }
734         err = genlmsg_end(msg, hdr);
735         if (err < 0)
736                 goto nla_put_failure;
737
738         swconfig_put_dev(dev);
739         return genlmsg_reply(msg, info);
740
741 nla_put_failure:
742         if (msg)
743                 nlmsg_free(msg);
744 error:
745         swconfig_put_dev(dev);
746         if (!err)
747                 err = -ENOMEM;
748         return err;
749 }
750
751 static int
752 swconfig_send_switch(struct sk_buff *msg, u32 pid, u32 seq, int flags,
753                 const struct switch_dev *dev)
754 {
755         void *hdr;
756
757         hdr = genlmsg_put(msg, pid, seq, &switch_fam, flags,
758                         SWITCH_CMD_NEW_ATTR);
759         if (IS_ERR(hdr))
760                 return -1;
761
762         NLA_PUT_U32(msg, SWITCH_ATTR_ID, dev->id);
763         NLA_PUT_STRING(msg, SWITCH_ATTR_NAME, dev->name);
764         NLA_PUT_STRING(msg, SWITCH_ATTR_DEV_NAME, dev->devname);
765         NLA_PUT_U32(msg, SWITCH_ATTR_VLANS, dev->vlans);
766         NLA_PUT_U32(msg, SWITCH_ATTR_PORTS, dev->ports);
767         NLA_PUT_U32(msg, SWITCH_ATTR_CPU_PORT, dev->cpu_port);
768
769         return genlmsg_end(msg, hdr);
770 nla_put_failure:
771         genlmsg_cancel(msg, hdr);
772         return -EMSGSIZE;
773 }
774
775 static int swconfig_dump_switches(struct sk_buff *skb,
776                 struct netlink_callback *cb)
777 {
778         struct switch_dev *dev;
779         int start = cb->args[0];
780         int idx = 0;
781
782         swconfig_lock();
783         list_for_each_entry(dev, &swdevs, dev_list) {
784                 if (++idx <= start)
785                         continue;
786                 if (swconfig_send_switch(skb, NETLINK_CB(cb->skb).pid,
787                                 cb->nlh->nlmsg_seq, NLM_F_MULTI,
788                                 dev) < 0)
789                         break;
790         }
791         swconfig_unlock();
792         cb->args[0] = idx;
793
794         return skb->len;
795 }
796
797 static int
798 swconfig_done(struct netlink_callback *cb)
799 {
800         return 0;
801 }
802
803 static struct genl_ops swconfig_ops[] = {
804         {
805                 .cmd = SWITCH_CMD_LIST_GLOBAL,
806                 .doit = swconfig_list_attrs,
807                 .policy = switch_policy,
808         },
809         {
810                 .cmd = SWITCH_CMD_LIST_VLAN,
811                 .doit = swconfig_list_attrs,
812                 .policy = switch_policy,
813         },
814         {
815                 .cmd = SWITCH_CMD_LIST_PORT,
816                 .doit = swconfig_list_attrs,
817                 .policy = switch_policy,
818         },
819         {
820                 .cmd = SWITCH_CMD_GET_GLOBAL,
821                 .doit = swconfig_get_attr,
822                 .policy = switch_policy,
823         },
824         {
825                 .cmd = SWITCH_CMD_GET_VLAN,
826                 .doit = swconfig_get_attr,
827                 .policy = switch_policy,
828         },
829         {
830                 .cmd = SWITCH_CMD_GET_PORT,
831                 .doit = swconfig_get_attr,
832                 .policy = switch_policy,
833         },
834         {
835                 .cmd = SWITCH_CMD_SET_GLOBAL,
836                 .doit = swconfig_set_attr,
837                 .policy = switch_policy,
838         },
839         {
840                 .cmd = SWITCH_CMD_SET_VLAN,
841                 .doit = swconfig_set_attr,
842                 .policy = switch_policy,
843         },
844         {
845                 .cmd = SWITCH_CMD_SET_PORT,
846                 .doit = swconfig_set_attr,
847                 .policy = switch_policy,
848         },
849         {
850                 .cmd = SWITCH_CMD_GET_SWITCH,
851                 .dumpit = swconfig_dump_switches,
852                 .policy = switch_policy,
853                 .done = swconfig_done,
854         }
855 };
856
857 int
858 register_switch(struct switch_dev *dev, struct net_device *netdev)
859 {
860         INIT_LIST_HEAD(&dev->dev_list);
861         if (netdev) {
862                 dev->netdev = netdev;
863                 if (!dev->devname)
864                         dev->devname = netdev->name;
865         }
866         BUG_ON(!dev->devname);
867
868         if (dev->ports > 0) {
869                 dev->portbuf = kzalloc(sizeof(struct switch_port) * dev->ports,
870                                 GFP_KERNEL);
871                 if (!dev->portbuf)
872                         return -ENOMEM;
873         }
874         dev->id = ++swdev_id;
875         swconfig_defaults_init(dev);
876         spin_lock_init(&dev->lock);
877         swconfig_lock();
878         list_add(&dev->dev_list, &swdevs);
879         swconfig_unlock();
880
881         return 0;
882 }
883 EXPORT_SYMBOL_GPL(register_switch);
884
885 void
886 unregister_switch(struct switch_dev *dev)
887 {
888         kfree(dev->portbuf);
889         spin_lock(&dev->lock);
890         swconfig_lock();
891         list_del(&dev->dev_list);
892         swconfig_unlock();
893         spin_unlock(&dev->lock);
894 }
895 EXPORT_SYMBOL_GPL(unregister_switch);
896
897
898 static int __init
899 swconfig_init(void)
900 {
901         int i, err;
902
903         INIT_LIST_HEAD(&swdevs);
904         err = genl_register_family(&switch_fam);
905         if (err)
906                 return err;
907
908         for (i = 0; i < ARRAY_SIZE(swconfig_ops); i++) {
909                 err = genl_register_ops(&switch_fam, &swconfig_ops[i]);
910                 if (err)
911                         goto unregister;
912         }
913
914         return 0;
915
916 unregister:
917         genl_unregister_family(&switch_fam);
918         return err;
919 }
920
921 static void __exit
922 swconfig_exit(void)
923 {
924         genl_unregister_family(&switch_fam);
925 }
926
927 module_init(swconfig_init);
928 module_exit(swconfig_exit);
929