2 * net/dsa/dsa.c - Hardware switch handling
3 * Copyright (c) 2008-2009 Marvell Semiconductor
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
11 #include <linux/list.h>
12 #include <linux/netdevice.h>
13 #include <linux/platform_device.h>
14 #include <linux/slab.h>
15 #include <linux/module.h>
19 char dsa_driver_version
[] = "0.1";
22 /* switch driver registration ***********************************************/
23 static DEFINE_MUTEX(dsa_switch_drivers_mutex
);
24 static LIST_HEAD(dsa_switch_drivers
);
26 void register_switch_driver(struct dsa_switch_driver
*drv
)
28 mutex_lock(&dsa_switch_drivers_mutex
);
29 list_add_tail(&drv
->list
, &dsa_switch_drivers
);
30 mutex_unlock(&dsa_switch_drivers_mutex
);
32 EXPORT_SYMBOL_GPL(register_switch_driver
);
34 void unregister_switch_driver(struct dsa_switch_driver
*drv
)
36 mutex_lock(&dsa_switch_drivers_mutex
);
37 list_del_init(&drv
->list
);
38 mutex_unlock(&dsa_switch_drivers_mutex
);
40 EXPORT_SYMBOL_GPL(unregister_switch_driver
);
42 static struct dsa_switch_driver
*
43 dsa_switch_probe(struct mii_bus
*bus
, int sw_addr
, char **_name
)
45 struct dsa_switch_driver
*ret
;
46 struct list_head
*list
;
52 mutex_lock(&dsa_switch_drivers_mutex
);
53 list_for_each(list
, &dsa_switch_drivers
) {
54 struct dsa_switch_driver
*drv
;
56 drv
= list_entry(list
, struct dsa_switch_driver
, list
);
58 name
= drv
->probe(bus
, sw_addr
);
64 mutex_unlock(&dsa_switch_drivers_mutex
);
72 /* basic switch operations **************************************************/
73 static struct dsa_switch
*
74 dsa_switch_setup(struct dsa_switch_tree
*dst
, int index
,
75 struct device
*parent
, struct mii_bus
*bus
)
77 struct dsa_chip_data
*pd
= dst
->pd
->chip
+ index
;
78 struct dsa_switch_driver
*drv
;
79 struct dsa_switch
*ds
;
83 bool valid_name_found
= false;
86 * Probe for switch model.
88 drv
= dsa_switch_probe(bus
, pd
->sw_addr
, &name
);
90 printk(KERN_ERR
"%s[%d]: could not detect attached switch\n",
91 dst
->master_netdev
->name
, index
);
92 return ERR_PTR(-EINVAL
);
94 printk(KERN_INFO
"%s[%d]: detected a %s switch\n",
95 dst
->master_netdev
->name
, index
, name
);
99 * Allocate and initialise switch state.
101 ds
= kzalloc(sizeof(*ds
) + drv
->priv_size
, GFP_KERNEL
);
103 return ERR_PTR(-ENOMEM
);
107 ds
->pd
= dst
->pd
->chip
+ index
;
109 ds
->master_mii_bus
= bus
;
113 * Validate supplied switch configuration.
115 for (i
= 0; i
< DSA_MAX_PORTS
; i
++) {
118 name
= pd
->port_names
[i
];
122 if (!strcmp(name
, "cpu")) {
123 if (dst
->cpu_switch
!= -1) {
124 printk(KERN_ERR
"multiple cpu ports?!\n");
128 dst
->cpu_switch
= index
;
130 } else if (!strcmp(name
, "dsa")) {
131 ds
->dsa_port_mask
|= 1 << i
;
133 ds
->phys_port_mask
|= 1 << i
;
135 valid_name_found
= true;
138 if (!valid_name_found
&& i
== DSA_MAX_PORTS
) {
144 * If the CPU connects to this switch, set the switch tree
145 * tagging protocol to the preferred tagging format of this
148 if (ds
->dst
->cpu_switch
== index
)
149 ds
->dst
->tag_protocol
= drv
->tag_protocol
;
153 * Do basic register setup.
155 ret
= drv
->setup(ds
);
159 ret
= drv
->set_addr(ds
, dst
->master_netdev
->dev_addr
);
163 ds
->slave_mii_bus
= mdiobus_alloc();
164 if (ds
->slave_mii_bus
== NULL
) {
168 dsa_slave_mii_bus_init(ds
);
170 ret
= mdiobus_register(ds
->slave_mii_bus
);
176 * Create network devices for physical switch ports.
178 for (i
= 0; i
< DSA_MAX_PORTS
; i
++) {
179 struct net_device
*slave_dev
;
181 if (!(ds
->phys_port_mask
& (1 << i
)))
184 slave_dev
= dsa_slave_create(ds
, parent
, i
, pd
->port_names
[i
]);
185 if (slave_dev
== NULL
) {
186 printk(KERN_ERR
"%s[%d]: can't create dsa "
187 "slave device for port %d(%s)\n",
188 dst
->master_netdev
->name
,
189 index
, i
, pd
->port_names
[i
]);
193 ds
->ports
[i
] = slave_dev
;
199 mdiobus_free(ds
->slave_mii_bus
);
205 static void dsa_switch_destroy(struct dsa_switch
*ds
)
210 /* link polling *************************************************************/
211 static void dsa_link_poll_work(struct work_struct
*ugly
)
213 struct dsa_switch_tree
*dst
;
216 dst
= container_of(ugly
, struct dsa_switch_tree
, link_poll_work
);
218 for (i
= 0; i
< dst
->pd
->nr_chips
; i
++) {
219 struct dsa_switch
*ds
= dst
->ds
[i
];
221 if (ds
!= NULL
&& ds
->drv
->poll_link
!= NULL
)
222 ds
->drv
->poll_link(ds
);
225 mod_timer(&dst
->link_poll_timer
, round_jiffies(jiffies
+ HZ
));
228 static void dsa_link_poll_timer(unsigned long _dst
)
230 struct dsa_switch_tree
*dst
= (void *)_dst
;
232 schedule_work(&dst
->link_poll_work
);
236 /* platform driver init and cleanup *****************************************/
237 static int dev_is_class(struct device
*dev
, void *class)
239 if (dev
->class != NULL
&& !strcmp(dev
->class->name
, class))
245 static struct device
*dev_find_class(struct device
*parent
, char *class)
247 if (dev_is_class(parent
, class)) {
252 return device_find_child(parent
, class, dev_is_class
);
255 static struct mii_bus
*dev_to_mii_bus(struct device
*dev
)
259 d
= dev_find_class(dev
, "mdio_bus");
272 static struct net_device
*dev_to_net_device(struct device
*dev
)
276 d
= dev_find_class(dev
, "net");
278 struct net_device
*nd
;
290 static int dsa_probe(struct platform_device
*pdev
)
292 static int dsa_version_printed
;
293 struct dsa_platform_data
*pd
= pdev
->dev
.platform_data
;
294 struct net_device
*dev
;
295 struct dsa_switch_tree
*dst
;
298 if (!dsa_version_printed
++)
299 printk(KERN_NOTICE
"Distributed Switch Architecture "
300 "driver version %s\n", dsa_driver_version
);
302 if (pd
== NULL
|| pd
->netdev
== NULL
)
305 dev
= dev_to_net_device(pd
->netdev
);
309 if (dev
->dsa_ptr
!= NULL
) {
314 dst
= kzalloc(sizeof(*dst
), GFP_KERNEL
);
320 platform_set_drvdata(pdev
, dst
);
323 dst
->master_netdev
= dev
;
324 dst
->cpu_switch
= -1;
327 for (i
= 0; i
< pd
->nr_chips
; i
++) {
329 struct dsa_switch
*ds
;
331 bus
= dev_to_mii_bus(pd
->chip
[i
].mii_bus
);
333 printk(KERN_ERR
"%s[%d]: no mii bus found for "
334 "dsa switch\n", dev
->name
, i
);
338 ds
= dsa_switch_setup(dst
, i
, &pdev
->dev
, bus
);
340 printk(KERN_ERR
"%s[%d]: couldn't create dsa switch "
341 "instance (error %ld)\n", dev
->name
, i
,
347 if (ds
->drv
->poll_link
!= NULL
)
348 dst
->link_poll_needed
= 1;
352 * If we use a tagging format that doesn't have an ethertype
353 * field, make sure that all packets from this point on get
354 * sent to the tag format's receive function.
357 dev
->dsa_ptr
= (void *)dst
;
359 if (dst
->link_poll_needed
) {
360 INIT_WORK(&dst
->link_poll_work
, dsa_link_poll_work
);
361 init_timer(&dst
->link_poll_timer
);
362 dst
->link_poll_timer
.data
= (unsigned long)dst
;
363 dst
->link_poll_timer
.function
= dsa_link_poll_timer
;
364 dst
->link_poll_timer
.expires
= round_jiffies(jiffies
+ HZ
);
365 add_timer(&dst
->link_poll_timer
);
371 static int dsa_remove(struct platform_device
*pdev
)
373 struct dsa_switch_tree
*dst
= platform_get_drvdata(pdev
);
376 if (dst
->link_poll_needed
)
377 del_timer_sync(&dst
->link_poll_timer
);
379 flush_work(&dst
->link_poll_work
);
381 for (i
= 0; i
< dst
->pd
->nr_chips
; i
++) {
382 struct dsa_switch
*ds
= dst
->ds
[i
];
385 dsa_switch_destroy(ds
);
391 static void dsa_shutdown(struct platform_device
*pdev
)
395 static struct platform_driver dsa_driver
= {
397 .remove
= dsa_remove
,
398 .shutdown
= dsa_shutdown
,
401 .owner
= THIS_MODULE
,
405 static int __init
dsa_init_module(void)
409 rc
= platform_driver_register(&dsa_driver
);
413 #ifdef CONFIG_NET_DSA_TAG_DSA
414 dev_add_pack(&dsa_packet_type
);
416 #ifdef CONFIG_NET_DSA_TAG_EDSA
417 dev_add_pack(&edsa_packet_type
);
419 #ifdef CONFIG_NET_DSA_TAG_TRAILER
420 dev_add_pack(&trailer_packet_type
);
424 module_init(dsa_init_module
);
426 static void __exit
dsa_cleanup_module(void)
428 #ifdef CONFIG_NET_DSA_TAG_TRAILER
429 dev_remove_pack(&trailer_packet_type
);
431 #ifdef CONFIG_NET_DSA_TAG_EDSA
432 dev_remove_pack(&edsa_packet_type
);
434 #ifdef CONFIG_NET_DSA_TAG_DSA
435 dev_remove_pack(&dsa_packet_type
);
437 platform_driver_unregister(&dsa_driver
);
439 module_exit(dsa_cleanup_module
);
441 MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>");
442 MODULE_DESCRIPTION("Driver for Distributed Switch Architecture switch chips");
443 MODULE_LICENSE("GPL");
444 MODULE_ALIAS("platform:dsa");