aboutsummaryrefslogtreecommitdiffstats
path: root/net/dsa
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /net/dsa
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'net/dsa')
-rw-r--r--net/dsa/Kconfig54
-rw-r--r--net/dsa/Makefile19
-rw-r--r--net/dsa/dsa.c54
-rw-r--r--net/dsa/dsa_priv.h127
-rw-r--r--net/dsa/slave.c13
-rw-r--r--net/dsa/tag_dsa.c15
-rw-r--r--net/dsa/tag_edsa.c15
-rw-r--r--net/dsa/tag_trailer.c15
8 files changed, 256 insertions, 56 deletions
diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
index f5eede1d6cb..c53ded2a98d 100644
--- a/net/dsa/Kconfig
+++ b/net/dsa/Kconfig
@@ -1,24 +1,60 @@
1config HAVE_NET_DSA 1menuconfig NET_DSA
2 def_bool y 2 bool "Distributed Switch Architecture support"
3 depends on NETDEVICES && !S390 3 default n
4 4 depends on EXPERIMENTAL && NETDEVICES && !S390
5# Drivers must select NET_DSA and the appropriate tagging format
6
7config NET_DSA
8 tristate
9 depends on HAVE_NET_DSA
10 select PHYLIB 5 select PHYLIB
6 ---help---
7 This allows you to use hardware switch chips that use
8 the Distributed Switch Architecture.
9
11 10
12if NET_DSA 11if NET_DSA
13 12
14# tagging formats 13# tagging formats
15config NET_DSA_TAG_DSA 14config NET_DSA_TAG_DSA
16 bool 15 bool
16 default n
17 17
18config NET_DSA_TAG_EDSA 18config NET_DSA_TAG_EDSA
19 bool 19 bool
20 default n
20 21
21config NET_DSA_TAG_TRAILER 22config NET_DSA_TAG_TRAILER
22 bool 23 bool
24 default n
25
26
27# switch drivers
28config NET_DSA_MV88E6XXX
29 bool
30 default n
31
32config NET_DSA_MV88E6060
33 bool "Marvell 88E6060 ethernet switch chip support"
34 select NET_DSA_TAG_TRAILER
35 ---help---
36 This enables support for the Marvell 88E6060 ethernet switch
37 chip.
38
39config NET_DSA_MV88E6XXX_NEED_PPU
40 bool
41 default n
42
43config NET_DSA_MV88E6131
44 bool "Marvell 88E6085/6095/6095F/6131 ethernet switch chip support"
45 select NET_DSA_MV88E6XXX
46 select NET_DSA_MV88E6XXX_NEED_PPU
47 select NET_DSA_TAG_DSA
48 ---help---
49 This enables support for the Marvell 88E6085/6095/6095F/6131
50 ethernet switch chips.
51
52config NET_DSA_MV88E6123_61_65
53 bool "Marvell 88E6123/6161/6165 ethernet switch chip support"
54 select NET_DSA_MV88E6XXX
55 select NET_DSA_TAG_EDSA
56 ---help---
57 This enables support for the Marvell 88E6123/6161/6165
58 ethernet switch chips.
23 59
24endif 60endif
diff --git a/net/dsa/Makefile b/net/dsa/Makefile
index 7b9fcbbeda5..2374faff4de 100644
--- a/net/dsa/Makefile
+++ b/net/dsa/Makefile
@@ -1,8 +1,13 @@
1# the core
2obj-$(CONFIG_NET_DSA) += dsa_core.o
3dsa_core-y += dsa.o slave.o
4
5# tagging formats 1# tagging formats
6dsa_core-$(CONFIG_NET_DSA_TAG_DSA) += tag_dsa.o 2obj-$(CONFIG_NET_DSA_TAG_DSA) += tag_dsa.o
7dsa_core-$(CONFIG_NET_DSA_TAG_EDSA) += tag_edsa.o 3obj-$(CONFIG_NET_DSA_TAG_EDSA) += tag_edsa.o
8dsa_core-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o 4obj-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o
5
6# switch drivers
7obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx.o
8obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
9obj-$(CONFIG_NET_DSA_MV88E6123_61_65) += mv88e6123_61_65.o
10obj-$(CONFIG_NET_DSA_MV88E6131) += mv88e6131.o
11
12# the core
13obj-$(CONFIG_NET_DSA) += dsa.o slave.o
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 45295ca0957..3fb14b7c13c 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -12,7 +12,6 @@
12#include <linux/netdevice.h> 12#include <linux/netdevice.h>
13#include <linux/platform_device.h> 13#include <linux/platform_device.h>
14#include <linux/slab.h> 14#include <linux/slab.h>
15#include <linux/module.h>
16#include <net/dsa.h> 15#include <net/dsa.h>
17#include "dsa_priv.h" 16#include "dsa_priv.h"
18 17
@@ -29,7 +28,6 @@ void register_switch_driver(struct dsa_switch_driver *drv)
29 list_add_tail(&drv->list, &dsa_switch_drivers); 28 list_add_tail(&drv->list, &dsa_switch_drivers);
30 mutex_unlock(&dsa_switch_drivers_mutex); 29 mutex_unlock(&dsa_switch_drivers_mutex);
31} 30}
32EXPORT_SYMBOL_GPL(register_switch_driver);
33 31
34void unregister_switch_driver(struct dsa_switch_driver *drv) 32void unregister_switch_driver(struct dsa_switch_driver *drv)
35{ 33{
@@ -37,7 +35,6 @@ void unregister_switch_driver(struct dsa_switch_driver *drv)
37 list_del_init(&drv->list); 35 list_del_init(&drv->list);
38 mutex_unlock(&dsa_switch_drivers_mutex); 36 mutex_unlock(&dsa_switch_drivers_mutex);
39} 37}
40EXPORT_SYMBOL_GPL(unregister_switch_driver);
41 38
42static struct dsa_switch_driver * 39static struct dsa_switch_driver *
43dsa_switch_probe(struct mii_bus *bus, int sw_addr, char **_name) 40dsa_switch_probe(struct mii_bus *bus, int sw_addr, char **_name)
@@ -201,6 +198,29 @@ static void dsa_switch_destroy(struct dsa_switch *ds)
201} 198}
202 199
203 200
201/* hooks for ethertype-less tagging formats *********************************/
202/*
203 * The original DSA tag format and some other tag formats have no
204 * ethertype, which means that we need to add a little hack to the
205 * networking receive path to make sure that received frames get
206 * the right ->protocol assigned to them when one of those tag
207 * formats is in use.
208 */
209bool dsa_uses_dsa_tags(void *dsa_ptr)
210{
211 struct dsa_switch_tree *dst = dsa_ptr;
212
213 return !!(dst->tag_protocol == htons(ETH_P_DSA));
214}
215
216bool dsa_uses_trailer_tags(void *dsa_ptr)
217{
218 struct dsa_switch_tree *dst = dsa_ptr;
219
220 return !!(dst->tag_protocol == htons(ETH_P_TRAILER));
221}
222
223
204/* link polling *************************************************************/ 224/* link polling *************************************************************/
205static void dsa_link_poll_work(struct work_struct *ugly) 225static void dsa_link_poll_work(struct work_struct *ugly)
206{ 226{
@@ -370,7 +390,7 @@ static int dsa_remove(struct platform_device *pdev)
370 if (dst->link_poll_needed) 390 if (dst->link_poll_needed)
371 del_timer_sync(&dst->link_poll_timer); 391 del_timer_sync(&dst->link_poll_timer);
372 392
373 flush_work(&dst->link_poll_work); 393 flush_work_sync(&dst->link_poll_work);
374 394
375 for (i = 0; i < dst->pd->nr_chips; i++) { 395 for (i = 0; i < dst->pd->nr_chips; i++) {
376 struct dsa_switch *ds = dst->ds[i]; 396 struct dsa_switch *ds = dst->ds[i];
@@ -398,36 +418,12 @@ static struct platform_driver dsa_driver = {
398 418
399static int __init dsa_init_module(void) 419static int __init dsa_init_module(void)
400{ 420{
401 int rc; 421 return platform_driver_register(&dsa_driver);
402
403 rc = platform_driver_register(&dsa_driver);
404 if (rc)
405 return rc;
406
407#ifdef CONFIG_NET_DSA_TAG_DSA
408 dev_add_pack(&dsa_packet_type);
409#endif
410#ifdef CONFIG_NET_DSA_TAG_EDSA
411 dev_add_pack(&edsa_packet_type);
412#endif
413#ifdef CONFIG_NET_DSA_TAG_TRAILER
414 dev_add_pack(&trailer_packet_type);
415#endif
416 return 0;
417} 422}
418module_init(dsa_init_module); 423module_init(dsa_init_module);
419 424
420static void __exit dsa_cleanup_module(void) 425static void __exit dsa_cleanup_module(void)
421{ 426{
422#ifdef CONFIG_NET_DSA_TAG_TRAILER
423 dev_remove_pack(&trailer_packet_type);
424#endif
425#ifdef CONFIG_NET_DSA_TAG_EDSA
426 dev_remove_pack(&edsa_packet_type);
427#endif
428#ifdef CONFIG_NET_DSA_TAG_DSA
429 dev_remove_pack(&dsa_packet_type);
430#endif
431 platform_driver_unregister(&dsa_driver); 427 platform_driver_unregister(&dsa_driver);
432} 428}
433module_exit(dsa_cleanup_module); 429module_exit(dsa_cleanup_module);
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index d4cf5cc747e..4b0ea054044 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -11,9 +11,97 @@
11#ifndef __DSA_PRIV_H 11#ifndef __DSA_PRIV_H
12#define __DSA_PRIV_H 12#define __DSA_PRIV_H
13 13
14#include <linux/list.h>
14#include <linux/phy.h> 15#include <linux/phy.h>
16#include <linux/timer.h>
17#include <linux/workqueue.h>
15#include <net/dsa.h> 18#include <net/dsa.h>
16 19
20struct dsa_switch {
21 /*
22 * Parent switch tree, and switch index.
23 */
24 struct dsa_switch_tree *dst;
25 int index;
26
27 /*
28 * Configuration data for this switch.
29 */
30 struct dsa_chip_data *pd;
31
32 /*
33 * The used switch driver.
34 */
35 struct dsa_switch_driver *drv;
36
37 /*
38 * Reference to mii bus to use.
39 */
40 struct mii_bus *master_mii_bus;
41
42 /*
43 * Slave mii_bus and devices for the individual ports.
44 */
45 u32 dsa_port_mask;
46 u32 phys_port_mask;
47 struct mii_bus *slave_mii_bus;
48 struct net_device *ports[DSA_MAX_PORTS];
49};
50
51struct dsa_switch_tree {
52 /*
53 * Configuration data for the platform device that owns
54 * this dsa switch tree instance.
55 */
56 struct dsa_platform_data *pd;
57
58 /*
59 * Reference to network device to use, and which tagging
60 * protocol to use.
61 */
62 struct net_device *master_netdev;
63 __be16 tag_protocol;
64
65 /*
66 * The switch and port to which the CPU is attached.
67 */
68 s8 cpu_switch;
69 s8 cpu_port;
70
71 /*
72 * Link state polling.
73 */
74 int link_poll_needed;
75 struct work_struct link_poll_work;
76 struct timer_list link_poll_timer;
77
78 /*
79 * Data for the individual switch chips.
80 */
81 struct dsa_switch *ds[DSA_MAX_SWITCHES];
82};
83
84static inline bool dsa_is_cpu_port(struct dsa_switch *ds, int p)
85{
86 return !!(ds->index == ds->dst->cpu_switch && p == ds->dst->cpu_port);
87}
88
89static inline u8 dsa_upstream_port(struct dsa_switch *ds)
90{
91 struct dsa_switch_tree *dst = ds->dst;
92
93 /*
94 * If this is the root switch (i.e. the switch that connects
95 * to the CPU), return the cpu port number on this switch.
96 * Else return the (DSA) port number that connects to the
97 * switch that is one hop closer to the cpu.
98 */
99 if (dst->cpu_switch == ds->index)
100 return dst->cpu_port;
101 else
102 return ds->pd->rtable[dst->cpu_switch];
103}
104
17struct dsa_slave_priv { 105struct dsa_slave_priv {
18 /* 106 /*
19 * The linux network interface corresponding to this 107 * The linux network interface corresponding to this
@@ -35,8 +123,44 @@ struct dsa_slave_priv {
35 struct phy_device *phy; 123 struct phy_device *phy;
36}; 124};
37 125
126struct dsa_switch_driver {
127 struct list_head list;
128
129 __be16 tag_protocol;
130 int priv_size;
131
132 /*
133 * Probing and setup.
134 */
135 char *(*probe)(struct mii_bus *bus, int sw_addr);
136 int (*setup)(struct dsa_switch *ds);
137 int (*set_addr)(struct dsa_switch *ds, u8 *addr);
138
139 /*
140 * Access to the switch's PHY registers.
141 */
142 int (*phy_read)(struct dsa_switch *ds, int port, int regnum);
143 int (*phy_write)(struct dsa_switch *ds, int port,
144 int regnum, u16 val);
145
146 /*
147 * Link state polling and IRQ handling.
148 */
149 void (*poll_link)(struct dsa_switch *ds);
150
151 /*
152 * ethtool hardware statistics.
153 */
154 void (*get_strings)(struct dsa_switch *ds, int port, uint8_t *data);
155 void (*get_ethtool_stats)(struct dsa_switch *ds,
156 int port, uint64_t *data);
157 int (*get_sset_count)(struct dsa_switch *ds);
158};
159
38/* dsa.c */ 160/* dsa.c */
39extern char dsa_driver_version[]; 161extern char dsa_driver_version[];
162void register_switch_driver(struct dsa_switch_driver *type);
163void unregister_switch_driver(struct dsa_switch_driver *type);
40 164
41/* slave.c */ 165/* slave.c */
42void dsa_slave_mii_bus_init(struct dsa_switch *ds); 166void dsa_slave_mii_bus_init(struct dsa_switch *ds);
@@ -46,15 +170,12 @@ struct net_device *dsa_slave_create(struct dsa_switch *ds,
46 170
47/* tag_dsa.c */ 171/* tag_dsa.c */
48netdev_tx_t dsa_xmit(struct sk_buff *skb, struct net_device *dev); 172netdev_tx_t dsa_xmit(struct sk_buff *skb, struct net_device *dev);
49extern struct packet_type dsa_packet_type;
50 173
51/* tag_edsa.c */ 174/* tag_edsa.c */
52netdev_tx_t edsa_xmit(struct sk_buff *skb, struct net_device *dev); 175netdev_tx_t edsa_xmit(struct sk_buff *skb, struct net_device *dev);
53extern struct packet_type edsa_packet_type;
54 176
55/* tag_trailer.c */ 177/* tag_trailer.c */
56netdev_tx_t trailer_xmit(struct sk_buff *skb, struct net_device *dev); 178netdev_tx_t trailer_xmit(struct sk_buff *skb, struct net_device *dev);
57extern struct packet_type trailer_packet_type;
58 179
59 180
60#endif 181#endif
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index e32083d5d8f..0a47b6c3703 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -66,7 +66,7 @@ static int dsa_slave_open(struct net_device *dev)
66 if (!(master->flags & IFF_UP)) 66 if (!(master->flags & IFF_UP))
67 return -ENETDOWN; 67 return -ENETDOWN;
68 68
69 if (!ether_addr_equal(dev->dev_addr, master->dev_addr)) { 69 if (compare_ether_addr(dev->dev_addr, master->dev_addr)) {
70 err = dev_uc_add(master, dev->dev_addr); 70 err = dev_uc_add(master, dev->dev_addr);
71 if (err < 0) 71 if (err < 0)
72 goto out; 72 goto out;
@@ -89,7 +89,7 @@ clear_allmulti:
89 if (dev->flags & IFF_ALLMULTI) 89 if (dev->flags & IFF_ALLMULTI)
90 dev_set_allmulti(master, -1); 90 dev_set_allmulti(master, -1);
91del_unicast: 91del_unicast:
92 if (!ether_addr_equal(dev->dev_addr, master->dev_addr)) 92 if (compare_ether_addr(dev->dev_addr, master->dev_addr))
93 dev_uc_del(master, dev->dev_addr); 93 dev_uc_del(master, dev->dev_addr);
94out: 94out:
95 return err; 95 return err;
@@ -107,7 +107,7 @@ static int dsa_slave_close(struct net_device *dev)
107 if (dev->flags & IFF_PROMISC) 107 if (dev->flags & IFF_PROMISC)
108 dev_set_promiscuity(master, -1); 108 dev_set_promiscuity(master, -1);
109 109
110 if (!ether_addr_equal(dev->dev_addr, master->dev_addr)) 110 if (compare_ether_addr(dev->dev_addr, master->dev_addr))
111 dev_uc_del(master, dev->dev_addr); 111 dev_uc_del(master, dev->dev_addr);
112 112
113 return 0; 113 return 0;
@@ -146,13 +146,13 @@ static int dsa_slave_set_mac_address(struct net_device *dev, void *a)
146 if (!(dev->flags & IFF_UP)) 146 if (!(dev->flags & IFF_UP))
147 goto out; 147 goto out;
148 148
149 if (!ether_addr_equal(addr->sa_data, master->dev_addr)) { 149 if (compare_ether_addr(addr->sa_data, master->dev_addr)) {
150 err = dev_uc_add(master, addr->sa_data); 150 err = dev_uc_add(master, addr->sa_data);
151 if (err < 0) 151 if (err < 0)
152 return err; 152 return err;
153 } 153 }
154 154
155 if (!ether_addr_equal(dev->dev_addr, master->dev_addr)) 155 if (compare_ether_addr(dev->dev_addr, master->dev_addr))
156 dev_uc_del(master, dev->dev_addr); 156 dev_uc_del(master, dev->dev_addr);
157 157
158out: 158out:
@@ -301,6 +301,7 @@ static const struct net_device_ops dsa_netdev_ops = {
301 .ndo_start_xmit = dsa_xmit, 301 .ndo_start_xmit = dsa_xmit,
302 .ndo_change_rx_flags = dsa_slave_change_rx_flags, 302 .ndo_change_rx_flags = dsa_slave_change_rx_flags,
303 .ndo_set_rx_mode = dsa_slave_set_rx_mode, 303 .ndo_set_rx_mode = dsa_slave_set_rx_mode,
304 .ndo_set_multicast_list = dsa_slave_set_rx_mode,
304 .ndo_set_mac_address = dsa_slave_set_mac_address, 305 .ndo_set_mac_address = dsa_slave_set_mac_address,
305 .ndo_do_ioctl = dsa_slave_ioctl, 306 .ndo_do_ioctl = dsa_slave_ioctl,
306}; 307};
@@ -313,6 +314,7 @@ static const struct net_device_ops edsa_netdev_ops = {
313 .ndo_start_xmit = edsa_xmit, 314 .ndo_start_xmit = edsa_xmit,
314 .ndo_change_rx_flags = dsa_slave_change_rx_flags, 315 .ndo_change_rx_flags = dsa_slave_change_rx_flags,
315 .ndo_set_rx_mode = dsa_slave_set_rx_mode, 316 .ndo_set_rx_mode = dsa_slave_set_rx_mode,
317 .ndo_set_multicast_list = dsa_slave_set_rx_mode,
316 .ndo_set_mac_address = dsa_slave_set_mac_address, 318 .ndo_set_mac_address = dsa_slave_set_mac_address,
317 .ndo_do_ioctl = dsa_slave_ioctl, 319 .ndo_do_ioctl = dsa_slave_ioctl,
318}; 320};
@@ -325,6 +327,7 @@ static const struct net_device_ops trailer_netdev_ops = {
325 .ndo_start_xmit = trailer_xmit, 327 .ndo_start_xmit = trailer_xmit,
326 .ndo_change_rx_flags = dsa_slave_change_rx_flags, 328 .ndo_change_rx_flags = dsa_slave_change_rx_flags,
327 .ndo_set_rx_mode = dsa_slave_set_rx_mode, 329 .ndo_set_rx_mode = dsa_slave_set_rx_mode,
330 .ndo_set_multicast_list = dsa_slave_set_rx_mode,
328 .ndo_set_mac_address = dsa_slave_set_mac_address, 331 .ndo_set_mac_address = dsa_slave_set_mac_address,
329 .ndo_do_ioctl = dsa_slave_ioctl, 332 .ndo_do_ioctl = dsa_slave_ioctl,
330}; 333};
diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c
index cacce1e22f9..98dfe80b453 100644
--- a/net/dsa/tag_dsa.c
+++ b/net/dsa/tag_dsa.c
@@ -186,7 +186,20 @@ out:
186 return 0; 186 return 0;
187} 187}
188 188
189struct packet_type dsa_packet_type __read_mostly = { 189static struct packet_type dsa_packet_type __read_mostly = {
190 .type = cpu_to_be16(ETH_P_DSA), 190 .type = cpu_to_be16(ETH_P_DSA),
191 .func = dsa_rcv, 191 .func = dsa_rcv,
192}; 192};
193
194static int __init dsa_init_module(void)
195{
196 dev_add_pack(&dsa_packet_type);
197 return 0;
198}
199module_init(dsa_init_module);
200
201static void __exit dsa_cleanup_module(void)
202{
203 dev_remove_pack(&dsa_packet_type);
204}
205module_exit(dsa_cleanup_module);
diff --git a/net/dsa/tag_edsa.c b/net/dsa/tag_edsa.c
index e70c43c25e6..6f383322ad2 100644
--- a/net/dsa/tag_edsa.c
+++ b/net/dsa/tag_edsa.c
@@ -205,7 +205,20 @@ out:
205 return 0; 205 return 0;
206} 206}
207 207
208struct packet_type edsa_packet_type __read_mostly = { 208static struct packet_type edsa_packet_type __read_mostly = {
209 .type = cpu_to_be16(ETH_P_EDSA), 209 .type = cpu_to_be16(ETH_P_EDSA),
210 .func = edsa_rcv, 210 .func = edsa_rcv,
211}; 211};
212
213static int __init edsa_init_module(void)
214{
215 dev_add_pack(&edsa_packet_type);
216 return 0;
217}
218module_init(edsa_init_module);
219
220static void __exit edsa_cleanup_module(void)
221{
222 dev_remove_pack(&edsa_packet_type);
223}
224module_exit(edsa_cleanup_module);
diff --git a/net/dsa/tag_trailer.c b/net/dsa/tag_trailer.c
index 94bc260d015..d6d7d0add3c 100644
--- a/net/dsa/tag_trailer.c
+++ b/net/dsa/tag_trailer.c
@@ -114,7 +114,20 @@ out:
114 return 0; 114 return 0;
115} 115}
116 116
117struct packet_type trailer_packet_type __read_mostly = { 117static struct packet_type trailer_packet_type __read_mostly = {
118 .type = cpu_to_be16(ETH_P_TRAILER), 118 .type = cpu_to_be16(ETH_P_TRAILER),
119 .func = trailer_rcv, 119 .func = trailer_rcv,
120}; 120};
121
122static int __init trailer_init_module(void)
123{
124 dev_add_pack(&trailer_packet_type);
125 return 0;
126}
127module_init(trailer_init_module);
128
129static void __exit trailer_cleanup_module(void)
130{
131 dev_remove_pack(&trailer_packet_type);
132}
133module_exit(trailer_cleanup_module);