2 * net/dsa/dsa.c - Hardware switch handling
3 * Copyright (c) 2008 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>
17 char dsa_driver_version
[] = "0.1";
20 /* switch driver registration ***********************************************/
21 static DEFINE_MUTEX(dsa_switch_drivers_mutex
);
22 static LIST_HEAD(dsa_switch_drivers
);
24 void register_switch_driver(struct dsa_switch_driver
*drv
)
26 mutex_lock(&dsa_switch_drivers_mutex
);
27 list_add_tail(&drv
->list
, &dsa_switch_drivers
);
28 mutex_unlock(&dsa_switch_drivers_mutex
);
31 void unregister_switch_driver(struct dsa_switch_driver
*drv
)
33 mutex_lock(&dsa_switch_drivers_mutex
);
34 list_del_init(&drv
->list
);
35 mutex_unlock(&dsa_switch_drivers_mutex
);
38 static struct dsa_switch_driver
*
39 dsa_switch_probe(struct mii_bus
*bus
, int sw_addr
, char **_name
)
41 struct dsa_switch_driver
*ret
;
42 struct list_head
*list
;
48 mutex_lock(&dsa_switch_drivers_mutex
);
49 list_for_each(list
, &dsa_switch_drivers
) {
50 struct dsa_switch_driver
*drv
;
52 drv
= list_entry(list
, struct dsa_switch_driver
, list
);
54 name
= drv
->probe(bus
, sw_addr
);
60 mutex_unlock(&dsa_switch_drivers_mutex
);
68 /* basic switch operations **************************************************/
69 static struct dsa_switch
*
70 dsa_switch_setup(struct device
*parent
, struct dsa_platform_data
*pd
,
71 struct mii_bus
*bus
, struct net_device
*dev
)
73 struct dsa_switch
*ds
;
75 struct dsa_switch_driver
*drv
;
80 * Probe for switch model.
82 drv
= dsa_switch_probe(bus
, pd
->sw_addr
, &name
);
84 printk(KERN_ERR
"%s: could not detect attached switch\n",
86 return ERR_PTR(-EINVAL
);
88 printk(KERN_INFO
"%s: detected a %s switch\n", dev
->name
, name
);
92 * Allocate and initialise switch state.
94 ds
= kzalloc(sizeof(*ds
) + drv
->priv_size
, GFP_KERNEL
);
96 return ERR_PTR(-ENOMEM
);
99 ds
->master_netdev
= dev
;
100 ds
->master_mii_bus
= bus
;
103 ds
->tag_protocol
= drv
->tag_protocol
;
107 * Validate supplied switch configuration.
110 for (i
= 0; i
< DSA_MAX_PORTS
; i
++) {
113 name
= pd
->port_names
[i
];
117 if (!strcmp(name
, "cpu")) {
118 if (ds
->cpu_port
!= -1) {
119 printk(KERN_ERR
"multiple cpu ports?!\n");
125 ds
->valid_port_mask
|= 1 << i
;
129 if (ds
->cpu_port
== -1) {
130 printk(KERN_ERR
"no cpu port?!\n");
137 * If we use a tagging format that doesn't have an ethertype
138 * field, make sure that all packets from this point on get
139 * sent to the tag format's receive function. (Which will
140 * discard received packets until we set ds->ports[] below.)
143 dev
->dsa_ptr
= (void *)ds
;
147 * Do basic register setup.
149 ret
= drv
->setup(ds
);
153 ret
= drv
->set_addr(ds
, dev
->dev_addr
);
157 ds
->slave_mii_bus
= mdiobus_alloc();
158 if (ds
->slave_mii_bus
== NULL
) {
162 dsa_slave_mii_bus_init(ds
);
164 ret
= mdiobus_register(ds
->slave_mii_bus
);
170 * Create network devices for physical switch ports.
173 for (i
= 0; i
< DSA_MAX_PORTS
; i
++) {
174 struct net_device
*slave_dev
;
176 if (!(ds
->valid_port_mask
& (1 << i
)))
179 slave_dev
= dsa_slave_create(ds
, parent
, i
, pd
->port_names
[i
]);
180 if (slave_dev
== NULL
) {
181 printk(KERN_ERR
"%s: can't create dsa slave "
182 "device for port %d(%s)\n",
183 dev
->name
, i
, pd
->port_names
[i
]);
187 ds
->ports
[i
] = slave_dev
;
193 mdiobus_free(ds
->slave_mii_bus
);
200 static void dsa_switch_destroy(struct dsa_switch
*ds
)
205 /* hooks for ethertype-less tagging formats *********************************/
207 * The original DSA tag format and some other tag formats have no
208 * ethertype, which means that we need to add a little hack to the
209 * networking receive path to make sure that received frames get
210 * the right ->protocol assigned to them when one of those tag
213 bool dsa_uses_dsa_tags(void *dsa_ptr
)
215 struct dsa_switch
*ds
= dsa_ptr
;
217 return !!(ds
->tag_protocol
== htons(ETH_P_DSA
));
220 bool dsa_uses_trailer_tags(void *dsa_ptr
)
222 struct dsa_switch
*ds
= dsa_ptr
;
224 return !!(ds
->tag_protocol
== htons(ETH_P_TRAILER
));
228 /* link polling *************************************************************/
229 static void dsa_link_poll_work(struct work_struct
*ugly
)
231 struct dsa_switch
*ds
;
233 ds
= container_of(ugly
, struct dsa_switch
, link_poll_work
);
235 ds
->drv
->poll_link(ds
);
236 mod_timer(&ds
->link_poll_timer
, round_jiffies(jiffies
+ HZ
));
239 static void dsa_link_poll_timer(unsigned long _ds
)
241 struct dsa_switch
*ds
= (void *)_ds
;
243 schedule_work(&ds
->link_poll_work
);
247 /* platform driver init and cleanup *****************************************/
248 static int dev_is_class(struct device
*dev
, void *class)
250 if (dev
->class != NULL
&& !strcmp(dev
->class->name
, class))
256 static struct device
*dev_find_class(struct device
*parent
, char *class)
258 if (dev_is_class(parent
, class)) {
263 return device_find_child(parent
, class, dev_is_class
);
266 static struct mii_bus
*dev_to_mii_bus(struct device
*dev
)
270 d
= dev_find_class(dev
, "mdio_bus");
283 static struct net_device
*dev_to_net_device(struct device
*dev
)
287 d
= dev_find_class(dev
, "net");
289 struct net_device
*nd
;
301 static int dsa_probe(struct platform_device
*pdev
)
303 static int dsa_version_printed
;
304 struct dsa_platform_data
*pd
= pdev
->dev
.platform_data
;
305 struct net_device
*dev
;
307 struct dsa_switch
*ds
;
309 if (!dsa_version_printed
++)
310 printk(KERN_NOTICE
"Distributed Switch Architecture "
311 "driver version %s\n", dsa_driver_version
);
313 if (pd
== NULL
|| pd
->mii_bus
== NULL
|| pd
->netdev
== NULL
)
316 bus
= dev_to_mii_bus(pd
->mii_bus
);
320 dev
= dev_to_net_device(pd
->netdev
);
324 if (dev
->dsa_ptr
!= NULL
) {
329 ds
= dsa_switch_setup(&pdev
->dev
, pd
, bus
, dev
);
335 if (ds
->drv
->poll_link
!= NULL
) {
336 INIT_WORK(&ds
->link_poll_work
, dsa_link_poll_work
);
337 init_timer(&ds
->link_poll_timer
);
338 ds
->link_poll_timer
.data
= (unsigned long)ds
;
339 ds
->link_poll_timer
.function
= dsa_link_poll_timer
;
340 ds
->link_poll_timer
.expires
= round_jiffies(jiffies
+ HZ
);
341 add_timer(&ds
->link_poll_timer
);
344 platform_set_drvdata(pdev
, ds
);
349 static int dsa_remove(struct platform_device
*pdev
)
351 struct dsa_switch
*ds
= platform_get_drvdata(pdev
);
353 if (ds
->drv
->poll_link
!= NULL
)
354 del_timer_sync(&ds
->link_poll_timer
);
356 flush_scheduled_work();
358 dsa_switch_destroy(ds
);
363 static void dsa_shutdown(struct platform_device
*pdev
)
367 static struct platform_driver dsa_driver
= {
369 .remove
= dsa_remove
,
370 .shutdown
= dsa_shutdown
,
373 .owner
= THIS_MODULE
,
377 static int __init
dsa_init_module(void)
379 return platform_driver_register(&dsa_driver
);
381 module_init(dsa_init_module
);
383 static void __exit
dsa_cleanup_module(void)
385 platform_driver_unregister(&dsa_driver
);
387 module_exit(dsa_cleanup_module
);
389 MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>")
390 MODULE_DESCRIPTION("Driver for Distributed Switch Architecture switch chips");
391 MODULE_LICENSE("GPL");
392 MODULE_ALIAS("platform:dsa");