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