aboutsummaryrefslogtreecommitdiffstats
path: root/net/dsa/dsa.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dsa/dsa.c')
-rw-r--r--net/dsa/dsa.c186
1 files changed, 148 insertions, 38 deletions
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 0a49632fac47..22f34cf4cb27 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -10,7 +10,6 @@
10 */ 10 */
11 11
12#include <linux/list.h> 12#include <linux/list.h>
13#include <linux/netdevice.h>
14#include <linux/platform_device.h> 13#include <linux/platform_device.h>
15#include <linux/slab.h> 14#include <linux/slab.h>
16#include <linux/module.h> 15#include <linux/module.h>
@@ -44,7 +43,7 @@ void unregister_switch_driver(struct dsa_switch_driver *drv)
44EXPORT_SYMBOL_GPL(unregister_switch_driver); 43EXPORT_SYMBOL_GPL(unregister_switch_driver);
45 44
46static struct dsa_switch_driver * 45static struct dsa_switch_driver *
47dsa_switch_probe(struct mii_bus *bus, int sw_addr, char **_name) 46dsa_switch_probe(struct device *host_dev, int sw_addr, char **_name)
48{ 47{
49 struct dsa_switch_driver *ret; 48 struct dsa_switch_driver *ret;
50 struct list_head *list; 49 struct list_head *list;
@@ -59,7 +58,7 @@ dsa_switch_probe(struct mii_bus *bus, int sw_addr, char **_name)
59 58
60 drv = list_entry(list, struct dsa_switch_driver, list); 59 drv = list_entry(list, struct dsa_switch_driver, list);
61 60
62 name = drv->probe(bus, sw_addr); 61 name = drv->probe(host_dev, sw_addr);
63 if (name != NULL) { 62 if (name != NULL) {
64 ret = drv; 63 ret = drv;
65 break; 64 break;
@@ -76,7 +75,7 @@ dsa_switch_probe(struct mii_bus *bus, int sw_addr, char **_name)
76/* basic switch operations **************************************************/ 75/* basic switch operations **************************************************/
77static struct dsa_switch * 76static struct dsa_switch *
78dsa_switch_setup(struct dsa_switch_tree *dst, int index, 77dsa_switch_setup(struct dsa_switch_tree *dst, int index,
79 struct device *parent, struct mii_bus *bus) 78 struct device *parent, struct device *host_dev)
80{ 79{
81 struct dsa_chip_data *pd = dst->pd->chip + index; 80 struct dsa_chip_data *pd = dst->pd->chip + index;
82 struct dsa_switch_driver *drv; 81 struct dsa_switch_driver *drv;
@@ -89,7 +88,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
89 /* 88 /*
90 * Probe for switch model. 89 * Probe for switch model.
91 */ 90 */
92 drv = dsa_switch_probe(bus, pd->sw_addr, &name); 91 drv = dsa_switch_probe(host_dev, pd->sw_addr, &name);
93 if (drv == NULL) { 92 if (drv == NULL) {
94 printk(KERN_ERR "%s[%d]: could not detect attached switch\n", 93 printk(KERN_ERR "%s[%d]: could not detect attached switch\n",
95 dst->master_netdev->name, index); 94 dst->master_netdev->name, index);
@@ -110,8 +109,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
110 ds->index = index; 109 ds->index = index;
111 ds->pd = dst->pd->chip + index; 110 ds->pd = dst->pd->chip + index;
112 ds->drv = drv; 111 ds->drv = drv;
113 ds->master_mii_bus = bus; 112 ds->master_dev = host_dev;
114
115 113
116 /* 114 /*
117 * Validate supplied switch configuration. 115 * Validate supplied switch configuration.
@@ -144,14 +142,44 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
144 goto out; 142 goto out;
145 } 143 }
146 144
145 /* Make the built-in MII bus mask match the number of ports,
146 * switch drivers can override this later
147 */
148 ds->phys_mii_mask = ds->phys_port_mask;
149
147 /* 150 /*
148 * If the CPU connects to this switch, set the switch tree 151 * If the CPU connects to this switch, set the switch tree
149 * tagging protocol to the preferred tagging format of this 152 * tagging protocol to the preferred tagging format of this
150 * switch. 153 * switch.
151 */ 154 */
152 if (ds->dst->cpu_switch == index) 155 if (dst->cpu_switch == index) {
153 ds->dst->tag_protocol = drv->tag_protocol; 156 switch (drv->tag_protocol) {
157#ifdef CONFIG_NET_DSA_TAG_DSA
158 case DSA_TAG_PROTO_DSA:
159 dst->rcv = dsa_netdev_ops.rcv;
160 break;
161#endif
162#ifdef CONFIG_NET_DSA_TAG_EDSA
163 case DSA_TAG_PROTO_EDSA:
164 dst->rcv = edsa_netdev_ops.rcv;
165 break;
166#endif
167#ifdef CONFIG_NET_DSA_TAG_TRAILER
168 case DSA_TAG_PROTO_TRAILER:
169 dst->rcv = trailer_netdev_ops.rcv;
170 break;
171#endif
172#ifdef CONFIG_NET_DSA_TAG_BRCM
173 case DSA_TAG_PROTO_BRCM:
174 dst->rcv = brcm_netdev_ops.rcv;
175 break;
176#endif
177 default:
178 break;
179 }
154 180
181 dst->tag_protocol = drv->tag_protocol;
182 }
155 183
156 /* 184 /*
157 * Do basic register setup. 185 * Do basic register setup.
@@ -210,6 +238,51 @@ static void dsa_switch_destroy(struct dsa_switch *ds)
210{ 238{
211} 239}
212 240
241#ifdef CONFIG_PM_SLEEP
242static int dsa_switch_suspend(struct dsa_switch *ds)
243{
244 int i, ret = 0;
245
246 /* Suspend slave network devices */
247 for (i = 0; i < DSA_MAX_PORTS; i++) {
248 if (!(ds->phys_port_mask & (1 << i)))
249 continue;
250
251 ret = dsa_slave_suspend(ds->ports[i]);
252 if (ret)
253 return ret;
254 }
255
256 if (ds->drv->suspend)
257 ret = ds->drv->suspend(ds);
258
259 return ret;
260}
261
262static int dsa_switch_resume(struct dsa_switch *ds)
263{
264 int i, ret = 0;
265
266 if (ds->drv->resume)
267 ret = ds->drv->resume(ds);
268
269 if (ret)
270 return ret;
271
272 /* Resume slave network devices */
273 for (i = 0; i < DSA_MAX_PORTS; i++) {
274 if (!(ds->phys_port_mask & (1 << i)))
275 continue;
276
277 ret = dsa_slave_resume(ds->ports[i]);
278 if (ret)
279 return ret;
280 }
281
282 return 0;
283}
284#endif
285
213 286
214/* link polling *************************************************************/ 287/* link polling *************************************************************/
215static void dsa_link_poll_work(struct work_struct *ugly) 288static void dsa_link_poll_work(struct work_struct *ugly)
@@ -256,7 +329,7 @@ static struct device *dev_find_class(struct device *parent, char *class)
256 return device_find_child(parent, class, dev_is_class); 329 return device_find_child(parent, class, dev_is_class);
257} 330}
258 331
259static struct mii_bus *dev_to_mii_bus(struct device *dev) 332struct mii_bus *dsa_host_dev_to_mii_bus(struct device *dev)
260{ 333{
261 struct device *d; 334 struct device *d;
262 335
@@ -272,6 +345,7 @@ static struct mii_bus *dev_to_mii_bus(struct device *dev)
272 345
273 return NULL; 346 return NULL;
274} 347}
348EXPORT_SYMBOL_GPL(dsa_host_dev_to_mii_bus);
275 349
276static struct net_device *dev_to_net_device(struct device *dev) 350static struct net_device *dev_to_net_device(struct device *dev)
277{ 351{
@@ -410,7 +484,8 @@ static int dsa_of_probe(struct platform_device *pdev)
410 chip_index++; 484 chip_index++;
411 cd = &pd->chip[chip_index]; 485 cd = &pd->chip[chip_index];
412 486
413 cd->mii_bus = &mdio_bus->dev; 487 cd->of_node = child;
488 cd->host_dev = &mdio_bus->dev;
414 489
415 sw_addr = of_get_property(child, "reg", NULL); 490 sw_addr = of_get_property(child, "reg", NULL);
416 if (!sw_addr) 491 if (!sw_addr)
@@ -431,6 +506,8 @@ static int dsa_of_probe(struct platform_device *pdev)
431 if (!port_name) 506 if (!port_name)
432 continue; 507 continue;
433 508
509 cd->port_dn[port_index] = port;
510
434 cd->port_names[port_index] = kstrdup(port_name, 511 cd->port_names[port_index] = kstrdup(port_name,
435 GFP_KERNEL); 512 GFP_KERNEL);
436 if (!cd->port_names[port_index]) { 513 if (!cd->port_names[port_index]) {
@@ -534,17 +611,9 @@ static int dsa_probe(struct platform_device *pdev)
534 dst->cpu_port = -1; 611 dst->cpu_port = -1;
535 612
536 for (i = 0; i < pd->nr_chips; i++) { 613 for (i = 0; i < pd->nr_chips; i++) {
537 struct mii_bus *bus;
538 struct dsa_switch *ds; 614 struct dsa_switch *ds;
539 615
540 bus = dev_to_mii_bus(pd->chip[i].mii_bus); 616 ds = dsa_switch_setup(dst, i, &pdev->dev, pd->chip[i].host_dev);
541 if (bus == NULL) {
542 printk(KERN_ERR "%s[%d]: no mii bus found for "
543 "dsa switch\n", dev->name, i);
544 continue;
545 }
546
547 ds = dsa_switch_setup(dst, i, &pdev->dev, bus);
548 if (IS_ERR(ds)) { 617 if (IS_ERR(ds)) {
549 printk(KERN_ERR "%s[%d]: couldn't create dsa switch " 618 printk(KERN_ERR "%s[%d]: couldn't create dsa switch "
550 "instance (error %ld)\n", dev->name, i, 619 "instance (error %ld)\n", dev->name, i,
@@ -608,7 +677,62 @@ static void dsa_shutdown(struct platform_device *pdev)
608{ 677{
609} 678}
610 679
680static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,
681 struct packet_type *pt, struct net_device *orig_dev)
682{
683 struct dsa_switch_tree *dst = dev->dsa_ptr;
684
685 if (unlikely(dst == NULL)) {
686 kfree_skb(skb);
687 return 0;
688 }
689
690 return dst->rcv(skb, dev, pt, orig_dev);
691}
692
693static struct packet_type dsa_pack_type __read_mostly = {
694 .type = cpu_to_be16(ETH_P_XDSA),
695 .func = dsa_switch_rcv,
696};
697
698#ifdef CONFIG_PM_SLEEP
699static int dsa_suspend(struct device *d)
700{
701 struct platform_device *pdev = to_platform_device(d);
702 struct dsa_switch_tree *dst = platform_get_drvdata(pdev);
703 int i, ret = 0;
704
705 for (i = 0; i < dst->pd->nr_chips; i++) {
706 struct dsa_switch *ds = dst->ds[i];
707
708 if (ds != NULL)
709 ret = dsa_switch_suspend(ds);
710 }
711
712 return ret;
713}
714
715static int dsa_resume(struct device *d)
716{
717 struct platform_device *pdev = to_platform_device(d);
718 struct dsa_switch_tree *dst = platform_get_drvdata(pdev);
719 int i, ret = 0;
720
721 for (i = 0; i < dst->pd->nr_chips; i++) {
722 struct dsa_switch *ds = dst->ds[i];
723
724 if (ds != NULL)
725 ret = dsa_switch_resume(ds);
726 }
727
728 return ret;
729}
730#endif
731
732static SIMPLE_DEV_PM_OPS(dsa_pm_ops, dsa_suspend, dsa_resume);
733
611static const struct of_device_id dsa_of_match_table[] = { 734static const struct of_device_id dsa_of_match_table[] = {
735 { .compatible = "brcm,bcm7445-switch-v4.0" },
612 { .compatible = "marvell,dsa", }, 736 { .compatible = "marvell,dsa", },
613 {} 737 {}
614}; 738};
@@ -622,6 +746,7 @@ static struct platform_driver dsa_driver = {
622 .name = "dsa", 746 .name = "dsa",
623 .owner = THIS_MODULE, 747 .owner = THIS_MODULE,
624 .of_match_table = dsa_of_match_table, 748 .of_match_table = dsa_of_match_table,
749 .pm = &dsa_pm_ops,
625 }, 750 },
626}; 751};
627 752
@@ -633,30 +758,15 @@ static int __init dsa_init_module(void)
633 if (rc) 758 if (rc)
634 return rc; 759 return rc;
635 760
636#ifdef CONFIG_NET_DSA_TAG_DSA 761 dev_add_pack(&dsa_pack_type);
637 dev_add_pack(&dsa_packet_type); 762
638#endif
639#ifdef CONFIG_NET_DSA_TAG_EDSA
640 dev_add_pack(&edsa_packet_type);
641#endif
642#ifdef CONFIG_NET_DSA_TAG_TRAILER
643 dev_add_pack(&trailer_packet_type);
644#endif
645 return 0; 763 return 0;
646} 764}
647module_init(dsa_init_module); 765module_init(dsa_init_module);
648 766
649static void __exit dsa_cleanup_module(void) 767static void __exit dsa_cleanup_module(void)
650{ 768{
651#ifdef CONFIG_NET_DSA_TAG_TRAILER 769 dev_remove_pack(&dsa_pack_type);
652 dev_remove_pack(&trailer_packet_type);
653#endif
654#ifdef CONFIG_NET_DSA_TAG_EDSA
655 dev_remove_pack(&edsa_packet_type);
656#endif
657#ifdef CONFIG_NET_DSA_TAG_DSA
658 dev_remove_pack(&dsa_packet_type);
659#endif
660 platform_driver_unregister(&dsa_driver); 770 platform_driver_unregister(&dsa_driver);
661} 771}
662module_exit(dsa_cleanup_module); 772module_exit(dsa_cleanup_module);